Index: sys/kern/kern_cons.c =================================================================== --- sys/kern/kern_cons.c +++ sys/kern/kern_cons.c @@ -522,9 +522,9 @@ } void -cnputs(char *p) +cnputsn(const char *p, size_t n) { - int c; + size_t i; int unlock_reqd = 0; if (use_cnputs_mtx) { @@ -539,13 +539,19 @@ unlock_reqd = 1; } - while ((c = *p++) != '\0') - cnputc(c); + for (i = 0; i < n; i++) + cnputc(p[i]); if (unlock_reqd) mtx_unlock_spin(&cnputs_mtx); } +void +cnputs(char *p) +{ + cnputsn(p, strlen(p)); +} + static int consmsgbuf_size = 8192; SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0, "Console tty buffer size"); Index: sys/kern/subr_prf.c =================================================================== --- sys/kern/subr_prf.c +++ sys/kern/subr_prf.c @@ -258,27 +258,6 @@ msgbuftrigger = 1; } -/* - * Ttyprintf displays a message on a tty; it should be used only by - * the tty driver, or anything that knows the underlying tty will not - * be revoke(2)'d away. Other callers should use tprintf. - */ -int -ttyprintf(struct tty *tp, const char *fmt, ...) -{ - va_list ap; - struct putchar_arg pca; - int retval; - - va_start(ap, fmt); - pca.tty = tp; - pca.flags = TOTTY; - pca.p_bufr = NULL; - retval = kvprintf(fmt, putchar, &pca, 10, ap); - va_end(ap); - return (retval); -} - static int _vprintf(int level, int flags, const char *fmt, va_list ap) { Index: sys/kern/tty_info.c =================================================================== --- sys/kern/tty_info.c +++ sys/kern/tty_info.c @@ -46,10 +46,13 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include #include #include +#include #include #include #include @@ -209,6 +212,27 @@ return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ } +static int +sbuf_tty_drain(void *a, const char *d, int len) +{ + struct tty *tp; + int rc; + + tp = a; + + if (kdb_active) { + cnputsn(d, len); + return (len); + } + if (tp != NULL && panicstr == NULL) { + rc = tty_putstrn(tp, d, len); + if (rc != 0) + return (-ENXIO); + return (len); + } + return (-ENXIO); +} + /* * Report on state of foreground process group. */ @@ -219,6 +243,7 @@ struct proc *p, *ppick; struct thread *td, *tdpick; const char *stateprefix, *state; + struct sbuf sb; long rss; int load, pctcpu; pid_t pid; @@ -230,24 +255,27 @@ if (tty_checkoutq(tp) == 0) return; + (void)sbuf_new(&sb, tp->t_prbuf, sizeof(tp->t_prbuf), SBUF_FIXEDLEN); + sbuf_set_drain(&sb, sbuf_tty_drain, tp); + /* Print load average. */ load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; - ttyprintf(tp, "%sload: %d.%02d ", tp->t_column == 0 ? "" : "\n", + sbuf_printf(&sb, "%sload: %d.%02d ", tp->t_column == 0 ? "" : "\n", load / 100, load % 100); if (tp->t_session == NULL) { - ttyprintf(tp, "not a controlling terminal\n"); - return; + sbuf_printf(&sb, "not a controlling terminal\n"); + goto out; } if (tp->t_pgrp == NULL) { - ttyprintf(tp, "no foreground process group\n"); - return; + sbuf_printf(&sb, "no foreground process group\n"); + goto out; } PGRP_LOCK(tp->t_pgrp); if (LIST_EMPTY(&tp->t_pgrp->pg_members)) { PGRP_UNLOCK(tp->t_pgrp); - ttyprintf(tp, "empty foreground process group\n"); - return; + sbuf_printf(&sb, "empty foreground process group\n"); + goto out; } /* @@ -305,11 +333,15 @@ PROC_UNLOCK(p); /* Print command, pid, state, rtime, utime, stime, %cpu, and rss. */ - ttyprintf(tp, + sbuf_printf(&sb, " cmd: %s %d [%s%s] %ld.%02ldr %ld.%02ldu %ld.%02lds %d%% %ldk\n", comm, pid, stateprefix, state, (long)rtime.tv_sec, rtime.tv_usec / 10000, (long)utime.tv_sec, utime.tv_usec / 10000, (long)stime.tv_sec, stime.tv_usec / 10000, pctcpu / 100, rss); + +out: + sbuf_finish(&sb); + sbuf_delete(&sb); } Index: sys/kern/tty_ttydisc.c =================================================================== --- sys/kern/tty_ttydisc.c +++ sys/kern/tty_ttydisc.c @@ -1251,17 +1251,27 @@ */ int -tty_putchar(struct tty *tp, char c) +tty_putstrn(struct tty *tp, const char *p, size_t n) { + size_t i; + tty_lock_assert(tp, MA_OWNED); if (tty_gone(tp)) return (-1); - ttydisc_echo_force(tp, c, 0); + for (i = 0; i < n; i++) + ttydisc_echo_force(tp, p[i], 0); + tp->t_writepos = tp->t_column; ttyinq_reprintpos_set(&tp->t_inq); ttydevsw_outwakeup(tp); return (0); } + +int +tty_putchar(struct tty *tp, char c) +{ + return (tty_putstrn(tp, &c, 1)); +} Index: sys/sys/cons.h =================================================================== --- sys/sys/cons.h +++ sys/sys/cons.h @@ -137,6 +137,7 @@ void cngets(char *, size_t, int); void cnputc(int); void cnputs(char *); +void cnputsn(const char *, size_t); int cnunavailable(void); void constty_set(struct tty *tp); void constty_clear(void); Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h +++ sys/sys/systm.h @@ -290,7 +290,6 @@ int vsnprintf(char *, size_t, const char *, __va_list) __printflike(3, 0); int vsnrprintf(char *, size_t, int, const char *, __va_list) __printflike(4, 0); int vsprintf(char *buf, const char *, __va_list) __printflike(2, 0); -int ttyprintf(struct tty *, const char *, ...) __printflike(2, 3); int sscanf(const char *, char const * _Nonnull, ...) __scanflike(2, 3); int vsscanf(const char * _Nonnull, char const * _Nonnull, __va_list) __scanflike(2, 0); long strtol(const char *, char **, int); Index: sys/sys/tty.h =================================================================== --- sys/sys/tty.h +++ sys/sys/tty.h @@ -132,6 +132,13 @@ void *t_devswsoftc; /* (c) Soft config, for drivers. */ void *t_hooksoftc; /* (t) Soft config, for hooks. */ struct cdev *t_dev; /* (c) Primary character device. */ + +#ifndef PRINTF_BUFR_SIZE +#define TTY_PRINTF_SIZE 256 +#else +#define TTY_PRINTF_SIZE PRINTF_BUFR_SIZE +#endif + char t_prbuf[TTY_PRINTF_SIZE]; /* (t) */ }; /* @@ -194,6 +201,7 @@ /* System messages. */ int tty_checkoutq(struct tty *tp); int tty_putchar(struct tty *tp, char c); +int tty_putstrn(struct tty *tp, const char *p, size_t n); int tty_ioctl(struct tty *tp, u_long cmd, void *data, int fflag, struct thread *td);