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