]> arthur.barton.de Git - netatalk.git/commitdiff
Implement proper daemonisation for afpd and cnid_metad, fix for NetAFP #10163.
authorFrank Lahm <franklahm@googlemail.com>
Fri, 26 Aug 2011 09:28:23 +0000 (11:28 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 31 Aug 2011 06:10:53 +0000 (08:10 +0200)
etc/afpd/main.c
etc/cnid_dbd/cnid_metad.c
include/atalk/util.h
libatalk/util/server_lock.c
libatalk/util/unix.c

index b29510ba263ad1a51673be4ee39c3eb3a533951f..c27755655db75a551aec0505ca20975e5ed1eb06 100644 (file)
@@ -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
index 86d904bdf7becb45ce689afaae9ae3d7f6385668..ad9727daab226d6dbb9b4bd5f789aacb9e301e94 100644 (file)
@@ -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);
 
index b6039735d064c77dec6149332f370087d39df7c7..df7cfcc20b59221ba6664190dbaa66407ab6f35c 100644 (file)
@@ -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
index a08e30a2f199c5954839bfd82b36282792bdee22..68c7355645c5596bf3520a04d14f52126de28a62 100644 (file)
@@ -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;
+}
index 9e71fcb4b71a3b7fd53479c4cebc2cef7cb3bb30..c16c5da5b50d1514243a29c0afb3edd9bd7593f6 100644 (file)
 #include <atalk/util.h>
 #include <atalk/unix.h>
 
+/* 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
  *