Hi, something that has often bothered me, is that once you hook up a console to a headless server, you've missed all the output. This makes it harder to diagnose bugs in rc(8) startup skripts from remote. Another thing i've missed is that fsck(8) output will just scroll by and is usually lost.
Why not dump the initial output from /dev/console into a share of the system message buffer and make it readable via dmesg -c? Things like the fixed 16k size and bumping the message buffer on various platforms need still to be discussed, but how's the idea in general? Index: sbin/dmesg/dmesg.8 =================================================================== RCS file: /cvs/src/sbin/dmesg/dmesg.8,v retrieving revision 1.14 diff -u -p -p -u -r1.14 dmesg.8 --- sbin/dmesg/dmesg.8 14 Aug 2013 06:32:35 -0000 1.14 +++ sbin/dmesg/dmesg.8 7 Dec 2014 12:47:40 -0000 @@ -38,6 +38,7 @@ .Nd display the system message buffer .Sh SYNOPSIS .Nm dmesg +.Op Fl c .Op Fl M Ar core .Op Fl N Ar system .Sh DESCRIPTION @@ -57,6 +58,11 @@ Extract the name list from the specified .Ar system instead of the default .Pa /bsd . +.It Fl c +Display the contents of the console message buffer instead. +This can be used to review +.Xr rc 8 +system startup messages. .El .Sh FILES .Bl -tag -width /var/run/dmesg.boot -compact Index: sbin/dmesg/dmesg.c =================================================================== RCS file: /cvs/src/sbin/dmesg/dmesg.c,v retrieving revision 1.23 diff -u -p -p -u -r1.23 dmesg.c --- sbin/dmesg/dmesg.c 22 Apr 2014 20:43:12 -0000 1.23 +++ sbin/dmesg/dmesg.c 7 Dec 2014 12:47:40 -0000 @@ -66,11 +66,15 @@ main(int argc, char *argv[]) char *p; struct msgbuf cur; char *memf, *nlistf, *bufdata = NULL; + int readconsolemsgs = 0; char buf[5]; memf = nlistf = NULL; - while ((ch = getopt(argc, argv, "M:N:")) != -1) + while ((ch = getopt(argc, argv, "cM:N:")) != -1) switch(ch) { + case 'c': + readconsolemsgs = 1; + break; case 'M': memf = optarg; break; @@ -89,7 +93,7 @@ main(int argc, char *argv[]) size_t len; mib[0] = CTL_KERN; - mib[1] = KERN_MSGBUFSIZE; + mib[1] = readconsolemsgs ? KERN_CMSGBUFSIZE : KERN_MSGBUFSIZE; len = sizeof(msgbufsize); if (sysctl(mib, 2, &msgbufsize, &len, NULL, 0)) err(1, "sysctl: KERN_MSGBUFSIZE"); @@ -99,7 +103,7 @@ main(int argc, char *argv[]) if (bufdata == NULL) errx(1, "couldn't allocate space for buffer data"); - mib[1] = KERN_MSGBUF; + mib[1] = readconsolemsgs ? KERN_CMSGBUF : KERN_MSGBUF; len = msgbufsize; if (sysctl(mib, 2, bufdata, &len, NULL, 0)) err(1, "sysctl: KERN_MSGBUF"); @@ -179,6 +183,6 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-M core] [-N system]\n", __progname); + fprintf(stderr, "usage: %s [-c] [-M core] [-N system]\n", __progname); exit(1); } Index: sys/kern/kern_sysctl.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sysctl.c,v retrieving revision 1.274 diff -u -p -p -u -r1.274 kern_sysctl.c --- sys/kern/kern_sysctl.c 5 Dec 2014 04:35:08 -0000 1.274 +++ sys/kern/kern_sysctl.c 7 Dec 2014 12:47:40 -0000 @@ -444,19 +444,27 @@ kern_sysctl(int *name, u_int namelen, vo return (sysctl_rdint(oldp, oldlenp, newp, 0)); #endif case KERN_MSGBUFSIZE: + case KERN_CMSGBUFSIZE: { + struct msgbuf *mp; + mp = (name[0] == KERN_MSGBUFSIZE) ? msgbufp : cmsgbufp; /* * deal with cases where the message buffer has * become corrupted. */ - if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) + if (!mp || mp->msg_magic != MSG_MAGIC) return (ENXIO); - return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); + return (sysctl_rdint(oldp, oldlenp, newp, mp->msg_bufs)); + } case KERN_MSGBUF: + case KERN_CMSGBUF: { + struct msgbuf *mp; + mp = (name[0] == KERN_MSGBUF) ? msgbufp : cmsgbufp; /* see note above */ - if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) + if (!mp || mp->msg_magic != MSG_MAGIC) return (ENXIO); - return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp, - msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); + return (sysctl_rdstruct(oldp, oldlenp, newp, mp, + mp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); + } case KERN_MALLOCSTATS: return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p)); Index: sys/kern/subr_log.c =================================================================== RCS file: /cvs/src/sys/kern/subr_log.c,v retrieving revision 1.23 diff -u -p -p -u -r1.23 subr_log.c --- sys/kern/subr_log.c 3 Nov 2014 03:08:00 -0000 1.23 +++ sys/kern/subr_log.c 7 Dec 2014 12:47:40 -0000 @@ -74,8 +74,9 @@ struct logsoftc { int log_open; /* also used in log() */ int msgbufmapped; /* is the message buffer mapped */ -int msgbufenabled; /* is logging to the buffer enabled */ +int cmsgbufenabled; /* console buffer logging enabled */ struct msgbuf *msgbufp; /* the mapped buffer, itself. */ +struct msgbuf *cmsgbufp; /* console messages buffer. */ struct file *syslogf; void filt_logrdetach(struct knote *kn); @@ -88,7 +89,7 @@ void initmsgbuf(caddr_t buf, size_t bufsize) { struct msgbuf *mbp; - long new_bufs; + long new_bufs, new_cbufs = 0; /* Sanity-check the given size. */ if (bufsize < sizeof(struct msgbuf)) @@ -96,7 +97,14 @@ initmsgbuf(caddr_t buf, size_t bufsize) mbp = msgbufp = (struct msgbuf *)buf; - new_bufs = bufsize - offsetof(struct msgbuf, msg_bufc); + /* + * Init console message buffer logging, + * if it does not consume more than a quarter of the msgbuf space. + */ + if (bufsize / 4 >= CMSGBUFSIZE) { + new_cbufs = CMSGBUFSIZE; + } + new_bufs = bufsize - offsetof(struct msgbuf, msg_bufc) - new_cbufs; if ((mbp->msg_magic != MSG_MAGIC) || (mbp->msg_bufs != new_bufs) || (mbp->msg_bufr < 0) || (mbp->msg_bufr >= mbp->msg_bufs) || (mbp->msg_bufx < 0) || (mbp->msg_bufx >= mbp->msg_bufs)) { @@ -113,17 +121,23 @@ initmsgbuf(caddr_t buf, size_t bufsize) /* Always start new buffer data on a new line. */ if (mbp->msg_bufx > 0 && mbp->msg_bufc[mbp->msg_bufx - 1] != '\n') - msgbuf_putchar('\n'); + msgbuf_putchar(msgbufp, '\n'); + if (new_cbufs) { + mbp = cmsgbufp = (struct msgbuf *)(buf + CMSGBUFSIZE); + new_bufs = CMSGBUFSIZE - offsetof(struct msgbuf, msg_bufc); + memset(mbp, 0, CMSGBUFSIZE); + mbp->msg_magic = MSG_MAGIC; + mbp->msg_bufs = new_bufs; + cmsgbufenabled = 1; + } /* mark it as ready for use. */ - msgbufmapped = msgbufenabled = 1; + msgbufmapped = 1; } void -msgbuf_putchar(const char c) +msgbuf_putchar(struct msgbuf *mbp, const char c) { - struct msgbuf *mbp = msgbufp; - if (mbp->msg_magic != MSG_MAGIC) /* Nothing we can do */ return; Index: sys/kern/subr_prf.c =================================================================== RCS file: /cvs/src/sys/kern/subr_prf.c,v retrieving revision 1.83 diff -u -p -p -u -r1.83 subr_prf.c --- sys/kern/subr_prf.c 13 Jul 2014 23:49:40 -0000 1.83 +++ sys/kern/subr_prf.c 7 Dec 2014 12:47:40 -0000 @@ -349,7 +349,7 @@ kputchar(int c, int flags, struct tty *t constty = NULL; if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && msgbufmapped) - msgbuf_putchar(c); + msgbuf_putchar(msgbufp, c); if ((flags & TOCONS) && (constty == NULL || ddb_active) && c != '\0') (*v_putc)(c); #ifdef DDB Index: sys/kern/tty.c =================================================================== RCS file: /cvs/src/sys/kern/tty.c,v retrieving revision 1.116 diff -u -p -p -u -r1.116 tty.c --- sys/kern/tty.c 1 Dec 2014 07:51:47 -0000 1.116 +++ sys/kern/tty.c 7 Dec 2014 12:47:40 -0000 @@ -51,6 +51,7 @@ #include <sys/vnode.h> #include <sys/syslog.h> #include <sys/malloc.h> +#include <sys/msgbuf.h> #include <sys/signalvar.h> #include <sys/resourcevar.h> #include <sys/sysctl.h> @@ -60,6 +61,7 @@ #include <sys/namei.h> +#include <dev/cons.h> #include <dev/rndvar.h> #include "pty.h" @@ -1783,6 +1785,17 @@ loop: } if (cc > obufcc) obufcc = cc; + + /* duplicate /dev/console output into message buffer */ + if (cmsgbufenabled && cn_tab && + cn_tab->cn_dev == tp->t_dev && tp->t_gen == 0) { + int i; + for (i = 0; i < cc; i++) { + char c = cp[i]; + if (c != '\0' && c != '\r' && c != 0177) + msgbuf_putchar(cmsgbufp, c); + } + } } /* * If nothing fancy need be done, grab those characters we Index: sys/sys/msgbuf.h =================================================================== RCS file: /cvs/src/sys/sys/msgbuf.h,v retrieving revision 1.8 diff -u -p -p -u -r1.8 msgbuf.h --- sys/sys/msgbuf.h 14 Apr 2005 21:58:50 -0000 1.8 +++ sys/sys/msgbuf.h 7 Dec 2014 12:47:40 -0000 @@ -42,8 +42,11 @@ struct msgbuf { char msg_bufc[1]; /* buffer */ }; #ifdef _KERNEL +#define CMSGBUFSIZE (4 * 4 * 1024) /* console message buffer size */ extern struct msgbuf *msgbufp; +extern struct msgbuf *cmsgbufp; +extern int cmsgbufenabled; void initmsgbuf(caddr_t buf, size_t bufsize); -void msgbuf_putchar(const char c); +void msgbuf_putchar(struct msgbuf *, const char c); #endif Index: sys/sys/sysctl.h =================================================================== RCS file: /cvs/src/sys/sys/sysctl.h,v retrieving revision 1.152 diff -u -p -p -u -r1.152 sysctl.h --- sys/sys/sysctl.h 5 Dec 2014 04:12:48 -0000 1.152 +++ sys/sys/sysctl.h 7 Dec 2014 12:47:40 -0000 @@ -181,7 +181,9 @@ struct ctlname { #define KERN_PROC_CWD 78 /* node: proc cwd */ #define KERN_PROC_NOBROADCASTKILL 79 /* node: proc no broadcast kill */ #define KERN_PROC_VMMAP 80 /* node: proc vmmap */ -#define KERN_MAXID 81 /* number of valid kern ids */ +#define KERN_CMSGBUFSIZE 81 /* int: console message buffer size */ +#define KERN_CMSGBUF 82 /* console message buffer */ +#define KERN_MAXID 83 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \