1: /* rcvtty.c - a rcvmail program (a lot like rcvalert) handling IPC ttys */
2:
3: #include "../h/mh.h"
4: #include "../h/rcvmail.h"
5: #include "../h/scansbr.h"
6: #include "../zotnet/tws.h"
7: #include <signal.h>
8: #include <sys/stat.h>
9: #ifndef TTYD
10: #include <utmp.h>
11: #endif not TTYD
12:
13: /* */
14:
15: static struct swit switches[] = {
16: #define HELPSW 0
17: "help", 4,
18:
19: NULL, NULL
20: };
21:
22: /* */
23:
24: static jmp_buf myctx;
25:
26: long lseek ();
27: char *getusr ();
28:
29: /* */
30:
31: /* ARGSUSED */
32:
33: main (argc, argv)
34: int argc;
35: char **argv;
36: {
37: int md,
38: vecp = 0;
39: char *cp,
40: *user,
41: buf[100],
42: **ap,
43: **argp,
44: *arguments[MAXARGS],
45: *vec[MAXARGS];
46: #ifndef TTYD
47: char tty[BUFSIZ];
48: struct utmp ut;
49: register FILE *uf;
50: #endif not TTYD
51:
52: invo_name = r1bindex (argv[0], '/');
53: mts_init (invo_name);
54: if ((cp = m_find (invo_name)) != NULL) {
55: ap = brkstring (cp = getcpy (cp), " ", "\n");
56: ap = copyip (ap, arguments);
57: }
58: else
59: ap = arguments;
60: (void) copyip (argv + 1, ap);
61: argp = arguments;
62:
63: /* */
64:
65: while (cp = *argp++) {
66: if (*cp == '-')
67: switch (smatch (++cp, switches)) {
68: case AMBIGSW:
69: ambigsw (cp, switches);
70: done (1);
71: case UNKWNSW:
72: vec[vecp++] = --cp;
73: continue;
74: case HELPSW:
75: (void) sprintf (buf, "%s [command ...]", invo_name);
76: help (buf, switches);
77: done (1);
78: }
79: vec[vecp++] = cp;
80: }
81: vec[vecp] = 0;
82:
83: /* */
84:
85: if ((md = vecp ? message_fd (vec) : header_fd ()) == NOTOK)
86: exit (RCV_MBX);
87:
88: user = getusr ();
89: #ifndef TTYD
90: if ((uf = fopen ("/etc/utmp", "r")) == NULL)
91: exit (RCV_MBX);
92: while (fread ((char *) &ut, sizeof ut, 1, uf) == 1)
93: if (ut.ut_name[0] != NULL
94: && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) {
95: (void) strncpy (tty, ut.ut_line, sizeof ut.ut_line);
96: alert (tty, md);
97: }
98: (void) fclose (uf);
99: #else TTYD
100: alert (user, md);
101: #endif TTYD
102:
103: exit (RCV_MOK);
104: }
105:
106: /* */
107:
108: /* ARGSUSED */
109:
110: static int alrmser (i)
111: int i;
112: {
113: longjmp (myctx, DONE);
114: }
115:
116:
117: static int message_fd (vec)
118: char *vec[];
119: {
120: int bytes,
121: child_id,
122: fd;
123: char tmpfil[BUFSIZ];
124: struct stat st;
125:
126: (void) unlink (mktemp (strcpy (tmpfil, "/tmp/rcvttyXXXXX")));
127: if ((fd = creat (tmpfil, 0600)) == NOTOK)
128: return header_fd ();
129: (void) close (fd);
130:
131: if ((fd = open (tmpfil, 2)) == NOTOK)
132: return header_fd ();
133: (void) unlink (tmpfil);
134:
135: /* */
136:
137: switch (child_id = vfork ()) {
138: case NOTOK:
139: (void) close (fd);
140: return header_fd ();
141:
142: case OK:
143: rewind (stdin);
144: if (dup2 (fd, 1) == NOTOK || dup2 (fd, 2) == NOTOK)
145: _exit (-1);
146: closefds (3);
147: #ifdef BSD42
148: (void) setpgrp (0, getpid ());
149: #endif BSD42
150: execvp (vec[0], vec);
151: _exit (-1);
152:
153: default:
154: switch (setjmp (myctx)) {
155: case OK:
156: (void) signal (SIGALRM, alrmser);
157: bytes = fstat (fileno (stdin), &st) != NOTOK
158: ? (int) st.st_size : 100;
159: if (bytes <= 0)
160: bytes = 100;
161: (void) alarm ((unsigned) (bytes * 60 + 300));
162:
163: (void) pidwait (child_id, OK);
164:
165: (void) alarm (0);
166: if (fstat (fd, &st) != NOTOK && st.st_size > 0L)
167: return fd;
168: (void) close (fd);
169: return header_fd ();
170:
171: default:
172: #ifndef BSD42
173: (void) kill (child_id, SIGKILL);
174: #else BSD42
175: (void) killpg (child_id, SIGKILL);
176: #endif BSD42
177: (void) close (fd);
178: return header_fd ();
179: }
180: }
181: }
182:
183: /* */
184:
185: int header_fd () {
186: int fd;
187: char tmpfil[BUFSIZ];
188:
189: (void) strcpy (tmpfil, m_tmpfil (invo_name));
190: if ((fd = creat (tmpfil, 0600)) == NOTOK)
191: return NOTOK;
192: (void) close (fd);
193:
194: if ((fd = open (tmpfil, 2)) == NOTOK)
195: return NOTOK;
196: (void) unlink (tmpfil);
197:
198: rewind (stdin);
199: (void) scan (stdin, 0, 0, NULLVP, 0, 0, 0, 0L, 0);
200: (void) write (fd, scanl, strlen (scanl));
201:
202: return fd;
203: }
204:
205: /* */
206:
207: #ifndef TTYD
208: static alert (tty, md)
209: register char *tty;
210: int md;
211: {
212: int i,
213: td;
214: char buffer[BUFSIZ],
215: ttyspec[BUFSIZ];
216: struct stat st;
217:
218: (void) sprintf (ttyspec, "/dev/%s", tty);
219: if (stat (ttyspec, &st) == NOTOK || (st.st_mode & 02) == 0)
220: return;
221:
222: switch (setjmp (myctx)) {
223: case OK:
224: (void) signal (SIGALRM, alrmser);
225: (void) alarm (2);
226: td = open (ttyspec, 1);
227: (void) alarm (0);
228: if (td == NOTOK)
229: return;
230: break;
231:
232: default:
233: (void) alarm (0);
234: return;
235: }
236:
237: (void) lseek (md, 0L, 0);
238:
239: while ((i = read (md, buffer, sizeof buffer)) > 0)
240: if (write (td, buffer, i) != i)
241: break;
242:
243: (void) close (td);
244: }
245: #else TTYD
246:
247: /* */
248:
249: static alert (user, md)
250: register char *user;
251: int md;
252: {
253: int i,
254: td;
255: char buffer[BUFSIZ];
256:
257: if ((td = ttyw ("notify", NULLCP, NULLCP, user)) == NOTOK)
258: return;
259: (void) signal (SIGPIPE, SIG_IGN);
260:
261: (void) lseek (md, 0L, 0);
262: while ((i = read (md, buffer, sizeof buffer)) > 0)
263: if (write (td, buffer, i) != i)
264: break;
265:
266: (void) close (td);
267: }
268: #endif TTYD