xref: /original-bsd/libexec/comsat/comsat.c (revision 81a135f6)
1 #ifndef lint
2 static	char sccsid[] = "@(#)comsat.c	4.10 (Berkeley) 04/11/84";
3 #endif
4 
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/stat.h>
8 #include <sys/wait.h>
9 
10 #include <netinet/in.h>
11 
12 #include <stdio.h>
13 #include <sgtty.h>
14 #include <utmp.h>
15 #include <signal.h>
16 #include <errno.h>
17 #include <netdb.h>
18 
19 /*
20  * comsat
21  */
22 int	debug = 0;
23 #define	dprintf	if (debug) printf
24 
25 #define MAXUTMP 100		/* down from init */
26 
27 struct	sockaddr_in sin = { AF_INET };
28 extern	errno;
29 
30 struct	utmp utmp[100];
31 int	nutmp;
32 int	uf;
33 unsigned utmpmtime;			/* last modification time for utmp */
34 int	onalrm();
35 long	lastmsgtime;
36 
37 #define	MAXIDLE	120
38 #define NAMLEN (sizeof (uts[0].ut_name) + 1)
39 
40 main(argc, argv)
41 	int argc;
42 	char *argv[];
43 {
44 	register int cc;
45 	char buf[BUFSIZ];
46 	char msgbuf[100];
47 	struct sockaddr_in from;
48 	int fromlen;
49 
50 	/* verify proper invocation */
51 	fromlen = sizeof (from);
52 	if (getsockname(0, &from, &fromlen) < 0) {
53 		fprintf(stderr, "%s: ", argv[0]);
54 		perror("getsockname");
55 		_exit(1);
56 	}
57 	chdir("/usr/spool/mail");
58 	if ((uf = open("/etc/utmp",0)) < 0) {
59 		perror("/etc/utmp");
60 		(void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0);
61 		exit(1);
62 	}
63 	lastmsgtime = time(0);
64 	onalrm();
65 	signal(SIGALRM, onalrm);
66 	signal(SIGTTOU, SIG_IGN);
67 	for (;;) {
68 		cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0);
69 		if (cc <= 0) {
70 			if (errno != EINTR)
71 				sleep(1);
72 			errno = 0;
73 			continue;
74 		}
75 		sigblock(1<<SIGALRM);
76 		msgbuf[cc] = 0;
77 		lastmsgtime = time(0);
78 		mailfor(msgbuf);
79 		sigsetmask(0);
80 	}
81 }
82 
83 onalrm()
84 {
85 	struct stat statbf;
86 	struct utmp *utp;
87 
88 	if (time(0) - lastmsgtime >= MAXIDLE)
89 		exit(1);
90 	dprintf("alarm\n");
91 	alarm(15);
92 	fstat(uf,&statbf);
93 	if (statbf.st_mtime > utmpmtime) {
94 		dprintf(" changed\n");
95 		utmpmtime = statbf.st_mtime;
96 		lseek(uf, 0, 0);
97 		nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp);
98 	} else
99 		dprintf(" ok\n");
100 }
101 
102 mailfor(name)
103 	char *name;
104 {
105 	register struct utmp *utp = &utmp[nutmp];
106 	register char *cp;
107 	char *rindex();
108 	int offset;
109 
110 	dprintf("mailfor %s\n", name);
111 	cp = name;
112 	while (*cp && *cp != '@')
113 		cp++;
114 	if (*cp == 0) {
115 		dprintf("bad format\n");
116 		return;
117 	}
118 	*cp = 0;
119 	offset = atoi(cp+1);
120 	while (--utp >= utmp)
121 		if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
122 			if (fork() == 0) {
123 				signal(SIGALRM, SIG_DFL);
124 				alarm(30);
125 				notify(utp, offset), exit(0);
126 			} else
127 				while (wait3(0, WNOHANG, 0) > 0)
128 					continue;
129 }
130 
131 char *cr;
132 
133 notify(utp, offset)
134 	register struct utmp *utp;
135 {
136 	FILE *tp;
137 	struct sgttyb gttybuf;
138 	char tty[20], hostname[32];
139 	char name[sizeof (utmp[0].ut_name) + 1];
140 	struct stat stb;
141 
142 	strcpy(tty, "/dev/");
143 	strncat(tty, utp->ut_line, sizeof(utp->ut_line));
144 	dprintf("notify %s on %s\n", utp->ut_name, tty);
145 	if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) {
146 		dprintf("wrong mode\n");
147 		return;
148 	}
149 	if ((tp = fopen(tty,"w")) == 0) {
150 		dprintf("fopen failed\n");
151 		return;
152 	}
153 	ioctl(fileno(tp), TIOCGETP, &gttybuf);
154 	cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r";
155 	gethostname(hostname, sizeof (hostname));
156 	strncpy(name, utp->ut_name, sizeof (utp->ut_name));
157 	name[sizeof (name) - 1] = 0;
158 	fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n",
159 	    cr, name, hostname, cr);
160 	fprintf(tp,"----%s\n", cr);
161 	jkfprintf(tp, name, offset);
162 	fclose(tp);
163 }
164 
165 jkfprintf(tp, name, offset)
166 	register FILE *tp;
167 {
168 	register FILE *fi;
169 	register int linecnt, charcnt;
170 	char line[BUFSIZ];
171 	int inheader;
172 
173 	dprintf("HERE %s's mail starting at %d\n",
174 	    name, offset);
175 	if ((fi = fopen(name,"r")) == NULL) {
176 		dprintf("Cant read the mail\n");
177 		return;
178 	}
179 	fseek(fi, offset, 0);
180 	/*
181 	 * Print the first 7 lines or 560 characters of the new mail
182 	 * (whichever comes first).  Skip header crap other than
183 	 * From, Subject, To, and Date.
184 	 */
185 	linecnt = 7;
186 	charcnt = 560;
187 	inheader = 1;
188 	while (fgets(line, sizeof (line), fi) != NULL) {
189 		register char *cp;
190 		char *index();
191 		int cnt;
192 
193 		if (linecnt <= 0 || charcnt <= 0) {
194 			fprintf(tp,"...more...%s\n", cr);
195 			return;
196 		}
197 		if (strncmp(line, "From ", 5) == 0)
198 			continue;
199 		if (inheader && (line[0] == ' ' || line[0] == '\t'))
200 			continue;
201 		cp = index(line, ':');
202 		if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp))
203 			inheader = 0;
204 		else
205 			cnt = cp - line;
206 		if (inheader &&
207 		    strncmp(line, "Date", cnt) &&
208 		    strncmp(line, "From", cnt) &&
209 		    strncmp(line, "Subject", cnt) &&
210 		    strncmp(line, "To", cnt))
211 			continue;
212 		cp = index(line, '\n');
213 		if (cp)
214 			*cp = '\0';
215 		fprintf(tp,"%s%s\n", line, cr);
216 		linecnt--, charcnt -= strlen(line);
217 	}
218 	fprintf(tp,"----%s\n", cr);
219 }
220