]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/rcvtty.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / rcvtty.c
1 /* rcvtty.c - a rcvmail program (a lot like rcvalert) handling IPC ttys */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: rcvtty.c,v 1.13 1994/04/21 18:20:50 jromine Exp $";
4 #endif /* lint */
5
6 #ifndef BSD42
7 #undef TTYD
8 #endif
9 #include "../h/mh.h"
10 #include "../h/rcvmail.h"
11 #include "../h/scansbr.h"
12 #include "../zotnet/tws.h"
13 #include <signal.h>
14 #include <sys/stat.h>
15 #ifndef TTYD
16 #include <utmp.h>
17 #endif /* not TTYD */
18 #ifdef LOCALE
19 #include <locale.h>
20 #endif
21
22 /* \f */
23 #define SCANFMT \
24 "%2(hour{dtimenow}):%02(min{dtimenow}): %<(size)%5(size) %>%<{encrypted}E%>\
25 %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \
26 %{subject}%<{body}<<%{body}>>%>"
27
28 static struct swit switches[] = {
29 #define HELPSW 0
30 "help", 4,
31
32 #define BIFFSW 1
33 "biff", 0,
34
35 #define FORMSW 2
36 "form formatfile", 0,
37 #define FMTSW 3
38 "format string", 5,
39
40 #define NLSW 4
41 "newline", 0,
42 #define NNLSW 5
43 "nonewline", 0,
44 #define BELSW 6
45 "bell", 0,
46 #define NBELSW 7
47 "nobell", 0,
48
49 NULL, 0
50 };
51
52 /* \f */
53
54 static jmp_buf myctx;
55
56 off_t lseek ();
57 char *getusr ();
58
59 static int message_fd(), header_fd();
60 static alert();
61
62 static int bell = 1;
63 static int newline = 1;
64 static int biff = 0;
65 static char *form = NULL;
66 static char *format = NULL;
67
68 /* \f */
69
70 /* ARGSUSED */
71
72 main (argc, argv)
73 int argc;
74 char **argv;
75 {
76 int md,
77 vecp = 0;
78 char *cp,
79 *user,
80 buf[100],
81 **ap,
82 **argp,
83 *arguments[MAXARGS],
84 *vec[MAXARGS];
85 #ifndef TTYD
86 char tty[BUFSIZ];
87 struct utmp ut;
88 register FILE *uf;
89 #endif /* not TTYD */
90
91 #ifdef LOCALE
92 setlocale(LC_ALL, "");
93 #endif
94 invo_name = r1bindex (argv[0], '/');
95 mts_init (invo_name);
96 if ((cp = m_find (invo_name)) != NULL) {
97 ap = brkstring (cp = getcpy (cp), " ", "\n");
98 ap = copyip (ap, arguments);
99 }
100 else
101 ap = arguments;
102 (void) copyip (argv + 1, ap);
103 argp = arguments;
104
105 /* \f */
106
107 while (cp = *argp++) {
108 if (*cp == '-')
109 switch (smatch (++cp, switches)) {
110 case AMBIGSW:
111 ambigsw (cp, switches);
112 done (1);
113 case UNKWNSW:
114 vec[vecp++] = --cp;
115 continue;
116 case HELPSW:
117 (void) sprintf (buf, "%s [command ...]", invo_name);
118 help (buf, switches);
119 done (1);
120
121 case BIFFSW:
122 biff = 1;
123 continue;
124
125 case FORMSW:
126 if (!(form = *argp++) || *form == '-')
127 adios (NULLCP, "missing argument to %s", argp[-2]);
128 format = NULL;
129 continue;
130 case FMTSW:
131 if (!(format = *argp++) || *format == '-')
132 adios (NULLCP, "missing argument to %s", argp[-2]);
133 form = NULL;
134 continue;
135
136 case NLSW:
137 newline = 1;
138 continue;
139 case NNLSW:
140 newline = 0;
141 continue;
142 case BELSW:
143 bell = 1;
144 continue;
145 case NBELSW:
146 bell = 0;
147 continue;
148
149 }
150 vec[vecp++] = cp;
151 }
152 vec[vecp] = 0;
153
154 /* \f */
155
156 if ((md = vecp ? message_fd (vec) : header_fd ()) == NOTOK)
157 exit (RCV_MBX);
158
159 user = getusr ();
160 #ifndef TTYD
161 if ((uf = fopen ("/etc/utmp", "r")) == NULL)
162 exit (RCV_MBX);
163 while (fread ((char *) &ut, sizeof ut, 1, uf) == 1)
164 if (ut.ut_name[0] != 0
165 && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) {
166 (void) strncpy (tty, ut.ut_line, sizeof ut.ut_line);
167 alert (tty, md);
168 }
169 (void) fclose (uf);
170 #else /* TTYD */
171 alert (user, md);
172 #endif /* TTYD */
173
174 exit (RCV_MOK);
175 }
176
177 /* \f */
178
179 /* ARGSUSED */
180
181 static TYPESIG alrmser (i)
182 int i;
183 {
184 longjmp (myctx, DONE);
185 }
186
187
188 static int message_fd (vec)
189 char *vec[];
190 {
191 int bytes,
192 child_id,
193 fd;
194 char tmpfil[BUFSIZ];
195 struct stat st;
196
197 (void) unlink (mktemp (strcpy (tmpfil, "/tmp/rcvttyXXXXX")));
198 if ((fd = creat (tmpfil, 0600)) == NOTOK)
199 return header_fd ();
200 (void) close (fd);
201
202 if ((fd = open (tmpfil, 2)) == NOTOK)
203 return header_fd ();
204 (void) unlink (tmpfil);
205
206 /* \f */
207
208 switch (child_id = vfork ()) {
209 case NOTOK:
210 (void) close (fd);
211 return header_fd ();
212
213 case OK:
214 rewind (stdin);
215 if (dup2 (fd, 1) == NOTOK || dup2 (fd, 2) == NOTOK)
216 _exit (-1);
217 closefds (3);
218 #ifdef BSD42
219 (void) setpgrp (0, getpid ());
220 #endif /* BSD42 */
221 execvp (vec[0], vec);
222 _exit (-1);
223
224 default:
225 switch (setjmp (myctx)) {
226 case OK:
227 (void) signal (SIGALRM, alrmser);
228 bytes = fstat (fileno (stdin), &st) != NOTOK
229 ? (int) st.st_size : 100;
230 if (bytes <= 0)
231 bytes = 100;
232 (void) alarm ((unsigned) (bytes * 60 + 300));
233
234 (void) pidwait (child_id, OK);
235
236 (void) alarm (0);
237 if (fstat (fd, &st) != NOTOK && st.st_size > (off_t)0)
238 return fd;
239 (void) close (fd);
240 return header_fd ();
241
242 default:
243 #ifndef BSD42
244 (void) kill (child_id, SIGKILL);
245 #else /* BSD42 */
246 (void) killpg (child_id, SIGKILL);
247 #endif /* BSD42 */
248 (void) close (fd);
249 return header_fd ();
250 }
251 }
252 }
253
254 /* \f */
255
256 static int header_fd () {
257 int fd;
258 char tmpfil[BUFSIZ];
259
260 (void) strcpy (tmpfil, m_tmpfil (invo_name));
261 if ((fd = creat (tmpfil, 0600)) == NOTOK)
262 return NOTOK;
263 (void) close (fd);
264
265 if ((fd = open (tmpfil, 2)) == NOTOK)
266 return NOTOK;
267 (void) unlink (tmpfil);
268
269 rewind (stdin);
270 (void) scan (stdin, 0, 0, new_fs (form, format, SCANFMT), 0, 0, 0,
271 0, 0, 0L, 0);
272 if ( newline )
273 (void) write (fd, "\n\r", 2);
274 (void) write (fd, scanl, strlen (scanl));
275 if ( bell )
276 (void) write (fd, "\007", 1);
277
278 return fd;
279 }
280
281 /* \f */
282
283 #ifndef TTYD
284 static alert (tty, md)
285 char *tty;
286 int md;
287 {
288 int i,
289 td;
290 char buffer[BUFSIZ],
291 ttyspec[BUFSIZ];
292 struct stat st;
293
294 (void) sprintf (ttyspec, "/dev/%s", tty);
295 if (stat (ttyspec, &st) == NOTOK ||
296 (st.st_mode & (biff ? S_IEXEC :
297 #ifdef BSD43
298 (S_IWRITE >> 3)
299 #else /* BSD43 */
300 02
301 #endif /* BSD43 */
302 )) == 0)
303 return;
304
305 switch (setjmp (myctx)) {
306 case OK:
307 (void) signal (SIGALRM, alrmser);
308 (void) alarm (2);
309 td = open (ttyspec, 1);
310 (void) alarm (0);
311 if (td == NOTOK)
312 return;
313 break;
314
315 default:
316 (void) alarm (0);
317 return;
318 }
319
320 (void) lseek (md, (off_t)0, 0);
321
322 while ((i = read (md, buffer, sizeof buffer)) > 0)
323 if (write (td, buffer, i) != i)
324 break;
325
326 (void) close (td);
327 }
328 #else /* TTYD */
329
330 /* \f */
331
332 static alert (user, md)
333 register char *user;
334 int md;
335 {
336 int i,
337 td;
338 char buffer[BUFSIZ];
339
340 if ((td = ttyw ("notify", NULLCP, NULLCP, user)) == NOTOK)
341 return;
342 (void) signal (SIGPIPE, SIG_IGN);
343
344 (void) lseek (md, (off_t), 0);
345 while ((i = read (md, buffer, sizeof buffer)) > 0)
346 if (write (td, buffer, i) != i)
347 break;
348
349 (void) close (td);
350 }
351 #endif /* TTYD */