[Midnightbsd-cvs] src [10436] trunk/lib/libdpv: add libdpv

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Tue Jun 5 18:58:24 EDT 2018


Revision: 10436
          http://svnweb.midnightbsd.org/src/?rev=10436
Author:   laffer1
Date:     2018-06-05 18:58:23 -0400 (Tue, 05 Jun 2018)
Log Message:
-----------
add libdpv

Added Paths:
-----------
    trunk/lib/libdpv/
    trunk/lib/libdpv/Makefile
    trunk/lib/libdpv/dialog_util.c
    trunk/lib/libdpv/dialog_util.h
    trunk/lib/libdpv/dialogrc.c
    trunk/lib/libdpv/dialogrc.h
    trunk/lib/libdpv/dprompt.c
    trunk/lib/libdpv/dprompt.h
    trunk/lib/libdpv/dpv.3
    trunk/lib/libdpv/dpv.c
    trunk/lib/libdpv/dpv.h
    trunk/lib/libdpv/dpv_private.h
    trunk/lib/libdpv/status.c
    trunk/lib/libdpv/status.h
    trunk/lib/libdpv/util.c
    trunk/lib/libdpv/util.h

Added: trunk/lib/libdpv/Makefile
===================================================================
--- trunk/lib/libdpv/Makefile	                        (rev 0)
+++ trunk/lib/libdpv/Makefile	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,19 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/lib/libdpv/Makefile 275040 2014-11-25 13:47:53Z dteske $
+
+LIB=		dpv
+SHLIB_MAJOR=	1
+INCS=		dpv.h
+MAN=		dpv.3
+MLINKS=		dpv.3 dpv_free.3
+
+DPADD=		${LIBDIALOG} ${LIBFIGPAR} ${LIBNCURSESW} ${LIBUTIL}
+LDADD=		-ldialog -lfigpar -lncursesw -lutil
+
+SRCS=		dialog_util.c dialogrc.c dprompt.c dpv.c status.c util.c
+
+CFLAGS+=	-I${.CURDIR}
+
+WARNS?=		6
+
+.include <bsd.lib.mk>


Property changes on: trunk/lib/libdpv/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dialog_util.c
===================================================================
--- trunk/lib/libdpv/dialog_util.c	                        (rev 0)
+++ trunk/lib/libdpv/dialog_util.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,641 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/dialog_util.c 295107 2016-02-01 00:44:29Z dteske $");
+
+#include <sys/ioctl.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "dialog_util.h"
+#include "dpv.h"
+#include "dpv_private.h"
+
+extern char **environ;
+
+#define TTY_DEFAULT_ROWS	24
+#define TTY_DEFAULT_COLS	80
+
+/* [X]dialog(1) characteristics */
+uint8_t dialog_test	= 0;
+uint8_t use_dialog	= 0;
+uint8_t use_libdialog	= 1;
+uint8_t use_xdialog	= 0;
+uint8_t use_color	= 1;
+char dialog[PATH_MAX]	= DIALOG;
+
+/* [X]dialog(1) functionality */
+char *title	= NULL;
+char *backtitle	= NULL;
+int dheight	= 0;
+int dwidth	= 0;
+static char *dargv[64] = { NULL };
+
+/* TTY/Screen characteristics */
+static struct winsize *maxsize = NULL;
+
+/* Function prototypes */
+static void tty_maxsize_update(void);
+static void x11_maxsize_update(void);
+
+/*
+ * Update row/column fields of `maxsize' global (used by dialog_maxrows() and
+ * dialog_maxcols()). If the `maxsize' pointer is NULL, it will be initialized.
+ * The `ws_row' and `ws_col' fields of `maxsize' are updated to hold current
+ * maximum height and width (respectively) for a dialog(1) widget based on the
+ * active TTY size.
+ *
+ * This function is called automatically by dialog_maxrows/cols() to reflect
+ * changes in terminal size in-between calls.
+ */
+static void
+tty_maxsize_update(void)
+{
+	int fd = STDIN_FILENO;
+	struct termios t;
+
+	if (maxsize == NULL) {
+		if ((maxsize = malloc(sizeof(struct winsize))) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		memset((void *)maxsize, '\0', sizeof(struct winsize));
+	}
+
+	if (!isatty(fd))
+		fd = open("/dev/tty", O_RDONLY);
+	if ((tcgetattr(fd, &t) < 0) || (ioctl(fd, TIOCGWINSZ, maxsize) < 0)) {
+		maxsize->ws_row = TTY_DEFAULT_ROWS;
+		maxsize->ws_col = TTY_DEFAULT_COLS;
+	}
+}
+
+/*
+ * Update row/column fields of `maxsize' global (used by dialog_maxrows() and
+ * dialog_maxcols()). If the `maxsize' pointer is NULL, it will be initialized.
+ * The `ws_row' and `ws_col' fields of `maxsize' are updated to hold current
+ * maximum height and width (respectively) for an Xdialog(1) widget based on
+ * the active video resolution of the X11 environment.
+ *
+ * This function is called automatically by dialog_maxrows/cols() to initialize
+ * `maxsize'. Since video resolution changes are less common and more obtrusive
+ * than changes to terminal size, the dialog_maxrows/cols() functions only call
+ * this function when `maxsize' is set to NULL.
+ */
+static void
+x11_maxsize_update(void)
+{
+	FILE *f = NULL;
+	char *cols;
+	char *cp;
+	char *rows;
+	char cmdbuf[LINE_MAX];
+	char rbuf[LINE_MAX];
+
+	if (maxsize == NULL) {
+		if ((maxsize = malloc(sizeof(struct winsize))) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		memset((void *)maxsize, '\0', sizeof(struct winsize));
+	}
+
+	/* Assemble the command necessary to get X11 sizes */
+	snprintf(cmdbuf, LINE_MAX, "%s --print-maxsize 2>&1", dialog);
+
+	fflush(STDIN_FILENO); /* prevent popen(3) from seeking on stdin */
+
+	if ((f = popen(cmdbuf, "r")) == NULL) {
+		if (debug)
+			warnx("WARNING! Command `%s' failed", cmdbuf);
+		return;
+	}
+
+	/* Read in the line returned from Xdialog(1) */
+	if ((fgets(rbuf, LINE_MAX, f) == NULL) || (pclose(f) < 0))
+		return;
+
+	/* Check for X11-related errors */
+	if (strncmp(rbuf, "Xdialog: Error", 14) == 0)
+		return;
+
+	/* Parse expected output: MaxSize: YY, XXX */
+	if ((rows = strchr(rbuf, ' ')) == NULL)
+		return;
+	if ((cols = strchr(rows, ',')) != NULL) {
+		/* strtonum(3) doesn't like trailing junk */
+		*(cols++) = '\0';
+		if ((cp = strchr(cols, '\n')) != NULL)
+			*cp = '\0';
+	}
+
+	/* Convert to unsigned short */
+	maxsize->ws_row = (unsigned short)strtonum(
+	    rows, 0, USHRT_MAX, (const char **)NULL);
+	maxsize->ws_col = (unsigned short)strtonum(
+	    cols, 0, USHRT_MAX, (const char **)NULL);
+}
+
+/*
+ * Return the current maximum height (rows) for an [X]dialog(1) widget.
+ */
+int
+dialog_maxrows(void)
+{
+
+	if (use_xdialog && maxsize == NULL)
+		x11_maxsize_update(); /* initialize maxsize for GUI */
+	else if (!use_xdialog)
+		tty_maxsize_update(); /* update maxsize for TTY */
+	return (maxsize->ws_row);
+}
+
+/*
+ * Return the current maximum width (cols) for an [X]dialog(1) widget.
+ */
+int
+dialog_maxcols(void)
+{
+
+	if (use_xdialog && maxsize == NULL)
+		x11_maxsize_update(); /* initialize maxsize for GUI */
+	else if (!use_xdialog)
+		tty_maxsize_update(); /* update maxsize for TTY */
+
+	if (use_dialog || use_libdialog) {
+		if (use_shadow)
+			return (maxsize->ws_col - 2);
+		else
+			return (maxsize->ws_col);
+	} else
+		return (maxsize->ws_col);
+}
+
+/*
+ * Return the current maximum width (cols) for the terminal.
+ */
+int
+tty_maxcols(void)
+{
+
+	if (use_xdialog && maxsize == NULL)
+		x11_maxsize_update(); /* initialize maxsize for GUI */
+	else if (!use_xdialog)
+		tty_maxsize_update(); /* update maxsize for TTY */
+
+	return (maxsize->ws_col);
+}
+
+/*
+ * Spawn an [X]dialog(1) `--gauge' box with a `--prompt' value of init_prompt.
+ * Writes the resulting process ID to the pid_t pointed at by `pid'. Returns a
+ * file descriptor (int) suitable for writing data to the [X]dialog(1) instance
+ * (data written to the file descriptor is seen as standard-in by the spawned
+ * [X]dialog(1) process).
+ */
+int
+dialog_spawn_gauge(char *init_prompt, pid_t *pid)
+{
+	char dummy_init[2] = "";
+	char *cp;
+	int height;
+	int width;
+	int error;
+	posix_spawn_file_actions_t action;
+#if DIALOG_SPAWN_DEBUG
+	unsigned int i;
+#endif
+	unsigned int n = 0;
+	int stdin_pipe[2] = { -1, -1 };
+
+	/* Override `dialog' with a path from ENV_DIALOG if provided */
+	if ((cp = getenv(ENV_DIALOG)) != NULL)
+		snprintf(dialog, PATH_MAX, "%s", cp);
+
+	/* For Xdialog(1), set ENV_XDIALOG_HIGH_DIALOG_COMPAT */
+	setenv(ENV_XDIALOG_HIGH_DIALOG_COMPAT, "1", 1);
+
+	/* Constrain the height/width */
+	height = dialog_maxrows();
+	if (backtitle != NULL)
+		height -= use_shadow ? 5 : 4;
+	if (dheight < height)
+		height = dheight;
+	width = dialog_maxcols();
+	if (dwidth < width)
+		width = dwidth;
+
+	/* Populate argument array */
+	dargv[n++] = dialog;
+	if (title != NULL) {
+		if ((dargv[n] = malloc(8)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--title");
+		dargv[n++] = title;
+	} else {
+		if ((dargv[n] = malloc(8)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--title");
+		if ((dargv[n] = malloc(1)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		*dargv[n++] = '\0';
+	}
+	if (backtitle != NULL) {
+		if ((dargv[n] = malloc(12)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--backtitle");
+		dargv[n++] = backtitle;
+	}
+	if (use_color) {
+		if ((dargv[n] = malloc(11)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--colors");
+	}
+	if (use_xdialog) {
+		if ((dargv[n] = malloc(7)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--left");
+
+		/*
+		 * NOTE: Xdialog(1)'s `--wrap' appears to be broken for the
+		 * `--gauge' widget prompt-updates. Add it anyway (in-case it
+		 * gets fixed in some later release).
+		 */
+		if ((dargv[n] = malloc(7)) == NULL)
+			errx(EXIT_FAILURE, "Out of memory?!");
+		sprintf(dargv[n++], "--wrap");
+	}
+	if ((dargv[n] = malloc(8)) == NULL)
+		errx(EXIT_FAILURE, "Out of memory?!");
+	sprintf(dargv[n++], "--gauge");
+	dargv[n++] = use_xdialog ? dummy_init : init_prompt;
+	if ((dargv[n] = malloc(40)) == NULL)
+		errx(EXIT_FAILURE, "Out of memory?!");
+	snprintf(dargv[n++], 40, "%u", height);
+	if ((dargv[n] = malloc(40)) == NULL)
+		errx(EXIT_FAILURE, "Out of memory?!");
+	snprintf(dargv[n++], 40, "%u", width);
+	dargv[n] = NULL;
+
+	/* Open a pipe(2) to communicate with [X]dialog(1) */
+	if (pipe(stdin_pipe) < 0)
+		err(EXIT_FAILURE, "%s: pipe(2)", __func__);
+
+	/* Fork [X]dialog(1) process */
+#if DIALOG_SPAWN_DEBUG
+	fprintf(stderr, "%s: spawning `", __func__);
+	for (i = 0; i < n; i++) {
+		if (i == 0)
+			fprintf(stderr, "%s", dargv[i]);
+		else if (*dargv[i] == '-' && *(dargv[i] + 1) == '-')
+			fprintf(stderr, " %s", dargv[i]);
+		else
+			fprintf(stderr, " \"%s\"", dargv[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, dialog, &action,
+	    (const posix_spawnattr_t *)NULL, dargv, environ);
+	if (error != 0)
+		err(EXIT_FAILURE, "%s: posix_spawnp(3)", __func__);
+
+	/* NB: Do not free(3) *dargv[], else SIGSEGV */
+
+	return (stdin_pipe[1]);
+}
+
+/*
+ * Returns the number of lines in buffer pointed to by `prompt'. Takes both
+ * newlines and escaped-newlines into account.
+ */
+unsigned int
+dialog_prompt_numlines(const char *prompt, uint8_t nlstate)
+{
+	uint8_t nls = nlstate; /* See dialog_prompt_nlstate() */
+	const char *cp = prompt;
+	unsigned int nlines = 1;
+
+	if (prompt == NULL || *prompt == '\0')
+		return (0);
+
+	while (*cp != '\0') {
+		if (use_dialog) {
+			if (strncmp(cp, "\\n", 2) == 0) {
+				cp++;
+				nlines++;
+				nls = TRUE; /* See declaration comment */
+			} else if (*cp == '\n') {
+				if (!nls)
+					nlines++;
+				nls = FALSE; /* See declaration comment */
+			}
+		} else if (use_libdialog) {
+			if (*cp == '\n')
+				nlines++;
+		} else if (strncmp(cp, "\\n", 2) == 0) {
+			cp++;
+			nlines++;
+		}
+		cp++;
+	}
+
+	return (nlines);
+}
+
+/*
+ * Returns the length in bytes of the longest line in buffer pointed to by
+ * `prompt'. Takes newlines and escaped newlines into account. Also discounts
+ * dialog(1) color escape codes if enabled (via `use_color' global).
+ */
+unsigned int
+dialog_prompt_longestline(const char *prompt, uint8_t nlstate)
+{
+	uint8_t backslash = 0;
+	uint8_t nls = nlstate; /* See dialog_prompt_nlstate() */
+	const char *p = prompt;
+	int longest = 0;
+	int n = 0;
+
+	/* `prompt' parameter is required */
+	if (prompt == NULL)
+		return (0);
+	if (*prompt == '\0')
+		return (0); /* shortcut */
+
+	/* Loop until the end of the string */
+	while (*p != '\0') {
+		/* dialog(1) and dialog(3) will render literal newlines */
+		if (use_dialog || use_libdialog) {
+			if (*p == '\n') {
+				if (!use_libdialog && nls)
+					n++;
+				else {
+					if (n > longest)
+						longest = n;
+					n = 0;
+				}
+				nls = FALSE; /* See declaration comment */
+				p++;
+				continue;
+			}
+		}
+
+		/* Check for backslash character */
+		if (*p == '\\') {
+			/* If second backslash, count as a single-char */
+			if ((backslash ^= 1) == 0)
+				n++;
+		} else if (backslash) {
+			if (*p == 'n' && !use_libdialog) { /* new line */
+				/* NB: dialog(3) ignores escaped newlines */
+				nls = TRUE; /* See declaration comment */
+				if (n > longest)
+					longest = n;
+				n = 0;
+			} else if (use_color && *p == 'Z') {
+				if (*++p != '\0')
+					p++;
+				backslash = 0;
+				continue;
+			} else /* [X]dialog(1)/dialog(3) only expand those */
+				n += 2;
+
+			backslash = 0;
+		} else
+			n++;
+		p++;
+	}
+	if (n > longest)
+		longest = n;
+
+	return (longest);
+}
+
+/*
+ * Returns a pointer to the last line in buffer pointed to by `prompt'. Takes
+ * both newlines (if using dialog(1) versus Xdialog(1)) and escaped newlines
+ * into account. If no newlines (escaped or otherwise) appear in the buffer,
+ * `prompt' is returned. If passed a NULL pointer, returns NULL.
+ */
+char *
+dialog_prompt_lastline(char *prompt, uint8_t nlstate)
+{
+	uint8_t nls = nlstate; /* See dialog_prompt_nlstate() */
+	char *lastline;
+	char *p;
+
+	if (prompt == NULL)
+		return (NULL);
+	if (*prompt == '\0')
+		return (prompt); /* shortcut */
+
+	lastline = p = prompt;
+	while (*p != '\0') {
+		/* dialog(1) and dialog(3) will render literal newlines */
+		if (use_dialog || use_libdialog) {
+			if (*p == '\n') {
+				if (use_libdialog || !nls)
+					lastline = p + 1;
+				nls = FALSE; /* See declaration comment */
+			}
+		}
+		/* dialog(3) does not expand escaped newlines */
+		if (use_libdialog) {
+			p++;
+			continue;
+		}
+		if (*p == '\\' && *(p + 1) != '\0' && *(++p) == 'n') {
+			nls = TRUE; /* See declaration comment */
+			lastline = p + 1;
+		}
+		p++;
+	}
+
+	return (lastline);
+}
+
+/*
+ * Returns the number of extra lines generated by wrapping the text in buffer
+ * pointed to by `prompt' within `ncols' columns (for prompts, this should be
+ * dwidth - 4). Also discounts dialog(1) color escape codes if enabled (via
+ * `use_color' global).
+ */
+int
+dialog_prompt_wrappedlines(char *prompt, int ncols, uint8_t nlstate)
+{
+	uint8_t backslash = 0;
+	uint8_t nls = nlstate; /* See dialog_prompt_nlstate() */
+	char *cp;
+	char *p = prompt;
+	int n = 0;
+	int wlines = 0;
+
+	/* `prompt' parameter is required */
+	if (p == NULL)
+		return (0);
+	if (*p == '\0')
+		return (0); /* shortcut */
+
+	/* Loop until the end of the string */
+	while (*p != '\0') {
+		/* dialog(1) and dialog(3) will render literal newlines */
+		if (use_dialog || use_libdialog) {
+			if (*p == '\n') {
+				if (use_dialog || !nls)
+					n = 0;
+				nls = FALSE; /* See declaration comment */
+			}
+		}
+
+		/* Check for backslash character */
+		if (*p == '\\') {
+			/* If second backslash, count as a single-char */
+			if ((backslash ^= 1) == 0)
+				n++;
+		} else if (backslash) {
+			if (*p == 'n' && !use_libdialog) { /* new line */
+				/* NB: dialog(3) ignores escaped newlines */
+				nls = TRUE; /* See declaration comment */
+				n = 0;
+			} else if (use_color && *p == 'Z') {
+				if (*++p != '\0')
+					p++;
+				backslash = 0;
+				continue;
+			} else /* [X]dialog(1)/dialog(3) only expand those */
+				n += 2;
+
+			backslash = 0;
+		} else
+			n++;
+
+		/* Did we pass the width barrier? */
+		if (n > ncols) {
+			/*
+			 * Work backward to find the first whitespace on-which
+			 * dialog(1) will wrap the line (but don't go before
+			 * the start of this line).
+			 */
+			cp = p;
+			while (n > 1 && !isspace(*cp)) {
+				cp--;
+				n--;
+			}
+			if (n > 0 && isspace(*cp))
+				p = cp;
+			wlines++;
+			n = 1;
+		}
+
+		p++;
+	}
+
+	return (wlines);
+}
+
+/*
+ * Returns zero if the buffer pointed to by `prompt' contains an escaped
+ * newline but only if appearing after any/all literal newlines. This is
+ * specific to dialog(1) and does not apply to Xdialog(1).
+ *
+ * As an attempt to make shell scripts easier to read, dialog(1) will "eat"
+ * the first literal newline after an escaped newline. This however has a bug
+ * in its implementation in that rather than allowing `\\n\n' to be treated
+ * similar to `\\n' or `\n', dialog(1) expands the `\\n' and then translates
+ * the following literal newline (with or without characters between [!]) into
+ * a single space.
+ *
+ * If you want to be compatible with Xdialog(1), it is suggested that you not
+ * use literal newlines (they aren't supported); but if you have to use them,
+ * go right ahead. But be forewarned... if you set $DIALOG in your environment
+ * to something other than `cdialog' (our current dialog(1)), then it should
+ * do the same thing w/respect to how to handle a literal newline after an
+ * escaped newline (you could do no wrong by translating every literal newline
+ * into a space but only when you've previously encountered an escaped one;
+ * this is what dialog(1) is doing).
+ *
+ * The ``newline state'' (or nlstate for short; as I'm calling it) is helpful
+ * if you plan to combine multiple strings into a single prompt text. In lead-
+ * up to this procedure, a common task is to calculate and utilize the widths
+ * and heights of each piece of prompt text to later be combined. However, if
+ * (for example) the first string ends in a positive newline state (has an
+ * escaped newline without trailing literal), the first literal newline in the
+ * second string will be mangled.
+ *
+ * The return value of this function should be used as the `nlstate' argument
+ * to dialog_*() functions that require it to allow accurate calculations in
+ * the event such information is needed.
+ */
+uint8_t
+dialog_prompt_nlstate(const char *prompt)
+{
+	const char *cp;
+
+	if (prompt == NULL)
+		return 0;
+
+	/*
+	 * Work our way backward from the end of the string for efficiency.
+	 */
+	cp = prompt + strlen(prompt);
+	while (--cp >= prompt) {
+		/*
+		 * If we get to a literal newline first, this prompt ends in a
+		 * clean state for rendering with dialog(1). Otherwise, if we
+		 * get to an escaped newline first, this prompt ends in an un-
+		 * clean state (following literal will be mangled; see above).
+		 */
+		if (*cp == '\n')
+			return (0);
+		else if (*cp == 'n' && --cp > prompt && *cp == '\\')
+			return (1);
+	}
+
+	return (0); /* no newlines (escaped or otherwise) */
+}
+
+/*
+ * Free allocated items initialized by tty_maxsize_update() and
+ * x11_maxsize_update()
+ */
+void
+dialog_maxsize_free(void)
+{
+	if (maxsize != NULL) {
+		free(maxsize);
+		maxsize = NULL;
+	}
+}


Property changes on: trunk/lib/libdpv/dialog_util.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dialog_util.h
===================================================================
--- trunk/lib/libdpv/dialog_util.h	                        (rev 0)
+++ trunk/lib/libdpv/dialog_util.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/dialog_util.h 295107 2016-02-01 00:44:29Z dteske $
+ */
+
+#ifndef _DIALOG_UTIL_H_
+#define _DIALOG_UTIL_H_
+
+#include <sys/types.h>
+
+#include "dialogrc.h"
+
+#define DIALOG_SPAWN_DEBUG	0	/* Debug spawning of [X]dialog(1) */
+
+/* dialog(3) and [X]dialog(1) characteristics */
+#define DIALOG		"dialog"
+#define XDIALOG		"Xdialog"
+#define PROMPT_MAX	16384
+#define ENV_DIALOG	"DIALOG"
+#define ENV_USE_COLOR	"USE_COLOR"
+#define ENV_XDIALOG_HIGH_DIALOG_COMPAT	"XDIALOG_HIGH_DIALOG_COMPAT"
+extern uint8_t dialog_test;
+extern uint8_t use_libdialog;
+extern uint8_t use_dialog;
+extern uint8_t use_xdialog;
+extern uint8_t use_color;
+extern char dialog[];
+
+/* dialog(3) and [X]dialog(1) functionality */
+extern char *title, *backtitle;
+extern int dheight, dwidth;
+
+__BEGIN_DECLS
+uint8_t		 dialog_prompt_nlstate(const char *_prompt);
+void		 dialog_maxsize_free(void);
+char		*dialog_prompt_lastline(char *_prompt, uint8_t _nlstate);
+int		 dialog_maxcols(void);
+int		 dialog_maxrows(void);
+int		 dialog_prompt_wrappedlines(char *_prompt, int _ncols,
+		    uint8_t _nlstate);
+int		 dialog_spawn_gauge(char *_init_prompt, pid_t *_pid);
+int		 tty_maxcols(void);
+#define		 tty_maxrows() dialog_maxrows()
+unsigned int	 dialog_prompt_longestline(const char *_prompt,
+		    uint8_t _nlstate);
+unsigned int	 dialog_prompt_numlines(const char *_prompt, uint8_t _nlstate);
+__END_DECLS
+
+#endif /* !_DIALOG_UTIL_H_ */


Property changes on: trunk/lib/libdpv/dialog_util.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dialogrc.c
===================================================================
--- trunk/lib/libdpv/dialogrc.c	                        (rev 0)
+++ trunk/lib/libdpv/dialogrc.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,361 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2015 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/dialogrc.c 293619 2016-01-09 23:33:44Z dteske $");
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <figpar.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_m.h>
+
+#include "dialogrc.h"
+
+#define STR_BUFSIZE 255
+
+/* dialog(1) `.dialogrc' characteristics */
+uint8_t use_colors = 1;
+uint8_t use_shadow = 1;
+char gauge_color[STR_BUFSIZE]	= "47b"; /* (BLUE,WHITE,ON) */
+char separator[STR_BUFSIZE]	= "";
+
+/* Function prototypes */
+static int setattr(struct figpar_config *, uint32_t, char *, char *);
+static int setbool(struct figpar_config *, uint32_t, char *, char *);
+static int setnum(struct figpar_config *, uint32_t, char *, char *);
+static int setstr(struct figpar_config *, uint32_t, char *, char *);
+
+/*
+ * Anatomy of DIALOGRC (~/.dialogrc by default)
+ * NOTE: Must appear after private function prototypes (above)
+ * NB: Brace-initialization of union requires cast to *first* member of union
+ */
+static struct figpar_config dialogrc_config[] = {
+    /* TYPE            DIRECTIVE                      DEFAULT        HANDLER */
+    {FIGPAR_TYPE_INT,  "aspect",                      {(void *)0},   &setnum},
+    {FIGPAR_TYPE_STR,  "separate_widget",             {separator},   &setstr},
+    {FIGPAR_TYPE_INT,  "tab_len",                     {(void *)0},   &setnum},
+    {FIGPAR_TYPE_BOOL, "visit_items",                 {(void *)0},   &setbool},
+    {FIGPAR_TYPE_BOOL, "use_shadow",                  {(void *)1},   &setbool},
+    {FIGPAR_TYPE_BOOL, "use_colors",                  {(void *)1},   &setbool},
+    {FIGPAR_TYPE_STR,  "screen_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "shadow_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "dialog_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "title_color",                 {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "border_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_active_color",         {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_inactive_color",       {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_key_active_color",     {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_key_inactive_color",   {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_label_active_color",   {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "button_label_inactive_color", {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "inputbox_color",              {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "inputbox_border_color",       {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "searchbox_color",             {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "searchbox_title_color",       {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "searchbox_border_color",      {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "position_indicator_color",    {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "menubox_color",               {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "menubox_border_color",        {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "item_color",                  {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "item_selected_color",         {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "tag_color",                   {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "tag_selected_color",          {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "tag_key_color",               {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "tag_key_selected_color",      {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "check_color",                 {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "check_selected_color",        {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "uarrow_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "darrow_color",                {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "itemhelp_color",              {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "form_active_text_color",      {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "form_text_color",             {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "form_item_readonly_color",    {NULL},        &setattr},
+    {FIGPAR_TYPE_STR,  "gauge_color",                 {gauge_color}, &setattr},
+    {0, NULL, {0}, NULL}
+};
+
+/*
+ * figpar call-back for interpreting value as .dialogrc `Attribute'
+ */
+static int
+setattr(struct figpar_config *option, uint32_t line __unused,
+    char *directive __unused, char *value)
+{
+	char *cp = value;
+	char *val;
+	size_t len;
+	char attrbuf[4];
+
+	if (option == NULL) {
+		warnx("%s:%d:%s: Missing callback parameter", __FILE__,
+		    __LINE__, __func__);
+		return (-1); /* Abort processing */
+	}
+
+	/* Allocate memory for the data if not already done */
+	if (option->value.str == NULL) {
+		if ((option->value.str = malloc(STR_BUFSIZE)) == NULL)
+			return (-1);
+	}
+
+	/*
+	 * If the first character is left-parenthesis, the format is
+	 * `(background,foreground,highlight)' otherwise, we should take it
+	 * as a reference to another color.
+	 */
+	if (*cp != '(') {
+		/* Copy the [current] value from the referenced color */
+		val = dialogrc_config_option(cp)->value.str;
+		if (val != NULL)
+			snprintf(option->value.str, STR_BUFSIZE, "%s", val);
+
+		return (0);
+	} else
+		cp++;
+
+	strtolower(cp);
+
+	/* Initialize the attrbuf (fg,bg,hi,NUL) */
+	attrbuf[0] = '0';
+	attrbuf[1] = '0';
+	attrbuf[2] = 'B'; /* \ZB = disable; \Zb = enable (see dialog(1)) */
+	attrbuf[3] = '\0';
+
+	/* Interpret the foreground color */
+	if      (strncmp(cp, "red,",     4) == 0) attrbuf[0] = '1';
+	else if (strncmp(cp, "green,",   6) == 0) attrbuf[0] = '2';
+	else if (strncmp(cp, "yellow,",  7) == 0) attrbuf[0] = '3';
+	else if (strncmp(cp, "blue,",    5) == 0) attrbuf[0] = '4';
+	else if (strncmp(cp, "magenta,", 8) == 0) attrbuf[0] = '5';
+	else if (strncmp(cp, "cyan,",    5) == 0) attrbuf[0] = '6';
+	else if (strncmp(cp, "white,",   6) == 0) attrbuf[0] = '7';
+	else if (strncmp(cp, "black,",   6) == 0) attrbuf[0] = '8';
+
+	/* Advance to the background color */
+	cp = strchr(cp, ',');
+	if (cp == NULL)
+		goto write_attrbuf;
+	else
+		cp++;
+
+	/* Interpret the background color */
+	if      (strncmp(cp, "red,",     4) == 0) attrbuf[1] = '1';
+	else if (strncmp(cp, "green,",   6) == 0) attrbuf[1] = '2';
+	else if (strncmp(cp, "yellow,",  7) == 0) attrbuf[1] = '3';
+	else if (strncmp(cp, "blue,",    5) == 0) attrbuf[1] = '4';
+	else if (strncmp(cp, "magenta,", 8) == 0) attrbuf[1] = '5';
+	else if (strncmp(cp, "cyan,",    5) == 0) attrbuf[1] = '6';
+	else if (strncmp(cp, "white,",   6) == 0) attrbuf[1] = '7';
+	else if (strncmp(cp, "black,",   6) == 0) attrbuf[1] = '8';
+
+	/* Advance to the highlight */
+	cp = strchr(cp, ',');
+	if (cp == NULL)
+		goto write_attrbuf;
+	else
+		cp++;
+
+	/* Trim trailing parenthesis */
+	len = strlen(cp);
+	if (cp[len - 1] == ')')
+		cp[len - 1] = '\0';
+
+	/* Interpret the highlight (initialized to off above) */
+	if (strcmp(cp, "on") == 0 || strncmp(cp, "on,", 3) == 0)
+		attrbuf[2] = 'b'; /* \Zb = enable bold (see dialog(1)) */
+
+write_attrbuf:
+	sprintf(option->value.str, "%s", attrbuf);
+
+	return (0);
+}
+
+/*
+ * figpar call-back for interpreting value as .dialogrc `Boolean'
+ */
+static int
+setbool(struct figpar_config *option, uint32_t line __unused,
+    char *directive __unused, char *value)
+{
+
+	if (option == NULL) {
+		warnx("%s:%d:%s: Missing callback parameter", __FILE__,
+		    __LINE__, __func__);
+		return (-1); /* Abort processing */
+	}
+
+	/* Assume ON, check for OFF (case-insensitive) */
+	option->value.boolean = 1;
+	strtolower(value);
+	if (strcmp(value, "off") == 0)
+		option->value.boolean = 0;
+
+	return (0);
+}
+
+/*
+ * figpar call-back for interpreting value as .dialogrc `Number'
+ */
+static int
+setnum(struct figpar_config *option, uint32_t line __unused,
+    char *directive __unused, char *value)
+{
+
+	if (option == NULL) {
+		warnx("%s:%d:%s: Missing callback parameter", __FILE__,
+		    __LINE__, __func__);
+		return (-1); /* Abort processing */
+	}
+
+	/* Convert the string to a 32-bit signed integer */
+	option->value.num = (int32_t)strtol(value, (char **)NULL, 10);
+
+	return (0);
+}
+
+/*
+ * figpar call-back for interpreting value as .dialogrc `String'
+ */
+static int
+setstr(struct figpar_config *option, uint32_t line __unused,
+    char *directive __unused, char *value)
+{
+	size_t len;
+
+	if (option == NULL) {
+		warnx("%s:%d:%s: Missing callback parameter", __FILE__,
+		    __LINE__, __func__);
+		return (-1); /* Abort processing */
+	}
+
+	/* Allocate memory for the data if not already done */
+	if (option->value.str == NULL) {
+		if ((option->value.str = malloc(STR_BUFSIZE)) == NULL)
+			return (-1);
+	}
+
+	/* Trim leading quote */
+	if (*value == '"')
+		value++;
+
+	/* Write the data into the buffer */
+	snprintf(option->value.str, STR_BUFSIZE, "%s", value);
+
+	/* Trim trailing quote */
+	len = strlen(option->value.str);
+	if (option->value.str[len - 1] == '"')
+		option->value.str[len - 1] = '\0';
+
+	return (0);
+}
+
+/*
+ * Parse (in order of preference) $DIALOGRC or `$HOME/.dialogrc'. Returns zero
+ * on success, -1 on failure (and errno should be consulted).
+ */
+int
+parse_dialogrc(void)
+{
+	char *cp;
+	int res;
+	size_t len;
+	char path[PATH_MAX];
+
+	/* Allow $DIALOGRC to override `$HOME/.dialogrc' default */
+	if ((cp = getenv(ENV_DIALOGRC)) != NULL && *cp != '\0')
+		snprintf(path, PATH_MAX, "%s", cp);
+	else if ((cp = getenv(ENV_HOME)) != NULL) {
+		/* Copy $HOME into buffer and append trailing `/' if missing */
+		snprintf(path, PATH_MAX, "%s", cp);
+		len = strlen(path);
+		cp = path + len;
+		if (len > 0 && len < (PATH_MAX - 1) && *(cp - 1) != '/') {
+			*cp++ = '/';
+			*cp = '\0';
+			len++;
+		}
+
+		/* If we still have room, shove in the name of rc file */
+		if (len < (PATH_MAX - 1))
+			snprintf(cp, PATH_MAX - len, "%s", DIALOGRC);
+	} else {
+		/* Like dialog(1), don't process a file if $HOME is unset */
+		errno = ENOENT;
+		return (-1);
+	}
+
+	/* Process file (either $DIALOGRC if set, or `$HOME/.dialogrc') */
+	res = parse_config(dialogrc_config,
+		path, NULL, FIGPAR_BREAK_ON_EQUALS);
+
+	/* Set some globals based on what we parsed */
+	use_shadow = dialogrc_config_option("use_shadow")->value.boolean;
+	use_colors = dialogrc_config_option("use_colors")->value.boolean;
+	snprintf(gauge_color, STR_BUFSIZE, "%s",
+	    dialogrc_config_option("gauge_color")->value.str);
+
+	return (res);
+}
+
+/*
+ * Return a pointer to the `.dialogrc' config option specific to `directive' or
+ * static figpar_dummy_config (full of NULLs) if none found (see
+ * get_config_option(3); part of figpar(3)).
+ */
+struct figpar_config *
+dialogrc_config_option(const char *directive)
+{
+	return (get_config_option(dialogrc_config, directive));
+}
+
+/*
+ * Free allocated items initialized by setattr() (via parse_config() callback
+ * matrix [dialogrc_config] used in parse_dialogrc() above).
+ */
+void
+dialogrc_free(void)
+{
+	char *value;
+	uint32_t n;
+
+	for (n = 0; dialogrc_config[n].directive != NULL; n++) {
+		if (dialogrc_config[n].action != &setattr)
+			continue;
+		value = dialogrc_config[n].value.str;
+		if (value != NULL && value != gauge_color) {
+			free(dialogrc_config[n].value.str);
+			dialogrc_config[n].value.str = NULL;
+		}
+	}
+}


Property changes on: trunk/lib/libdpv/dialogrc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dialogrc.h
===================================================================
--- trunk/lib/libdpv/dialogrc.h	                        (rev 0)
+++ trunk/lib/libdpv/dialogrc.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2015 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/dialogrc.h 293619 2016-01-09 23:33:44Z dteske $
+ */
+
+#ifndef _DIALOGRC_H_
+#define _DIALOGRC_H_
+
+#include <sys/types.h>
+
+#include <figpar.h>
+
+/* dialog(3) dlg_color_table[] attributes */
+#define GAUGE_ATTR	33	/* entry used for gauge_color */
+
+/* dialog(1) characteristics */
+#define DIALOGRC	".dialogrc"
+#define ENV_DIALOGRC	"DIALOGRC"
+#define ENV_HOME	"HOME"
+
+/* dialog(1) `.dialogrc' characteristics */
+extern uint8_t use_colors;
+extern uint8_t use_shadow;
+extern char gauge_color[];
+extern char separator[];
+
+__BEGIN_DECLS
+void			 dialogrc_free(void);
+int			 parse_dialogrc(void);
+struct figpar_config	*dialogrc_config_option(const char *_directive);
+__END_DECLS
+
+#endif /* !_DIALOGRC_H_ */


Property changes on: trunk/lib/libdpv/dialogrc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dprompt.c
===================================================================
--- trunk/lib/libdpv/dprompt.c	                        (rev 0)
+++ trunk/lib/libdpv/dprompt.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,768 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/dprompt.c 284714 2015-06-23 04:03:54Z dteske $");
+
+#include <sys/types.h>
+
+#define _BSD_SOURCE /* to get dprintf() prototype in stdio.h below */
+#include <dialog.h>
+#include <err.h>
+#include <libutil.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_m.h>
+#include <unistd.h>
+
+#include "dialog_util.h"
+#include "dialogrc.h"
+#include "dprompt.h"
+#include "dpv.h"
+#include "dpv_private.h"
+
+#define FLABEL_MAX 1024
+
+static int fheight = 0; /* initialized by dprompt_init() */
+static char dprompt[PROMPT_MAX + 1] = "";
+static char *dprompt_pos = (char *)(0); /* treated numerically */
+
+/* Display characteristics */
+#define FM_DONE 0x01
+#define FM_FAIL 0x02
+#define FM_PEND 0x04
+static uint8_t dprompt_free_mask;
+static char *done = NULL;
+static char *fail = NULL;
+static char *pend = NULL;
+int display_limit = DISPLAY_LIMIT_DEFAULT;	/* Max entries to show */
+int label_size    = LABEL_SIZE_DEFAULT;		/* Max width for labels */
+int pbar_size     = PBAR_SIZE_DEFAULT;		/* Mini-progressbar size */
+static int gauge_percent = 0;
+static int done_size, done_lsize, done_rsize;
+static int fail_size, fail_lsize, fail_rsize;
+static int mesg_size, mesg_lsize, mesg_rsize;
+static int pend_size, pend_lsize, pend_rsize;
+static int pct_lsize, pct_rsize;
+static void *gauge = NULL;
+#define SPIN_SIZE 4
+static char spin[SPIN_SIZE + 1] = "/-\\|";
+static char msg[PROMPT_MAX + 1];
+static char *spin_cp = spin;
+
+/* Function prototypes */
+static char	spin_char(void);
+static int	dprompt_add_files(struct dpv_file_node *file_list,
+		    struct dpv_file_node *curfile, int pct);
+
+/*
+ * Returns a pointer to the current spin character in the spin string and
+ * advances the global position to the next character for the next call.
+ */
+static char
+spin_char(void)
+{
+	char ch;
+
+	if (spin_cp == '\0')
+		spin_cp = spin;
+	ch = *spin_cp;
+
+	/* Advance the spinner to the next char */
+	if (++spin_cp >= (spin + SPIN_SIZE))
+		spin_cp = spin;
+
+	return (ch);
+}
+
+/*
+ * Initialize heights and widths based on various strings and environment
+ * variables (such as ENV_USE_COLOR).
+ */
+void
+dprompt_init(struct dpv_file_node *file_list)
+{
+	uint8_t nls = 0;
+	int len;
+	int max_cols;
+	int max_rows;
+	int nthfile;
+	int numlines;
+	struct dpv_file_node *curfile;
+
+	/*
+	 * Initialize dialog(3) `colors' support and draw backtitle
+	 */
+	if (use_libdialog && !debug) {
+		init_dialog(stdin, stdout);
+		dialog_vars.colors = 1;
+		if (backtitle != NULL) {
+			dialog_vars.backtitle = (char *)backtitle;
+			dlg_put_backtitle();
+		}
+	}
+
+	/* Calculate width of dialog(3) or [X]dialog(1) --gauge box */
+	dwidth = label_size + pbar_size + 9;
+
+	/*
+	 * Calculate height of dialog(3) or [X]dialog(1) --gauge box
+	 */
+	dheight = 5;
+	max_rows = dialog_maxrows();
+	/* adjust max_rows for backtitle and/or dialog(3) statusLine */
+	if (backtitle != NULL)
+		max_rows -= use_shadow ? 3 : 2;
+	if (use_libdialog && use_shadow)
+		max_rows -= 2;
+	/* add lines for `-p text' */
+	numlines = dialog_prompt_numlines(pprompt, 0);
+	if (debug)
+		warnx("`-p text' is %i line%s long", numlines,
+		    numlines == 1 ? "" : "s");
+	dheight += numlines;
+	/* adjust dheight for various implementations */
+	if (use_dialog) {
+		dheight -= dialog_prompt_nlstate(pprompt);
+		nls = dialog_prompt_nlstate(pprompt);
+	} else if (use_xdialog) {
+		if (pprompt == NULL || *pprompt == '\0')
+			dheight++;
+	} else if (use_libdialog) {
+		if (pprompt != NULL && *pprompt != '\0')
+			dheight--;
+	}
+	/* limit the number of display items (necessary per dialog(1,3)) */
+	if (display_limit == 0 || display_limit > DPV_DISPLAY_LIMIT)
+		display_limit = DPV_DISPLAY_LIMIT;
+	/* verify fheight will fit (stop if we hit 1) */
+	for (; display_limit > 0; display_limit--) {
+		nthfile = numlines = 0;
+		fheight = (int)dpv_nfiles > display_limit ?
+		    (unsigned int)display_limit : dpv_nfiles;
+		for (curfile = file_list; curfile != NULL;
+		    curfile = curfile->next) {
+			nthfile++;
+			numlines += dialog_prompt_numlines(curfile->name, nls);
+			if ((nthfile % display_limit) == 0) {
+				if (numlines > fheight)
+					fheight = numlines;
+				numlines = nthfile = 0;
+			}
+		}
+		if (numlines > fheight)
+			fheight = numlines;
+		if ((dheight + fheight +
+		    (int)dialog_prompt_numlines(aprompt, use_dialog) -
+		    (use_dialog ? (int)dialog_prompt_nlstate(aprompt) : 0))
+		    <= max_rows)
+			break;	
+	}
+	/* don't show any items if we run the risk of hitting a blank set */
+	if ((max_rows - (use_shadow ? 5 : 4)) >= fheight)
+		dheight += fheight;
+	else
+		fheight = 0;
+	/* add lines for `-a text' */
+	numlines = dialog_prompt_numlines(aprompt, use_dialog);
+	if (debug)
+		warnx("`-a text' is %i line%s long", numlines,
+		    numlines == 1 ? "" : "s");
+	dheight += numlines;
+
+	/* If using Xdialog(1), adjust accordingly (based on testing) */
+	if (use_xdialog)
+		dheight += dheight / 4;
+
+	/* For wide mode, long prefix (`pprompt') or append (`aprompt')
+	 * strings will bump width */
+	if (wide) {
+		len = (int)dialog_prompt_longestline(pprompt, 0); /* !nls */
+		if ((len + 4) > dwidth)
+			dwidth = len + 4;
+		len = (int)dialog_prompt_longestline(aprompt, 1); /* nls */
+		if ((len + 4) > dwidth)
+			dwidth = len + 4;
+	}
+
+	/* Enforce width constraints to maximum values */
+	max_cols = dialog_maxcols();
+	if (max_cols > 0 && dwidth > max_cols)
+		dwidth = max_cols;
+
+	/* Optimize widths to sane values*/
+	if (pbar_size > dwidth - 9) {
+		pbar_size = dwidth - 9;
+		label_size = 0;
+		/* -9 = "|  - [" ... "] |" */
+	}
+	if (pbar_size < 0)
+		label_size = dwidth - 8;
+		/* -8 = "|  " ... " -  |" */
+	else if (label_size > (dwidth - pbar_size - 9) || wide)
+		label_size = no_labels ? 0 : dwidth - pbar_size - 9;
+		/* -9 = "| " ... " - [" ... "] |" */
+
+	/* Hide labels if requested */
+	if (no_labels)
+		label_size = 0;
+
+	/* Touch up the height (now that we know dwidth) */
+	dheight += dialog_prompt_wrappedlines(pprompt, dwidth - 4, 0);
+	dheight += dialog_prompt_wrappedlines(aprompt, dwidth - 4, 1);
+
+	if (debug)
+		warnx("dheight = %i dwidth = %i fheight = %i",
+		    dheight, dwidth, fheight);
+
+	/* Calculate left/right portions of % */
+	pct_lsize = (pbar_size - 4) / 2; /* -4 == printf("%-3s%%", pct) */
+	pct_rsize = pct_lsize;
+	/* If not evenly divisible by 2, increment the right-side */
+	if ((pct_rsize + pct_rsize + 4) != pbar_size)
+		pct_rsize++;
+
+	/* Initialize "Done" text */
+	if (done == NULL && (done = msg_done) == NULL) {
+		if ((done = getenv(ENV_MSG_DONE)) != NULL)
+			done_size = strlen(done);
+		else {
+			done_size = strlen(DPV_DONE_DEFAULT);
+			if ((done = malloc(done_size + 1)) == NULL)
+				errx(EXIT_FAILURE, "Out of memory?!");
+			dprompt_free_mask |= FM_DONE;
+			snprintf(done, done_size + 1, DPV_DONE_DEFAULT);
+		}
+	}
+	if (pbar_size < done_size) {
+		done_lsize = done_rsize = 0;
+		*(done + pbar_size) = '\0';
+		done_size = pbar_size;
+	} else {
+		/* Calculate left/right portions for mini-progressbar */
+		done_lsize = (pbar_size - done_size) / 2;
+		done_rsize = done_lsize;
+		/* If not evenly divisible by 2, increment the right-side */
+		if ((done_rsize + done_size + done_lsize) != pbar_size)
+			done_rsize++;
+	}
+
+	/* Initialize "Fail" text */
+	if (fail == NULL && (fail = msg_fail) == NULL) {
+		if ((fail = getenv(ENV_MSG_FAIL)) != NULL)
+			fail_size = strlen(fail);
+		else {
+			fail_size = strlen(DPV_FAIL_DEFAULT);
+			if ((fail = malloc(fail_size + 1)) == NULL)
+				errx(EXIT_FAILURE, "Out of memory?!");
+			dprompt_free_mask |= FM_FAIL;
+			snprintf(fail, fail_size + 1, DPV_FAIL_DEFAULT);
+		}
+	}
+	if (pbar_size < fail_size) {
+		fail_lsize = fail_rsize = 0;
+		*(fail + pbar_size) = '\0';
+		fail_size = pbar_size;
+	} else {
+		/* Calculate left/right portions for mini-progressbar */
+		fail_lsize = (pbar_size - fail_size) / 2;
+		fail_rsize = fail_lsize;
+		/* If not evenly divisible by 2, increment the right-side */
+		if ((fail_rsize + fail_size + fail_lsize) != pbar_size)
+			fail_rsize++;
+	}
+
+	/* Initialize "Pending" text */
+	if (pend == NULL && (pend = msg_pending) == NULL) {
+		if ((pend = getenv(ENV_MSG_PENDING)) != NULL)
+			pend_size = strlen(pend);
+		else {
+			pend_size = strlen(DPV_PENDING_DEFAULT);
+			if ((pend = malloc(pend_size + 1)) == NULL)
+				errx(EXIT_FAILURE, "Out of memory?!");
+			dprompt_free_mask |= FM_PEND;
+			snprintf(pend, pend_size + 1, DPV_PENDING_DEFAULT);
+		}
+	}
+	if (pbar_size < pend_size) {
+		pend_lsize = pend_rsize = 0;
+		*(pend + pbar_size) = '\0';
+		pend_size = pbar_size;
+	} else {
+		/* Calculate left/right portions for mini-progressbar */
+		pend_lsize = (pbar_size - pend_size) / 2;
+		pend_rsize = pend_lsize;
+		/* If not evenly divisible by 2, increment the right-side */
+		if ((pend_rsize + pend_lsize + pend_size) != pbar_size)
+			pend_rsize++;
+	}
+
+	if (debug)
+		warnx("label_size = %i pbar_size = %i", label_size, pbar_size);
+
+	dprompt_clear();
+}
+
+/*
+ * Clear the [X]dialog(1) `--gauge' prompt buffer.
+ */
+void
+dprompt_clear(void)
+{
+
+	*dprompt = '\0';
+	dprompt_pos = dprompt;
+}
+
+/*
+ * Append to the [X]dialog(1) `--gauge' prompt buffer. Syntax is like printf(3)
+ * and returns the number of bytes appended to the buffer.
+ */
+int
+dprompt_add(const char *format, ...)
+{
+	int len;
+	va_list ap;
+
+	if (dprompt_pos >= (dprompt + PROMPT_MAX))
+		return (0);
+
+	va_start(ap, format);
+	len = vsnprintf(dprompt_pos, (size_t)(PROMPT_MAX -
+	    (dprompt_pos - dprompt)), format, ap);
+	va_end(ap);
+	if (len == -1)
+		errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow",
+		    __func__);
+
+	if ((dprompt_pos + len) < (dprompt + PROMPT_MAX))
+		dprompt_pos += len;
+	else
+		dprompt_pos = dprompt + PROMPT_MAX;
+
+	return (len);
+}
+
+/*
+ * Append active files to the [X]dialog(1) `--gauge' prompt buffer. Syntax
+ * requires a pointer to the head of the dpv_file_node linked-list. Returns the
+ * number of files processed successfully.
+ */
+static int
+dprompt_add_files(struct dpv_file_node *file_list,
+    struct dpv_file_node *curfile, int pct)
+{
+	char c;
+	char bold_code = 'b'; /* default: enabled */
+	char color_code = '4'; /* default: blue */
+	uint8_t after_curfile = curfile != NULL ? FALSE : TRUE;
+	uint8_t nls = 0;
+	char *cp;
+	char *lastline;
+	char *name;
+	const char *bg_code;
+	const char *estext;
+	const char *format;
+	enum dprompt_state dstate;
+	int estext_lsize;
+	int estext_rsize;
+	int flabel_size;
+	int hlen;
+	int lsize;
+	int nlines = 0;
+	int nthfile = 0;
+	int pwidth;
+	int rsize;
+	struct dpv_file_node *fp;
+	char flabel[FLABEL_MAX + 1];
+	char human[32];
+	char pbar[pbar_size + 16]; /* +15 for optional color */
+	char pbar_cap[sizeof(pbar)];
+	char pbar_fill[sizeof(pbar)];
+
+
+	/* Override color defaults with that of main progress bar */
+	if (use_colors || use_shadow) { /* NB: shadow enables color */
+		color_code = gauge_color[0];
+		/* NB: str[1] aka bg is unused */
+		bold_code = gauge_color[2];
+	}
+
+	/*
+	 * Create mini-progressbar for current file (if applicable)
+	 */
+	*pbar = '\0';
+	if (pbar_size >= 0 && pct >= 0 && curfile != NULL &&
+	    (curfile->length >= 0 || dialog_test)) {
+		snprintf(pbar, pbar_size + 1, "%*s%3u%%%*s", pct_lsize, "",
+		    pct, pct_rsize, "");
+		if (use_color) {
+			/* Calculate the fill-width of progressbar */
+			pwidth = pct * pbar_size / 100;
+			/* Round up based on one-tenth of a percent */
+			if ((pct * pbar_size % 100) > 50)
+				pwidth++;
+
+			/*
+			 * Make two copies of pbar. Make one represent the fill
+			 * and the other the remainder (cap). We'll insert the
+			 * ANSI delimiter in between.
+			 */
+			*pbar_fill = '\0';
+			*pbar_cap = '\0';
+			strncat(pbar_fill, (const char *)(pbar), dwidth);
+			*(pbar_fill + pwidth) = '\0';
+			strncat(pbar_cap, (const char *)(pbar+pwidth), dwidth);
+
+			/* Finalize the mini [color] progressbar */
+			snprintf(pbar, sizeof(pbar),
+			    "\\Z%c\\Zr\\Z%c%s%s%s\\Zn", bold_code, color_code,
+			    pbar_fill, "\\ZR", pbar_cap);
+		}
+	}
+
+	for (fp = file_list; fp != NULL; fp = fp->next) {
+		flabel_size = label_size;
+		name = fp->name;
+		nthfile++;
+
+		/*
+		 * Support multiline filenames (where the filename is taken as
+		 * the last line and the text leading up to the last line can
+		 * be used as (for example) a heading/separator between files.
+		 */
+		if (use_dialog)
+			nls = dialog_prompt_nlstate(pprompt);
+		nlines += dialog_prompt_numlines(name, nls);
+		lastline = dialog_prompt_lastline(name, 1);
+		if (name != lastline) {
+			c = *lastline;
+			*lastline = '\0';
+			dprompt_add("%s", name);
+			*lastline = c;
+			name = lastline;
+		}
+
+		/* Support color codes (for dialog(1,3)) in file names */
+		if ((use_dialog || use_libdialog) && use_color) {
+			cp = name;
+			while (*cp != '\0') {
+				if (*cp == '\\' && *(cp + 1) != '\0' &&
+				    *(++cp) == 'Z' && *(cp + 1) != '\0') {
+					cp++;
+					flabel_size += 3;
+				}
+				cp++;
+			}
+			if (flabel_size > FLABEL_MAX)
+				flabel_size = FLABEL_MAX;
+		}
+
+		/* If no mini-progressbar, increase label width */
+		if (pbar_size < 0 && flabel_size <= FLABEL_MAX - 2 &&
+		    no_labels == FALSE)
+			flabel_size += 2;
+
+		/* If name is too long, add an ellipsis */
+		if (snprintf(flabel, flabel_size + 1, "%s", name) >
+		    flabel_size) sprintf(flabel + flabel_size - 3, "...");
+
+		/*
+		 * Append the label (processing the current file differently)
+		 */
+		if (fp == curfile && pct < 100) {
+			/*
+			 * Add an ellipsis to current file name if it will fit.
+			 * There may be an ellipsis already from truncating the
+			 * label (in which case, we already have one).
+			 */
+			cp = flabel + strlen(flabel);
+			if (cp < (flabel + flabel_size))
+				snprintf(cp, flabel_size -
+				    (cp - flabel) + 1, "...");
+
+			/* Append label (with spinner and optional color) */
+			dprompt_add("%s%-*s%s %c", use_color ? "\\Zb" : "",
+			    flabel_size, flabel, use_color ? "\\Zn" : "",
+			    spin_char());
+		} else
+			dprompt_add("%-*s%s %s", flabel_size,
+			    flabel, use_color ? "\\Zn" : "", " ");
+
+		/*
+		 * Append pbar/status (processing the current file differently)
+		 */
+		dstate = DPROMPT_NONE;
+		if (fp->msg != NULL)
+			dstate = DPROMPT_CUSTOM_MSG;
+		else if (pbar_size < 0)
+			dstate = DPROMPT_NONE;
+		else if (pbar_size < 4)
+			dstate = DPROMPT_MINIMAL;
+		else if (after_curfile)
+			dstate = DPROMPT_PENDING;
+		else if (fp == curfile) {
+			if (*pbar == '\0') {
+				if (fp->length < 0)
+					dstate = DPROMPT_DETAILS;
+				else if (fp->status == DPV_STATUS_RUNNING)
+					dstate = DPROMPT_DETAILS;
+				else
+					dstate = DPROMPT_END_STATE;
+			}
+			else if (dialog_test) /* status/length ignored */
+				dstate = pct < 100 ?
+				    DPROMPT_PBAR : DPROMPT_END_STATE;
+			else if (fp->status == DPV_STATUS_RUNNING)
+				dstate = fp->length < 0 ?
+				    DPROMPT_DETAILS : DPROMPT_PBAR;
+			else /* not running */
+				dstate = fp->length < 0 ?
+				    DPROMPT_DETAILS : DPROMPT_END_STATE;
+		} else { /* before curfile */
+			if (dialog_test)
+				dstate = DPROMPT_END_STATE;
+			else
+				dstate = fp->length < 0 ?
+				    DPROMPT_DETAILS : DPROMPT_END_STATE;
+		}
+		format = use_color ?
+		    " [\\Z%c%s%-*s%s%-*s\\Zn]\\n" :
+		    " [%-*s%s%-*s]\\n";
+		if (fp->status == DPV_STATUS_FAILED) {
+			bg_code = "\\Zr\\Z1"; /* Red */
+			estext_lsize = fail_lsize;
+			estext_rsize = fail_rsize;
+			estext = fail;
+		} else { /* e.g., DPV_STATUS_DONE */
+			bg_code = "\\Zr\\Z2"; /* Green */
+			estext_lsize = done_lsize;
+			estext_rsize = done_rsize;
+			estext = done;
+		}
+		switch (dstate) {
+		case DPROMPT_PENDING: /* Future file(s) */
+			dprompt_add(" [%-*s%s%-*s]\\n",
+			    pend_lsize, "", pend, pend_rsize, "");
+			break;
+		case DPROMPT_PBAR: /* Current file */
+			dprompt_add(" [%s]\\n", pbar);
+			break;
+		case DPROMPT_END_STATE: /* Past/Current file(s) */
+			if (use_color)
+				dprompt_add(format, bold_code, bg_code,
+				    estext_lsize, "", estext,
+				    estext_rsize, "");
+			else
+				dprompt_add(format,
+				    estext_lsize, "", estext,
+				    estext_rsize, "");
+			break;
+		case DPROMPT_DETAILS: /* Past/Current file(s) */
+			humanize_number(human, pbar_size + 2, fp->read, "",
+			    HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000);
+
+			/* Calculate center alignment */
+			hlen = (int)strlen(human);
+			lsize = (pbar_size - hlen) / 2;
+			rsize = lsize;
+			if ((lsize+hlen+rsize) != pbar_size)
+				rsize++;
+
+			if (use_color)
+				dprompt_add(format, bold_code, bg_code,
+				    lsize, "", human, rsize, "");
+			else
+				dprompt_add(format,
+				    lsize, "", human, rsize, "");
+			break;
+		case DPROMPT_CUSTOM_MSG: /* File-specific message override */
+			snprintf(msg, PROMPT_MAX + 1, "%s", fp->msg);
+			if (pbar_size < (mesg_size = strlen(msg))) {
+				mesg_lsize = mesg_rsize = 0;
+				*(msg + pbar_size) = '\0';
+				mesg_size = pbar_size;
+			} else {
+				mesg_lsize = (pbar_size - mesg_size) / 2;
+				mesg_rsize = mesg_lsize;
+				if ((mesg_rsize + mesg_size + mesg_lsize)
+				    != pbar_size)
+					mesg_rsize++;
+			}
+			if (use_color)
+				dprompt_add(format, bold_code, bg_code,
+				    mesg_lsize, "", msg, mesg_rsize, "");
+			else
+				dprompt_add(format, mesg_lsize, "", msg,
+				    mesg_rsize, "");
+			break;
+		case DPROMPT_MINIMAL: /* Short progress bar, minimal room */
+			if (use_color)
+				dprompt_add(format, bold_code, bg_code,
+				    pbar_size, "", "", 0, "");
+			else
+				dprompt_add(format, pbar_size, "", "", 0, "");
+			break;
+		case DPROMPT_NONE: /* pbar_size < 0 */
+			/* FALLTHROUGH */
+		default:
+			dprompt_add(" \\n");
+			/*
+			 * NB: Leading space required for the case when
+			 * spin_char() returns a single backslash [\] which
+			 * without the space, changes the meaning of `\n'
+			 */
+		}
+
+		/* Stop building if we've hit the internal limit */
+		if (nthfile >= display_limit)
+			break;
+
+		/* If this is the current file, all others are pending */
+		if (fp == curfile)
+			after_curfile = TRUE;
+	}
+
+	/*
+	 * Since we cannot change the height/width of the [X]dialog(1) widget
+	 * after spawn, to make things look nice let's pad the height so that
+	 * the `-a text' always appears in the same spot.
+	 *
+	 * NOTE: fheight is calculated in dprompt_init(). It represents the
+	 * maximum height required to display the set of items (broken up into
+	 * pieces of display_limit chunks) whose names contain the most
+	 * newlines for any given set.
+	 */
+	while (nlines < fheight) {
+		dprompt_add("\n");
+		nlines++;
+	}
+
+	return (nthfile);
+}
+
+/*
+ * Process the dpv_file_node linked-list of named files, re-generating the
+ * [X]dialog(1) `--gauge' prompt text for the current state of transfers.
+ */
+void
+dprompt_recreate(struct dpv_file_node *file_list,
+    struct dpv_file_node *curfile, int pct)
+{
+	size_t len;
+
+	/*
+	 * Re-Build the prompt text
+	 */
+	dprompt_clear();
+	if (display_limit > 0)
+		dprompt_add_files(file_list, curfile, pct);
+
+	/* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */
+	if (use_xdialog) {
+		/* Replace `\n' with `\n\\n\n' in dprompt */
+		len = strlen(dprompt);
+		len += strcount(dprompt, "\\n") * 5; /* +5 chars per count */
+		if (len > PROMPT_MAX)
+			errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow "
+			    "(%zu > %i)", __func__, len, PROMPT_MAX);
+		if (replaceall(dprompt, "\\n", "\n\\n\n") < 0)
+			err(EXIT_FAILURE, "%s: replaceall()", __func__);
+	}
+	else if (use_libdialog)
+		strexpandnl(dprompt);
+}
+
+/*
+ * Print the [X]dialog(1) `--gauge' prompt text to a buffer.
+ */
+int
+dprompt_sprint(char * restrict str, const char *prefix, const char *append)
+{
+
+	return (snprintf(str, PROMPT_MAX, "%s%s%s%s", use_color ? "\\Zn" : "",
+	    prefix ? prefix : "", dprompt, append ? append : ""));
+}
+
+/*
+ * Print the [X]dialog(1) `--gauge' prompt text to file descriptor fd (could
+ * be STDOUT_FILENO or a pipe(2) file descriptor to actual [X]dialog(1)).
+ */
+void
+dprompt_dprint(int fd, const char *prefix, const char *append, int overall)
+{
+	int percent = gauge_percent;
+
+	if (overall >= 0 && overall <= 100)
+		gauge_percent = percent = overall;
+	dprintf(fd, "XXX\n%s%s%s%s\nXXX\n%i\n", use_color ? "\\Zn" : "",
+	    prefix ? prefix : "", dprompt, append ? append : "", percent);
+	fsync(fd);
+}
+
+/*
+ * Print the dialog(3) `gauge' prompt text using libdialog.
+ */
+void
+dprompt_libprint(const char *prefix, const char *append, int overall)
+{
+	int percent = gauge_percent;
+	char buf[DPV_PPROMPT_MAX + DPV_APROMPT_MAX + DPV_DISPLAY_LIMIT * 1024];
+
+	dprompt_sprint(buf, prefix, append);
+
+	if (overall >= 0 && overall <= 100)
+		gauge_percent = percent = overall;
+	gauge = dlg_reallocate_gauge(gauge, title == NULL ? "" : title,
+	    buf, dheight, dwidth, percent);
+	dlg_update_gauge(gauge, percent);
+}
+
+/*
+ * Free allocated items initialized by dprompt_init()
+ */
+void
+dprompt_free(void)
+{
+	if ((dprompt_free_mask & FM_DONE) != 0) {
+		dprompt_free_mask ^= FM_DONE;
+		free(done);
+		done = NULL;
+	}
+	if ((dprompt_free_mask & FM_FAIL) != 0) {
+		dprompt_free_mask ^= FM_FAIL;
+		free(fail);
+		fail = NULL;
+	}
+	if ((dprompt_free_mask & FM_PEND) != 0) {
+		dprompt_free_mask ^= FM_PEND;
+		free(pend);
+		pend = NULL;
+	}
+}


Property changes on: trunk/lib/libdpv/dprompt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dprompt.h
===================================================================
--- trunk/lib/libdpv/dprompt.h	                        (rev 0)
+++ trunk/lib/libdpv/dprompt.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,60 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/dprompt.h 274116 2014-11-04 23:46:01Z dteske $
+ */
+
+#ifndef _DPROMPT_H_
+#define _DPROMPT_H_
+
+#include <sys/cdefs.h>
+
+#include "dpv.h"
+
+/* Display characteristics */
+#define ENV_MSG_DONE	"msg_done"
+#define ENV_MSG_FAIL	"msg_fail"
+#define ENV_MSG_PENDING	"msg_pending"
+extern int display_limit;
+extern int label_size;
+extern int pbar_size;
+
+__BEGIN_DECLS
+void	dprompt_clear(void);
+void	dprompt_dprint(int _fd, const char *_prefix, const char *_append,
+	    int _overall);
+void	dprompt_free(void);
+void	dprompt_init(struct dpv_file_node *_file_list);
+void	dprompt_libprint(const char *_prefix, const char *_append,
+	    int _overall);
+void	dprompt_recreate(struct dpv_file_node *_file_list,
+	    struct dpv_file_node *_curfile, int _pct);
+int	dprompt_add(const char *_format, ...);
+int	dprompt_sprint(char * restrict _str, const char *_prefix,
+	    const char *_append);
+__END_DECLS
+
+#endif /* !_DPROMPT_H_ */


Property changes on: trunk/lib/libdpv/dprompt.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dpv.3
===================================================================
--- trunk/lib/libdpv/dpv.3	                        (rev 0)
+++ trunk/lib/libdpv/dpv.3	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,512 @@
+.\" $MidnightBSD$
+.\" Copyright (c) 2013-2016 Devin Teske
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: stable/10/lib/libdpv/dpv.3 306378 2016-09-27 19:00:22Z pluknet $
+.\"
+.Dd Jan 26, 2016
+.Dt DPV 3
+.Os
+.Sh NAME
+.Nm dpv
+.Nd dialog progress view library
+.Sh LIBRARY
+.Lb libdpv
+.Sh SYNOPSIS
+.In dpv.h
+.Ft int
+.Fo dpv
+.Fa "struct dpv_config *config, struct dpv_file_node *file_list"
+.Fc
+.Ft void
+.Fo dpv_free
+.Fa "void"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+library provides an interface for creating complex
+.Dq gauge
+widgets for displaying progress on various actions.
+The
+.Nm
+library can display progress with one of
+.Xr dialog 3 ,
+.Xr dialog 1 ,
+or
+.Xr Xdialog 1
+.Pq x11/xdialog from the ports tree .
+.Pp
+The
+.Fn dpv
+.Fa config
+argument contains the following properties for configuring global display
+features:
+.Bd -literal -offset indent
+struct dpv_config {
+    uint8_t          keep_tite;     /* Cleaner exit for scripts */
+    enum dpv_display display_type;  /* Def. DPV_DISPLAY_LIBDIALOG */
+    enum dpv_output  output_type;   /* Default DPV_OUTPUT_NONE */
+    int              debug;         /* Enable debug on stderr */
+    int              display_limit; /* Files/page. Default -1 */
+    int              label_size;    /* Label size. Default 28 */
+    int              pbar_size;     /* Mini-progress size */
+    int              dialog_updates_per_second; /* Default 16 */
+    int              status_updates_per_second; /* Default 2 */
+    uint16_t         options;       /* Default 0 (none) */
+    char             *title;        /* Widget title */
+    char             *backtitle;    /* Widget backtitle */
+    char             *aprompt;      /* Append. Default NULL */
+    char             *pprompt;      /* Prefix. Default NULL */
+    char             *msg_done;     /* Default `Done' */
+    char             *msg_fail;     /* Default `Fail' */
+    char             *msg_pending;  /* Default `Pending' */
+    char             *output;       /* Output format string */
+    const char       *status_solo;  /* dialog(3) solo-status format.
+                                     * Default DPV_STATUS_SOLO */
+    const char       *status_many;  /* dialog(3) many-status format.
+                                     * Default DPV_STATUS_MANY */
+
+    /*
+     * Function pointer; action to perform data transfer
+     */
+    int (*action)(struct dpv_file_node *file, int out);
+};
+
+enum dpv_display {
+    DPV_DISPLAY_LIBDIALOG = 0, /* Use dialog(3) (default) */
+    DPV_DISPLAY_STDOUT,        /* Use stdout */
+    DPV_DISPLAY_DIALOG,        /* Use spawned dialog(1) */
+    DPV_DISPLAY_XDIALOG,       /* Use spawned Xdialog(1) */
+};
+
+enum dpv_output {
+    DPV_OUTPUT_NONE = 0, /* No output (default) */
+    DPV_OUTPUT_FILE,     /* Read `output' member as file path */
+    DPV_OUTPUT_SHELL,    /* Read `output' member as shell cmd */
+};
+.Ed
+.Pp
+The
+.Va options
+member of the
+.Fn dpv
+.Fa config
+argument is a mask of bit fields indicating various processing options.
+Possible flags are as follows:
+.Bl -tag -width DPV_NO_OVERRUN
+.It Dv DPV_TEST_MODE
+Enable test mode.
+In test mode, the
+.Fn action
+callback of the
+.Fa config
+argument is not called but instead simulated-data is used to drive progress.
+Appends
+.Dq [TEST MODE]
+to the status line
+.Po
+to override, set the
+.Va status_format
+member of the
+.Fn dpv
+.Fa config
+argument;
+e.g., to
+.Dv DPV_STATUS_DEFAULT
+.Pc .
+.It Dv DPV_WIDE_MODE
+Enable wide mode.
+In wide mode, the length of the
+.Va aprompt
+and
+.Va pprompt
+members of the
+.Fn dpv
+.Fa config
+argument will bump the width of the gauge widget.
+Prompts wider than the maximum width will wrap
+.Po
+unless using
+.Xr Xdialog 1 ;
+see BUGS section below
+.Pc .
+.It Dv DPV_NO_LABELS
+Disables the display of labels associated with each transfer
+.Po
+.Va label_size
+member of
+.Fn dpv
+.Fa config
+argument is ignored
+.Pc .
+.It Dv DPV_USE_COLOR
+Force the use of color even if the
+.Va display_type
+does not support color
+.Po
+.Ev USE_COLOR
+environment variable is ignored
+.Pc .
+.It Dv DPV_NO_OVERRUN
+When enabled, callbacks for the current
+.Vt dpv_file_node
+are terminated when
+.Fn action
+returns 100 or greater
+.Po
+alleviates the need to change the
+.Va status
+of the current
+.Vt dpv_file_node
+but may also cause file truncation if the stream exceeds expected length
+.Pc .
+.El
+.Pp
+The
+.Fa file_list
+argument to
+.Fn dpv
+is a pointer to a
+.Dq linked-list ,
+described as follows in
+.In dpv.h :
+.Bd -literal -offset indent
+struct dpv_file_node {
+    enum dpv_status    status; /* status of read operation */
+    char               *msg;   /* display instead of "Done/Fail" */
+    char               *name;  /* name of file to read */
+    char               *path;  /* path to file */
+    long long          length; /* expected size */
+    long long          read;   /* number units read (e.g., bytes) */
+    struct dpv_file_node *next;/* pointer to next (end with NULL) */
+};
+.Ed
+.Pp
+For each of the items in the
+.Fa file_list
+.Dq linked-list
+argument, the
+.Fn action
+callback member of the
+.Fn dpv
+.Fa config
+argument is called.
+The
+.Fn action
+function should perform a
+.Dq nominal
+action on the file and return.
+The return value of
+.Vt int
+represents the current progress percentage
+.Pq 0-100
+for the current file.
+.Pp
+The
+.Fn action
+callback provides two variables for each call.
+.Fa file
+provides a reference to the current
+.Vt dpv_file_node
+being processed.
+.Fa out
+provides a file descriptor where the data should go.
+.Pp
+If the
+.Va output
+member of the
+.Fn dpv
+.Fa config
+argument was set to DPV_OUTPUT_NONE
+.Pq default ; when invoking Fn dpv ,
+the
+.Fa out
+file descriptor of
+.Fn action
+will be zero and should be ignored.
+If
+.Fa output
+was set to DPV_OUTPUT_FILE,
+.Fa out
+will be an open file descriptor to a file.
+If
+.Fa output
+was set to DPV_OUTPUT_SHELL,
+.Fa out
+will be an open file descriptor to a pipe for a spawned shell program.
+When
+.Fa out
+is greater than zero, you should write any data you have read back to
+.Fa out .
+.Pp
+To abort
+.Fn dpv ,
+either from the
+.Fn action
+callback or asynchronously from a signal handler, two globals are provided via
+.In dpv.h :
+.Bd -literal -offset indent
+extern int dpv_interrupt; /* Set to TRUE in interrupt handler */
+extern int dpv_abort;     /* Set to true in callback to abort */
+.Ed
+.Pp
+These globals are not automatically reset and must be manually maintained.
+Don't forget to reset these globals before subsequent invocations of
+.Fn dpv
+when making multiple calls from the same program.
+.Pp
+In addition, the
+.Va status
+member of the
+.Fn action
+.Fa file
+argument can be used to control callbacks for the current file.
+The
+.Va status
+member can be set to any of the following from
+.In dpv.h :
+.Bd -literal -offset indent
+enum dpv_status {
+	DPV_STATUS_RUNNING = 0, /* Running (default) */
+	DPV_STATUS_DONE,        /* Completed */
+	DPV_STATUS_FAILED,      /* Oops, something went wrong */
+};
+.Ed
+.Pp
+The default
+.Fa status
+is zero, DPV_STATUS_RUNING, which keeps the callbacks coming for the current
+.Fn file .
+Setting
+.Ql file->status
+to anything other than DPV_STATUS_RUNNING will cause
+.Fn dpv
+to loop to the next file, effecting the next callback, if any.
+.Pp
+The
+.Fn action
+callback is responsible for calculating percentages and
+.Pq recommended
+maintaining a
+.Nm
+global counter so
+.Fn dpv
+can display throughput statistics.
+Percentages are reported through the
+.Vt int
+return value of the
+.Fn action
+callback.
+Throughput statistics are calculated from the following global
+.Vt int
+in
+.In dpv.h :
+.Bd -literal -offset indent
+extern int dpv_overall_read;
+.Ed
+.Pp
+This should be set to the number of bytes that have been read for all files.
+Throughput information is displayed in the status line
+.Pq only available when using Xr dialog 3
+at the bottom of the screen.
+See DPV_DISPLAY_LIBDIALOG above.
+.Pp
+Note that
+.Va dpv_overall_read
+does not have to represent bytes.
+For example, you can change the
+.Va status_format
+to display something other than
+.Dq Li bytes
+and increment
+.Va dpv_overall_read
+accordingly
+.Pq e.g., counting lines .
+.Pp
+When
+.Fn dpv
+is processing the current file, the
+.Va length
+and
+.Va read
+members of the
+.Fn action
+.Fa file
+argument are used for calculating the display of mini progress bars
+.Po
+if enabled; see
+.Va pbar_size
+above
+.Pc .
+If the
+.Va length
+member of the current
+.Fa file
+is less than zero
+.Pq indicating an unknown file length ,
+a
+.Xr humanize_number 3
+version of the
+.Va read
+member is used instead of a traditional progress bar.
+Otherwise a progress bar is calculated as percentage read to file length.
+.Fn action
+callback must maintain these member values for mini-progress bars.
+.Pp
+The
+.Fn dpv_free
+function performs
+.Xr free 3
+on private global variables initialized by
+.Fn dpv .
+.Sh ENVIRONMENT
+The following environment variables are referenced by
+.Nm :
+.Bl -tag -width ".Ev USE_COLOR"
+.It Ev DIALOG
+Override command string used to launch
+.Xr dialog 1
+.Pq requires Dv DPV_DISPLAY_DIALOG
+or
+.Xr Xdialog 1
+.Pq requires Dv DPV_DISPLAY_XDIALOG ;
+default is either
+.Ql dialog
+.Pq for Dv DPV_DISPLAY_DIALOG
+or
+.Ql Xdialog
+.Pq for Dv DPV_DISPLAY_XDIALOG .
+.It Ev DIALOGRC
+If set and non-NULL, path to
+.Ql .dialogrc
+file.
+.It Ev HOME
+If
+.Ql Ev $DIALOGRC
+is either not set or NULL, used as a prefix to
+.Ql .dialogrc
+.Pq i.e., Ql $HOME/.dialogrc .
+.It Ev USE_COLOR
+If set and NULL, disables the use of color when using
+.Xr dialog 1
+.Pq does not apply to Xr Xdialog 1 .
+.It Ev msg_done Ev msg_fail Ev msg_pending
+Internationalization strings for overriding the default English strings
+.Ql Done ,
+.Ql Fail ,
+and
+.Ql Pending
+respectively.
+To prevent their usage, explicitly set the
+.Va msg_done ,
+.Va msg_fail ,
+and
+.Va msg_pending
+members of
+.Fn dpv
+.Fa config
+argument to default macros
+.Pq DPV_DONE_DEFAULT, DPV_FAIL_DEFAULT, and DPV_PENDING_DEFAULT
+or desired values.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa $HOME/.dialogrc" -compact
+.It Pa $HOME/.dialogrc
+.El
+.Sh SEE ALSO
+.Xr dialog 1 ,
+.Xr dialog 3 ,
+.Xr Xdialog 1
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Fx 10.2 .
+.Sh AUTHORS
+.An Devin Teske Aq dteske at FreeBSD.org
+.Sh BUGS
+.Xr Xdialog 1 ,
+when given both
+.Ql Fl -title Ar title
+.Po
+see above
+.Ql Va title
+member of
+.Va struct dpv_config
+.Pc
+and
+.Ql Fl -backtitle Ar backtitle
+.Po
+see above
+.Ql Va backtitle
+member of
+.Va struct dpv_config
+.Pc ,
+displays the backtitle in place of the title and vice-versa.
+.Pp
+.Xr Xdialog 1
+does not wrap long prompt texts received after initial launch.
+This is a known issue with the
+.Ql --gauge
+widget in
+.Xr Xdialog 1 .
+Embed escaped newlines within prompt text(s) to force line breaks.
+.Pp
+.Xr dialog 1
+does not display the first character after a series of escaped escape-sequences
+(e.g., ``\\\\n'' produces ``\\'' instead of ``\\n'').
+This is a known issue with
+.Xr dialog 1
+and does not affect
+.Xr dialog 3
+or
+.Xr Xdialog 1 .
+.Pp
+If your application ignores
+.Ev USE_COLOR
+when set and NULL before calling
+.Xr dpv 3
+with color escape sequences anyway,
+.Xr dialog 3
+and
+.Xr dialog 1
+may not render properly.
+Workaround is to detect when
+.Ev USE_COLOR
+is set and NULL and either not use color escape sequences at that time or use
+.Xr unsetenv 3
+to unset
+.Ev USE_COLOR ,
+forcing interpretation of color sequences.
+This does not effect
+.Xr Xdialog 1 ,
+which renders the color escape sequences as plain text.
+See
+.Do
+embedded "\\Z" sequences
+.Dc
+in
+.Xr dialog 1
+for additional information.


Property changes on: trunk/lib/libdpv/dpv.3
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dpv.c
===================================================================
--- trunk/lib/libdpv/dpv.c	                        (rev 0)
+++ trunk/lib/libdpv/dpv.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,731 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2016 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/dpv.c 295107 2016-02-01 00:44:29Z dteske $");
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <dialog.h>
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_m.h>
+#include <unistd.h>
+
+#include "dialog_util.h"
+#include "dialogrc.h"
+#include "dprompt.h"
+#include "dpv.h"
+#include "dpv_private.h"
+#include "status.h"
+#include "util.h"
+
+/* Test Mechanics (Only used when dpv_config.options |= DPV_TEST_MODE) */
+#define INCREMENT		1	/* Increment % per-pass test-mode */
+#define XDIALOG_INCREMENT	15	/* different for slower Xdialog(1) */
+static uint8_t increment = INCREMENT;
+
+/* Debugging */
+uint8_t debug = FALSE;
+
+/* Data to process */
+int dpv_interrupt = FALSE;
+int dpv_abort = FALSE;
+unsigned int dpv_nfiles = 0;
+
+/* Data processing */
+long long dpv_overall_read = 0;
+static char pathbuf[PATH_MAX];
+
+/* Extra display information */
+uint8_t keep_tite = FALSE;	/* dpv_config.keep_tite */
+uint8_t no_labels = FALSE;	/* dpv_config.options & DPV_NO_LABELS */
+uint8_t wide = FALSE;		/* dpv_config.options & DPV_WIDE_MODE */
+char *aprompt = NULL;		/* dpv_config.aprompt */
+char *msg_done = NULL;		/* dpv_config.msg_done */
+char *msg_fail = NULL;		/* dpv_config.msg_fail */
+char *msg_pending = NULL;	/* dpv_config.msg_pending */
+char *pprompt = NULL;		/* dpv_config.pprompt */
+
+/* Status-Line format for when using dialog(3) */
+static const char *status_format_custom = NULL;
+static char status_format_default[DPV_STATUS_FORMAT_MAX];
+
+/*
+ * 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;
+	keep_tite	= FALSE;
+	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;
+		keep_tite	= config->keep_tite;
+		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 */
+
+	/* Default localeconv(3) settings for dialog(3) status */
+	setlocale(LC_NUMERIC,
+		getenv("LC_ALL") == NULL && getenv("LC_NUMERIC") == NULL ?
+		LC_NUMERIC_DEFAULT : "");
+
+	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 (!keep_tite && !dpv_interrupt)
+			printf("\n");
+	} else
+		warnx("%s: %lli overall read", __func__, dpv_overall_read);
+
+	if (dpv_interrupt || dpv_abort)
+		return (-1);
+	else
+		return (0);
+}
+
+/*
+ * Free allocated items initialized by dpv()
+ */
+void
+dpv_free(void)
+{
+	dialogrc_free();
+	dprompt_free();
+	dialog_maxsize_free();
+	if (aprompt != NULL) {
+		free(aprompt);
+		aprompt = NULL;
+	}
+	if (pprompt != NULL) {
+		free(pprompt);
+		pprompt = NULL;
+	}
+	status_free();
+}


Property changes on: trunk/lib/libdpv/dpv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dpv.h
===================================================================
--- trunk/lib/libdpv/dpv.h	                        (rev 0)
+++ trunk/lib/libdpv/dpv.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2016 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/dpv.h 295107 2016-02-01 00:44:29Z dteske $
+ */
+
+#ifndef _DPV_H_
+#define _DPV_H_
+
+#include <sys/types.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* localeconv(3) */
+#define LC_NUMERIC_DEFAULT	"en_US.ISO8859-1"
+
+/* Data to process */
+extern long long dpv_overall_read;
+
+/* Interrupt flag */
+extern int dpv_interrupt;	/* Set to TRUE in interrupt handler */
+extern int dpv_abort;		/* Set to true in callback to abort */
+
+/*
+ * Display types for use with display_type member of dpv_config structure
+ */
+enum dpv_display {
+	DPV_DISPLAY_LIBDIALOG = 0,	/* Display using dialog(3) (default) */
+	DPV_DISPLAY_STDOUT,		/* Display on stdout */
+	DPV_DISPLAY_DIALOG,		/* Display using spawned dialog(1) */
+	DPV_DISPLAY_XDIALOG,		/* Display using spawned Xdialog(1) */
+};
+
+/*
+ * Output types for use with output_type member of dpv_config structure
+ */
+enum dpv_output {
+	DPV_OUTPUT_NONE = 0,	/* No output (default) */
+	DPV_OUTPUT_FILE,	/* Read `output' member as file path */
+	DPV_OUTPUT_SHELL,	/* Read `output' member as shell cmd */
+};
+
+/*
+ * Activity types for use with status member of dpv_file_node structure.
+ * If you set a status other than DPV_STATUS_RUNNING on the current file in the
+ * action callback of dpv_config structure, you'll end callbacks for that
+ * dpv_file_node.
+ */
+enum dpv_status {
+	DPV_STATUS_RUNNING = 0,	/* Running (default) */
+	DPV_STATUS_DONE,	/* Completed */
+	DPV_STATUS_FAILED,	/* Oops, something went wrong */
+};
+
+/*
+ * Anatomy of file option; pass an array of these as dpv() file_list argument
+ * terminated with a NULL pointer.
+ */
+struct dpv_file_node {
+	enum dpv_status		status; /* status of read operation */
+	char			*msg;	/* display instead of "Done/Fail" */
+	char			*name;	/* name of file to read */
+	char			*path;	/* path to file */
+	long long		length;	/* expected size */
+	long long		read;	/* number units read (e.g., bytes) */
+	struct dpv_file_node	*next;	/* pointer to next (end with NULL) */
+};
+
+/*
+ * Anatomy of config option to pass as dpv() config argument
+ */
+struct dpv_config {
+	uint8_t	keep_tite;		/* Prevent visually distracting exit */
+	enum dpv_display display_type;	/* Display (default TYPE_LIBDIALOG) */
+	enum dpv_output  output_type;	/* Output (default TYPE_NONE) */
+	int	debug;			/* Enable debugging output on stderr */
+	int	display_limit;		/* Files per `page'. Default -1 */
+	int	label_size;		/* Label size. Default 28 */
+	int	pbar_size;		/* Mini-progress size. See dpv(3) */
+	int	dialog_updates_per_second; /* Progress updates/s. Default 16 */
+	int	status_updates_per_second; /* dialog(3) status updates/second.
+	   	                            * Default 2 */
+	uint16_t options;	/* Special options. Default 0 */
+	char	*title;		/* widget title */
+	char	*backtitle;	/* Widget backtitle */
+	char	*aprompt;	/* Prompt append. Default NULL */
+	char	*pprompt;	/* Prompt prefix. Default NULL */
+	char	*msg_done;	/* Progress text. Default `Done' */
+	char	*msg_fail;	/* Progress text. Default `Fail' */
+	char	*msg_pending;	/* Progress text. Default `Pending' */
+	char	*output;	/* Output format string; see dpv(3) */
+	const char *status_solo; /* dialog(3) solo-status format.
+	                          * Default DPV_STATUS_SOLO */
+	const char *status_many; /* dialog(3) many-status format.
+	                          * Default DPV_STATUS_MANY */
+
+	/*
+	 * Function pointer; action to perform data transfer
+	 */
+	int (*action)(struct dpv_file_node *file, int out);
+};
+
+/*
+ * Macros for dpv() options bitmask argument
+ */
+#define DPV_TEST_MODE		0x0001	/* Test mode (fake reading data) */
+#define DPV_WIDE_MODE		0x0002	/* prefix/append bump dialog width */
+#define DPV_NO_LABELS		0x0004	/* Hide file_node.name labels */
+#define DPV_USE_COLOR		0x0008	/* Override to force color output */
+#define DPV_NO_OVERRUN		0x0010	/* Stop transfers when they hit 100% */
+
+/*
+ * Limits (modify with extreme care)
+ */
+#define DPV_APROMPT_MAX		4096	/* Buffer size for `-a text' */
+#define DPV_DISPLAY_LIMIT	10	/* Max file progress lines */
+#define DPV_PPROMPT_MAX		4096	/* Buffer size for `-p text' */
+#define DPV_STATUS_FORMAT_MAX	80	/* Buffer size for `-u format' */
+
+/*
+ * Extra display information
+ */
+#define DPV_STATUS_SOLO		"%'10lli bytes read @ %'9.1f bytes/sec."
+#define DPV_STATUS_MANY		(DPV_STATUS_SOLO " [%i/%i busy/wait]")
+
+/*
+ * Strings
+ */
+#define DPV_DONE_DEFAULT	"Done"
+#define DPV_FAIL_DEFAULT	"Fail"
+#define DPV_PENDING_DEFAULT	"Pending"
+
+__BEGIN_DECLS
+void	dpv_free(void);
+int	dpv(struct dpv_config *_config, struct dpv_file_node *_file_list);
+__END_DECLS
+
+#endif /* !_DPV_H_ */


Property changes on: trunk/lib/libdpv/dpv.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/dpv_private.h
===================================================================
--- trunk/lib/libdpv/dpv_private.h	                        (rev 0)
+++ trunk/lib/libdpv/dpv_private.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,68 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2016 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/dpv_private.h 295107 2016-02-01 00:44:29Z dteske $
+ */
+
+#ifndef _DPV_PRIVATE_H_
+#define _DPV_PRIVATE_H_
+
+#include <sys/types.h>
+
+/* Debugging */
+extern uint8_t debug;
+
+/* Data to process */
+extern unsigned int dpv_nfiles;
+
+/* Extra display information */
+extern uint8_t keep_tite;
+extern uint8_t no_labels;
+extern uint8_t wide;
+extern char *msg_done, *msg_fail, *msg_pending;
+extern char *pprompt, *aprompt;
+extern const char status_format[];
+
+/* Defaults */
+#define DIALOG_UPDATES_PER_SEC	16
+#define XDIALOG_UPDATES_PER_SEC	4
+#define DISPLAY_LIMIT_DEFAULT	0	/* Auto-calculate */
+#define LABEL_SIZE_DEFAULT	28
+#define PBAR_SIZE_DEFAULT	17
+#define STATUS_UPDATES_PER_SEC	2
+
+/* states for dprompt_add_files() of dprompt.c */
+enum dprompt_state {
+	DPROMPT_NONE = 0,	/* Default */
+	DPROMPT_PENDING,	/* Pending */
+	DPROMPT_PBAR,		/* Progress bar */
+	DPROMPT_END_STATE,	/* Done/Fail */
+	DPROMPT_DETAILS,	/* dpv_file_node->read */
+	DPROMPT_CUSTOM_MSG,	/* dpv_file_node->msg */
+	DPROMPT_MINIMAL,	/* whitespace */
+};
+
+#endif /* !_DPV_PRIVATE_H_ */


Property changes on: trunk/lib/libdpv/dpv_private.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/status.c
===================================================================
--- trunk/lib/libdpv/status.c	                        (rev 0)
+++ trunk/lib/libdpv/status.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,112 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/status.c 274116 2014-11-04 23:46:01Z dteske $");
+
+#include <curses.h>
+#include <dialog.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dialog_util.h"
+#include "status.h"
+
+/* static globals */
+static char *status_buf = NULL;
+static int status_bufsize = -1;
+static int status_row;
+static int status_width;
+
+/*
+ * Print a `one-liner' status message at the bottom of the screen. Messages are
+ * trimmed to fit within the console length (ANSI coloring not accounted for).
+ */
+void
+status_printf(const char *fmt, ...)
+{
+	int n, attrs;
+	chtype color = dlg_color_pair(dlg_color_table[BUTTON_ACTIVE_ATTR].fg,
+	    dlg_color_table[SCREEN_ATTR].bg) | A_BOLD;
+	va_list args;
+
+	status_row = tty_maxrows() - 1;
+	status_width = tty_maxcols();
+
+	/* NULL is a special convention meaning "erase the old stuff" */
+	if (fmt == NULL) {
+		move(status_row, 0);
+		clrtoeol();
+		return;
+	}
+
+	/* Resize buffer if terminal width is greater */
+	if ((status_width + 1) > status_bufsize) {
+		status_buf = realloc(status_buf, status_width + 1);
+		if (status_buf == NULL) {
+			status_bufsize = -1;
+			return;
+		}
+		status_bufsize = status_width + 1;
+	}
+
+	/* Print the message within a space-filled buffer */
+	memset(status_buf, ' ', status_width);
+	va_start(args, fmt);
+	n = vsnprintf(status_buf, status_width + 1, fmt, args);
+	va_end(args);
+
+	/* If vsnprintf(3) produced less bytes than the maximum, change the
+	 * implicitly-added NUL-terminator into a space and terminate at max */
+	if (n < status_width) {
+		status_buf[n] = ' ';
+		status_buf[status_width] = '\0';
+	}
+
+	/* Print text in screen bg, button active fg, and bold */
+	attrs = getattrs(stdscr);
+	attrset(color);
+	mvaddstr(status_row, 0, status_buf);
+	attrset(attrs);
+
+	/* Seat the cursor over the last character at absolute lower-right */
+	move(status_row, status_width - 1);
+	refresh();
+}
+
+/*
+ * Free allocated items initialized by status_printf()
+ */
+void
+status_free(void)
+{
+	if (status_buf != NULL) {
+		free(status_buf);
+		status_buf = NULL;
+	}
+}


Property changes on: trunk/lib/libdpv/status.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/status.h
===================================================================
--- trunk/lib/libdpv/status.h	                        (rev 0)
+++ trunk/lib/libdpv/status.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/status.h 274116 2014-11-04 23:46:01Z dteske $
+ */
+
+#ifndef _STATUS_H_
+#define _STATUS_H_
+
+#include <sys/cdefs.h>
+
+/* dialog(3) dlg_color_table[] attributes */
+#define SCREEN_ATTR		0 /* entry used for status line bg */
+#define BUTTON_ACTIVE_ATTR	5 /* entry used for status line fg */
+
+__BEGIN_DECLS
+void	status_free(void);
+void	status_printf(const char *_format, ...);
+__END_DECLS
+
+#endif /* !_STATUS_H_ */


Property changes on: trunk/lib/libdpv/status.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/util.c
===================================================================
--- trunk/lib/libdpv/util.c	                        (rev 0)
+++ trunk/lib/libdpv/util.c	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libdpv/util.c 274116 2014-11-04 23:46:01Z dteske $");
+
+#include <err.h>
+#include <limits.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "util.h"
+
+extern char **environ;
+static char cmdbuf[CMDBUFMAX]	= "";
+static char shellcmd[PATH_MAX]	= PATH_SHELL;
+static char *shellcmd_argv[6]	= {
+	shellcmd,
+	__DECONST(char *, "-c"),
+	cmdbuf,
+	__DECONST(char *, "--"),
+	shellcmd,
+	NULL,
+};
+
+/*
+ * 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];
+}


Property changes on: trunk/lib/libdpv/util.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libdpv/util.h
===================================================================
--- trunk/lib/libdpv/util.h	                        (rev 0)
+++ trunk/lib/libdpv/util.h	2018-06-05 22:58:23 UTC (rev 10436)
@@ -0,0 +1,51 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013-2016 Devin Teske <dteske at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libdpv/util.h 293620 2016-01-09 23:44:41Z dteske $
+ */
+
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <sys/types.h>
+
+#include <paths.h>
+
+#define SHELL_SPAWN_DEBUG	0	/* Debug spawning of sh(1) commands */
+
+#ifdef _PATH_BSHELL
+#define PATH_SHELL	_PATH_BSHELL
+#else
+#define PATH_SHELL	"/bin/sh"
+#endif
+
+#define CMDBUFMAX	65536
+
+__BEGIN_DECLS
+int	shell_spawn_pipecmd(const char *_cmd, const char *_label, pid_t *_pid);
+__END_DECLS
+
+#endif /* !_UTIL_H_ */


Property changes on: trunk/lib/libdpv/util.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list