3 * UNFS3 server framework
4 * Originally generated using rpcgen
5 * Portions (C) 2004, Pascal Schmidt
6 * see file LICENSE for license details
12 #include <sys/types.h>
15 #include <rpc/pmap_clnt.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
37 #if HAVE_RPC_SVC_SOC_H == 1
38 # include <rpc/svc_soc.h>
50 #include "Config/exports.h"
53 #define SIG_PF void(*)(int)
56 #define UNFS_NAME "UNFS3 unfsd " PACKAGE_VERSION " (C) 2006, Pascal Schmidt <unfs3-server@ewetel.net>\n"
64 /* options and default values */
65 int opt_detach = TRUE;
66 char *opt_exports = "/etc/exports";
67 int opt_cluster = FALSE;
68 char *opt_cluster_path = "/";
69 int opt_tcponly = FALSE;
70 unsigned int opt_nfs_port = NFS_PORT; /* 0 means RPC_ANYSOCK */
71 unsigned int opt_mount_port = NFS_PORT;
72 int opt_singleuser = FALSE;
73 int opt_brute_force = FALSE;
74 int opt_testconfig = FALSE;
75 struct in_addr opt_bind_addr;
76 int opt_readable_executables = FALSE;
77 char *opt_pid_file = NULL;
79 /* Register with portmapper? */
80 int opt_portmapper = TRUE;
83 * output message to syslog or stdout
85 void logmsg(int prio, const char *fmt, ...)
96 vsyslog(prio, fmt, ap);
98 vsnprintf(mesg, 1024, fmt, ap);
99 syslog(prio, mesg, 1024);
109 * return remote address from svc_req structure
111 struct in_addr get_remote(struct svc_req *rqstp)
113 return (svc_getcaller(rqstp->rq_xprt))->sin_addr;
117 * return remote port from svc_req structure
119 short get_port(struct svc_req *rqstp)
121 return (svc_getcaller(rqstp->rq_xprt))->sin_port;
125 * return the socket type of the request (SOCK_STREAM or SOCK_DGRAM)
127 int get_socket_type(struct svc_req *rqstp)
134 #if HAVE_STRUCT___RPC_SVCXPRT_XP_FD == 1
135 res = getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET, SO_TYPE, &v, &l);
137 res = getsockopt(rqstp->rq_xprt->xp_sock, SOL_SOCKET, SO_TYPE, &v, &l);
141 logmsg(LOG_CRIT, "unable to determine socket type");
149 * write current pid to a file
151 static void create_pid_file(void)
159 fd = backend_open_create(opt_pid_file, O_RDWR | O_CREAT | O_TRUNC, 0644);
161 logmsg(LOG_WARNING, "failed to create pid file `%s'", opt_pid_file);
164 #if defined(LOCK_EX) && defined(LOCK_NB)
165 res = backend_flock(fd, LOCK_EX | LOCK_NB);
167 logmsg(LOG_WARNING, "failed to lock pid file `%s'", opt_pid_file);
173 sprintf(buf, "%i\n", backend_getpid());
176 res = backend_pwrite(fd, buf, len, 0);
179 logmsg(LOG_WARNING, "failed to write pid file `%s'", opt_pid_file);
186 static void remove_pid_file(void)
193 res = backend_remove(opt_pid_file);
194 if (res == -1 && errno != ENOENT) {
195 logmsg(LOG_WARNING, "failed to remove pid file `%s'", opt_pid_file);
200 * parse command line options
202 static void parse_options(int argc, char **argv)
205 char *optstring = "bcC:de:hl:m:n:prstTuwi:";
208 opt = getopt(argc, argv, optstring);
211 opt_brute_force = TRUE;
218 opt_cluster_path = optarg;
227 if (optarg[0] != '/') {
228 /* A relative path won't work for re-reading the exports
229 file on SIGHUP, since we are changing directory */
230 fprintf(stderr, "Error: relative path to exports file\n");
234 opt_exports = optarg;
238 printf("Usage: %s [options]\n", argv[0]);
239 printf("\t-h display this short option summary\n");
240 printf("\t-u use unprivileged port for services\n");
241 printf("\t-d do not detach from terminal\n");
242 printf("\t-e <file> file to use instead of /etc/exports\n");
243 printf("\t-i <file> write daemon pid to given file\n");
245 printf("\t-c enable cluster extensions\n");
246 printf("\t-C <path> set path for cluster extensions\n");
248 printf("\t-n <port> port to use for NFS service\n");
249 printf("\t-m <port> port to use for MOUNT service\n");
251 ("\t-t TCP only, do not listen on UDP ports\n");
252 printf("\t-p do not register with the portmapper\n");
253 printf("\t-s single user mode\n");
254 printf("\t-b enable brute force file searching\n");
256 ("\t-l <addr> bind to interface with specified address\n");
258 ("\t-r report unreadable executables as readable\n");
259 printf("\t-T test exports file and exit\n");
263 opt_bind_addr.s_addr = inet_addr(optarg);
264 if (opt_bind_addr.s_addr == (unsigned) -1) {
265 fprintf(stderr, "Invalid bind address\n");
270 opt_mount_port = strtol(optarg, NULL, 10);
271 if (opt_mount_port == 0) {
272 fprintf(stderr, "Invalid port\n");
277 opt_nfs_port = strtol(optarg, NULL, 10);
278 if (opt_nfs_port == 0) {
279 fprintf(stderr, "Invalid port\n");
284 opt_portmapper = FALSE;
287 opt_readable_executables = TRUE;
290 opt_singleuser = TRUE;
292 if (backend_getuid() == 0) {
294 "Warning: running as root with -s is dangerous");
296 "All clients will have root access to all exported files!");
304 opt_testconfig = TRUE;
311 opt_pid_file = optarg;
321 * signal handler and error exit function
323 void daemon_exit(int error)
326 if (error == SIGHUP) {
332 if (error == SIGUSR1) {
333 if (fh_cache_use > 0)
334 logmsg(LOG_INFO, "fh entries %i access %i hit %i miss %i",
335 fh_cache_max, fh_cache_use, fh_cache_hit,
336 fh_cache_use - fh_cache_hit);
338 logmsg(LOG_INFO, "fh cache unused");
339 logmsg(LOG_INFO, "open file descriptors: read %i, write %i",
340 fd_cache_readers, fd_cache_writers);
345 if (opt_portmapper) {
346 svc_unregister(MOUNTPROG, MOUNTVERS1);
347 svc_unregister(MOUNTPROG, MOUNTVERS3);
350 if (opt_portmapper) {
351 svc_unregister(NFS3_PROGRAM, NFS_V3);
354 if (error == SIGSEGV)
355 logmsg(LOG_EMERG, "segmentation fault");
369 * NFS service dispatch function
370 * generated by rpcgen
372 static void nfs3_program_3(struct svc_req *rqstp, register SVCXPRT * transp)
375 GETATTR3args nfsproc3_getattr_3_arg;
376 SETATTR3args nfsproc3_setattr_3_arg;
377 LOOKUP3args nfsproc3_lookup_3_arg;
378 ACCESS3args nfsproc3_access_3_arg;
379 READLINK3args nfsproc3_readlink_3_arg;
380 READ3args nfsproc3_read_3_arg;
381 WRITE3args nfsproc3_write_3_arg;
382 CREATE3args nfsproc3_create_3_arg;
383 MKDIR3args nfsproc3_mkdir_3_arg;
384 SYMLINK3args nfsproc3_symlink_3_arg;
385 MKNOD3args nfsproc3_mknod_3_arg;
386 REMOVE3args nfsproc3_remove_3_arg;
387 RMDIR3args nfsproc3_rmdir_3_arg;
388 RENAME3args nfsproc3_rename_3_arg;
389 LINK3args nfsproc3_link_3_arg;
390 READDIR3args nfsproc3_readdir_3_arg;
391 READDIRPLUS3args nfsproc3_readdirplus_3_arg;
392 FSSTAT3args nfsproc3_fsstat_3_arg;
393 FSINFO3args nfsproc3_fsinfo_3_arg;
394 PATHCONF3args nfsproc3_pathconf_3_arg;
395 COMMIT3args nfsproc3_commit_3_arg;
398 xdrproc_t _xdr_argument, _xdr_result;
399 char *(*local) (char *, struct svc_req *);
401 switch (rqstp->rq_proc) {
403 _xdr_argument = (xdrproc_t) xdr_void;
404 _xdr_result = (xdrproc_t) xdr_void;
405 local = (char *(*)(char *, struct svc_req *)) nfsproc3_null_3_svc;
408 case NFSPROC3_GETATTR:
409 _xdr_argument = (xdrproc_t) xdr_GETATTR3args;
410 _xdr_result = (xdrproc_t) xdr_GETATTR3res;
412 (char *(*)(char *, struct svc_req *)) nfsproc3_getattr_3_svc;
415 case NFSPROC3_SETATTR:
416 _xdr_argument = (xdrproc_t) xdr_SETATTR3args;
417 _xdr_result = (xdrproc_t) xdr_SETATTR3res;
419 (char *(*)(char *, struct svc_req *)) nfsproc3_setattr_3_svc;
422 case NFSPROC3_LOOKUP:
423 _xdr_argument = (xdrproc_t) xdr_LOOKUP3args;
424 _xdr_result = (xdrproc_t) xdr_LOOKUP3res;
426 (char *(*)(char *, struct svc_req *)) nfsproc3_lookup_3_svc;
429 case NFSPROC3_ACCESS:
430 _xdr_argument = (xdrproc_t) xdr_ACCESS3args;
431 _xdr_result = (xdrproc_t) xdr_ACCESS3res;
433 (char *(*)(char *, struct svc_req *)) nfsproc3_access_3_svc;
436 case NFSPROC3_READLINK:
437 _xdr_argument = (xdrproc_t) xdr_READLINK3args;
438 _xdr_result = (xdrproc_t) xdr_READLINK3res;
440 (char *(*)(char *, struct svc_req *)) nfsproc3_readlink_3_svc;
444 _xdr_argument = (xdrproc_t) xdr_READ3args;
445 _xdr_result = (xdrproc_t) xdr_READ3res;
446 local = (char *(*)(char *, struct svc_req *)) nfsproc3_read_3_svc;
450 _xdr_argument = (xdrproc_t) xdr_WRITE3args;
451 _xdr_result = (xdrproc_t) xdr_WRITE3res;
453 (char *(*)(char *, struct svc_req *)) nfsproc3_write_3_svc;
456 case NFSPROC3_CREATE:
457 _xdr_argument = (xdrproc_t) xdr_CREATE3args;
458 _xdr_result = (xdrproc_t) xdr_CREATE3res;
460 (char *(*)(char *, struct svc_req *)) nfsproc3_create_3_svc;
464 _xdr_argument = (xdrproc_t) xdr_MKDIR3args;
465 _xdr_result = (xdrproc_t) xdr_MKDIR3res;
467 (char *(*)(char *, struct svc_req *)) nfsproc3_mkdir_3_svc;
470 case NFSPROC3_SYMLINK:
471 _xdr_argument = (xdrproc_t) xdr_SYMLINK3args;
472 _xdr_result = (xdrproc_t) xdr_SYMLINK3res;
474 (char *(*)(char *, struct svc_req *)) nfsproc3_symlink_3_svc;
478 _xdr_argument = (xdrproc_t) xdr_MKNOD3args;
479 _xdr_result = (xdrproc_t) xdr_MKNOD3res;
481 (char *(*)(char *, struct svc_req *)) nfsproc3_mknod_3_svc;
484 case NFSPROC3_REMOVE:
485 _xdr_argument = (xdrproc_t) xdr_REMOVE3args;
486 _xdr_result = (xdrproc_t) xdr_REMOVE3res;
488 (char *(*)(char *, struct svc_req *)) nfsproc3_remove_3_svc;
492 _xdr_argument = (xdrproc_t) xdr_RMDIR3args;
493 _xdr_result = (xdrproc_t) xdr_RMDIR3res;
495 (char *(*)(char *, struct svc_req *)) nfsproc3_rmdir_3_svc;
498 case NFSPROC3_RENAME:
499 _xdr_argument = (xdrproc_t) xdr_RENAME3args;
500 _xdr_result = (xdrproc_t) xdr_RENAME3res;
502 (char *(*)(char *, struct svc_req *)) nfsproc3_rename_3_svc;
506 _xdr_argument = (xdrproc_t) xdr_LINK3args;
507 _xdr_result = (xdrproc_t) xdr_LINK3res;
508 local = (char *(*)(char *, struct svc_req *)) nfsproc3_link_3_svc;
511 case NFSPROC3_READDIR:
512 _xdr_argument = (xdrproc_t) xdr_READDIR3args;
513 _xdr_result = (xdrproc_t) xdr_READDIR3res;
515 (char *(*)(char *, struct svc_req *)) nfsproc3_readdir_3_svc;
518 case NFSPROC3_READDIRPLUS:
519 _xdr_argument = (xdrproc_t) xdr_READDIRPLUS3args;
520 _xdr_result = (xdrproc_t) xdr_READDIRPLUS3res;
521 local = (char *(*)(char *, struct svc_req *))
522 nfsproc3_readdirplus_3_svc;
525 case NFSPROC3_FSSTAT:
526 _xdr_argument = (xdrproc_t) xdr_FSSTAT3args;
527 _xdr_result = (xdrproc_t) xdr_FSSTAT3res;
529 (char *(*)(char *, struct svc_req *)) nfsproc3_fsstat_3_svc;
532 case NFSPROC3_FSINFO:
533 _xdr_argument = (xdrproc_t) xdr_FSINFO3args;
534 _xdr_result = (xdrproc_t) xdr_FSINFO3res;
536 (char *(*)(char *, struct svc_req *)) nfsproc3_fsinfo_3_svc;
539 case NFSPROC3_PATHCONF:
540 _xdr_argument = (xdrproc_t) xdr_PATHCONF3args;
541 _xdr_result = (xdrproc_t) xdr_PATHCONF3res;
543 (char *(*)(char *, struct svc_req *)) nfsproc3_pathconf_3_svc;
546 case NFSPROC3_COMMIT:
547 _xdr_argument = (xdrproc_t) xdr_COMMIT3args;
548 _xdr_result = (xdrproc_t) xdr_COMMIT3res;
550 (char *(*)(char *, struct svc_req *)) nfsproc3_commit_3_svc;
554 svcerr_noproc(transp);
557 memset((char *) &argument, 0, sizeof(argument));
558 if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) & argument)) {
559 svcerr_decode(transp);
562 result = (*local) ((char *) &argument, rqstp);
563 if (result != NULL &&
564 !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
565 svcerr_systemerr(transp);
566 logmsg(LOG_CRIT, "unable to send RPC reply");
569 (transp, (xdrproc_t) _xdr_argument, (caddr_t) & argument)) {
570 logmsg(LOG_CRIT, "unable to free XDR arguments");
576 * mount protocol dispatcher
577 * generated by rpcgen
579 static void mountprog_3(struct svc_req *rqstp, register SVCXPRT * transp)
582 dirpath mountproc_mnt_3_arg;
583 dirpath mountproc_umnt_3_arg;
586 xdrproc_t _xdr_argument, _xdr_result;
587 char *(*local) (char *, struct svc_req *);
589 switch (rqstp->rq_proc) {
591 _xdr_argument = (xdrproc_t) xdr_void;
592 _xdr_result = (xdrproc_t) xdr_void;
594 (char *(*)(char *, struct svc_req *)) mountproc_null_3_svc;
598 _xdr_argument = (xdrproc_t) xdr_dirpath;
599 _xdr_result = (xdrproc_t) xdr_mountres3;
600 local = (char *(*)(char *, struct svc_req *)) mountproc_mnt_3_svc;
604 _xdr_argument = (xdrproc_t) xdr_void;
605 _xdr_result = (xdrproc_t) xdr_mountlist;
607 (char *(*)(char *, struct svc_req *)) mountproc_dump_3_svc;
611 _xdr_argument = (xdrproc_t) xdr_dirpath;
612 _xdr_result = (xdrproc_t) xdr_void;
614 (char *(*)(char *, struct svc_req *)) mountproc_umnt_3_svc;
617 case MOUNTPROC_UMNTALL:
618 _xdr_argument = (xdrproc_t) xdr_void;
619 _xdr_result = (xdrproc_t) xdr_void;
621 (char *(*)(char *, struct svc_req *)) mountproc_umntall_3_svc;
624 case MOUNTPROC_EXPORT:
625 _xdr_argument = (xdrproc_t) xdr_void;
626 _xdr_result = (xdrproc_t) xdr_exports;
628 (char *(*)(char *, struct svc_req *)) mountproc_export_3_svc;
632 svcerr_noproc(transp);
635 memset((char *) &argument, 0, sizeof(argument));
636 if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) & argument)) {
637 svcerr_decode(transp);
640 result = (*local) ((char *) &argument, rqstp);
641 if (result != NULL &&
642 !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
643 svcerr_systemerr(transp);
644 logmsg(LOG_CRIT, "unable to send RPC reply");
647 (transp, (xdrproc_t) _xdr_argument, (caddr_t) & argument)) {
648 logmsg(LOG_CRIT, "unable to free XDR arguments");
653 static void register_nfs_service(SVCXPRT * udptransp, SVCXPRT * tcptransp)
655 if (opt_portmapper) {
656 pmap_unset(NFS3_PROGRAM, NFS_V3);
659 if (udptransp != NULL) {
660 /* Register NFS service for UDP */
662 (udptransp, NFS3_PROGRAM, NFS_V3, nfs3_program_3,
663 opt_portmapper ? IPPROTO_UDP : 0)) {
664 fprintf(stderr, "%s\n",
665 "unable to register (NFS3_PROGRAM, NFS_V3, udp).");
670 if (tcptransp != NULL) {
671 /* Register NFS service for TCP */
673 (tcptransp, NFS3_PROGRAM, NFS_V3, nfs3_program_3,
674 opt_portmapper ? IPPROTO_TCP : 0)) {
675 fprintf(stderr, "%s\n",
676 "unable to register (NFS3_PROGRAM, NFS_V3, tcp).");
682 static void register_mount_service(SVCXPRT * udptransp, SVCXPRT * tcptransp)
684 if (opt_portmapper) {
685 pmap_unset(MOUNTPROG, MOUNTVERS1);
686 pmap_unset(MOUNTPROG, MOUNTVERS3);
689 if (udptransp != NULL) {
690 /* Register MOUNT service (v1) for UDP */
692 (udptransp, MOUNTPROG, MOUNTVERS1, mountprog_3,
693 opt_portmapper ? IPPROTO_UDP : 0)) {
694 fprintf(stderr, "%s\n",
695 "unable to register (MOUNTPROG, MOUNTVERS1, udp).");
699 /* Register MOUNT service (v3) for UDP */
701 (udptransp, MOUNTPROG, MOUNTVERS3, mountprog_3,
702 opt_portmapper ? IPPROTO_UDP : 0)) {
703 fprintf(stderr, "%s\n",
704 "unable to register (MOUNTPROG, MOUNTVERS3, udp).");
709 if (tcptransp != NULL) {
710 /* Register MOUNT service (v1) for TCP */
712 (tcptransp, MOUNTPROG, MOUNTVERS1, mountprog_3,
713 opt_portmapper ? IPPROTO_TCP : 0)) {
714 fprintf(stderr, "%s\n",
715 "unable to register (MOUNTPROG, MOUNTVERS1, tcp).");
719 /* Register MOUNT service (v3) for TCP */
721 (tcptransp, MOUNTPROG, MOUNTVERS3, mountprog_3,
722 opt_portmapper ? IPPROTO_TCP : 0)) {
723 fprintf(stderr, "%s\n",
724 "unable to register (MOUNTPROG, MOUNTVERS3, tcp).");
730 static SVCXPRT *create_udp_transport(unsigned int port)
732 SVCXPRT *transp = NULL;
733 struct sockaddr_in sin;
740 sin.sin_family = AF_INET;
741 sin.sin_port = htons(port);
742 sin.sin_addr.s_addr = opt_bind_addr.s_addr;
743 sock = socket(PF_INET, SOCK_DGRAM, 0);
744 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
745 if (bind(sock, (struct sockaddr *) &sin, sizeof(struct sockaddr))) {
747 fprintf(stderr, "Couldn't bind to udp port %d\n", port);
752 transp = svcudp_bufcreate(sock, NFS_MAX_UDP_PACKET, NFS_MAX_UDP_PACKET);
754 if (transp == NULL) {
755 fprintf(stderr, "%s\n", "cannot create udp service.");
762 static SVCXPRT *create_tcp_transport(unsigned int port)
764 SVCXPRT *transp = NULL;
765 struct sockaddr_in sin;
772 sin.sin_family = AF_INET;
773 sin.sin_port = htons(port);
774 sin.sin_addr.s_addr = opt_bind_addr.s_addr;
775 sock = socket(PF_INET, SOCK_STREAM, 0);
776 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
777 if (bind(sock, (struct sockaddr *) &sin, sizeof(struct sockaddr))) {
779 fprintf(stderr, "Couldn't bind to tcp port %d\n", port);
784 transp = svctcp_create(sock, 0, 0);
786 if (transp == NULL) {
787 fprintf(stderr, "%s\n", "cannot create tcp service.");
794 /* Run RPC service. This is our own implementation of svc_run(), which
795 allows us to handle other events as well. */
796 static void unfs3_svc_run()
802 fd_cache_close_inactive();
806 /* Note: On Windows, it's not possible to call select with all sets
807 empty; to use it as a sleep function. In our case, however,
808 readfds should never be empty, since we always have our listen
809 socket. Well, at least hope that our Windows RPC library works
810 like that. oncrpc-ms does. */
811 switch (select(FD_SETSIZE, &readfds, NULL, NULL, &tv)) {
813 if (errno == EINTR) {
816 perror("unfs3_svc_run: select failed");
822 svc_getreqset(&readfds);
828 * Generate write verifier based on PID and current time
830 void regenerate_write_verifier(void)
832 *(wverf + 0) = (uint32) getpid();
833 *(wverf + 0) ^= rand();
834 *(wverf + 4) = (uint32) time(NULL);
838 * Change readdir cookie value
840 void change_readdir_cookie(void)
842 rcookie = rcookie >> 32;
844 rcookie = rcookie << 32;
849 * originally generated by rpcgen
850 * forking, logging, options, and signal handler stuff added
852 int main(int argc, char **argv)
854 register SVCXPRT *tcptransp = NULL, *udptransp = NULL;
858 struct sigaction act;
863 opt_bind_addr.s_addr = INADDR_ANY;
865 parse_options(argc, argv);
867 fprintf(stderr, "Error: extra arguments on command line\n");
871 /* init write verifier */
872 regenerate_write_verifier();
874 res = backend_init();
876 fprintf(stderr, "backend initialization failed\n");
880 /* config test mode */
881 if (opt_testconfig) {
882 res = exports_parse();
886 fprintf(stderr, "Parse error in `%s'\n", opt_exports);
892 /* prepare syslog access */
893 openlog("unfsd", LOG_CONS | LOG_PID, LOG_DAEMON);
895 /* flush stdout after each newline */
896 setvbuf(stdout, NULL, _IOLBF, 0);
901 udptransp = create_udp_transport(opt_nfs_port);
902 tcptransp = create_tcp_transport(opt_nfs_port);
904 register_nfs_service(udptransp, tcptransp);
906 /* MOUNT transports. If ports are equal, then the MOUNT service can reuse
907 the NFS transports. */
908 if (opt_mount_port != opt_nfs_port) {
910 udptransp = create_udp_transport(opt_mount_port);
911 tcptransp = create_tcp_transport(opt_mount_port);
914 register_mount_service(udptransp, tcptransp);
920 fprintf(stderr, "could not fork into background\n");
926 if (!opt_detach || pid == 0) {
928 sigemptyset(&actset);
929 act.sa_handler = daemon_exit;
930 act.sa_mask = actset;
932 sigaction(SIGHUP, &act, NULL);
933 sigaction(SIGTERM, &act, NULL);
934 sigaction(SIGINT, &act, NULL);
935 sigaction(SIGQUIT, &act, NULL);
936 sigaction(SIGSEGV, &act, NULL);
937 sigaction(SIGUSR1, &act, NULL);
939 act.sa_handler = SIG_IGN;
940 sigaction(SIGPIPE, &act, NULL);
941 sigaction(SIGUSR2, &act, NULL);
942 sigaction(SIGALRM, &act, NULL);
944 /* don't make directory we started in busy */
947 /* detach from terminal */
956 /* no umask to not screw up create modes */
959 /* create pid file if wanted */
962 /* initialize internal stuff */