diff --git a/lib/libdpv/dpv.3 b/lib/libdpv/dpv.3 index 8581279e1dc6..011ab8208d14 100644 --- a/lib/libdpv/dpv.3 +++ b/lib/libdpv/dpv.3 @@ -1,510 +1,511 @@ -.\" Copyright (c) 2013-2015 Devin Teske +.\" 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$ .\" -.Dd Oct 22, 2015 +.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 Xdialog 1 , .Xr dialog 3 .Sh HISTORY The .Nm library first appeared in .Fx 10.2 . .Sh AUTHORS .An Devin Teske Aq dteske@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. diff --git a/lib/libdpv/dpv.c b/lib/libdpv/dpv.c index d3506ca9d82d..edf75bd1dfe7 100644 --- a/lib/libdpv/dpv.c +++ b/lib/libdpv/dpv.c @@ -1,727 +1,730 @@ /*- * Copyright (c) 2013-2014 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 (!dpv_interrupt) + 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(); } diff --git a/lib/libdpv/dpv.h b/lib/libdpv/dpv.h index 03768a7ced40..67d7bc11e9a8 100644 --- a/lib/libdpv/dpv.h +++ b/lib/libdpv/dpv.h @@ -1,164 +1,165 @@ /*- * Copyright (c) 2013-2014 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$ */ #ifndef _DPV_H_ #define _DPV_H_ #include #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_ */ diff --git a/lib/libdpv/dpv_private.h b/lib/libdpv/dpv_private.h index 5164eb321ed2..1bebba643f18 100644 --- a/lib/libdpv/dpv_private.h +++ b/lib/libdpv/dpv_private.h @@ -1,66 +1,67 @@ /*- * Copyright (c) 2013-2014 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$ */ #ifndef _DPV_PRIVATE_H_ #define _DPV_PRIVATE_H_ #include /* 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_ */ diff --git a/sys/sys/param.h b/sys/sys/param.h index 7c03f3374d4c..c383c432e43f 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -1,363 +1,363 @@ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)param.h 8.3 (Berkeley) 4/4/95 * $FreeBSD$ */ #ifndef _SYS_PARAM_H_ #define _SYS_PARAM_H_ #include #define BSD 199506 /* System version (year & month). */ #define BSD4_3 1 #define BSD4_4 1 /* * __FreeBSD_version numbers are documented in the Porter's Handbook. * If you bump the version for any reason, you should update the documentation * there. * Currently this lives here in the doc/ repository: * * head/en_US.ISO8859-1/books/porters-handbook/versions/chapter.xml * * scheme is: Rxx * 'R' is in the range 0 to 4 if this is a release branch or * x.0-CURRENT before RELENG_*_0 is created, otherwise 'R' is * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100096 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100097 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, * which by definition is always true on FreeBSD. This macro is also defined * on other systems that use the kernel of FreeBSD, such as GNU/kFreeBSD. * * It is tempting to use this macro in userland code when we want to enable * kernel-specific routines, and in fact it's fine to do this in code that * is part of FreeBSD itself. However, be aware that as presence of this * macro is still not widespread (e.g. older FreeBSD versions, 3rd party * compilers, etc), it is STRONGLY DISCOURAGED to check for this macro in * external applications without also checking for __FreeBSD__ as an * alternative. */ #undef __FreeBSD_kernel__ #define __FreeBSD_kernel__ #ifdef _KERNEL #define P_OSREL_SIGWAIT 700000 #define P_OSREL_SIGSEGV 700004 #define P_OSREL_MAP_ANON 800104 #define P_OSREL_MAP_FSTRICT 1100036 #define P_OSREL_SHUTDOWN_ENOTCONN 1100077 #define P_OSREL_MAJOR(x) ((x) / 100000) #endif #ifndef LOCORE #include #endif /* * Machine-independent constants (some used in following include files). * Redefined constants are from POSIX 1003.1 limits file. * * MAXCOMLEN should be >= sizeof(ac_comm) (see ) */ #include #define MAXCOMLEN 19 /* max command name remembered */ #define MAXINTERP PATH_MAX /* max interpreter file name length */ #define MAXLOGNAME 33 /* max login name length (incl. NUL) */ #define MAXUPRC CHILD_MAX /* max simultaneous processes */ #define NCARGS ARG_MAX /* max bytes for an exec function */ #define NGROUPS (NGROUPS_MAX+1) /* max number groups */ #define NOFILE OPEN_MAX /* max open files per process */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */ #define SPECNAMELEN 63 /* max length of devicename */ /* More types and definitions used throughout the kernel. */ #ifdef _KERNEL #include #include #ifndef LOCORE #include #include #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #endif #ifndef _KERNEL /* Signals. */ #include #endif /* Machine type dependent parameters. */ #include #ifndef _KERNEL #include #endif #ifndef DEV_BSHIFT #define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ #endif #define DEV_BSIZE (1<>PAGE_SHIFT) #endif /* * btodb() is messy and perhaps slow because `bytes' may be an off_t. We * want to shift an unsigned type to avoid sign extension and we don't * want to widen `bytes' unnecessarily. Assume that the result fits in * a daddr_t. */ #ifndef btodb #define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ (sizeof (bytes) > sizeof(long) \ ? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \ : (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT)) #endif #ifndef dbtob #define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ ((off_t)(db) << DEV_BSHIFT) #endif #define PRIMASK 0x0ff #define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */ #define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */ #define NZERO 0 /* default "nice" */ #define NBBY 8 /* number of bits in a byte */ #define NBPW sizeof(int) /* number of bytes per word (integer) */ #define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */ #define NODEV (dev_t)(-1) /* non-existent device */ /* * File system parameters and macros. * * MAXBSIZE - Filesystems are made out of blocks of at most MAXBSIZE bytes * per block. MAXBSIZE may be made larger without effecting * any existing filesystems as long as it does not exceed MAXPHYS, * and may be made smaller at the risk of not being able to use * filesystems which require a block size exceeding MAXBSIZE. * * MAXBCACHEBUF - Maximum size of a buffer in the buffer cache. This must * be >= MAXBSIZE and can be set differently for different * architectures by defining it in . * Making this larger allows NFS to do larger reads/writes. * * BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the * minimum KVM memory reservation the kernel is willing to make. * Filesystems can of course request smaller chunks. Actual * backing memory uses a chunk size of a page (PAGE_SIZE). * The default value here can be overridden on a per-architecture * basis by defining it in . This should * probably be done to increase its value, when MAXBCACHEBUF is * defined as a larger value in . * * If you make BKVASIZE too small you risk seriously fragmenting * the buffer KVM map which may slow things down a bit. If you * make it too big the kernel will not be able to optimally use * the KVM memory reserved for the buffer cache and will wind * up with too-few buffers. * * The default is 16384, roughly 2x the block size used by a * normal UFS filesystem. */ #define MAXBSIZE 65536 /* must be power of 2 */ #ifndef MAXBCACHEBUF #define MAXBCACHEBUF MAXBSIZE /* must be a power of 2 >= MAXBSIZE */ #endif #ifndef BKVASIZE #define BKVASIZE 16384 /* must be power of 2 */ #endif #define BKVAMASK (BKVASIZE-1) /* * MAXPATHLEN defines the longest permissible path length after expanding * symbolic links. It is used to allocate a temporary buffer from the buffer * pool in which to do the name expansion, hence should be a power of two, * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the * maximum number of symbolic links that may be expanded in a path name. * It should be set high enough to allow all legitimate uses, but halt * infinite loops reasonably quickly. */ #define MAXPATHLEN PATH_MAX #define MAXSYMLINKS 32 /* Bit map related macros. */ #define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY)) #define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY))) #define isset(a,i) \ (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) #define isclr(a,i) \ ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0) /* Macros for counting and rounding. */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #define nitems(x) (sizeof((x)) / sizeof((x)[0])) #define rounddown(x, y) (((x)/(y))*(y)) #define rounddown2(x, y) ((x)&(~((y)-1))) /* if y is power of two */ #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ #define powerof2(x) ((((x)-1)&(x))==0) /* Macros for min/max. */ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) #ifdef _KERNEL /* * Basic byte order function prototypes for non-inline functions. */ #ifndef LOCORE #ifndef _BYTEORDER_PROTOTYPED #define _BYTEORDER_PROTOTYPED __BEGIN_DECLS __uint32_t htonl(__uint32_t); __uint16_t htons(__uint16_t); __uint32_t ntohl(__uint32_t); __uint16_t ntohs(__uint16_t); __END_DECLS #endif #endif #ifndef lint #ifndef _BYTEORDER_FUNC_DEFINED #define _BYTEORDER_FUNC_DEFINED #define htonl(x) __htonl(x) #define htons(x) __htons(x) #define ntohl(x) __ntohl(x) #define ntohs(x) __ntohs(x) #endif /* !_BYTEORDER_FUNC_DEFINED */ #endif /* lint */ #endif /* _KERNEL */ /* * Scale factor for scaled integers used to count %cpu time and load avgs. * * The number of CPU `tick's that map to a unique `%age' can be expressed * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that * can be calculated (assuming 32 bits) can be closely approximated using * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). * * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age', * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024. */ #define FSHIFT 11 /* bits to right of fixed binary point */ #define FSCALE (1<> (PAGE_SHIFT - DEV_BSHIFT)) #define ctodb(db) /* calculates pages to devblks */ \ ((db) << (PAGE_SHIFT - DEV_BSHIFT)) /* * Old spelling of __containerof(). */ #define member2struct(s, m, x) \ ((struct s *)(void *)((char *)(x) - offsetof(struct s, m))) /* * Access a variable length array that has been declared as a fixed * length array. */ #define __PAST_END(array, offset) (((__typeof__(*(array)) *)(array))[offset]) #endif /* _SYS_PARAM_H_ */