Beispiel #1
0
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;
}
Beispiel #2
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;
    }
}
Beispiel #3
0
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);
    }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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
}
Beispiel #6
0
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);
}
Beispiel #7
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
}
Beispiel #8
0
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;
    }
}
Beispiel #9
0
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;
}
Beispiel #10
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;
}
Beispiel #11
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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 */
}
Beispiel #14
0
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;
}
Beispiel #15
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);
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
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;
}
Beispiel #20
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@*/
}
Beispiel #21
0
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 */
}
Beispiel #22
0
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;
}
Beispiel #23
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;
}
Beispiel #24
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 */
}
Beispiel #25
0
/*
 * 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);
}
Beispiel #26
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;
}
Beispiel #27
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								/* } */
}
Beispiel #28
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");
	// 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);
}
Beispiel #29
0
/*
 * 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);
}
Beispiel #30
0
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 */
}