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