xref: /csrg-svn/libexec/comsat/comsat.c (revision 1572)
1*1572Sbill static	char *sccsid = "@(#)comsat.c	4.2 (Berkeley) 10/20/80";
21513Sroot #include <stdio.h>
31513Sroot #include <sys/mx.h>
41513Sroot #include <sgtty.h>
51513Sroot #include <utmp.h>
61513Sroot #include <sys/types.h>
71513Sroot #include <stat.h>
81513Sroot #include <wait.h>
91513Sroot #include <signal.h>
101513Sroot 
111513Sroot /*
121513Sroot  * comsat
131513Sroot  */
141513Sroot #define	dprintf	if (0) printf
151513Sroot int	xd;
161513Sroot 
171513Sroot struct  ctp {
181513Sroot 	short   ctrl;
191513Sroot 	short   ctrlarg;
201513Sroot 	struct  sgttyb ctrlv;
211513Sroot } ctp;
221513Sroot 
231513Sroot #define MAXUTMP 100		/* down from init */
241513Sroot 
251513Sroot struct	utmp utmp[100];
261513Sroot int	nutmp;
271513Sroot int	uf;
281513Sroot unsigned utmpmtime;			/* last modification time for utmp */
291513Sroot int	onalrm();
301513Sroot 
311513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1)
321513Sroot 
331513Sroot main(argc, argv)
341513Sroot char **argv;
351513Sroot {
361513Sroot 	register cc;
371513Sroot 	char buf[BUFSIZ];
381513Sroot 
391513Sroot 	if (fork())
401513Sroot 		exit();
411513Sroot 	chdir("/usr/spool/mail");
421513Sroot 	if((uf = open("/etc/utmp",0)) < 0)
431513Sroot 		perror("/etc/utmp"), exit(1);
441513Sroot 	while (fork())
451513Sroot 		wait(0);
46*1572Sbill 	sleep(10);
471513Sroot 	onalrm();
481513Sroot 	sigset(SIGALRM, onalrm);
491513Sroot 	sigignore(SIGTTOU);
501513Sroot 	unlink("/dev/mail");
511513Sroot 	xd = mpx("/dev/mail", 0666);
521513Sroot 	if (xd < 0) {
531513Sroot 		close(2);
541513Sroot 		open("/dev/console", 1);
551513Sroot 		perror("/dev/mail");
561513Sroot 		exit(1);
571513Sroot 	}
581513Sroot 	while((cc=read(xd, buf, BUFSIZ)) >= 0) {
591513Sroot 		dprintf("0: got %d bytes\n", cc);
601513Sroot 		unpack(buf, cc);
611513Sroot 	}
62*1572Sbill 	_exit(1);
631513Sroot }
641513Sroot 
651513Sroot #define	skip(rp, c)	((struct rh *)(((char *)rp)+c))
661513Sroot 
671513Sroot unpack(rp, cc)
681513Sroot 	register struct rh *rp;
691513Sroot {
701513Sroot 	register struct rh *end;
711513Sroot 	int i;
721513Sroot 
731513Sroot 	i = 0;
741513Sroot 	end = skip(rp, cc);
751513Sroot 	while (rp < end) {
761513Sroot 		dprintf("%d: ", ++i);
771513Sroot 		if (rp->count==0) {
781513Sroot 			dprintf("%d byte control message\n", rp->ccount);
791513Sroot 			control(rp->index, rp+1, rp->ccount);
801513Sroot 		} else {
811513Sroot 			dprintf("%*.*s\n", rp->count, rp->count, rp+1);
821513Sroot 			sighold(SIGALRM);
831513Sroot 			mailfor(rp+1);
841513Sroot 			sigrelse(SIGALRM);
851513Sroot 		}
861513Sroot 		rp->count += rp->ccount;
871513Sroot 		if (rp->count & 1)
881513Sroot 			rp->count++;
891513Sroot 		rp = skip(rp, rp->count);
901513Sroot 		rp++;
911513Sroot 	}
921513Sroot }
931513Sroot 
941513Sroot control(x, cb, cc)
951513Sroot 	register char *cb;
961513Sroot {
971513Sroot 	register char *end;
981513Sroot 	int cmd;
991513Sroot 	short *sp;
1001513Sroot 	struct wh or;
1011513Sroot 
1021513Sroot 	end = cb + cc;
1031513Sroot 	cmd = *cb++;
1041513Sroot 	sp = (short *)cb+1;
1051513Sroot 	switch (cmd) {
1061513Sroot 
1071513Sroot 	case M_WATCH:
1081513Sroot 		dprintf("attach %x, uid %d\n", x, *sp);
1091513Sroot 		attach(x, xd);
1101513Sroot 		break;
1111513Sroot 
1121513Sroot 	case M_CLOSE:
1131513Sroot 		sp = (short *)cb;
1141513Sroot 		dprintf("detach %x, uid %d\n", x, *sp);
1151513Sroot 		detach(x, xd);
1161513Sroot 		break;
1171513Sroot 
1181513Sroot 	case M_IOCTL:
1191513Sroot 		dprintf("ioctl %x\n", x);
1201513Sroot 		or.index = x;
1211513Sroot 		or.count = 0;
1221513Sroot 		or.ccount = sizeof ctp;
1231513Sroot 		or.data = (char *) &ctp.ctrlarg;
1241513Sroot 		ctp.ctrlarg = M_IOANS;
1251513Sroot 		write(xd, &or, sizeof or);
1261513Sroot 		break;
1271513Sroot 
1281513Sroot 	default:
1291513Sroot 		dprintf("unknown command %d\n", cmd);
1301513Sroot 		return;
1311513Sroot 	}
1321513Sroot }
1331513Sroot 
1341513Sroot onalrm()
1351513Sroot {
1361513Sroot 	struct stat statbf;
1371513Sroot 	struct utmp *utp;
1381513Sroot 
1391513Sroot 	dprintf("alarm\n");
1401513Sroot 	alarm(15);
1411513Sroot 	fstat(uf,&statbf);
1421513Sroot 	if (statbf.st_mtime > utmpmtime) {
1431513Sroot 		dprintf(" changed\n");
1441513Sroot 		utmpmtime = statbf.st_mtime;
1451513Sroot 		lseek(uf, 0, 0);
1461513Sroot 		nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp);
1471513Sroot 	} else
1481513Sroot 		dprintf(" ok\n");
1491513Sroot }
1501513Sroot 
1511513Sroot mailfor(name)
1521513Sroot 	char *name;
1531513Sroot {
1541513Sroot 	register struct utmp *utp = &utmp[nutmp];
1551513Sroot 	register char *cp;
1561513Sroot 	char *rindex();
1571513Sroot 	int offset;
1581513Sroot 
1591513Sroot 	dprintf("mailfor %s\n", name);
1601513Sroot 	cp = name;
1611513Sroot 	while (*cp && *cp != '@')
1621513Sroot 		cp++;
1631513Sroot 	if (*cp == 0) {
1641513Sroot 		dprintf("bad format\n");
1651513Sroot 		return;
1661513Sroot 	}
1671513Sroot 	*cp = 0;
1681513Sroot 	offset = atoi(cp+1);
1691513Sroot 	while (--utp >= utmp)
1701513Sroot 		if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
1711513Sroot 			if (fork() == 0) {
1721513Sroot 				signal(SIGALRM, SIG_DFL);
1731513Sroot 				alarm(30);
1741513Sroot 				notify(utp, offset), exit(0);
1751513Sroot 			} else
1761513Sroot 				while (wait3(0, WNOHANG, 0) > 0)
1771513Sroot 					continue;
1781513Sroot }
1791513Sroot 
1801513Sroot char *cr;
1811513Sroot 
1821513Sroot notify(utp, offset)
1831513Sroot 	register struct utmp *utp;
1841513Sroot {
1851513Sroot 	FILE *tp;
1861513Sroot 	struct sgttyb gttybuf;
1871513Sroot 	char tty[20];
1881513Sroot 	char name[sizeof (utmp[0].ut_name) + 1];
1891513Sroot 	struct stat stb;
1901513Sroot 
1911513Sroot 	strcpy(tty, "/dev/");
1921513Sroot 	strncat(tty, utp->ut_line, sizeof(utp->ut_line));
1931513Sroot 	dprintf("notify %s on %s\n", utp->ut_name, tty);
1941513Sroot 	if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) {
1951513Sroot 		dprintf("wrong mode\n");
1961513Sroot 		return;
1971513Sroot 	}
1981513Sroot 	if ((tp = fopen(tty,"w")) == 0) {
1991513Sroot 		dprintf("fopen failed\n");
2001513Sroot 		return;
2011513Sroot 	}
2021513Sroot 	gtty(fileno(tp),&gttybuf);
2031513Sroot 	cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r";
2041513Sroot 	strncpy(name, utp->ut_name, sizeof (utp->ut_name));
2051513Sroot 	name[sizeof (name) - 1] = 0;
2061513Sroot 	fprintf(tp,"%s\n\007New mail for %s\007 has arrived:%s\n",
2071513Sroot 	    cr, name, cr);
2081513Sroot 	fprintf(tp,"----%s\n", cr);
2091513Sroot 	jkfprintf(tp, name, offset);
2101513Sroot 	 fclose(tp);
2111513Sroot }
2121513Sroot 
2131513Sroot jkfprintf(tp, name, offset)
2141513Sroot 	register FILE *tp;
2151513Sroot {
2161513Sroot 	register FILE *fi;
2171513Sroot 	register int linecnt, charcnt;
2181513Sroot 
2191513Sroot 	dprintf("HERE %s's mail starting at %d\n",
2201513Sroot 	    name, offset);
2211513Sroot 	if ((fi = fopen(name,"r")) == NULL) {
2221513Sroot 		dprintf("Cant read the mail\n");
2231513Sroot 		return;
2241513Sroot 	}
2251513Sroot 	fseek(fi, offset, 0);
2261513Sroot 	linecnt = 7;
2271513Sroot 	charcnt = 560;
2281513Sroot 	/*
2291513Sroot 	 * print the first 7 lines or 560 characters of the new mail
2301513Sroot 	 * (whichever comes first)
2311513Sroot 	 */
2321513Sroot 	for (;;) {
2331513Sroot 		register ch;
2341513Sroot 
2351513Sroot 	 	if ((ch = getc(fi)) == EOF) {
2361513Sroot 			fprintf(tp,"----%s\n", cr);
2371513Sroot 			break;
2381513Sroot 		}
2391513Sroot 		if (ch == '\n') {
2401513Sroot 			fprintf(tp,"%s\n", cr);
2411513Sroot 		 	if (linecnt-- < 0) {
2421513Sroot 				fprintf(tp,"...more...%s\n", cr);
2431513Sroot 				break;
2441513Sroot 			}
2451513Sroot 		} else if(linecnt <= 0) {
2461513Sroot 			fprintf(tp,"...more...%s\n", cr);
2471513Sroot 			break;
2481513Sroot 		} else
2491513Sroot 			putc(ch, tp);
2501513Sroot 		if (charcnt-- == 0) {
2511513Sroot 			fprintf(tp, "%s\n", cr);
2521513Sroot 			break;
2531513Sroot 		}
2541513Sroot 	}
2551513Sroot }
256