Example #1
0
int
reusable_tape(
    tape_t *tp)
{
    int count = 0;

    if(tp == NULL) return 0;
    if(tp->reuse == 0) return 0;
    if( g_str_equal(tp->datestamp, "0")) return 1;
    while(tp != NULL) {
	if(tp->reuse == 1) count++;
	tp = tp->prev;
    }
    return (count >= getconf_int(CNF_TAPECYCLE));
}
Example #2
0
tape_t *
lookup_last_reusable_tape(
     int skip)
{
    tape_t *tp, **tpsave;
    int count=0;
    int s;
    int tapecycle = getconf_int(CNF_TAPECYCLE);
    labelstr_t *labelstr = getconf_labelstr(CNF_LABELSTR);
    autolabel_t *autolabel = getconf_autolabel(CNF_AUTOLABEL);

    /*
     * The idea here is we keep the last "several" reusable tapes we
     * find in a stack and then return the n-th oldest one to the
     * caller.  If skip is zero, the oldest is returned, if it is
     * one, the next oldest, two, the next to next oldest and so on.
     */
    tpsave = g_malloc((skip + 1) * sizeof(*tpsave));
    for(s = 0; s <= skip; s++) {
	tpsave[s] = NULL;
    }
    for(tp = tape_list; tp != NULL; tp = tp->next) {
	if (tp->reuse == 1 && !g_str_equal(tp->datestamp, "0") &&
	    match_labelstr(labelstr, autolabel, tp->label,
			   tp->barcode, tp->meta)) {
	    count++;
	    for(s = skip; s > 0; s--) {
	        tpsave[s] = tpsave[s - 1];
	    }
	    tpsave[0] = tp;
	}
    }
    s = tapecycle - count;
    if(s < 0) s = 0;
    if(count < tapecycle - skip) tp = NULL;
    else tp = tpsave[skip - s];
    amfree(tpsave);
    return tp;
}
Example #3
0
int
connect_to_ndmp_proxy(char **errmsg)
{
    int   i;
    int   proxy_port;
    int   fd;

    *errmsg = NULL;
    proxy_port = getconf_int(CNF_NDMP_PROXY_PORT);

    if (proxy_port == 0) {
	*errmsg = g_strdup("no NDMP-PROXY-PORT configured; cannot start NDMP proxy");
    }

    /* we loop until getting a successful connection, either from a proxy we
     * launched or a proxy another process launched.  We only do this a few
     * times, though, in case there's some problem starting the proxy, or
     * something already running on that port. */
    for (i = 0; i < 3; i++) {
	g_debug("openning a connection to ndmp-proxy on port %d", proxy_port);
	fd = stream_client("localhost", proxy_port, 32768, 32768, NULL, 0);
	if (fd >= 0) {
	    g_debug("connected to ndmp-proxy");
	    return fd;
	}

	g_debug("Could not connect to ndmp-proxy: %s; trying to start a new instance",
		    strerror(errno));
	*errmsg = start_ndmp_proxy();
	if (*errmsg) {
	    return -1;
	}

    }

    *errmsg = stralloc(_("failed to open a connection to ndmp-proxy"));
    return -1;
}
Example #4
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);
}
Example #5
0
/*
 * The reply wait state.  We enter here much like we do with s_ackwait.
 */
static p_action_t
s_repwait(
    proto_t *	p,
    p_action_t	action,
    pkt_t *	pkt)
{
    pkt_t ack;

    /*
     * Timeout waiting for a reply.
     */
    if (action == PA_TIMEOUT) {
	assert(pkt == NULL);

	/*
	 * If we've blown our timeout limit, free up this packet and
	 * return.
	 */
	if (p->resettries == 0 || DROP_DEAD_TIME(p->origtime)) {
	    security_seterror(p->security_handle, _("timeout waiting for REP"));
	    return (PA_ABORT);
	}

	/*
	 * We still have some tries left.  Resend the request.
	 */
	p->resettries--;
	p->state = s_sendreq;
	p->reqtries = getconf_int(CNF_REQ_TRIES);
	return (PA_CONTINUE);
    }

    assert(action == PA_RCVDATA);

    /* Finish if we get a NAK */
    if (pkt->type == P_NAK)
	return (PA_FINISH);

    /*
     * We've received some data.  If we didn't get a reply,
     * requeue the packet and retry.  Otherwise, acknowledge
     * the reply, cleanup this packet, and return.
     */
    if (pkt->type != P_REP && pkt->type != P_PREP)
	return (PA_PENDING);

    if(pkt->type == P_REP) {
	pkt_init_empty(&ack, P_ACK);
	if (security_sendpkt(p->security_handle, &ack) < 0) {
	    /* XXX should retry */
	    amfree(ack.body);
	    security_seterror(p->security_handle, _("error sending ACK: %s"),
		security_geterror(p->security_handle));
	    return (PA_ABORT);
	}
	amfree(ack.body);
	return (PA_FINISH);
    }
    else if(pkt->type == P_PREP) {
	p->timeout = p->repwait - CURTIME + p->curtime + 1;
	if (p->timeout <= 0)
	    p->timeout = 1;
	return (PA_CONTPEND);
    }

    /* should never go here, shut up compiler warning */
    return (PA_FINISH);
}
Example #6
0
/*
 * Generate a request packet, and submit it to the state machine
 * for transmission.
 */
void
protocol_sendreq(
    const char *		hostname,
    const security_driver_t *	security_driver,
    char *			(*conf_fn)(char *, void *),
    const char *		req,
    time_t			repwait,
    protocol_sendreq_callback	continuation,
    void *			datap)
{
    proto_t *p;
    static char *platform = NULL;
    static char *distro = NULL;

    p = g_malloc(sizeof(proto_t));
    p->state = s_sendreq;
    p->hostname = g_strdup(hostname);
    p->security_driver = security_driver;
    /* p->security_handle set in connect_callback */
    p->repwait = repwait;
    p->origtime = CURTIME;
    /* p->curtime set in the sendreq state */
    p->connecttries = getconf_int(CNF_CONNECT_TRIES);
    p->resettries = RESET_TRIES;
    p->reqtries = getconf_int(CNF_REQ_TRIES);
    p->conf_fn = conf_fn;
    pkt_init(&p->req, P_REQ, "%s", req);

    /*
     * These are here for the caller
     * We call the continuation function after processing is complete.
     * We pass the datap on through untouched.  It is here so the caller
     * has a way to keep state with each request.
     */
    p->continuation = continuation;
    p->datap = datap;
    p->event_handle = NULL;

    proto_debug(1, _("protocol: security_connect: host %s -> p %p\n"),
		    hostname, p);

    if (!platform && !distro) {
	get_platform_and_distro(&platform, &distro);
    }

    if (distro != NULL &&
	!g_str_equal(distro, "mac") &&
#if defined HAVE_FUNC_GETSERVBYNAME_R_4 || defined HAVE_FUNC_GETSERVBYNAME_R_5 || defined HAVE_FUNC_GETSERVBYNAME_R_6
	1 &&
#else
	0 &&
#endif
	(
#ifdef BSDTCP_SECURITY
	 security_driver == &bsdtcp_security_driver ||
#endif
	 security_driver == &local_security_driver ||
#ifdef RSH_SECURITY
	 security_driver == &rsh_security_driver ||
#endif
#ifdef SSL_SECURITY
	 security_driver == &ssl_security_driver ||
#endif
#ifdef SSH_SECURITY
	 security_driver == &ssh_security_driver ||
#endif
	 0)) {
	g_thread_create(connect_thread, (gpointer)p, TRUE, NULL);
	g_mutex_lock(protocol_mutex);
	nb_thread++;
	g_mutex_unlock(protocol_mutex);
    } else {
	// bsd_security_driver		no connect,all use same socket
	// bsdudp_security_driver	no connect,all use same socket
	// krb5_security_driver		untested
	security_connect(p->security_driver, p->hostname, p->conf_fn, connect_callbackX,
			 p, p->datap);
    }
}
Example #7
0
void
update_info_dumper(
     disk_t *dp,
     off_t origsize,
     off_t dumpsize,
     time_t dumptime)
{
    int level, i;
    info_t info;
    stats_t *infp;
    perf_t *perfp;
    char *conf_infofile;

    level = sched(dp)->level;

    conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));
    if (open_infofile(conf_infofile)) {
	error(_("could not open info db \"%s\""), conf_infofile);
	/*NOTREACHED*/
    }
    amfree(conf_infofile);

    get_info(dp->host->hostname, dp->name, &info);

    /* Clean up information about this and higher-level dumps.  This
       assumes that update_info_dumper() is always run before
       update_info_taper(). */
    for (i = level; i < DUMP_LEVELS; ++i) {
      infp = &info.inf[i];
      infp->size = (off_t)-1;
      infp->csize = (off_t)-1;
      infp->secs = (time_t)-1;
      infp->date = (time_t)-1;
      infp->label[0] = '\0';
      infp->filenum = 0;
    }

    /* now store information about this dump */
    infp = &info.inf[level];
    infp->size = origsize;
    infp->csize = dumpsize;
    infp->secs = dumptime;
    if (sched(dp)->timestamp == 0) {
	infp->date = 0;
    } else {
	infp->date = get_time_from_timestamp(sched(dp)->datestamp);
    }

    if(level == 0) perfp = &info.full;
    else perfp = &info.incr;

    /* Update the stats, but only if the new values are meaningful */
    if(dp->compress != COMP_NONE && origsize > (off_t)0) {
	newperf(perfp->comp, (double)dumpsize/(double)origsize);
    }
    if(dumptime > (time_t)0) {
	if((off_t)dumptime >= dumpsize)
	    newperf(perfp->rate, 1);
	else
	    newperf(perfp->rate, (double)dumpsize/(double)dumptime);
    }

    if(origsize >= (off_t)0 && getconf_int(CNF_RESERVE)<100) {
	info.command = NO_COMMAND;
    }

    if (origsize >= (off_t)0 && level == info.last_level) {
	info.consecutive_runs++;
    } else if (origsize >= (off_t)0) {
	info.last_level = level;
	info.consecutive_runs = 1;
    }

    if(origsize >= (off_t)0 && dumpsize >= (off_t)0) {
	for(i=NB_HISTORY-1;i>0;i--) {
	    info.history[i] = info.history[i-1];
	}

	info.history[0].level = level;
	info.history[0].size  = origsize;
	info.history[0].csize = dumpsize;
	if (sched(dp)->timestamp == 0) {
	    info.history[0].date = 0;
	} else {
	    info.history[0].date = get_time_from_timestamp(sched(dp)->datestamp);
	}
	info.history[0].secs  = dumptime;
    }

    if (put_info(dp->host->hostname, dp->name, &info)) {
	int save_errno = errno;
	g_fprintf(stderr, _("infofile update failed (%s,'%s'): %s\n"),
		  dp->host->hostname, dp->name, strerror(save_errno));
	log_add(L_ERROR, _("infofile update failed (%s,'%s'): %s\n"),
		dp->host->hostname, dp->name, strerror(save_errno));
	error(_("infofile update failed (%s,'%s'): %s\n"),
	      dp->host->hostname, dp->name, strerror(save_errno));
	/*NOTREACHED*/
    }

    close_infofile();
}
Example #8
0
/* Link up the TaperSource with the Device, including retries etc. */
static void run_device_output(taper_state_t * taper_state,
                              dump_info_t * dump_info) {
    GValue val;
    guint file_number;
    dump_info->current_part = 1;
    dump_info->total_time.tv_sec = 0;
    dump_info->total_time.tv_usec = 0;
    dump_info->total_bytes = 0;

    for (;;) {
        GTimeVal start_time, end_time, run_time;
        StreamingRequirement streaming_mode;
        queue_result_flags queue_result;
        CountingConsumerData consumer_data;
        dumpfile_t *this_header;
        size_t max_memory;
        
        this_header = munge_headers(dump_info);
        if (this_header == NULL) {
            char * qdiskname = quote_string(dump_info->diskname);
	    char * errstr = taper_source_get_errmsg(dump_info->source);
	    if (!errstr)
		errstr = "Failed reading dump header.";
	    errstr = quote_string(errstr);
            putresult(FAILED,
             "%s INPUT-ERROR TAPE-GOOD %s \"\"\n",
                      dump_info->handle, errstr);
            log_add(L_FAIL, "%s %s %s %d %s",
                    dump_info->hostname, qdiskname, dump_info->timestamp,
                    dump_info->level, errstr);
            amfree(qdiskname);
	    amfree(errstr);
            return;
        }            

        if (!find_and_label_new_tape(taper_state, dump_info)) {
            bail_no_volume(dump_info, taper_state->last_errmsg);
	    dumpfile_free(this_header);
            return;
        }

	while (!device_start_file(taper_state->device, this_header)) {
            /* Close the device. */
            device_finish(taper_state->device);
            g_object_unref(taper_state->device);
            taper_state->device = NULL;

            if (!find_and_label_new_tape(taper_state, dump_info)) {
		bail_no_volume(dump_info, taper_state->last_errmsg);
		dumpfile_free(this_header);
		return;
            }
        }
	dumpfile_free(this_header);

        bzero(&val, sizeof(val));
        if (!device_property_get(taper_state->device, PROPERTY_STREAMING, &val)
            || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) {
            g_fprintf(stderr, "taper: Couldn't get streaming type!\n");
            streaming_mode = STREAMING_REQUIREMENT_REQUIRED;
        } else {
            streaming_mode = g_value_get_enum(&val);
        }
    
        file_number = taper_state->device->file;

        consumer_data.next_consumer = device_write_consumer;
        consumer_data.next_consumer_data = taper_state->device;
        consumer_data.bytes_written = 0;

        g_get_current_time(&start_time);

        if (getconf_seen(CNF_DEVICE_OUTPUT_BUFFER_SIZE)) {
            max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE);
            if (getconf_seen(CNF_TAPEBUFS)) {
                g_fprintf(stderr,
                        "Configuration directives 'device_output_buffer_size' "
                        "and \n"
                        "'tapebufs' are incompatible; using former.\n");
            }
        } else if (getconf_seen(CNF_TAPEBUFS)) {
            max_memory = getconf_int(CNF_TAPEBUFS) *
                taper_state->device->block_size;
        } else {
            /* Use default. */
            max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE);
        }

        queue_result = do_consumer_producer_queue_full
            (taper_source_producer,
             dump_info->source,
             counting_consumer,
             &consumer_data,
             taper_state->device->block_size, max_memory,
             streaming_mode);

        g_get_current_time(&end_time);
        run_time = timesub(end_time, start_time);

        /* The device_write_consumer leaves the file open, so close it now. */
        if (!device_finish_file(taper_state->device)) {
            queue_result = queue_result | QUEUE_CONSUMER_ERROR;
        }

        if (!finish_part_attempt(taper_state, dump_info, queue_result,
                                 run_time, consumer_data.bytes_written)) {
            break;
        }
    }
}
Example #9
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 */
}
Example #10
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;
}
Example #11
0
int
main(
    int		argc,
    char **	argv)
{
    config_overrides_t *cfg_ovr;
    char *hostname;
    char *auth;
    char *service;
    char *config = NULL;
    int opt;
    extern int optind;
    extern char *optarg;
    FILE *input_file;
    int use_connect = 0;
    int got_input_file = 0;
    int i;
    unsigned char gfd[32768];

    glib_init();

    /*
     * Configure program for internationalization:
     *   1) Only set the message locale for now.
     *   2) Set textdomain for all amanda related programs to "amanda"
     *      We don't want to be forced to support dozens of message catalogs.
     */
    setlocale(LC_MESSAGES, "C");
    textdomain("amanda");

//    safe_fd(-1, 0);
    safe_cd();

    set_pname("amservice");
    /* drop root privileges */
    if (!set_root_privs(0)) {
	error(_("amservice must be run setuid root"));
    }

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_SERVER);

    add_amanda_log_handler(amanda_log_stderr);

    our_features = am_init_feature_set();
    our_feature_string = am_feature_to_string(our_features);
    /* process arguments */

    for (i=0; i<argc; i++) {
	g_debug("argv[%d] = %s", i, argv[i]);
    }

    for (i = 0;i < 32768; i++) {
	gfd[i] = 0;
    }

    cfg_ovr = new_config_overrides(argc/2);
    input_file = stdin;
    while((opt = getopt_long(argc, argv, "o:f:s", long_options, NULL)) != EOF) {
	switch(opt) {
	case 1:		printf("amservice-%s\n", VERSION);
			return(0);
			break;
	case 2:		g_free(our_feature_string);
			g_free(our_features);
			our_feature_string = g_strdup(optarg);
			our_features = am_string_to_feature(our_feature_string);
			break;
	case 3: {	gchar *copy_optarg = g_strdup(optarg);
			gchar *coma = strchr(copy_optarg, ',');
			gchar *stream_in;
			if (nb_lstream == DATA_FD_COUNT) {
			    g_critical("Too many --stream, maximum is %d",
				       DATA_FD_COUNT);
			    exit(1);
			} else if (coma) {
			    *coma++ = '\0';
			    stream_in = coma;
			    coma = strchr(coma, ',');
			    if (coma) {
				*coma++ = '\0';
				lstreams[nb_lstream].name = g_strdup(copy_optarg);
				lstreams[nb_lstream].fd_in = atoi(stream_in);
				lstreams[nb_lstream].fd_out = atoi(coma);
				gfd[lstreams[nb_lstream].fd_in] = 1;
				gfd[lstreams[nb_lstream].fd_out] = 1;
				nb_lstream++;
			    }
			}
			if (!coma) {
			    g_critical("Invalid --stream option (%s)", optarg);
			    exit(1);
			}
			g_free(copy_optarg);
			break;
		  }
	case 4:		g_free(config);
			config = g_strdup(optarg);
			break;
	case 'o':	add_config_override_opt(cfg_ovr, optarg);
			break;
	case 'f':	if (got_input_file == 1) {
			    g_critical("Invalid two -f argument");
			    exit(1);
			}
			got_input_file = 1;
			if (*optarg == '/') {
			    input_file = fopen(optarg, "r");
			} else {
			    char *name = g_strjoin(NULL, get_original_cwd(), "/",
						   optarg, NULL);
			    input_file = fopen(name, "r");
			    amfree(name);
			}
			if (!input_file) {
			    g_critical("Cannot open input file '%s': %s",
				optarg, strerror(errno));
			    exit(1);
			}
			break;
	case 's':	use_connect = 1;
			break;
	}
    }

    if (use_connect && !got_input_file) {
	g_critical("The -s option require -f");
	exit(1);
    }

    /* close all unused fd */
    for (i = 3;i < 32768; i++) {
	if (gfd[i] == 0 && i != dbfd() &&
	    (!got_input_file ||  i != fileno(input_file))) {
	    close(i);
	}
    }
    argc -= optind, argv += optind;
    if(argc < 3) usage();

    /* set a default config */
    set_config_overrides(cfg_ovr);
    config_init(CONFIG_INIT_CLIENT|CONFIG_INIT_GLOBAL, NULL);
    if (config) {
	config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, config);
    }
    dbrename(get_config_name(), DBG_SUBDIR_SERVER);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);

    hostname = argv[0];
    auth = argv[1];
    if (g_str_equal(auth,"NULL")) {
	auth = getconf_str(CNF_AUTH);
    }
    service = argv[2];

    /* start client side checks */

    copy_stream = use_connect && got_input_file;
    client_protocol(hostname, auth, service, config, input_file);

    amfree(our_feature_string);
    am_release_feature_set(our_features);
    our_features = NULL;
    if (got_input_file)
	fclose(input_file);

    dbclose();
    return(remote_errors != 0);
}
Example #12
0
/* return  == NULL: correct
 *         != NULL: error message
 *
 * The ndmp-proxy is assumed to take a configuration name and a port number
 * on its command line, and to immediately attempt to bind to that port.  If
 * the bind operation succeeds, it should print "OK\n" to stdout and close the
 * file descriptor.  If the operation fails because the address is already
 * in use (and thus, most likely, there's another proxy running already), then
 * it should print "INUSE\n", close the file descriptor, and exit.  For any other
 * failure, it should print a suitable error message and exit.
 */
static char *
start_ndmp_proxy(void)
{
    char      *ndmp_proxy;
    GPtrArray *proxy_argv;
    char       buffer[32769];
    int        proxy_in, proxy_out, proxy_err;
    int        rc;
    pid_t      pid;
    char      *errmsg;
    amwait_t   wait_status;

    proxy_argv = g_ptr_array_new();
    g_ptr_array_add(proxy_argv, g_strdup("ndmp-proxy"));
    g_ptr_array_add(proxy_argv, g_strdup(get_config_name()));
    g_ptr_array_add(proxy_argv, g_strdup_printf("%d", getconf_int(CNF_NDMP_PROXY_PORT)));
    g_ptr_array_add(proxy_argv, NULL);
    ndmp_proxy = g_strdup_printf("%s/ndmp-proxy", amlibexecdir);

    proxy_in = open("/dev/null", O_RDONLY);
    proxy_err = debug_fd();
    pid = pipespawnv(ndmp_proxy, STDOUT_PIPE, 0,
			        &proxy_in, &proxy_out, &proxy_err,
			        (char **)proxy_argv->pdata);

    close(proxy_in);
    g_ptr_array_free_full(proxy_argv);
    g_debug("started ndmp-proxy with pid %d", pid);

    /* wait for the proxy to say "OK" */
    rc = full_read(proxy_out, buffer, sizeof(buffer)-1);
    if (rc == -1) {
	errmsg = g_strdup_printf("Error reading from ndmp-proxy: %s",
				 strerror(errno));
	/* clean up the PID if possible */
	waitpid(pid, NULL, WNOHANG);
	return errmsg;
    } else if (rc == 0) {
	if (waitpid(pid, &wait_status, WNOHANG)) {
	    errmsg = str_exit_status("ndmp-proxy", wait_status);
	} else {
	    errmsg = g_strdup_printf("unexpected EOF from ndmp-proxy");
	}
	return errmsg;
    }

    aclose(proxy_out);

    /* process the output */
    buffer[rc] = '\0';
    if (0 == strcmp(buffer, "OK\n")) {
	return NULL;
    } else if (0 == strcmp(buffer, "INUSE\n")) {
	g_warning("overlapping attempts to start ndmp-proxy; ignoring this attempt");
	/* clean up the pid */
	waitpid(pid, NULL, 0);
	return NULL;
    } else {
	errmsg = g_strdup_printf("ndmp-proxy failed: %s", buffer);
	return errmsg;
    }
}
Example #13
0
void edit_value(int curr)
{
    struct passwd *pw = NULL;
    char ctdluidname[256];
    char buf[SIZ];
    char *default_value = NULL;
    int ctdluid = 0;
    int portnum = 0;
    int auth = 0;
    int lportnum = 0;

    if (setup_type == UI_SILENT)
    {
        default_value = getenv(EnvNames[curr]);
    }
    if (default_value == NULL) {
        default_value = "";
    }

    switch (curr) {

    case eSysAdminName:
        getconf_str(admin_name, "c_sysadm");
        set_str_val(curr, admin_name, default_value);
        setconf_str("c_sysadm", admin_name);
        break;

    case eSysAdminPW:
        set_str_val(curr, admin_pass, default_value);
        break;

    case eUID:

        if (setup_type == UI_SILENT)
        {
            if (default_value) {
                ctdluid = atoi(default_value);
            }
        }
        else
        {
#ifdef __CYGWIN__
            ctdluid = 0;	/* work-around for Windows */
#else
            pw = getpwuid(ctdluid);
            if (pw == NULL) {
                set_int_val(curr, &ctdluid, default_value);
            }
            else {
                strcpy(ctdluidname, pw->pw_name);
                set_str_val(curr, ctdluidname, default_value);
                pw = getpwnam(ctdluidname);
                if (pw != NULL) {
                    ctdluid = pw->pw_uid;
                }
                else if (atoi(ctdluidname) > 0) {
                    ctdluid = atoi(ctdluidname);
                }
            }
#endif
        }
        setconf_int("c_ctdluid", ctdluid);
        break;

    case eIP_ADDR:
        getconf_str(buf, "c_ip_addr");
        set_str_val(curr, buf, default_value);
        setconf_str("c_ip_addr", buf);
        break;

    case eCTDL_Port:
        portnum = getconf_int("c_port_number");
        set_int_val(curr, &portnum, default_value);
        setconf_int("c_port_number", portnum);
        break;

    case eAuthType:
        auth = getconf_int("c_auth_mode");
        if (setup_type == UI_SILENT)
        {
            if ( (default_value) && (!strcasecmp(default_value, "yes")) ) auth = AUTHMODE_HOST;
            if ( (default_value) && (!strcasecmp(default_value, "host")) ) auth = AUTHMODE_HOST;
            if ( (default_value) && (!strcasecmp(default_value, "ldap")) ) auth = AUTHMODE_LDAP;
            if ( (default_value) && (!strcasecmp(default_value, "ldap_ad")) ) auth = AUTHMODE_LDAP_AD;
            if ( (default_value) && (!strcasecmp(default_value, "active directory")) ) auth = AUTHMODE_LDAP_AD;
        }
        else {
            set_int_val(curr, &auth, default_value);
        }
        setconf_int("c_auth_mode", auth);
        break;

    case eLDAP_Host:
        getconf_str(buf, "c_ldap_host");
        if (IsEmptyStr(buf)) {
            strcpy(buf, "localhost");
        }
        set_str_val(curr, buf, default_value);
        setconf_str("c_ldap_host", buf);
        break;

    case eLDAP_Port:
        lportnum = getconf_int("c_ldap_port");
        if (lportnum == 0) {
            lportnum = 389;
        }
        set_int_val(curr, &lportnum, default_value);
        setconf_int("c_ldap_port", lportnum);
        break;

    case eLDAP_Base_DN:
        getconf_str(buf, "c_ldap_base_dn");
        set_str_val(curr, buf, default_value);
        setconf_str("c_ldap_base_dn", buf);
        break;

    case eLDAP_Bind_DN:
        getconf_str(buf, "c_ldap_bind_dn");
        set_str_val(curr, buf, default_value);
        setconf_str("c_ldap_bind_dn", buf);
        break;

    case eLDAP_Bind_PW:
        getconf_str(buf, "c_ldap_bind_pw");
        set_str_val(curr, buf, default_value);
        setconf_str("c_ldap_bind_pw", buf);
        break;
    }
}
Example #14
0
                  int main(int argc, char *argv[])
{
    int a, i;
    int curr;
    char buf[1024];
    char aaa[128];
    int relh = 0;
    int home = 0;
    int nRetries = 0;
    char relhome[PATH_MAX]="";
    char ctdldir[PATH_MAX]=CTDLDIR;
    struct passwd *pw;
    gid_t gid;
    char *activity = NULL;

    /* Keep a mild groove on */
    program_title = _("Citadel setup program");

    /* set an invalid setup type */
    setup_type = (-1);

    /* parse command line args */
    for (a = 0; a < argc; ++a) {
        if (!strncmp(argv[a], "-u", 2)) {
            strcpy(aaa, argv[a]);
            strcpy(aaa, &aaa[2]);
            setup_type = atoi(aaa);
        }
        else if (!strcmp(argv[a], "-q")) {
            setup_type = UI_SILENT;
        }
        else if (!strncmp(argv[a], "-h", 2)) {
            relh=argv[a][2]!='/';
            if (!relh) {
                safestrncpy(ctdl_home_directory, &argv[a][2], sizeof ctdl_home_directory);
            } else {
                safestrncpy(relhome, &argv[a][2], sizeof relhome);
            }
            home = 1;
        }

    }

    calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
    SetTitles();

    /* If a setup type was not specified, try to determine automatically
     * the best one to use out of all available types.
     */
    if (setup_type < 0) {
        setup_type = discover_ui();
    }

    enable_home = ( relh | home );

    if (chdir(ctdl_run_dir) != 0) {
        display_error("%s: [%s]\n", _("The directory you specified does not exist"), ctdl_run_dir);
        exit(errno);
    }


    /*
     * Connect to the running Citadel server.
     */
    while ((serv_sock < 0) && (nRetries < 10)) {
        serv_sock = uds_connectsock(file_citadel_admin_socket);
        nRetries ++;
        if (serv_sock < 0)
            sleep(1);
    }
    if (serv_sock < 0) {
        display_error(
            "%s: %s %s\n",
            _("Setup could not connect to a running Citadel server."),
            strerror(errno), file_citadel_admin_socket
        );
        exit(1);
    }

    /*
     * read the server greeting
     */
    serv_gets(buf);
    if (buf[0] != '2') {
        display_error("%s\n", buf);
        exit(2);
    }

    /*
     * Are we connected to the correct Citadel server?
     */
    serv_puts("INFO");
    serv_gets(buf);
    if (buf[0] != '1') {
        display_error("%s\n", buf);
        exit(3);
    }
    a = 0;
    while (serv_gets(buf), strcmp(buf, "000")) {
        if (a == 5) {
            if (atoi(buf) != REV_LEVEL) {
                display_error("%s\n",
                              _("Your setup program and Citadel server are from different versions.")
                             );
                exit(4);
            }
        }
        ++a;
    }

    /*
     * Now begin.
     */


    if (setup_type == UI_TEXT) {
        printf("\n\n\n	       *** %s ***\n\n", program_title);
    }

    if (setup_type == UI_DIALOG) {
        system("clear 2>/dev/null");
    }

    /* Go through a series of dialogs prompting for config info */
    for (curr = 1; curr < eMaxQuestions; ++curr) {
        edit_value(curr);

        if (	(curr == eAuthType)
                && (getconf_int("c_auth_mode") != AUTHMODE_LDAP)
                && (getconf_int("c_auth_mode") != AUTHMODE_LDAP_AD)
           ) {
            curr += 5;	/* skip LDAP questions if we're not authenticating against LDAP */
        }

        if (curr == eSysAdminName) {
            if (getconf_int("c_auth_mode") == AUTHMODE_NATIVE) {
                /* for native auth mode, fetch the admin's existing pw */
                snprintf(buf, sizeof buf, "AGUP %s", admin_name);
                serv_puts(buf);
                serv_gets(buf);
                if (buf[0] == '2') {
                    extract_token(admin_pass, &buf[4], 1, '|', sizeof admin_pass);
                }
            }
            else {
                ++curr;		/* skip the password question for non-native auth modes */
            }
        }
    }

    if ((pw = getpwuid( getconf_int("c_ctdluid") )) == NULL) {
        gid = getgid();
    } else {
        gid = pw->pw_gid;
    }

    if (create_run_directories(getconf_int("c_ctdluid"), gid) != 0) {
        display_error("%s\n", _("failed to create directories"));
    }

    activity = _("Reconfiguring Citadel server");
    progress(activity, 0, 5);
    sleep(1);					/* Let the message appear briefly */

    /*
     * Create the administrator account.  It's ok if the command fails if this user already exists.
     */
    progress(activity, 1, 5);
    snprintf(buf, sizeof buf, "CREU %s|%s", admin_name, admin_pass);
    serv_puts(buf);
    progress(activity, 2, 5);
    serv_gets(buf);
    progress(activity, 3, 5);

    /*
     * Assign the desired password and access level to the administrator account.
     */
    snprintf(buf, sizeof buf, "AGUP %s", admin_name);
    serv_puts(buf);
    progress(activity, 4, 5);
    serv_gets(buf);
    if (buf[0] == '2') {
        int admin_flags = extract_int(&buf[4], 2);
        int admin_times_called = extract_int(&buf[4], 3);
        int admin_msgs_posted = extract_int(&buf[4], 4);
        snprintf(buf, sizeof buf, "ASUP %s|%s|%d|%d|%d|6",
                 admin_name, admin_pass, admin_flags, admin_times_called, admin_msgs_posted
                );
        serv_puts(buf);
        serv_gets(buf);
    }
    progress(activity, 5, 5);

#ifndef __CYGWIN__
    check_xinetd_entry();	/* Check /etc/xinetd.d/telnet */
    disable_other_mtas();   /* Offer to disable other MTAs */
    fixnss();		/* Check for the 'db' nss and offer to disable it */
#endif

    /*
     * Restart citserver
     */
    activity = _("Restarting Citadel server to apply changes");
    progress(activity, 0, 41);

    serv_puts("TIME");
    serv_gets(buf);
    long original_start_time = extract_long(&buf[4], 3);

    progress(activity, 1, 41);
    serv_puts("DOWN 1");
    progress(activity, 2, 41);
    serv_gets(buf);
    if (buf[0] != '2') {
        display_error("%s\n", buf);
        exit(6);
    }

    close(serv_sock);
    serv_sock = (-1);

    for (i=3; i<=6; ++i) {					/* wait for server to shut down */
        progress(activity, i, 41);
        sleep(1);
    }

    for (i=7; ((i<=38) && (serv_sock < 0)) ; ++i) {		/* wait for server to start up */
        progress(activity, i, 41);
        serv_sock = uds_connectsock(file_citadel_admin_socket);
        sleep(1);
    }

    progress(activity, 39, 41);
    serv_gets(buf);

    progress(activity, 40, 41);
    serv_puts("TIME");
    serv_gets(buf);
    long new_start_time = extract_long(&buf[4], 3);

    close(serv_sock);
    progress(activity, 41, 41);

    if (	(original_start_time == new_start_time)
            || (new_start_time <= 0)
       ) {
        display_error("%s\n", _("Setup failed to restart Citadel server.  Please restart it manually."));
        exit(7);
    }

    exit(0);
    return 0;
}