xref: /csrg-svn/libexec/comsat/comsat.c (revision 13783)
19289Ssam #ifndef lint
2*13783Ssam static	char *sccsid = "@(#)comsat.c	4.9 83/07/04";
39289Ssam #endif
46394Sroot 
59289Ssam #include <sys/types.h>
69289Ssam #include <sys/socket.h>
713549Ssam #include <sys/stat.h>
813549Ssam #include <sys/wait.h>
99289Ssam 
109289Ssam #include <netinet/in.h>
119289Ssam 
121513Sroot #include <stdio.h>
131513Sroot #include <sgtty.h>
141513Sroot #include <utmp.h>
151513Sroot #include <signal.h>
166394Sroot #include <errno.h>
179289Ssam #include <netdb.h>
181513Sroot 
191513Sroot /*
201513Sroot  * comsat
211513Sroot  */
2212746Ssam int	debug = 0;
2312746Ssam #define	dprintf	if (debug) printf
241513Sroot 
251513Sroot #define MAXUTMP 100		/* down from init */
261513Sroot 
279878Ssam struct	sockaddr_in sin = { AF_INET };
286394Sroot extern	errno;
296394Sroot 
301513Sroot struct	utmp utmp[100];
311513Sroot int	nutmp;
321513Sroot int	uf;
331513Sroot unsigned utmpmtime;			/* last modification time for utmp */
341513Sroot int	onalrm();
359289Ssam struct	servent *sp;
361513Sroot 
371513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1)
381513Sroot 
391513Sroot main(argc, argv)
401513Sroot char **argv;
411513Sroot {
421513Sroot 	register cc;
431513Sroot 	char buf[BUFSIZ];
446394Sroot 	int s;
451513Sroot 
469289Ssam 	sp = getservbyname("biff", "udp");
479289Ssam 	if (sp == 0) {
489289Ssam 		fprintf(stderr, "comsat: biff/udp: unknown service\n");
499289Ssam 		exit(1);
509289Ssam 	}
5112746Ssam 	if (!debug)
521513Sroot 	if (fork())
531513Sroot 		exit();
541513Sroot 	chdir("/usr/spool/mail");
551513Sroot 	if((uf = open("/etc/utmp",0)) < 0)
561513Sroot 		perror("/etc/utmp"), exit(1);
571572Sbill 	sleep(10);
581513Sroot 	onalrm();
5913022Ssam 	signal(SIGALRM, onalrm);
6013022Ssam 	signal(SIGTTOU, SIG_IGN);
619289Ssam 	s = socket(AF_INET, SOCK_DGRAM, 0, 0);
626394Sroot 	if (s < 0) {
636394Sroot 		perror("socket");
641513Sroot 		exit(1);
651513Sroot 	}
669289Ssam 	sin.sin_port = sp->s_port;
679289Ssam 	if (bind(s, &sin, sizeof (sin), 0) < 0) {
689289Ssam 		perror("bind");
699289Ssam 		exit(1);
709289Ssam 	}
716394Sroot 	for (;;) {
726394Sroot 		char msgbuf[100];
736394Sroot 		int cc;
741513Sroot 
759289Ssam 		cc = recv(s, msgbuf, sizeof (msgbuf) - 1, 0);
766394Sroot 		if (cc <= 0) {
776394Sroot 			if (errno != EINTR)
786394Sroot 				sleep(1);
796394Sroot 			errno = 0;
806394Sroot 			continue;
811513Sroot 		}
826394Sroot 		msgbuf[cc] = 0;
836394Sroot 		mailfor(msgbuf);
841513Sroot 	}
851513Sroot }
861513Sroot 
871513Sroot onalrm()
881513Sroot {
891513Sroot 	struct stat statbf;
901513Sroot 	struct utmp *utp;
911513Sroot 
921513Sroot 	dprintf("alarm\n");
931513Sroot 	alarm(15);
941513Sroot 	fstat(uf,&statbf);
951513Sroot 	if (statbf.st_mtime > utmpmtime) {
961513Sroot 		dprintf(" changed\n");
971513Sroot 		utmpmtime = statbf.st_mtime;
981513Sroot 		lseek(uf, 0, 0);
991513Sroot 		nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp);
1001513Sroot 	} else
1011513Sroot 		dprintf(" ok\n");
1021513Sroot }
1031513Sroot 
1041513Sroot mailfor(name)
1051513Sroot 	char *name;
1061513Sroot {
1071513Sroot 	register struct utmp *utp = &utmp[nutmp];
1081513Sroot 	register char *cp;
1091513Sroot 	char *rindex();
1101513Sroot 	int offset;
1111513Sroot 
1121513Sroot 	dprintf("mailfor %s\n", name);
1131513Sroot 	cp = name;
1141513Sroot 	while (*cp && *cp != '@')
1151513Sroot 		cp++;
1161513Sroot 	if (*cp == 0) {
1171513Sroot 		dprintf("bad format\n");
1181513Sroot 		return;
1191513Sroot 	}
1201513Sroot 	*cp = 0;
1211513Sroot 	offset = atoi(cp+1);
1221513Sroot 	while (--utp >= utmp)
1231513Sroot 		if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
1241513Sroot 			if (fork() == 0) {
1251513Sroot 				signal(SIGALRM, SIG_DFL);
1261513Sroot 				alarm(30);
1271513Sroot 				notify(utp, offset), exit(0);
1281513Sroot 			} else
1291513Sroot 				while (wait3(0, WNOHANG, 0) > 0)
1301513Sroot 					continue;
1311513Sroot }
1321513Sroot 
1331513Sroot char *cr;
1341513Sroot 
1351513Sroot notify(utp, offset)
1361513Sroot 	register struct utmp *utp;
1371513Sroot {
1381513Sroot 	FILE *tp;
1391513Sroot 	struct sgttyb gttybuf;
14012746Ssam 	char tty[20], hostname[32];
1411513Sroot 	char name[sizeof (utmp[0].ut_name) + 1];
1421513Sroot 	struct stat stb;
1431513Sroot 
1441513Sroot 	strcpy(tty, "/dev/");
1451513Sroot 	strncat(tty, utp->ut_line, sizeof(utp->ut_line));
1461513Sroot 	dprintf("notify %s on %s\n", utp->ut_name, tty);
1471513Sroot 	if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) {
1481513Sroot 		dprintf("wrong mode\n");
1491513Sroot 		return;
1501513Sroot 	}
1511513Sroot 	if ((tp = fopen(tty,"w")) == 0) {
1521513Sroot 		dprintf("fopen failed\n");
1531513Sroot 		return;
1541513Sroot 	}
15512746Ssam 	ioctl(fileno(tp), TIOCGETP, &gttybuf);
1561513Sroot 	cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r";
15712746Ssam 	gethostname(hostname, sizeof (hostname));
1581513Sroot 	strncpy(name, utp->ut_name, sizeof (utp->ut_name));
1591513Sroot 	name[sizeof (name) - 1] = 0;
16012746Ssam 	fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n",
16112746Ssam 	    cr, name, hostname, cr);
1621513Sroot 	fprintf(tp,"----%s\n", cr);
1631513Sroot 	jkfprintf(tp, name, offset);
16412746Ssam 	fclose(tp);
1651513Sroot }
1661513Sroot 
1671513Sroot jkfprintf(tp, name, offset)
1681513Sroot 	register FILE *tp;
1691513Sroot {
1701513Sroot 	register FILE *fi;
1711513Sroot 	register int linecnt, charcnt;
17212746Ssam 	char line[BUFSIZ];
173*13783Ssam 	int inheader;
1741513Sroot 
1751513Sroot 	dprintf("HERE %s's mail starting at %d\n",
1761513Sroot 	    name, offset);
1771513Sroot 	if ((fi = fopen(name,"r")) == NULL) {
1781513Sroot 		dprintf("Cant read the mail\n");
1791513Sroot 		return;
1801513Sroot 	}
1811513Sroot 	fseek(fi, offset, 0);
18212746Ssam 	/*
18312746Ssam 	 * Print the first 7 lines or 560 characters of the new mail
18412746Ssam 	 * (whichever comes first).  Skip header crap other than
185*13783Ssam 	 * From, Subject, To, and Date.
18612746Ssam 	 */
1871513Sroot 	linecnt = 7;
1881513Sroot 	charcnt = 560;
189*13783Ssam 	inheader = 1;
19012746Ssam 	while (fgets(line, sizeof (line), fi) != NULL) {
19112746Ssam 		register char *cp;
19212746Ssam 		char *index();
193*13783Ssam 		int cnt;
1941513Sroot 
19512746Ssam 		if (linecnt <= 0 || charcnt <= 0) {
1961513Sroot 			fprintf(tp,"...more...%s\n", cr);
19713022Ssam 			return;
1981513Sroot 		}
199*13783Ssam 		if (strncmp(line, "From ", 5) == 0)
200*13783Ssam 			continue;
201*13783Ssam 		if (inheader && (line[0] == ' ' || line[0] == '\t'))
202*13783Ssam 			continue;
20312746Ssam 		cp = index(line, ':');
204*13783Ssam 		if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp))
205*13783Ssam 			inheader = 0;
206*13783Ssam 		else
207*13783Ssam 			cnt = cp - line;
208*13783Ssam 		if (inheader &&
209*13783Ssam 		    strncmp(line, "Date", cnt) &&
210*13783Ssam 		    strncmp(line, "From", cnt) &&
211*13783Ssam 		    strncmp(line, "Subject", cnt) &&
212*13783Ssam 		    strncmp(line, "To", cnt))
21312746Ssam 			continue;
21412746Ssam 		cp = index(line, '\n');
21512746Ssam 		if (cp)
21612746Ssam 			*cp = '\0';
21712746Ssam 		fprintf(tp,"%s%s\n", line, cr);
21812746Ssam 		linecnt--, charcnt -= strlen(line);
2191513Sroot 	}
22012746Ssam 	fprintf(tp,"----%s\n", cr);
2211513Sroot }
222