|
|
1.1 root 1: /* pipe.c - fred talks to dish */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/others/quipu/uips/fred/RCS/pipe.c,v 7.6 90/07/27 08:45:26 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/others/quipu/uips/fred/RCS/pipe.c,v 7.6 90/07/27 08:45:26 mrose Exp $
9: *
10: *
11: * $Log: pipe.c,v $
12: * Revision 7.6 90/07/27 08:45:26 mrose
13: * update
14: *
15: * Revision 7.5 90/06/11 21:17:10 mrose
16: * touch-up
17: *
18: * Revision 7.4 90/06/11 10:55:32 mrose
19: * UFN
20: *
21: * Revision 7.3 90/01/16 20:43:41 mrose
22: * last check-out
23: *
24: * Revision 7.2 90/01/11 18:36:39 mrose
25: * real-sync
26: *
27: * Revision 7.1 89/12/13 20:01:51 mrose
28: * errfp
29: *
30: * Revision 7.0 89/11/23 22:09:03 mrose
31: * Release 6.0
32: *
33: */
34:
35: /*
36: * NOTICE
37: *
38: * Acquisition, use, and distribution of this module and related
39: * materials are subject to the restrictions of a license agreement.
40: * Consult the Preface in the User's Manual for the full terms of
41: * this agreement.
42: *
43: */
44:
45:
46: #include <signal.h>
47: #include "fred.h"
48: #include "internet.h"
49:
50: #include <sys/ioctl.h>
51: #ifndef SYS5
52: #include <sys/file.h>
53: #else
54: #if !defined(AIX) && !defined(HPUX)
55: #include <sys/fcntl.h>
56: #else
57: #include <fcntl.h>
58: #endif
59: #endif
60: #include <sys/stat.h>
61: #include "usr.dirent.h"
62: #ifdef BSD42
63: #include <sys/wait.h>
64: #endif
65:
66: /* */
67:
68: int didbind = 0;
69: int dontpage = 0;
70:
71: static int dish_running = NOTOK;
72:
73: static struct sockaddr_in sin;
74:
75: /* DISH */
76:
77: int dish (command, silent)
78: char *command;
79: int silent;
80: {
81: int cc,
82: isarea,
83: isuser,
84: n,
85: sd,
86: status;
87: char buffer[BUFSIZ],
88: where[BUFSIZ];
89: register struct sockaddr_in *sock = &sin;
90: FILE *fp;
91:
92: if (watch) {
93: fprintf (stderr, "%s\n", command);
94: (void) fflush (stderr);
95: }
96:
97: isarea = strncmp (command, "moveto -pwd", sizeof "moveto -pwd" - 1)
98: ? 0 : 1;
99: isuser = !isarea && strcmp (command, "squid -fred -user") == 0;
100:
101: if (dish_running != NOTOK && kill (dish_running, 0) == NOTOK)
102: dish_running = NOTOK;
103:
104: if (dish_running == NOTOK) {
105: int vecp;
106: char dishname[BUFSIZ],
107: *vec[10];
108: static int very_first_time = 1;
109:
110: if (very_first_time) {
111: (void) unsetenv ("DISHPROC");
112: (void) unsetenv ("DISHPARENT");
113:
114: (void) strcpy (ufn_file, "/tmp/ufnrc.XXXXXX");
115: (void) unlink (mktemp (ufn_file));
116: (void) setenv ("UFNRC", ufn_file);
117:
118: very_first_time = 0;
119: }
120:
121: if (get_dish_sock (&sin, getpid ()) == NOTOK)
122: exit (1);
123:
124: (void) strcpy (dishname, _isodefile (isodebinpath, "dish"));
125:
126: fork_again: ;
127: switch (dish_running = vfork ()) {
128: case NOTOK:
129: adios ("fork", "unable to");
130: /* NOT REACHED */
131:
132: case OK:
133: if (ifd != NOTOK)
134: (void) close (ifd);
135: if (ofd != NOTOK)
136: (void) close (ofd);
137: vecp = 0;
138: vec[vecp++] = "dish";
139: vec[vecp++] = "-pipe";
140: vec[vecp++] = "-fast";
141: vec[vecp] = NULL;
142: (void) execv (dishname, vec);
143: fprintf (stderr, "unable to exec ");
144: perror (dishname);
145: _exit (1);
146:
147: default:
148: for (;;) {
149: if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0))
150: == NOTOK)
151: adios ("client", "unable to start");
152: if (join_tcp_server (sd, sock) != NOTOK)
153: break;
154:
155: (void) close_tcp_socket (sd);
156:
157: sleep (5);
158:
159: if (kill (dish_running, 0) == NOTOK)
160: goto fork_again;
161: }
162: didbind = 0;
163: (void) signal (SIGPIPE, SIG_IGN);
164: break;
165: }
166: }
167: else {
168: if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK)
169: adios ("client", "unable to start");
170: if (join_tcp_server (sd, sock) == NOTOK)
171: adios ("server", "unable to join");
172: }
173:
174: n = send (sd, command, cc = strlen (command), 0);
175: if (debug)
176: fprintf (stderr, "wrote %d of %d octets to DUA\n", n, cc);
177:
178: if (n != cc)
179: if (n == NOTOK) {
180: advise ("please retry", "write to DUA failed,");
181: (void) f_quit (NULLVP);
182: (void) close_tcp_socket (sd);
183: return NOTOK;
184: }
185: else
186: adios (NULLCP, "write to DUA truncated, sent %d of %d octets",
187: n, cc);
188:
189: status = OK;
190: for (;;) {
191: if ((cc = recv (sd, buffer, sizeof buffer - 1, 0)) == NOTOK) {
192: if (!interrupted)
193: adios ("failed", "read from DUA");
194:
195: (void) kill (dish_running, SIGINT);
196: interrupted = 0;
197: continue;
198: }
199:
200: buffer[cc] = NULL;
201: if (debug)
202: fprintf (stderr, "read %d octets from DUA: 0x%x\n", cc, buffer[0]);
203: if (cc == OK) {
204: if (kill (dish_running, 0) == NOTOK)
205: advise (NULLCP, "lost DUA");
206:
207: break;
208: }
209:
210: switch (buffer[0]) {
211: case '2':
212: if ((fp = errfp) == NULL)
213: fp = stdfp != stdout ? stdfp : stderr;
214: status = NOTOK;
215:
216: copy_out: ;
217: if (cc > 1 && !silent)
218: paginate (fp, buffer + 1, cc - 1);
219:
220: while ((cc = recv (sd, buffer, sizeof buffer - 1, 0)) > OK)
221: if (!silent)
222: paginate (fp, buffer, cc);
223:
224: if (!silent)
225: paginate (fp, NULLCP, 0);
226: break;
227:
228: case '1':
229: case '3':
230: if (isarea || isuser) {
231: char *cp,
232: **vp;
233:
234: if (cp = index (buffer + 1, '\n'))
235: *cp = NULL;
236: #ifdef notdef
237: if (buffer[1] == NULL)
238: break;
239: #endif
240: buffer[0] = '@';
241: vp = isarea ? &myarea : &mydn;
242:
243: if (*vp)
244: free (*vp);
245: *vp = strdup (buffer);
246: }
247: fp = stdfp;
248: goto copy_out;
249:
250: case 'e':
251: if (watch) {
252: fprintf (stderr, "%s\n", buffer + 1);
253: (void) fflush (stderr);
254: }
255: if (system (buffer + 1))
256: (void) strcpy (where, "e");
257: else
258: (void) getcwd (where, sizeof where);
259: goto stuff_it;
260:
261: case 'y':
262: if (network)
263: (void) strcpy (where, "n");
264: else {
265: fprintf (stderr, "%s", buffer + 1);
266: (void) fflush (stderr);
267: (void) fgets (where, sizeof where, stdin);
268: }
269: goto stuff_it;
270:
271: case 'p':
272: (void) sprintf (where, "Enter password for \"%s\": ",
273: buffer + 1);
274: (void) strcpy (where, getpassword (where));
275:
276: stuff_it: ;
277: n = send (sd, where, cc = strlen (where), 0);
278: if (debug)
279: fprintf (stderr, "wrote %d of %d octets to DUA\n", n, cc);
280:
281: if (n != cc)
282: if (n == NOTOK) {
283: advise ("please retry", "write to DUA failed,");
284: (void) f_quit (NULLVP);
285: (void) close_tcp_socket (sd);
286: return NOTOK;
287: }
288: else
289: adios (NULLCP,
290: "write to DUA truncated, sent %d of %d octets",
291: n, cc);
292: continue;
293:
294: default:
295: advise (NULLCP, "unexpected opcode 0x%x -- contact a camayoc",
296: buffer[0]);
297: break;
298: }
299: break;
300: }
301:
302: (void) close_tcp_socket (sd);
303:
304: return status;
305: }
306:
307: /* */
308:
309: paginate (fp, buffer, cc)
310: FILE *fp;
311: char *buffer;
312: int cc;
313: {
314: static int first_time = 1;
315: static int doing_pager = 0;
316: static int pid = NOTOK;
317: static int sd = NOTOK;
318: static SFP istat, qstat;
319:
320: if (cc == 0) {
321: #ifndef BSD42
322: int status;
323: #else
324: union wait status;
325: #endif
326: int child;
327:
328: first_time = 1;
329: (void) fflush (fp);
330: if (!doing_pager)
331: return;
332:
333: doing_pager = 0;
334:
335: if (dup2 (sd, fileno (fp)) == NOTOK)
336: adios ("standard output", "unable to dup2");
337:
338: clearerr (fp);
339: (void) close (sd);
340:
341: while ((child = wait (&status)) != NOTOK && pid != child)
342: continue;
343:
344: (void) signal (SIGINT, istat);
345: (void) signal (SIGQUIT, qstat);
346:
347: return;
348: }
349:
350: if (first_time) {
351: int pd[2];
352:
353: first_time = 0;
354:
355: if (dontpage || network || *pager == NULL || !isatty (fileno (fp)))
356: goto no_pager;
357:
358: (void) fflush (fp);
359:
360: foreground ();
361:
362: if ((sd = dup (fileno (fp))) == NOTOK) {
363: advise ("dup", "unable to");
364: goto no_pager;
365: }
366:
367: if (pipe (pd) == NOTOK) {
368: advise ("pipe", "unable to");
369: goto no_pager;
370: }
371: switch (pid = fork ()) {
372: case NOTOK:
373: advise ("fork", "unable to");
374: (void) close (pd[0]);
375: (void) close (pd[1]);
376: goto no_pager;
377:
378: case OK:
379: (void) signal (SIGINT, SIG_DFL);
380: (void) signal (SIGQUIT, SIG_DFL);
381:
382: (void) close (pd[1]);
383: if (pd[0] != fileno (stdin)) {
384: (void) dup2 (pd[0], fileno (stdin));
385: (void) close (pd[0]);
386: }
387: if (readonly)
388: mypager (stdin);
389: else {
390: execlp (pager, pager, NULLCP);
391: fprintf (stderr, "unable to exec ");
392: perror (pager);
393: }
394: _exit (-1);
395:
396: default:
397: (void) close (pd[0]);
398: if (pd[1] != fileno (fp)) {
399: (void) dup2 (pd[1], fileno (fp));
400: (void) close (pd[1]);
401: }
402: break;
403: }
404:
405: istat = signal (SIGINT, SIG_IGN);
406: qstat = signal (SIGQUIT, SIG_IGN);
407:
408: doing_pager = 1;
409: }
410:
411: no_pager: ;
412: if (network && !mail) {
413: register char *cp,
414: *dp;
415:
416: for (dp = (cp = buffer) + cc; cp < dp; cp++) {
417: if (*cp == '\n')
418: (void) fputc ('\r', fp);
419: (void) fputc (*cp, fp);
420: }
421: }
422: else
423: (void) fwrite (buffer, sizeof buffer[0], cc, fp);
424: }
425:
426: /* */
427:
428: /* if you start a fred command and then background fred, if your pager is less,
429: then for some reason, less gets the terminal modes/process groups messed up.
430:
431: this code pretty much ensures that fred is running in the foreground when
432: it forks less. there is still a critical window, but it is very small...
433: */
434:
435: static foreground () {
436: #ifdef TIOCGPGRP
437: int pgrp,
438: tpgrp;
439: SFP tstat;
440:
441: if ((pgrp = getpgrp (0)) == NOTOK)
442: return;
443:
444: tstat = signal (SIGTTIN, SIG_DFL);
445: for (;;) {
446: if (ioctl (fileno (stdin), TIOCGPGRP, (char *) &tpgrp) == NOTOK)
447: break;
448: if (pgrp == tpgrp)
449: break;
450:
451: (void) kill (0, SIGTTIN);
452: }
453: (void) signal (SIGTTIN, tstat);
454: #endif
455: }
456:
457: /* */
458:
459: static int cols;
460: static int rows;
461: static int length = 0;
462: static int width = 0;
463:
464:
465: static mypager (fp)
466: FILE *fp;
467: {
468: register char *bp;
469: char buffer[BUFSIZ];
470: #ifdef TIOCGWINSZ
471: struct winsize ws;
472: #endif
473:
474: #ifdef TIOCGWINSZ
475: if (ioctl (fileno (stdout), TIOCGWINSZ, (char *) &ws) != NOTOK)
476: length = ws.ws_row, width = ws.ws_col;
477: #endif
478: if (--length <= 0)
479: length = 23;
480: if (--width <= 0)
481: width = 79;
482:
483: rows = cols = 0;
484:
485: while (fgets (buffer, sizeof buffer, fp))
486: for (bp = buffer; *bp; bp++)
487: pagchar (*bp);
488:
489: (void) fflush (stdout);
490: }
491:
492:
493: static pagchar (ch)
494: char ch;
495: {
496: char buffer[BUFSIZ];
497:
498: switch (ch) {
499: case '\n':
500: cols = 0;
501: if (++rows < length)
502: break;
503: (void) putc (0x07, stdout);
504: (void) fflush (stdout);
505: buffer[0] = NULL;
506: (void) read (fileno (stdout), buffer, sizeof buffer);
507: if (buffer[0] == '\n')
508: rows = 0;
509: else {
510: (void) putc ('\n', stdout);
511: rows = length / 3;
512: }
513: return;
514:
515: case '\t':
516: cols |= 07;
517: cols++;
518: break;
519:
520: case '\b':
521: cols--;
522: break;
523:
524: case '\r':
525: cols = 0;
526: break;
527:
528: default:
529: if (ch >= ' ')
530: cols++;
531: break;
532: }
533:
534: if (cols >= width) {
535: pagchar ('\n');
536: pagchar (ch);
537: }
538: else
539: (void) putc (ch, stdout);
540: }
541:
542: /* BIND */
543:
544: /* ARGSUSED */
545:
546: int f_bind (vec)
547: char **vec;
548: {
549: if (didbind) {
550: didbind = 0;
551: return OK;
552: }
553:
554: #ifdef notdef
555: if (dish_running == NOTOK || kill (dish_running, 0) == NOTOK)
556: return dish ("bind", 0);
557:
558: return OK;
559: #else
560: return dish ("bind", 0);
561: #endif
562: }
563:
564: /* ARGSUSED */
565:
566: /* QUIT */
567:
568: int f_quit (vec)
569: char **vec;
570: {
571: if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) {
572: fprintf (stdfp, "quit\n");
573: fprintf (stdfp, " terminate fred\n");
574:
575: return OK;
576: }
577:
578: if (dish_running != NOTOK) {
579: (void) kill (dish_running, SIGHUP);
580:
581: dish_running = NOTOK;
582: }
583:
584: if (ufn_file[0])
585: (void) unlink (ufn_file);
586:
587: return DONE;
588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.