/*
 *	Suck up system messages
 */

#include <stdio.h>
#include <sys/local.h>
#include <sys/param.h>
#include <a.out.h>

char    *msgbuf;        /* will be alloced to be msgbuf[msgbufs] */
char    *msgbufp;       /* current msgbuf pointer in kernel */
int     msgbufs;        /* size of msgbuf in kernel */
int	sflg;
int	of	= -1;

struct omesg {
	char	*omsgflg;
	int	omindex;
	char    omsgbuf[1];     /* actually alloced to be [msgbufs] */
};
struct omesg *omesg;
#define OMESG_SIZE (sizeof *omesg - 1)

struct nlist nl[] = {
#ifdef DEC
	{"_msgbuf"},
#define X_BUF           0
	{"_msgbufp"}
#define X_BUFP          1
#else
	{"msgbuf"},             /* char * */
#define X_BUF           0
	{"msgbufp"},            /* char * */
#define X_BUFP          1
	{"msgbufs"},            /* int */
#define X_BUFS          2
#endif
	""
};

main(argc, argv)
char **argv;
{
	int mem;
	register char *mp, *omp, *mstart;
	int samef;

	if (argc>1 && argv[1][0] == '-') {
		sflg = 1;
		argc--;
		argv++;
	}

	nlist(argc>2? argv[2]:"/unix", nl);
	if (nl[X_BUF].n_type==0)
		done("No namelist\n");
	if ((mem = open((argc>1? argv[1]: "/dev/mem"), 0)) < 0)
		done("No mem\n");

	lseek(mem, (long)nl[X_BUFS].n_value, 0);
	read(mem, (char *)&msgbufs, sizeof(msgbufs));
	msgbuf = calloc (msgbufs, 1);
	omesg = (struct omesg *) calloc (OMESG_SIZE + msgbufs, 1);

	lseek(mem, (long)nl[X_BUF].n_value, 0);
	read(mem, (char *)&nl[X_BUF].n_value, sizeof msgbuf);
	lseek(mem, (long)nl[X_BUF].n_value, 0);
	read(mem, msgbuf, msgbufs);

	lseek(mem, (long)nl[X_BUFP].n_value, 0);
	read(mem, (char *)&msgbufp, sizeof(msgbufp));

	if (sflg) {
		of = open("/usr/adm/msgbuf", 2);
		read(of, (char *)omesg, OMESG_SIZE + msgbufs);
		lseek(of, 0L, 0);
		sflg = 0;
	}

	if (   msgbufp <  (char *)nl[X_BUF].n_value
	    || msgbufp >= (char *)nl[X_BUF].n_value + msgbufs
	   )
		done("Namelist mismatch\n");
	/* translate msgbufp to point to our copy of msgbuf */
	msgbufp += msgbuf - (char *)nl[X_BUF].n_value;
	mstart = &msgbuf[omesg->omindex];
	omp = &omesg->omsgbuf[msgbufp-msgbuf];
	mp = msgbufp;
	samef = 1;
	do {
		if (*mp++ != *omp++) {
			mstart = msgbufp;
			samef = 0;
			pdate();
			printf("...\n");
			break;
		}
		if (mp == &msgbuf[msgbufs])
			mp = msgbuf;
		if (omp == &omesg->omsgbuf[msgbufs])
			omp = omesg->omsgbuf;
	} while (mp != mstart);
	if (samef && mstart == msgbufp)
		exit(0);
	mp = mstart;
	do {
		pdate();
		if (*mp)
			putchar(*mp);
		mp++;
		if (mp == &msgbuf[msgbufs])
			mp = msgbuf;
	} while (mp != msgbufp);
	done((char *)NULL);
}

done(s)
char *s;
{
	register char *p, *q;

	if (s && s!=omesg->omsgflg && sflg==0) {
		pdate();
		printf(s);
	}
	omesg->omsgflg = s;
	q = omesg->omsgbuf;
	for (p = msgbuf; p < &msgbuf[msgbufs]; )
		*q++ = *p++;
	omesg->omindex = msgbufp - msgbuf;
	write(of, (char *)omesg, OMESG_SIZE + msgbufs);
	exit(s!=NULL);
}

pdate()
{
	extern char *ctime();
	static firstime;
	time_t tbuf;

	if (firstime==0) {
		firstime++;
		time(&tbuf);
		printf("\n%.12s\n", ctime(&tbuf)+4);
	}
}
