Imported Upstream version 2.5.0
[debian/amanda] / client-src / sendbackup.c
index e8050448a6544d6b2f298187ac0d835b233fd17d..e824e1ef286555960ca682cfe184f06cb63392e9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup.c,v 1.44.2.9.4.4.2.16.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: sendbackup.c,v 1.77 2006/03/09 16:51:41 martinea Exp $
  *
  * common code for the sendbackup-* programs.
  */
@@ -34,7 +34,7 @@
 #include "clock.h"
 #include "pipespawn.h"
 #include "amfeatures.h"
-#include "stream.h"
+#include "amandad.h"
 #include "arglist.h"
 #include "getfsent.h"
 #include "version.h"
@@ -48,18 +48,12 @@ int encpid = -1;
 int indexpid = -1;
 char *errorstr = NULL;
 
-int data_socket, data_port, dataf;
-int mesg_socket, mesg_port, mesgf;
-int index_socket, index_port, indexf;
+int datafd;
+int mesgfd;
+int indexfd;
 
 option_t *options;
 
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.h"
-#else                                  /* I'd tell you what this does */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#endif
-
 long dump_size = -1;
 
 backup_program_t *program = NULL;
@@ -78,36 +72,60 @@ int pipefork P((void (*func) P((void)), char *fname, int *stdinfd,
                int stdoutfd, int stderrfd));
 void parse_backup_messages P((int mesgin));
 static void process_dumpline P((char *str));
+static void save_fd P((int *, int));
 
-
-char *optionstr(option_t *options)
+char *optionstr(options)
+option_t *options;
 {
     static char *optstr = NULL;
-    char *compress_opt = "";
+    char *compress_opt;
+    char *encrypt_opt;
+    char *decrypt_opt;
     char *record_opt = "";
-    char *bsd_opt = "";
-    char *krb4_opt = "";
-    char *kencrypt_opt = "";
     char *index_opt = "";
+    char *auth_opt;
     char *exclude_file_opt;
     char *exclude_list_opt;
     char *exc = NULL;
     sle_t *excl;
 
     if(options->compress == COMPR_BEST)
-       compress_opt = "compress-best;";
+       compress_opt = stralloc("compress-best;");
     else if(options->compress == COMPR_FAST)
-       compress_opt = "compress-fast;";
+       compress_opt = stralloc("compress-fast;");
     else if(options->compress == COMPR_SERVER_BEST)
-       compress_opt = "srvcomp-best;";
+       compress_opt = stralloc("srvcomp-best;");
     else if(options->compress == COMPR_SERVER_FAST)
-       compress_opt = "srvcomp-fast;";
+       compress_opt = stralloc("srvcomp-fast;");
+    else if(options->compress == COMPR_SERVER_CUST)
+       compress_opt = vstralloc("srvcomp-cust=", options->srvcompprog, ";", NULL);
+    else if(options->compress == COMPR_CUST)
+       compress_opt = vstralloc("comp-cust=", options->clntcompprog, ";", NULL);
+    else
+       compress_opt = stralloc("");
+    
+    if(options->encrypt == ENCRYPT_CUST) {
+      encrypt_opt = vstralloc("encrypt-cust=", options->clnt_encrypt, ";", NULL);
+      if (options->clnt_decrypt_opt)
+       decrypt_opt = vstralloc("client-decrypt-option=", options->clnt_decrypt_opt, ";", NULL);
+      else
+       decrypt_opt = stralloc("");
+    }
+    else if(options->encrypt == ENCRYPT_SERV_CUST) {
+      encrypt_opt = vstralloc("encrypt-serv-cust=", options->srv_encrypt, ";", NULL);
+      if(options->srv_decrypt_opt)
+       decrypt_opt = vstralloc("server-decrypt-option=", options->srv_decrypt_opt, ";", NULL);
+      else
+       decrypt_opt = stralloc("");
+    }
+    else {
+       encrypt_opt = stralloc("");
+       decrypt_opt = stralloc("");
+    }
+
     if(options->no_record) record_opt = "no-record;";
-    if(options->bsd_auth) bsd_opt = "bsd-auth;";
-#ifdef KRB4_SECURITY
-    if(options->krb4_auth) krb4_opt = "krb4-auth;";
-    if(options->kencrypt) kencrypt_opt = "kencrypt;";
-#endif
+    if(options->auth) auth_opt = vstralloc("auth=", options->auth, ";", NULL);
+       else auth_opt = stralloc("");
     if(options->createindex) index_opt = "index;";
 
     exclude_file_opt = stralloc("");
@@ -126,14 +144,20 @@ char *optionstr(option_t *options)
     }
     optstr = newvstralloc(optstr,
                          compress_opt,
+                         encrypt_opt,
+                         decrypt_opt,
                          record_opt,
-                         bsd_opt,
-                         krb4_opt,
-                         kencrypt_opt,
                          index_opt,
+                         auth_opt,
                          exclude_file_opt,
                          exclude_list_opt,
                          NULL);
+    amfree(compress_opt);
+    amfree(encrypt_opt);
+    amfree(decrypt_opt);
+    amfree(auth_opt);
+    amfree(exclude_file_opt);
+    amfree(exclude_list_opt);
     return optstr;
 }
 
@@ -155,23 +179,21 @@ char **argv;
 
     /* initialize */
 
-#ifdef KRB4_SECURITY
-    safe_fd(KEY_PIPE, 1);              /* XXX interface needs to be fixed */
-#else
-    safe_fd(-1, 0);
-#endif
-
+    safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT);
     safe_cd();
 
     set_pname("sendbackup");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     interactive = (argc > 1 && strcmp(argv[1],"-t") == 0);
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
     dbopen();
     startclock();
-    dbprintf(("%s: version %s\n", argv[0], version()));
+    dbprintf(("%s: version %s\n", get_pname(), version()));
 
     our_features = am_init_feature_set();
     our_feature_string = am_feature_to_string(our_features);
@@ -193,8 +215,6 @@ char **argv;
     dumpdate = NULL;
     stroptions = NULL;
 
-    /* parse dump request */
-
     for(; (line = agets(stdin)) != NULL; free(line)) {
        if(interactive) {
            fprintf(stderr, "%s> ", get_pname());
@@ -307,7 +327,7 @@ char **argv;
     dbprintf(("                     since %s\n", dumpdate));
     dbprintf(("                     options `%s'\n", stroptions));
 
-    for(i = 0; programs[i] != NULL; i++) {
+    for(i = 0; programs[i]; i++) {
        if (strcmp(programs[i]->name, prog) == 0) {
            break;
        }
@@ -319,42 +339,16 @@ char **argv;
 
     options = parse_options(stroptions, disk, amdevice, g_options->features, 0);
 
-#ifdef KRB4_SECURITY
-    /* modification by BIS@BBN 4/25/2003:
-     * with the option processing changes in amanda 2.4.4, must change
-     * the conditional from krb4_auth to options->krb4_auth */
-    if(options->krb4_auth) {
-       if(read(KEY_PIPE, session_key, sizeof session_key) 
-          != sizeof session_key) {
-         error("ERROR [%s: could not read session key]", get_pname());
-       }
-    }
-#endif
-
     if(!interactive) {
-      data_socket = stream_server(&data_port, STREAM_BUFSIZE, -1);
-      if(data_socket < 0) {
-       error("ERROR [%s: could not create data socket: %s]",
-             get_pname(), strerror(errno));
-      }
-      mesg_socket = stream_server(&mesg_port, -1, -1);
-      if(mesg_socket < 0) {
-       error("ERROR [%s: could not create mesg socket: %s]",
-             get_pname(), strerror(errno));
-      }
-    }
-    if (!interactive && options->createindex) {
-      index_socket = stream_server(&index_port, -1, -1);
-      if(index_socket < 0) {
-       error("ERROR [%s: could not create index socket: %s]",
-             get_pname(), strerror(errno));
-      }
-    } else {
-      index_port = -1;
+       datafd = DATA_FD_OFFSET + 0;
+       mesgfd = DATA_FD_OFFSET + 1;
+       indexfd = DATA_FD_OFFSET + 2;
     }
+    if (!options->createindex)
+       indexfd = -1;
 
     printf("CONNECT DATA %d MESG %d INDEX %d\n",
-          data_port, mesg_port, index_port);
+          datafd, mesgfd, indexfd);
     printf("OPTIONS ");
     if(am_has_feature(g_options->features, fe_rep_options_features)) {
        printf("features=%s;", our_feature_string);
@@ -367,91 +361,34 @@ char **argv;
     }
     printf("\n");
     fflush(stdout);
-    freopen("/dev/null", "w", stdout);
-
-    if (options->createindex)
-      dbprintf(("%s: waiting for connect on %d, then %d, then %d\n",
-               debug_prefix_time(NULL), data_port, mesg_port, index_port));
-    else
-      dbprintf(("%s: waiting for connect on %d, then %d\n",
-               debug_prefix_time(NULL), data_port, mesg_port));
-
-    if(interactive) {
-      if((dataf = open("/dev/null", O_RDWR)) < 0) {
-       error("ERROR [%s: open of /dev/null for debug data stream: %s]",
-             get_pname(), strerror(errno));
-      }
-      mesgf = 2;
-    } else {
-      dataf = stream_accept(data_socket, TIMEOUT, -1, -1);
-      if(dataf == -1) {
-       dbprintf(("%s: timeout on data port %d\n",
-                 debug_prefix_time(NULL), data_port));
-      }
-      mesgf = stream_accept(mesg_socket, TIMEOUT, -1, -1);
-      if(mesgf == -1) {
-        dbprintf(("%s: timeout on mesg port %d\n",
-                 debug_prefix_time(NULL), mesg_port));
-      }
+    if (freopen("/dev/null", "w", stdout) == NULL) {
+       dbprintf(("%s: error redirecting stdout to /dev/null: %s\n",
+           debug_prefix_time(NULL), mesgfd, strerror(errno)));
+        exit(1);
     }
+
     if(interactive) {
-      indexf = 1;
-    } else if (options->createindex) {
-      indexf = stream_accept(index_socket, TIMEOUT, -1, -1);
-      if (indexf == -1) {
-       dbprintf(("%s: timeout on index port %d\n",
-                 debug_prefix_time(NULL), index_port));
+      if((datafd = open("/dev/null", O_RDWR)) < 0) {
+       s = strerror(errno);
+       error("ERROR [%s: open of /dev/null for debug data stream: %s]\n",
+                 get_pname(), s);
       }
+      mesgfd = 2;
+      indexfd = 1;
     }
 
     if(!interactive) {
-      if(dataf == -1 || mesgf == -1 || (options->createindex && indexf == -1)) {
+      if(datafd == -1 || mesgfd == -1 || (options->createindex && indexfd == -1)) {
         dbclose();
         exit(1);
       }
     }
 
-    dbprintf(("%s: got all connections\n", debug_prefix_time(NULL)));
-
-#ifdef KRB4_SECURITY
-    if(!interactive) {
-      /* modification by BIS@BBN 4/25/2003:
-       * with the option processing changes in amanda 2.4.4, must change
-       * the conditional from krb4_auth to options->krb4_auth */
-      if (options->krb4_auth) {
-        if(kerberos_handshake(dataf, session_key) == 0) {
-           dbprintf(("%s: kerberos_handshake on data socket failed\n",
-                     debug_prefix_time(NULL)));
-           dbclose();
-           exit(1);
-        } else {
-           dbprintf(("%s: kerberos_handshake on data socket succeeded\n",
-                     debug_prefix_time(NULL)));
-
-       }
-
-        if(kerberos_handshake(mesgf, session_key) == 0) {
-           dbprintf(("%s: kerberos_handshake on mesg socket failed\n",
-                     debug_prefix_time(NULL)));
-           dbclose();
-           exit(1);
-        } else {
-           dbprintf(("%s: kerberos_handshake on mesg socket succeeded\n",
-                     debug_prefix_time(NULL)));
-
-       }
-
-        dbprintf(("%s: kerberos handshakes succeeded!\n",
-                 debug_prefix_time(NULL)));
-      }
-    }
-#endif
-
     if(!interactive) {
       /* redirect stderr */
-      if(dup2(mesgf, 2) == -1) {
-         dbprintf(("%s: error redirecting stderr: %s\n",
-                   debug_prefix(NULL), strerror(errno)));
+      if(dup2(mesgfd, 2) == -1) {
+         dbprintf(("%s: error redirecting stderr to fd %d: %s\n",
+             debug_prefix_time(NULL), mesgfd, strerror(errno)));
          dbclose();
          exit(1);
       }
@@ -461,9 +398,11 @@ char **argv;
       error("error [opening mesg pipe: %s]", strerror(errno));
     }
 
-    program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate,
-                         dataf, mesgpipe[1], indexf);
+    program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate, datafd, mesgpipe[1],
+                         indexfd);
+    dbprintf(("%s: started backup\n", debug_prefix_time(NULL)));
     parse_backup_messages(mesgpipe[0]);
+    dbprintf(("%s: parsed backup messages\n", debug_prefix_time(NULL)));
 
     amfree(prog);
     amfree(disk);
@@ -508,7 +447,7 @@ int pid;
 {
     if(pid == dumppid) return program->backup_name;
     if(pid == comppid) return "compress";
-    if(pid == encpid)  return "kencrypt";
+    if(pid == encpid) return "encrypt";
     if(pid == indexpid) return "index";
     return "unknown";
 }
@@ -588,10 +527,10 @@ amwait_t w;
     }
 
     if(ret == 0) {
-       ap_snprintf(number, sizeof(number), "%d", sig);
+       snprintf(number, sizeof(number), "%d", sig);
        thiserr = vstralloc(str, " got signal ", number, NULL);
     } else {
-       ap_snprintf(number, sizeof(number), "%d", ret);
+       snprintf(number, sizeof(number), "%d", ret);
        thiserr = vstralloc(str, " returned ", number, NULL);
     }
 
@@ -609,7 +548,7 @@ amwait_t w;
 
 /* Send header info to the message file.
 */
-void write_tapeheader()
+void info_tapeheader()
 {
     fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name);
 
@@ -641,7 +580,7 @@ int stdoutfd, stderrfd;
     int pid, inpipe[2];
 
     dbprintf(("%s: forking function %s in pipeline\n",
-             debug_prefix_time(NULL), fname));
+       debug_prefix_time(NULL), fname));
 
     if(pipe(inpipe) == -1) {
        error("error [open pipe to %s: %s]", fname, strerror(errno));
@@ -658,13 +597,16 @@ int stdoutfd, stderrfd;
        aclose(inpipe[1]);      /* close output side of pipe */
 
        if(dup2(inpipe[0], 0) == -1) {
-           error("error [dup2 0 %s: dup2 in: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, in): %s]",
+                 fname, inpipe[0], strerror(errno));
        }
        if(dup2(stdoutfd, 1) == -1) {
-           error("error [dup2 1 %s: dup2 out: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, out): %s]",
+                 fname, stdoutfd, strerror(errno));
        }
        if(dup2(stderrfd, 2) == -1) {
-           error("error [dup2 2 %s: dup2 err: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, err): %s]",
+                 fname, stderrfd, strerror(errno));
        }
 
        func();
@@ -731,6 +673,7 @@ char *str;
     return d;
 }
 
+
 static void process_dumpline(str)
 char *str;
 {
@@ -803,13 +746,7 @@ char *str;
 
 static volatile int index_finished = 0;
 
-static void index_closed(sig)
-int sig;
-{
-  index_finished = 1;
-}
-
-void save_fd(fd, min)
+static void save_fd(fd, min)
 int *fd, min;
 {
   int origfd = *fd;
@@ -818,19 +755,18 @@ int *fd, min;
     int newfd = dup(*fd);
     if (newfd == -1)
       dbprintf(("%s: unable to save file descriptor [%s]\n",
-               debug_prefix(NULL), strerror(errno)));
+       debug_prefix_time(NULL), strerror(errno)));
     *fd = newfd;
   }
   if (origfd != *fd)
     dbprintf(("%s: dupped file descriptor %i to %i\n",
-             debug_prefix(NULL), origfd, *fd));
+      debug_prefix_time(NULL), origfd, *fd));
 }
 
 void start_index(createindex, input, mesg, index, cmd)
 int createindex, input, mesg, index;
 char *cmd;
 {
-  struct sigaction act, oact;
   int pipefd[2];
   FILE *pipe_fp;
   int exitcode;
@@ -873,31 +809,21 @@ char *cmd;
     }
   }
 
-  /* set up a signal handler for SIGPIPE for when the pipe is finished
-     creating the index file */
-  /* at that point we obviously want to stop writing to it */
-  act.sa_handler = index_closed;
-  sigemptyset(&act.sa_mask);
-  act.sa_flags = 0;
-  if (sigaction(SIGPIPE, &act, &oact) != 0) {
-    error("couldn't set index SIGPIPE handler [%s]", strerror(errno));
-  }
-
   if ((pipe_fp = popen(cmd, "w")) == NULL) {
     error("couldn't start index creator [%s]", strerror(errno));
   }
 
   dbprintf(("%s: started index creator: \"%s\"\n",
-           debug_prefix_time(NULL), cmd));
+    debug_prefix_time(NULL), cmd));
   while(1) {
     char buffer[BUFSIZ], *ptr;
     int bytes_read;
     int bytes_written;
     int just_written;
 
-    bytes_read = read(0, buffer, sizeof(buffer));
-    if ((bytes_read < 0) && (errno == EINTR))
-      continue;
+    do {
+       bytes_read = read(0, buffer, sizeof(buffer));
+    } while ((bytes_read < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 
     if (bytes_read < 0) {
       error("index tee cannot read [%s]", strerror(errno));
@@ -909,36 +835,31 @@ char *cmd;
     /* write the stuff to the subprocess */
     ptr = buffer;
     bytes_written = 0;
-    while (bytes_read > bytes_written && !index_finished) {
-      just_written = write(fileno(pipe_fp), ptr, bytes_read - bytes_written);
-      if (just_written < 0) {
-         /* the signal handler may have assigned to index_finished
-          * just as we waited for write() to complete. */
-         if (!index_finished) {
-             dbprintf(("%s: index tee cannot write to index creator [%s]\n",
-                       debug_prefix_time(NULL), strerror(errno)));
-             index_finished = 1;
+    just_written = fullwrite(fileno(pipe_fp), ptr, bytes_read);
+    if (just_written < 0) {
+       /* the signal handler may have assigned to index_finished
+        * just as we waited for write() to complete.
+        */
+       if (errno != EPIPE) {
+           dbprintf(("%s: index tee cannot write to index creator [%s]\n",
+                           debug_prefix_time(NULL), strerror(errno)));
        }
-      } else {
+    } else {
        bytes_written += just_written;
        ptr += just_written;
-      }
     }
 
     /* write the stuff to stdout, ensuring none lost when interrupt
        occurs */
     ptr = buffer;
     bytes_written = 0;
-    while (bytes_read > bytes_written) {
-      just_written = write(3, ptr, bytes_read - bytes_written);
-      if ((just_written < 0) && (errno == EINTR))
-       continue;
-      if (just_written < 0) {
+    just_written = fullwrite(3, ptr, bytes_read);
+    if (just_written < 0) {
        error("index tee cannot write [%s]", strerror(errno));
-      } else {
+       /* NOTREACHED */
+    } else {
        bytes_written += just_written;
        ptr += just_written;
-      }
     }
   }
 
@@ -948,7 +869,7 @@ char *cmd;
   /* check the exit code of the pipe and moan if not 0 */
   if ((exitcode = pclose(pipe_fp)) != 0) {
     dbprintf(("%s: index pipe returned %d\n",
-             debug_prefix_time(NULL), exitcode));
+      debug_prefix_time(NULL), exitcode));
   } else {
     dbprintf(("%s: index created successfully\n", debug_prefix_time(NULL)));
   }
@@ -962,7 +883,3 @@ extern backup_program_t dump_program, gnutar_program;
 backup_program_t *programs[] = {
   &dump_program, &gnutar_program, NULL
 };
-
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.c"
-#endif