Esempio n. 1
0
File: dpv.c Progetto: coyizumi/cs111
/*
 * Takes a list of names that are to correspond to input streams coming from
 * stdin or fifos and produces necessary config to drive dpv(3) `--gauge'
 * widget. If the `-d' flag is used, output is instead send to terminal
 * standard output (and the output can then be saved to a file, piped into
 * custom [X]dialog(1) invocation, or whatever.
 */
int
main(int argc, char *argv[])
{
	char dummy;
	int ch;
	int n = 0;
	size_t config_size = sizeof(struct dpv_config);
	size_t file_node_size = sizeof(struct dpv_file_node);
	struct dpv_config *config;
	struct dpv_file_node *curfile;
	struct sigaction act;

	pgm = argv[0]; /* store a copy of invocation name */

	/* Allocate config structure */
	if ((config = malloc(config_size)) == NULL)
		errx(EXIT_FAILURE, "Out of memory?!");
	memset((void *)(config), '\0', config_size);

	/*
	 * Process command-line options
	 */
	while ((ch = getopt(argc, argv,
	    "a:b:dDhi:I:lL:mn:No:p:P:t:TU:wx:X")) != -1) {
		switch(ch) {
		case 'a': /* additional message text to append */
			if (config->aprompt == NULL) {
				config->aprompt = malloc(DPV_APROMPT_MAX);
				if (config->aprompt == NULL)
					errx(EXIT_FAILURE, "Out of memory?!");
			}
			snprintf(config->aprompt, DPV_APROMPT_MAX, "%s",
			    optarg);
			break;
		case 'b': /* [X]dialog(1) backtitle */
			if (config->backtitle != NULL)
				free((char *)config->backtitle);
			config->backtitle = malloc(strlen(optarg) + 1);
			if (config->backtitle == NULL)
				errx(EXIT_FAILURE, "Out of memory?!");
			*(config->backtitle) = '\0';
			strcat(config->backtitle, optarg);
			break;
		case 'd': /* debugging */
			debug = TRUE;
			config->debug = debug;
			break;
		case 'D': /* use dialog(1) instead of libdialog */
			config->display_type = DPV_DISPLAY_DIALOG;
			break;
		case 'h': /* help/usage */
			usage();
			break; /* NOTREACHED */
		case 'i': /* status line format string for single-file */
			config->status_solo = optarg;
			break;
		case 'I': /* status line format string for many-files */
			config->status_many = optarg;
			break;
		case 'l': /* Line mode */
			line_mode = TRUE;
			break;
		case 'L': /* custom label size */
			config->label_size =
			    (int)strtol(optarg, (char **)NULL, 10);
			if (config->label_size == 0 && errno == EINVAL)
				errx(EXIT_FAILURE,
				    "`-L' argument must be numeric");
			else if (config->label_size < -1)
				config->label_size = -1;
			break;
		case 'm': /* enable multiple file arguments */
			multiple = TRUE;
			break;
		case 'o': /* `-o path' for sending data-read to file */
			output_type = DPV_OUTPUT_FILE;
			config->output_type = DPV_OUTPUT_FILE;
			config->output = optarg;
			break;
		case 'n': /* custom number of files per `page' */
			config->display_limit =
				(int)strtol(optarg, (char **)NULL, 10);
			if (config->display_limit == 0 && errno == EINVAL)
				errx(EXIT_FAILURE,
				    "`-n' argument must be numeric");
			else if (config->display_limit < 0)
				config->display_limit = -1;
			break;
		case 'N': /* No overrun (truncate reads of known-length) */
			no_overrun = TRUE;
			config->options |= DPV_NO_OVERRUN;
			break;
		case 'p': /* additional message text to use as prefix */
			if (config->pprompt == NULL) {
				config->pprompt = malloc(DPV_PPROMPT_MAX + 2);
				if (config->pprompt == NULL)
					errx(EXIT_FAILURE, "Out of memory?!");
				/* +2 is for implicit "\n" appended later */
			}
			snprintf(config->pprompt, DPV_PPROMPT_MAX, "%s",
			    optarg);
			break;
		case 'P': /* custom size for mini-progressbar */
			config->pbar_size =
			    (int)strtol(optarg, (char **)NULL, 10);
			if (config->pbar_size == 0 && errno == EINVAL)
				errx(EXIT_FAILURE,
				    "`-P' argument must be numeric");
			else if (config->pbar_size < -1)
				config->pbar_size = -1;
			break;
		case 't': /* [X]dialog(1) title */
			if (config->title != NULL)
				free(config->title);
			config->title = malloc(strlen(optarg) + 1);
			if (config->title == NULL)
				errx(EXIT_FAILURE, "Out of memory?!");
			*(config->title) = '\0';
			strcat(config->title, optarg);
			break;
		case 'T': /* test mode (don't read data, fake it) */
			config->options |= DPV_TEST_MODE;
			break;
		case 'U': /* updates per second */
			config->status_updates_per_second =
			    (int)strtol(optarg, (char **)NULL, 10);
			if (config->status_updates_per_second == 0 &&
			    errno == EINVAL)
				errx(EXIT_FAILURE,
				    "`-U' argument must be numeric");
			break;
		case 'w': /* `-p' and `-a' widths bump [X]dialog(1) width */
			config->options |= DPV_WIDE_MODE;
			break;
		case 'x': /* `-x cmd' for sending data-read to sh(1) code */
			output_type = DPV_OUTPUT_SHELL;
			config->output_type = DPV_OUTPUT_SHELL;
			config->output = optarg;
			break;
		case 'X': /* X11 support through x11/xdialog */
			config->display_type = DPV_DISPLAY_XDIALOG;
			break;
		case '?': /* unknown argument (based on optstring) */
			/* FALLTHROUGH */
		default: /* unhandled argument (based on switch) */
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	/* Process remaining arguments as list of names to display */
	for (curfile = file_list; n < argc; n++) {
		nfiles++;

		/* Allocate a new struct for the file argument */
		if (curfile == NULL) {
			if ((curfile = malloc(file_node_size)) == NULL)
				errx(EXIT_FAILURE, "Out of memory?!");
			memset((void *)(curfile), '\0', file_node_size);
			file_list = curfile;
		} else {
			if ((curfile->next = malloc(file_node_size)) == NULL)
				errx(EXIT_FAILURE, "Out of memory?!");
			memset((void *)(curfile->next), '\0', file_node_size);
			curfile = curfile->next;
		}
		curfile->name = argv[n];

		/* Read possible `lines:' prefix from label syntax */
		if (sscanf(curfile->name, "%lli:%c", &(curfile->length),
		    &dummy) == 2)
			curfile->name = strchr(curfile->name, ':') + 1;
		else
			curfile->length = -1;

		/* Read path argument if enabled */
		if (multiple) {
			if (++n >= argc)
				errx(EXIT_FAILURE, "Missing path argument "
				    "for label number %i", nfiles);
			curfile->path = argv[n];
		} else
			break;
	}

	/* Display usage and exit if not given at least one name */
	if (nfiles == 0) {
		warnx("no labels provided");
		usage();
		/* NOTREACHED */
	}

	/*
	 * Set cleanup routine for Ctrl-C action
	 */
	if (config->display_type == DPV_DISPLAY_LIBDIALOG) {
		act.sa_handler = sig_int;
		sigaction(SIGINT, &act, 0);
	}

	/* Set status formats and action */
	if (line_mode) {
		config->status_solo = LINE_STATUS_SOLO;
		config->status_many = LINE_STATUS_SOLO;
		config->action = operate_on_lines;
	} else {
		config->status_solo = BYTE_STATUS_SOLO;
		config->status_many = BYTE_STATUS_SOLO;
		config->action = operate_on_bytes;
	}

	/*
	 * Hand off to dpv(3)...
	 */
	if (dpv(config, file_list) != 0 && debug)
		warnx("dpv(3) returned error!?");

	end_dialog();
	dpv_free();

	exit(EXIT_SUCCESS);
}
Esempio n. 2
0
int
main(void)
{
	char *chrootdir;
	char *distributions;
	int retval;
	size_t config_size = sizeof(struct dpv_config);
	size_t file_node_size = sizeof(struct dpv_file_node);
	size_t span;
	struct dpv_config *config;
	struct dpv_file_node *dist = dists;
	static char backtitle[] = "FreeBSD Installer";
	static char title[] = "Archive Extraction";
	static char aprompt[] = "\n  Overall Progress:";
	static char pprompt[] = "Extracting distribution files...\n";
	struct sigaction act;
	char error[PATH_MAX + 512];

	if ((distributions = getenv("DISTRIBUTIONS")) == NULL)
		errx(EXIT_FAILURE, "DISTRIBUTIONS variable is not set");
	if ((distdir = getenv("BSDINSTALL_DISTDIR")) == NULL)
		distdir = __DECONST(char *, "");

	/* Initialize dialog(3) */
	init_dialog(stdin, stdout);
	dialog_vars.backtitle = backtitle;
	dlg_put_backtitle();

	dialog_msgbox("",
	    "Checking distribution archives.\nPlease wait...", 4, 35, FALSE);

	/*
	 * Parse $DISTRIBUTIONS into dpv(3) linked-list
	 */
	while (*distributions != '\0') {
		span = strcspn(distributions, "\t\n\v\f\r ");
		if (span < 1) { /* currently on whitespace */
			distributions++;
			continue;
		}

		/* Allocate a new struct for the distribution */
		if (dist == NULL) {
			if ((dist = calloc(1, file_node_size)) == NULL)
				_errx(EXIT_FAILURE, "Out of memory!");
			dists = dist;
		} else {
			dist->next = calloc(1, file_node_size);
			if (dist->next == NULL)
				_errx(EXIT_FAILURE, "Out of memory!");
			dist = dist->next;
		}

		/* Set path */
		if ((dist->path = malloc(span + 1)) == NULL)
			_errx(EXIT_FAILURE, "Out of memory!");
		snprintf(dist->path, span + 1, "%s", distributions);
		dist->path[span] = '\0';

		/* Set display name */
		dist->name = strrchr(dist->path, '/');
		if (dist->name == NULL)
			dist->name = dist->path;

		/* Set initial length in files (-1 == error) */
		dist->length = count_files(dist->path);
		if (dist->length < 0) {
			end_dialog();
			return (EXIT_FAILURE);
		}

		distributions += span;
	}

	/* Optionally chdir(2) into $BSDINSTALL_CHROOT */
	chrootdir = getenv("BSDINSTALL_CHROOT");
	if (chrootdir != NULL && chdir(chrootdir) != 0) {
		snprintf(error, sizeof(error),
		    "Could not change to directory %s: %s\n",
		    chrootdir, strerror(errno));
		dialog_msgbox("Error", error, 0, 0, TRUE);
		end_dialog();
		return (EXIT_FAILURE);
	}

	/* Set cleanup routine for Ctrl-C action */
	act.sa_handler = sig_int;
	sigaction(SIGINT, &act, 0);

	/*
	 * Hand off to dpv(3)
	 */
	if ((config = calloc(1, config_size)) == NULL)
		_errx(EXIT_FAILURE, "Out of memory!");
	config->backtitle	= backtitle;
	config->title		= title;
	config->pprompt		= pprompt;
	config->aprompt		= aprompt;
	config->options		|= DPV_WIDE_MODE;
	config->label_size	= -1;
	config->action		= extract_files;
	config->status_solo	=
	    "%10lli files read @ %'9.1f files/sec.";
	config->status_many	= 
	    "%10lli files read @ %'9.1f files/sec. [%i/%i busy/wait]";
	end_dialog();
	retval = dpv(config, dists);

	dpv_free();
	while ((dist = dists) != NULL) {
		dists = dist->next;
		if (dist->path != NULL)
			free(dist->path);
		free(dist);
	}

	return (retval);
}