0
|
1 /* rcvtty.c - a rcvmail program (a lot like rcvalert) handling IPC ttys */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: rcvtty.c,v 1.1.1.1 2005/04/18 14:46:07 kono Exp $";
|
0
|
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 #ifndef UTMP_FILENAME
|
|
18 #ifdef UTMP_FILE
|
|
19 #define UTMP_FILENAME UTMP_FILE
|
|
20 #else
|
|
21 #ifdef _PATH_UTMP
|
|
22 #define UTMP_FILENAME _PATH_UTMP
|
|
23 #else
|
|
24 #define UTMP_FILENAME "/etc/utmp"
|
|
25 #endif
|
|
26 #endif
|
|
27 #endif /* UTMP_FILENAME */
|
|
28 #endif /* not TTYD */
|
|
29 #ifdef LOCALE
|
|
30 #include <locale.h>
|
|
31 #endif
|
12
|
32 //#ifdef UNISTD
|
0
|
33 #include <unistd.h>
|
12
|
34 //#endif
|
0
|
35
|
|
36 /* */
|
|
37 #ifdef MIME_HEADERS
|
|
38 #define SCANFMT \
|
|
39 "%2(hour{dtimenow}):%02(min{dtimenow}): %<(size)%5(size) %>%<{encrypted}E%>\
|
|
40 %<(mymbox{from})%<{to}To:%14(hdecode(friendly{to}))%>%>\
|
|
41 %<(zero)%17(hdecode(friendly{from}))%> \
|
|
42 %(hdecode{subject})%<{body}<<%{body}>>%>"
|
|
43 #else /* MIME_HEADERS */
|
|
44 #define SCANFMT \
|
|
45 "%2(hour{dtimenow}):%02(min{dtimenow}): %<(size)%5(size) %>%<{encrypted}E%>\
|
|
46 %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \
|
|
47 %{subject}%<{body}<<%{body}>>%>"
|
|
48 #endif /* MIME_HEADERS */
|
|
49
|
|
50 static struct swit switches[] = {
|
|
51 #define HELPSW 0
|
|
52 "help", 4,
|
|
53
|
|
54 #define BIFFSW 1
|
|
55 "biff", 0,
|
|
56
|
|
57 #define FORMSW 2
|
|
58 "form formatfile", 0,
|
|
59 #define FMTSW 3
|
|
60 "format string", 5,
|
|
61
|
|
62 #define NLSW 4
|
|
63 "newline", 0,
|
|
64 #define NNLSW 5
|
|
65 "nonewline", 0,
|
|
66 #define BELSW 6
|
|
67 "bell", 0,
|
|
68 #define NBELSW 7
|
|
69 "nobell", 0,
|
|
70
|
|
71 NULL, 0
|
|
72 };
|
|
73
|
|
74 /* */
|
|
75
|
|
76 static jmp_buf myctx;
|
|
77
|
|
78 off_t lseek ();
|
|
79 char *getusr ();
|
|
80
|
|
81 static int message_fd(), header_fd();
|
16
|
82 static void alert();
|
0
|
83
|
|
84 static int bell = 1;
|
|
85 static int newline = 1;
|
|
86 static int biff = 0;
|
|
87 static char *form = NULL;
|
|
88 static char *format = NULL;
|
|
89
|
|
90 /* */
|
|
91
|
|
92 /* ARGSUSED */
|
|
93
|
|
94 #ifdef BSD43
|
|
95 static int return_gid;
|
|
96 #endif /* BSD43 */
|
|
97
|
|
98 main (argc, argv)
|
|
99 int argc;
|
|
100 char **argv;
|
|
101 {
|
|
102 int md,
|
|
103 vecp = 0;
|
|
104 char *cp,
|
|
105 *user,
|
|
106 buf[100],
|
|
107 **ap,
|
|
108 **argp,
|
|
109 *arguments[MAXARGS],
|
|
110 *vec[MAXARGS];
|
|
111 #ifndef TTYD
|
|
112 char tty[BUFSIZ];
|
|
113 struct utmp ut;
|
|
114 register FILE *uf;
|
|
115 #endif /* not TTYD */
|
|
116
|
|
117 #ifdef BSD43
|
|
118 return_gid = getegid(); /* Save effective gid, assuming we'll use it */
|
|
119 setegid(getgid()); /* Turn off extraordinary privileges */
|
|
120 #endif /* BSD43 */
|
|
121 #ifdef LOCALE
|
|
122 setlocale(LC_ALL, "");
|
|
123 #endif
|
|
124 #ifdef JAPAN
|
|
125 ml_init();
|
|
126 #endif /* JAPAN */
|
|
127 invo_name = r1bindex (argv[0], '/');
|
|
128 if (strlen(invo_name) > NAMESZ) {
|
|
129 fprintf(stderr, "%s: argv[0] too long\n", invo_name);
|
|
130 exit(1);
|
|
131 }
|
|
132 mts_init (invo_name);
|
|
133 if ((cp = m_find (invo_name)) != NULL) {
|
|
134 ap = brkstring (cp = getcpy (cp), " ", "\n");
|
|
135 ap = copyip (ap, arguments);
|
|
136 }
|
|
137 else
|
|
138 ap = arguments;
|
|
139 if (argc > MAXARGS - (ap - arguments))
|
|
140 adios (NULLCP, "too many arguments.");
|
|
141 (void) copyip (argv + 1, ap);
|
|
142 for (argp = arguments; *argp; argp++)
|
|
143 if (strlen(*argp) >= BUFSIZ / 4)
|
|
144 adios (NULLCP, "argument too long");
|
|
145 argp = arguments;
|
|
146
|
|
147 /* */
|
|
148
|
|
149 while (cp = *argp++) {
|
|
150 if (*cp == '-')
|
|
151 switch (smatch (++cp, switches)) {
|
|
152 case AMBIGSW:
|
|
153 ambigsw (cp, switches);
|
|
154 done (1);
|
|
155 case UNKWNSW:
|
|
156 vec[vecp++] = --cp;
|
|
157 continue;
|
|
158 case HELPSW:
|
|
159 (void) sprintf (buf, "%s [command ...]", invo_name);
|
|
160 help (buf, switches);
|
|
161 done (1);
|
|
162
|
|
163 case BIFFSW:
|
|
164 biff = 1;
|
|
165 continue;
|
|
166
|
|
167 case FORMSW:
|
|
168 if (!(form = *argp++) || *form == '-')
|
|
169 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
170 format = NULL;
|
|
171 continue;
|
|
172 case FMTSW:
|
|
173 if (!(format = *argp++) || *format == '-')
|
|
174 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
175 form = NULL;
|
|
176 continue;
|
|
177
|
|
178 case NLSW:
|
|
179 newline = 1;
|
|
180 continue;
|
|
181 case NNLSW:
|
|
182 newline = 0;
|
|
183 continue;
|
|
184 case BELSW:
|
|
185 bell = 1;
|
|
186 continue;
|
|
187 case NBELSW:
|
|
188 bell = 0;
|
|
189 continue;
|
|
190
|
|
191 }
|
|
192 vec[vecp++] = cp;
|
|
193 }
|
|
194 vec[vecp] = 0;
|
|
195
|
|
196 /* */
|
|
197
|
|
198 if ((md = vecp ? message_fd (vec) : header_fd ()) == NOTOK)
|
|
199 exit (RCV_MBX);
|
|
200
|
|
201 user = getusr ();
|
|
202 #ifndef TTYD
|
|
203 if ((uf = fopen (UTMP_FILENAME, "r")) == NULL)
|
|
204 exit (RCV_MBX);
|
|
205 while (fread ((char *) &ut, sizeof ut, 1, uf) == 1)
|
|
206 if (ut.ut_name[0] != 0
|
|
207 #ifdef UTMAXTYPE
|
|
208 && ut.ut_type == USER_PROCESS
|
|
209 #endif
|
|
210 && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) {
|
|
211 (void) strncpy (tty, ut.ut_line, sizeof ut.ut_line);
|
|
212 alert (tty, md);
|
|
213 }
|
|
214 (void) fclose (uf);
|
|
215 #else /* TTYD */
|
|
216 alert (user, md);
|
|
217 #endif /* TTYD */
|
|
218
|
|
219 exit (RCV_MOK);
|
|
220 }
|
|
221
|
|
222 /* */
|
|
223
|
|
224 /* ARGSUSED */
|
|
225
|
|
226 static TYPESIG alrmser (i)
|
|
227 int i;
|
|
228 {
|
|
229 longjmp (myctx, DONE);
|
|
230 }
|
|
231
|
|
232
|
|
233 static int message_fd (vec)
|
|
234 char *vec[];
|
|
235 {
|
|
236 int bytes,
|
|
237 child_id,
|
|
238 fd;
|
|
239 char tmpfil[BUFSIZ];
|
|
240 struct stat st;
|
|
241
|
|
242 (void) unlink (mktemp (strcpy (tmpfil, "/tmp/rcvttyXXXXX")));
|
|
243 if ((fd = creat (tmpfil, 0600)) == NOTOK)
|
|
244 return header_fd ();
|
|
245 (void) close (fd);
|
|
246
|
|
247 if ((fd = open (tmpfil, 2)) == NOTOK)
|
|
248 return header_fd ();
|
|
249 (void) unlink (tmpfil);
|
|
250
|
|
251 /* */
|
|
252
|
|
253 switch (child_id = vfork ()) {
|
|
254 case NOTOK:
|
|
255 (void) close (fd);
|
|
256 return header_fd ();
|
|
257
|
|
258 case OK:
|
|
259 rewind (stdin);
|
|
260 if (dup2 (fd, 1) == NOTOK || dup2 (fd, 2) == NOTOK)
|
|
261 _exit (-1);
|
|
262 closefds (3);
|
|
263 #ifdef BSD42
|
13
|
264 (void) setpgrp (); // (void) setpgrp (0, getpid ());
|
0
|
265 #endif /* BSD42 */
|
|
266 #ifdef SVR4
|
|
267 (void) setsid();
|
|
268 #endif /* SVR4 */
|
|
269 execvp (vec[0], vec);
|
|
270 _exit (-1);
|
|
271
|
|
272 default:
|
|
273 switch (setjmp (myctx)) {
|
|
274 case OK:
|
|
275 (void) signal (SIGALRM, alrmser);
|
|
276 bytes = fstat (fileno (stdin), &st) != NOTOK
|
|
277 ? (int) st.st_size : 100;
|
|
278 if (bytes <= 0)
|
|
279 bytes = 100;
|
|
280 (void) alarm ((unsigned) (bytes * 60 + 300));
|
|
281
|
|
282 (void) pidwait (child_id, OK);
|
|
283
|
|
284 (void) alarm (0);
|
|
285 if (fstat (fd, &st) != NOTOK && st.st_size > (off_t)0)
|
|
286 return fd;
|
|
287 (void) close (fd);
|
|
288 return header_fd ();
|
|
289
|
|
290 default:
|
|
291 #ifndef BSD42
|
|
292 (void) kill (child_id, SIGKILL);
|
|
293 #else /* BSD42 */
|
|
294 (void) killpg (child_id, SIGKILL);
|
|
295 #endif /* BSD42 */
|
|
296 (void) close (fd);
|
|
297 return header_fd ();
|
|
298 }
|
|
299 }
|
|
300 }
|
|
301
|
|
302 /* */
|
|
303
|
|
304 static int header_fd () {
|
|
305 int fd;
|
|
306 char tmpfil[BUFSIZ];
|
|
307
|
|
308 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
309 if ((fd = creat (tmpfil, 0600)) == NOTOK)
|
|
310 return NOTOK;
|
|
311 (void) close (fd);
|
|
312
|
|
313 if ((fd = open (tmpfil, 2)) == NOTOK)
|
|
314 return NOTOK;
|
|
315 (void) unlink (tmpfil);
|
|
316
|
|
317 rewind (stdin);
|
|
318 (void) scan (stdin, 0, 0, new_fs (form, format, SCANFMT), 0, 0, 0,
|
|
319 0, 0, 0L, 0);
|
|
320 if ( newline )
|
|
321 (void) write (fd, "\n\r", 2);
|
|
322 (void) write (fd, scanl, strlen (scanl));
|
|
323 if ( bell )
|
|
324 (void) write (fd, "\007", 1);
|
|
325
|
|
326 return fd;
|
|
327 }
|
|
328
|
|
329 /* */
|
|
330
|
|
331 #ifndef TTYD
|
16
|
332 static void alert (tty, md)
|
0
|
333 char *tty;
|
|
334 int md;
|
|
335 {
|
|
336 int i,
|
|
337 td;
|
|
338 char buffer[BUFSIZ],
|
|
339 ttyspec[BUFSIZ];
|
|
340 struct stat st;
|
|
341
|
|
342 (void) sprintf (ttyspec, "/dev/%s", tty);
|
|
343 if (stat (ttyspec, &st) == NOTOK ||
|
|
344 (st.st_mode & (biff ? S_IEXEC :
|
|
345 #ifdef BSD43
|
|
346 (S_IWRITE >> 3)
|
|
347 #else /* BSD43 */
|
|
348 020
|
|
349 #endif /* BSD43 */
|
|
350 )) == 0)
|
|
351 return;
|
|
352
|
|
353 switch (setjmp (myctx)) {
|
|
354 case OK:
|
|
355 (void) signal (SIGALRM, alrmser);
|
|
356 (void) alarm (2);
|
|
357 #ifdef BSD43
|
|
358 setegid(return_gid); /* Reset gid to open tty */
|
|
359 #endif /* BSD43 */
|
|
360 td = open (ttyspec, 1);
|
|
361 #ifdef BSD43
|
|
362 setegid(getgid()); /* Return us to normal privileges */
|
|
363 #endif /* BSD43 */
|
|
364 (void) alarm (0);
|
|
365 if (td == NOTOK)
|
|
366 return;
|
|
367 break;
|
|
368
|
|
369 default:
|
|
370 (void) alarm (0);
|
|
371 return;
|
|
372 }
|
|
373
|
|
374 (void) lseek (md, (off_t)0, 0);
|
|
375
|
|
376 #ifdef JAPAN
|
|
377 {
|
|
378 FILE *fd = fdopen(td, "w");
|
|
379 while ((i = read (md, buffer, sizeof buffer)) > 0) {
|
|
380 buffer[i] = '\0';
|
|
381 ml_fputs(buffer, fd);
|
|
382 fflush(fd);
|
|
383 }
|
|
384 fclose(fd);
|
|
385 }
|
|
386 #else /* JAPAN */
|
|
387 while ((i = read (md, buffer, sizeof buffer)) > 0)
|
|
388 if (write (td, buffer, i) != i)
|
|
389 break;
|
|
390 #endif /* JAPAN */
|
|
391
|
|
392 (void) close (td);
|
|
393 }
|
|
394 #else /* TTYD */
|
|
395
|
|
396 /* */
|
|
397
|
|
398 static alert (user, md)
|
|
399 register char *user;
|
|
400 int md;
|
|
401 {
|
|
402 int i,
|
|
403 td;
|
|
404 char buffer[BUFSIZ];
|
|
405
|
|
406 #ifdef BSD43
|
|
407 setegid(return_gid); /* Reset gid to open tty */
|
|
408 #endif /* BSD43 */
|
|
409 td = ttyw ("notify", NULLCP, NULLCP, user);
|
|
410 #ifdef BSD43
|
|
411 setegid(getgid()); /* Return us to normal privileges */
|
|
412 #endif /* BSD43 */
|
|
413 if (td == NOTOK)
|
|
414 return;
|
|
415 (void) signal (SIGPIPE, SIG_IGN);
|
|
416
|
|
417 (void) lseek (md, (off_t)0, 0);
|
|
418 #ifdef JAPAN
|
|
419 {
|
|
420 FILE *fd = fdopen(td, "w");
|
|
421 while ((i = read (md, buffer, sizeof buffer)) > 0) {
|
|
422 buffer[i] = '\0';
|
|
423 ml_fputs(buffer, fd);
|
|
424 fflush(fd);
|
|
425 }
|
|
426 fclose(fd);
|
|
427 }
|
|
428 #else /* JAPAN */
|
|
429 while ((i = read (md, buffer, sizeof buffer)) > 0)
|
|
430 if (write (td, buffer, i) != i)
|
|
431 break;
|
|
432 #endif /* JAPAN */
|
|
433
|
|
434 (void) close (td);
|
|
435 }
|
|
436 #endif /* TTYD */
|