Deleted Added
full compact
subr_prf.c (209949) subr_prf.c (222537)
1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 21 unchanged lines hidden (view full) ---

30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
35 */
36
37#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 21 unchanged lines hidden (view full) ---

30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 209949 2010-07-12 15:32:45Z jkim $");
38__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 222537 2011-05-31 17:29:58Z ken $");
39
40#include "opt_ddb.h"
41#include "opt_printf.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/lock.h>
46#include <sys/kdb.h>

--- 42 unchanged lines hidden (view full) ---

89struct snprintf_arg {
90 char *str;
91 size_t remain;
92};
93
94extern int log_open;
95
96static void msglogchar(int c, int pri);
39
40#include "opt_ddb.h"
41#include "opt_printf.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/lock.h>
46#include <sys/kdb.h>

--- 42 unchanged lines hidden (view full) ---

89struct snprintf_arg {
90 char *str;
91 size_t remain;
92};
93
94extern int log_open;
95
96static void msglogchar(int c, int pri);
97static void msglogstr(char *str, int pri, int filter_cr);
97static void putchar(int ch, void *arg);
98static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
99static void snprintf_func(int ch, void *arg);
100
101static int msgbufmapped; /* Set when safe to use msgbuf */
102int msgbuftrigger;
103
104static int log_console_output = 1;
105TUNABLE_INT("kern.log_console_output", &log_console_output);
106SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
107 &log_console_output, 0, "Duplicate console output to the syslog.");
108
98static void putchar(int ch, void *arg);
99static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
100static void snprintf_func(int ch, void *arg);
101
102static int msgbufmapped; /* Set when safe to use msgbuf */
103int msgbuftrigger;
104
105static int log_console_output = 1;
106TUNABLE_INT("kern.log_console_output", &log_console_output);
107SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
108 &log_console_output, 0, "Duplicate console output to the syslog.");
109
110/*
111 * See the comment in log_console() below for more explanation of this.
112 */
113static int log_console_add_linefeed = 0;
114TUNABLE_INT("kern.log_console_add_linefeed", &log_console_add_linefeed);
115SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RW,
116 &log_console_add_linefeed, 0, "log_console() adds extra newlines.");
117
109static int always_console_output = 0;
110TUNABLE_INT("kern.always_console_output", &always_console_output);
111SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
112 &always_console_output, 0, "Always output to console despite TIOCCONS.");
113
114/*
115 * Warn that a system table is full.
116 */

--- 118 unchanged lines hidden (view full) ---

235 * called by interrupt routines). If there is no process reading the
236 * log yet, it writes to the console also.
237 */
238void
239log(int level, const char *fmt, ...)
240{
241 va_list ap;
242 struct putchar_arg pca;
118static int always_console_output = 0;
119TUNABLE_INT("kern.always_console_output", &always_console_output);
120SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
121 &always_console_output, 0, "Always output to console despite TIOCCONS.");
122
123/*
124 * Warn that a system table is full.
125 */

--- 118 unchanged lines hidden (view full) ---

244 * called by interrupt routines). If there is no process reading the
245 * log yet, it writes to the console also.
246 */
247void
248log(int level, const char *fmt, ...)
249{
250 va_list ap;
251 struct putchar_arg pca;
252#ifdef PRINTF_BUFR_SIZE
253 char bufr[PRINTF_BUFR_SIZE];
254#endif
243
244 pca.tty = NULL;
245 pca.pri = level;
246 pca.flags = log_open ? TOLOG : TOCONS;
255
256 pca.tty = NULL;
257 pca.pri = level;
258 pca.flags = log_open ? TOLOG : TOCONS;
259#ifdef PRINTF_BUFR_SIZE
260 pca.p_bufr = bufr;
261 pca.p_next = pca.p_bufr;
262 pca.n_bufr = sizeof(bufr);
263 pca.remain = sizeof(bufr);
264 *pca.p_next = '\0';
265#else
247 pca.p_bufr = NULL;
266 pca.p_bufr = NULL;
267#endif
248
249 va_start(ap, fmt);
250 kvprintf(fmt, putchar, &pca, 10, ap);
251 va_end(ap);
252
268
269 va_start(ap, fmt);
270 kvprintf(fmt, putchar, &pca, 10, ap);
271 va_end(ap);
272
273#ifdef PRINTF_BUFR_SIZE
274 /* Write any buffered console/log output: */
275 if (*pca.p_bufr != '\0') {
276 if (pca.flags & TOLOG)
277 msglogstr(pca.p_bufr, level, /*filter_cr*/1);
278
279 if (pca.flags & TOCONS)
280 cnputs(pca.p_bufr);
281 }
282#endif
253 msgbuftrigger = 1;
254}
255
256#define CONSCHUNK 128
257
258void
259log_console(struct uio *uio)
260{
283 msgbuftrigger = 1;
284}
285
286#define CONSCHUNK 128
287
288void
289log_console(struct uio *uio)
290{
261 int c, i, error, nl;
291 int c, error, nl;
262 char *consbuffer;
263 int pri;
264
265 if (!log_console_output)
266 return;
267
268 pri = LOG_INFO | LOG_CONSOLE;
269 uio = cloneuio(uio);
270 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
271
272 nl = 0;
273 while (uio->uio_resid > 0) {
292 char *consbuffer;
293 int pri;
294
295 if (!log_console_output)
296 return;
297
298 pri = LOG_INFO | LOG_CONSOLE;
299 uio = cloneuio(uio);
300 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
301
302 nl = 0;
303 while (uio->uio_resid > 0) {
274 c = imin(uio->uio_resid, CONSCHUNK);
304 c = imin(uio->uio_resid, CONSCHUNK - 1);
275 error = uiomove(consbuffer, c, uio);
276 if (error != 0)
277 break;
305 error = uiomove(consbuffer, c, uio);
306 if (error != 0)
307 break;
278 for (i = 0; i < c; i++) {
279 msglogchar(consbuffer[i], pri);
280 if (consbuffer[i] == '\n')
281 nl = 1;
282 else
283 nl = 0;
284 }
308 /* Make sure we're NUL-terminated */
309 consbuffer[c] = '\0';
310 if (consbuffer[c - 1] == '\n')
311 nl = 1;
312 else
313 nl = 0;
314 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
285 }
315 }
286 if (!nl)
287 msglogchar('\n', pri);
316 /*
317 * The previous behavior in log_console() is preserved when
318 * log_console_add_linefeed is non-zero. For that behavior, if an
319 * individual console write came in that was not terminated with a
320 * line feed, it would add a line feed.
321 *
322 * This results in different data in the message buffer than
323 * appears on the system console (which doesn't add extra line feed
324 * characters).
325 *
326 * A number of programs and rc scripts write a line feed, or a period
327 * and a line feed when they have completed their operation. On
328 * the console, this looks seamless, but when displayed with
329 * 'dmesg -a', you wind up with output that looks like this:
330 *
331 * Updating motd:
332 * .
333 *
334 * On the console, it looks like this:
335 * Updating motd:.
336 *
337 * We could add logic to detect that situation, or just not insert
338 * the extra newlines. Set the kern.log_console_add_linefeed
339 * sysctl/tunable variable to get the old behavior.
340 */
341 if (!nl && log_console_add_linefeed) {
342 consbuffer[0] = '\n';
343 consbuffer[1] = '\0';
344 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
345 }
288 msgbuftrigger = 1;
289 free(uio, M_IOV);
290 free(consbuffer, M_TEMP);
291 return;
292}
293
294int
295printf(const char *fmt, ...)

--- 29 unchanged lines hidden (view full) ---

325#else
326 /* Don't buffer console output. */
327 pca.p_bufr = NULL;
328#endif
329
330 retval = kvprintf(fmt, putchar, &pca, 10, ap);
331
332#ifdef PRINTF_BUFR_SIZE
346 msgbuftrigger = 1;
347 free(uio, M_IOV);
348 free(consbuffer, M_TEMP);
349 return;
350}
351
352int
353printf(const char *fmt, ...)

--- 29 unchanged lines hidden (view full) ---

383#else
384 /* Don't buffer console output. */
385 pca.p_bufr = NULL;
386#endif
387
388 retval = kvprintf(fmt, putchar, &pca, 10, ap);
389
390#ifdef PRINTF_BUFR_SIZE
333 /* Write any buffered console output: */
334 if (*pca.p_bufr != '\0')
391 /* Write any buffered console/log output: */
392 if (*pca.p_bufr != '\0') {
335 cnputs(pca.p_bufr);
393 cnputs(pca.p_bufr);
394 msglogstr(pca.p_bufr, pca.pri, /*filter_cr*/ 1);
395 }
336#endif
337
338 if (!panicstr)
339 msgbuftrigger = 1;
340
341 return (retval);
342}
343
344static void
396#endif
397
398 if (!panicstr)
399 msgbuftrigger = 1;
400
401 return (retval);
402}
403
404static void
345putcons(int c, struct putchar_arg *ap)
405putbuf(int c, struct putchar_arg *ap)
346{
347 /* Check if no console output buffer was provided. */
406{
407 /* Check if no console output buffer was provided. */
348 if (ap->p_bufr == NULL)
408 if (ap->p_bufr == NULL) {
349 /* Output direct to the console. */
409 /* Output direct to the console. */
350 cnputc(c);
351 else {
410 if (ap->flags & TOCONS)
411 cnputc(c);
412
413 if (ap->flags & TOLOG)
414 msglogchar(c, ap->pri);
415 } else {
352 /* Buffer the character: */
416 /* Buffer the character: */
353 if (c == '\n') {
354 *ap->p_next++ = '\r';
355 ap->remain--;
356 }
357 *ap->p_next++ = c;
358 ap->remain--;
359
360 /* Always leave the buffer zero terminated. */
361 *ap->p_next = '\0';
362
363 /* Check if the buffer needs to be flushed. */
417 *ap->p_next++ = c;
418 ap->remain--;
419
420 /* Always leave the buffer zero terminated. */
421 *ap->p_next = '\0';
422
423 /* Check if the buffer needs to be flushed. */
364 if (ap->remain < 3 || c == '\n') {
365 cnputs(ap->p_bufr);
424 if (ap->remain == 2 || c == '\n') {
425
426 if (ap->flags & TOLOG)
427 msglogstr(ap->p_bufr, ap->pri, /*filter_cr*/1);
428
429 if (ap->flags & TOCONS) {
430 if ((panicstr == NULL) && (constty != NULL))
431 msgbuf_addstr(&consmsgbuf, -1,
432 ap->p_bufr, /*filter_cr*/ 0);
433
434 if ((constty == NULL) ||(always_console_output))
435 cnputs(ap->p_bufr);
436 }
437
366 ap->p_next = ap->p_bufr;
367 ap->remain = ap->n_bufr;
368 *ap->p_next = '\0';
369 }
438 ap->p_next = ap->p_bufr;
439 ap->remain = ap->n_bufr;
440 *ap->p_next = '\0';
441 }
442
443 /*
444 * Since we fill the buffer up one character at a time,
445 * this should not happen. We should always catch it when
446 * ap->remain == 2 (if not sooner due to a newline), flush
447 * the buffer and move on. One way this could happen is
448 * if someone sets PRINTF_BUFR_SIZE to 1 or something
449 * similarly silly.
450 */
451 KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
452 ap->remain));
370 }
371}
372
373/*
374 * Print a character on console or users terminal. If destination is
375 * the console then the last bunch of characters are saved in msgbuf for
376 * inspection later.
377 */
378static void
379putchar(int c, void *arg)
380{
381 struct putchar_arg *ap = (struct putchar_arg*) arg;
382 struct tty *tp = ap->tty;
383 int flags = ap->flags;
453 }
454}
455
456/*
457 * Print a character on console or users terminal. If destination is
458 * the console then the last bunch of characters are saved in msgbuf for
459 * inspection later.
460 */
461static void
462putchar(int c, void *arg)
463{
464 struct putchar_arg *ap = (struct putchar_arg*) arg;
465 struct tty *tp = ap->tty;
466 int flags = ap->flags;
467 int putbuf_done = 0;
384
385 /* Don't use the tty code after a panic or while in ddb. */
386 if (kdb_active) {
387 if (c != '\0')
388 cnputc(c);
468
469 /* Don't use the tty code after a panic or while in ddb. */
470 if (kdb_active) {
471 if (c != '\0')
472 cnputc(c);
389 } else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
390 if (c != '\0')
391 putcons(c, ap);
392 } else {
473 } else {
393 if ((flags & TOTTY) && tp != NULL)
474 if ((panicstr == NULL) && (flags & TOTTY) && (tp != NULL))
394 tty_putchar(tp, c);
475 tty_putchar(tp, c);
476
395 if (flags & TOCONS) {
477 if (flags & TOCONS) {
396 if (constty != NULL)
397 msgbuf_addchar(&consmsgbuf, c);
398 if (always_console_output && c != '\0')
399 putcons(c, ap);
478 putbuf(c, ap);
479 putbuf_done = 1;
400 }
401 }
480 }
481 }
402 if ((flags & TOLOG))
403 msglogchar(c, ap->pri);
482 if ((flags & TOLOG) && (putbuf_done == 0)) {
483 if (c != '\0')
484 putbuf(c, ap);
485 }
404}
405
406/*
407 * Scaled down version of sprintf(3).
408 */
409int
410sprintf(char *buf, const char *cfmt, ...)
411{

--- 473 unchanged lines hidden (view full) ---

885 if (c == '\n') {
886 dangling = 0;
887 lastpri = -1;
888 } else {
889 dangling = 1;
890 }
891}
892
486}
487
488/*
489 * Scaled down version of sprintf(3).
490 */
491int
492sprintf(char *buf, const char *cfmt, ...)
493{

--- 473 unchanged lines hidden (view full) ---

967 if (c == '\n') {
968 dangling = 0;
969 lastpri = -1;
970 } else {
971 dangling = 1;
972 }
973}
974
975static void
976msglogstr(char *str, int pri, int filter_cr)
977{
978 if (!msgbufmapped)
979 return;
980
981 msgbuf_addstr(msgbufp, pri, str, filter_cr);
982}
983
893void
894msgbufinit(void *ptr, int size)
895{
896 char *cp;
897 static struct msgbuf *oldp = NULL;
898
899 size -= sizeof(*msgbufp);
900 cp = (char *)ptr;

--- 145 unchanged lines hidden ---
984void
985msgbufinit(void *ptr, int size)
986{
987 char *cp;
988 static struct msgbuf *oldp = NULL;
989
990 size -= sizeof(*msgbufp);
991 cp = (char *)ptr;

--- 145 unchanged lines hidden ---