X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendbackup.c;h=5af8dcef5be8ceb048dc46eadbf892721c37a11d;hb=12179dea039515c06168c0037d048566a3f623de;hp=e824e1ef286555960ca682cfe184f06cb63392e9;hpb=94c03cae686e4196a345d72452fda2a5203768ce;p=debian%2Famanda diff --git a/client-src/sendbackup.c b/client-src/sendbackup.c index e824e1e..5af8dce 100644 --- a/client-src/sendbackup.c +++ b/client-src/sendbackup.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: sendbackup.c,v 1.77 2006/03/09 16:51:41 martinea Exp $ + * $Id: sendbackup.c,v 1.88 2006/07/25 18:27:56 martinea Exp $ * * common code for the sendbackup-* programs. */ @@ -38,14 +38,15 @@ #include "arglist.h" #include "getfsent.h" #include "version.h" +#include "clientconf.h" #define TIMEOUT 30 -int comppid = -1; -int dumppid = -1; -int tarpid = -1; -int encpid = -1; -int indexpid = -1; +pid_t comppid = (pid_t)-1; +pid_t dumppid = (pid_t)-1; +pid_t tarpid = (pid_t)-1; +pid_t encpid = (pid_t)-1; +pid_t indexpid = (pid_t)-1; char *errorstr = NULL; int datafd; @@ -53,6 +54,7 @@ int mesgfd; int indexfd; option_t *options; +g_option_t *g_options = NULL; long dump_size = -1; @@ -60,22 +62,27 @@ backup_program_t *program = NULL; static am_feature_t *our_features = NULL; static char *our_feature_string = NULL; -static g_option_t *g_options = NULL; +static char *amandad_auth = NULL; /* local functions */ -int main P((int argc, char **argv)); -char *optionstr P((option_t *options)); -char *childstr P((int pid)); -int check_status P((int pid, amwait_t w)); - -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(options) -option_t *options; +int main(int argc, char **argv); +char *optionstr(option_t *options); +char *childstr(pid_t pid); +int check_status(pid_t pid, amwait_t w); + +pid_t pipefork(void (*func)(void), char *fname, int *stdinfd, + int stdoutfd, int stderrfd); +void parse_backup_messages(int mesgin); +static void process_dumpline(char *str); +static void save_fd(int *, int); + +double first_num(char *str); + + + +char * +optionstr( + option_t * options) { static char *optstr = NULL; char *compress_opt; @@ -142,6 +149,7 @@ option_t *options; strappend(exclude_list_opt, exc); } } + amfree(exc); optstr = newvstralloc(optstr, compress_opt, encrypt_opt, @@ -162,16 +170,23 @@ option_t *options; } -int main(argc, argv) -int argc; -char **argv; +int +main( + int argc, + char ** argv) { int interactive = 0; - int level, mesgpipe[2]; - char *prog, *disk, *amdevice, *dumpdate, *stroptions; + int level = 0; + int mesgpipe[2]; + char *prog, *dumpdate, *stroptions; + char *disk = NULL; + char *qdisk = NULL; + char *amdevice = NULL; + char *qamdevice = NULL; char *line = NULL; char *err_extra = NULL; char *s; + char *conffile; int i; int ch; unsigned long malloc_hist_1, malloc_size_1; @@ -179,7 +194,8 @@ char **argv; /* initialize */ - safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT); + safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2); + safe_cd(); set_pname("sendbackup"); @@ -187,17 +203,38 @@ char **argv; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); + /* Don't die when interrupt received */ + signal(SIGINT, SIG_IGN); + malloc_size_1 = malloc_inuse(&malloc_hist_1); - interactive = (argc > 1 && strcmp(argv[1],"-t") == 0); + if(argc > 1 && strcmp(argv[1],"-t") == 0) { + interactive = 1; + argc--; + argv++; + } else { + interactive = 0; + } + erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); - dbopen(); + dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(("%s: version %s\n", get_pname(), version())); + if(argc > 2 && strcmp(argv[1], "amandad") == 0) { + amandad_auth = stralloc(argv[2]); + } + our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); + conffile = vstralloc(CONFIG_DIR, "/", "amanda-client.conf", NULL); + if (read_clientconf(conffile) > 0) { + error("error reading conffile: %s", conffile); + /*NOTREACHED*/ + } + amfree(conffile); + if(interactive) { /* * In interactive (debug) mode, the backup data is sent to @@ -211,17 +248,20 @@ char **argv; prog = NULL; disk = NULL; + qdisk = NULL; amdevice = NULL; dumpdate = NULL; stroptions = NULL; for(; (line = agets(stdin)) != NULL; free(line)) { + if (line[0] == '\0') + continue; if(interactive) { fprintf(stderr, "%s> ", get_pname()); fflush(stderr); } #define sc "OPTIONS " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { + if(strncmp(line, sc, SIZEOF(sc)-1) == 0) { #undef sc g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { @@ -229,6 +269,18 @@ char **argv; gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH); g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } + + if (g_options->config) { + conffile = vstralloc(CONFIG_DIR, "/", g_options->config, "/", + "amanda-client.conf", NULL); + if (read_clientconf(conffile) > 0) { + error("error reading conffile: %s", conffile); + /*NOTREACHED*/ + } + amfree(conffile); + + dbrename(g_options->config, DBG_SUBDIR_CLIENT); + } continue; } @@ -237,6 +289,7 @@ char **argv; goto err; } + dbprintf((" sendbackup req: <%s>\n", line)); s = line; ch = *s++; @@ -255,11 +308,15 @@ char **argv; err_extra = "no disk name"; goto err; /* no disk name */ } + amfree(disk); - disk = s - 1; - skip_non_whitespace(s, ch); + amfree(qdisk); + qdisk = s - 1; + ch = *qdisk; + skip_quoted_string(s, ch); s[-1] = '\0'; - disk = stralloc(disk); + qdisk = stralloc(qdisk); + disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { @@ -269,6 +326,7 @@ char **argv; if(!isdigit((int)s[-1])) { amfree(amdevice); + amfree(qamdevice); amdevice = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; @@ -278,7 +336,7 @@ char **argv; else { amdevice = stralloc(disk); } - + qamdevice = quote_string(amdevice); /* find the level number */ if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { err_extra = "bad level"; @@ -303,11 +361,11 @@ char **argv; goto err; /* no options */ } #define sc "OPTIONS " - if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) { + if(strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { err_extra = "no OPTIONS keyword"; goto err; /* no options */ } - s += sizeof(sc)-1; + s += SIZEOF(sc)-1; ch = s[-1]; #undef sc skip_whitespace(s, ch); /* find the options string */ @@ -320,9 +378,18 @@ char **argv; } amfree(line); + if (prog == NULL || + disk == NULL || + amdevice == NULL || + dumpdate == NULL || + stroptions == NULL) { + err_extra = "no valid sendbackup request"; + goto err; + } + dbprintf((" parsed request as: program `%s'\n", prog)); - dbprintf((" disk `%s'\n", disk)); - dbprintf((" device `%s'\n", amdevice)); + dbprintf((" disk `%s'\n", qdisk)); + dbprintf((" device `%s'\n", qamdevice)); dbprintf((" level %d\n", level)); dbprintf((" since %s\n", dumpdate)); dbprintf((" options `%s'\n", stroptions)); @@ -334,6 +401,7 @@ char **argv; } if (programs[i] == NULL) { error("ERROR [%s: unknown program %s]", get_pname(), prog); + /*NOTREACHED*/ } program = programs[i]; @@ -341,14 +409,23 @@ char **argv; if(!interactive) { datafd = DATA_FD_OFFSET + 0; - mesgfd = DATA_FD_OFFSET + 1; - indexfd = DATA_FD_OFFSET + 2; + mesgfd = DATA_FD_OFFSET + 2; + indexfd = DATA_FD_OFFSET + 4; } if (!options->createindex) indexfd = -1; + if(options->auth && amandad_auth) { + if(strcasecmp(options->auth, amandad_auth) != 0) { + printf("ERROR [client configured for auth=%s while server requested '%s']\n", + amandad_auth, options->auth); + exit(-1); + } + } + printf("CONNECT DATA %d MESG %d INDEX %d\n", - datafd, mesgfd, indexfd); + DATA_FD_OFFSET, DATA_FD_OFFSET+1, + indexfd == -1 ? -1 : DATA_FD_OFFSET+2); printf("OPTIONS "); if(am_has_feature(g_options->features, fe_rep_options_features)) { printf("features=%s;", our_feature_string); @@ -372,6 +449,7 @@ char **argv; s = strerror(errno); error("ERROR [%s: open of /dev/null for debug data stream: %s]\n", get_pname(), s); + /*NOTREACHED*/ } mesgfd = 2; indexfd = 1; @@ -396,6 +474,7 @@ char **argv; if(pipe(mesgpipe) == -1) { error("error [opening mesg pipe: %s]", strerror(errno)); + /*NOTREACHED*/ } program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate, datafd, mesgpipe[1], @@ -406,7 +485,9 @@ char **argv; amfree(prog); amfree(disk); + amfree(qdisk); amfree(amdevice); + amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); @@ -438,12 +519,15 @@ char **argv; return 1; } -char *childstr(pid) -int pid; + /* * Returns a string for a child process. Checks the saved dump and * compress pids to see which it is. */ + +char * +childstr( + pid_t pid) { if(pid == dumppid) return program->backup_name; if(pid == comppid) return "compress"; @@ -453,14 +537,16 @@ int pid; } -int check_status(pid, w) -int pid; -amwait_t w; /* * Determine if the child return status really indicates an error. * If so, add the error message to the error string; more than one * child can have an error. */ + +int +check_status( + pid_t pid, + amwait_t w) { char *thiserr = NULL; char *str; @@ -527,10 +613,10 @@ amwait_t w; } if(ret == 0) { - snprintf(number, sizeof(number), "%d", sig); + snprintf(number, SIZEOF(number), "%d", sig); thiserr = vstralloc(str, " got signal ", number, NULL); } else { - snprintf(number, sizeof(number), "%d", ret); + snprintf(number, SIZEOF(number), "%d", ret); thiserr = vstralloc(str, " returned ", number, NULL); } @@ -546,9 +632,11 @@ amwait_t w; } -/* Send header info to the message file. -*/ -void info_tapeheader() +/* + *Send header info to the message file. + */ +void +info_tapeheader(void) { fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name); @@ -562,7 +650,7 @@ void info_tapeheader() #endif ); - fprintf(stderr, "%s -f... -\n", program->restore_name); + fprintf(stderr, "%s -f - ...\n", program->restore_name); if (options->compress == COMPR_FAST || options->compress == COMPR_BEST) fprintf(stderr, "%s: info COMPRESS_SUFFIX=%s\n", @@ -571,24 +659,29 @@ void info_tapeheader() fprintf(stderr, "%s: info end\n", get_pname()); } -int pipefork(func, fname, stdinfd, stdoutfd, stderrfd) -void (*func) P((void)); -char *fname; -int *stdinfd; -int stdoutfd, stderrfd; +pid_t +pipefork( + void (*func)(void), + char * fname, + int * stdinfd, + int stdoutfd, + int stderrfd) { - int pid, inpipe[2]; + int inpipe[2]; + pid_t pid; dbprintf(("%s: forking function %s in pipeline\n", debug_prefix_time(NULL), fname)); if(pipe(inpipe) == -1) { error("error [open pipe to %s: %s]", fname, strerror(errno)); + /*NOTREACHED*/ } switch(pid = fork()) { case -1: error("error [fork %s: %s]", fname, strerror(errno)); + /*NOTREACHED*/ default: /* parent process */ aclose(inpipe[0]); /* close input side of pipe */ *stdinfd = inpipe[1]; @@ -599,27 +692,32 @@ int stdoutfd, stderrfd; if(dup2(inpipe[0], 0) == -1) { error("error [fork %s: dup2(%d, in): %s]", fname, inpipe[0], strerror(errno)); + /*NOTRACHED*/ } if(dup2(stdoutfd, 1) == -1) { error("error [fork %s: dup2(%d, out): %s]", fname, stdoutfd, strerror(errno)); + /*NOTRACHED*/ } if(dup2(stderrfd, 2) == -1) { error("error [fork %s: dup2(%d, err): %s]", fname, stderrfd, strerror(errno)); + /*NOTRACHED*/ } func(); exit(0); - /* NOTREACHED */ + /*NOTREACHED*/ } return pid; } -void parse_backup_messages(mesgin) -int mesgin; +void +parse_backup_messages( + int mesgin) { - int goterror, wpid; + int goterror; + pid_t wpid; amwait_t retstat; char *line; @@ -632,6 +730,7 @@ int mesgin; if(errno) { error("error [read mesg pipe: %s]", strerror(errno)); + /*NOTREACHED*/ } while((wpid = wait(&retstat)) != -1) { @@ -640,8 +739,10 @@ int mesgin; if(errorstr) { error("error [%s]", errorstr); + /*NOTREACHED*/ } else if(dump_size == -1) { error("error [no backup size line]"); + /*NOTREACHED*/ } program->end_backup(goterror); @@ -651,13 +752,13 @@ int mesgin; } -double first_num P((char *str)); - -double first_num(str) -char *str; /* * Returns the value of the first integer in a string. */ + +double +first_num( + char * str) { char *num; int ch; @@ -669,15 +770,16 @@ char *str; while(isdigit(ch) || ch == '.') ch = *str++; str[-1] = '\0'; d = atof(num); - str[-1] = ch; + str[-1] = (char)ch; return d; } -static void process_dumpline(str) -char *str; +static void +process_dumpline( + char * str) { - regex_t *rp; + amregex_t *rp; char *type; char startchr; @@ -724,30 +826,30 @@ char *str; } -/* start_index. Creates an index file from the output of dump/tar. - It arranges that input is the fd to be written by the dump process. - If createindex is not enabled, it does nothing. If it is not, a - new process will be created that tees input both to a pipe whose - read fd is dup2'ed input and to a program that outputs an index - file to `index'. - - make sure that the chat from restore doesn't go to stderr cause - this goes back to amanda which doesn't expect to see it - (2>/dev/null should do it) - - Originally by Alan M. McIvor, 13 April 1996 - - Adapted by Alexandre Oliva, 1 May 1997 - - This program owes a lot to tee.c from GNU sh-utils and dumptee.c - from the DeeJay backup package. - -*/ - -static volatile int index_finished = 0; +/* + * start_index. Creates an index file from the output of dump/tar. + * It arranges that input is the fd to be written by the dump process. + * If createindex is not enabled, it does nothing. If it is not, a + * new process will be created that tees input both to a pipe whose + * read fd is dup2'ed input and to a program that outputs an index + * file to `index'. + * + * make sure that the chat from restore doesn't go to stderr cause + * this goes back to amanda which doesn't expect to see it + * (2>/dev/null should do it) + * + * Originally by Alan M. McIvor, 13 April 1996 + * + * Adapted by Alexandre Oliva, 1 May 1997 + * + * This program owes a lot to tee.c from GNU sh-utils and dumptee.c + * from the DeeJay backup package. + */ -static void save_fd(fd, min) -int *fd, min; +static void +save_fd( + int * fd, + int min) { int origfd = *fd; @@ -763,9 +865,13 @@ int *fd, min; debug_prefix_time(NULL), origfd, *fd)); } -void start_index(createindex, input, mesg, index, cmd) -int createindex, input, mesg, index; -char *cmd; +void +start_index( + int createindex, + int input, + int mesg, + int index, + char * cmd) { int pipefd[2]; FILE *pipe_fp; @@ -776,16 +882,19 @@ char *cmd; if (pipe(pipefd) != 0) { error("creating index pipe: %s", strerror(errno)); + /*NOTREACHED*/ } switch(indexpid = fork()) { case -1: error("forking index tee process: %s", strerror(errno)); + /*NOTREACHED*/ default: aclose(pipefd[0]); if (dup2(pipefd[1], input) == -1) { error("dup'ping index tee output: %s", strerror(errno)); + /*NOTREACHED*/ } aclose(pipefd[1]); return; @@ -811,22 +920,24 @@ char *cmd; if ((pipe_fp = popen(cmd, "w")) == NULL) { error("couldn't start index creator [%s]", strerror(errno)); + /*NOTREACHED*/ } dbprintf(("%s: started index creator: \"%s\"\n", debug_prefix_time(NULL), cmd)); while(1) { char buffer[BUFSIZ], *ptr; - int bytes_read; - int bytes_written; - int just_written; + ssize_t bytes_read; + size_t bytes_written; + ssize_t just_written; do { - bytes_read = read(0, buffer, sizeof(buffer)); + 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)); + /*NOTREACHED*/ } if (bytes_read == 0) @@ -835,9 +946,9 @@ char *cmd; /* write the stuff to the subprocess */ ptr = buffer; bytes_written = 0; - just_written = fullwrite(fileno(pipe_fp), ptr, bytes_read); + just_written = fullwrite(fileno(pipe_fp), ptr, (size_t)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) { @@ -853,10 +964,10 @@ char *cmd; occurs */ ptr = buffer; bytes_written = 0; - just_written = fullwrite(3, ptr, bytes_read); + just_written = fullwrite(3, ptr, (size_t)bytes_read); if (just_written < 0) { error("index tee cannot write [%s]", strerror(errno)); - /* NOTREACHED */ + /*NOTREACHED*/ } else { bytes_written += just_written; ptr += just_written;