From: Frank Lahm Date: Fri, 26 Aug 2011 09:28:23 +0000 (+0200) Subject: Implement proper daemonisation for afpd and cnid_metad, fix for NetAFP #10163. X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=0d7777ad35e6db12c49450a5634621af1ae210ff;ds=sidebyside Implement proper daemonisation for afpd and cnid_metad, fix for NetAFP #10163. --- diff --git a/etc/afpd/main.c b/etc/afpd/main.c index b29510ba..c2775565 100644 --- a/etc/afpd/main.c +++ b/etc/afpd/main.c @@ -258,6 +258,21 @@ int main(int ac, char **av) set_auth_parameters( ac, av ); #endif /* TRU64 */ + /* Parse argv args and initialize default options */ + afp_options_init(&default_options); + if (!afp_options_parse(ac, av, &default_options)) + exit(EXITERR_CONF); + + if (!(default_options.flags & OPTION_DEBUG) && (daemonize(0, 0) != 0)) + exit(EXITERR_SYS); + + switch(check_lockfile("afpd", default_options.pidfile)) { + case 0: + break; + default: + exit(EXITERR_SYS); + } + /* Log SIGBUS/SIGSEGV SBT */ fault_setup(NULL); @@ -265,23 +280,9 @@ int main(int ac, char **av) set_processname("afpd"); setuplog("default log_note"); - afp_options_init(&default_options); - if (!afp_options_parse(ac, av, &default_options)) - exit(EXITERR_CONF); - - /* Save the user's current umask for use with CNID (and maybe some - * other things, too). */ + /* Save the user's current umask */ default_options.save_mask = umask( default_options.umask ); - switch(server_lock("afpd", default_options.pidfile, - default_options.flags & OPTION_DEBUG)) { - case -1: /* error */ - exit(EXITERR_SYS); - case 0: /* child */ - break; - default: /* server */ - exit(0); - } atexit(afp_exit); /* install child handler for asp and dsi. we do this before afp_goaway diff --git a/etc/cnid_dbd/cnid_metad.c b/etc/cnid_dbd/cnid_metad.c index 86d904bd..ad9727da 100644 --- a/etc/cnid_dbd/cnid_metad.c +++ b/etc/cnid_dbd/cnid_metad.c @@ -490,6 +490,17 @@ int main(int argc, char *argv[]) } } + if (!debug && daemonize(0, 0) != 0) + exit(EXITERR_SYS); + + /* Check PID lockfile and become a daemon */ + switch(check_lockfile("cnid_metad", _PATH_CNID_METAD_LOCK)) { + case 0: + break; + default: + exit(EXITERR_SYS); + } + if (loglevel) { strlcpy(logconfig + 8, loglevel, 13); free(loglevel); @@ -508,16 +519,6 @@ int main(int argc, char *argv[]) (void)setlimits(); - /* Check PID lockfile and become a daemon */ - switch(server_lock("cnid_metad", _PATH_CNID_METAD_LOCK, debug)) { - case -1: /* error */ - daemon_exit(EXITERR_SYS); - case 0: /* child */ - break; - default: /* server */ - exit(0); - } - if ((srvfd = tsockfd_create(host, port, 10)) < 0) daemon_exit(1); diff --git a/include/atalk/util.h b/include/atalk/util.h index b6039735..df7cfcc2 100644 --- a/include/atalk/util.h +++ b/include/atalk/util.h @@ -73,6 +73,7 @@ extern void bprint (char *, int); extern int strdiacasecmp (const char *, const char *); extern int strndiacasecmp (const char *, const char *, size_t); extern pid_t server_lock (char * /*program*/, char * /*file*/, int /*debug*/); +extern int check_lockfile (const char *program, const char *pidfile); extern void fault_setup (void (*fn)(void *)); extern void netatalk_panic(const char *why); #define server_unlock(x) (unlink(x)) @@ -178,6 +179,7 @@ extern const char *getcwdpath(void); extern char *stripped_slashes_basename(char *p); extern int lchdir(const char *dir); extern void randombytes(void *buf, int n); +extern int daemonize(int nochdir, int noclose); /****************************************************************** * cnid.c diff --git a/libatalk/util/server_lock.c b/libatalk/util/server_lock.c index a08e30a2..68c73556 100644 --- a/libatalk/util/server_lock.c +++ b/libatalk/util/server_lock.c @@ -97,3 +97,37 @@ pid_t server_lock(char *program, char *pidfile, int debug) return 0; } +/*! + * Check and write lockfile + */ +int check_lockfile(const char *program, const char *pidfile) +{ + char buf[10]; + FILE *pf; + pid_t pid; + int mask; + + /* check for pid. this can get fooled by stale pid's. */ + if ((pf = fopen(pidfile, "r"))) { + if (fgets(buf, sizeof(buf), pf) && !kill(pid = atol(buf), 0)) { + fprintf(stderr, "%s is already running (pid = %d), or the lock file is stale.\n", + program, pid); + fclose(pf); + return -1; + } + fclose(pf); + } + + /* Write PID to pidfile */ + mask = umask(022); + if ((pf = fopen(pidfile, "w")) == NULL) { + fprintf(stderr, "%s: can't open lock file, \"%s\"\n", program, + pidfile); + return -1; + } + umask(mask); + fprintf(pf, "%d\n", getpid()); + fclose(pf); + + return 0; +} diff --git a/libatalk/util/unix.c b/libatalk/util/unix.c index 9e71fcb4..c16c5da5 100644 --- a/libatalk/util/unix.c +++ b/libatalk/util/unix.c @@ -41,6 +41,59 @@ #include #include +/* close all FDs >= a specified value */ +static void closeall(int fd) +{ + int fdlimit = sysconf(_SC_OPEN_MAX); + + while (fd < fdlimit) + close(fd++); +} + +/*! + * Daemonize + * + * Fork, exit parent, setsid(), optionally chdir("/"), optionally close all fds + * + * returns -1 on failure, but you can't do much except exit in that case + * since we may already have forked + */ +int daemonize(int nochdir, int noclose) +{ + switch (fork()) { + case 0: + break; + case -1: + return -1; + default: + _exit(0); + } + + if (setsid() < 0) + return -1; + + switch (fork()) { + case 0: + break; + case -1: + return -1; + default: + _exit(0); + } + + if (!nochdir) + chdir("/"); + + if (!noclose) { + closeall(0); + open("/dev/null",O_RDWR); + dup(0); + dup(0); + } + + return 0; +} + /*! * @brief get cwd in static buffer *