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