/*
* 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
* 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.
*/
#include "clock.h"
#include "pipespawn.h"
#include "amfeatures.h"
-#include "stream.h"
+#include "amandad.h"
#include "arglist.h"
#include "getfsent.h"
#include "version.h"
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;
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("");
}
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;
}
/* 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);
dumpdate = NULL;
stroptions = NULL;
- /* parse dump request */
-
for(; (line = agets(stdin)) != NULL; free(line)) {
if(interactive) {
fprintf(stderr, "%s> ", get_pname());
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;
}
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);
}
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);
}
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);
{
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";
}
}
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);
}
/* 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);
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));
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();
return d;
}
+
static void process_dumpline(str)
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;
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;
}
}
- /* 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));
/* 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;
- }
}
}
/* 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)));
}
backup_program_t *programs[] = {
&dump_program, &gnutar_program, NULL
};
-
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.c"
-#endif