Пример #1
0
int
hid_parse_usage_in_page(const char *name)
{
	const char *sep;
	int k, j;
	unsigned int l;
	size_t len;

	_DIAGASSERT(name != NULL);

	sep = strchr(name, ':');
	if (sep == NULL)
		return -1;
	len = sep - name;
	for (k = 0; k < npages; k++)
		if (strncmp(pages[k].name, name, len) == 0)
			goto found;
	if (sscanf(name, "%x:%x", &k, &j) == 2) {
		return (k << 16) | j;
	}
	return -1;
 found:
	sep++;
	for (j = 0; j < pages[k].pagesize; j++)
		if (pages[k].page_contents[j].usage == -1) {
			if (sscanf(sep, fmtcheck(
			    pages[k].page_contents[j].name, "%u"), &l) == 1) {
				return (pages[k].usage << 16) | l;
			}
		} else if (strcmp(pages[k].page_contents[j].name, sep) == 0)
			return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
	return (-1);
}
Пример #2
0
const char *
hid_usage_in_page(unsigned int u)
{
	int page = HID_PAGE(u);
	int i = HID_USAGE(u);
	static char b[100];
	int j, k, us;

	for (k = 0; k < npages; k++)
		if (pages[k].usage == page)
			break;
	if (k >= npages)
		goto bad;
	for (j = 0; j < pages[k].pagesize; j++) {
		us = pages[k].page_contents[j].usage;
		if (us == -1) {
			sprintf(b,
			    fmtcheck(pages[k].page_contents[j].name, "%d"),
			    i);
			return b;
		}
		if (us == i)
			return pages[k].page_contents[j].name;
	}
 bad:
	sprintf(b, "0x%04x", i);
	return b;
}
Пример #3
0
int
main(int argc, char *argv[])
{
    int		i, n, r;
    const char	*f, *cf, *f1, *f2;

    printf("1..1\n");
    r = 0;
    n = sizeof(test_fmts) / sizeof(test_fmts[0]);
    for (i=0 ; i<n ; i++) {
        f1 = test_fmts[i].fmt1;
        f2 = test_fmts[i].fmt2;
        f = fmtcheck(f1, f2);
        if (test_fmts[i].correct == 1) {
            cf = f1;
        } else {
            cf = f2;
        }
        if (f != cf) {
            r++;
            errx(1, "Test %d: (%s) vs. (%s) failed "
                 "(should have returned %s)", i, f1, f2,
                 (test_fmts[i].correct == 1) ? "1st" : "2nd");
        }
    }
    printf("ok 1\n");
    exit(0);
}
Пример #4
0
/*
 * Spawn a sh(1) command. Writes the resulting process ID to the pid_t pointed
 * at by `pid'. Returns a file descriptor (int) suitable for writing data to
 * the spawned command (data written to file descriptor is seen as standard-in
 * by the spawned sh(1) command). Returns `-1' if unable to spawn command.
 *
 * If cmd contains a single "%s" sequence, replace it with label if non-NULL.
 */
int
shell_spawn_pipecmd(const char *cmd, const char *label, pid_t *pid)
{
	int error;
	int len;
	posix_spawn_file_actions_t action;
#if SHELL_SPAWN_DEBUG
	unsigned int i;
#endif
	int stdin_pipe[2] = { -1, -1 };

	/* Populate argument array */
	if (label != NULL && fmtcheck(cmd, "%s") == cmd)
		len = snprintf(cmdbuf, CMDBUFMAX, cmd, label);
	else
		len = snprintf(cmdbuf, CMDBUFMAX, "%s", cmd);
	if (len >= CMDBUFMAX) {
		warnx("%s:%d:%s: cmdbuf[%u] too small to hold cmd argument",
		    __FILE__, __LINE__, __func__, CMDBUFMAX);
		return (-1);
	}

	/* Open a pipe to communicate with [X]dialog(1) */
	if (pipe(stdin_pipe) < 0)
		err(EXIT_FAILURE, "%s: pipe(2)", __func__);

	/* Fork sh(1) process */
#if SHELL_SPAWN_DEBUG
	fprintf(stderr, "%s: spawning `", __func__);
	for (i = 0; shellcmd_argv[i] != NULL; i++) {
		if (i == 0)
			fprintf(stderr, "%s", shellcmd_argv[i]);
		else if (i == 2)
			fprintf(stderr, " '%s'", shellcmd_argv[i]);
		else
			fprintf(stderr, " %s", shellcmd_argv[i]);
	}
	fprintf(stderr, "'\n");
#endif
	posix_spawn_file_actions_init(&action);
	posix_spawn_file_actions_adddup2(&action, stdin_pipe[0], STDIN_FILENO);
	posix_spawn_file_actions_addclose(&action, stdin_pipe[1]);
	error = posix_spawnp(pid, shellcmd, &action,
	    (const posix_spawnattr_t *)NULL, shellcmd_argv, environ);
	if (error != 0)
		err(EXIT_FAILURE, "%s: posix_spawnp(3)", __func__);

	return stdin_pipe[1];
}
Пример #5
0
/*
 * Takes a pointer to a dpv_config structure containing layout details and
 * pointer to initial element in a linked-list of dpv_file_node structures,
 * each presenting a file to process. Executes the `action' function passed-in
 * as a member to the `config' structure argument.
 */
int
dpv(struct dpv_config *config, struct dpv_file_node *file_list)
{
	char c;
	uint8_t keep_going;
	uint8_t nls = FALSE; /* See dialog_prompt_nlstate() */
	uint8_t no_overrun = FALSE;
	uint8_t pprompt_nls = FALSE; /* See dialog_prompt_nlstate() */
	uint8_t shrink_label_size = FALSE;
	mode_t mask;
	uint16_t options;
	char *cp;
	char *fc;
	char *last;
	char *name;
	char *output;
	const char *status_fmt;
	const char *path_fmt;
	enum dpv_display display_type;
	enum dpv_output output_type;
	enum dpv_status status;
	int (*action)(struct dpv_file_node *file, int out);
	int backslash;
	int dialog_last_update = 0;
	int dialog_old_nthfile = 0;
	int dialog_old_seconds = -1;
	int dialog_out = STDOUT_FILENO;
	int dialog_update_usec = 0;
	int dialog_updates_per_second;
	int files_left;
	int max_cols;
	int nthfile = 0;
	int output_out;
	int overall = 0;
	int pct;
	int res;
	int seconds;
	int status_last_update = 0;
	int status_old_nthfile = 0;
	int status_old_seconds = -1;
	int status_update_usec = 0;
	int status_updates_per_second;
	pid_t output_pid;
	pid_t pid;
	size_t len;
	struct dpv_file_node *curfile;
	struct dpv_file_node *first_file;
	struct dpv_file_node *list_head;
	struct timeval now;
	struct timeval start;
	char init_prompt[PROMPT_MAX + 1] = "";

	/* Initialize globals to default values */
	aprompt		= NULL;
	pprompt		= NULL;
	options		= 0;
	action		= NULL;
	backtitle	= NULL;
	debug		= FALSE;
	dialog_test	= FALSE;
	dialog_updates_per_second = DIALOG_UPDATES_PER_SEC;
	display_limit	= DISPLAY_LIMIT_DEFAULT;
	display_type	= DPV_DISPLAY_LIBDIALOG;
	label_size	= LABEL_SIZE_DEFAULT;
	msg_done	= NULL;
	msg_fail	= NULL;
	msg_pending	= NULL;
	no_labels	= FALSE;
	output		= NULL;
	output_type	= DPV_OUTPUT_NONE;
	pbar_size	= PBAR_SIZE_DEFAULT;
	status_format_custom = NULL;
	status_updates_per_second = STATUS_UPDATES_PER_SEC;
	title		= NULL;
	wide		= FALSE;

	/* Process config options (overriding defaults) */
	if (config != NULL) {
		if (config->aprompt != NULL) {
			if (aprompt == NULL) {
				aprompt = malloc(DPV_APROMPT_MAX);
				if (aprompt == NULL)
					return (-1);
			}
			snprintf(aprompt, DPV_APROMPT_MAX, "%s",
			    config->aprompt);
		}
		if (config->pprompt != NULL) {
			if (pprompt == NULL) {
				pprompt = malloc(DPV_PPROMPT_MAX + 2);
				/* +2 is for implicit "\n" appended later */
				if (pprompt == NULL)
					return (-1);
			}
			snprintf(pprompt, DPV_APROMPT_MAX, "%s",
			    config->pprompt);
		}

		options		= config->options;
		action		= config->action;
		backtitle	= config->backtitle;
		debug		= config->debug;
		dialog_test	= ((options & DPV_TEST_MODE) != 0);
		dialog_updates_per_second = config->dialog_updates_per_second;
		display_limit	= config->display_limit;
		display_type	= config->display_type;
		label_size	= config->label_size;
		msg_done	= (char *)config->msg_done;
		msg_fail	= (char *)config->msg_fail;
		msg_pending	= (char *)config->msg_pending;
		no_labels	= ((options & DPV_NO_LABELS) != 0);
		no_overrun	= ((options & DPV_NO_OVERRUN) != 0);
		output          = config->output;
		output_type	= config->output_type;
		pbar_size	= config->pbar_size;
		status_updates_per_second = config->status_updates_per_second;
		title		= config->title;
		wide		= ((options & DPV_WIDE_MODE) != 0);

		/* Enforce some minimums (pedantic) */
		if (display_limit < -1)
			display_limit = -1;
		if (label_size < -1)
			label_size = -1;
		if (pbar_size < -1)
			pbar_size = -1;

		/* For the mini-pbar, -1 means hide, zero is invalid unless
		 * only one file is given */
		if (pbar_size == 0) {
			if (file_list == NULL || file_list->next == NULL)
				pbar_size = -1;
			else
				pbar_size = PBAR_SIZE_DEFAULT;
		}

		/* For the label, -1 means auto-size, zero is invalid unless
		 * specifically requested through the use of options flag */
		if (label_size == 0 && no_labels == FALSE)
			label_size = LABEL_SIZE_DEFAULT;

		/* Status update should not be zero */
		if (status_updates_per_second == 0)
			status_updates_per_second = STATUS_UPDATES_PER_SEC;
	} /* config != NULL */

	/* Process the type of display we've been requested to produce */
	switch (display_type) {
	case DPV_DISPLAY_STDOUT:
		debug		= TRUE;
		use_color	= FALSE;
		use_dialog	= FALSE;
		use_libdialog	= FALSE;
		use_xdialog	= FALSE;
		break;
	case DPV_DISPLAY_DIALOG:
		use_color	= TRUE;
		use_dialog	= TRUE;
		use_libdialog	= FALSE;
		use_xdialog	= FALSE;
		break;
	case DPV_DISPLAY_XDIALOG:
		snprintf(dialog, PATH_MAX, XDIALOG);
		use_color	= FALSE;
		use_dialog	= FALSE;
		use_libdialog	= FALSE;
		use_xdialog	= TRUE;
		break;
	default:
		use_color	= TRUE;
		use_dialog	= FALSE;
		use_libdialog	= TRUE;
		use_xdialog	= FALSE;
		break;
	} /* display_type */

	/* Enforce additional minimums that require knowing our display type */
	if (dialog_updates_per_second == 0)
		dialog_updates_per_second = use_xdialog ?
			XDIALOG_UPDATES_PER_SEC : DIALOG_UPDATES_PER_SEC;

	/* Allow forceful override of use_color */
	if (config != NULL && (config->options & DPV_USE_COLOR) != 0)
		use_color = TRUE;

	/* Count the number of files in provided list of dpv_file_node's */
	if (use_dialog && pprompt != NULL && *pprompt != '\0')
		pprompt_nls = dialog_prompt_nlstate(pprompt);

	max_cols = dialog_maxcols();
	if (label_size == -1)
		shrink_label_size = TRUE;

	/* Process file arguments */
	for (curfile = file_list; curfile != NULL; curfile = curfile->next) {
		dpv_nfiles++;

		/* dialog(3) only expands literal newlines */
		if (use_libdialog) strexpandnl(curfile->name);

		/* Optionally calculate label size for file */
		if (shrink_label_size) {
			nls = FALSE;
			name = curfile->name;
			if (curfile == file_list)
				nls = pprompt_nls;
			last = (char *)dialog_prompt_lastline(name, nls);
			if (use_dialog) {
				c = *last;
				*last = '\0';
				nls = dialog_prompt_nlstate(name);
				*last = c;
			}
			len = dialog_prompt_longestline(last, nls);
			if ((int)len > (label_size - 3)) {
				if (label_size > 0)
					label_size += 3;
				label_size = len;
				/* Room for ellipsis (unless NULL) */
				if (label_size > 0)
					label_size += 3;
			}

			if (max_cols > 0 && label_size > (max_cols - pbar_size
			    - 9))
				label_size = max_cols - pbar_size - 9;
		}

		if (debug)
			warnx("label=[%s] path=[%s] size=%lli",
			    curfile->name, curfile->path, curfile->length);
	} /* file_list */

	/* Optionally process the contents of DIALOGRC (~/.dialogrc) */
	if (use_dialog) {
		res = parse_dialogrc();
		if (debug && res == 0) {
			warnx("Successfully read `%s' config file", DIALOGRC);
			warnx("use_shadow = %i (Boolean)", use_shadow);
			warnx("use_colors = %i (Boolean)", use_colors);
			warnx("gauge_color=[%s] (FBH)", gauge_color);
		}
	} else if (use_libdialog) {
		init_dialog(stdin, stdout);
		use_shadow = dialog_state.use_shadow;
		use_colors = dialog_state.use_colors;
		gauge_color[0] = 48 + dlg_color_table[GAUGE_ATTR].fg;
		gauge_color[1] = 48 + dlg_color_table[GAUGE_ATTR].bg;
		gauge_color[2] = dlg_color_table[GAUGE_ATTR].hilite ?
		    'b' : 'B';
		gauge_color[3] = '\0';
		end_dialog();
		if (debug) {
			warnx("Finished initializing dialog(3) library");
			warnx("use_shadow = %i (Boolean)", use_shadow);
			warnx("use_colors = %i (Boolean)", use_colors);
			warnx("gauge_color=[%s] (FBH)", gauge_color);
		}
	}

	/* Enable mini progress bar automatically for stdin streams if unable
	 * to calculate progress (missing `lines:' syntax). */
	if (dpv_nfiles <= 1 && file_list != NULL && file_list->length < 0 &&
	    !dialog_test)
		pbar_size = PBAR_SIZE_DEFAULT;

	/* If $USE_COLOR is set and non-NULL enable color; otherwise disable */
	if ((cp = getenv(ENV_USE_COLOR)) != 0)
		use_color = *cp != '\0' ? 1 : 0;

	/* Print error and return `-1' if not given at least one name */
	if (dpv_nfiles == 0) {
		warnx("%s: no labels provided", __func__);
		return (-1);
	} else if (debug)
		warnx("%s: %u label%s provided", __func__, dpv_nfiles,
		    dpv_nfiles == 1 ? "" : "s");

	/* If only one file and pbar size is zero, default to `-1' */
	if (dpv_nfiles <= 1 && pbar_size == 0)
		pbar_size = -1;

	/* Print some debugging information */
	if (debug) {
		warnx("%s: %s(%i) max rows x cols = %i x %i",
		    __func__, use_xdialog ? XDIALOG : DIALOG,
		    use_libdialog ? 3 : 1, dialog_maxrows(),
		    dialog_maxcols());
	}

	/* Xdialog(1) updates a lot slower than dialog(1) */
	if (dialog_test && use_xdialog)
		increment = XDIALOG_INCREMENT;

	/* Always add implicit newline to pprompt (when specified) */
	if (pprompt != NULL && *pprompt != '\0') {
		len = strlen(pprompt);
		/*
		 * NOTE: pprompt = malloc(PPROMPT_MAX + 2)
		 * NOTE: (see getopt(2) section above for pprompt allocation)
		 */
		pprompt[len++] = '\\';
		pprompt[len++] = 'n';
		pprompt[len++] = '\0';
	}

	/* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */
	if (use_xdialog && pprompt != NULL) {
		/* Replace `\n' with `\n\\n\n' in pprompt */
		len = strlen(pprompt);
		len += strcount(pprompt, "\\n") * 2;
		if (len > DPV_PPROMPT_MAX)
			errx(EXIT_FAILURE, "%s: Oops, pprompt buffer overflow "
			    "(%zu > %i)", __func__, len, DPV_PPROMPT_MAX);
		if (replaceall(pprompt, "\\n", "\n\\n\n") < 0)
			err(EXIT_FAILURE, "%s: replaceall()", __func__);
	}
	/* libdialog requires literal newlines */
	else if (use_libdialog && pprompt != NULL)
		strexpandnl(pprompt);

	/* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */
	if (use_xdialog && aprompt != NULL) {
		/* Replace `\n' with `\n\\n\n' in aprompt */
		len = strlen(aprompt);
		len += strcount(aprompt, "\\n") * 2;
		if (len > DPV_APROMPT_MAX)
			errx(EXIT_FAILURE, "%s: Oops, aprompt buffer overflow "
			    " (%zu > %i)", __func__, len, DPV_APROMPT_MAX);
		if (replaceall(aprompt, "\\n", "\n\\n\n") < 0)
			err(EXIT_FAILURE, "%s: replaceall()", __func__);
	}
	/* libdialog requires literal newlines */
	else if (use_libdialog && aprompt != NULL)
		strexpandnl(aprompt);

	/*
	 * Warn user about an obscure dialog(1) bug (neither Xdialog(1) nor
	 * libdialog are affected) in the `--gauge' widget. If the first non-
	 * whitespace letter of "{new_prompt}" in "XXX\n{new_prompt}\nXXX\n"
	 * is a number, the number can sometimes be mistaken for a percentage
	 * to the overall progressbar. Other nasty side-effects such as the
	 * entire prompt not displaying or displaying improperly are caused by
	 * this bug too.
	 *
	 * NOTE: When we can use color, we have a work-around... prefix the
	 * output with `\Zn' (used to terminate ANSI and reset to normal).
	 */
	if (use_dialog && !use_color) {
		backslash = 0;

		/* First, check pprompt (falls through if NULL) */
		fc = pprompt;
		while (fc != NULL && *fc != '\0') {
			if (*fc == '\n') /* leading literal newline OK */
				break;
			if (!isspace(*fc) && *fc != '\\' && backslash == 0)
				break;
			else if (backslash > 0 && *fc != 'n')
				break;
			else if (*fc == '\\') {
				backslash++;
				if (backslash > 2)
					break; /* we're safe */
			}
			fc++;
		}
		/* First non-whitespace character that dialog(1) will see */
		if (fc != NULL && *fc >= '0' && *fc <= '9')
			warnx("%s: WARNING! text argument to `-p' begins with "
			    "a number (not recommended)", __func__);
		else if (fc > pprompt)
			warnx("%s: WARNING! text argument to `-p' begins with "
			    "whitespace (not recommended)", __func__);

		/*
		 * If no pprompt or pprompt is all whitespace, check the first
		 * file name provided to make sure it is alright too.
		 */
		if ((pprompt == NULL || *fc == '\0') && file_list != NULL) {
			first_file = file_list;
			fc = first_file->name;
			while (fc != NULL && *fc != '\0' && isspace(*fc))
				fc++;
			/* First non-whitespace char that dialog(1) will see */
			if (fc != NULL && *fc >= '0' && *fc <= '9')
				warnx("%s: WARNING! File name `%s' begins "
				    "with a number (use `-p text' for safety)",
				    __func__, first_file->name);
		}
	}

	dprompt_init(file_list);
		/* Reads: label_size pbar_size pprompt aprompt dpv_nfiles */
		/* Inits: dheight and dwidth */

	if (!debug) {
		/* Internally create the initial `--gauge' prompt text */
		dprompt_recreate(file_list, (struct dpv_file_node *)NULL, 0);

		/* Spawn [X]dialog(1) `--gauge', returning pipe descriptor */
		if (use_libdialog) {
			status_printf("");
			dprompt_libprint(pprompt, aprompt, 0);
		} else {
			dprompt_sprint(init_prompt, pprompt, aprompt);
			dialog_out = dialog_spawn_gauge(init_prompt, &pid);
			dprompt_dprint(dialog_out, pprompt, aprompt, 0);
		}
	} /* !debug */

	/* Seed the random(3) generator */
	if (dialog_test)
		srandom(0xf1eeface);

	/* Set default/custom status line format */
	if (dpv_nfiles > 1) {
		snprintf(status_format_default, DPV_STATUS_FORMAT_MAX, "%s",
		    DPV_STATUS_MANY);
		status_format_custom = config->status_many;
	} else {
		snprintf(status_format_default, DPV_STATUS_FORMAT_MAX, "%s",
		    DPV_STATUS_SOLO);
		status_format_custom = config->status_solo;
	}

	/* Add test mode identifier to default status line if enabled */
	if (dialog_test && (strlen(status_format_default) + 12) <
	    DPV_STATUS_FORMAT_MAX)
		strcat(status_format_default, " [TEST MODE]");

	/* Verify custom status format */
	status_fmt = fmtcheck(status_format_custom, status_format_default);
	if (status_format_custom != NULL &&
	    status_fmt == status_format_default) {
		warnx("WARNING! Invalid status_format configuration `%s'",
		      status_format_custom);
		warnx("Default status_format `%s'", status_format_default);
	}

	/* Record when we started (used to prevent updating too quickly) */
	(void)gettimeofday(&start, (struct timezone *)NULL);

	/* Calculate number of microseconds in-between sub-second updates */
	if (status_updates_per_second != 0)
		status_update_usec = 1000000 / status_updates_per_second;
	if (dialog_updates_per_second != 0)
		dialog_update_usec = 1000000 / dialog_updates_per_second;

	/*
	 * Process the file list [serially] (one for each argument passed)
	 */
	files_left = dpv_nfiles;
	list_head = file_list;
	for (curfile = file_list; curfile != NULL; curfile = curfile->next) {
		keep_going = TRUE;
		output_out = -1;
		pct = 0;
		nthfile++;
		files_left--;

		if (dpv_interrupt)
			break;
		if (dialog_test)
			pct = 0 - increment;

		/* Attempt to spawn output program for this file */
		if (!dialog_test && output != NULL) {
			mask = umask(0022);
			(void)umask(mask);

			switch (output_type) {
			case DPV_OUTPUT_SHELL:
				output_out = shell_spawn_pipecmd(output,
				    curfile->name, &output_pid);
				break;
			case DPV_OUTPUT_FILE:
				path_fmt = fmtcheck(output, "%s");
				if (path_fmt == output)
					len = snprintf(pathbuf,
					    PATH_MAX, output, curfile->name);
				else
					len = snprintf(pathbuf,
					    PATH_MAX, "%s", output);
				if (len >= PATH_MAX) {
					warnx("%s:%d:%s: pathbuf[%u] too small"
					    "to hold output argument",
					    __FILE__, __LINE__, __func__,
					    PATH_MAX);
					return (-1);
				}
				if ((output_out = open(pathbuf,
				    O_CREAT|O_WRONLY, DEFFILEMODE & ~mask))
				    < 0) {
					warn("%s", pathbuf);
					return (-1);
				}
				break;
			default:
				break;
			}
		}

		while (!dpv_interrupt && keep_going) {
			if (dialog_test) {
				usleep(50000);
				pct += increment;
				dpv_overall_read +=
				    (int)(random() / 512 / dpv_nfiles);
				    /* 512 limits fake readout to Megabytes */
			} else if (action != NULL)
				pct = action(curfile, output_out);

			if (no_overrun || dialog_test)
				keep_going = (pct < 100);
			else {
				status = curfile->status;
				keep_going = (status == DPV_STATUS_RUNNING);
			}

			/* Get current time and calculate seconds elapsed */
			gettimeofday(&now, (struct timezone *)NULL);
			now.tv_sec = now.tv_sec - start.tv_sec;
			now.tv_usec = now.tv_usec - start.tv_usec;
			if (now.tv_usec < 0)
				now.tv_sec--, now.tv_usec += 1000000;
			seconds = now.tv_sec + (now.tv_usec / 1000000.0);

			/* Update dialog (be it dialog(3), dialog(1), etc.) */
			if ((dialog_updates_per_second != 0 &&
			   (
			    seconds != dialog_old_seconds ||
			    now.tv_usec - dialog_last_update >=
			        dialog_update_usec ||
			    nthfile != dialog_old_nthfile
			   )) || pct == 100
			) {
				/* Calculate overall progress (rounding up) */
				overall = (100 * nthfile - 100 + pct) /
				    dpv_nfiles;
				if (((100 * nthfile - 100 + pct) * 10 /
				    dpv_nfiles % 100) > 50)
					overall++;

				dprompt_recreate(list_head, curfile, pct);

				if (use_libdialog && !debug) {
					/* Update dialog(3) widget */
					dprompt_libprint(pprompt, aprompt,
					    overall);
				} else {
					/* stdout, dialog(1), or Xdialog(1) */
					dprompt_dprint(dialog_out, pprompt,
					    aprompt, overall);
					fsync(dialog_out);
				}
				dialog_old_seconds = seconds;
				dialog_old_nthfile = nthfile;
				dialog_last_update = now.tv_usec;
			}

			/* Update the status line */
			if ((use_libdialog && !debug) &&
			    status_updates_per_second != 0 &&
			   (
			    keep_going != TRUE ||
			    seconds != status_old_seconds ||
			    now.tv_usec - status_last_update >=
			        status_update_usec ||
			    nthfile != status_old_nthfile
			   )
			) {
				status_printf(status_fmt, dpv_overall_read,
				    (dpv_overall_read / (seconds == 0 ? 1 :
					seconds) * 1.0),
				    1, /* XXX until we add parallelism XXX */
				    files_left);
				status_old_seconds = seconds;
				status_old_nthfile = nthfile;
				status_last_update = now.tv_usec;
			}
		}

		if (!dialog_test && output_out >= 0) {
			close(output_out);
			waitpid(output_pid, (int *)NULL, 0);	
		}

		if (dpv_abort)
			break;

		/* Advance head of list when we hit the max display lines */
		if (display_limit > 0 && nthfile % display_limit == 0)
			list_head = curfile->next;
	}

	if (!debug) {
		if (use_libdialog)
			end_dialog();
		else {
			close(dialog_out);
			waitpid(pid, (int *)NULL, 0);	
		}
		if (!dpv_interrupt)
			printf("\n");
	} else
		warnx("%s: %lli overall read", __func__, dpv_overall_read);

	if (dpv_interrupt || dpv_abort)
		return (-1);
	else
		return (0);
}
Пример #6
0
int
PassB(FILE *fd)
{
    u_char *p,*q;
    MD5_CTX ctx;
    int i,j,sep,cnt;
    u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
    struct CTM_Syntax *sp;
    FILE *b = 0;	/* backup command */
    u_char buf[BUFSIZ];
    char md5_1[33];
    int ret = 0;
    int match = 0;
    struct CTM_Filter *filter = NULL;

    if(Verbose>3)
	printf("PassB -- Backing up files which would be changed.\n");

    MD5Init (&ctx);
    snprintf(buf, sizeof(buf), fmtcheck(TarCmd, TARCMD), BackupFile);
    b=popen(buf, "w");
    if(!b) { warn("%s", buf); return Exit_Garbage; }

    GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
    GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
    GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
    GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
    GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
    GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG

    for(;;) {
	Delete(md5);
	Delete(uid);
	Delete(gid);
	Delete(mode);
	Delete(md5before);
	Delete(trash);
	Delete(name);
	cnt = -1;

	GETFIELD(p,' ');

	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG

	if(!strcmp(p+3,"_END"))
	    break;

	for(sp=Syntax;sp->Key;sp++)
	    if(!strcmp(p+3,sp->Key))
		goto found;
	WRONG
    found:
	for(i=0;(j = sp->List[i]);i++) {
	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
		sep = ' ';
	    else
		sep = '\n';

	    switch (j & CTM_F_MASK) {
		case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break;
		case CTM_F_Uid:  GETFIELDCOPY(uid,sep); break;
		case CTM_F_Gid:  GETFIELDCOPY(gid,sep); break;
		case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
		case CTM_F_MD5:
		    if(j & CTM_Q_MD5_Before)
			GETFIELDCOPY(md5before,sep);
		    else
			GETFIELDCOPY(md5,sep);
		    break;
		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
		case CTM_F_Bytes: GETDATA(trash,cnt); break;
		default: WRONG
		}
	    }
	/* XXX This should go away.  Disallow trailing '/' */
	j = strlen(name)-1;
	if(name[j] == '/') name[j] = '\0';

	if (KeepIt && 
	    (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")))
	    continue;
		
	/* match the name against the elements of the filter list.  The
	   action associated with the last matched filter determines whether
	   this file should be ignored or backed up. */
	match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
	for (filter = FilterList; filter; filter = filter->Next) {
	    if (0 == regexec(&filter->CompiledRegex, name, 0, 0, 0))
		match = filter->Action;
	}

	if (CTM_FILTER_DISABLE == match)
		continue;

	if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") ||
	    !strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") || 
	    !strcmp(sp->Key,"FR")) {
	    /* send name to the archiver for a backup */
	    cnt = strlen(name);
	    if (cnt != fwrite(name,1,cnt,b) || EOF == fputc('\n',b)) {
		warn("%s", name);
		pclose(b);
		WRONG;
	    }
	}
    }

    ret = pclose(b);

    Delete(md5);
    Delete(uid);
    Delete(gid);
    Delete(mode);
    Delete(md5before);
    Delete(trash);
    Delete(name);

    q = MD5End (&ctx,md5_1);
    GETFIELD(p,'\n');			/* <MD5> */
    if(strcmp(q,p)) WRONG
    if (-1 != getc(fd)) WRONG
    return ret;
}