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 chunker_cmd( chunker_t *chunker, cmd_t cmd, disk_t *dp, char *mesg) { char *cmdline = NULL; char number[NUM_STR_SIZE]; char chunksize[NUM_STR_SIZE]; char use[NUM_STR_SIZE]; char *o; int activehd=0; assignedhd_t **h=NULL; char *features; char *qname; char *qdest; switch(cmd) { case START: cmdline = g_strjoin(NULL, cmdstr[cmd], " ", mesg, "\n", NULL); break; case PORT_WRITE: if(dp && sched(dp) && sched(dp)->holdp) { h = sched(dp)->holdp; activehd = sched(dp)->activehd; } if (dp && h) { qname = quote_string(dp->name); qdest = quote_string(sched(dp)->destname); h[activehd]->disk->allocated_dumpers++; g_snprintf(number, sizeof(number), "%d", sched(dp)->level); g_snprintf(chunksize, sizeof(chunksize), "%lld", (long long)holdingdisk_get_chunksize(h[0]->disk->hdisk)); g_snprintf(use, sizeof(use), "%lld", (long long)h[0]->reserved); features = am_feature_to_string(dp->host->features); o = optionstr(dp); cmdline = g_strjoin(NULL, cmdstr[cmd], " ", disk2serial(dp), " ", qdest, " ", dp->host->hostname, " ", features, " ", qname, " ", number, " ", mesg, /* datestamp */ " ", chunksize, " ", dp->program, " ", use, " |", o, "\n", NULL); amfree(features); amfree(o); amfree(qdest); amfree(qname); } else { error(_("%s command without disk and holding disk.\n"), cmdstr[cmd]); /*NOTREACHED*/ } break; case CONTINUE: if(dp && sched(dp) && sched(dp)->holdp) { h = sched(dp)->holdp; activehd = sched(dp)->activehd; } if(dp && h) { qname = quote_string(dp->name); qdest = quote_string(h[activehd]->destname); h[activehd]->disk->allocated_dumpers++; g_snprintf(chunksize, sizeof(chunksize), "%lld", (long long)holdingdisk_get_chunksize(h[activehd]->disk->hdisk)); g_snprintf(use, sizeof(use), "%lld", (long long)(h[activehd]->reserved - h[activehd]->used)); cmdline = g_strjoin(NULL, cmdstr[cmd], " ", disk2serial(dp), " ", qdest, " ", chunksize, " ", use, "\n", NULL ); amfree(qdest); amfree(qname); } else { cmdline = g_strconcat(cmdstr[cmd], "\n", NULL); } break; case QUIT: cmdline = g_strjoin(NULL, cmdstr[cmd], "\n", NULL); break; case ABORT: { char *q = quote_string(mesg); cmdline = g_strjoin(NULL, cmdstr[cmd], " ", q, "\n", NULL); amfree(q); } break; case DONE: case FAILED: if( dp ) { cmdline = g_strjoin(NULL, cmdstr[cmd], " ", disk2serial(dp), "\n", NULL); } else { cmdline = g_strjoin(NULL, cmdstr[cmd], "\n", NULL); } break; default: error(_("Don't know how to send %s command to chunker"), cmdstr[cmd]); /*NOTREACHED*/ } /* * Note: cmdline already has a '\n'. */ g_printf(_("driver: send-cmd time %s to %s: %s"), walltime_str(curclock()), chunker->name, cmdline); fflush(stdout); if (full_write(chunker->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) { g_printf(_("writing %s command: %s\n"), chunker->name, strerror(errno)); fflush(stdout); amfree(cmdline); return 0; } if (cmd == QUIT) aclose(chunker->fd); amfree(cmdline); return 1; }
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 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 dumper_cmd( dumper_t *dumper, cmd_t cmd, disk_t *dp, char *mesg) { char *cmdline; char *qmesg; switch(cmd) { case START: cmdline = g_strdup_printf("%s %s\n", cmdstr[cmd], mesg); break; case PORT_DUMP: { application_t *application = NULL; GPtrArray *array; GString *strbuf; gchar **args; am_feature_t *features; char *device, *plugin; char *tmp; if (!dp) error("PORT-DUMP without disk pointer\n"); array = g_ptr_array_new(); features = dp->host->features; device = (dp->device) ? dp->device : "NODEVICE"; if (dp->application != NULL) { application = lookup_application(dp->application); g_assert(application != NULL); } g_ptr_array_add(array, g_strdup(cmdstr[cmd])); g_ptr_array_add(array, g_strdup(disk2serial(dp))); g_ptr_array_add(array, g_strdup_printf("%d", dumper->output_port)); g_ptr_array_add(array, g_strdup(dp->host->hostname)); g_ptr_array_add(array, am_feature_to_string(features)); g_ptr_array_add(array, quote_string(dp->name)); g_ptr_array_add(array, quote_string(device)); g_ptr_array_add(array, g_strdup_printf("%d", sched(dp)->level)); g_ptr_array_add(array, g_strdup(sched(dp)->dumpdate)); /* * Build the last argument */ strbuf = g_string_new("|"); if (am_has_feature(features, fe_req_xml)) { char *qtmp; tmp = xml_optionstr(dp, 1); qtmp = quote_string(tmp); g_free(tmp); g_string_append(strbuf, qtmp); g_free(qtmp); tmp = xml_dumptype_properties(dp); qtmp = quote_string(tmp); g_free(tmp); g_string_append(strbuf, qtmp); g_free(qtmp); if (application) { tmp = xml_application(dp, application, features); qtmp = quote_string(tmp); g_free(tmp); g_string_append(strbuf, qtmp); g_free(qtmp); } } else { tmp = optionstr(dp); g_string_append(strbuf, tmp); g_free(tmp); } g_string_append_c(strbuf, '\n'); g_assert(dp->program != NULL); if (g_str_equal(dp->program, "APPLICATION")) { g_assert(application != NULL); plugin = application_get_plugin(application); } else { plugin = dp->program; } g_ptr_array_add(array, quote_string(plugin)); g_ptr_array_add(array, quote_string(dp->amandad_path)); g_ptr_array_add(array, quote_string(dp->client_username)); g_ptr_array_add(array, quote_string(dp->client_port)); g_ptr_array_add(array, quote_string(dp->ssh_keys)); g_ptr_array_add(array, g_strdup(dp->auth)); g_ptr_array_add(array, g_strdup(data_path_to_string(dp->data_path))); g_ptr_array_add(array, g_strdup(dp->dataport_list)); g_ptr_array_add(array, g_strdup_printf("%d", dp->max_warnings)); g_ptr_array_add(array, g_string_free(strbuf, FALSE)); g_ptr_array_add(array, NULL); args = (gchar **)g_ptr_array_free(array, FALSE); cmdline = g_strjoinv(" ", args); g_strfreev(args); break; } case QUIT: case ABORT: qmesg = quote_string(mesg); cmdline = g_strdup_printf("%s %s\n", cmdstr[cmd], qmesg); amfree(qmesg); break; default: error("Don't know how to send %s command to dumper", cmdstr[cmd]); /*NOTREACHED*/ } /* * Note: cmdline already has a '\n'. */ if(dumper->down) { g_printf(_("driver: send-cmd time %s ignored to down dumper %s: %s"), walltime_str(curclock()), dumper->name, cmdline); } else { g_printf(_("driver: send-cmd time %s to %s: %s"), walltime_str(curclock()), dumper->name, cmdline); fflush(stdout); if (full_write(dumper->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) { g_printf(_("writing %s command: %s\n"), dumper->name, strerror(errno)); fflush(stdout); g_free(cmdline); return 0; } if (cmd == QUIT) aclose(dumper->fd); } g_free(cmdline); return 1; }
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) { config_overrides_t *cfg_ovr; char *hostname; char *auth; char *service; char *config = NULL; int opt; extern int optind; extern char *optarg; FILE *input_file; int use_connect = 0; int got_input_file = 0; int i; unsigned char gfd[32768]; glib_init(); /* * 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 */ for (i=0; i<argc; i++) { g_debug("argv[%d] = %s", i, argv[i]); } for (i = 0;i < 32768; i++) { gfd[i] = 0; } 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 2: g_free(our_feature_string); g_free(our_features); our_feature_string = g_strdup(optarg); our_features = am_string_to_feature(our_feature_string); break; case 3: { gchar *copy_optarg = g_strdup(optarg); gchar *coma = strchr(copy_optarg, ','); gchar *stream_in; if (nb_lstream == DATA_FD_COUNT) { g_critical("Too many --stream, maximum is %d", DATA_FD_COUNT); exit(1); } else if (coma) { *coma++ = '\0'; stream_in = coma; coma = strchr(coma, ','); if (coma) { *coma++ = '\0'; lstreams[nb_lstream].name = g_strdup(copy_optarg); lstreams[nb_lstream].fd_in = atoi(stream_in); lstreams[nb_lstream].fd_out = atoi(coma); gfd[lstreams[nb_lstream].fd_in] = 1; gfd[lstreams[nb_lstream].fd_out] = 1; nb_lstream++; } } if (!coma) { g_critical("Invalid --stream option (%s)", optarg); exit(1); } g_free(copy_optarg); break; } case 4: g_free(config); config = g_strdup(optarg); 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 input 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); } /* close all unused fd */ for (i = 3;i < 32768; i++) { if (gfd[i] == 0 && i != dbfd() && (!got_input_file || i != fileno(input_file))) { close(i); } } argc -= optind, argv += optind; if(argc < 3) usage(); /* set a default config */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_CLIENT|CONFIG_INIT_GLOBAL, NULL); if (config) { config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, config); } 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]; if (g_str_equal(auth,"NULL")) { auth = getconf_str(CNF_AUTH); } service = argv[2]; /* start client side checks */ copy_stream = use_connect && got_input_file; client_protocol(hostname, auth, service, config, 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) { 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; }
int dumper_cmd( dumper_t *dumper, cmd_t cmd, disk_t *dp, char *mesg) { char *cmdline = NULL; char number[NUM_STR_SIZE]; char numberport[NUM_STR_SIZE]; char *o; char *device; char *features; char *qname; char *qmesg; switch(cmd) { case START: cmdline = vstralloc(cmdstr[cmd], " ", mesg, "\n", NULL); break; case PORT_DUMP: if(dp && dp->device) { device = dp->device; } else { device = "NODEVICE"; } if (dp != NULL) { application_t *application = NULL; char *plugin; char *qplugin; char *qamandad_path; char *qclient_username; char *qclient_port; char *qssh_keys; if (dp->application != NULL) { application = lookup_application(dp->application); g_assert(application != NULL); } device = quote_string((dp->device) ? dp->device : "NODEVICE"); qname = quote_string(dp->name); g_snprintf(number, SIZEOF(number), "%d", sched(dp)->level); g_snprintf(numberport, SIZEOF(numberport), "%d", dumper->output_port); features = am_feature_to_string(dp->host->features); if (am_has_feature(dp->host->features, fe_req_xml)) { o = xml_optionstr(dp, dp->host->features, NULL, 1); if (application) { char *xml_app; xml_app = xml_application(dp, application, dp->host->features); vstrextend(&o, xml_app, NULL); amfree(xml_app); } o = quote_string(o); } else { o = optionstr(dp, dp->host->features, NULL); } if ( o == NULL ) { error(_("problem with option string, check the dumptype definition.\n")); } g_assert(dp->program); if (0 == strcmp(dp->program, "APPLICATION")) { g_assert(application != NULL); plugin = application_get_plugin(application); } else { plugin = dp->program; } qplugin = quote_string(plugin); qamandad_path = quote_string(dp->amandad_path); qclient_username = quote_string(dp->client_username); qclient_port = quote_string(dp->client_port); qssh_keys = quote_string(dp->ssh_keys); dbprintf("security_driver %s\n", dp->auth); cmdline = vstralloc(cmdstr[cmd], " ", disk2serial(dp), " ", numberport, " ", dp->host->hostname, " ", features, " ", qname, " ", device, " ", number, " ", sched(dp)->dumpdate, " ", qplugin, " ", qamandad_path, " ", qclient_username, " ", qclient_port, " ", qssh_keys, " ", dp->auth, " ", data_path_to_string(dp->data_path), " |", o, "\n", NULL); amfree(qplugin); amfree(qamandad_path); amfree(qclient_username); amfree(qclient_port); amfree(qssh_keys); amfree(features); amfree(o); amfree(qname); amfree(device); } else { error(_("PORT-DUMP without disk pointer\n")); /*NOTREACHED*/ } break; case QUIT: case ABORT: qmesg = quote_string(mesg); cmdline = vstralloc(cmdstr[cmd], " ", qmesg, "\n", NULL ); amfree(qmesg); break; default: error(_("Don't know how to send %s command to dumper"), cmdstr[cmd]); /*NOTREACHED*/ } /* * Note: cmdline already has a '\n'. */ if(dumper->down) { g_printf(_("driver: send-cmd time %s ignored to down dumper %s: %s"), walltime_str(curclock()), dumper->name, cmdline); } else { g_printf(_("driver: send-cmd time %s to %s: %s"), walltime_str(curclock()), dumper->name, cmdline); fflush(stdout); if (full_write(dumper->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) { g_printf(_("writing %s command: %s\n"), dumper->name, strerror(errno)); fflush(stdout); amfree(cmdline); return 0; } if (cmd == QUIT) aclose(dumper->fd); } amfree(cmdline); return 1; }
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; }