xref: /original-bsd/libexec/comsat/comsat.c (revision 3ca00c4d)
1 #ifndef lint
2 static	char *sccsid = "@(#)comsat.c	4.6 83/05/27";
3 #endif
4 
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 
8 #include <netinet/in.h>
9 
10 #include <stdio.h>
11 #include <sgtty.h>
12 #include <utmp.h>
13 #include <stat.h>
14 #include <wait.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 	if (!debug)
58 	while (fork())
59 		wait(0);
60 	sleep(10);
61 	onalrm();
62 	sigset(SIGALRM, onalrm);
63 	sigignore(SIGTTOU);
64 	s = socket(AF_INET, SOCK_DGRAM, 0, 0);
65 	if (s < 0) {
66 		perror("socket");
67 		exit(1);
68 	}
69 	sin.sin_port = sp->s_port;
70 	if (bind(s, &sin, sizeof (sin), 0) < 0) {
71 		perror("bind");
72 		exit(1);
73 	}
74 	for (;;) {
75 		char msgbuf[100];
76 		int cc;
77 
78 		cc = recv(s, msgbuf, sizeof (msgbuf) - 1, 0);
79 		if (cc <= 0) {
80 			if (errno != EINTR)
81 				sleep(1);
82 			errno = 0;
83 			continue;
84 		}
85 		msgbuf[cc] = 0;
86 		mailfor(msgbuf);
87 	}
88 }
89 
90 onalrm()
91 {
92 	struct stat statbf;
93 	struct utmp *utp;
94 
95 	dprintf("alarm\n");
96 	alarm(15);
97 	fstat(uf,&statbf);
98 	if (statbf.st_mtime > utmpmtime) {
99 		dprintf(" changed\n");
100 		utmpmtime = statbf.st_mtime;
101 		lseek(uf, 0, 0);
102 		nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp);
103 	} else
104 		dprintf(" ok\n");
105 }
106 
107 mailfor(name)
108 	char *name;
109 {
110 	register struct utmp *utp = &utmp[nutmp];
111 	register char *cp;
112 	char *rindex();
113 	int offset;
114 
115 	dprintf("mailfor %s\n", name);
116 	cp = name;
117 	while (*cp && *cp != '@')
118 		cp++;
119 	if (*cp == 0) {
120 		dprintf("bad format\n");
121 		return;
122 	}
123 	*cp = 0;
124 	offset = atoi(cp+1);
125 	while (--utp >= utmp)
126 		if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
127 			if (fork() == 0) {
128 				signal(SIGALRM, SIG_DFL);
129 				alarm(30);
130 				notify(utp, offset), exit(0);
131 			} else
132 				while (wait3(0, WNOHANG, 0) > 0)
133 					continue;
134 }
135 
136 char *cr;
137 
138 notify(utp, offset)
139 	register struct utmp *utp;
140 {
141 	FILE *tp;
142 	struct sgttyb gttybuf;
143 	char tty[20], hostname[32];
144 	char name[sizeof (utmp[0].ut_name) + 1];
145 	struct stat stb;
146 
147 	strcpy(tty, "/dev/");
148 	strncat(tty, utp->ut_line, sizeof(utp->ut_line));
149 	dprintf("notify %s on %s\n", utp->ut_name, tty);
150 	if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) {
151 		dprintf("wrong mode\n");
152 		return;
153 	}
154 	if ((tp = fopen(tty,"w")) == 0) {
155 		dprintf("fopen failed\n");
156 		return;
157 	}
158 	ioctl(fileno(tp), TIOCGETP, &gttybuf);
159 	cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r";
160 	gethostname(hostname, sizeof (hostname));
161 	strncpy(name, utp->ut_name, sizeof (utp->ut_name));
162 	name[sizeof (name) - 1] = 0;
163 	fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n",
164 	    cr, name, hostname, cr);
165 	fprintf(tp,"----%s\n", cr);
166 	jkfprintf(tp, name, offset);
167 	fclose(tp);
168 }
169 
170 jkfprintf(tp, name, offset)
171 	register FILE *tp;
172 {
173 	register FILE *fi;
174 	register int linecnt, charcnt;
175 	char line[BUFSIZ];
176 
177 	dprintf("HERE %s's mail starting at %d\n",
178 	    name, offset);
179 	if ((fi = fopen(name,"r")) == NULL) {
180 		dprintf("Cant read the mail\n");
181 		return;
182 	}
183 	fseek(fi, offset, 0);
184 	/*
185 	 * Print the first 7 lines or 560 characters of the new mail
186 	 * (whichever comes first).  Skip header crap other than
187 	 * From: and Subject:.
188 	 */
189 	linecnt = 7;
190 	charcnt = 560;
191 	while (fgets(line, sizeof (line), fi) != NULL) {
192 		register char *cp;
193 		char *index();
194 
195 		if (linecnt <= 0 || charcnt <= 0) {
196 			fprintf(tp,"...more...%s\n", cr);
197 			break;
198 		}
199 		cp = index(line, ':');
200 		if (cp &&
201 		    strncmp(line, "Date", cp - line) &&
202 		    strncmp(line, "From", cp - line) &&
203 		    strncmp(line, "Subject", cp - line) &&
204 		    strncmp(line, "To", cp - line))
205 			continue;
206 		cp = index(line, '\n');
207 		if (cp)
208 			*cp = '\0';
209 		fprintf(tp,"%s%s\n", line, cr);
210 		linecnt--, charcnt -= strlen(line);
211 	}
212 	fprintf(tp,"----%s\n", cr);
213 }
214