xref: /csrg-svn/libexec/comsat/comsat.c (revision 1513)
1*1513Sroot static	char *sccsid = "@(#)comsat.c	4.1 (Berkeley) 10/18/80";
2*1513Sroot #include <stdio.h>
3*1513Sroot #include <sys/mx.h>
4*1513Sroot #include <sgtty.h>
5*1513Sroot #include <utmp.h>
6*1513Sroot #include <sys/types.h>
7*1513Sroot #include <stat.h>
8*1513Sroot #include <wait.h>
9*1513Sroot #include <signal.h>
10*1513Sroot 
11*1513Sroot /*
12*1513Sroot  * comsat
13*1513Sroot  */
14*1513Sroot #define	dprintf	if (0) printf
15*1513Sroot int	xd;
16*1513Sroot 
17*1513Sroot struct  ctp {
18*1513Sroot 	short   ctrl;
19*1513Sroot 	short   ctrlarg;
20*1513Sroot 	struct  sgttyb ctrlv;
21*1513Sroot } ctp;
22*1513Sroot 
23*1513Sroot #define MAXUTMP 100		/* down from init */
24*1513Sroot 
25*1513Sroot struct	utmp utmp[100];
26*1513Sroot int	nutmp;
27*1513Sroot int	uf;
28*1513Sroot unsigned utmpmtime;			/* last modification time for utmp */
29*1513Sroot int	onalrm();
30*1513Sroot 
31*1513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1)
32*1513Sroot 
33*1513Sroot main(argc, argv)
34*1513Sroot char **argv;
35*1513Sroot {
36*1513Sroot 	register cc;
37*1513Sroot 	char buf[BUFSIZ];
38*1513Sroot 
39*1513Sroot 	if (fork())
40*1513Sroot 		exit();
41*1513Sroot 	chdir("/usr/spool/mail");
42*1513Sroot 	if((uf = open("/etc/utmp",0)) < 0)
43*1513Sroot 		perror("/etc/utmp"), exit(1);
44*1513Sroot 	while (fork())
45*1513Sroot 		wait(0);
46*1513Sroot 	onalrm();
47*1513Sroot 	sigset(SIGALRM, onalrm);
48*1513Sroot 	sigignore(SIGTTOU);
49*1513Sroot 	unlink("/dev/mail");
50*1513Sroot 	xd = mpx("/dev/mail", 0666);
51*1513Sroot 	if (xd < 0) {
52*1513Sroot 		close(2);
53*1513Sroot 		open("/dev/console", 1);
54*1513Sroot 		perror("/dev/mail");
55*1513Sroot 		exit(1);
56*1513Sroot 	}
57*1513Sroot 	while((cc=read(xd, buf, BUFSIZ)) >= 0) {
58*1513Sroot 		dprintf("0: got %d bytes\n", cc);
59*1513Sroot 		unpack(buf, cc);
60*1513Sroot 	}
61*1513Sroot }
62*1513Sroot 
63*1513Sroot #define	skip(rp, c)	((struct rh *)(((char *)rp)+c))
64*1513Sroot 
65*1513Sroot unpack(rp, cc)
66*1513Sroot 	register struct rh *rp;
67*1513Sroot {
68*1513Sroot 	register struct rh *end;
69*1513Sroot 	int i;
70*1513Sroot 
71*1513Sroot 	i = 0;
72*1513Sroot 	end = skip(rp, cc);
73*1513Sroot 	while (rp < end) {
74*1513Sroot 		dprintf("%d: ", ++i);
75*1513Sroot 		if (rp->count==0) {
76*1513Sroot 			dprintf("%d byte control message\n", rp->ccount);
77*1513Sroot 			control(rp->index, rp+1, rp->ccount);
78*1513Sroot 		} else {
79*1513Sroot 			dprintf("%*.*s\n", rp->count, rp->count, rp+1);
80*1513Sroot 			sighold(SIGALRM);
81*1513Sroot 			mailfor(rp+1);
82*1513Sroot 			sigrelse(SIGALRM);
83*1513Sroot 		}
84*1513Sroot 		rp->count += rp->ccount;
85*1513Sroot 		if (rp->count & 1)
86*1513Sroot 			rp->count++;
87*1513Sroot 		rp = skip(rp, rp->count);
88*1513Sroot 		rp++;
89*1513Sroot 	}
90*1513Sroot }
91*1513Sroot 
92*1513Sroot control(x, cb, cc)
93*1513Sroot 	register char *cb;
94*1513Sroot {
95*1513Sroot 	register char *end;
96*1513Sroot 	int cmd;
97*1513Sroot 	short *sp;
98*1513Sroot 	struct wh or;
99*1513Sroot 
100*1513Sroot 	end = cb + cc;
101*1513Sroot 	cmd = *cb++;
102*1513Sroot 	sp = (short *)cb+1;
103*1513Sroot 	switch (cmd) {
104*1513Sroot 
105*1513Sroot 	case M_WATCH:
106*1513Sroot 		dprintf("attach %x, uid %d\n", x, *sp);
107*1513Sroot 		attach(x, xd);
108*1513Sroot 		break;
109*1513Sroot 
110*1513Sroot 	case M_CLOSE:
111*1513Sroot 		sp = (short *)cb;
112*1513Sroot 		dprintf("detach %x, uid %d\n", x, *sp);
113*1513Sroot 		detach(x, xd);
114*1513Sroot 		break;
115*1513Sroot 
116*1513Sroot 	case M_IOCTL:
117*1513Sroot 		dprintf("ioctl %x\n", x);
118*1513Sroot 		or.index = x;
119*1513Sroot 		or.count = 0;
120*1513Sroot 		or.ccount = sizeof ctp;
121*1513Sroot 		or.data = (char *) &ctp.ctrlarg;
122*1513Sroot 		ctp.ctrlarg = M_IOANS;
123*1513Sroot 		write(xd, &or, sizeof or);
124*1513Sroot 		break;
125*1513Sroot 
126*1513Sroot 	default:
127*1513Sroot 		dprintf("unknown command %d\n", cmd);
128*1513Sroot 		return;
129*1513Sroot 	}
130*1513Sroot }
131*1513Sroot 
132*1513Sroot onalrm()
133*1513Sroot {
134*1513Sroot 	struct stat statbf;
135*1513Sroot 	struct utmp *utp;
136*1513Sroot 
137*1513Sroot 	dprintf("alarm\n");
138*1513Sroot 	alarm(15);
139*1513Sroot 	fstat(uf,&statbf);
140*1513Sroot 	if (statbf.st_mtime > utmpmtime) {
141*1513Sroot 		dprintf(" changed\n");
142*1513Sroot 		utmpmtime = statbf.st_mtime;
143*1513Sroot 		lseek(uf, 0, 0);
144*1513Sroot 		nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp);
145*1513Sroot 	} else
146*1513Sroot 		dprintf(" ok\n");
147*1513Sroot }
148*1513Sroot 
149*1513Sroot mailfor(name)
150*1513Sroot 	char *name;
151*1513Sroot {
152*1513Sroot 	register struct utmp *utp = &utmp[nutmp];
153*1513Sroot 	register char *cp;
154*1513Sroot 	char *rindex();
155*1513Sroot 	int offset;
156*1513Sroot 
157*1513Sroot 	dprintf("mailfor %s\n", name);
158*1513Sroot 	cp = name;
159*1513Sroot 	while (*cp && *cp != '@')
160*1513Sroot 		cp++;
161*1513Sroot 	if (*cp == 0) {
162*1513Sroot 		dprintf("bad format\n");
163*1513Sroot 		return;
164*1513Sroot 	}
165*1513Sroot 	*cp = 0;
166*1513Sroot 	offset = atoi(cp+1);
167*1513Sroot 	while (--utp >= utmp)
168*1513Sroot 		if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
169*1513Sroot 			if (fork() == 0) {
170*1513Sroot 				signal(SIGALRM, SIG_DFL);
171*1513Sroot 				alarm(30);
172*1513Sroot 				notify(utp, offset), exit(0);
173*1513Sroot 			} else
174*1513Sroot 				while (wait3(0, WNOHANG, 0) > 0)
175*1513Sroot 					continue;
176*1513Sroot }
177*1513Sroot 
178*1513Sroot char *cr;
179*1513Sroot 
180*1513Sroot notify(utp, offset)
181*1513Sroot 	register struct utmp *utp;
182*1513Sroot {
183*1513Sroot 	FILE *tp;
184*1513Sroot 	struct sgttyb gttybuf;
185*1513Sroot 	char tty[20];
186*1513Sroot 	char name[sizeof (utmp[0].ut_name) + 1];
187*1513Sroot 	struct stat stb;
188*1513Sroot 
189*1513Sroot 	strcpy(tty, "/dev/");
190*1513Sroot 	strncat(tty, utp->ut_line, sizeof(utp->ut_line));
191*1513Sroot 	dprintf("notify %s on %s\n", utp->ut_name, tty);
192*1513Sroot 	if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) {
193*1513Sroot 		dprintf("wrong mode\n");
194*1513Sroot 		return;
195*1513Sroot 	}
196*1513Sroot 	if ((tp = fopen(tty,"w")) == 0) {
197*1513Sroot 		dprintf("fopen failed\n");
198*1513Sroot 		return;
199*1513Sroot 	}
200*1513Sroot 	gtty(fileno(tp),&gttybuf);
201*1513Sroot 	cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r";
202*1513Sroot 	strncpy(name, utp->ut_name, sizeof (utp->ut_name));
203*1513Sroot 	name[sizeof (name) - 1] = 0;
204*1513Sroot 	fprintf(tp,"%s\n\007New mail for %s\007 has arrived:%s\n",
205*1513Sroot 	    cr, name, cr);
206*1513Sroot 	fprintf(tp,"----%s\n", cr);
207*1513Sroot 	jkfprintf(tp, name, offset);
208*1513Sroot 	 fclose(tp);
209*1513Sroot }
210*1513Sroot 
211*1513Sroot jkfprintf(tp, name, offset)
212*1513Sroot 	register FILE *tp;
213*1513Sroot {
214*1513Sroot 	register FILE *fi;
215*1513Sroot 	register int linecnt, charcnt;
216*1513Sroot 
217*1513Sroot 	dprintf("HERE %s's mail starting at %d\n",
218*1513Sroot 	    name, offset);
219*1513Sroot 	if ((fi = fopen(name,"r")) == NULL) {
220*1513Sroot 		dprintf("Cant read the mail\n");
221*1513Sroot 		return;
222*1513Sroot 	}
223*1513Sroot 	fseek(fi, offset, 0);
224*1513Sroot 	linecnt = 7;
225*1513Sroot 	charcnt = 560;
226*1513Sroot 	/*
227*1513Sroot 	 * print the first 7 lines or 560 characters of the new mail
228*1513Sroot 	 * (whichever comes first)
229*1513Sroot 	 */
230*1513Sroot 	for (;;) {
231*1513Sroot 		register ch;
232*1513Sroot 
233*1513Sroot 	 	if ((ch = getc(fi)) == EOF) {
234*1513Sroot 			fprintf(tp,"----%s\n", cr);
235*1513Sroot 			break;
236*1513Sroot 		}
237*1513Sroot 		if (ch == '\n') {
238*1513Sroot 			fprintf(tp,"%s\n", cr);
239*1513Sroot 		 	if (linecnt-- < 0) {
240*1513Sroot 				fprintf(tp,"...more...%s\n", cr);
241*1513Sroot 				break;
242*1513Sroot 			}
243*1513Sroot 		} else if(linecnt <= 0) {
244*1513Sroot 			fprintf(tp,"...more...%s\n", cr);
245*1513Sroot 			break;
246*1513Sroot 		} else
247*1513Sroot 			putc(ch, tp);
248*1513Sroot 		if (charcnt-- == 0) {
249*1513Sroot 			fprintf(tp, "%s\n", cr);
250*1513Sroot 			break;
251*1513Sroot 		}
252*1513Sroot 	}
253*1513Sroot }
254