int main( int argc, char ** argv) { int i; /* * 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(-1, 0); set_pname("infofile"); dbopen(DBG_SUBDIR_SERVER); for(i = 1; i < argc; ++i) { if(i+1 >= argc) { g_fprintf(stderr,_("usage: %s host disk [host disk ...]\n"),argv[0]); return 1; } open_infofile("curinfo"); dump_db(argv[i], argv[i+1]); i++; close_infofile(); } return 0; }
void startup_tape_process( char *taper_program) { int fd[2]; char **config_options; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { error(_("taper pipe: %s"), strerror(errno)); /*NOTREACHED*/ } if(fd[0] < 0 || fd[0] >= (int)FD_SETSIZE) { error(_("taper socketpair 0: descriptor %d out of range (0 .. %d)\n"), fd[0], (int)FD_SETSIZE-1); /*NOTREACHED*/ } if(fd[1] < 0 || fd[1] >= (int)FD_SETSIZE) { error(_("taper socketpair 1: descriptor %d out of range (0 .. %d)\n"), fd[1], (int)FD_SETSIZE-1); /*NOTREACHED*/ } switch(taper_pid = fork()) { case -1: error(_("fork taper: %s"), strerror(errno)); /*NOTREACHED*/ case 0: /* child process */ aclose(fd[0]); if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) error(_("taper dup2: %s"), strerror(errno)); config_options = get_config_options(2); config_options[0] = "taper"; config_options[1] = get_config_name(); safe_fd(-1, 0); execve(taper_program, config_options, safe_env()); error("exec %s: %s", taper_program, strerror(errno)); /*NOTREACHED*/ default: /* parent process */ aclose(fd[1]); taper = fd[0]; taper_ev_read = NULL; } }
void startup_chunk_process( chunker_t *chunker, char *chunker_program) { int fd[2]; char **config_options; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { error(_("%s pipe: %s"), chunker->name, strerror(errno)); /*NOTREACHED*/ } switch(chunker->pid = fork()) { case -1: error(_("fork %s: %s"), chunker->name, strerror(errno)); /*NOTREACHED*/ case 0: /* child process */ aclose(fd[0]); if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) { error(_("%s dup2: %s"), chunker->name, strerror(errno)); /*NOTREACHED*/ } config_options = get_config_options(2); config_options[0] = chunker->name ? chunker->name : "chunker", config_options[1] = get_config_name(); safe_fd(-1, 0); execve(chunker_program, config_options, safe_env()); error(_("exec %s (%s): %s"), chunker_program, chunker->name, strerror(errno)); /*NOTREACHED*/ default: /* parent process */ aclose(fd[1]); chunker->down = 0; chunker->fd = fd[0]; chunker->ev_read = NULL; g_fprintf(stderr,_("driver: started %s pid %u\n"), chunker->name, (unsigned)chunker->pid); fflush(stderr); } }
int main( int argc, char ** argv) { char *line = NULL; char *qdisk = NULL; char *qamdevice = NULL; char *optstr = NULL; char *err_extra = NULL; char *s, *fp; int ch; dle_t *dle = NULL; int level; GSList *errlist; level_t *alevel; if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { printf("selfcheck-%s\n", VERSION); return (0); } /* initialize */ /* * 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(-1, 0); openbsd_fd_inform(); safe_cd(); set_pname("selfcheck"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("version %s\n"), VERSION); g_printf("OK version %s\n", VERSION); print_platform(); if(argc > 2 && g_str_equal(argv[1], "amandad")) { amandad_auth = g_strdup(argv[2]); } config_init(CONFIG_INIT_CLIENT, NULL); /* (check for config errors comes later) */ check_running_as(RUNNING_AS_CLIENT_LOGIN); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); /* handle all service requests */ /*@ignore@*/ for(; (line = agets(stdin)) != NULL; free(line)) { /*@end@*/ if (line[0] == '\0') continue; if(strncmp_const(line, "OPTIONS ") == 0) { if (g_options) { g_printf(_("ERROR [Multiple OPTIONS line in selfcheck input]\n")); error(_("Multiple OPTIONS line in selfcheck input\n")); /*NOTREACHED*/ } g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { g_options->hostname = g_malloc(MAX_HOSTNAME_LENGTH+1); gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH); g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } g_printf("OPTIONS "); if(am_has_feature(g_options->features, fe_rep_options_features)) { g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { g_printf("hostname=%s;", g_options->hostname); } g_printf("\n"); fflush(stdout); 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); amfree(errstr); amfree(line); dbclose(); return 1; } if (am_has_feature(g_options->features, fe_req_xml)) { break; } continue; } dle = alloc_dle(); s = line; ch = *s++; skip_whitespace(s, ch); /* find program name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate the program name */ dle->program_is_application_api = 0; if(g_str_equal(dle->program, "APPLICATION")) { 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'; /* terminate the program name */ } if(strncmp_const(dle->program, "CALCSIZE") == 0) { skip_whitespace(s, ch); /* find program name */ if (ch == '\0') { goto err; /* no program */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; dle->estimatelist = g_slist_append(dle->estimatelist, GINT_TO_POINTER(ES_CALCSIZE)); } else { dle->estimatelist = g_slist_append(dle->estimatelist, GINT_TO_POINTER(ES_CLIENT)); } skip_whitespace(s, ch); /* find disk name */ if (ch == '\0') { goto err; /* no disk */ } qdisk = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the disk name */ dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { goto err; /* no device or level */ } if(!isdigit((int)s[-1])) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the device */ qamdevice = g_strdup(fp); dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { dle->device = g_strdup(dle->disk); qamdevice = g_strdup(qdisk); } amfree(qamdevice); /* find level number */ if (ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { goto err; /* bad level */ } alevel = g_new0(level_t, 1); alevel->level = level; dle->levellist = g_slist_append(dle->levellist, alevel); skip_integer(s, ch); skip_whitespace(s, ch); if (ch && strncmp_const_skip(s - 1, "OPTIONS ", s, ch) == 0) { skip_whitespace(s, ch); /* find the option string */ if(ch == '\0') { goto err; /* bad options string */ } optstr = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the options */ parse_options(optstr, dle, g_options->features, 1); /*@ignore@*/ check_options(dle); check_disk(dle); /*@end@*/ } else if (ch == '\0') { /* check all since no option */ need_samba=1; need_rundump=1; need_dump=1; need_restore=1; need_vdump=1; need_vrestore=1; need_xfsdump=1; need_xfsrestore=1; need_vxdump=1; need_vxrestore=1; need_runtar=1; need_gnutar=1; need_compress_path=1; need_calcsize=1; need_global_check=1; /*@ignore@*/ check_disk(dle); /*@end@*/ } else { goto err; /* bad syntax */ } free_dle(dle); dle = NULL; } if (g_options == NULL) { g_printf(_("ERROR [Missing OPTIONS line in selfcheck input]\n")); error(_("Missing OPTIONS line in selfcheck input\n")); /*NOTREACHED*/ } if (am_has_feature(g_options->features, fe_req_xml)) { char *errmsg = NULL; dle_t *dles, *dle, *dle_next; dles = amxml_parse_node_FILE(stdin, &errmsg); if (errmsg) { err_extra = errmsg; goto err; } if (merge_dles_properties(dles, 1) == 0) { goto checkoverall; } for (dle = dles; dle != NULL; dle = dle->next) { run_client_scripts(EXECUTE_ON_PRE_HOST_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle->next) { check_options(dle); run_client_scripts(EXECUTE_ON_PRE_DLE_AMCHECK, g_options, dle, stdout); check_disk(dle); run_client_scripts(EXECUTE_ON_POST_DLE_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle->next) { run_client_scripts(EXECUTE_ON_POST_HOST_AMCHECK, g_options, dle, stdout); } for (dle = dles; dle != NULL; dle = dle_next) { dle_next = dle->next; free_dle(dle); } } checkoverall: check_overall(); amfree(line); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; free_g_options(g_options); dbclose(); return 0; 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")); } amfree(err_extra); amfree(line); if (dle) free_dle(dle); dbclose(); return 1; }
int main( int argc, char ** argv) { #ifdef GNUTAR int i; char *e; char *dbf; char *cmdline; GPtrArray *array = g_ptr_array_new(); gchar **strings; char **new_argv; #endif if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("runtar-%s\n", VERSION); return (0); } /* * 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(-1, 0); safe_cd(); set_pname("runtar"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_CLIENT); config_init(CONFIG_INIT_CLIENT, NULL); if (argc < 3) { error(_("Need at least 3 arguments\n")); /*NOTREACHED*/ } dbprintf(_("version %s\n"), VERSION); if (!g_str_equal(argv[3], "--create")) { error(_("Can only be used to create tar archives\n")); /*NOTREACHED*/ } #ifndef GNUTAR g_fprintf(stderr,_("gnutar not available on this system.\n")); dbprintf(_("%s: gnutar not available on this system.\n"), argv[0]); dbclose(); return 1; #else /* * Print out version information for tar. */ do { FILE * version_file; char version_buf[80]; if ((version_file = popen(GNUTAR " --version 2>&1", "r")) != NULL) { if (fgets(version_buf, (int)sizeof(version_buf), version_file) != NULL) { dbprintf(_(GNUTAR " version: %s\n"), version_buf); } else { if (ferror(version_file)) { dbprintf(_(GNUTAR " version: Read failure: %s\n"), strerror(errno)); } else { dbprintf(_(GNUTAR " version: Read failure; EOF\n")); } } } else { dbprintf(_(GNUTAR " version: unavailable: %s\n"), strerror(errno)); } } while(0); #ifdef WANT_SETUID_CLIENT check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY); if (!become_root()) { error(_("error [%s could not become root (is the setuid bit set?)]\n"), get_pname()); /*NOTREACHED*/ } #else check_running_as(RUNNING_AS_CLIENT_LOGIN); #endif /* skip argv[0] */ argc--; argv++; dbprintf(_("config: %s\n"), argv[0]); if (!g_str_equal(argv[0], "NOCONFIG")) dbrename(argv[0], DBG_SUBDIR_CLIENT); argc--; argv++; new_argv = g_new0(char *, argc+1); new_argv[0] = g_strdup_printf("%s", argv[0]); g_ptr_array_add(array, g_strdup(GNUTAR)); for (i = 1; argv[i]; i++) { g_ptr_array_add(array, quote_string(argv[i])); new_argv[i] = g_strdup_printf("%s", argv[i]); } g_ptr_array_add(array, NULL); strings = (gchar **)g_ptr_array_free(array, FALSE); cmdline = g_strjoinv(" ", strings); g_strfreev(strings); dbprintf(_("running: %s\n"), cmdline); amfree(cmdline); dbf = dbfn(); if (dbf) { dbf = g_strdup(dbf); } dbclose(); execve(GNUTAR, new_argv, safe_env()); e = strerror(errno); dbreopen(dbf, "more"); amfree(dbf); dbprintf(_("execve of %s failed (%s)\n"), GNUTAR, e); dbclose(); g_fprintf(stderr, _("runtar: could not exec %s: %s\n"), GNUTAR, e); return 1; #endif }
int main( int argc, char ** argv) { config_overrides_t *cfg_ovr; char *hostname; char *auth; char *service; int opt; extern int optind; extern char *optarg; FILE *input_file; int use_connect = 0; int got_input_file = 0; /* * 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(-1, 0); safe_cd(); set_pname("amservice"); /* drop root privileges */ if (!set_root_privs(0)) { error(_("amservice must be run setuid root")); } /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); /* process arguments */ cfg_ovr = new_config_overrides(argc/2); input_file = stdin; while((opt = getopt_long(argc, argv, "o:f:s", long_options, NULL)) != EOF) { switch(opt) { case 1: printf("amservice-%s\n", VERSION); return(0); break; case 'o': add_config_override_opt(cfg_ovr, optarg); break; case 'f': if (got_input_file == 1) { g_critical("Invalid two -f argument"); exit(1); } got_input_file = 1; if (*optarg == '/') { input_file = fopen(optarg, "r"); } else { char *name = g_strjoin(NULL, get_original_cwd(), "/", optarg, NULL); input_file = fopen(name, "r"); amfree(name); } if (!input_file) { g_critical("Cannot open output file '%s': %s", optarg, strerror(errno)); exit(1); } break; case 's': use_connect = 1; break; } } if (use_connect && !got_input_file) { g_critical("The -s option require -f"); exit(1); } argc -= optind, argv += optind; if(argc < 3) usage(); /* set a default config */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_CLIENT, NULL); dbrename(get_config_name(), DBG_SUBDIR_SERVER); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT); hostname = argv[0]; auth = argv[1]; service = argv[2]; /* start client side checks */ copy_stream = use_connect && got_input_file; client_protocol(hostname, auth, service, input_file); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; if (got_input_file) fclose(input_file); dbclose(); return(remote_errors != 0); }
int main( int argc, char ** argv) { #ifdef TEST /* standalone test to ckeck wether the calculated file size is ok */ struct stat finfo; int i; off_t dump_total = (off_t)0; off_t gtar_total = (off_t)0; char *d; int l, w; /* * 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(-1, 0); set_pname("calcsize"); dbopen(NULL); config_init(CONFIG_INIT_CLIENT, NULL); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); if (argc < 2) { g_fprintf(stderr,_("Usage: %s file[s]\n"),argv[0]); return 1; } for(i=1; i<argc; i++) { if(lstat(argv[i], &finfo) == -1) { g_fprintf(stderr, "%s: %s\n", argv[i], strerror(errno)); continue; } g_printf("%s: st_size=%lu", argv[i],(unsigned long)finfo.st_size); g_printf(": blocks=%llu\n", ST_BLOCKS(finfo)); dump_total += (ST_BLOCKS(finfo) + (off_t)1) / (off_t)2 + (off_t)1; gtar_total += ROUND(4,(ST_BLOCKS(finfo) + (off_t)1)); } g_printf(" gtar dump\n"); g_printf("total %-9lu %-9lu\n",gtar_total,dump_total); return 0; #else int i; char *dirname=NULL; char *amname=NULL, *qamname=NULL; char *filename=NULL, *qfilename = NULL; if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("calcsize-%s\n", VERSION); return (0); } safe_fd(-1, 0); safe_cd(); set_pname("calcsize"); dbopen(DBG_SUBDIR_CLIENT); config_init(CONFIG_INIT_CLIENT, NULL); dbprintf(_("version %s\n"), VERSION); /* drop root privileges; we'll regain them for the required operations */ #ifdef WANT_SETUID_CLIENT check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY); if (!set_root_privs(0)) { error(_("calcsize must be run setuid root")); } #else check_running_as(RUNNING_AS_CLIENT_LOGIN); #endif argc--, argv++; /* skip program name */ /* need at least program, amname, and directory name */ if(argc < 4) { error(_("Usage: %s config [DUMP|STAR|GNUTAR] name dir [-X exclude-file] [-I include-file] [level date]*"), get_pname()); /*NOTREACHED*/ } dbprintf(_("config: %s\n"), *argv); if (!g_str_equal(*argv, "NOCONFIG")) { dbrename(*argv, DBG_SUBDIR_CLIENT); } argc--; argv++; /* parse backup program name */ if(g_str_equal(*argv, "DUMP")) { #if !defined(DUMP) && !defined(XFSDUMP) error("dump not available on this system"); /*NOTREACHED*/ #else add_file_name = add_file_name_dump; add_file = add_file_dump; final_size = final_size_dump; #endif } else if(g_str_equal(*argv, "GNUTAR")) { #ifndef GNUTAR error("gnutar not available on this system"); /*NOTREACHED*/ #else add_file_name = add_file_name_gnutar; add_file = add_file_gnutar; final_size = final_size_gnutar; use_gtar_excl++; #endif } else { add_file_name = add_file_name_unknown; add_file = add_file_unknown; final_size = final_size_unknown; } argc--, argv++; /* the amanda name can be different from the directory name */ if (argc > 0) { amname = *argv; qamname = quote_string(amname); argc--, argv++; } else { error("missing <name>"); /*NOTREACHED*/ } /* the toplevel directory name to search from */ if (argc > 0) { dirname = *argv; argc--, argv++; } else { error("missing <dir>"); /*NOTREACHED*/ } if ((argc > 1) && g_str_equal(*argv, "-X")) { argv++; if (!(use_gtar_excl || use_star_excl)) { error("exclusion specification not supported"); /*NOTREACHED*/ } filename = g_strdup(*argv); qfilename = quote_string(filename); if (access(filename, R_OK) != 0) { g_fprintf(stderr,"Cannot open exclude file %s\n", qfilename); use_gtar_excl = use_star_excl = 0; } else { exclude_sl = calc_load_file(filename); if (!exclude_sl) { g_fprintf(stderr,"Cannot open exclude file %s: %s\n", qfilename, strerror(errno)); use_gtar_excl = use_star_excl = 0; } } amfree(qfilename); amfree(filename); argc -= 2; argv++; } else { use_gtar_excl = use_star_excl = 0; } if ((argc > 1) && g_str_equal(*argv, "-I")) { argv++; filename = g_strdup(*argv); qfilename = quote_string(filename); if (access(filename, R_OK) != 0) { g_fprintf(stderr,"Cannot open include file %s\n", qfilename); use_gtar_excl = use_star_excl = 0; } else { include_sl = calc_load_file(filename); if (!include_sl) { g_fprintf(stderr,"Cannot open include file %s: %s\n", qfilename, strerror(errno)); use_gtar_excl = use_star_excl = 0; } } amfree(qfilename); amfree(filename); argc -= 2; argv++; } /* the dump levels to calculate sizes for */ ndumps = 0; while(argc >= 2) { if(ndumps < MAXDUMPS) { dumplevel[ndumps] = atoi(argv[0]); dumpdate [ndumps] = (time_t) atol(argv[1]); ndumps++; argc -= 2, argv += 2; } } if(argc) { error("leftover arg \"%s\", expected <level> and <date>", *argv); /*NOTREACHED*/ } if(is_empty_sl(include_sl)) { traverse_dirs(dirname,"."); } else { sle_t *an_include = include_sl->first; while(an_include != NULL) { /* char *adirname = stralloc2(dirname, an_include->name+1); traverse_dirs(adirname); amfree(adirname); */ traverse_dirs(dirname, an_include->name); an_include = an_include->next; } } for(i = 0; i < ndumps; i++) { amflock(1, "size"); dbprintf("calcsize: %s %d SIZE %lld\n", qamname, dumplevel[i], (long long)final_size(i, dirname)); g_fprintf(stderr, "%s %d SIZE %lld\n", qamname, dumplevel[i], (long long)final_size(i, dirname)); fflush(stderr); amfunlock(1, "size"); } amfree(qamname); return 0; #endif }
void startup_tape_process( char *taper_program, int taper_parallel_write, gboolean no_taper) { int fd[2]; int i; char **config_options; taper_t *taper; /* always allocate the tapetable */ tapetable = calloc(sizeof(taper_t), taper_parallel_write+1); if (!tapetable) { error(_("could not g_malloc tapetable")); /*NOTREACHED*/ } for (taper = tapetable, i = 0; i < taper_parallel_write; taper++, i++) { taper->name = g_strdup_printf("worker%d", i); taper->sendresult = 0; taper->input_error = NULL; taper->tape_error = NULL; taper->result = 0; taper->dumper = NULL; taper->disk = NULL; taper->first_label = NULL; taper->first_fileno = 0; taper->state = TAPER_STATE_DEFAULT; taper->left = 0; taper->written = 0; /* jump right to degraded mode if there's no taper */ if (no_taper) { taper->tape_error = g_strdup("no taper started (--no-taper)"); taper->result = BOGUS; } } /* don't start the taper if we're not supposed to */ if (no_taper) return; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { error(_("taper pipe: %s"), strerror(errno)); /*NOTREACHED*/ } if(fd[0] < 0 || fd[0] >= (int)FD_SETSIZE) { error(_("taper socketpair 0: descriptor %d out of range (0 .. %d)\n"), fd[0], (int)FD_SETSIZE-1); /*NOTREACHED*/ } if(fd[1] < 0 || fd[1] >= (int)FD_SETSIZE) { error(_("taper socketpair 1: descriptor %d out of range (0 .. %d)\n"), fd[1], (int)FD_SETSIZE-1); /*NOTREACHED*/ } switch(taper_pid = fork()) { case -1: error(_("fork taper: %s"), strerror(errno)); /*NOTREACHED*/ case 0: /* child process */ aclose(fd[0]); if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) error(_("taper dup2: %s"), strerror(errno)); config_options = get_config_options(2); config_options[0] = "taper"; config_options[1] = get_config_name(); safe_fd(-1, 0); execve(taper_program, config_options, safe_env()); error("exec %s: %s", taper_program, strerror(errno)); /*NOTREACHED*/ default: /* parent process */ aclose(fd[1]); taper_fd = fd[0]; taper_ev_read = NULL; } }
int main( int argc, char ** argv) { char *logfname; char *conf_logdir; FILE *logfile; config_overrides_t *cfg_ovr = NULL; char *cfg_opt = NULL; /* * 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(-1, 0); set_pname("amlogroll"); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); /* Process options */ cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc >= 2) { cfg_opt = argv[1]; } /* read configuration files */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } safe_cd(); /* must happen after config_init */ check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfname = vstralloc(conf_logdir, "/", "log", NULL); amfree(conf_logdir); if((logfile = fopen(logfname, "r")) == NULL) { error(_("could not open log %s: %s"), logfname, strerror(errno)); /*NOTREACHED*/ } amfree(logfname); add_amanda_log_handler(amanda_log_trace_log); while(get_logline(logfile)) { if(curlog == L_START) { handle_start(); if(datestamp != NULL) { break; } } } afclose(logfile); log_rename(datestamp); amfree(datestamp); dbclose(); return 0; }
int main( int argc, char ** argv) { GList *dlist; GList *dlist1; disk_t *diskp; disklist_t diskl; size_t i; char *conf_diskfile; char *conf_tapelist; char *conf_indexdir; find_result_t *output_find; time_t tmp_time; int amtrmidx_debug = 0; config_overrides_t *cfg_ovr = NULL; gboolean compress_index; gboolean sort_index; char *lock_file; file_lock *lock_index; if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("amtrmidx-%s\n", VERSION); return (0); } /* * 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(-1, 0); safe_cd(); set_pname("amtrmidx"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); dbprintf(_("%s: version %s\n"), argv[0], VERSION); cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc > 1 && g_str_equal(argv[1], "-t")) { amtrmidx_debug = 1; argc--; argv++; } if (argc < 2) { g_fprintf(stderr, _("Usage: %s [-t] <config> [-o configoption]*\n"), argv[0]); return 1; } set_config_overrides(cfg_ovr); config_init_with_global(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, argv[1]); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskl); amfree(conf_diskfile); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); compress_index = getconf_boolean(CNF_COMPRESS_INDEX); sort_index = getconf_boolean(CNF_SORT_INDEX); output_find = find_dump(&diskl); conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); /* take a lock file to prevent concurent trim */ lock_file = g_strdup_printf("%s/%s", conf_indexdir, "lock"); lock_index = file_lock_new(lock_file); if (file_lock_lock_wr(lock_index) != 0) goto lock_failed; /* now go through the list of disks and find which have indexes */ time(&tmp_time); tmp_time -= 7*24*60*60; /* back one week */ for (dlist = diskl.head; dlist != NULL; dlist = dlist->next) { diskp = dlist->data; if (diskp->index) { char *indexdir, *qindexdir; DIR *d; struct dirent *f; char **names; size_t name_length; size_t name_count; char *host; char *disk, *qdisk; size_t len_date; disk_t *dp; GSList *matching_dp = NULL; /* get listing of indices, newest first */ host = sanitise_filename(diskp->host->hostname); disk = sanitise_filename(diskp->name); qdisk = quote_string(diskp->name); indexdir = g_strjoin(NULL, conf_indexdir, "/", host, "/", disk, "/", NULL); qindexdir = quote_string(indexdir); /* find all dles that use the same indexdir */ for (dlist1 = diskl.head; dlist1 != NULL; dlist1 = dlist1->next) { char *dp_host, *dp_disk; dp = dlist1->data; dp_host = sanitise_filename(dp->host->hostname); dp_disk = sanitise_filename(dp->name); if (g_str_equal(host, dp_host) && g_str_equal(disk, dp_disk)) { matching_dp = g_slist_append(matching_dp, dp); } amfree(dp_host); amfree(dp_disk); } dbprintf("%s %s -> %s\n", diskp->host->hostname, qdisk, qindexdir); amfree(qdisk); if ((d = opendir(indexdir)) == NULL) { dbprintf(_("could not open index directory %s\n"), qindexdir); amfree(host); amfree(disk); amfree(indexdir); amfree(qindexdir); g_slist_free(matching_dp); continue; } name_length = 100; names = (char **)g_malloc(name_length * sizeof(char *)); name_count = 0; while ((f = readdir(d)) != NULL) { size_t l; if(is_dot_or_dotdot(f->d_name)) { continue; } for(i = 0; i < sizeof("YYYYMMDDHHMMSS")-1; i++) { if(! isdigit((int)(f->d_name[i]))) { break; } } len_date = i; /* len_date=8 for YYYYMMDD */ /* len_date=14 for YYYYMMDDHHMMSS */ if((len_date != 8 && len_date != 14) || f->d_name[len_date] != '_' || ! isdigit((int)(f->d_name[len_date+1]))) { continue; /* not an index file */ } /* * Clear out old index temp files. */ l = strlen(f->d_name) - (sizeof(".tmp")-1); if ((l > (len_date + 1)) && (g_str_equal(f->d_name + l, ".tmp"))) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, f->d_name, NULL); qpath = quote_string(path); if(lstat(path, &sbuf) != -1 && ((sbuf.st_mode & S_IFMT) == S_IFREG) && ((time_t)sbuf.st_mtime < tmp_time)) { dbprintf("rm %s\n", qpath); if(amtrmidx_debug == 0 && unlink(path) == -1) { dbprintf(_("Error removing %s: %s\n"), qpath, strerror(errno)); } } amfree(qpath); amfree(path); continue; } if(name_count >= name_length) { char **new_names; new_names = g_malloc((name_length * 2) * sizeof(char *)); memcpy(new_names, names, name_length * sizeof(char *)); amfree(names); names = new_names; name_length *= 2; } names[name_count++] = g_strdup(f->d_name); } closedir(d); qsort(names, name_count, sizeof(char *), sort_by_name_reversed); /* * Search for the first full dump past the minimum number * of index files to keep. */ for(i = 0; i < name_count; i++) { char *datestamp; int level; size_t len_date; int matching = 0; GSList *mdp; for(len_date = 0; len_date < sizeof("YYYYMMDDHHMMSS")-1; len_date++) { if(! isdigit((int)(names[i][len_date]))) { break; } } datestamp = g_strdup(names[i]); datestamp[len_date] = '\0'; if (sscanf(&names[i][len_date+1], "%d", &level) != 1) level = 0; for (mdp = matching_dp; mdp != NULL; mdp = mdp->next) { dp = mdp->data; if (dump_exist(output_find, dp->host->hostname, dp->name, datestamp, level)) { matching = 1; } } if (!matching) { struct stat sbuf; char *path, *qpath; path = g_strconcat(indexdir, names[i], NULL); qpath = quote_string(path); if(lstat(path, &sbuf) != -1 && ((sbuf.st_mode & S_IFMT) == S_IFREG) && ((time_t)sbuf.st_mtime < tmp_time)) { dbprintf("rm %s\n", qpath); if(amtrmidx_debug == 0 && unlink(path) == -1) { dbprintf(_("Error removing %s: %s\n"), qpath, strerror(errno)); } } amfree(qpath); amfree(path); } /* Did it require un/compression and/or sorting */ { char *orig_name = getindexfname(host, disk, datestamp, level); char *sorted_name = getindex_sorted_fname(host, disk, datestamp, level); char *sorted_gz_name = getindex_sorted_gz_fname(host, disk, datestamp, level); char *unsorted_name = getindex_unsorted_fname(host, disk, datestamp, level); char *unsorted_gz_name = getindex_unsorted_gz_fname(host, disk, datestamp, level); gboolean orig_exist = FALSE; gboolean sorted_exist = FALSE; gboolean sorted_gz_exist = FALSE; gboolean unsorted_exist = FALSE; gboolean unsorted_gz_exist = FALSE; int fd; int uncompress_err_fd = -1; int sort_err_fd = -1; int compress_err_fd = -1; pid_t uncompress_pid = -1; pid_t sort_pid = -1; pid_t compress_pid = -1; orig_exist = file_exists(orig_name); sorted_exist = file_exists(sorted_name); sorted_gz_exist = file_exists(sorted_gz_name); unsorted_exist = file_exists(unsorted_name); unsorted_gz_exist = file_exists(unsorted_gz_name); if (sort_index && compress_index) { if (!sorted_gz_exist) { if (sorted_exist) { // COMPRESS compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // SORT AND COMPRESS sort_pid = run_sort(-1, &fd, &sort_err_fd, unsorted_name, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS SORT AND COMPRESS uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, &fd, &sort_err_fd, NULL, NULL); compress_pid = run_compress(fd, NULL, &compress_err_fd, NULL, sorted_gz_name); unlink(orig_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (sort_index && !compress_index) { if (!sorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_exist) { // SORT sort_pid = run_sort(-1, NULL, &sort_err_fd, unsorted_name, sorted_name); unlink(unsorted_name); } else if (unsorted_gz_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, unsorted_gz_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS AND SORT uncompress_pid = run_uncompress(-1, &fd, &uncompress_err_fd, orig_name, NULL); sort_pid = run_sort(fd, NULL, &sort_err_fd, NULL, sorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_exist) { unlink(unsorted_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && compress_index) { if (!sorted_gz_exist && !unsorted_gz_exist) { if (sorted_exist) { // COMPRESS sorted compress_pid = run_compress(-1, NULL, &compress_err_fd, sorted_name, sorted_gz_name); unlink(sorted_name); } else if (unsorted_exist) { // COMPRESS unsorted compress_pid = run_compress(-1, NULL, &compress_err_fd, unsorted_name, unsorted_gz_name); unlink(unsorted_name); } else if (orig_exist) { // RENAME orig rename(orig_name, unsorted_gz_name); } } else { if (sorted_exist) { unlink(sorted_name); } if (unsorted_exist) { unlink(unsorted_name); } if (sorted_gz_exist && unsorted_gz_exist) { unlink(unsorted_gz_name); } } } else if (!sort_index && !compress_index) { if (!sorted_exist && !unsorted_exist) { if (sorted_gz_exist) { // UNCOMPRESS sorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, sorted_gz_name, sorted_name); unlink(sorted_gz_name); } else if (unsorted_gz_exist) { // UNCOMPRESS unsorted uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, unsorted_gz_name, unsorted_name); unlink(unsorted_gz_name); } else if (orig_exist) { // UNCOMPRESS orig uncompress_pid = run_uncompress(-1, NULL, &uncompress_err_fd, orig_name, unsorted_name); unlink(orig_name); } } else { if (sorted_gz_exist) { unlink(sorted_gz_name); } if (unsorted_gz_exist) { unlink(unsorted_gz_name); } if (sorted_exist && unsorted_exist) { unlink(unsorted_name); } } } if (uncompress_pid != -1) wait_process(uncompress_pid, uncompress_err_fd, "uncompress"); if (sort_pid != -1) wait_process(sort_pid, sort_err_fd, "sort"); if (compress_pid != -1) wait_process(compress_pid, compress_err_fd, "compress"); g_free(orig_name); g_free(sorted_name); g_free(sorted_gz_name); g_free(unsorted_name); g_free(unsorted_gz_name); } amfree(datestamp); amfree(names[i]); } g_slist_free(matching_dp); amfree(names); amfree(host); amfree(disk); amfree(indexdir); amfree(qindexdir); } } file_lock_unlock(lock_index); lock_failed: file_lock_free(lock_index); amfree(conf_indexdir); amfree(lock_file); free_find_result(&output_find); clear_tapelist(); free_disklist(&diskl); unload_disklist(); dbclose(); return 0; }
int main( int argc, char ** argv) { int interactive = 0; 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; GSList *errlist; FILE *mesgstream; level_t *alevel; /* initialize */ /* * 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); safe_cd(); set_pname("sendbackup"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* Don't die when interrupt received */ signal(SIGINT, SIG_IGN); if(argc > 1 && strcmp(argv[1],"-t") == 0) { interactive = 1; argc--; argv++; } else { interactive = 0; } erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); dbopen(DBG_SUBDIR_CLIENT); startclock(); 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 * /dev/null and none of the network connections back to driver * programs on the tape host are set up. The index service is * run and goes to stdout. */ g_fprintf(stderr, _("%s: running in interactive test mode\n"), get_pname()); fflush(stderr); } qdisk = NULL; dumpdate = NULL; stroptions = NULL; for(; (line = agets(stdin)) != NULL; free(line)) { if (line[0] == '\0') continue; if(interactive) { g_fprintf(stderr, "%s> ", get_pname()); fflush(stderr); } 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 (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"); goto err; /* no program name */ } dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; 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"); goto err; /* no disk name */ } amfree(qdisk); qdisk = s - 1; ch = *qdisk; skip_quoted_string(s, ch); s[-1] = '\0'; qdisk = stralloc(qdisk); dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { err_extra = _("bad level"); goto err; } if(!isdigit((int)s[-1])) { amfree(qamdevice); qamdevice = s - 1; ch = *qamdevice; skip_quoted_string(s, ch); s[-1] = '\0'; qamdevice = stralloc(qamdevice); dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { 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"); 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"); goto err; /* no dumpdate */ } amfree(dumpdate); dumpdate = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; dumpdate = stralloc(dumpdate); skip_whitespace(s, ch); /* find the options keyword */ if(ch == '\0') { err_extra = _("no options"); goto err; /* no options */ } if(strncmp_const_skip(s - 1, "OPTIONS ", s, ch) != 0) { err_extra = _("no OPTIONS keyword"); goto err; /* no options */ } skip_whitespace(s, ch); /* find the options string */ if(ch == '\0') { 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*/ } if (am_has_feature(g_options->features, fe_req_xml)) { char *errmsg = NULL; 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); } 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; } if (g_slist_length(dle->levellist) != 1) { err_extra = _("Too many level"); goto err; } 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); 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]; } if(!interactive) { datafd = DATA_FD_OFFSET + 0; mesgfd = DATA_FD_OFFSET + 2; indexfd = DATA_FD_OFFSET + 4; } 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); } } 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)) { g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { g_printf("hostname=%s;", g_options->hostname); } g_printf("\n"); fflush(stdout); if (freopen("/dev/null", "w", stdout) == NULL) { dbprintf(_("Error redirecting stdout to /dev/null: %s\n"), strerror(errno)); exit(1); } if(interactive) { 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(datafd == -1 || mesgfd == -1 || (dle->create_index && indexfd == -1)) { dbclose(); exit(1); } } 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; } /* 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); dbprintf(_("gnutar: pid %ld: %s"), (long)comppid, COMPRESS_PATH); if(compopt != skip_argument) { dbprintf(_("pid %ld: %s %s\n"), (long)comppid, COMPRESS_PATH, compopt); } else { dbprintf(_("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 (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); 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); 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*/ } 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); } 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); } 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")); } run_client_scripts(EXECUTE_ON_POST_DLE_BACKUP, g_options, dle, mesgstream); fflush(mesgstream); amfree(qdisk); amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; free_g_options(g_options); dbclose(); return 0; 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")); } amfree(qdisk); amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); dbclose(); return 1; }
pid_t pipespawnv_passwd( char * prog, int pipedef, int need_root, int * stdinfd, int * stdoutfd, int * stderrfd, char ** my_argv) { pid_t pid; int i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2]; char number[NUM_STR_SIZE]; char **arg; char *e; char **env; char *cmdline; char **newenv; char *passwdvar = NULL; int *passwdfd = NULL; GPtrArray *array = g_ptr_array_new(); gchar **strings; /* * Log the command line and count the args. */ if ((pipedef & PASSWD_PIPE) != 0) { passwdvar = *my_argv++; passwdfd = (int *)*my_argv++; } memset(inpipe, -1, sizeof(inpipe)); memset(outpipe, -1, sizeof(outpipe)); memset(errpipe, -1, sizeof(errpipe)); memset(passwdpipe, -1, sizeof(passwdpipe)); g_ptr_array_add(array, g_strdup(prog)); for(arg = my_argv; *arg != NULL; arg++) { if (*arg == skip_argument) continue; g_ptr_array_add(array, quote_string(*arg)); } g_ptr_array_add(array, NULL); strings = (gchar **)g_ptr_array_free(array, FALSE); cmdline = g_strjoinv(" ", strings); g_strfreev(strings); dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline); /* * Create the pipes */ if ((pipedef & STDIN_PIPE) != 0) { if(pipe(inpipe) == -1) { error(_("error [open pipe to %s: %s]"), prog, strerror(errno)); /*NOTREACHED*/ } } if ((pipedef & STDOUT_PIPE) != 0) { if(pipe(outpipe) == -1) { error(_("error [open pipe to %s: %s]"), prog, strerror(errno)); /*NOTREACHED*/ } } if ((pipedef & STDERR_PIPE) != 0) { if(pipe(errpipe) == -1) { error(_("error [open pipe to %s: %s]"), prog, strerror(errno)); /*NOTREACHED*/ } } if ((pipedef & PASSWD_PIPE) != 0) { if(pipe(passwdpipe) == -1) { error(_("error [open pipe to %s: %s]"), prog, strerror(errno)); /*NOTREACHED*/ } } /* * Fork and set up the return or run the program. */ switch(pid = fork()) { case -1: e = strerror(errno); error(_("error [fork %s: %s]"), prog, e); /*NOTREACHED*/ default: /* parent process */ if ((pipedef & STDIN_PIPE) != 0) { aclose(inpipe[0]); /* close input side of pipe */ *stdinfd = inpipe[1]; } if ((pipedef & STDOUT_PIPE) != 0) { aclose(outpipe[1]); /* close output side of pipe */ *stdoutfd = outpipe[0]; } if ((pipedef & STDERR_PIPE) != 0) { aclose(errpipe[1]); /* close output side of pipe */ *stderrfd = errpipe[0]; } if ((pipedef & PASSWD_PIPE) != 0) { aclose(passwdpipe[0]); /* close input side of pipe */ *passwdfd = passwdpipe[1]; } break; case 0: /* child process */ debug_dup_stderr_to_debug(); if ((pipedef & STDIN_PIPE) != 0) { aclose(inpipe[1]); /* close output side of pipe */ } else { inpipe[0] = *stdinfd; } if ((pipedef & STDOUT_PIPE) != 0) { aclose(outpipe[0]); /* close input side of pipe */ } else { outpipe[1] = *stdoutfd; } if ((pipedef & STDERR_PIPE) != 0) { aclose(errpipe[0]); /* close input side of pipe */ } else { errpipe[1] = *stderrfd; } if ((pipedef & PASSWD_PIPE) != 0) { aclose(passwdpipe[1]); /* close output side of pipe */ } /* * Shift the pipes to the standard file descriptors as requested. */ if(dup2(inpipe[0], 0) == -1) { g_fprintf(stderr, "error [spawn %s: dup2 in: %s]", prog, strerror(errno)); exit(1); /*NOTREACHED*/ } if(dup2(outpipe[1], 1) == -1) { g_fprintf(stderr, "error [spawn %s: dup2 out: %s]", prog, strerror(errno)); exit(1); /*NOTREACHED*/ } if(dup2(errpipe[1], 2) == -1) { g_fprintf(stderr, "error [spawn %s: dup2 err: %s]", prog, strerror(errno)); exit(1); /*NOTREACHED*/ } /* * Get the "safe" environment. If we are sending a password to * the child via a pipe, add the environment variable for that. */ env = safe_env(); if ((pipedef & PASSWD_PIPE) != 0) { for (i = 0; env[i] != NULL; i++) (void)i; /* make lint happy and do nothing */ newenv = (char **)g_malloc((i + 1 + 1) * sizeof(*newenv)); g_snprintf(number, sizeof(number), "%d", passwdpipe[0]); newenv[0] = g_strjoin(NULL, passwdvar, "=", number, NULL); for(i = 0; env[i] != NULL; i++) newenv[i + 1] = env[i]; newenv[i + 1] = NULL; amfree(env); env = newenv; safe_fd(passwdpipe[0], 1); } else { safe_fd(-1, 0); } if (need_root) { become_root(); } else { /* if our real userid is zero, the child shouldn't inherit * that, so drop privs permanently */ if (getuid() == 0 && !set_root_privs(-1)) { error(_("could not drop root privileges")); } } execve(prog, my_argv, env); e = strerror(errno); error(_("error [exec %s: %s]"), prog, e); /*NOTREACHED*/ } amfree(cmdline); return pid; }
int main( int argc, char ** argv) { static struct databuf db; struct cmdargs *cmdargs; int infd; char *q = NULL; char *filename = NULL; off_t chunksize, use; times_t runtime; am_feature_t *their_features = NULL; int a; config_overrides_t *cfg_ovr = NULL; char *cfg_opt = NULL; char *m; /* * 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(-1, 0); set_pname("chunker"); dbopen(DBG_SUBDIR_SERVER); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_trace_log); cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc > 1) cfg_opt = argv[1]; config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); apply_config_overrides(cfg_ovr); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } safe_cd(); /* do this *after* config_init() */ check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], VERSION); fflush(stderr); /* now, make sure we are a valid user */ signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); cmdargs = getcmd(); if(cmdargs->cmd == START) { if(cmdargs->argc <= 1) error(_("error [dumper START: not enough args: timestamp]")); chunker_timestamp = newstralloc(chunker_timestamp, cmdargs->argv[1]); } else { log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); error(_("Didn't get START command")); } /* do {*/ cmdargs = getcmd(); switch(cmdargs->cmd) { case QUIT: break; case PORT_WRITE: /* * PORT-WRITE * handle * filename * host * features * disk * level * dumpdate * chunksize * progname * use * options */ a = 1; if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: handle]")); /*NOTREACHED*/ } handle = newstralloc(handle, cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: filename]")); /*NOTREACHED*/ } filename = newstralloc(filename, cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: hostname]")); /*NOTREACHED*/ } hostname = newstralloc(hostname, cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: features]")); /*NOTREACHED*/ } am_release_feature_set(their_features); their_features = am_string_to_feature(cmdargs->argv[a++]); if (!their_features) { error(_("error [chunker PORT-WRITE: invalid feature string]")); /*NOTREACHED*/ } if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: diskname]")); /*NOTREACHED*/ } diskname = newstralloc(diskname, cmdargs->argv[a++]); if (qdiskname) amfree(qdiskname); qdiskname = quote_string(diskname); /* qdiskname is a global */ if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: level]")); /*NOTREACHED*/ } level = atoi(cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: dumpdate]")); /*NOTREACHED*/ } dumpdate = newstralloc(dumpdate, cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: chunksize]")); /*NOTREACHED*/ } chunksize = OFF_T_ATOI(cmdargs->argv[a++]); chunksize = am_floor(chunksize, (off_t)DISK_BLOCK_KB); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: progname]")); /*NOTREACHED*/ } progname = newstralloc(progname, cmdargs->argv[a++]); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: use]")); /*NOTREACHED*/ } use = am_floor(OFF_T_ATOI(cmdargs->argv[a++]), DISK_BLOCK_KB); if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: options]")); /*NOTREACHED*/ } options = newstralloc(options, cmdargs->argv[a++]); if(a != cmdargs->argc) { error(_("error [chunker PORT-WRITE: too many args: %d != %d]"), cmdargs->argc, a); /*NOTREACHED*/ } if((infd = startup_chunker(filename, use, chunksize, &db)) < 0) { q = quote_string(vstrallocf(_("[chunker startup failed: %s]"), errstr)); putresult(TRYAGAIN, "%s %s\n", handle, q); error("startup_chunker failed: %s", errstr); } command_in_transit = NULL; if(infd >= 0 && do_chunk(infd, &db)) { char kb_str[NUM_STR_SIZE]; char kps_str[NUM_STR_SIZE]; double rt; runtime = stopclock(); rt = g_timeval_to_double(runtime); g_snprintf(kb_str, SIZEOF(kb_str), "%lld", (long long)(dumpsize - (off_t)headersize)); g_snprintf(kps_str, SIZEOF(kps_str), "%3.1lf", isnormal(rt) ? (double)dumpsize / rt : 0.0); errstr = newvstrallocf(errstr, "sec %s kb %s kps %s", walltime_str(runtime), kb_str, kps_str); m = vstrallocf("[%s]", errstr); q = quote_string(m); amfree(m); if(command_in_transit != NULL) { cmdargs = command_in_transit; command_in_transit = NULL; } else { cmdargs = getcmd(); } switch(cmdargs->cmd) { case DONE: putresult(DONE, "%s %lld %s\n", handle, (long long)(dumpsize - (off_t)headersize), q); log_add(L_SUCCESS, "%s %s %s %d [%s]", hostname, qdiskname, chunker_timestamp, level, errstr); break; case BOGUS: case TRYAGAIN: case FAILED: case ABORT_FINISHED: if(dumpsize > (off_t)DISK_BLOCK_KB) { putresult(PARTIAL, "%s %lld %s\n", handle, (long long)(dumpsize - (off_t)headersize), q); log_add(L_PARTIAL, "%s %s %s %d [%s]", hostname, qdiskname, chunker_timestamp, level, errstr); } else { errstr = newvstrallocf(errstr, _("dumper returned %s"), cmdstr[cmdargs->cmd]); amfree(q); m = vstrallocf("[%s]",errstr); q = quote_string(m); amfree(m); putresult(FAILED, "%s %s\n", handle, q); log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, chunker_timestamp, level, errstr); } default: break; } amfree(q); } else if(infd != -2) { if(q == NULL) { m = vstrallocf("[%s]", errstr); q = quote_string(m); amfree(m); } if(!abort_pending) { putresult(FAILED, "%s %s\n", handle, q); } log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, chunker_timestamp, level, errstr); amfree(q); } amfree(filename); amfree(db.filename); break; default: if(cmdargs->argc >= 1) { q = quote_string(cmdargs->argv[0]); } else { q = stralloc(_("(no input?)")); } putresult(BAD_COMMAND, "%s\n", q); amfree(q); break; } /* } while(cmdargs->cmd != QUIT); */ log_add(L_INFO, "pid-done %ld", (long)getpid()); amfree(errstr); amfree(chunker_timestamp); amfree(handle); amfree(hostname); amfree(diskname); amfree(qdiskname); amfree(dumpdate); amfree(progname); amfree(options); free_cmdargs(cmdargs); if (command_in_transit) free_cmdargs(command_in_transit); am_release_feature_set(their_features); their_features = NULL; dbclose(); return (0); /* exit */ }
static int start_chg_glue(void) { int stdin_pipe[2] = { -1, -1 }; int stdout_pipe[2] = { -1, -1 }; char *chg_glue = NULL; char **config_options = NULL; char *cmdline = NULL; /* is it already running? */ if (tpchanger_pid != -1) return 1; if (pipe(stdin_pipe) == -1 || pipe(stdout_pipe) == -1) { changer_resultstr = vstrallocf( _("<error> could not make pipe: %s"), strerror(errno)); goto error; } config_options = get_config_options(2); config_options[0] = g_strdup("chg-glue"); config_options[1] = g_strdup(get_config_name()); chg_glue = g_strdup_printf("%s/chg-glue", amlibexecdir); cmdline = g_strjoinv(" ", config_options); g_debug("invoking %s: %s", chg_glue, cmdline); amfree(cmdline); switch(tpchanger_pid = fork()) { case -1: changer_resultstr = vstrallocf( _("<error> could not fork: %s"), strerror(errno)); goto error; case 0: debug_dup_stderr_to_debug(); if(dup2(stdin_pipe[0], 0) == -1) { changer_resultstr = vstrallocf( _("<error> could not dup2: %s\n"), strerror(errno)); goto child_err; } if(dup2(stdout_pipe[1], 1) == -1) { changer_resultstr = vstrallocf( _("<error> could not dup2: %s\n"), strerror(errno)); goto child_err; } safe_fd(-1, 0); execv(chg_glue, config_options); changer_resultstr = vstrallocf( _("<error> could not exec \"%s\": %s\n"), chg_glue, strerror(errno)); child_err: (void)full_write(stdout_pipe[1], changer_resultstr, strlen(changer_resultstr)); exit(1); default: aclose(stdin_pipe[0]); aclose(stdout_pipe[1]); g_strfreev(config_options); amfree(chg_glue); amfree(cmdline); tpchanger_stdout = stdout_pipe[0]; tpchanger_stdin = stdin_pipe[1]; return 1; } error: amfree(chg_glue); amfree(cmdline); aclose(stdin_pipe[0]); aclose(stdin_pipe[1]); aclose(stdout_pipe[0]); aclose(stdout_pipe[1]); return 0; }
// disable shm in pulseaudio void pulseaudio_init(void) { struct stat s; // do we have pulseaudio in the system? if (stat("/etc/pulse/client.conf", &s) == -1) { if (arg_debug) printf("/etc/pulse/client.conf not found\n"); return; } // create the new user pulseaudio directory if (mkdir(RUN_PULSE_DIR, 0700) == -1) errExit("mkdir"); // mount it nosuid, noexec, nodev fs_noexec(RUN_PULSE_DIR); // create the new client.conf file char *pulsecfg = NULL; if (asprintf(&pulsecfg, "%s/client.conf", RUN_PULSE_DIR) == -1) errExit("asprintf"); if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644)) // root needed errExit("copy_file"); FILE *fp = fopen(pulsecfg, "a"); if (!fp) errExit("fopen"); fprintf(fp, "%s", "\nenable-shm = no\n"); SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); fclose(fp); // hand over the directory to the user if (set_perms(RUN_PULSE_DIR, getuid(), getgid(), 0700)) errExit("set_perms"); // create ~/.config/pulse directory if not present char *homeusercfg; if (asprintf(&homeusercfg, "%s/.config", cfg.homedir) == -1) errExit("asprintf"); if (lstat(homeusercfg, &s) == -1) { if (create_empty_dir_as_user(homeusercfg, 0700)) fs_logger2("create", homeusercfg); } else if (!S_ISDIR(s.st_mode)) { if (S_ISLNK(s.st_mode)) fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg); else fprintf(stderr, "Error: %s is not a directory\n", homeusercfg); exit(1); } free(homeusercfg); if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) errExit("asprintf"); if (lstat(homeusercfg, &s) == -1) { if (create_empty_dir_as_user(homeusercfg, 0700)) fs_logger2("create", homeusercfg); } else if (!S_ISDIR(s.st_mode)) { if (S_ISLNK(s.st_mode)) fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg); else fprintf(stderr, "Error: %s is not a directory\n", homeusercfg); exit(1); } // if we have ~/.config/pulse mount the new directory, else set environment variable. if (stat(homeusercfg, &s) == 0) { // get a file descriptor for ~/.config/pulse, fails if there is any symlink int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); if (fd == -1) errExit("safe_fd"); // confirm the actual mount destination is owned by the user if (fstat(fd, &s) == -1) errExit("fstat"); if (s.st_uid != getuid()) { fprintf(stderr, "Error: %s is not owned by the current user\n", homeusercfg); exit(1); } // preserve a read-only mount struct statvfs vfs; if (fstatvfs(fd, &vfs) == -1) errExit("fstatvfs"); if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY) fs_rdonly(RUN_PULSE_DIR); // mount via the link in /proc/self/fd char *proc; if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) errExit("asprintf"); if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0) errExit("mount pulseaudio"); fs_logger2("tmpfs", homeusercfg); free(proc); close(fd); // check /proc/self/mountinfo to confirm the mount is ok MountData *mptr = get_last_mount(); if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0) errLogExit("invalid pulseaudio mount"); char *p; if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) errExit("asprintf"); fs_logger2("create", p); free(p); } else { // set environment if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) errExit("setenv"); } free(pulsecfg); free(homeusercfg); }
int main(int argc, char ** argv) { char * tapelist_name; taper_state_t state; config_overwrites_t *cfg_ovr = NULL; char *cfg_opt = NULL; /* * 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(-1, 0); set_pname("taper"); dbopen("server"); device_api_init(); init_taper_state(&state); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], version()); dbprintf(_("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), argv[0], version()); /* Process options */ cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if(argc > 2) { error("Too many arguments!\n"); g_assert_not_reached(); } if (argc > 1) cfg_opt = argv[1]; config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); apply_config_overwrites(cfg_ovr); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } safe_cd(); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_trace_log); check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST)); if (read_tapelist(tapelist_name) != 0) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("could not load tapelist \"%s\"", tapelist_name); g_assert_not_reached(); } amfree(tapelist_name); state.have_changer = changer_init(); if (state.have_changer < 0) { log_add(L_INFO, "pid-done %ld", (long)getpid()); error("changer initialization failed: %s", strerror(errno)); g_assert_not_reached(); } state.next_tape_label = NULL; state.next_tape_device = NULL; state.cur_tape = 0; if (!find_first_tape(&state)) { log_add(L_INFO, "pid-done %ld", (long)getpid()); return EXIT_SUCCESS; } while (process_driver_command(&state)); log_add(L_INFO, "pid-done %ld", (long)getpid()); return EXIT_SUCCESS; }
static gboolean start_impl( XferElement *elt) { char *tmpbuf; XferFilterProcess *self = (XferFilterProcess *)elt; char *cmd_str; char **argv; char *errmsg; char **env; int rfd, wfd; /* first build up a log message of what we're going to do, properly shell quoted */ argv = self->argv; cmd_str = g_shell_quote(*(argv++)); while (*argv) { char *qarg = g_shell_quote(*(argv++)); tmpbuf = g_strconcat(cmd_str, " ", qarg, NULL); g_free(cmd_str); cmd_str = tmpbuf; g_free(qarg); } g_debug("%s spawning: %s", xfer_element_repr(elt), cmd_str); rfd = xfer_element_swap_output_fd(elt->upstream, -1); wfd = xfer_element_swap_input_fd(elt->downstream, -1); /* now fork off the child and connect the pipes */ switch (self->child_pid = fork()) { case -1: error("cannot fork: %s", strerror(errno)); /* NOTREACHED */ case 0: /* child */ /* first, copy our fd's out of the stdio range */ while (rfd >= 0 && rfd <= STDERR_FILENO) rfd = dup(rfd); while (wfd >= 0 && wfd <= STDERR_FILENO) wfd = dup(wfd); /* set up stdin, stdout, and stderr, overwriting anything already open * on those fd's */ if (rfd > 0) dup2(rfd, STDIN_FILENO); if (wfd > 0) dup2(wfd, STDOUT_FILENO); dup2(self->pipe_err[1], STDERR_FILENO); /* and close everything else */ safe_fd(-1, 0); env = safe_env(); if (self->need_root && !become_root()) { errmsg = g_strdup_printf("could not become root: %s\n", strerror(errno)); full_write(STDERR_FILENO, errmsg, strlen(errmsg)); exit(1); } execve(self->argv[0], self->argv, env); free_env(env); errmsg = g_strdup_printf("exec of '%s' failed: %s\n", self->argv[0], strerror(errno)); full_write(STDERR_FILENO, errmsg, strlen(errmsg)); exit(1); default: /* parent */ break; } g_free(cmd_str); /* close the pipe fd's */ close(rfd); close(wfd); close(self->pipe_err[1]); /* watch for child death */ self->child_watch = new_child_watch_source(self->child_pid); g_source_set_callback(self->child_watch, (GSourceFunc)child_watch_callback, self, NULL); g_source_attach(self->child_watch, NULL); g_source_unref(self->child_watch); return TRUE; }
int main( int argc, char ** argv) { int c; char *command; application_argument_t argument; #ifdef STAR star_path = STAR; #else star_path = NULL; #endif star_tardumps = "/etc/tardumps"; star_dle_tardumps = 0; star_onefilesystem = 1; star_sparse = 1; star_directory = NULL; /* initialize */ /* * 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"); if (argc < 2) { printf("ERROR no command given to amstar\n"); error(_("No command given to amstar")); } /* drop root privileges */ if (!set_root_privs(0)) { if (strcmp(argv[1], "selfcheck") == 0) { printf("ERROR amstar must be run setuid root\n"); } error(_("amstar must be run setuid root")); } safe_fd(3, 2); set_pname("amstar"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); #if defined(USE_DBMALLOC) malloc_size_1 = malloc_inuse(&malloc_hist_1); #endif add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("version %s\n"), VERSION); config_init(CONFIG_INIT_CLIENT, NULL); //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED); //root for amrecover //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup /* parse argument */ command = argv[1]; argument.config = NULL; argument.host = NULL; argument.message = 0; argument.collection = 0; argument.calcsize = 0; argument.level = NULL; argument.command_options = NULL; init_dle(&argument.dle); opterr = 0; while (1) { int option_index = 0; c = getopt_long (argc, argv, "", long_options, &option_index); if (c == -1) break; switch (c) { case 1: argument.config = stralloc(optarg); break; case 2: argument.host = stralloc(optarg); break; case 3: argument.dle.disk = stralloc(optarg); break; case 4: argument.dle.device = stralloc(optarg); break; case 5: argument.level = g_slist_append(argument.level, GINT_TO_POINTER(atoi(optarg))); break; case 6: argument.dle.create_index = 1; break; case 7: argument.message = 1; break; case 8: argument.collection = 1; break; case 9: argument.dle.record = 1; break; case 10: star_path = stralloc(optarg); break; case 11: star_tardumps = stralloc(optarg); break; case 12: if (optarg && strcasecmp(optarg, "NO") == 0) star_dle_tardumps = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) star_dle_tardumps = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad STAR-DLE-TARDUMP property value (%s)]\n"), get_pname(), optarg); break; case 13: if (optarg && strcasecmp(optarg, "YES") != 0) { /* This option is required to be YES */ /* star_onefilesystem = 0; */ } break; case 14: if (optarg && strcasecmp(optarg, "NO") == 0) star_sparse = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) star_sparse = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg); break; case 15: argument.calcsize = 1; break; case 16: if (optarg) normal_message = g_slist_append(normal_message, optarg); break; case 17: if (optarg) ignore_message = g_slist_append(ignore_message, optarg); break; case 18: if (optarg) strange_message = g_slist_append(strange_message, optarg); break; case 19: if (optarg) argument.dle.include_list = append_sl(argument.dle.include_list, optarg); break; case 20: if (optarg) argument.dle.exclude_list = append_sl(argument.dle.exclude_list, optarg); break; case 21: if (optarg) star_directory = stralloc(optarg); break; case 22: argument.command_options = g_slist_append(argument.command_options, stralloc(optarg)); case 23: if (optarg) argument.dle.exclude_file = append_sl(argument.dle.exclude_file, optarg); break; case ':': case '?': break; } } if (!argument.dle.disk && argument.dle.device) argument.dle.disk = stralloc(argument.dle.device); if (!argument.dle.device && argument.dle.disk) argument.dle.device = stralloc(argument.dle.disk); argument.argc = argc - optind; argument.argv = argv + optind; if (argument.config) { /* overlay this configuration on the existing (nameless) configuration */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, argument.config); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); } if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } re_table = build_re_table(init_re_table, normal_message, ignore_message, strange_message); if (strcmp(command, "support") == 0) { amstar_support(&argument); } else if (strcmp(command, "selfcheck") == 0) { amstar_selfcheck(&argument); } else if (strcmp(command, "estimate") == 0) { amstar_estimate(&argument); } else if (strcmp(command, "backup") == 0) { amstar_backup(&argument); } else if (strcmp(command, "restore") == 0) { amstar_restore(&argument); } else if (strcmp(command, "validate") == 0) { amstar_validate(&argument); } else { fprintf(stderr, "Unknown command `%s'.\n", command); exit (1); } return 0; }
int main( int argc, char ** argv) { int c; char *command; application_argument_t argument; int i; #ifdef GNUTAR gnutar_path = GNUTAR; #else gnutar_path = NULL; #endif gnutar_directory = NULL; gnutar_onefilesystem = 1; gnutar_atimepreserve = 1; gnutar_checkdevice = 1; gnutar_sparse = 1; gnutar_no_unquote = 0; exit_handling = NULL; /* initialize */ /* * 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"); if (argc < 2) { printf("ERROR no command given to amgtar\n"); error(_("No command given to amgtar")); } /* drop root privileges */ if (!set_root_privs(0)) { if (strcmp(argv[1], "selfcheck") == 0) { printf("ERROR amgtar must be run setuid root\n"); } error(_("amgtar must be run setuid root")); } safe_fd(3, 2); set_pname("amgtar"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); #if defined(USE_DBMALLOC) malloc_size_1 = malloc_inuse(&malloc_hist_1); #endif add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_syslog); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("version %s\n"), version()); config_init(CONFIG_INIT_CLIENT, NULL); //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED); //root for amrecover //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup /* parse argument */ command = argv[1]; argument.config = NULL; argument.host = NULL; argument.message = 0; argument.collection = 0; argument.calcsize = 0; argument.tar_blocksize = NULL; argument.level = NULL; init_dle(&argument.dle); while (1) { int option_index = 0; c = getopt_long (argc, argv, "", long_options, &option_index); if (c == -1) { break; } switch (c) { case 1: argument.config = stralloc(optarg); break; case 2: argument.host = stralloc(optarg); break; case 3: argument.dle.disk = stralloc(optarg); break; case 4: argument.dle.device = stralloc(optarg); break; case 5: argument.level = g_slist_append(argument.level, GINT_TO_POINTER(atoi(optarg))); break; case 6: argument.dle.create_index = 1; break; case 7: argument.message = 1; break; case 8: argument.collection = 1; break; case 9: argument.dle.record = 1; break; case 10: gnutar_path = stralloc(optarg); break; case 11: gnutar_listdir = stralloc(optarg); break; case 12: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_onefilesystem = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) gnutar_onefilesystem = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad ONE-FILE-SYSTEM property value (%s)]\n"), get_pname(), optarg); break; case 13: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_sparse = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) gnutar_sparse = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg); break; case 14: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_atimepreserve = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) gnutar_atimepreserve = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad ATIME-PRESERVE property value (%s)]\n"), get_pname(), optarg); break; case 15: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_checkdevice = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) gnutar_checkdevice = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad CHECK-DEVICE property value (%s)]\n"), get_pname(), optarg); break; case 16: if (optarg) argument.dle.include_file = append_sl(argument.dle.include_file, optarg); break; case 17: if (optarg) argument.dle.include_list = append_sl(argument.dle.include_list, optarg); break; case 18: argument.dle.include_optional = 1; break; case 19: if (optarg) argument.dle.exclude_file = append_sl(argument.dle.exclude_file, optarg); break; case 20: if (optarg) argument.dle.exclude_list = append_sl(argument.dle.exclude_list, optarg); break; case 21: argument.dle.exclude_optional = 1; break; case 22: gnutar_directory = stralloc(optarg); break; case 23: if (optarg) normal_message = g_slist_append(normal_message, optarg); break; case 24: if (optarg) ignore_message = g_slist_append(ignore_message, optarg); break; case 25: if (optarg) strange_message = g_slist_append(strange_message, optarg); break; case 26: if (optarg) exit_handling = stralloc(optarg); break; case 27: argument.calcsize = 1; break; case 28: argument.tar_blocksize = stralloc(optarg); break; case 29: if (optarg && strcasecmp(optarg, "NO") == 0) gnutar_no_unquote = 0; else if (optarg && strcasecmp(optarg, "YES") == 0) gnutar_no_unquote = 1; else if (strcasecmp(command, "selfcheck") == 0) printf(_("ERROR [%s: bad No_UNQUOTE property value (%s)]\n"), get_pname(), optarg); break; case ':': case '?': break; } } argument.argc = argc - optind; argument.argv = argv + optind; if (argument.config) { config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, argument.config); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); } if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } re_table = build_re_table(init_re_table, normal_message, ignore_message, strange_message); for(i=0;i<256;i++) exit_value[i] = 1; /* BAD */ exit_value[0] = 0; /* GOOD */ exit_value[1] = 0; /* GOOD */ if (exit_handling) { char *s = exit_handling; while (s) { char *r = strchr(s, '='); if (r) { int j = atoi(s); if (j >= 0 && j < 256) { r++; if (strncasecmp(r, "GOOD", 4) == 0) { exit_value[j] = 0; } } } s = strchr(s+1, ' '); } } gnutar_listdir = getconf_str(CNF_GNUTAR_LIST_DIR); if (strlen(gnutar_listdir) == 0) gnutar_listdir = NULL; if (gnutar_path) { dbprintf("GNUTAR-PATH %s\n", gnutar_path); } else { dbprintf("GNUTAR-PATH is not set\n"); } if (gnutar_listdir) { dbprintf("GNUTAR-LISTDIR %s\n", gnutar_listdir); } else { dbprintf("GNUTAR-LISTDIR is not set\n"); } if (gnutar_directory) { dbprintf("DIRECTORY %s\n", gnutar_directory); } dbprintf("ONE-FILE-SYSTEM %s\n", gnutar_onefilesystem? "yes":"no"); dbprintf("SPARSE %s\n", gnutar_sparse? "yes":"no"); dbprintf("NO-UNQUOTE %s\n", gnutar_no_unquote? "yes":"no"); dbprintf("ATIME-PRESERVE %s\n", gnutar_atimepreserve? "yes":"no"); dbprintf("CHECK-DEVICE %s\n", gnutar_checkdevice? "yes":"no"); { amregex_t *rp; for (rp = re_table; rp->regex != NULL; rp++) { switch (rp->typ) { case DMP_NORMAL : dbprintf("NORMAL %s\n", rp->regex); break; case DMP_IGNORE : dbprintf("IGNORE %s\n", rp->regex); break; case DMP_STRANGE: dbprintf("STRANGE %s\n", rp->regex); break; case DMP_SIZE : dbprintf("SIZE %s\n", rp->regex); break; case DMP_ERROR : dbprintf("ERROR %s\n", rp->regex); break; } } } if (strcmp(command, "support") == 0) { amgtar_support(&argument); } else if (strcmp(command, "selfcheck") == 0) { amgtar_selfcheck(&argument); } else if (strcmp(command, "estimate") == 0) { amgtar_estimate(&argument); } else if (strcmp(command, "backup") == 0) { amgtar_backup(&argument); } else if (strcmp(command, "restore") == 0) { amgtar_restore(&argument); } else if (strcmp(command, "validate") == 0) { amgtar_validate(&argument); } else { dbprintf("Unknown command `%s'.\n", command); fprintf(stderr, "Unknown command `%s'.\n", command); exit (1); } return 0; }
int main( int argc, char ** argv) { int ch; char *exitstr; amwait_t status; if (argc > 1 && argv[1] && g_str_equal(argv[1], "--version")) { printf("killpgrp-%s\n", VERSION); return (0); } /* * 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(-1, 0); safe_cd(); set_pname("killpgrp"); dbopen(DBG_SUBDIR_CLIENT); config_init(CONFIG_INIT_CLIENT, NULL); if (argc < 2) { error("Need at least 2 arguments\n"); /*NOTREACHED*/ } dbprintf(_("version %s\n"), VERSION); dbprintf(_("config: %s\n"), argv[1]); if (!g_str_equal(argv[1], "NOCONFIG")) dbrename(argv[1], DBG_SUBDIR_CLIENT); #ifdef WANT_SETUID_CLIENT check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY); if (!become_root()) { error(_("error [%s could not become root (is the setuid bit set?)]\n"), get_pname()); /*NOTREACHED*/ } #else check_running_as(RUNNING_AS_CLIENT_LOGIN); #endif if (AM_GETPGRP() != getpid()) { error(_("error [must be the process group leader]")); /*NOTREACHED*/ } signal(SIGTERM, term_kill_soft); /* Consume any extranious input */ do { ch = getchar(); /* wait until EOF */ } while (ch != EOF); term_kill_soft(0); for(;;) { if (wait(&status) != -1) break; if (errno != EINTR) { error(_("error [wait() failed: %s]"), strerror(errno)); /*NOTREACHED*/ } } exitstr = str_exit_status("child", status); dbprintf("%s\n", exitstr); amfree(exitstr); /*@ignore@*/ return WIFEXITED(status)?WEXITSTATUS(status):1; /*@end@*/ }
int main( int argc, char ** argv) { char ch; am_feature_t *our_features = NULL; char *our_feature_string = NULL; char *options; ssize_t n; (void)argc; /* Quiet unused parameter warning */ (void)argv; /* Quiet unused parameter warning */ glib_init(); if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { printf("noop-%s\n", VERSION); return (0); } /* * 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"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); safe_fd(-1, 0); openbsd_fd_inform(); check_running_as(RUNNING_AS_CLIENT_LOGIN); do { /* soak up any stdin */ n = read(0, &ch, 1); } while ((n > 0) || ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)))); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); options = g_strjoin(NULL, "OPTIONS features=", our_feature_string, ";\n", NULL); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; if (full_write(1, options, strlen(options)) < strlen(options)) { error(_("error sending noop response: %s"), strerror(errno)); /*NOTREACHED*/ } amfree(options); close(0); close(1); close(2); return (0); /* exit */ }
int main( int argc, char ** argv) { disklist_t diskl; int no_keep; /* files per system to keep */ char **output_find_log; DIR *dir; struct dirent *adir; char **name; int useful; char *olddir; char *oldfile = NULL, *newfile = NULL; time_t today, date_keep; char *logname = NULL; struct stat stat_log; struct stat stat_old; char *conf_diskfile; char *conf_tapelist; char *conf_logdir; int dumpcycle; config_overwrites_t *cfg_ovr = NULL; /* * 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(-1, 0); safe_cd(); set_pname("amtrmlog"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if (argc > 1 && strcmp(argv[1], "-t") == 0) { amtrmidx_debug = 1; argc--; argv++; } if (argc < 2) { g_fprintf(stderr, _("Usage: %s [-t] <config> [-o configoption]*\n"), argv[0]); return 1; } dbopen(DBG_SUBDIR_SERVER); dbprintf(_("%s: version %s\n"), argv[0], version()); config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]); apply_config_overwrites(cfg_ovr); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskl); amfree(conf_diskfile); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if (read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); today = time((time_t *)NULL); dumpcycle = getconf_int(CNF_DUMPCYCLE); if(dumpcycle > 5000) dumpcycle = 5000; date_keep = today - (dumpcycle * 86400); output_find_log = find_log(); /* determine how many log to keep */ no_keep = getconf_int(CNF_TAPECYCLE) * 2; dbprintf(plural(_("Keeping %d log file\n"), _("Keeping %d log files\n"), no_keep), no_keep); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); olddir = vstralloc(conf_logdir, "/oldlog", NULL); if (mkpdir(olddir, 0700, (uid_t)-1, (gid_t)-1) != 0) { error(_("could not create parents of %s: %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (mkdir(olddir, 0700) != 0 && errno != EEXIST) { error(_("could not create %s: %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (stat(olddir,&stat_old) == -1) { error(_("can't stat oldlog directory \"%s\": %s"), olddir, strerror(errno)); /*NOTREACHED*/ } if (!S_ISDIR(stat_old.st_mode)) { error(_("Oldlog directory \"%s\" is not a directory"), olddir); /*NOTREACHED*/ } if ((dir = opendir(conf_logdir)) == NULL) { error(_("could not open log directory \"%s\": %s"), conf_logdir,strerror(errno)); /*NOTREACHED*/ } while ((adir=readdir(dir)) != NULL) { if(strncmp(adir->d_name,"log.",4)==0) { useful=0; for (name=output_find_log;*name !=NULL; name++) { if((strlen(adir->d_name) >= 13 && strlen(*name) >= 13 && adir->d_name[12] == '.' && (*name)[12] == '.' && strncmp(adir->d_name,*name,12)==0) || strncmp(adir->d_name,*name,18)==0) { useful=1; break; } } logname=newvstralloc(logname, conf_logdir, "/" ,adir->d_name, NULL); if(stat(logname,&stat_log)==0) { if((time_t)stat_log.st_mtime > date_keep) { useful = 1; } } if(useful == 0) { oldfile = newvstralloc(oldfile, conf_logdir, "/", adir->d_name, NULL); newfile = newvstralloc(newfile, olddir, "/", adir->d_name, NULL); if (rename(oldfile,newfile) != 0) { error(_("could not rename \"%s\" to \"%s\": %s"), oldfile, newfile, strerror(errno)); /*NOTREACHED*/ } } } } closedir(dir); for (name = output_find_log; *name != NULL; name++) { amfree(*name); } amfree(output_find_log); amfree(logname); amfree(oldfile); amfree(newfile); amfree(olddir); amfree(conf_logdir); clear_tapelist(); free_disklist(&diskl); dbclose(); return 0; }
int main( int argc, char ** argv) { in_port_t my_port; struct servent *sp; int i; time_t timer; char *lineread = NULL; struct sigaction act, oact; extern char *optarg; extern int optind; char cwd[STR_SIZE], *dn_guess = NULL, *mpt_guess = NULL; char *service_name; char *line = NULL; struct tm *tm; /* * 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(-1, 0); set_pname("amoldrecover"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_CLIENT); localhost = g_malloc(MAX_HOSTNAME_LENGTH+1); if (gethostname(localhost, MAX_HOSTNAME_LENGTH) != 0) { error(_("cannot determine local host name\n")); /*NOTREACHED*/ } localhost[MAX_HOSTNAME_LENGTH] = '\0'; g_free(config); config = g_strdup(DEFAULT_CONFIG); dbrename(config, DBG_SUBDIR_CLIENT); check_running_as(RUNNING_AS_ROOT); amfree(server_name); server_name = getenv("AMANDA_SERVER"); if(!server_name) server_name = DEFAULT_SERVER; server_name = g_strdup(server_name); amfree(tape_server_name); tape_server_name = getenv("AMANDA_TAPESERVER"); if(!tape_server_name) tape_server_name = DEFAULT_TAPE_SERVER; tape_server_name = g_strdup(tape_server_name); config_init(CONFIG_INIT_CLIENT, NULL); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } if (argc > 1 && argv[1][0] != '-') { /* * If the first argument is not an option flag, then we assume * it is a configuration name to match the syntax of the other * Amanda utilities. */ char **new_argv; new_argv = (char **) g_malloc((size_t)((argc + 1 + 1) * sizeof(*new_argv))); new_argv[0] = argv[0]; new_argv[1] = "-C"; for (i = 1; i < argc; i++) { new_argv[i + 1] = argv[i]; } new_argv[i + 1] = NULL; argc++; argv = new_argv; } while ((i = getopt(argc, argv, "C:s:t:d:U")) != EOF) { switch (i) { case 'C': g_free(config); config = g_strdup(optarg); break; case 's': g_free(server_name); server_name = g_strdup(optarg); break; case 't': g_free(tape_server_name); tape_server_name = g_strdup(optarg); break; case 'd': g_free(tape_device_name); tape_device_name = g_strdup(optarg); break; case 'U': case '?': (void)g_printf(USAGE); return 0; } } if (optind != argc) { (void)g_fprintf(stderr, USAGE); exit(1); } amfree(disk_name); amfree(mount_point); amfree(disk_path); dump_date[0] = '\0'; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* set up signal handler */ act.sa_handler = sigint_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTORER act.sa_restorer = NULL; #endif if (sigaction(SIGINT, &act, &oact) != 0) { error(_("error setting signal handler: %s"), strerror(errno)); /*NOTREACHED*/ } service_name = "amandaidx"; g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"), VERSION, server_name); if ((sp = getservbyname(service_name, "tcp")) == NULL) { error(_("%s/tcp unknown protocol"), service_name); /*NOTREACHED*/ } server_socket = stream_client_privileged(server_name, (in_port_t)ntohs((in_port_t)sp->s_port), 0, 0, &my_port, 0); if (server_socket < 0) { error(_("cannot connect to %s: %s"), server_name, strerror(errno)); /*NOTREACHED*/ } if (my_port >= IPPORT_RESERVED) { aclose(server_socket); error(_("did not get a reserved port: %d"), my_port); /*NOTREACHED*/ } /* get server's banner */ if (grab_reply(1) == -1) { aclose(server_socket); exit(1); } if (!server_happy()) { dbclose(); aclose(server_socket); exit(1); } /* do the security thing */ line = get_security(); if (converse(line) == -1) { aclose(server_socket); exit(1); } if (!server_happy()) { aclose(server_socket); exit(1); } memset(line, '\0', strlen(line)); amfree(line); /* try to get the features from the server */ { char *our_feature_string = NULL; char *their_feature_string = NULL; our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); line = g_strconcat("FEATURES ", our_feature_string, NULL); if(exchange(line) == 0) { their_feature_string = g_strdup(server_line+13); indexsrv_features = am_string_to_feature(their_feature_string); } else { indexsrv_features = am_set_default_feature_set(); } amfree(our_feature_string); amfree(their_feature_string); amfree(line); } /* set the date of extraction to be today */ (void)time(&timer); tm = localtime(&timer); if (tm) strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm); else error(_("BAD DATE")); g_printf(_("Setting restore date to today (%s)\n"), dump_date); line = g_strconcat("DATE ", dump_date, NULL); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); line = g_strconcat("SCNF ", config, NULL); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); if (server_happy()) { /* set host we are restoring to this host by default */ amfree(dump_hostname); set_host(localhost); if (dump_hostname) { /* get a starting disk and directory based on where we currently are */ switch (guess_disk(cwd, sizeof(cwd), &dn_guess, &mpt_guess)) { case 1: /* okay, got a guess. Set disk accordingly */ g_printf(_("$CWD '%s' is on disk '%s' mounted at '%s'.\n"), cwd, dn_guess, mpt_guess); set_disk(dn_guess, mpt_guess); set_directory(cwd); if (server_happy() && !g_str_equal(cwd, mpt_guess)) g_printf(_("WARNING: not on root of selected filesystem, check man-page!\n")); amfree(dn_guess); amfree(mpt_guess); break; case 0: g_printf(_("$CWD '%s' is on a network mounted disk\n"), cwd); g_printf(_("so you must 'sethost' to the server\n")); /* fake an unhappy server */ server_line[0] = '5'; break; case 2: case -1: default: g_printf(_("Use the setdisk command to choose dump disk to recover\n")); /* fake an unhappy server */ server_line[0] = '5'; break; } } } quit_prog = 0; do { if ((lineread = readline("amrecover> ")) == NULL) { clearerr(stdin); putchar('\n'); break; } if (lineread[0] != '\0') { add_history(lineread); process_line(lineread); /* act on line's content */ } amfree(lineread); } while (!quit_prog); dbclose(); aclose(server_socket); return 0; }
int main( int argc, char ** argv) { int foreground; int batch; int redirect; char **datearg = NULL; int nb_datearg = 0; char *conf_diskfile; char *conf_tapelist; char *conf_logfile; int conf_usetimestamps; disklist_t diskq; disk_t *dp; pid_t pid; pid_t driver_pid, reporter_pid; amwait_t exitcode; int opt; GSList *holding_list=NULL, *holding_file; int driver_pipe[2]; char date_string[100]; char date_string_standard[100]; time_t today; char *errstr; struct tm *tm; char *tapedev; char *tpchanger; char *qdisk, *qhname; GSList *datestamp_list = NULL; config_overrides_t *cfg_ovr; char **config_options; find_result_t *holding_files; disklist_t holding_disklist = { NULL, NULL }; /* * 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(-1, 0); safe_cd(); set_pname("amflush"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); foreground = 0; batch = 0; redirect = 1; /* process arguments */ cfg_ovr = new_config_overrides(argc/2); while((opt = getopt(argc, argv, "bfso:D:")) != EOF) { switch(opt) { case 'b': batch = 1; break; case 'f': foreground = 1; break; case 's': redirect = 0; break; case 'o': add_config_override_opt(cfg_ovr, optarg); break; case 'D': if (datearg == NULL) datearg = g_malloc(21*sizeof(char *)); if(nb_datearg == 20) { g_fprintf(stderr,_("maximum of 20 -D arguments.\n")); exit(1); } datearg[nb_datearg++] = g_strdup(optarg); datearg[nb_datearg] = NULL; break; } } argc -= optind, argv += optind; if(!foreground && !redirect) { g_fprintf(stderr,_("Can't redirect to stdout/stderr if not in forground.\n")); exit(1); } if(argc < 1) { error(_("Usage: amflush [-b] [-f] [-s] [-D date]* [-o configoption]* <confdir> [host [disk]* ]*")); /*NOTREACHED*/ } set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_EXPLICIT_NAME, argv[0]); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskq); amfree(conf_diskfile); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); /* load DLEs from the holding disk, in case there's anything to flush there */ search_holding_disk(&holding_files, &holding_disklist); /* note that the dumps are added to the global disklist, so we need not * consult holding_files or holding_disklist after this. The holding-only * dumps will be filtered properly by match_disklist, setting the dp->todo * flag appropriately. */ errstr = match_disklist(&diskq, argc-1, argv+1); if (errstr) { g_printf(_("%s"),errstr); amfree(errstr); } conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } amfree(conf_tapelist); conf_usetimestamps = getconf_boolean(CNF_USETIMESTAMPS); amflush_datestamp = get_datestamp_from_time(0); if(conf_usetimestamps == 0) { amflush_timestamp = g_strdup(amflush_datestamp); } else { amflush_timestamp = get_timestamp_from_time(0); } conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); conf_logfile = g_strjoin(NULL, conf_logdir, "/log", NULL); if (access(conf_logfile, F_OK) == 0) { run_amcleanup(get_config_name()); } if (access(conf_logfile, F_OK) == 0) { char *process_name = get_master_process(conf_logfile); error(_("%s exists: %s is already running, or you must run amcleanup"), conf_logfile, process_name); /*NOTREACHED*/ } driver_program = g_strjoin(NULL, amlibexecdir, "/", "driver", NULL); reporter_program = g_strjoin(NULL, sbindir, "/", "amreport", NULL); logroll_program = g_strjoin(NULL, amlibexecdir, "/", "amlogroll", NULL); tapedev = getconf_str(CNF_TAPEDEV); tpchanger = getconf_str(CNF_TPCHANGER); if (tapedev == NULL && tpchanger == NULL) { error(_("No tapedev or tpchanger specified")); } /* if dates were specified (-D), then use match_datestamp * against the list of all datestamps to turn that list * into a set of existing datestamps (basically, evaluate the * expressions into actual datestamps) */ if(datearg) { GSList *all_datestamps; GSList *datestamp; int i, ok; all_datestamps = holding_get_all_datestamps(); for(datestamp = all_datestamps; datestamp != NULL; datestamp = datestamp->next) { ok = 0; for(i=0; i<nb_datearg && ok==0; i++) { ok = match_datestamp(datearg[i], (char *)datestamp->data); } if (ok) datestamp_list = g_slist_insert_sorted(datestamp_list, g_strdup((char *)datestamp->data), g_compare_strings); } slist_free_full(all_datestamps, g_free); } else { /* otherwise, in batch mode, use all datestamps */ if(batch) { datestamp_list = holding_get_all_datestamps(); } /* or allow the user to pick datestamps */ else { datestamp_list = pick_datestamp(); } } if(!datestamp_list) { g_printf(_("Could not find any Amanda directories to flush.\n")); exit(1); } holding_list = holding_get_files_for_flush(datestamp_list); if (holding_list == NULL) { g_printf(_("Could not find any valid dump image, check directory.\n")); exit(1); } if (access(conf_logfile, F_OK) == 0) { char *process_name = get_master_process(conf_logfile); error(_("%s exists: someone started %s"), conf_logfile, process_name); /*NOTREACHED*/ } log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); if(!batch) confirm(datestamp_list); for(dp = diskq.head; dp != NULL; dp = dp->next) { if(dp->todo) { char *qname; qname = quote_string(dp->name); log_add(L_DISK, "%s %s", dp->host->hostname, qname); amfree(qname); } } if(!foreground) { /* write it before redirecting stdout */ puts(_("Running in background, you can log off now.")); puts(_("You'll get mail when amflush is finished.")); } if(redirect) redirect_stderr(); if(!foreground) detach(); add_amanda_log_handler(amanda_log_stderr); add_amanda_log_handler(amanda_log_trace_log); today = time(NULL); tm = localtime(&today); if (tm) { strftime(date_string, 100, "%a %b %e %H:%M:%S %Z %Y", tm); strftime(date_string_standard, 100, "%Y-%m-%d %H:%M:%S %Z", tm); } else { error(_("BAD DATE")); /* should never happen */ } g_fprintf(stderr, _("amflush: start at %s\n"), date_string); g_fprintf(stderr, _("amflush: datestamp %s\n"), amflush_timestamp); g_fprintf(stderr, _("amflush: starttime %s\n"), amflush_timestamp); g_fprintf(stderr, _("amflush: starttime-locale-independent %s\n"), date_string_standard); log_add(L_START, _("date %s"), amflush_timestamp); /* START DRIVER */ if(pipe(driver_pipe) == -1) { error(_("error [opening pipe to driver: %s]"), strerror(errno)); /*NOTREACHED*/ } if((driver_pid = fork()) == 0) { /* * This is the child process. */ dup2(driver_pipe[0], 0); close(driver_pipe[1]); config_options = get_config_options(3); config_options[0] = "driver"; config_options[1] = get_config_name(); config_options[2] = "nodump"; safe_fd(-1, 0); execve(driver_program, config_options, safe_env()); error(_("cannot exec %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } else if(driver_pid == -1) { error(_("cannot fork for %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } driver_stream = fdopen(driver_pipe[1], "w"); if (!driver_stream) { error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } g_fprintf(driver_stream, "DATE %s\n", amflush_timestamp); for(holding_file=holding_list; holding_file != NULL; holding_file = holding_file->next) { dumpfile_t file; holding_file_get_dumpfile((char *)holding_file->data, &file); if (holding_file_size((char *)holding_file->data, 1) <= 0) { g_debug("%s is empty - ignoring", (char *)holding_file->data); log_add(L_INFO, "%s: removing file with no data.", (char *)holding_file->data); holding_file_unlink((char *)holding_file->data); dumpfile_free_data(&file); continue; } /* search_holding_disk should have already ensured that every * holding dumpfile has an entry in the dynamic disklist */ dp = lookup_disk(file.name, file.disk); assert(dp != NULL); /* but match_disklist may have indicated we should not flush it */ if (dp->todo == 0) continue; qdisk = quote_string(file.disk); qhname = quote_string((char *)holding_file->data); g_fprintf(stderr, "FLUSH %s %s %s %d %s\n", file.name, qdisk, file.datestamp, file.dumplevel, qhname); g_debug("flushing '%s'", (char *)holding_file->data); g_fprintf(driver_stream, "FLUSH %s %s %s %d %s\n", file.name, qdisk, file.datestamp, file.dumplevel, qhname); amfree(qdisk); amfree(qhname); dumpfile_free_data(&file); } g_fprintf(stderr, "ENDFLUSH\n"); fflush(stderr); g_fprintf(driver_stream, "ENDFLUSH\n"); fflush(driver_stream); fclose(driver_stream); /* WAIT DRIVER */ while(1) { if((pid = wait(&exitcode)) == -1) { if(errno == EINTR) { continue; } else { error(_("wait for %s: %s"), driver_program, strerror(errno)); /*NOTREACHED*/ } } else if (pid == driver_pid) { break; } } slist_free_full(datestamp_list, g_free); datestamp_list = NULL; slist_free_full(holding_list, g_free); holding_list = NULL; if(redirect) { /* rename errfile */ char *errfile, *errfilex, *nerrfilex, number[100]; int tapecycle; int maxdays, days; struct stat stat_buf; errfile = g_strjoin(NULL, conf_logdir, "/amflush", NULL); errfilex = NULL; nerrfilex = NULL; tapecycle = getconf_int(CNF_TAPECYCLE); maxdays = tapecycle + 2; days = 1; /* First, find out the last existing errfile, */ /* to avoid ``infinite'' loops if tapecycle is infinite */ g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); while ( days < maxdays && stat(errfilex,&stat_buf)==0) { days++; g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); } g_snprintf(number,100,"%d",days); errfilex = newvstralloc(errfilex, errfile, ".", number, NULL); nerrfilex = NULL; while (days > 1) { amfree(nerrfilex); nerrfilex = errfilex; days--; g_snprintf(number,100,"%d",days); errfilex = g_strjoin(NULL, errfile, ".", number, NULL); if (rename(errfilex, nerrfilex) != 0) { error(_("cannot rename \"%s\" to \"%s\": %s"), errfilex, nerrfilex, strerror(errno)); /*NOTREACHED*/ } } errfilex = newvstralloc(errfilex, errfile, ".1", NULL); if (rename(errfile,errfilex) != 0) { error(_("cannot rename \"%s\" to \"%s\": %s"), errfilex, nerrfilex, strerror(errno)); /*NOTREACHED*/ } amfree(errfile); amfree(errfilex); amfree(nerrfilex); } /* * Have amreport generate report and send mail. Note that we do * not bother checking the exit status. If it does not work, it * can be rerun. */ if((reporter_pid = fork()) == 0) { /* * This is the child process. */ config_options = get_config_options(3); config_options[0] = "amreport"; config_options[1] = get_config_name(); config_options[2] = "--from-amdump"; safe_fd(-1, 0); execve(reporter_program, config_options, safe_env()); error(_("cannot exec %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } else if(reporter_pid == -1) { error(_("cannot fork for %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } while(1) { if((pid = wait(&exitcode)) == -1) { if(errno == EINTR) { continue; } else { error(_("wait for %s: %s"), reporter_program, strerror(errno)); /*NOTREACHED*/ } } else if (pid == reporter_pid) { break; } } log_add(L_INFO, "pid-done %ld", (long)getpid()); /* * Call amlogroll to rename the log file to its datestamped version. * Since we exec at this point, our exit code will be that of amlogroll. */ config_options = get_config_options(2); config_options[0] = "amlogroll"; config_options[1] = get_config_name(); safe_fd(-1, 0); execve(logroll_program, config_options, safe_env()); error(_("cannot exec %s: %s"), logroll_program, strerror(errno)); /*NOTREACHED*/ return 0; /* keep the compiler happy */ }
/* * Forks a ssh to the host listed in rc->hostname * Returns negative on error, with an errmsg in rc->errmsg. */ static int runssh( struct tcp_conn * rc, const char * amandad_path, const char * client_username, const char * ssh_keys, const char * client_port) { int rpipe[2], wpipe[2]; char *xamandad_path = (char *)amandad_path; char *xclient_username = (char *)client_username; char *xssh_keys = (char *)ssh_keys; char *xclient_port = (char *)client_port; GPtrArray *myargs; gchar *ssh_options[100] = {SSH_OPTIONS, NULL}; gchar **ssh_option; gchar *cmd; memset(rpipe, -1, sizeof(rpipe)); memset(wpipe, -1, sizeof(wpipe)); if (pipe(rpipe) < 0 || pipe(wpipe) < 0) { g_free(rc->errmsg); rc->errmsg = g_strdup_printf(_("pipe: %s"), strerror(errno)); return (-1); } if(!xamandad_path || strlen(xamandad_path) <= 1) xamandad_path = g_strjoin(NULL, amlibexecdir, "/", "amandad", NULL); if(!xclient_username || strlen(xclient_username) <= 1) xclient_username = CLIENT_LOGIN; if(!xclient_port || strlen(xclient_port) <= 1) xclient_port = NULL; myargs = g_ptr_array_sized_new(20); g_ptr_array_add(myargs, SSH); for (ssh_option = ssh_options; *ssh_option != NULL; ssh_option++) { g_ptr_array_add(myargs, *ssh_option); } g_ptr_array_add(myargs, "-l"); g_ptr_array_add(myargs, xclient_username); if (xclient_port) { g_ptr_array_add(myargs, "-p"); g_ptr_array_add(myargs, xclient_port); } if (ssh_keys && strlen(ssh_keys) > 1) { g_ptr_array_add(myargs, "-i"); g_ptr_array_add(myargs, xssh_keys); } g_ptr_array_add(myargs, rc->hostname); g_ptr_array_add(myargs, xamandad_path); g_ptr_array_add(myargs, "-auth=ssh"); g_ptr_array_add(myargs, NULL); cmd = g_strjoinv(" ", (gchar **)myargs->pdata); g_debug("exec: %s", cmd); g_free(cmd); switch (rc->pid = fork()) { case -1: g_free(rc->errmsg); rc->errmsg = g_strdup_printf(_("fork: %s"), strerror(errno)); aclose(rpipe[0]); aclose(rpipe[1]); aclose(wpipe[0]); aclose(wpipe[1]); return (-1); case 0: dup2(wpipe[0], 0); dup2(rpipe[1], 1); break; default: rc->read = rpipe[0]; aclose(rpipe[1]); rc->write = wpipe[1]; aclose(wpipe[0]); rc->child_watch = new_child_watch_source(rc->pid); g_source_set_callback(rc->child_watch, (GSourceFunc)ssh_child_watch_callback, rc, NULL); g_source_attach(rc->child_watch, NULL); g_source_unref(rc->child_watch); return (0); } /* drop root privs for good */ set_root_privs(-1); safe_fd(-1, 0); execvp(SSH, (gchar **)myargs->pdata); error("error: couldn't exec %s: %s", SSH, strerror(errno)); /* should never go here, shut up compiler warning */ return(-1); }
int main( int argc, char ** argv) { int i; time_t timer; char *lineread = NULL; struct sigaction act, oact; extern char *optarg; extern int optind; char *line = NULL; const security_driver_t *secdrv; char *req = NULL; int response_error; struct tm *tm; config_overrides_t *cfg_ovr; char *starting_hostname = NULL; /* * 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(-1, 0); set_pname("amrecover"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_CLIENT); /* treat amrecover-specific command line options as the equivalent * -o command-line options to set configuration values */ cfg_ovr = new_config_overrides(argc/2); /* If the first argument is not an option flag, then we assume * it is a configuration name to match the syntax of the other * Amanda utilities. */ if (argc > 1 && argv[1][0] != '-') { add_config_override(cfg_ovr, "conf", argv[1]); /* remove that option from the command line */ argv[1] = argv[0]; argv++; argc--; } /* now parse regular command-line '-' options */ while ((i = getopt(argc, argv, "o:C:s:t:d:Uh:")) != EOF) { switch (i) { case 'C': add_config_override(cfg_ovr, "conf", optarg); break; case 's': add_config_override(cfg_ovr, "index_server", optarg); break; case 't': add_config_override(cfg_ovr, "tape_server", optarg); break; case 'd': add_config_override(cfg_ovr, "tapedev", optarg); break; case 'o': add_config_override_opt(cfg_ovr, optarg); break; case 'h': starting_hostname = g_strdup(optarg); break; case 'U': case '?': (void)g_printf(USAGE); return 0; } } if (optind != argc) { (void)g_fprintf(stderr, USAGE); exit(1); } /* load the base client configuration */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_CLIENT, NULL); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } /* and now try to load the configuration named in that file */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, getconf_str(CNF_CONF)); check_running_as(RUNNING_AS_ROOT); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); our_features = am_init_feature_set(); our_features_string = am_feature_to_string(our_features); if (!starting_hostname) { starting_hostname = g_malloc(MAX_HOSTNAME_LENGTH+1); if (gethostname(starting_hostname, MAX_HOSTNAME_LENGTH) != 0) { error(_("cannot determine local host name\n")); /*NOTREACHED*/ } starting_hostname[MAX_HOSTNAME_LENGTH] = '\0'; } server_name = NULL; if (getconf_seen(CNF_INDEX_SERVER) == -2) { /* command line argument */ server_name = getconf_str(CNF_INDEX_SERVER); } if (!server_name) { server_name = getenv("AMANDA_SERVER"); if (server_name) { g_printf(_("Using index server from environment AMANDA_SERVER (%s)\n"), server_name); } } if (!server_name) { server_name = getconf_str(CNF_INDEX_SERVER); } if (!server_name) { error(_("No index server set")); /*NOTREACHED*/ } server_name = g_strdup(server_name); tape_server_name = NULL; if (getconf_seen(CNF_TAPE_SERVER) == -2) { /* command line argument */ tape_server_name = getconf_str(CNF_TAPE_SERVER); } if (!tape_server_name) { tape_server_name = getenv("AMANDA_TAPE_SERVER"); if (!tape_server_name) { tape_server_name = getenv("AMANDA_TAPESERVER"); if (tape_server_name) { g_printf(_("Using tape server from environment AMANDA_TAPESERVER (%s)\n"), tape_server_name); } } else { g_printf(_("Using tape server from environment AMANDA_TAPE_SERVER (%s)\n"), tape_server_name); } } if (!tape_server_name) { tape_server_name = getconf_str(CNF_TAPE_SERVER); } if (!tape_server_name) { error(_("No tape server set")); /*NOTREACHED*/ } tape_server_name = g_strdup(tape_server_name); amfree(tape_device_name); tape_device_name = getconf_str(CNF_TAPEDEV); if (!tape_device_name || strlen(tape_device_name) == 0 || !getconf_seen(CNF_TAPEDEV)) { tape_device_name = NULL; } else { tape_device_name = g_strdup(tape_device_name); } authopt = g_strdup(getconf_str(CNF_AUTH)); amfree(disk_name); amfree(mount_point); amfree(disk_path); dump_date[0] = '\0'; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* set up signal handler */ act.sa_handler = sigint_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGINT, &act, &oact) != 0) { error(_("error setting signal handler: %s"), strerror(errno)); /*NOTREACHED*/ } proplist = g_hash_table_new_full(g_str_hash, g_str_equal, &g_free, &free_property_t); protocol_init(); /* We assume that amindexd support fe_amindexd_options_features */ /* and fe_amindexd_options_auth */ /* We should send a noop to really know */ req = g_strdup_printf("SERVICE amindexd\n" "OPTIONS features=%s;auth=%s;\n", our_features_string, authopt); secdrv = security_getdriver(authopt); if (secdrv == NULL) { error(_("no '%s' security driver available for host '%s'"), authopt, server_name); /*NOTREACHED*/ } protocol_sendreq(server_name, secdrv, generic_client_get_security_conf, req, STARTUP_TIMEOUT, amindexd_response, &response_error); amfree(req); protocol_run(); g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"), VERSION, server_name); if(response_error != 0) { g_fprintf(stderr,"%s\n",errstr); exit(1); } /* get server's banner */ if (grab_reply(1) == -1) { aclose(server_socket); exit(1); } if (!server_happy()) { dbclose(); aclose(server_socket); exit(1); } /* try to get the features from the server */ { char *their_feature_string = NULL; indexsrv_features = NULL; line = g_strdup_printf("FEATURES %s", our_features_string); if(exchange(line) == 0) { their_feature_string = g_strdup(server_line+13); indexsrv_features = am_string_to_feature(their_feature_string); if (!indexsrv_features) g_printf(_("Bad feature string from server: %s"), their_feature_string); } if (!indexsrv_features) indexsrv_features = am_set_default_feature_set(); amfree(their_feature_string); amfree(line); } /* set the date of extraction to be today */ (void)time(&timer); tm = localtime(&timer); if (tm) strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm); else error(_("BAD DATE")); g_printf(_("Setting restore date to today (%s)\n"), dump_date); line = g_strdup_printf("DATE %s", dump_date); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); line = g_strdup_printf("SCNF %s", get_config_name()); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); if (server_happy()) { /* set host we are restoring to this host by default */ amfree(dump_hostname); set_host(starting_hostname); if (dump_hostname) g_printf(_("Use the setdisk command to choose dump disk to recover\n")); else g_printf(_("Use the sethost command to choose a host to recover\n")); } quit_prog = 0; do { if ((lineread = readline("amrecover> ")) == NULL) { clearerr(stdin); putchar('\n'); break; } if (lineread[0] != '\0') { add_history(lineread); dbprintf(_("user command: '%s'\n"), lineread); process_line(lineread); /* act on line's content */ } amfree(lineread); } while (!quit_prog); dbclose(); aclose(server_socket); return 0; }
int main( int argc, char ** argv) { #ifndef ERRMSG char *dump_program; int i; char *e; char *cmdline; #endif /* ERRMSG */ /* * 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(-1, 0); safe_cd(); set_pname("rundump"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_CLIENT); config_init(CONFIG_INIT_CLIENT, NULL); if (argc < 3) { error(_("Need at least 3 arguments\n")); /*NOTREACHED*/ } dbprintf(_("version %s\n"), VERSION); #ifdef ERRMSG /* { */ g_fprintf(stderr, ERRMSG); dbprintf("%s: %s", argv[0], ERRMSG); dbclose(); return 1; #else /* } { */ #ifdef WANT_SETUID_CLIENT check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY); if (!become_root()) { error(_("error [%s could not become root (is the setuid bit set?)]\n"), get_pname()); /*NOTREACHED*/ } #else check_running_as(RUNNING_AS_CLIENT_LOGIN); #endif /* skip argv[0] */ argc--; argv++; dbprintf(_("config: %s\n"), argv[0]); if (strcmp(argv[0], "NOCONFIG") != 0) dbrename(argv[0], DBG_SUBDIR_CLIENT); argc--; argv++; #ifdef XFSDUMP if (strcmp(argv[0], "xfsdump") == 0) dump_program = XFSDUMP; else /* strcmp(argv[0], "xfsdump") != 0 */ #endif #ifdef VXDUMP if (strcmp(argv[0], "vxdump") == 0) dump_program = VXDUMP; else /* strcmp(argv[0], "vxdump") != 0 */ #endif #ifdef VDUMP if (strcmp(argv[0], "vdump") == 0) dump_program = VDUMP; else /* strcmp(argv[0], "vdump") != 0 */ #endif #if defined(DUMP) dump_program = DUMP; #else # if defined(XFSDUMP) dump_program = XFSDUMP; # else # if defined(VXDUMP) dump_program = VXDUMP; # else dump_program = "dump"; # endif # endif #endif cmdline = stralloc(dump_program); for (i = 1; argv[i]; i++) { char *quoted; quoted = quote_string(argv[i]); cmdline = vstrextend(&cmdline, " ", quoted, NULL); amfree(quoted); } dbprintf(_("running: %s\n"), cmdline); amfree(cmdline); execve(dump_program, argv, safe_env()); e = strerror(errno); dbprintf(_("failed (%s)\n"), e); dbclose(); g_fprintf(stderr, _("rundump: could not exec %s: %s\n"), dump_program, e); return 1; #endif /* } */ }
// disable shm in pulseaudio void pulseaudio_init(void) { struct stat s; // do we have pulseaudio in the system? if (stat("/etc/pulse/client.conf", &s) == -1) { if (arg_debug) printf("/etc/pulse/client.conf not found\n"); return; } // create the new user pulseaudio directory if (mkdir(RUN_PULSE_DIR, 0700) == -1) errExit("mkdir"); // make it a mount point and add mount flags if (mount(RUN_PULSE_DIR, RUN_PULSE_DIR, NULL, MS_BIND, NULL) < 0 || mount(NULL, RUN_PULSE_DIR, NULL, MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_BIND|MS_REMOUNT, NULL) < 0) errExit("mount RUN_PULSE_DIR"); // create the new client.conf file char *pulsecfg = NULL; if (asprintf(&pulsecfg, "%s/client.conf", RUN_PULSE_DIR) == -1) errExit("asprintf"); if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644)) // root needed errExit("copy_file"); FILE *fp = fopen(pulsecfg, "a+"); if (!fp) errExit("fopen"); fprintf(fp, "%s", "\nenable-shm = no\n"); SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); fclose(fp); // hand over the directory to the user if (set_perms(RUN_PULSE_DIR, getuid(), getgid(), 0700)) errExit("set_perms"); // create ~/.config/pulse directory if not present char *dir1; if (asprintf(&dir1, "%s/.config", cfg.homedir) == -1) errExit("asprintf"); if (lstat(dir1, &s) == -1) { pid_t child = fork(); if (child < 0) errExit("fork"); if (child == 0) { // drop privileges drop_privs(0); int rv = mkdir(dir1, 0755); if (rv == 0) { if (set_perms(dir1, getuid(), getgid(), 0755)) {;} // do nothing } #ifdef HAVE_GCOV __gcov_flush(); #endif _exit(0); } // wait for the child to finish waitpid(child, NULL, 0); fs_logger2("create", dir1); } else { // we expect a user owned directory if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) { if (S_ISLNK(s.st_mode)) fprintf(stderr, "Error: user .config is a symbolic link\n"); else fprintf(stderr, "Error: user .config is not a directory owned by the current user\n"); exit(1); } } free(dir1); if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1) errExit("asprintf"); if (lstat(dir1, &s) == -1) { pid_t child = fork(); if (child < 0) errExit("fork"); if (child == 0) { // drop privileges drop_privs(0); int rv = mkdir(dir1, 0700); if (rv == 0) { if (set_perms(dir1, getuid(), getgid(), 0700)) {;} // do nothing } #ifdef HAVE_GCOV __gcov_flush(); #endif _exit(0); } // wait for the child to finish waitpid(child, NULL, 0); fs_logger2("create", dir1); } else { // we expect a user owned directory if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) { if (S_ISLNK(s.st_mode)) fprintf(stderr, "Error: user .config/pulse is a symbolic link\n"); else fprintf(stderr, "Error: user .config/pulse is not a directory owned by the current user\n"); exit(1); } } free(dir1); // if we have ~/.config/pulse mount the new directory, else set environment variable. char *homeusercfg; if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) errExit("asprintf"); if (stat(homeusercfg, &s) == 0) { // get a file descriptor for ~/.config/pulse, fails if there is any symlink int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); if (fd == -1) errExit("safe_fd"); // confirm the actual mount destination is owned by the user if (fstat(fd, &s) == -1 || s.st_uid != getuid()) errExit("fstat"); // mount via the link in /proc/self/fd char *proc; if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) errExit("asprintf"); if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0) errExit("mount pulseaudio"); fs_logger2("tmpfs", homeusercfg); free(proc); close(fd); // check /proc/self/mountinfo to confirm the mount is ok MountData *mptr = get_last_mount(); if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0) errLogExit("invalid pulseaudio mount"); char *p; if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) errExit("asprintf"); fs_logger2("create", p); free(p); } else { // set environment if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) errExit("setenv"); } free(pulsecfg); free(homeusercfg); }
/* * Forks a ssh to the host listed in rc->hostname * Returns negative on error, with an errmsg in rc->errmsg. */ static int runssh( struct tcp_conn * rc, const char * amandad_path, const char * client_username, const char * ssh_keys) { int rpipe[2], wpipe[2]; char *xamandad_path = (char *)amandad_path; char *xclient_username = (char *)client_username; char *xssh_keys = (char *)ssh_keys; memset(rpipe, -1, SIZEOF(rpipe)); memset(wpipe, -1, SIZEOF(wpipe)); if (pipe(rpipe) < 0 || pipe(wpipe) < 0) { rc->errmsg = newvstrallocf(rc->errmsg, _("pipe: %s"), strerror(errno)); return (-1); } switch (rc->pid = fork()) { case -1: rc->errmsg = newvstrallocf(rc->errmsg, _("fork: %s"), strerror(errno)); aclose(rpipe[0]); aclose(rpipe[1]); aclose(wpipe[0]); aclose(wpipe[1]); return (-1); case 0: dup2(wpipe[0], 0); dup2(rpipe[1], 1); break; default: rc->read = rpipe[0]; aclose(rpipe[1]); rc->write = wpipe[1]; aclose(wpipe[0]); return (0); } safe_fd(-1, 0); if(!xamandad_path || strlen(xamandad_path) <= 1) xamandad_path = vstralloc(amlibexecdir, "/", "amandad", versionsuffix(), NULL); if(!xclient_username || strlen(xclient_username) <= 1) xclient_username = CLIENT_LOGIN; if(!ssh_keys || strlen(ssh_keys) <= 1) { execlp(SSH, SSH, SSH_OPTIONS, "-l", xclient_username, rc->hostname, xamandad_path, "-auth=ssh", "amdump", "amindexd", "amidxtaped", (char *)NULL); } else { execlp(SSH, SSH, SSH_OPTIONS, "-l", xclient_username, "-i", xssh_keys, rc->hostname, xamandad_path, "-auth=ssh", "amdump", "amindexd", "amidxtaped", (char *)NULL); } error("error: couldn't exec %s: %s", SSH, strerror(errno)); /* should never go here, shut up compiler warning */ return(-1); }
static void check_disk( dle_t *dle) { char *device = NULL; char *err = NULL; char *user_and_password = NULL; char *domain = NULL; char *share = NULL, *subdir = NULL; size_t lpass = 0; int amode = R_OK; int access_result; char *access_type; char *extra_info = NULL; char *qdisk = NULL; char *qamdevice = NULL; char *qdevice = NULL; if (dle->disk) { need_global_check=1; qdisk = quote_string(dle->disk); qamdevice = quote_string(dle->device); device = g_strdup("nodevice"); dbprintf(_("checking disk %s\n"), qdisk); if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE) { if (dle->device[0] == '/' && dle->device[1] == '/') { err = g_strdup_printf( _("Can't use CALCSIZE for samba estimate, use CLIENT: %s"), dle->device); goto common_exit; } } if (g_str_equal(dle->program, "GNUTAR")) { if(dle->device[0] == '/' && dle->device[1] == '/') { #ifdef SAMBA_CLIENT int nullfd, checkerr; int passwdfd; char *pwtext; size_t pwtext_len; pid_t checkpid; amwait_t retstat; pid_t wpid; int rc; char *line; char *sep; FILE *ferr; char *pw_fd_env; int errdos; parsesharename(dle->device, &share, &subdir); if (!share) { err = g_strdup_printf( _("cannot parse for share/subdir disk entry %s"), dle->device); goto common_exit; } if ((subdir) && (SAMBA_VERSION < 2)) { err = g_strdup_printf(_("subdirectory specified for share '%s' but, samba is not v2 or better"), dle->device); goto common_exit; } if ((user_and_password = findpass(share, &domain)) == NULL) { err = g_strdup_printf(_("cannot find password for %s"), dle->device); goto common_exit; } lpass = strlen(user_and_password); if ((pwtext = strchr(user_and_password, '%')) == NULL) { err = g_strdup_printf( _("password field not \'user%%pass\' for %s"), dle->device); goto common_exit; } *pwtext++ = '\0'; pwtext_len = (size_t)strlen(pwtext); amfree(device); if ((device = makesharename(share, 0)) == NULL) { err = g_strdup_printf(_("cannot make share name of %s"), share); goto common_exit; } if ((nullfd = open("/dev/null", O_RDWR)) == -1) { err = g_strdup_printf(_("Cannot access /dev/null : %s"), strerror(errno)); goto common_exit; } if (pwtext_len > 0) { pw_fd_env = "PASSWD_FD"; } else { pw_fd_env = "dummy_PASSWD_FD"; } checkpid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, 0, &nullfd, &nullfd, &checkerr, pw_fd_env, &passwdfd, "smbclient", device, *user_and_password ? "-U" : skip_argument, *user_and_password ? user_and_password : skip_argument, "-E", domain ? "-W" : skip_argument, domain ? domain : skip_argument, #if SAMBA_VERSION >= 2 subdir ? "-D" : skip_argument, subdir ? subdir : skip_argument, #endif "-c", "quit", NULL); checkpid = checkpid; amfree(domain); aclose(nullfd); /*@ignore@*/ if ((pwtext_len > 0) && full_write(passwdfd, pwtext, pwtext_len) < pwtext_len) { err = g_strdup_printf(_("password write failed: %s: %s"), dle->device, strerror(errno)); aclose(passwdfd); goto common_exit; } /*@end@*/ memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); aclose(passwdfd); ferr = fdopen(checkerr, "r"); if (!ferr) { g_printf(_("ERROR [Can't fdopen ferr: %s]\n"), strerror(errno)); error(_("Can't fdopen ferr: %s"), strerror(errno)); /*NOTREACHED*/ } sep = ""; errdos = 0; for(sep = ""; (line = agets(ferr)) != NULL; free(line)) { if (line[0] == '\0') continue; strappend(extra_info, sep); strappend(extra_info, line); sep = ": "; if(strstr(line, "ERRDOS") != NULL) { errdos = 1; } } afclose(ferr); checkerr = -1; rc = 0; sep = ""; while ((wpid = wait(&retstat)) != -1) { if (!WIFEXITED(retstat) || WEXITSTATUS(retstat) != 0) { char *exitstr = str_exit_status("smbclient", retstat); strappend(err, sep); strappend(err, exitstr); sep = "\n"; amfree(exitstr); rc = 1; } } if (errdos != 0 || rc != 0) { char *tmpbuf; if (extra_info) { tmpbuf = g_strdup_printf( _("samba access error: %s: %s %s"), dle->device, extra_info, err); amfree(extra_info); } else { tmpbuf = g_strdup_printf(_("samba access error: %s: %s"), dle->device, err); } g_free(err); err = tmpbuf; } #else err = g_strdup_printf( _("This client is not configured for samba: %s"), qdisk); #endif goto common_exit; } amode = F_OK; amfree(device); device = amname_to_dirname(dle->device); } else if (g_str_equal(dle->program, "DUMP")) { if(dle->device[0] == '/' && dle->device[1] == '/') { err = g_strdup_printf( _("The DUMP program cannot handle samba shares, use GNUTAR: %s"), qdisk); goto common_exit; } #ifdef VDUMP /* { */ #ifdef DUMP /* { */ if (g_str_equal(amname_to_fstype(dle->device), "advfs")) #else /* }{*/ if (1) #endif /* } */ { amfree(device); device = amname_to_dirname(dle->device); amode = F_OK; } else #endif /* } */ { amfree(device); device = amname_to_devname(dle->device); #ifdef USE_RUNDUMP amode = F_OK; #else amode = R_OK; #endif } } } if (dle->program_is_application_api) { pid_t application_api_pid; backup_support_option_t *bsu; int app_err[2]; GPtrArray *errarray; bsu = backup_support_option(dle->program, g_options, dle->disk, dle->device, &errarray); if (!bsu) { char *line; guint i; for (i=0; i < errarray->len; i++) { line = g_ptr_array_index(errarray, i); fprintf(stdout, _("ERROR Application '%s': %s\n"), dle->program, line); amfree(line); } err = g_strdup_printf(_("Application '%s': can't run support command"), dle->program); goto common_exit; } if (dle->data_path == DATA_PATH_AMANDA && (bsu->data_path_set & DATA_PATH_AMANDA)==0) { g_printf("ERROR application %s doesn't support amanda data-path\n", dle->program); } if (dle->data_path == DATA_PATH_DIRECTTCP && (bsu->data_path_set & DATA_PATH_DIRECTTCP)==0) { g_printf("ERROR application %s doesn't support directtcp data-path\n", dle->program); } if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE && !bsu->calcsize) { g_printf("ERROR application %s doesn't support calcsize estimate\n", dle->program); } if (dle->include_file && dle->include_file->nb_element > 0 && !bsu->include_file) { g_printf("ERROR application %s doesn't support include-file\n", dle->program); } if (dle->include_list && dle->include_list->nb_element > 0 && !bsu->include_list) { g_printf("ERROR application %s doesn't support include-list\n", dle->program); } if (dle->include_optional && !bsu->include_optional) { g_printf("ERROR application %s doesn't support optional include\n", dle->program); } if (dle->exclude_file && dle->exclude_file->nb_element > 0 && !bsu->exclude_file) { g_printf("ERROR application %s doesn't support exclude-file\n", dle->program); } if (dle->exclude_list && dle->exclude_list->nb_element > 0 && !bsu->exclude_list) { g_printf("ERROR application %s doesn't support exclude-list\n", dle->program); } if (dle->exclude_optional && !bsu->exclude_optional) { g_printf("ERROR application %s doesn't support optional exclude\n", dle->program); } fflush(stdout);fflush(stderr); if (pipe(app_err) < 0) { err = g_strdup_printf(_("Application '%s': can't create pipe"), dle->program); goto common_exit; } switch (application_api_pid = fork()) { case -1: err = g_strdup_printf(_("fork failed: %s"), strerror(errno)); goto common_exit; case 0: /* child */ { GPtrArray *argv_ptr = g_ptr_array_new(); GPtrArray *argv_quoted = g_ptr_array_new(); gchar **args, **quoted_strings, **ptr; char *cmd = g_strjoin(NULL, APPLICATION_DIR, "/", dle->program, NULL); GSList *scriptlist; script_t *script; estimatelist_t el; char *cmdline; aclose(app_err[0]); dup2(app_err[1], 2); g_ptr_array_add(argv_ptr, g_strdup(dle->program)); g_ptr_array_add(argv_ptr, g_strdup("selfcheck")); if (bsu->message_line == 1) { g_ptr_array_add(argv_ptr, g_strdup("--message")); g_ptr_array_add(argv_ptr, g_strdup("line")); } if (g_options->config != NULL && bsu->config == 1) { g_ptr_array_add(argv_ptr, g_strdup("--config")); g_ptr_array_add(argv_ptr, g_strdup(g_options->config)); } if (g_options->hostname != NULL && bsu->host == 1) { g_ptr_array_add(argv_ptr, g_strdup("--host")); g_ptr_array_add(argv_ptr, g_strdup(g_options->hostname)); } if (dle->disk != NULL && bsu->disk == 1) { g_ptr_array_add(argv_ptr, g_strdup("--disk")); g_ptr_array_add(argv_ptr, g_strdup(dle->disk)); } if (dle->device) { g_ptr_array_add(argv_ptr, g_strdup("--device")); g_ptr_array_add(argv_ptr, g_strdup(dle->device)); } if (dle->create_index && bsu->index_line == 1) { g_ptr_array_add(argv_ptr, g_strdup("--index")); g_ptr_array_add(argv_ptr, g_strdup("line")); } if (dle->record && bsu->record == 1) { g_ptr_array_add(argv_ptr, g_strdup("--record")); } for (el = dle->estimatelist; el != NULL; el=el->next) { estimate_t estimate = (estimate_t)GPOINTER_TO_INT(el->data); if (estimate == ES_CALCSIZE && bsu->calcsize == 1) { g_ptr_array_add(argv_ptr, g_strdup("--calcsize")); } } 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); args = (gchar **)g_ptr_array_free(argv_ptr, FALSE); /* * Build the command line to display */ g_ptr_array_add(argv_quoted, g_strdup(cmd)); for (ptr = args; *ptr; ptr++) g_ptr_array_add(argv_quoted, quote_string(*ptr)); g_ptr_array_add(argv_quoted, NULL); quoted_strings = (gchar **)g_ptr_array_free(argv_quoted, FALSE); cmdline = g_strjoinv(" ", quoted_strings); g_strfreev(quoted_strings); dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline); amfree(cmdline); safe_fd(-1, 0); execve(cmd, args, safe_env()); g_printf(_("ERROR [Can't execute %s: %s]\n"), cmd, strerror(errno)); exit(127); } default: /* parent */ { int status; FILE *app_stderr; char *line; aclose(app_err[1]); app_stderr = fdopen(app_err[0], "r"); if (!app_stderr) { g_printf(_("ERROR [Can't fdopen app_stderr: %s]\n"), strerror(errno)); error(_("Can't fdopen app_stderr: %s"), strerror(errno)); /*NOTREACHED*/ } while((line = agets(app_stderr)) != NULL) { if (strlen(line) > 0) { fprintf(stdout, "ERROR Application '%s': %s\n", dle->program, line); dbprintf("ERROR %s\n", line); } amfree(line); } fclose(app_stderr); if (waitpid(application_api_pid, &status, 0) < 0) { err = g_strdup_printf(_("waitpid failed: %s"), strerror(errno)); goto common_exit; } else if (!WIFEXITED(status)) { err = g_strdup_printf(_("Application '%s': exited with signal %d"), dle->program, WTERMSIG(status)); goto common_exit; } else if (WEXITSTATUS(status) != 0) { err = g_strdup_printf(_("Application '%s': exited with status %d"), dle->program, WEXITSTATUS(status)); goto common_exit; } } } amfree(bsu); fflush(stdout);fflush(stderr); amfree(device); amfree(qamdevice); amfree(qdisk); return; } if (device) { qdevice = quote_string(device); dbprintf(_("device %s\n"), qdevice); /* skip accessability test if this is an AFS entry */ if(strncmp_const(device, "afs:") != 0) { #ifdef CHECK_FOR_ACCESS_WITH_OPEN access_result = open(device, O_RDONLY); access_type = "open"; #else access_result = access(device, amode); access_type = "access"; #endif if(access_result == -1) { err = g_strdup_printf(_("Could not %s %s (%s): %s"), access_type, qdevice, qdisk, strerror(errno)); } #ifdef CHECK_FOR_ACCESS_WITH_OPEN aclose(access_result); #endif } } common_exit: if (!qdevice) qdevice = quote_string(device); amfree(share); amfree(subdir); if(user_and_password) { memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); } amfree(domain); if(err) { g_printf(_("ERROR %s\n"), err); dbprintf(_("%s\n"), err); amfree(err); } else { if (dle->disk) { g_printf("OK %s\n", qdisk); dbprintf(_("disk %s OK\n"), qdisk); } if (dle->device) { g_printf("OK %s\n", qamdevice); dbprintf(_("amdevice %s OK\n"), qamdevice); } if (device) { g_printf("OK %s\n", qdevice); dbprintf(_("device %s OK\n"), qdevice); } } if(extra_info) { dbprintf(_("extra info: %s\n"), extra_info); amfree(extra_info); } amfree(qdisk); amfree(qdevice); amfree(qamdevice); amfree(device); /* XXX perhaps do something with level: read dumpdates and sanity check */ }