/*
* 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 2004/01/14 12:59:12 martinea Exp $
+ * $Id: sendbackup.c,v 1.88 2006/07/25 18:27:56 martinea Exp $
*
* common code for the sendbackup-* programs.
*/
#include "amanda.h"
+#include "match.h"
#include "sendbackup.h"
#include "clock.h"
#include "pipespawn.h"
#include "amfeatures.h"
-#include "stream.h"
#include "arglist.h"
#include "getfsent.h"
-#include "version.h"
+#include "conffile.h"
+#include "amandates.h"
+
+#define sendbackup_debug(i, ...) do { \
+ if ((i) <= debug_sendbackup) { \
+ dbprintf(__VA_LIST__); \
+ } \
+} while (0)
#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;
+pid_t application_api_pid = (pid_t)-1;
char *errorstr = NULL;
-int data_socket, data_port, dataf;
-int mesg_socket, mesg_port, mesgf;
-int index_socket, index_port, indexf;
-
-option_t *options;
+int datafd;
+int mesgfd;
+int indexfd;
-#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
+g_option_t *g_options = NULL;
long dump_size = -1;
backup_program_t *program = NULL;
+dle_t *gdle = 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));
+int main(int argc, char **argv);
+char *childstr(pid_t pid);
+int check_status(pid_t pid, amwait_t w, int mesgfd);
+
+pid_t pipefork(void (*func)(void), char *fname, int *stdinfd,
+ int stdoutfd, int stderrfd);
+int check_result(int mesgfd);
+void parse_backup_messages(dle_t *dle, int mesgin);
+static void process_dumpline(char *str);
+static void save_fd(int *, int);
+void application_api_info_tapeheader(int mesgfd, char *prog, dle_t *dle);
+
+int fdprintf(int fd, char *format, ...) G_GNUC_PRINTF(2, 3);
+
+int
+fdprintf(
+ int fd,
+ char *format,
+ ...)
+{
+ va_list argp;
+ char *s;
+ int r;
+ arglist_start(argp, format);
+ s = g_strdup_vprintf(format, argp);
+ arglist_end(argp);
-char *optionstr(option_t *options)
-{
- static char *optstr = NULL;
- char *compress_opt = "";
- char *record_opt = "";
- char *bsd_opt = "";
- char *krb4_opt = "";
- char *kencrypt_opt = "";
- char *index_opt = "";
- char *exclude_file_opt;
- char *exclude_list_opt;
- char *exc = NULL;
- sle_t *excl;
-
- if(options->compress == COMPR_BEST)
- compress_opt = "compress-best;";
- else if(options->compress == COMPR_FAST)
- compress_opt = "compress-fast;";
- else if(options->compress == COMPR_SERVER_BEST)
- compress_opt = "srvcomp-best;";
- else if(options->compress == COMPR_SERVER_FAST)
- compress_opt = "srvcomp-fast;";
- 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->createindex) index_opt = "index;";
-
- exclude_file_opt = stralloc("");
- if(options->exclude_file) {
- for(excl = options->exclude_file->first; excl != NULL; excl=excl->next){
- exc = newvstralloc(exc, "exclude-file=", excl->name, ";", NULL);
- strappend(exclude_file_opt, exc);
- }
- }
- exclude_list_opt = stralloc("");
- if(options->exclude_list) {
- for(excl = options->exclude_list->first; excl != NULL; excl=excl->next){
- exc = newvstralloc(exc, "exclude-list=", excl->name, ";", NULL);
- strappend(exclude_list_opt, exc);
- }
- }
- optstr = newvstralloc(optstr,
- compress_opt,
- record_opt,
- bsd_opt,
- krb4_opt,
- kencrypt_opt,
- index_opt,
- exclude_file_opt,
- exclude_list_opt,
- NULL);
- return optstr;
+ r = full_write(fd, s, strlen(s));
+ amfree(s);
+ return r;
}
-
-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];
+ dle_t *dle = NULL;
+ char *dumpdate, *stroptions;
+ char *qdisk = NULL;
+ char *qamdevice = NULL;
char *line = NULL;
char *err_extra = NULL;
char *s;
int i;
int ch;
- unsigned long malloc_hist_1, malloc_size_1;
- unsigned long malloc_hist_2, malloc_size_2;
- int fd;
+ GSList *errlist;
+ FILE *mesgstream;
+ level_t *alevel;
/* initialize */
-
- for(fd = 3; fd < FD_SETSIZE; fd++) {
- /*
- * Make sure nobody spoofs us with a lot of extra open files
- * that would cause an open we do to get a very high file
- * descriptor, which in turn might be used as an index into
- * an array (e.g. an fd_set).
- */
-#ifdef KRB4_SECURITY
- if (fd != KEY_PIPE) /* XXX interface needs to be fixed */
-#endif
- close(fd);
- }
+ /*
+ * Configure program for internationalization:
+ * 1) Only set the message locale for now.
+ * 2) Set textdomain for all amanda related programs to "amanda"
+ * We don't want to be forced to support dozens of message catalogs.
+ */
+ setlocale(LC_MESSAGES, "C");
+ textdomain("amanda");
+
+ safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
+ openbsd_fd_inform();
safe_cd();
set_pname("sendbackup");
- malloc_size_1 = malloc_inuse(&malloc_hist_1);
+ /* Don't die when child closes pipe */
+ signal(SIGPIPE, SIG_IGN);
+
+ /* Don't die when interrupt received */
+ signal(SIGINT, SIG_IGN);
- interactive = (argc > 1 && strcmp(argv[1],"-t") == 0);
- erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
- dbopen();
+ if(argc > 1 && strcmp(argv[1],"-t") == 0) {
+ interactive = 1;
+ argc--;
+ argv++;
+ } else {
+ interactive = 0;
+ }
+
+ add_amanda_log_handler(amanda_log_stderr);
+ add_amanda_log_handler(amanda_log_syslog);
+ dbopen(DBG_SUBDIR_CLIENT);
startclock();
- dbprintf(("%s: version %s\n", argv[0], version()));
+ dbprintf(_("Version %s\n"), 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);
+ config_init(CONFIG_INIT_CLIENT, NULL);
+ /* (check for config errors comes later) */
+
+ check_running_as(RUNNING_AS_CLIENT_LOGIN);
+
if(interactive) {
/*
* In interactive (debug) mode, the backup data is sent to
* programs on the tape host are set up. The index service is
* run and goes to stdout.
*/
- fprintf(stderr, "%s: running in interactive test mode\n", get_pname());
+ g_fprintf(stderr, _("%s: running in interactive test mode\n"), get_pname());
fflush(stderr);
}
- prog = NULL;
- disk = NULL;
- amdevice = NULL;
+ qdisk = NULL;
dumpdate = NULL;
stroptions = NULL;
- /* parse dump request */
-
for(; (line = agets(stdin)) != NULL; free(line)) {
+ if (line[0] == '\0')
+ continue;
if(interactive) {
- fprintf(stderr, "%s> ", get_pname());
+ g_fprintf(stderr, "%s> ", get_pname());
fflush(stderr);
}
-#define sc "OPTIONS "
- if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-#undef sc
+ if(strncmp_const(line, "OPTIONS ") == 0) {
g_options = parse_g_options(line+8, 1);
if(!g_options->hostname) {
g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1);
gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH);
g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0';
}
+
+ if (g_options->config) {
+ /* overlay this configuration on the existing (nameless) configuration */
+ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
+ g_options->config);
+
+ dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
+ }
+
+ /* check for any config errors now */
+ if (config_errors(&errlist) >= CFGERR_ERRORS) {
+ char *errstr = config_errors_to_error_string(errlist);
+ g_printf("%s\n", errstr);
+ dbclose();
+ return 1;
+ }
+
+ if (am_has_feature(g_options->features, fe_req_xml)) {
+ break;
+ }
continue;
}
- if (prog != NULL) {
- err_extra = "multiple requests";
+ if (dle && dle->program != NULL) {
+ err_extra = _("multiple requests");
goto err;
}
+ dbprintf(_(" sendbackup req: <%s>\n"), line);
+ dle = alloc_dle();
+
s = line;
ch = *s++;
skip_whitespace(s, ch); /* find the program name */
if(ch == '\0') {
- err_extra = "no program name";
+ err_extra = _("no program name");
goto err; /* no program name */
}
- prog = s - 1;
+ dle->program = s - 1;
skip_non_whitespace(s, ch);
s[-1] = '\0';
- prog = stralloc(prog);
+
+ if (strcmp(dle->program, "APPLICATION")==0) {
+ dle->program_is_application_api=1;
+ skip_whitespace(s, ch); /* find dumper name */
+ if (ch == '\0') {
+ goto err; /* no program */
+ }
+ dle->program = s - 1;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ }
+ dle->program = stralloc(dle->program);
skip_whitespace(s, ch); /* find the disk name */
if(ch == '\0') {
- err_extra = "no disk name";
+ 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);
+ dle->disk = unquote_string(qdisk);
skip_whitespace(s, ch); /* find the device or level */
if (ch == '\0') {
- err_extra = "bad level";
+ err_extra = _("bad level");
goto err;
}
if(!isdigit((int)s[-1])) {
- amfree(amdevice);
- amdevice = s - 1;
- skip_non_whitespace(s, ch);
+ amfree(qamdevice);
+ qamdevice = s - 1;
+ ch = *qamdevice;
+ skip_quoted_string(s, ch);
s[-1] = '\0';
- amdevice = stralloc(amdevice);
+ qamdevice = stralloc(qamdevice);
+ dle->device = unquote_string(qamdevice);
skip_whitespace(s, ch); /* find level number */
}
else {
- amdevice = stralloc(disk);
+ dle->device = stralloc(dle->disk);
+ qamdevice = stralloc(qdisk);
}
-
/* find the level number */
if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
- err_extra = "bad level";
+ err_extra = _("bad level");
goto err; /* bad level */
}
skip_integer(s, ch);
+ alevel = g_new0(level_t, 1);
+ alevel->level = level;
+ dle->levellist = g_slist_append(dle->levellist, alevel);
skip_whitespace(s, ch); /* find the dump date */
if(ch == '\0') {
- err_extra = "no dumpdate";
+ err_extra = _("no dumpdate");
goto err; /* no dumpdate */
}
amfree(dumpdate);
skip_whitespace(s, ch); /* find the options keyword */
if(ch == '\0') {
- err_extra = "no options";
+ err_extra = _("no options");
goto err; /* no options */
}
-#define sc "OPTIONS "
- if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
- err_extra = "no OPTIONS keyword";
+ if(strncmp_const_skip(s - 1, "OPTIONS ", s, ch) != 0) {
+ err_extra = _("no OPTIONS keyword");
goto err; /* no options */
}
- s += sizeof(sc)-1;
- ch = s[-1];
-#undef sc
skip_whitespace(s, ch); /* find the options string */
if(ch == '\0') {
- err_extra = "bad options string";
+ err_extra = _("bad options string");
goto err; /* no options */
}
amfree(stroptions);
stroptions = stralloc(s - 1);
}
amfree(line);
+ if (g_options == NULL) {
+ g_printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n"));
+ error(_("Missing OPTIONS line in sendbackup input\n"));
+ /*NOTREACHED*/
+ }
- dbprintf((" parsed request as: program `%s'\n", prog));
- dbprintf((" disk `%s'\n", disk));
- dbprintf((" device `%s'\n", amdevice));
- dbprintf((" level %d\n", level));
- dbprintf((" since %s\n", dumpdate));
- dbprintf((" options `%s'\n", stroptions));
+ if (am_has_feature(g_options->features, fe_req_xml)) {
+ char *errmsg = NULL;
- for(i = 0; programs[i] != NULL; i++) {
- if (strcmp(programs[i]->name, prog) == 0) {
- break;
+ dle = amxml_parse_node_FILE(stdin, &errmsg);
+ if (errmsg) {
+ err_extra = errmsg;
+ goto err;
+ }
+ if (!dle) {
+ err_extra = _("One DLE required");
+ goto err;
+ } else if (dle->next) {
+ err_extra = _("Only one DLE allowed");
+ goto err;
}
+
+ qdisk = quote_string(dle->disk);
+ if (dle->device == NULL)
+ dle->device = stralloc(dle->disk);
+ qamdevice = quote_string(dle->device);
+ dumpdate = stralloc("NODATE");
+ stroptions = stralloc("");
+ } else {
+ parse_options(stroptions, dle, g_options->features, 0);
}
- if (programs[i] == NULL) {
- error("ERROR [%s: unknown program %s]", get_pname(), prog);
+ gdle = dle;
+
+ if (dle->program == NULL ||
+ dle->disk == NULL ||
+ dle->device == NULL ||
+ dle->levellist == NULL ||
+ dumpdate == NULL) {
+ err_extra = _("no valid sendbackup request");
+ goto err;
}
- program = programs[i];
- options = parse_options(stroptions, disk, amdevice, g_options->features, 0);
+ if (g_slist_length(dle->levellist) != 1) {
+ err_extra = _("Too many level");
+ goto err;
+ }
-#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());
+ alevel = (level_t *)dle->levellist->data;
+ level = alevel->level;
+ dbprintf(_(" Parsed request as: program `%s'\n"), dle->program);
+ 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);
+ dbprintf(_(" datapath `%s'\n"),
+ data_path_to_string(dle->data_path));
+
+ if (dle->program_is_application_api==1) {
+ /* check that the application_api exist */
+ } else {
+ for(i = 0; programs[i]; i++) {
+ if (strcmp(programs[i]->name, dle->program) == 0) {
+ break;
+ }
+ }
+ if (programs[i] == NULL) {
+ dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(),
+ dle->program);
+ error(_("ERROR [%s: unknown program %s]"), get_pname(),
+ dle->program);
+ /*NOTREACHED*/
}
+ program = programs[i];
}
-#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));
- }
+ datafd = DATA_FD_OFFSET + 0;
+ mesgfd = DATA_FD_OFFSET + 2;
+ indexfd = DATA_FD_OFFSET + 4;
}
- 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;
+ if (!dle->create_index)
+ indexfd = -1;
+
+ if (dle->auth && amandad_auth) {
+ if(strcasecmp(dle->auth, amandad_auth) != 0) {
+ g_printf(_("ERROR [client configured for auth=%s while server requested '%s']\n"),
+ amandad_auth, dle->auth);
+ exit(-1);
+ }
}
- printf("CONNECT DATA %d MESG %d INDEX %d\n",
- data_port, mesg_port, index_port);
- printf("OPTIONS ");
+ if (dle->kencrypt) {
+ g_printf("KENCRYPT\n");
+ }
+
+ g_printf(_("CONNECT DATA %d MESG %d INDEX %d\n"),
+ DATA_FD_OFFSET, DATA_FD_OFFSET+1,
+ indexfd == -1 ? -1 : DATA_FD_OFFSET+2);
+ g_printf(_("OPTIONS "));
if(am_has_feature(g_options->features, fe_rep_options_features)) {
- printf("features=%s;", our_feature_string);
+ g_printf("features=%s;", our_feature_string);
}
if(am_has_feature(g_options->features, fe_rep_options_hostname)) {
- printf("hostname=%s;", g_options->hostname);
+ g_printf("hostname=%s;", g_options->hostname);
}
- if(am_has_feature(g_options->features, fe_rep_options_sendbackup_options)) {
- printf("%s", optionstr(options));
+ if (!am_has_feature(g_options->features, fe_rep_options_features) &&
+ !am_has_feature(g_options->features, fe_rep_options_hostname)) {
+ g_printf(";");
}
- printf("\n");
+ g_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(_("Error redirecting stdout to /dev/null: %s\n"),
+ 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) {
+ error(_("ERROR [open of /dev/null for debug data stream: %s]\n"),
+ strerror(errno));
+ /*NOTREACHED*/
}
+ mesgfd = 2;
+ indexfd = 1;
}
if(!interactive) {
- if(dataf == -1 || mesgf == -1 || (options->createindex && indexf == -1)) {
+ if(datafd == -1 || mesgfd == -1 || (dle->create_index && indexfd == -1)) {
dbclose();
exit(1);
}
}
- dbprintf(("%s: got all connections\n", debug_prefix_time(NULL)));
+ mesgstream = fdopen(mesgfd,"w");
+ run_client_scripts(EXECUTE_ON_PRE_DLE_BACKUP, g_options, dle, mesgstream);
+ fflush(mesgstream);
+
+ if (dle->program_is_application_api==1) {
+ guint j;
+ char *cmd=NULL;
+ GPtrArray *argv_ptr;
+ char levelstr[20];
+ backup_support_option_t *bsu;
+ char *compopt = NULL;
+ char *encryptopt = skip_argument;
+ int compout, dumpout;
+ GSList *scriptlist;
+ script_t *script;
+ time_t cur_dumptime;
+ int result;
+ GPtrArray *errarray;
+ int errfd[2];
+ FILE *dumperr;
+
+ /* apply client-side encryption here */
+ if ( dle->encrypt == ENCRYPT_CUST ) {
+ encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
+ &compout, &datafd, &mesgfd,
+ dle->clnt_encrypt, encryptopt, NULL);
+ dbprintf(_("encrypt: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
+ } else {
+ compout = datafd;
+ encpid = -1;
+ }
-#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)));
+ /* now do the client-side compression */
+ if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
+ compopt = skip_argument;
+#if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
+ if(dle->compress == COMP_BEST) {
+ compopt = COMPRESS_BEST_OPT;
+ } else {
+ compopt = COMPRESS_FAST_OPT;
+ }
+#endif
+ comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
+ &dumpout, &compout, &mesgfd,
+ COMPRESS_PATH, compopt, NULL);
+ if(compopt != skip_argument) {
+ dbprintf(_("compress pid %ld: %s %s\n"),
+ (long)comppid, COMPRESS_PATH, compopt);
+ } else {
+ dbprintf(_("compress pid %ld: %s\n"), (long)comppid, COMPRESS_PATH);
+ }
+ } else if (dle->compress == COMP_CUST) {
+ compopt = skip_argument;
+ comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
+ &dumpout, &compout, &mesgfd,
+ dle->compprog, compopt, NULL);
+ if(compopt != skip_argument) {
+ dbprintf(_("pid %ld: %s %s\n"),
+ (long)comppid, dle->compprog, compopt);
+ } else {
+ dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog);
+ }
+ } else {
+ dumpout = compout;
+ comppid = -1;
+ }
+ cur_dumptime = time(0);
+ bsu = backup_support_option(dle->program, g_options, dle->disk,
+ dle->device, &errarray);
+ if (!bsu) {
+ char *errmsg;
+ char *qerrmsg;
+ guint i;
+ for (i=0; i < errarray->len; i++) {
+ errmsg = g_ptr_array_index(errarray, i);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd,
+ _("sendbackup: error [Application '%s': %s]\n"),
+ dle->program, errmsg);
+ dbprintf("aa: %s\n",qerrmsg);
+ amfree(qerrmsg);
+ }
+ if (i == 0) { /* no errarray */
+ errmsg = vstrallocf(_("Can't execute application '%s'"),
+ dle->program);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
+ dbprintf(_("ERROR %s\n"), qerrmsg);
+ amfree(qerrmsg);
+ amfree(errmsg);
+ }
+ return 0;
}
- if(kerberos_handshake(mesgf, session_key) == 0) {
- dbprintf(("%s: kerberos_handshake on mesg socket failed\n",
- debug_prefix_time(NULL)));
- dbclose();
+ if (pipe(errfd) < 0) {
+ char *errmsg;
+ char *qerrmsg;
+ errmsg = vstrallocf(_("Application '%s': can't create pipe"),
+ dle->program);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
+ dbprintf(_("ERROR %s\n"), qerrmsg);
+ amfree(qerrmsg);
+ amfree(errmsg);
+ return 0;
+ }
+
+ switch(application_api_pid=fork()) {
+ case 0:
+ argv_ptr = g_ptr_array_new();
+ cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL);
+ g_ptr_array_add(argv_ptr, stralloc(dle->program));
+ g_ptr_array_add(argv_ptr, stralloc("backup"));
+ if (bsu->message_line == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--message"));
+ g_ptr_array_add(argv_ptr, stralloc("line"));
+ }
+ if (g_options->config && bsu->config == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--config"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->config));
+ }
+ if (g_options->hostname && bsu->host == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--host"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
+ }
+ if (dle->disk && bsu->disk == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--disk"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->disk));
+ }
+ g_ptr_array_add(argv_ptr, stralloc("--device"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->device));
+ if (level <= bsu->max_level) {
+ g_ptr_array_add(argv_ptr, stralloc("--level"));
+ g_snprintf(levelstr,19,"%d",level);
+ g_ptr_array_add(argv_ptr, stralloc(levelstr));
+ }
+ if (indexfd != -1 && bsu->index_line == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--index"));
+ g_ptr_array_add(argv_ptr, stralloc("line"));
+ }
+ if (dle->record && bsu->record == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--record"));
+ }
+ application_property_add_to_argv(argv_ptr, dle, bsu,
+ g_options->features);
+
+ for (scriptlist = dle->scriptlist; scriptlist != NULL;
+ scriptlist = scriptlist->next) {
+ script = (script_t *)scriptlist->data;
+ if (script->result && script->result->proplist) {
+ property_add_to_argv(argv_ptr, script->result->proplist);
+ }
+ }
+
+ g_ptr_array_add(argv_ptr, NULL);
+ dbprintf(_("%s: running \"%s\n"), get_pname(), cmd);
+ for (j = 1; j < argv_ptr->len - 1; j++)
+ dbprintf(" %s\n", (char *)g_ptr_array_index(argv_ptr,j));
+ dbprintf(_("\"\n"));
+ if(dup2(dumpout, 1) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(errfd[1], 2) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if(dup2(mesgfd, 3) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if(indexfd > 0) {
+ if(dup2(indexfd, 4) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ fcntl(indexfd, F_SETFD, 0);
+ }
+ application_api_info_tapeheader(mesgfd, dle->program, dle);
+ if (indexfd != 0) {
+ safe_fd(3, 2);
+ } else {
+ safe_fd(3, 1);
+ }
+ execve(cmd, (char **)argv_ptr->pdata, safe_env());
exit(1);
- } else {
- dbprintf(("%s: kerberos_handshake on mesg socket succeeded\n",
- debug_prefix_time(NULL)));
+ break;
+
+ default:
+ break;
+ case -1:
+ error(_("%s: fork returned: %s"), get_pname(), strerror(errno));
+ }
+ close(errfd[1]);
+ dumperr = fdopen(errfd[0],"r");
+ if (!dumperr) {
+ error(_("Can't fdopen: %s"), strerror(errno));
+ /*NOTREACHED*/
}
- dbprintf(("%s: kerberos handshakes succeeded!\n",
- debug_prefix_time(NULL)));
- }
- }
-#endif
+ result = 0;
+ while ((line = agets(dumperr)) != NULL) {
+ if (strlen(line) > 0) {
+ fdprintf(mesgfd, "sendbackup: error [%s]\n", line);
+ dbprintf("error: %s\n", line);
+ result = 1;
+ }
+ amfree(line);
+ }
- if(!interactive) {
- /* redirect stderr */
- if(dup2(mesgf, 2) == -1) {
- dbprintf(("%s: error redirecting stderr: %s\n",
- debug_prefix(NULL), strerror(errno)));
- dbclose();
- exit(1);
- }
- }
+ result |= check_result(mesgfd);
+ if (result == 0) {
+ char *amandates_file;
+
+ amandates_file = getconf_str(CNF_AMANDATES);
+ if(start_amandates(amandates_file, 1)) {
+ amandates_updateone(dle->disk, level, cur_dumptime);
+ finish_amandates();
+ free_amandates();
+ } else {
+ if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE &&
+ bsu->calcsize) {
+ error(_("error [opening %s for writing: %s]"),
+ amandates_file, strerror(errno));
+ } else {
+ g_debug(_("non-fatal error opening '%s' for writing: %s]"),
+ amandates_file, strerror(errno));
+ }
+ }
+ }
+ amfree(bsu);
+ } else {
+ if(!interactive) {
+ /* redirect stderr */
+ if(dup2(mesgfd, 2) == -1) {
+ dbprintf(_("Error redirecting stderr to fd %d: %s\n"),
+ mesgfd, strerror(errno));
+ dbclose();
+ exit(1);
+ }
+ }
+
+ if(pipe(mesgpipe) == -1) {
+ s = strerror(errno);
+ dbprintf(_("error [opening mesg pipe: %s]\n"), s);
+ error(_("error [opening mesg pipe: %s]"), s);
+ }
- if(pipe(mesgpipe) == -1) {
- error("error [opening mesg pipe: %s]", strerror(errno));
+ program->start_backup(dle, g_options->hostname,
+ datafd, mesgpipe[1], indexfd);
+ dbprintf(_("Started backup\n"));
+ parse_backup_messages(dle, mesgpipe[0]);
+ dbprintf(_("Parsed backup messages\n"));
}
- program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate,
- dataf, mesgpipe[1], indexf);
- parse_backup_messages(mesgpipe[0]);
+ run_client_scripts(EXECUTE_ON_POST_DLE_BACKUP, g_options, dle, mesgstream);
+ fflush(mesgstream);
- amfree(prog);
- amfree(disk);
- amfree(amdevice);
+ amfree(qdisk);
+ amfree(qamdevice);
amfree(dumpdate);
amfree(stroptions);
amfree(our_feature_string);
am_release_feature_set(our_features);
our_features = NULL;
- am_release_feature_set(g_options->features);
- g_options->features = NULL;
- amfree(g_options->hostname);
- amfree(g_options->str);
- amfree(g_options);
+ free_g_options(g_options);
dbclose();
- malloc_size_2 = malloc_inuse(&malloc_hist_2);
+ return 0;
- if(malloc_size_1 != malloc_size_2) {
- malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
+ err:
+ if (err_extra) {
+ g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra);
+ dbprintf(_("REQ packet is bogus: %s\n"), err_extra);
+ } else {
+ g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET\n"));
+ dbprintf(_("REQ packet is bogus\n"));
}
- return 0;
+ amfree(qdisk);
+ amfree(qamdevice);
+ amfree(dumpdate);
+ amfree(stroptions);
+ amfree(our_feature_string);
- err:
- printf("FORMAT ERROR IN REQUEST PACKET\n");
- dbprintf(("%s: REQ packet is bogus%s%s\n",
- debug_prefix_time(NULL),
- err_extra ? ": " : "",
- err_extra ? err_extra : ""));
dbclose();
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";
- if(pid == encpid) return "kencrypt";
+ if(pid == encpid) return "encrypt";
if(pid == indexpid) return "index";
+ if(pid == application_api_pid) {
+ if (!gdle) {
+ dbprintf("gdle == NULL\n");
+ return "gdle == NULL";
+ }
+ return gdle->program;
+ }
return "unknown";
}
-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,
+ int mesgfd)
{
char *thiserr = NULL;
- char *str;
+ char *str, *strX;
int ret, sig, rc;
- char number[NUM_STR_SIZE];
str = childstr(pid);
* but the failure is noted.
*/
if(ret != 0) {
- fprintf(stderr, "? %s returned %d\n", str, ret);
+ fdprintf(mesgfd, _("? index %s returned %d\n"), str, ret);
rc = 0;
}
- }
-
-#ifndef HAVE_GZIP
- if(pid == comppid) {
+ indexpid = -1;
+ strX = "index";
+ } else if(pid == comppid) {
/*
* compress returns 2 sometimes, but it is ok.
*/
+#ifndef HAVE_GZIP
if(ret == 2) {
rc = 0;
}
- }
#endif
-
-#ifdef DUMP_RETURNS_1
- if(pid == dumppid && tarpid == -1) {
+ comppid = -1;
+ strX = "compress";
+ } else if(pid == dumppid && tarpid == -1) {
/*
* Ultrix dump returns 1 sometimes, but it is ok.
*/
+#ifdef DUMP_RETURNS_1
if(ret == 1) {
rc = 0;
}
- }
#endif
-
-#ifdef IGNORE_TAR_ERRORS
- if(pid == tarpid) {
+ dumppid = -1;
+ strX = "dump";
+ } else if(pid == tarpid) {
+ if (ret == 1) {
+ rc = 0;
+ }
/*
* tar bitches about active filesystems, but we do not care.
*/
+#ifdef IGNORE_TAR_ERRORS
if(ret == 2) {
rc = 0;
}
- }
#endif
+ dumppid = tarpid = -1;
+ strX = "dump";
+ } else if(pid == application_api_pid) {
+ strX = "Application";
+ } else {
+ strX = "unknown";
+ }
if(rc == 0) {
return 0; /* normal exit */
}
if(ret == 0) {
- ap_snprintf(number, sizeof(number), "%d", sig);
- thiserr = vstralloc(str, " got signal ", number, NULL);
+ thiserr = vstrallocf(_("%s (%d) %s got signal %d"), strX, (int)pid, str,
+ sig);
} else {
- ap_snprintf(number, sizeof(number), "%d", ret);
- thiserr = vstralloc(str, " returned ", number, NULL);
+ thiserr = vstrallocf(_("%s (%d) %s returned %d"), strX, (int)pid, str, ret);
}
+ fdprintf(mesgfd, "? %s\n", thiserr);
+
if(errorstr) {
- strappend(errorstr, ", ");
- strappend(errorstr, thiserr);
+ errorstr = newvstrallocf(errorstr, "%s, %s", errorstr, thiserr);
amfree(thiserr);
} else {
errorstr = thiserr;
}
-/* Send header info to the message file.
-*/
-void write_tapeheader()
+/*
+ *Send header info to the message file.
+ */
+void
+info_tapeheader(
+ dle_t *dle)
{
- fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name);
+ g_fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name);
- fprintf(stderr, "%s: info RECOVER_CMD=", get_pname());
- if (options->compress == COMPR_FAST || options->compress == COMPR_BEST)
- fprintf(stderr, "%s %s |", UNCOMPRESS_PATH,
+ g_fprintf(stderr, "%s: info RECOVER_CMD=", get_pname());
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST)
+ g_fprintf(stderr, "%s %s |", UNCOMPRESS_PATH,
#ifdef UNCOMPRESS_OPT
UNCOMPRESS_OPT
#else
#endif
);
- fprintf(stderr, "%s -f... -\n", program->restore_name);
+ g_fprintf(stderr, "%s -xpGf - ...\n", program->restore_name);
- if (options->compress == COMPR_FAST || options->compress == COMPR_BEST)
- fprintf(stderr, "%s: info COMPRESS_SUFFIX=%s\n",
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST)
+ g_fprintf(stderr, "%s: info COMPRESS_SUFFIX=%s\n",
get_pname(), COMPRESS_SUFFIX);
- fprintf(stderr, "%s: info end\n", get_pname());
+ g_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;
+void
+application_api_info_tapeheader(
+ int mesgfd,
+ char *prog,
+ dle_t *dle)
{
- int pid, inpipe[2];
+ char line[1024];
+
+ g_snprintf(line, 1024, "%s: info BACKUP=APPLICATION\n", get_pname());
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
- dbprintf(("%s: forking function %s in pipeline\n",
- debug_prefix_time(NULL), fname));
+ g_snprintf(line, 1024, "%s: info APPLICATION=%s\n", get_pname(), prog);
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+
+ g_snprintf(line, 1024, "%s: info RECOVER_CMD=", get_pname());
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
+ g_snprintf(line, 1024, "%s %s |", UNCOMPRESS_PATH,
+#ifdef UNCOMPRESS_OPT
+ UNCOMPRESS_OPT
+#else
+ ""
+#endif
+ );
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+ }
+ g_snprintf(line, 1024, "%s/%s restore [./file-to-restore]+\n",
+ APPLICATION_DIR, prog);
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+
+ if (dle->compress) {
+ g_snprintf(line, 1024, "%s: info COMPRESS_SUFFIX=%s\n",
+ get_pname(), COMPRESS_SUFFIX);
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+ }
+
+ g_snprintf(line, 1024, "%s: info end\n", get_pname());
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
+ dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
+ return;
+ }
+}
+
+pid_t
+pipefork(
+ void (*func)(void),
+ char * fname,
+ int * stdinfd,
+ int stdoutfd,
+ int stderrfd)
+{
+ int inpipe[2];
+ pid_t pid;
+
+ dbprintf(_("Forking function %s in pipeline\n"), fname);
if(pipe(inpipe) == -1) {
- error("error [open pipe to %s: %s]", fname, strerror(errno));
+ error(_("error [open pipe to %s: %s]"), fname, strerror(errno));
+ /*NOTREACHED*/
}
switch(pid = fork()) {
case -1:
- error("error [fork %s: %s]", fname, strerror(errno));
+ error(_("error [fork %s: %s]"), fname, strerror(errno));
+ /*NOTREACHED*/
default: /* parent process */
aclose(inpipe[0]); /* close input side of pipe */
*stdinfd = inpipe[1];
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));
+ /*NOTRACHED*/
}
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));
+ /*NOTRACHED*/
}
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));
+ /*NOTRACHED*/
}
func();
exit(0);
- /* NOTREACHED */
+ /*NOTREACHED*/
}
return pid;
}
-void parse_backup_messages(mesgin)
-int mesgin;
+int
+check_result(
+ int mesgfd)
{
- int goterror, wpid;
+ int goterror;
+ pid_t wpid;
amwait_t retstat;
- char *line;
goterror = 0;
+
+
+ while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
+ }
+
+ if (dumppid != -1) {
+ sleep(5);
+ while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
+ }
+ }
+ if (dumppid != -1) {
+ dbprintf(_("Sending SIGHUP to dump process %d\n"),
+ (int)dumppid);
+ if(dumppid != -1) {
+ if(kill(dumppid, SIGHUP) == -1) {
+ dbprintf(_("Can't send SIGHUP to %d: %s\n"),
+ (int)dumppid,
+ strerror(errno));
+ }
+ }
+ sleep(5);
+ while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
+ }
+ }
+ if (dumppid != -1) {
+ dbprintf(_("Sending SIGKILL to dump process %d\n"),
+ (int)dumppid);
+ if(dumppid != -1) {
+ if(kill(dumppid, SIGKILL) == -1) {
+ dbprintf(_("Can't send SIGKILL to %d: %s\n"),
+ (int)dumppid,
+ strerror(errno));
+ }
+ }
+ sleep(5);
+ while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
+ }
+ }
+
+ return goterror;
+}
+
+void
+parse_backup_messages(
+ dle_t *dle,
+ int mesgin)
+{
+ int goterror;
+ char *line;
+
amfree(errorstr);
for(; (line = areads(mesgin)) != NULL; free(line)) {
}
if(errno) {
- error("error [read mesg pipe: %s]", strerror(errno));
+ error(_("error [read mesg pipe: %s]"), strerror(errno));
+ /*NOTREACHED*/
}
- while((wpid = wait(&retstat)) != -1) {
- if(check_status(wpid, retstat)) goterror = 1;
- }
+ goterror = check_result(mesgfd);
if(errorstr) {
- error("error [%s]", errorstr);
+ error(_("error [%s]"), errorstr);
+ /*NOTREACHED*/
} else if(dump_size == -1) {
- error("error [no backup size line]");
+ error(_("error [no backup size line]"));
+ /*NOTREACHED*/
}
- program->end_backup(goterror);
+ program->end_backup(dle, goterror);
- fprintf(stderr, "%s: size %ld\n", get_pname(), dump_size);
- fprintf(stderr, "%s: end\n", get_pname());
+ fdprintf(mesgfd, _("%s: size %ld\n"), get_pname(), dump_size);
+ fdprintf(mesgfd, _("%s: end\n"), get_pname());
}
-double first_num P((char *str));
-
-double first_num(str)
-char *str;
-/*
- * Returns the value of the first integer in a string.
- */
+static void
+process_dumpline(
+ char * str)
{
- char *num;
- int ch;
- double d;
-
- ch = *str++;
- while(ch && !isdigit(ch)) ch = *str++;
- num = str - 1;
- while(isdigit(ch) || ch == '.') ch = *str++;
- str[-1] = '\0';
- d = atof(num);
- str[-1] = ch;
- return d;
-}
-
-static void process_dumpline(str)
-char *str;
-{
- regex_t *rp;
+ amregex_t *rp;
char *type;
char startchr;
}
}
if(rp->typ == DMP_SIZE) {
- dump_size = (long)((first_num(str) * rp->scale + 1023.0)/1024.0);
+ dump_size = (long)((the_num(str, rp->field)* rp->scale+1023.0)/1024.0);
}
switch(rp->typ) {
case DMP_NORMAL:
startchr = '!';
break;
}
- dbprintf(("%s: %3d: %7s(%c): %s\n",
- debug_prefix_time(NULL),
+ dbprintf("%3d: %7s(%c): %s\n",
rp->srcline,
type,
startchr,
- str));
- fprintf(stderr, "%c %s\n", startchr, str);
+ str);
+ fdprintf(mesgfd, "%c %s\n", startchr, 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;
-
-static void index_closed(sig)
-int sig;
-{
- index_finished = 1;
-}
+/*
+ * 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.
+ */
-void save_fd(fd, min)
-int *fd, min;
+static void
+save_fd(
+ int * fd,
+ int min)
{
int origfd = *fd;
while (*fd >= 0 && *fd < min) {
int newfd = dup(*fd);
if (newfd == -1)
- dbprintf(("%s: unable to save file descriptor [%s]\n",
- debug_prefix(NULL), strerror(errno)));
+ dbprintf(_("Unable to save file descriptor [%s]\n"), strerror(errno));
*fd = newfd;
}
if (origfd != *fd)
- dbprintf(("%s: dupped file descriptor %i to %i\n",
- debug_prefix(NULL), origfd, *fd));
+ dbprintf(_("Dupped file descriptor %i to %i\n"), 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)
{
- struct sigaction act, oact;
int pipefd[2];
FILE *pipe_fp;
int exitcode;
return;
if (pipe(pipefd) != 0) {
- error("creating index pipe: %s", strerror(errno));
+ error(_("creating index pipe: %s"), strerror(errno));
+ /*NOTREACHED*/
}
switch(indexpid = fork()) {
case -1:
- error("forking index tee process: %s", strerror(errno));
+ 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));
+ error(_("dup'ping index tee output: %s"), strerror(errno));
+ /*NOTREACHED*/
}
aclose(pipefd[1]);
return;
dup2(index, 1);
dup2(mesg, 2);
dup2(input, 3);
- for(index = 4; index < FD_SETSIZE; index++) {
+ for(index = 4; index < (int)FD_SETSIZE; index++) {
if (index != dbfd()) {
close(index);
}
}
- /* 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));
+ error(_("couldn't start index creator [%s]"), strerror(errno));
+ /*NOTREACHED*/
}
- dbprintf(("%s: started index creator: \"%s\"\n",
- debug_prefix_time(NULL), cmd));
+ dbprintf(_("Started index creator: \"%s\"\n"), cmd);
while(1) {
char buffer[BUFSIZ], *ptr;
- int bytes_read;
- int bytes_written;
- int just_written;
+ ssize_t bytes_read;
+ size_t bytes_written;
+ size_t 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));
+ error(_("index tee cannot read [%s]"), strerror(errno));
+ /*NOTREACHED*/
}
if (bytes_read == 0)
/* 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;
- }
- } else {
+ just_written = full_write(fileno(pipe_fp), ptr, (size_t)bytes_read);
+ if (just_written < (size_t)bytes_read) {
+ /*
+ * just as we waited for write() to complete.
+ */
+ if (errno != EPIPE) {
+ dbprintf(_("Index tee cannot write to index creator [%s]\n"),
+ strerror(errno));
+ }
+ } 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) {
- error("index tee cannot write [%s]", strerror(errno));
- } else {
+ just_written = full_write(3, ptr, bytes_read);
+ if (just_written < (size_t)bytes_read) {
+ error(_("index tee cannot write [%s]"), strerror(errno));
+ /*NOTREACHED*/
+ } else {
bytes_written += just_written;
ptr += just_written;
- }
}
}
/* finished */
/* 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));
+ char *exitstr = str_exit_status("Index pipe", exitcode);
+ dbprintf("%s\n", exitstr);
+ amfree(exitstr);
} else {
- dbprintf(("%s: index created successfully\n", debug_prefix_time(NULL)));
+ dbprintf(_("Index created successfully\n"));
}
pipe_fp = NULL;
backup_program_t *programs[] = {
&dump_program, &gnutar_program, NULL
};
-
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.c"
-#endif