Imported Upstream version 3.3.2
[debian/amanda] / amandad-src / amandad.c
index 1c47ae446467868dfb2dbb49ef9a04e1bb08e4e5..11009d854ef405fbbfd443427c61e2bfba83e9ab 100644 (file)
@@ -81,7 +81,8 @@ typedef enum {
     SERVICE_SENDBACKUP,
     SERVICE_SELFCHECK,
     SERVICE_AMINDEXD,
-    SERVICE_AMIDXTAPED
+    SERVICE_AMIDXTAPED,
+    SERVICE_AMDUMPD
 } service_t;
 
 static struct services {
@@ -94,7 +95,8 @@ static struct services {
    { "sendbackup", 1, SERVICE_SENDBACKUP },
    { "selfcheck", 1, SERVICE_SELFCHECK },
    { "amindexd", 0, SERVICE_AMINDEXD },
-   { "amidxtaped", 0, SERVICE_AMIDXTAPED }
+   { "amidxtaped", 0, SERVICE_AMIDXTAPED },
+   { "amdumpd", 0, SERVICE_AMDUMPD }
 };
 #define        NSERVICES       (int)(sizeof(services) / sizeof(services[0]))
 
@@ -212,6 +214,17 @@ main(
     safe_fd(-1, 0);
     safe_cd();
 
+    /*
+     * Nexenta needs the SUN_PERSONALITY env variable to be unset, otherwise
+     * the Sun version of tar in /usr/sun/sbin/tar is called instead.
+     *
+     * On other operating systems this will have no effect.
+     */
+
+#ifdef HAVE_UNSETENV
+    unsetenv("SUN_PERSONALITY");
+#endif
+
     /*
      * When called via inetd, it is not uncommon to forget to put the
      * argv[0] value on the config line.  On some systems (e.g. Solaris)
@@ -231,6 +244,11 @@ main(
        /*NOTREACHED*/
     }
 
+    if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
+       printf("amandad-%s\n", VERSION);
+       return (0);
+    }
+
     /* Don't die when child closes pipe */
     signal(SIGPIPE, SIG_IGN);
 
@@ -274,6 +292,14 @@ main(
                error(_("no driver for security type '%s'\n"), argv[i]);
                 /*NOTREACHED*/
            }
+           if (strcmp(auth, "local") == 0 ||
+               strcmp(auth, "rsh") == 0 ||
+               strcmp(auth, "ssh") == 0) {
+               int i;
+               for (i=0; i < NSERVICES; i++) {
+                   services[i].active = 1;
+               }
+           }
            continue;
        }
 
@@ -410,13 +436,13 @@ main(
     }
 
     /*
-     * If no security type specified, use BSD
+     * If no security type specified, use BSDTCP
      */
     if (secdrv == NULL) {
-       secdrv = security_getdriver("BSD");
-       auth = "bsd";
+       secdrv = security_getdriver("BSDTCP");
+       auth = "bsdtcp";
        if (secdrv == NULL) {
-           error(_("no driver for default security type 'BSD'\n"));
+           error(_("no driver for default security type 'BSDTCP'\n"));
            /*NOTREACHED*/
        }
     }
@@ -538,6 +564,7 @@ protocol_accept(
     char *service_path = NULL;
     GSList *errlist = NULL;
     int i;
+    char *peer_name;
 
     pkt_out.body = NULL;
 
@@ -549,7 +576,7 @@ protocol_accept(
     }
 
     /*
-     * If we have errors (not warnings) from the config file, let the server
+     * If we have errors (not warnings) from the config file, let the remote system
      * know immediately.  Unfortunately, we only get one ERROR line, so if there
      * are multiple errors, we just show the first.
      */
@@ -574,6 +601,10 @@ protocol_accept(
        return;
     }
 
+    peer_name = security_get_authenticated_peer_name(handle);
+    g_debug("authenticated peer name is '%s'", peer_name);
+    amfree(peer_name);
+
     /*
      * If pkt is NULL, then there was a problem with the new connection.
      */
@@ -1403,6 +1434,7 @@ process_readnetfd(
 
        /* fill info_end_buf from the tail end of combined_buf */
        memcpy(as->info_end_buf, combined_buf + n, INFO_END_LEN);
+       amfree(combined_buf);
 
        /* if we did see info_end_str, start reading the data fd (fd 0) */
        if (as->seen_info_end) {
@@ -1519,6 +1551,8 @@ service_new(
     struct active_service *as;
     pid_t pid;
     int newfd;
+    char *peer_name;
+    char *amanda_remote_host_env[2];
 
     assert(security_handle != NULL);
     assert(cmd != NULL);
@@ -1632,6 +1666,16 @@ service_new(
         * and start up.
         */
 
+       /* set up the AMANDA_AUTHENTICATED_PEER env var so child services
+        * can use it to authenticate */
+       peer_name = security_get_authenticated_peer_name(security_handle);
+       amanda_remote_host_env[0] = NULL;
+       amanda_remote_host_env[1] = NULL;
+       if (*peer_name) {
+           amanda_remote_host_env[0] =
+               g_strdup_printf("AMANDA_AUTHENTICATED_PEER=%s", peer_name);
+       }
+
        /*
         * The data stream is stdin in the new process
         */
@@ -1721,7 +1765,7 @@ service_new(
         aclose(data_write[STDERR_PIPE][1]);
        safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
 
-       execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env());
+       execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env_full(amanda_remote_host_env));
        error(_("could not exec service %s: %s\n"), cmd, strerror(errno));
        /*NOTREACHED*/
     }
@@ -1785,17 +1829,22 @@ service_delete(
     if (as->security_handle != NULL)
        security_close(as->security_handle);
 
+    /* try to kill the process; if this fails, then it's already dead and
+     * likely some of the other zombie cleanup ate its brains, so we don't
+     * bother to waitpid for it */
     assert(as->pid > 0);
-    kill(as->pid, SIGTERM);
     pid = waitpid(as->pid, NULL, WNOHANG);
-    count = 5;
-    while (pid != as->pid && count > 0) {
-       count--;
-       sleep(1);
+    if (pid != as->pid && kill(as->pid, SIGTERM) == 0) {
        pid = waitpid(as->pid, NULL, WNOHANG);
-    }
-    if (pid != as->pid) {
-       g_debug("Process %d failed to exit", (int)as->pid);
+       count = 5;
+       while (pid != as->pid && count > 0) {
+           count--;
+           sleep(1);
+           pid = waitpid(as->pid, NULL, WNOHANG);
+       }
+       if (pid != as->pid) {
+           g_debug("Process %d failed to exit", (int)as->pid);
+       }
     }
 
     serviceq = g_slist_remove(serviceq, (gpointer)as);