From c6505491db10b09666c9e8ea5cb572dde2816134 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Tue, 27 Apr 2021 08:28:27 -0400 Subject: Scrub sbuf --- pw/Makefile | 5 +- pw/sbuf/subr_prf.c | 1310 --------------------------------------------------- pw/sbuf/subr_sbuf.c | 950 ------------------------------------- pw/sbuf/sys/sbuf.h | 123 ----- 4 files changed, 1 insertion(+), 2387 deletions(-) delete mode 100644 pw/sbuf/subr_prf.c delete mode 100644 pw/sbuf/subr_sbuf.c delete mode 100644 pw/sbuf/sys/sbuf.h diff --git a/pw/Makefile b/pw/Makefile index 776d231..f13d1e3 100644 --- a/pw/Makefile +++ b/pw/Makefile @@ -24,9 +24,6 @@ SRC := pw_utils.c \ cpdir.c \ strtonum.c -SBUFSRC := sbuf/subr_sbuf.c \ - sbuf/subr_prf.c - LIBUTILSRC := libutil/_secure_path.c \ libutil/gr_util.c \ libutil/flopen.c \ @@ -45,7 +42,7 @@ pw: $(SRC:%.c=%.o) $(LIBUTILSRC:%.c=%.o) $(SBUFSRC:%.c=%.o) ent.xml $(LDID) -Sent.xml $@ %.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< -I. -Isbuf -Ilibutil + $(CC) $(CFLAGS) -c -o $@ $< -I. -Ilibutil install-pw: pw pw.8 pw.conf.5 $(GINSTALL) -Dm755 pw $(DESTDIR)/$(PREFIX)/sbin/pw diff --git a/pw/sbuf/subr_prf.c b/pw/sbuf/subr_prf.c deleted file mode 100644 index de4ff4f..0000000 --- a/pw/sbuf/subr_prf.c +++ /dev/null @@ -1,1310 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1986, 1988, 1991, 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. - * 3. 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. - * - * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 - */ - -#include -__FBSDID("$FreeBSD$"); - -#ifdef _KERNEL -#include "opt_ddb.h" -#include "opt_printf.h" -#endif /* _KERNEL */ - -#include -#ifdef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else /* !_KERNEL */ -#include -#endif -#include -#include - -#ifdef DDB -#include -#endif - -/* - * Note that stdarg.h and the ANSI style va_start macro is used for both - * ANSI and traditional C compilers. - */ -#ifdef _KERNEL -#include -#else -#include -#endif - -/* - * This is needed for sbuf_putbuf() when compiled into userland. Due to the - * shared nature of this file, it's the only place to put it. - */ -#ifndef _KERNEL -#include -#endif - -#ifdef _KERNEL - -#define TOCONS 0x01 -#define TOTTY 0x02 -#define TOLOG 0x04 - -/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ -#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) - -struct putchar_arg { - int flags; - int pri; - struct tty *tty; - char *p_bufr; - size_t n_bufr; - char *p_next; - size_t remain; -}; - -struct snprintf_arg { - char *str; - size_t remain; -}; - -extern int log_open; - -static void msglogchar(int c, int pri); -static void msglogstr(char *str, int pri, int filter_cr); -static void putchar(int ch, void *arg); -static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); -static void snprintf_func(int ch, void *arg); - -static bool msgbufmapped; /* Set when safe to use msgbuf */ -int msgbuftrigger; -struct msgbuf *msgbufp; - -#ifndef BOOT_TAG_SZ -#define BOOT_TAG_SZ 32 -#endif -#ifndef BOOT_TAG -/* Tag used to mark the start of a boot in dmesg */ -#define BOOT_TAG "---<>---" -#endif - -static char current_boot_tag[BOOT_TAG_SZ + 1] = BOOT_TAG; -SYSCTL_STRING(_kern, OID_AUTO, boot_tag, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, - current_boot_tag, 0, "Tag added to dmesg at start of boot"); - -static int log_console_output = 1; -SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN, - &log_console_output, 0, "Duplicate console output to the syslog"); - -/* - * See the comment in log_console() below for more explanation of this. - */ -static int log_console_add_linefeed; -SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN, - &log_console_add_linefeed, 0, "log_console() adds extra newlines"); - -static int always_console_output; -SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN, - &always_console_output, 0, "Always output to console despite TIOCCONS"); - -/* - * Warn that a system table is full. - */ -void -tablefull(const char *tab) -{ - - log(LOG_ERR, "%s: table is full\n", tab); -} - -/* - * Uprintf prints to the controlling terminal for the current process. - */ -int -uprintf(const char *fmt, ...) -{ - va_list ap; - struct putchar_arg pca; - struct proc *p; - struct thread *td; - int retval; - - td = curthread; - if (TD_IS_IDLETHREAD(td)) - return (0); - - if (td->td_proc == initproc) { - /* Produce output when we fail to load /sbin/init: */ - va_start(ap, fmt); - retval = vprintf(fmt, ap); - va_end(ap); - return (retval); - } - - sx_slock(&proctree_lock); - p = td->td_proc; - PROC_LOCK(p); - if ((p->p_flag & P_CONTROLT) == 0) { - PROC_UNLOCK(p); - sx_sunlock(&proctree_lock); - return (0); - } - SESS_LOCK(p->p_session); - pca.tty = p->p_session->s_ttyp; - SESS_UNLOCK(p->p_session); - PROC_UNLOCK(p); - if (pca.tty == NULL) { - sx_sunlock(&proctree_lock); - return (0); - } - pca.flags = TOTTY; - pca.p_bufr = NULL; - va_start(ap, fmt); - tty_lock(pca.tty); - sx_sunlock(&proctree_lock); - retval = kvprintf(fmt, putchar, &pca, 10, ap); - tty_unlock(pca.tty); - va_end(ap); - return (retval); -} - -/* - * tprintf and vtprintf print on the controlling terminal associated with the - * given session, possibly to the log as well. - */ -void -tprintf(struct proc *p, int pri, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vtprintf(p, pri, fmt, ap); - va_end(ap); -} - -void -vtprintf(struct proc *p, int pri, const char *fmt, va_list ap) -{ - struct tty *tp = NULL; - int flags = 0; - struct putchar_arg pca; - struct session *sess = NULL; - - sx_slock(&proctree_lock); - if (pri != -1) - flags |= TOLOG; - if (p != NULL) { - PROC_LOCK(p); - if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { - sess = p->p_session; - sess_hold(sess); - PROC_UNLOCK(p); - tp = sess->s_ttyp; - if (tp != NULL && tty_checkoutq(tp)) - flags |= TOTTY; - else - tp = NULL; - } else - PROC_UNLOCK(p); - } - pca.pri = pri; - pca.tty = tp; - pca.flags = flags; - pca.p_bufr = NULL; - if (pca.tty != NULL) - tty_lock(pca.tty); - sx_sunlock(&proctree_lock); - kvprintf(fmt, putchar, &pca, 10, ap); - if (pca.tty != NULL) - tty_unlock(pca.tty); - if (sess != NULL) - sess_release(sess); - msgbuftrigger = 1; -} - -static int -_vprintf(int level, int flags, const char *fmt, va_list ap) -{ - struct putchar_arg pca; - int retval; -#ifdef PRINTF_BUFR_SIZE - char bufr[PRINTF_BUFR_SIZE]; -#endif - - TSENTER(); - pca.tty = NULL; - pca.pri = level; - pca.flags = flags; -#ifdef PRINTF_BUFR_SIZE - pca.p_bufr = bufr; - pca.p_next = pca.p_bufr; - pca.n_bufr = sizeof(bufr); - pca.remain = sizeof(bufr); - *pca.p_next = '\0'; -#else - /* Don't buffer console output. */ - pca.p_bufr = NULL; -#endif - - retval = kvprintf(fmt, putchar, &pca, 10, ap); - -#ifdef PRINTF_BUFR_SIZE - /* Write any buffered console/log output: */ - if (*pca.p_bufr != '\0') { - if (pca.flags & TOLOG) - msglogstr(pca.p_bufr, level, /*filter_cr*/1); - - if (pca.flags & TOCONS) - cnputs(pca.p_bufr); - } -#endif - - TSEXIT(); - return (retval); -} - -/* - * Log writes to the log buffer, and guarantees not to sleep (so can be - * called by interrupt routines). If there is no process reading the - * log yet, it writes to the console also. - */ -void -log(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vlog(level, fmt, ap); - va_end(ap); -} - -void -vlog(int level, const char *fmt, va_list ap) -{ - - (void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap); - msgbuftrigger = 1; -} - -#define CONSCHUNK 128 - -void -log_console(struct uio *uio) -{ - int c, error, nl; - char *consbuffer; - int pri; - - if (!log_console_output) - return; - - pri = LOG_INFO | LOG_CONSOLE; - uio = cloneuio(uio); - consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); - - nl = 0; - while (uio->uio_resid > 0) { - c = imin(uio->uio_resid, CONSCHUNK - 1); - error = uiomove(consbuffer, c, uio); - if (error != 0) - break; - /* Make sure we're NUL-terminated */ - consbuffer[c] = '\0'; - if (consbuffer[c - 1] == '\n') - nl = 1; - else - nl = 0; - msglogstr(consbuffer, pri, /*filter_cr*/ 1); - } - /* - * The previous behavior in log_console() is preserved when - * log_console_add_linefeed is non-zero. For that behavior, if an - * individual console write came in that was not terminated with a - * line feed, it would add a line feed. - * - * This results in different data in the message buffer than - * appears on the system console (which doesn't add extra line feed - * characters). - * - * A number of programs and rc scripts write a line feed, or a period - * and a line feed when they have completed their operation. On - * the console, this looks seamless, but when displayed with - * 'dmesg -a', you wind up with output that looks like this: - * - * Updating motd: - * . - * - * On the console, it looks like this: - * Updating motd:. - * - * We could add logic to detect that situation, or just not insert - * the extra newlines. Set the kern.log_console_add_linefeed - * sysctl/tunable variable to get the old behavior. - */ - if (!nl && log_console_add_linefeed) { - consbuffer[0] = '\n'; - consbuffer[1] = '\0'; - msglogstr(consbuffer, pri, /*filter_cr*/ 1); - } - msgbuftrigger = 1; - free(uio, M_IOV); - free(consbuffer, M_TEMP); -} - -int -printf(const char *fmt, ...) -{ - va_list ap; - int retval; - - va_start(ap, fmt); - retval = vprintf(fmt, ap); - va_end(ap); - - return (retval); -} - -int -vprintf(const char *fmt, va_list ap) -{ - int retval; - - retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap); - - if (!KERNEL_PANICKED()) - msgbuftrigger = 1; - - return (retval); -} - -static void -prf_putbuf(char *bufr, int flags, int pri) -{ - - if (flags & TOLOG) - msglogstr(bufr, pri, /*filter_cr*/1); - - if (flags & TOCONS) { - if ((!KERNEL_PANICKED()) && (constty != NULL)) - msgbuf_addstr(&consmsgbuf, -1, - bufr, /*filter_cr*/ 0); - - if ((constty == NULL) ||(always_console_output)) - cnputs(bufr); - } -} - -static void -putbuf(int c, struct putchar_arg *ap) -{ - /* Check if no console output buffer was provided. */ - if (ap->p_bufr == NULL) { - /* Output direct to the console. */ - if (ap->flags & TOCONS) - cnputc(c); - - if (ap->flags & TOLOG) - msglogchar(c, ap->pri); - } else { - /* Buffer the character: */ - *ap->p_next++ = c; - ap->remain--; - - /* Always leave the buffer zero terminated. */ - *ap->p_next = '\0'; - - /* Check if the buffer needs to be flushed. */ - if (ap->remain == 2 || c == '\n') { - prf_putbuf(ap->p_bufr, ap->flags, ap->pri); - - ap->p_next = ap->p_bufr; - ap->remain = ap->n_bufr; - *ap->p_next = '\0'; - } - - /* - * Since we fill the buffer up one character at a time, - * this should not happen. We should always catch it when - * ap->remain == 2 (if not sooner due to a newline), flush - * the buffer and move on. One way this could happen is - * if someone sets PRINTF_BUFR_SIZE to 1 or something - * similarly silly. - */ - KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd", - ap->remain)); - } -} - -/* - * Print a character on console or users terminal. If destination is - * the console then the last bunch of characters are saved in msgbuf for - * inspection later. - */ -static void -putchar(int c, void *arg) -{ - struct putchar_arg *ap = (struct putchar_arg*) arg; - struct tty *tp = ap->tty; - int flags = ap->flags; - - /* Don't use the tty code after a panic or while in ddb. */ - if (kdb_active) { - if (c != '\0') - cnputc(c); - return; - } - - if ((flags & TOTTY) && tp != NULL && !KERNEL_PANICKED()) - tty_putchar(tp, c); - - if ((flags & (TOCONS | TOLOG)) && c != '\0') - putbuf(c, ap); -} - -/* - * Scaled down version of sprintf(3). - */ -int -sprintf(char *buf, const char *cfmt, ...) -{ - int retval; - va_list ap; - - va_start(ap, cfmt); - retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); - buf[retval] = '\0'; - va_end(ap); - return (retval); -} - -/* - * Scaled down version of vsprintf(3). - */ -int -vsprintf(char *buf, const char *cfmt, va_list ap) -{ - int retval; - - retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); - buf[retval] = '\0'; - return (retval); -} - -/* - * Scaled down version of snprintf(3). - */ -int -snprintf(char *str, size_t size, const char *format, ...) -{ - int retval; - va_list ap; - - va_start(ap, format); - retval = vsnprintf(str, size, format, ap); - va_end(ap); - return(retval); -} - -/* - * Scaled down version of vsnprintf(3). - */ -int -vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - struct snprintf_arg info; - int retval; - - info.str = str; - info.remain = size; - retval = kvprintf(format, snprintf_func, &info, 10, ap); - if (info.remain >= 1) - *info.str++ = '\0'; - return (retval); -} - -/* - * Kernel version which takes radix argument vsnprintf(3). - */ -int -vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) -{ - struct snprintf_arg info; - int retval; - - info.str = str; - info.remain = size; - retval = kvprintf(format, snprintf_func, &info, radix, ap); - if (info.remain >= 1) - *info.str++ = '\0'; - return (retval); -} - -static void -snprintf_func(int ch, void *arg) -{ - struct snprintf_arg *const info = arg; - - if (info->remain >= 2) { - *info->str++ = ch; - info->remain--; - } -} - -/* - * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse - * order; return an optional length and a pointer to the last character - * written in the buffer (i.e., the first character of the string). - * The buffer pointed to by `nbuf' must have length >= MAXNBUF. - */ -static char * -ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) -{ - char *p, c; - - p = nbuf; - *p = '\0'; - do { - c = hex2ascii(num % base); - *++p = upper ? toupper(c) : c; - } while (num /= base); - if (lenp) - *lenp = p - nbuf; - return (p); -} - -/* - * Scaled down version of printf(3). - * - * Two additional formats: - * - * The format %b is supported to decode error registers. - * Its usage is: - * - * printf("reg=%b\n", regval, "*"); - * - * where is the output base expressed as a control character, e.g. - * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, - * the first of which gives the bit number to be inspected (origin 1), and - * the next characters (up to a control character, i.e. a character <= 32), - * give the name of the register. Thus: - * - * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); - * - * would produce output: - * - * reg=3 - * - * XXX: %D -- Hexdump, takes pointer and separator string: - * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX - * ("%*D", len, ptr, " " -> XX XX XX XX ... - */ -int -kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) -{ -#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } - char nbuf[MAXNBUF]; - char *d; - const char *p, *percent, *q; - u_char *up; - int ch, n; - uintmax_t num; - int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; - int cflag, hflag, jflag, tflag, zflag; - int bconv, dwidth, upper; - char padc; - int stop = 0, retval = 0; - - num = 0; - q = NULL; - if (!func) - d = (char *) arg; - else - d = NULL; - - if (fmt == NULL) - fmt = "(fmt null)\n"; - - if (radix < 2 || radix > 36) - radix = 10; - - for (;;) { - padc = ' '; - width = 0; - while ((ch = (u_char)*fmt++) != '%' || stop) { - if (ch == '\0') - return (retval); - PCHAR(ch); - } - percent = fmt - 1; - qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; - sign = 0; dot = 0; bconv = 0; dwidth = 0; upper = 0; - cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; -reswitch: switch (ch = (u_char)*fmt++) { - case '.': - dot = 1; - goto reswitch; - case '#': - sharpflag = 1; - goto reswitch; - case '+': - sign = 1; - goto reswitch; - case '-': - ladjust = 1; - goto reswitch; - case '%': - PCHAR(ch); - break; - case '*': - if (!dot) { - width = va_arg(ap, int); - if (width < 0) { - ladjust = !ladjust; - width = -width; - } - } else { - dwidth = va_arg(ap, int); - } - goto reswitch; - case '0': - if (!dot) { - padc = '0'; - goto reswitch; - } - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - for (n = 0;; ++fmt) { - n = n * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') - break; - } - if (dot) - dwidth = n; - else - width = n; - goto reswitch; - case 'b': - ladjust = 1; - bconv = 1; - goto handle_nosign; - case 'c': - width -= 1; - - if (!ladjust && width > 0) - while (width--) - PCHAR(padc); - PCHAR(va_arg(ap, int)); - if (ladjust && width > 0) - while (width--) - PCHAR(padc); - break; - case 'D': - up = va_arg(ap, u_char *); - p = va_arg(ap, char *); - if (!width) - width = 16; - while(width--) { - PCHAR(hex2ascii(*up >> 4)); - PCHAR(hex2ascii(*up & 0x0f)); - up++; - if (width) - for (q=p;*q;q++) - PCHAR(*q); - } - break; - case 'd': - case 'i': - base = 10; - sign = 1; - goto handle_sign; - case 'h': - if (hflag) { - hflag = 0; - cflag = 1; - } else - hflag = 1; - goto reswitch; - case 'j': - jflag = 1; - goto reswitch; - case 'l': - if (lflag) { - lflag = 0; - qflag = 1; - } else - lflag = 1; - goto reswitch; - case 'n': - /* - * We do not support %n in kernel, but consume the - * argument. - */ - if (jflag) - (void)va_arg(ap, intmax_t *); - else if (qflag) - (void)va_arg(ap, quad_t *); - else if (lflag) - (void)va_arg(ap, long *); - else if (zflag) - (void)va_arg(ap, size_t *); - else if (hflag) - (void)va_arg(ap, short *); - else if (cflag) - (void)va_arg(ap, char *); - else - (void)va_arg(ap, int *); - break; - case 'o': - base = 8; - goto handle_nosign; - case 'p': - base = 16; - sharpflag = (width == 0); - sign = 0; - num = (uintptr_t)va_arg(ap, void *); - goto number; - case 'q': - qflag = 1; - goto reswitch; - case 'r': - base = radix; - if (sign) - goto handle_sign; - goto handle_nosign; - case 's': - p = va_arg(ap, char *); - if (p == NULL) - p = "(null)"; - if (!dot) - n = strlen (p); - else - for (n = 0; n < dwidth && p[n]; n++) - continue; - - width -= n; - - if (!ladjust && width > 0) - while (width--) - PCHAR(padc); - while (n--) - PCHAR(*p++); - if (ladjust && width > 0) - while (width--) - PCHAR(padc); - break; - case 't': - tflag = 1; - goto reswitch; - case 'u': - base = 10; - goto handle_nosign; - case 'X': - upper = 1; - /* FALLTHROUGH */ - case 'x': - base = 16; - goto handle_nosign; - case 'y': - base = 16; - sign = 1; - goto handle_sign; - case 'z': - zflag = 1; - goto reswitch; -handle_nosign: - sign = 0; - if (jflag) - num = va_arg(ap, uintmax_t); - else if (qflag) - num = va_arg(ap, u_quad_t); - else if (tflag) - num = va_arg(ap, ptrdiff_t); - else if (lflag) - num = va_arg(ap, u_long); - else if (zflag) - num = va_arg(ap, size_t); - else if (hflag) - num = (u_short)va_arg(ap, int); - else if (cflag) - num = (u_char)va_arg(ap, int); - else - num = va_arg(ap, u_int); - if (bconv) { - q = va_arg(ap, char *); - base = *q++; - } - goto number; -handle_sign: - if (jflag) - num = va_arg(ap, intmax_t); - else if (qflag) - num = va_arg(ap, quad_t); - else if (tflag) - num = va_arg(ap, ptrdiff_t); - else if (lflag) - num = va_arg(ap, long); - else if (zflag) - num = va_arg(ap, ssize_t); - else if (hflag) - num = (short)va_arg(ap, int); - else if (cflag) - num = (char)va_arg(ap, int); - else - num = va_arg(ap, int); -number: - if (sign && (intmax_t)num < 0) { - neg = 1; - num = -(intmax_t)num; - } - p = ksprintn(nbuf, num, base, &n, upper); - tmp = 0; - if (sharpflag && num != 0) { - if (base == 8) - tmp++; - else if (base == 16) - tmp += 2; - } - if (neg) - tmp++; - - if (!ladjust && padc == '0') - dwidth = width - tmp; - width -= tmp + imax(dwidth, n); - dwidth -= n; - if (!ladjust) - while (width-- > 0) - PCHAR(' '); - if (neg) - PCHAR('-'); - if (sharpflag && num != 0) { - if (base == 8) { - PCHAR('0'); - } else if (base == 16) { - PCHAR('0'); - PCHAR('x'); - } - } - while (dwidth-- > 0) - PCHAR('0'); - - while (*p) - PCHAR(*p--); - - if (bconv && num != 0) { - /* %b conversion flag format. */ - tmp = retval; - while (*q) { - n = *q++; - if (num & (1 << (n - 1))) { - PCHAR(retval != tmp ? - ',' : '<'); - for (; (n = *q) > ' '; ++q) - PCHAR(n); - } else - for (; *q > ' '; ++q) - continue; - } - if (retval != tmp) { - PCHAR('>'); - width -= retval - tmp; - } - } - - if (ladjust) - while (width-- > 0) - PCHAR(' '); - - break; - default: - while (percent < fmt) - PCHAR(*percent++); - /* - * Since we ignore a formatting argument it is no - * longer safe to obey the remaining formatting - * arguments as the arguments will no longer match - * the format specs. - */ - stop = 1; - break; - } - } -#undef PCHAR -} - -/* - * Put character in log buffer with a particular priority. - */ -static void -msglogchar(int c, int pri) -{ - static int lastpri = -1; - static int dangling; - char nbuf[MAXNBUF]; - char *p; - - if (!msgbufmapped) - return; - if (c == '\0' || c == '\r') - return; - if (pri != -1 && pri != lastpri) { - if (dangling) { - msgbuf_addchar(msgbufp, '\n'); - dangling = 0; - } - msgbuf_addchar(msgbufp, '<'); - for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;) - msgbuf_addchar(msgbufp, *p--); - msgbuf_addchar(msgbufp, '>'); - lastpri = pri; - } - msgbuf_addchar(msgbufp, c); - if (c == '\n') { - dangling = 0; - lastpri = -1; - } else { - dangling = 1; - } -} - -static void -msglogstr(char *str, int pri, int filter_cr) -{ - if (!msgbufmapped) - return; - - msgbuf_addstr(msgbufp, pri, str, filter_cr); -} - -void -msgbufinit(void *ptr, int size) -{ - char *cp; - static struct msgbuf *oldp = NULL; - bool print_boot_tag; - - size -= sizeof(*msgbufp); - cp = (char *)ptr; - print_boot_tag = !msgbufmapped; - /* Attempt to fetch kern.boot_tag tunable on first mapping */ - if (!msgbufmapped) - TUNABLE_STR_FETCH("kern.boot_tag", current_boot_tag, - sizeof(current_boot_tag)); - msgbufp = (struct msgbuf *)(cp + size); - msgbuf_reinit(msgbufp, cp, size); - if (msgbufmapped && oldp != msgbufp) - msgbuf_copy(oldp, msgbufp); - msgbufmapped = true; - if (print_boot_tag && *current_boot_tag != '\0') - printf("%s\n", current_boot_tag); - oldp = msgbufp; -} - -/* Sysctls for accessing/clearing the msgbuf */ -static int -sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) -{ - char buf[128]; - u_int seq; - int error, len; - - error = priv_check(req->td, PRIV_MSGBUF); - if (error) - return (error); - - /* Read the whole buffer, one chunk at a time. */ - mtx_lock(&msgbuf_lock); - msgbuf_peekbytes(msgbufp, NULL, 0, &seq); - for (;;) { - len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq); - mtx_unlock(&msgbuf_lock); - if (len == 0) - return (SYSCTL_OUT(req, "", 1)); /* add nulterm */ - - error = sysctl_handle_opaque(oidp, buf, len, req); - if (error) - return (error); - - mtx_lock(&msgbuf_lock); - } -} - -SYSCTL_PROC(_kern, OID_AUTO, msgbuf, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, - NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); - -static int msgbuf_clearflag; - -static int -sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) -{ - int error; - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); - if (!error && req->newptr) { - mtx_lock(&msgbuf_lock); - msgbuf_clear(msgbufp); - mtx_unlock(&msgbuf_lock); - msgbuf_clearflag = 0; - } - return (error); -} - -SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE, - &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I", - "Clear kernel message buffer"); - -#ifdef DDB - -DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) -{ - int i, j; - - if (!msgbufmapped) { - db_printf("msgbuf not mapped yet\n"); - return; - } - db_printf("msgbufp = %p\n", msgbufp); - db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", - msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, - msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); - for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) { - j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); - db_printf("%c", msgbufp->msg_ptr[j]); - } - db_printf("\n"); -} - -#endif /* DDB */ - -void -hexdump(const void *ptr, int length, const char *hdr, int flags) -{ - int i, j, k; - int cols; - const unsigned char *cp; - char delim; - - if ((flags & HD_DELIM_MASK) != 0) - delim = (flags & HD_DELIM_MASK) >> 8; - else - delim = ' '; - - if ((flags & HD_COLUMN_MASK) != 0) - cols = flags & HD_COLUMN_MASK; - else - cols = 16; - - cp = ptr; - for (i = 0; i < length; i+= cols) { - if (hdr != NULL) - printf("%s", hdr); - - if ((flags & HD_OMIT_COUNT) == 0) - printf("%04x ", i); - - if ((flags & HD_OMIT_HEX) == 0) { - for (j = 0; j < cols; j++) { - k = i + j; - if (k < length) - printf("%c%02x", delim, cp[k]); - else - printf(" "); - } - } - - if ((flags & HD_OMIT_CHARS) == 0) { - printf(" |"); - for (j = 0; j < cols; j++) { - k = i + j; - if (k >= length) - printf(" "); - else if (cp[k] >= ' ' && cp[k] <= '~') - printf("%c", cp[k]); - else - printf("."); - } - printf("|"); - } - printf("\n"); - } -} -#endif /* _KERNEL */ - -void -sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr, - int flags) -{ - int i, j, k; - int cols; - const unsigned char *cp; - char delim; - - if ((flags & HD_DELIM_MASK) != 0) - delim = (flags & HD_DELIM_MASK) >> 8; - else - delim = ' '; - - if ((flags & HD_COLUMN_MASK) != 0) - cols = flags & HD_COLUMN_MASK; - else - cols = 16; - - cp = ptr; - for (i = 0; i < length; i+= cols) { - if (hdr != NULL) - sbuf_printf(sb, "%s", hdr); - - if ((flags & HD_OMIT_COUNT) == 0) - sbuf_printf(sb, "%04x ", i); - - if ((flags & HD_OMIT_HEX) == 0) { - for (j = 0; j < cols; j++) { - k = i + j; - if (k < length) - sbuf_printf(sb, "%c%02x", delim, cp[k]); - else - sbuf_printf(sb, " "); - } - } - - if ((flags & HD_OMIT_CHARS) == 0) { - sbuf_printf(sb, " |"); - for (j = 0; j < cols; j++) { - k = i + j; - if (k >= length) - sbuf_printf(sb, " "); - else if (cp[k] >= ' ' && cp[k] <= '~') - sbuf_printf(sb, "%c", cp[k]); - else - sbuf_printf(sb, "."); - } - sbuf_printf(sb, "|"); - } - sbuf_printf(sb, "\n"); - } -} - -#ifdef _KERNEL -void -counted_warning(unsigned *counter, const char *msg) -{ - struct thread *td; - unsigned c; - - for (;;) { - c = *counter; - if (c == 0) - break; - if (atomic_cmpset_int(counter, c, c - 1)) { - td = curthread; - log(LOG_INFO, "pid %d (%s) %s%s\n", - td->td_proc->p_pid, td->td_name, msg, - c > 1 ? "" : " - not logging anymore"); - break; - } - } -} -#endif - -#ifdef _KERNEL -void -sbuf_putbuf(struct sbuf *sb) -{ - - prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1); -} -#else -void -sbuf_putbuf(struct sbuf *sb) -{ - - printf("%s", sbuf_data(sb)); -} -#endif - -int -sbuf_printf_drain(void *arg, const char *data, int len) -{ - size_t *retvalptr; - int r; -#ifdef _KERNEL - char *dataptr; - char oldchr; - - /* - * This is allowed as an extra byte is always resvered for - * terminating NUL byte. Save and restore the byte because - * we might be flushing a record, and there may be valid - * data after the buffer. - */ - oldchr = data[len]; - dataptr = __DECONST(char *, data); - dataptr[len] = '\0'; - - prf_putbuf(dataptr, TOLOG | TOCONS, -1); - r = len; - - dataptr[len] = oldchr; - -#else /* !_KERNEL */ - - r = printf("%.*s", len, data); - if (r < 0) - return (-errno); - -#endif - - retvalptr = arg; - if (retvalptr != NULL) - *retvalptr += r; - - return (r); -} diff --git a/pw/sbuf/subr_sbuf.c b/pw/sbuf/subr_sbuf.c deleted file mode 100644 index 5588bae..0000000 --- a/pw/sbuf/subr_sbuf.c +++ /dev/null @@ -1,950 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000-2008 Poul-Henning Kamp - * Copyright (c) 2000-2008 Dag-Erling Coïdan Smørgrav - * 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 - * in this position and unchanged. - * 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 - -#ifdef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#else /* _KERNEL */ -#include -#include -#include -#include -#include -#include -#include -#endif /* _KERNEL */ - -#include - -#ifdef _KERNEL -static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); -#define SBMALLOC(size, flags) malloc(size, M_SBUF, (flags) | M_ZERO) -#define SBFREE(buf) free(buf, M_SBUF) -#else /* _KERNEL */ -#define KASSERT(e, m) -#define SBMALLOC(size, flags) calloc(1, size) -#define SBFREE(buf) free(buf) -#endif /* _KERNEL */ - -/* - * Predicates - */ -#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) -#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) -#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) -#define SBUF_ISDRAINATEOL(s) ((s)->s_flags & SBUF_DRAINATEOL) -#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) -#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1)) -#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) -#define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) -#define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL) -#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR) -#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s)) -#define SBUF_MALLOCFLAG(s) \ - (((s)->s_flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK) - -/* - * Set / clear flags - */ -#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) -#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) - -#define SBUF_MINSIZE 2 /* Min is 1 byte + nulterm. */ -#define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */ - -#ifdef PAGE_SIZE -#define SBUF_MAXEXTENDSIZE PAGE_SIZE -#define SBUF_MAXEXTENDINCR PAGE_SIZE -#else -#define SBUF_MAXEXTENDSIZE 4096 -#define SBUF_MAXEXTENDINCR 4096 -#endif - -/* - * Debugging support - */ -#if defined(_KERNEL) && defined(INVARIANTS) - -static void -_assert_sbuf_integrity(const char *fun, struct sbuf *s) -{ - - KASSERT(s != NULL, - ("%s called with a NULL sbuf pointer", fun)); - KASSERT(s->s_buf != NULL, - ("%s called with uninitialized or corrupt sbuf", fun)); - if (SBUF_ISFINISHED(s) && SBUF_NULINCLUDED(s)) { - KASSERT(s->s_len <= s->s_size, - ("wrote past end of sbuf (%jd >= %jd)", - (intmax_t)s->s_len, (intmax_t)s->s_size)); - } else { - KASSERT(s->s_len < s->s_size, - ("wrote past end of sbuf (%jd >= %jd)", - (intmax_t)s->s_len, (intmax_t)s->s_size)); - } -} - -static void -_assert_sbuf_state(const char *fun, struct sbuf *s, int state) -{ - - KASSERT((s->s_flags & SBUF_FINISHED) == state, - ("%s called with %sfinished or corrupt sbuf", fun, - (state ? "un" : ""))); -} - -#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s)) -#define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i)) - -#else /* _KERNEL && INVARIANTS */ - -#define assert_sbuf_integrity(s) do { } while (0) -#define assert_sbuf_state(s, i) do { } while (0) - -#endif /* _KERNEL && INVARIANTS */ - -#ifdef CTASSERT -CTASSERT(powerof2(SBUF_MAXEXTENDSIZE)); -CTASSERT(powerof2(SBUF_MAXEXTENDINCR)); -#endif - -static int -sbuf_extendsize(int size) -{ - int newsize; - - if (size < (int)SBUF_MAXEXTENDSIZE) { - newsize = SBUF_MINEXTENDSIZE; - while (newsize < size) - newsize *= 2; - } else { - newsize = roundup(size, SBUF_MAXEXTENDINCR); - } - KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size)); - return (newsize); -} - -/* - * Extend an sbuf. - */ -static int -sbuf_extend(struct sbuf *s, int addlen) -{ - char *newbuf; - int newsize; - - if (!SBUF_CANEXTEND(s)) - return (-1); - newsize = sbuf_extendsize(s->s_size + addlen); - newbuf = SBMALLOC(newsize, SBUF_MALLOCFLAG(s)); - if (newbuf == NULL) - return (-1); - memcpy(newbuf, s->s_buf, s->s_size); - if (SBUF_ISDYNAMIC(s)) - SBFREE(s->s_buf); - else - SBUF_SETFLAG(s, SBUF_DYNAMIC); - s->s_buf = newbuf; - s->s_size = newsize; - return (0); -} - -/* - * Initialize an sbuf. - * If buf is non-NULL, it points to a static or already-allocated string - * big enough to hold at least length characters. - */ -struct sbuf * -sbuf_new(struct sbuf *s, char *buf, int length, int flags) -{ - - KASSERT(length >= 0, - ("attempt to create an sbuf of negative length (%d)", length)); - KASSERT((flags & ~SBUF_USRFLAGMSK) == 0, - ("%s called with invalid flags", __func__)); - KASSERT((flags & SBUF_AUTOEXTEND) || length >= SBUF_MINSIZE, - ("sbuf buffer %d smaller than minimum %d bytes", length, - SBUF_MINSIZE)); - - flags &= SBUF_USRFLAGMSK; - - /* - * Allocate 'DYNSTRUCT' sbuf from the heap, if NULL 's' was provided. - */ - if (s == NULL) { - s = SBMALLOC(sizeof(*s), - (flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK); - if (s == NULL) - goto out; - SBUF_SETFLAG(s, SBUF_DYNSTRUCT); - } else { - /* - * DYNSTRUCT SBMALLOC sbufs are allocated with M_ZERO, but - * user-provided sbuf objects must be initialized. - */ - memset(s, 0, sizeof(*s)); - } - - s->s_flags |= flags; - s->s_size = length; - s->s_buf = buf; - /* - * Never-written sbufs do not need \n termination. - */ - SBUF_SETFLAG(s, SBUF_DRAINATEOL); - - /* - * Allocate DYNAMIC, i.e., heap data buffer backing the sbuf, if no - * buffer was provided. - */ - if (s->s_buf == NULL) { - if (SBUF_CANEXTEND(s)) - s->s_size = sbuf_extendsize(s->s_size); - s->s_buf = SBMALLOC(s->s_size, SBUF_MALLOCFLAG(s)); - if (s->s_buf == NULL) - goto out; - SBUF_SETFLAG(s, SBUF_DYNAMIC); - } - -out: - if (s != NULL && s->s_buf == NULL) { - if (SBUF_ISDYNSTRUCT(s)) - SBFREE(s); - s = NULL; - } - return (s); -} - -#ifdef _KERNEL -/* - * Create an sbuf with uio data - */ -struct sbuf * -sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) -{ - - KASSERT(uio != NULL, - ("%s called with NULL uio pointer", __func__)); - KASSERT(error != NULL, - ("%s called with NULL error pointer", __func__)); - - s = sbuf_new(s, NULL, uio->uio_resid + 1, 0); - if (s == NULL) { - *error = ENOMEM; - return (NULL); - } - *error = uiomove(s->s_buf, uio->uio_resid, uio); - if (*error != 0) { - sbuf_delete(s); - return (NULL); - } - s->s_len = s->s_size - 1; - if (SBUF_ISSECTION(s)) - s->s_sect_len = s->s_size - 1; - *error = 0; - return (s); -} -#endif - -int -sbuf_get_flags(struct sbuf *s) -{ - - return (s->s_flags & SBUF_USRFLAGMSK); -} - -void -sbuf_clear_flags(struct sbuf *s, int flags) -{ - - s->s_flags &= ~(flags & SBUF_USRFLAGMSK); -} - -void -sbuf_set_flags(struct sbuf *s, int flags) -{ - - s->s_flags |= (flags & SBUF_USRFLAGMSK); -} - -/* - * Clear an sbuf and reset its position. - */ -void -sbuf_clear(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - KASSERT(s->s_drain_func == NULL, - ("%s makes no sense on sbuf %p with drain", __func__, s)); - - SBUF_CLEARFLAG(s, SBUF_FINISHED); - s->s_error = 0; - s->s_len = 0; - s->s_rec_off = 0; - s->s_sect_len = 0; -} - -/* - * Set the sbuf's end position to an arbitrary value. - * Effectively truncates the sbuf at the new position. - */ -int -sbuf_setpos(struct sbuf *s, ssize_t pos) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - KASSERT(pos >= 0, - ("attempt to seek to a negative position (%jd)", (intmax_t)pos)); - KASSERT(pos < s->s_size, - ("attempt to seek past end of sbuf (%jd >= %jd)", - (intmax_t)pos, (intmax_t)s->s_size)); - KASSERT(!SBUF_ISSECTION(s), - ("attempt to seek when in a section")); - - if (pos < 0 || pos > s->s_len) - return (-1); - s->s_len = pos; - return (0); -} - -/* - * Drain into a counter. Counts amount of data without producing output. - * Useful for cases like sysctl, where user may first request only size. - * This allows to avoid pointless allocation/freeing of large buffers. - */ -int -sbuf_count_drain(void *arg, const char *data __unused, int len) -{ - size_t *sizep; - - sizep = (size_t *)arg; - *sizep += len; - return (len); -} - -/* - * Set up a drain function and argument on an sbuf to flush data to - * when the sbuf buffer overflows. - */ -void -sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx) -{ - - assert_sbuf_state(s, 0); - assert_sbuf_integrity(s); - KASSERT(func == s->s_drain_func || s->s_len == 0, - ("Cannot change drain to %p on non-empty sbuf %p", func, s)); - s->s_drain_func = func; - s->s_drain_arg = ctx; -} - -/* - * Call the drain and process the return. - */ -static int -sbuf_drain(struct sbuf *s) -{ - int len; - - KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); - KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); - - if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) - return (s->s_error = EDEADLK); - len = s->s_drain_func(s->s_drain_arg, s->s_buf, - SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); - if (len <= 0) { - s->s_error = len ? -len : EDEADLK; - return (s->s_error); - } - KASSERT(len > 0 && len <= s->s_len, - ("Bad drain amount %d for sbuf %p", len, s)); - s->s_len -= len; - s->s_rec_off -= len; - /* - * Fast path for the expected case where all the data was - * drained. - */ - if (s->s_len == 0) { - /* - * When the s_buf is entirely drained, we need to remember if - * the last character was a '\n' or not for - * sbuf_nl_terminate(). - */ - if (s->s_buf[len - 1] == '\n') - SBUF_SETFLAG(s, SBUF_DRAINATEOL); - else - SBUF_CLEARFLAG(s, SBUF_DRAINATEOL); - return (0); - } - /* - * Move the remaining characters to the beginning of the - * string. - */ - memmove(s->s_buf, s->s_buf + len, s->s_len); - return (0); -} - -/* - * Append bytes to an sbuf. This is the core function for appending - * to an sbuf and is the main place that deals with extending the - * buffer and marking overflow. - */ -static void -sbuf_put_bytes(struct sbuf *s, const char *buf, size_t len) -{ - size_t n; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (s->s_error != 0) - return; - while (len > 0) { - if (SBUF_FREESPACE(s) <= 0) { - /* - * If there is a drain, use it, otherwise extend the - * buffer. - */ - if (s->s_drain_func != NULL) - (void)sbuf_drain(s); - else if (sbuf_extend(s, len > INT_MAX ? INT_MAX : len) - < 0) - s->s_error = ENOMEM; - if (s->s_error != 0) - return; - } - n = SBUF_FREESPACE(s); - if (len < n) - n = len; - memcpy(&s->s_buf[s->s_len], buf, n); - s->s_len += n; - if (SBUF_ISSECTION(s)) - s->s_sect_len += n; - len -= n; - buf += n; - } -} - -static void -sbuf_put_byte(struct sbuf *s, char c) -{ - - sbuf_put_bytes(s, &c, 1); -} - -/* - * Append a byte string to an sbuf. - */ -int -sbuf_bcat(struct sbuf *s, const void *buf, size_t len) -{ - - sbuf_put_bytes(s, buf, len); - if (s->s_error != 0) - return (-1); - return (0); -} - -#ifdef _KERNEL -/* - * Copy a byte string from userland into an sbuf. - */ -int -sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - KASSERT(s->s_drain_func == NULL, - ("Nonsensical copyin to sbuf %p with a drain", s)); - - if (s->s_error != 0) - return (-1); - if (len == 0) - return (0); - if (len > SBUF_FREESPACE(s)) { - sbuf_extend(s, len - SBUF_FREESPACE(s)); - if (SBUF_FREESPACE(s) < len) - len = SBUF_FREESPACE(s); - } - if (copyin(uaddr, s->s_buf + s->s_len, len) != 0) - return (-1); - s->s_len += len; - - return (0); -} -#endif - -/* - * Copy a byte string into an sbuf. - */ -int -sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - sbuf_clear(s); - return (sbuf_bcat(s, buf, len)); -} - -/* - * Append a string to an sbuf. - */ -int -sbuf_cat(struct sbuf *s, const char *str) -{ - size_t n; - - n = strlen(str); - sbuf_put_bytes(s, str, n); - if (s->s_error != 0) - return (-1); - return (0); -} - -#ifdef _KERNEL -/* - * Append a string from userland to an sbuf. - */ -int -sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) -{ - size_t done; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - KASSERT(s->s_drain_func == NULL, - ("Nonsensical copyin to sbuf %p with a drain", s)); - - if (s->s_error != 0) - return (-1); - - if (len == 0) - len = SBUF_FREESPACE(s); /* XXX return 0? */ - if (len > SBUF_FREESPACE(s)) { - sbuf_extend(s, len); - if (SBUF_FREESPACE(s) < len) - len = SBUF_FREESPACE(s); - } - switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) { - case ENAMETOOLONG: - s->s_error = ENOMEM; - /* fall through */ - case 0: - s->s_len += done - 1; - if (SBUF_ISSECTION(s)) - s->s_sect_len += done - 1; - break; - default: - return (-1); /* XXX */ - } - - return (done); -} -#endif - -/* - * Copy a string into an sbuf. - */ -int -sbuf_cpy(struct sbuf *s, const char *str) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - sbuf_clear(s); - return (sbuf_cat(s, str)); -} - -/* - * Format the given argument list and append the resulting string to an sbuf. - */ -#ifdef _KERNEL - -/* - * Append a non-NUL character to an sbuf. This prototype signature is - * suitable for use with kvprintf(9). - */ -static void -sbuf_putc_func(int c, void *arg) -{ - - if (c != '\0') - sbuf_put_byte(arg, c); -} - -int -sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - KASSERT(fmt != NULL, - ("%s called with a NULL format string", __func__)); - - (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap); - if (s->s_error != 0) - return (-1); - return (0); -} -#else /* !_KERNEL */ -int -sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) -{ - va_list ap_copy; - int error, len; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - KASSERT(fmt != NULL, - ("%s called with a NULL format string", __func__)); - - if (s->s_error != 0) - return (-1); - - /* - * For the moment, there is no way to get vsnprintf(3) to hand - * back a character at a time, to push everything into - * sbuf_putc_func() as was done for the kernel. - * - * In userspace, while drains are useful, there's generally - * not a problem attempting to malloc(3) on out of space. So - * expand a userland sbuf if there is not enough room for the - * data produced by sbuf_[v]printf(3). - */ - - error = 0; - do { - va_copy(ap_copy, ap); - len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1, - fmt, ap_copy); - if (len < 0) { - s->s_error = errno; - return (-1); - } - va_end(ap_copy); - - if (SBUF_FREESPACE(s) >= len) - break; - /* Cannot print with the current available space. */ - if (s->s_drain_func != NULL && s->s_len > 0) - error = sbuf_drain(s); /* sbuf_drain() sets s_error. */ - else if (sbuf_extend(s, len - SBUF_FREESPACE(s)) != 0) - s->s_error = error = ENOMEM; - } while (error == 0); - - /* - * s->s_len is the length of the string, without the terminating nul. - * When updating s->s_len, we must subtract 1 from the length that - * we passed into vsnprintf() because that length includes the - * terminating nul. - * - * vsnprintf() returns the amount that would have been copied, - * given sufficient space, so don't over-increment s_len. - */ - if (SBUF_FREESPACE(s) < len) - len = SBUF_FREESPACE(s); - s->s_len += len; - if (SBUF_ISSECTION(s)) - s->s_sect_len += len; - - KASSERT(s->s_len < s->s_size, - ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); - - if (s->s_error != 0) - return (-1); - return (0); -} -#endif /* _KERNEL */ - -/* - * Format the given arguments and append the resulting string to an sbuf. - */ -int -sbuf_printf(struct sbuf *s, const char *fmt, ...) -{ - va_list ap; - int result; - - va_start(ap, fmt); - result = sbuf_vprintf(s, fmt, ap); - va_end(ap); - return (result); -} - -/* - * Append a character to an sbuf. - */ -int -sbuf_putc(struct sbuf *s, int c) -{ - - sbuf_put_byte(s, c); - if (s->s_error != 0) - return (-1); - return (0); -} - -/* - * Append a trailing newline to a non-empty sbuf, if one is not already - * present. Handles sbufs with drain functions correctly. - */ -int -sbuf_nl_terminate(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - /* - * If the s_buf isn't empty, the last byte is simply s_buf[s_len - 1]. - * - * If the s_buf is empty because a drain function drained it, we - * remember if the last byte was a \n with the SBUF_DRAINATEOL flag in - * sbuf_drain(). - * - * In either case, we only append a \n if the previous character was - * something else. - */ - if (s->s_len == 0) { - if (!SBUF_ISDRAINATEOL(s)) - sbuf_put_byte(s, '\n'); - } else if (s->s_buf[s->s_len - 1] != '\n') - sbuf_put_byte(s, '\n'); - - if (s->s_error != 0) - return (-1); - return (0); -} - -/* - * Trim whitespace characters from end of an sbuf. - */ -int -sbuf_trim(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - KASSERT(s->s_drain_func == NULL, - ("%s makes no sense on sbuf %p with drain", __func__, s)); - - if (s->s_error != 0) - return (-1); - - while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) { - --s->s_len; - if (SBUF_ISSECTION(s)) - s->s_sect_len--; - } - - return (0); -} - -/* - * Check if an sbuf has an error. - */ -int -sbuf_error(const struct sbuf *s) -{ - - return (s->s_error); -} - -/* - * Finish off an sbuf. - */ -int -sbuf_finish(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - s->s_buf[s->s_len] = '\0'; - if (SBUF_NULINCLUDED(s)) - s->s_len++; - if (s->s_drain_func != NULL) { - while (s->s_len > 0 && s->s_error == 0) - s->s_error = sbuf_drain(s); - } - SBUF_SETFLAG(s, SBUF_FINISHED); -#ifdef _KERNEL - return (s->s_error); -#else - if (s->s_error != 0) { - errno = s->s_error; - return (-1); - } - return (0); -#endif -} - -/* - * Return a pointer to the sbuf data. - */ -char * -sbuf_data(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, SBUF_FINISHED); - KASSERT(s->s_drain_func == NULL, - ("%s makes no sense on sbuf %p with drain", __func__, s)); - - return (s->s_buf); -} - -/* - * Return the length of the sbuf data. - */ -ssize_t -sbuf_len(struct sbuf *s) -{ - - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - KASSERT(s->s_drain_func == NULL, - ("%s makes no sense on sbuf %p with drain", __func__, s)); - - if (s->s_error != 0) - return (-1); - - /* If finished, nulterm is already in len, else add one. */ - if (SBUF_NULINCLUDED(s) && !SBUF_ISFINISHED(s)) - return (s->s_len + 1); - return (s->s_len); -} - -/* - * Clear an sbuf, free its buffer if necessary. - */ -void -sbuf_delete(struct sbuf *s) -{ - int isdyn; - - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - - if (SBUF_ISDYNAMIC(s)) - SBFREE(s->s_buf); - isdyn = SBUF_ISDYNSTRUCT(s); - memset(s, 0, sizeof(*s)); - if (isdyn) - SBFREE(s); -} - -/* - * Check if an sbuf has been finished. - */ -int -sbuf_done(const struct sbuf *s) -{ - - return (SBUF_ISFINISHED(s)); -} - -/* - * Start a section. - */ -void -sbuf_start_section(struct sbuf *s, ssize_t *old_lenp) -{ - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (!SBUF_ISSECTION(s)) { - KASSERT(s->s_sect_len == 0, - ("s_sect_len != 0 when starting a section")); - if (old_lenp != NULL) - *old_lenp = -1; - s->s_rec_off = s->s_len; - SBUF_SETFLAG(s, SBUF_INSECTION); - } else { - KASSERT(old_lenp != NULL, - ("s_sect_len should be saved when starting a subsection")); - *old_lenp = s->s_sect_len; - s->s_sect_len = 0; - } -} - -/* - * End the section padding to the specified length with the specified - * character. - */ -ssize_t -sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c) -{ - ssize_t len; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - KASSERT(SBUF_ISSECTION(s), - ("attempt to end a section when not in a section")); - - if (pad > 1) { - len = roundup(s->s_sect_len, pad) - s->s_sect_len; - for (; s->s_error == 0 && len > 0; len--) - sbuf_put_byte(s, c); - } - len = s->s_sect_len; - if (old_len == -1) { - s->s_rec_off = s->s_sect_len = 0; - SBUF_CLEARFLAG(s, SBUF_INSECTION); - } else { - s->s_sect_len += old_len; - } - if (s->s_error != 0) - return (-1); - return (len); -} diff --git a/pw/sbuf/sys/sbuf.h b/pw/sbuf/sys/sbuf.h deleted file mode 100644 index f2cd679..0000000 --- a/pw/sbuf/sys/sbuf.h +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000-2008 Poul-Henning Kamp - * Copyright (c) 2000-2008 Dag-Erling Coïdan Smørgrav - * 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 - * in this position and unchanged. - * 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 _SYS_SBUF_H_ -#define _SYS_SBUF_H_ - -#include - -typedef __builtin_va_list __va_list; - -struct sbuf; -typedef int (sbuf_drain_func)(void *, const char *, int); - -/* - * Structure definition - */ -struct sbuf { - char *s_buf; /* storage buffer */ - sbuf_drain_func *s_drain_func; /* drain function */ - void *s_drain_arg; /* user-supplied drain argument */ - int s_error; /* current error code */ - ssize_t s_size; /* size of storage buffer */ - ssize_t s_len; /* current length of string */ -#define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */ -#define SBUF_AUTOEXTEND 0x00000001 /* automatically extend buffer */ -#define SBUF_INCLUDENUL 0x00000002 /* nulterm byte is counted in len */ -#define SBUF_DRAINTOEOR 0x00000004 /* use section 0 as drain EOR marker */ -#define SBUF_NOWAIT 0x00000008 /* Extend with non-blocking malloc */ -#define SBUF_USRFLAGMSK 0x0000ffff /* mask of flags the user may specify */ -#define SBUF_DYNAMIC 0x00010000 /* s_buf must be freed */ -#define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */ -#define SBUF_DYNSTRUCT 0x00080000 /* sbuf must be freed */ -#define SBUF_INSECTION 0x00100000 /* set by sbuf_start_section() */ -#define SBUF_DRAINATEOL 0x00200000 /* drained contents ended in \n */ - int s_flags; /* flags */ - ssize_t s_sect_len; /* current length of section */ - ssize_t s_rec_off; /* current record start offset */ -}; - -#ifndef HD_COLUMN_MASK -#define HD_COLUMN_MASK 0xff -#define HD_DELIM_MASK 0xff00 -#define HD_OMIT_COUNT (1 << 16) -#define HD_OMIT_HEX (1 << 17) -#define HD_OMIT_CHARS (1 << 18) -#endif /* HD_COLUMN_MASK */ - -__BEGIN_DECLS -/* - * API functions - */ -struct sbuf *sbuf_new(struct sbuf *, char *, int, int); -#define sbuf_new_auto() \ - sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND) -int sbuf_get_flags(struct sbuf *); -void sbuf_clear_flags(struct sbuf *, int); -void sbuf_set_flags(struct sbuf *, int); -void sbuf_clear(struct sbuf *); -int sbuf_setpos(struct sbuf *, ssize_t); -int sbuf_bcat(struct sbuf *, const void *, size_t); -int sbuf_bcpy(struct sbuf *, const void *, size_t); -int sbuf_cat(struct sbuf *, const char *); -int sbuf_cpy(struct sbuf *, const char *); -int sbuf_printf(struct sbuf *, const char *, ...) - __printflike(2, 3); -int sbuf_vprintf(struct sbuf *, const char *, __va_list) - __printflike(2, 0); -int sbuf_nl_terminate(struct sbuf *); -int sbuf_putc(struct sbuf *, int); -void sbuf_set_drain(struct sbuf *, sbuf_drain_func *, void *); -int sbuf_trim(struct sbuf *); -int sbuf_error(const struct sbuf *); -int sbuf_finish(struct sbuf *); -char *sbuf_data(struct sbuf *); -ssize_t sbuf_len(struct sbuf *); -int sbuf_done(const struct sbuf *); -void sbuf_delete(struct sbuf *); -void sbuf_start_section(struct sbuf *, ssize_t *); -ssize_t sbuf_end_section(struct sbuf *, ssize_t, size_t, int); -void sbuf_hexdump(struct sbuf *, const void *, int, const char *, - int); -int sbuf_count_drain(void *arg, const char *data, int len); -int sbuf_printf_drain(void *arg, const char *data, int len); -void sbuf_putbuf(struct sbuf *); - -#ifdef _KERNEL -struct uio; -struct sbuf *sbuf_uionew(struct sbuf *, struct uio *, int *); -int sbuf_bcopyin(struct sbuf *, const void *, size_t); -int sbuf_copyin(struct sbuf *, const void *, size_t); -#endif -__END_DECLS - -#endif -- cgit v1.2.3-56-ge451