|
|
1.1 root 1: /* msh.c - The MH shell (sigh) */
2:
3: /* TODO:
4: Keep more status information in maildrop map
5: */
6:
7: #include "../h/mh.h"
8: #include "../h/dropsbr.h"
9: #include "../h/formatsbr.h"
10: #include "../h/scansbr.h"
11: #include "../zotnet/tws.h"
12: #include <stdio.h>
13: #include "../zotnet/mts.h"
14: #include <ctype.h>
15: #include <sys/types.h>
16: #include <sys/stat.h>
17: #ifndef SYS5
18: #include <sgtty.h>
19: #else SYS5
20: #include <termio.h>
21: #include <sys/ioctl.h>
22: #endif SYS5
23: #include <pwd.h>
24: #include <setjmp.h>
25: #include <signal.h>
26: #include "../h/mshsbr.h"
27: #include "../h/vmhsbr.h"
28:
29:
30: #define QUOTE '\\' /* sigh */
31:
32:
33: /* */
34:
35: static struct swit switches[] = {
36: #define IDSW 0
37: "idstart number", -7, /* interface from bbc */
38: #define FDSW 1
39: "idstop number", -6, /* .. */
40: #define QDSW 2
41: "idquit number", -6, /* .. */
42: #define NMSW 3
43: "idname BBoard", -6, /* .. */
44:
45: #define PRMPTSW 4
46: "prompt string", 0,
47:
48: #define SCANSW 5
49: "scan", 0,
50: #define NSCANSW 6
51: "noscan", 0,
52:
53: #define READSW 7
54: "vmhread fd", -7,
55: #define WRITESW 8
56: "vmhwrite fd", -8,
57:
58: #define PREADSW 9
59: "popread fd", -7,
60: #define PWRITSW 10
61: "popwrite fd", -8,
62:
63: #define TCURSW 11
64: "topcur", 0,
65: #define NTCURSW 12
66: "notopcur", 0,
67:
68: #define HELPSW 13
69: "help", 4,
70:
71: NULL, NULL
72: };
73:
74: /* */
75: /* FOLDER */
76: char *fmsh = NULL; /* folder instead of file */
77: int modified; /* command modified folder */
78: struct msgs *mp; /* used a lot */
79: static int nMsgs = 0;
80: struct Msg *Msgs = NULL; /* Msgs[0] not used */
81: static FILE *fp; /* input file */
82: static FILE *yp = NULL; /* temporary file */
83: static int mode; /* mode of file */
84: static int numfds = 0; /* number of files cached */
85: static int maxfds = 0; /* number of files cached to be cached */
86: static time_t mtime = (time_t) 0;/* mtime of file */
87:
88:
89: /* VMH */
90: #define ALARM ((unsigned int) 10)
91: #define ttyN(c) ttyNaux ((c), NULLCP)
92:
93: static int vmh = 0;
94:
95: static int vmhpid = OK;
96: static int vmhfd0;
97: static int vmhfd1;
98: static int vmhfd2;
99:
100: static int vmhtty = NOTOK;
101:
102: #define SCAN 1
103: #define STATUS 2
104: #define DISPLAY 3
105: #define NWIN DISPLAY
106:
107: static int topcur = 0;
108:
109: static int numwins = 0;
110: static int windows[NWIN + 1];
111:
112: static jmp_buf peerenv;
113:
114: void padios (), padvise ();
115: int alrmser ();
116:
117:
118: #ifdef BPOP
119: /* POP */
120:
121: static int pmsh = 0; /* BPOP enabled */
122:
123: extern char response[];
124: #endif BPOP
125:
126:
127: /* PARENT */
128: static int pfd = NOTOK; /* fd parent is reading from */
129: static int ppid = 0; /* pid of parent */
130:
131:
132: /* COMMAND */
133: int interactive; /* running from a /dev/tty */
134: int redirected; /* re-directing output */
135: FILE *sp = NULL; /* original stdout */
136:
137: char *cmd_name; /* command being run */
138:
139: char myfilter[BUFSIZ]; /* path to mhl.forward */
140:
141: static char *myprompt = "(%s) ";/* prompting string */
142:
143:
144: /* BBOARDS */
145: static int gap; /* gap in BBoard-ID:s */
146:
147: static char *myname = NULL; /* BBoard name */
148:
149: char *BBoard_ID = "BBoard-ID";/* BBoard-ID constant */
150:
151: /* SIGNALS */
152: int (*istat) (); /* original SIGINT */
153: static int (*pstat) (); /* current SIGPIPE */
154: int (*qstat) (); /* original SIGQUIT */
155: #ifdef SIGTSTP
156: static int (*tstat) (); /* original SIGTSTP */
157: #endif SIGTSTP
158: int interrupted; /* SIGINT detected */
159: int broken_pipe; /* SIGPIPE detected */
160: int told_to_quit; /* SIGQUIT detected */
161:
162: #ifdef BSD42
163: int should_intr; /* signal handler should interrupt call */
164: jmp_buf sigenv; /* the environment pointer */
165: #endif BSD42
166:
167: int intrser (), pipeser (), quitser ();
168:
169:
170: #ifdef SYS5
171: struct passwd *getpwnam ();
172: #endif SYS5
173:
174: /* */
175:
176: /* ARGSUSED */
177:
178: main (argc, argv)
179: int argc;
180: char **argv;
181: {
182: int id = 0,
183: scansw = 0,
184: vmh1 = 0,
185: vmh2 = 0;
186: #ifdef BPOP
187: int pmsh1 = 0,
188: pmsh2 = 0;
189: #endif BPOP
190: char *cp,
191: *file = NULL,
192: *folder = NULL,
193: **ap,
194: **argp,
195: buf[80],
196: *arguments[MAXARGS];
197:
198: invo_name = r1bindex (argv[0], '/');
199: mts_init (invo_name);
200: if ((cp = m_find (invo_name)) != NULL) {
201: ap = brkstring (cp = getcpy (cp), " ", "\n");
202: ap = copyip (ap, arguments);
203: }
204: else
205: ap = arguments;
206: (void) copyip (argv + 1, ap);
207: argp = arguments;
208:
209: /* */
210:
211: while (cp = *argp++) {
212: if (*cp == '-')
213: switch (smatch (++cp, switches)) {
214: case AMBIGSW:
215: ambigsw (cp, switches);
216: done (1);
217: case UNKWNSW:
218: adios (NULLCP, "-%s unknown", cp);
219: case HELPSW:
220: (void) sprintf (buf, "%s [switches] file", invo_name);
221: help (buf, switches);
222: done (1);
223:
224: case IDSW:
225: if (!(cp = *argp++) || *cp == '-')
226: adios (NULLCP, "missing argument to %s", argp[-2]);
227: if ((id = atoi (cp)) < 1)
228: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
229: continue;
230: case FDSW:
231: if (!(cp = *argp++) || *cp == '-')
232: adios (NULLCP, "missing argument to %s", argp[-2]);
233: if ((pfd = atoi (cp)) <= 1)
234: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
235: continue;
236: case QDSW:
237: if (!(cp = *argp++) || *cp == '-')
238: adios (NULLCP, "missing argument to %s", argp[-2]);
239: if ((ppid = atoi (cp)) <= 1)
240: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
241: continue;
242: case NMSW:
243: if (!(myname = *argp++) || *myname == '-')
244: adios (NULLCP, "missing argument to %s", argp[-2]);
245: continue;
246:
247: case SCANSW:
248: scansw++;
249: continue;
250: case NSCANSW:
251: scansw = 0;
252: continue;
253:
254: case PRMPTSW:
255: if (!(myprompt = *argp++) || *myprompt == '-')
256: adios (NULLCP, "missing argument to %s", argp[-2]);
257: continue;
258:
259: case READSW:
260: if (!(cp = *argp++) || *cp == '-')
261: adios (NULLCP, "missing argument to %s", argp[-2]);
262: if ((vmh1 = atoi (cp)) < 1)
263: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
264: continue;
265: case WRITESW:
266: if (!(cp = *argp++) || *cp == '-')
267: adios (NULLCP, "missing argument to %s", argp[-2]);
268: if ((vmh2 = atoi (cp)) < 1)
269: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
270: continue;
271:
272: case PREADSW:
273: if (!(cp = *argp++) || *cp == '-')
274: adios (NULLCP, "missing argument to %s", argp[-2]);
275: #ifdef BPOP
276: if ((pmsh1 = atoi (cp)) < 1)
277: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
278: #endif BPOP
279: continue;
280: case PWRITSW:
281: if (!(cp = *argp++) || *cp == '-')
282: adios (NULLCP, "missing argument to %s", argp[-2]);
283: #ifdef BPOP
284: if ((pmsh2 = atoi (cp)) < 1)
285: adios (NULLCP, "bad argument %s %s", argp[-2], cp);
286: #endif BPOP
287: continue;
288:
289: case TCURSW:
290: topcur++;
291: continue;
292: case NTCURSW:
293: topcur = 0;
294: continue;
295: }
296: if (*cp == '+' || *cp == '@') {
297: if (folder)
298: adios (NULLCP, "only one folder at a time!");
299: else
300: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
301: }
302: else
303: if (file)
304: adios (NULLCP, "only one file at a time!");
305: else
306: file = cp;
307: }
308:
309: /* */
310:
311: if (!file && !folder)
312: file = "./msgbox";
313: if (file && folder)
314: adios (NULLCP, "use a file or a folder, not both");
315: (void) strcpy (myfilter, libpath (mhlforward));
316: #ifdef FIOCLEX
317: if (pfd > 1)
318: (void) ioctl (pfd, FIOCLEX, NULLCP);
319: #endif FIOCLEX
320:
321: #ifdef BSD42
322: should_intr = 0;
323: #endif BSD42
324: setsigx (istat, SIGINT, intrser);
325: setsigx (qstat, SIGQUIT, quitser);
326:
327: (void) sc_width (); /* MAGIC... */
328:
329: if (vmh = vmh1 && vmh2) {
330: (void) rcinit (vmh1, vmh2);
331: (void) pINI ();
332: (void) signal (SIGINT, SIG_IGN);
333: (void) signal (SIGQUIT, SIG_IGN);
334: #ifdef SIGTSTP
335: tstat = signal (SIGTSTP, SIG_IGN);
336: #endif SIGTSTP
337: }
338:
339: #ifdef BPOP
340: if (pmsh = pmsh1 && pmsh2) {
341: cp = getenv ("MHPOPDEBUG");
342: if (pop_set (pmsh1, pmsh2, cp && *cp) == NOTOK)
343: padios (NULLCP, "%s", response);
344: if (folder)
345: file = folder, folder = NULL;
346: }
347: #endif BPOP
348:
349: if (folder)
350: fsetup (folder);
351: else
352: setup (file);
353: readids (id);
354: display_info (id > 0 ? scansw : 0);
355:
356: msh (id > 0 ? scansw : 0);
357:
358: m_reset ();
359:
360: done (0);
361: }
362:
363: /* */
364:
365: static struct swit mshcmds[] = {
366: #define ALICMD 0
367: "ali", 0,
368: #define EXPLCMD 1
369: "burst", 0,
370: #define COMPCMD 2
371: "comp", 0,
372: #define DISTCMD 3
373: "dist", 0,
374: #define EXITCMD 4
375: "exit", 0,
376: #define FOLDCMD 5
377: "folder", 0,
378: #define FORWCMD 6
379: "forw", 0,
380: #define HELPCMD 7
381: "help", 0,
382: #define INCMD 8
383: "inc", 0,
384: #define MARKCMD 9
385: "mark", 0,
386: #define MAILCMD 10
387: "mhmail", 0,
388: #define MSGKCMD 11
389: "msgchk", 0,
390: #define NEXTCMD 12
391: "next", 0,
392: #define PACKCMD 13
393: "packf", 0,
394: #define PICKCMD 14
395: "pick", 0,
396: #define PREVCMD 15
397: "prev", 0,
398: #define QUITCMD 16
399: "quit", 0,
400: #define FILECMD 17
401: "refile", 0,
402: #define REPLCMD 18
403: "repl", 0,
404: #define RMMCMD 19
405: "rmm", 0,
406: #define SCANCMD 20
407: "scan", 0,
408: #define SENDCMD 21
409: "send", 0,
410: #define SHOWCMD 22
411: "show", 0,
412: #define SORTCMD 23
413: "sortm", 0,
414: #define WHATCMD 24
415: "whatnow", 0,
416: #define WHOMCMD 25
417: "whom", 0,
418:
419: NULL, NULL
420: };
421:
422: /* */
423:
424: static msh (scansw)
425: int scansw;
426: {
427: int i;
428: register char *cp,
429: **ap;
430: char prompt[BUFSIZ],
431: *vec[MAXARGS];
432: struct Cmd typein;
433: register struct Cmd *cmdp;
434:
435: (void) sprintf (prompt, myprompt, invo_name);
436: cmdp = &typein;
437:
438: for (;;) {
439: if (yp) {
440: (void) fclose (yp);
441: yp = NULL;
442: }
443: if (vmh) {
444: if ((i = getcmds (mshcmds, cmdp, scansw)) == EOF) {
445: (void) rcdone ();
446: return;
447: }
448: }
449: else {
450: (void) check_folder (scansw);
451: if ((i = getargs (prompt, mshcmds, cmdp)) == EOF) {
452: (void) putchar ('\n');
453: return;
454: }
455: }
456: cmd_name = mshcmds[i].sw;
457:
458: switch (i) {
459: case QUITCMD:
460: quit ();
461: return;
462:
463: case EXITCMD:
464: case EXPLCMD:
465: case FOLDCMD:
466: case FORWCMD: /* sigh */
467: case MARKCMD:
468: case NEXTCMD:
469: case PACKCMD:
470: case PICKCMD:
471: case PREVCMD:
472: case RMMCMD:
473: case SHOWCMD:
474: case SCANCMD:
475: case SORTCMD:
476: if ((cp = m_find (cmd_name)) != NULL) {
477: ap = brkstring (cp = getcpy (cp), " ", "\n");
478: ap = copyip (ap, vec);
479: }
480: else
481: ap = vec;
482: break;
483:
484: default:
485: cp = NULL;
486: ap = vec;
487: break;
488: }
489: (void) copyip (cmdp -> args + 1, ap);
490:
491: m_init ();
492:
493: if (!vmh && init_io (cmdp, vmh) == NOTOK) {
494: if (cp != NULL)
495: free (cp);
496: continue;
497: }
498: modified = 0;
499: redirected = vmh || cmdp -> direction != STDIO;
500:
501: switch (i) {
502: case ALICMD:
503: case COMPCMD:
504: case INCMD:
505: case MAILCMD:
506: case MSGKCMD:
507: case SENDCMD:
508: case WHATCMD:
509: case WHOMCMD:
510: if (!vmh || ttyN (cmdp) != NOTOK)
511: forkcmd (vec, cmd_name);
512: break;
513:
514: case DISTCMD:
515: if (!vmh || ttyN (cmdp) != NOTOK)
516: distcmd (vec);
517: break;
518:
519: case EXPLCMD:
520: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
521: explcmd (vec);
522: break;
523:
524: case FILECMD:
525: if (!vmh
526: || (filehak (vec) == OK ? ttyN (cmdp)
527: : winN (cmdp, DISPLAY, 1)) != NOTOK)
528: filecmd (vec);
529: break;
530:
531: case FOLDCMD:
532: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
533: foldcmd (vec);
534: break;
535:
536: case FORWCMD:
537: if (!vmh || ttyN (cmdp) != NOTOK)
538: forwcmd (vec);
539: break;
540:
541: case HELPCMD:
542: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
543: helpcmd (vec);
544: break;
545:
546: case EXITCMD:
547: case MARKCMD:
548: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
549: markcmd (vec);
550: break;
551:
552: case NEXTCMD:
553: case PREVCMD:
554: case SHOWCMD:
555: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
556: showcmd (vec);
557: break;
558:
559: case PACKCMD:
560: if (!vmh
561: || (packhak (vec) == OK ? ttyN (cmdp)
562: : winN (cmdp, DISPLAY, 1)) != NOTOK)
563: packcmd (vec);
564: break;
565:
566: case PICKCMD:
567: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
568: pickcmd (vec);
569: break;
570:
571: case REPLCMD:
572: if (!vmh || ttyN (cmdp) != NOTOK)
573: replcmd (vec);
574: break;
575:
576: case RMMCMD:
577: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
578: rmmcmd (vec);
579: break;
580:
581: case SCANCMD:
582: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
583: scancmd (vec);
584: break;
585:
586: case SORTCMD:
587: if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
588: sortcmd (vec);
589: break;
590:
591: default:
592: padios (NULLCP, "no dispatch for %s", cmd_name);
593: }
594:
595: if (vmh) {
596: if (vmhtty != NOTOK)
597: (void) ttyR (cmdp);
598: if (vmhpid > OK)
599: (void) winR (cmdp);
600: }
601: else
602: fin_io (cmdp, vmh);
603: if (cp != NULL)
604: free (cp);
605: if (i == EXITCMD) {
606: quit ();
607: return;
608: }
609: }
610: }
611:
612: /* */
613:
614: fsetup (folder)
615: char *folder;
616: {
617: register int msgnum;
618: char *maildir;
619: struct stat st;
620:
621: maildir = m_maildir (folder);
622: if (chdir (maildir) == NOTOK)
623: padios (maildir, "unable to change directory to");
624: if (!(mp = m_gmsg (folder)))
625: padios (NULLCP, "unable to read folder %s", folder);
626: if (mp -> hghmsg == 0)
627: padios (NULLCP, "no messages in %s", folder);
628:
629: mode = m_gmprot ();
630: mtime = stat (mp -> foldpath, &st) != NOTOK ? st.st_mtime : 0;
631:
632: m_gMsgs (mp -> hghmsg);
633:
634: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) {
635: Msgs[msgnum].m_bboard_id = 0;
636: Msgs[msgnum].m_top = NOTOK;
637: Msgs[msgnum].m_start = Msgs[msgnum].m_stop = 0L;
638: Msgs[msgnum].m_scanl = NULL;
639: }
640:
641: m_init ();
642:
643: fmsh = getcpy (folder);
644:
645: #ifndef BSD42
646: maxfds = _NFILE / 2;
647: #else BSD42
648: maxfds = getdtablesize () / 2;
649: #endif BSD42
650: if ((maxfds -= 2) < 1)
651: maxfds = 1;
652: }
653:
654: /* */
655:
656: setup (file)
657: char *file;
658: {
659: int i,
660: msgp;
661: #ifdef BPOP
662: char tmpfil[BUFSIZ];
663: #endif BPOP
664: struct stat st;
665:
666: #ifdef BPOP
667: if (pmsh) {
668: (void) strcpy (tmpfil, m_tmpfil (invo_name));
669: if ((fp = fopen (tmpfil, "w+")) == NULL)
670: padios (tmpfil, "unable to create");
671: (void) unlink (tmpfil);
672: }
673: else
674: #endif BPOP
675: if ((fp = fopen (file, "r")) == NULL)
676: padios (file, "unable to read");
677: #ifdef FIOCLEX
678: (void) ioctl (fileno (fp), FIOCLEX, NULLCP);
679: #endif FIOCLEX
680: if (fstat (fileno (fp), &st) != NOTOK) {
681: mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
682: msgp = read_map (file, (long) st.st_size);
683: }
684: else {
685: mode = m_gmprot (), mtime = 0;
686: msgp = 0;
687: }
688:
689: if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
690: padios (NULLCP, "no messages in %s", myname ? myname : file);
691:
692: mp = (struct msgs *) calloc ((unsigned) 1, MSIZE (mp, 1, msgp + 1));
693: if (mp == NULL)
694: padios (NULLCP, "unable to allocate folder storage");
695:
696: mp -> hghmsg = msgp;
697: mp -> nummsg = msgp;
698: mp -> lowmsg = 1;
699: mp -> curmsg = 0;
700:
701: mp -> foldpath = getcpy (myname ? myname : file);
702: mp -> msgflags = NULL;
703: #ifdef BPOP
704: if (pmsh)
705: mp -> msgflags |= READONLY;
706: else {
707: #endif BPOP
708: (void) stat (file, &st);
709: if (st.st_uid != getuid () || access (file, 02) == NOTOK)
710: mp -> msgflags |= READONLY;
711: #ifdef BPOP
712: }
713: #endif BPOP
714: mp -> lowoff = 1;
715: mp -> hghoff = mp -> hghmsg + 1;
716:
717: #ifdef MTR
718: mp -> msgstats = (short *)
719: calloc ((unsigned) 1, MSIZEX (mp, mp -> lowmsg, mp -> hghmsg));
720: if (mp -> msgstats == NULL)
721: padios (NULLCP, "unable to allocate messages storage");
722: mp -> msgstats = (mp -> msgbase = mp -> msgstats) - mp -> lowoff;
723: if (mp -> msgstats < 0)
724: padios (NULLCP, "setup() botch -- you lose big");
725: #endif MTR
726: #ifdef BPOP
727: if (pmsh) {
728: for (i = mp -> lowmsg; i <= mp -> hghmsg; i++) {
729: Msgs[i].m_top = i;
730: mp -> msgstats[i] = EXISTS | VIRTUAL;
731: }
732: }
733: else
734: #endif BPOP
735: for (i = mp -> lowmsg; i <= mp -> hghmsg; i++)
736: mp -> msgstats[i] = EXISTS;
737: m_init ();
738:
739: mp -> msgattrs[0] = getcpy ("unseen");
740: mp -> msgattrs[1] = NULL;
741:
742: m_unknown (fp); /* the MAGIC invocation */
743: if (fmsh) {
744: free (fmsh);
745: fmsh = NULL;
746: }
747: }
748:
749: /* */
750:
751: static int read_map (file, size)
752: char *file;
753: long size;
754: {
755: register int i,
756: msgp;
757: register struct drop *dp,
758: *mp;
759: struct drop *rp;
760:
761: #ifdef BPOP
762: if (pmsh)
763: return read_pop ();
764: #endif BPOP
765:
766: if ((i = map_read (file, size, &rp, 1)) == 0)
767: return 0;
768:
769: m_gMsgs (i);
770:
771: msgp = 1;
772: for (dp = rp; i-- > 0; msgp++, dp++) {
773: mp = &Msgs[msgp].m_drop;
774: mp -> d_id = dp -> d_id;
775: mp -> d_size = dp -> d_size;
776: mp -> d_start = dp -> d_start;
777: mp -> d_stop = dp -> d_stop;
778: Msgs[msgp].m_scanl = NULL;
779: }
780: free ((char *) rp);
781:
782: return (msgp - 1);
783: }
784:
785: /* */
786:
787: static int read_file (pos, msgp)
788: register long pos;
789: register int msgp;
790: {
791: register int i;
792: register struct drop *dp,
793: *mp;
794: struct drop *rp;
795:
796: #ifdef BPOP
797: if (pmsh)
798: return (msgp - 1);
799: #endif BPOP
800:
801: if ((i = mbx_read (fp, pos, &rp, 1)) <= 0)
802: return (msgp - 1);
803:
804: m_gMsgs ((msgp - 1) + i);
805:
806: for (dp = rp; i-- > 0; msgp++, dp++) {
807: mp = &Msgs[msgp].m_drop;
808: mp -> d_id = 0;
809: mp -> d_size = dp -> d_size;
810: mp -> d_start = dp -> d_start;
811: mp -> d_stop = dp -> d_stop;
812: Msgs[msgp].m_scanl = NULL;
813: }
814: free ((char *) rp);
815:
816: return (msgp - 1);
817: }
818:
819: /* */
820:
821: #ifdef BPOP
822: static int read_pop () {
823: int nmsgs,
824: nbytes;
825:
826: if (pop_stat (&nmsgs, &nbytes) == NOTOK)
827: padios (NULLCP, "%s", response);
828:
829: m_gMsgs (nmsgs);
830:
831: return nmsgs;
832: }
833:
834:
835: static int pop_action (s)
836: register char *s;
837: {
838: fprintf (yp, "%s\n", s);
839: }
840: #endif BPOP
841:
842: /* */
843:
844: static m_gMsgs (n)
845: int n;
846: {
847: if (Msgs == NULL) {
848: nMsgs = n + MAXFOLDER / 2;
849: Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
850: if (Msgs == NULL)
851: padios (NULLCP, "unable to allocate Msgs structure");
852: return;
853: }
854:
855: if (nMsgs >= n)
856: return;
857:
858: nMsgs = n + MAXFOLDER / 2;
859: Msgs = (struct Msg *) realloc ((char *) Msgs,
860: (unsigned) (nMsgs + 2) * sizeof *Msgs);
861: if (Msgs == NULL)
862: padios (NULLCP, "unable to reallocate Msgs structure");
863: }
864:
865: /* */
866:
867: FILE *msh_ready (msgnum, full)
868: register int msgnum;
869: int full;
870: {
871: register int msgp;
872: int fd;
873: long pos1,
874: pos2;
875: char *cp,
876: tmpfil[BUFSIZ];
877:
878: if (yp) {
879: (void) fclose (yp);
880: yp = NULL;
881: }
882:
883: if (fmsh) {
884: if ((fd = Msgs[msgnum].m_top) == NOTOK) {
885: if (numfds >= maxfds)
886: for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++)
887: if (Msgs[msgp].m_top != NOTOK) {
888: (void) close (Msgs[msgp].m_top);
889: Msgs[msgp].m_top = NOTOK;
890: numfds--;
891: break;
892: }
893:
894: if ((fd = open (cp = m_name (msgnum), 0)) == NOTOK)
895: padios (cp, "unable to open message");
896: Msgs[msgnum].m_top = fd;
897: numfds++;
898: }
899:
900: if ((fd = dup (fd)) == NOTOK)
901: padios ("cached message", "unable to dup");
902: if ((yp = fdopen (fd, "r")) == NULL)
903: padios (NULLCP, "unable to fdopen cached message");
904: (void) fseek (yp, 0L, 0);
905: return yp;
906: }
907:
908: #ifdef BPOP
909: if (pmsh && (mp -> msgstats[msgnum] & VIRTUAL)) {
910: if (Msgs[msgnum].m_top == 0)
911: padios (NULLCP, "msh_ready (%d, %d) botch", msgnum, full);
912: if (!full) {
913: (void) strcpy (tmpfil, m_tmpfil (invo_name));
914: if ((yp = fopen (tmpfil, "w+")) == NULL)
915: padios (tmpfil, "unable to create");
916: (void) unlink (tmpfil);
917:
918: if (pop_top (Msgs[msgnum].m_top, 4, pop_action) == NOTOK)
919: padios (NULLCP, "%s", response);
920:
921: m_eomsbr ((int (*)()) 0); /* XXX */
922: msg_style = MS_DEFAULT; /* .. */
923: (void) fseek (yp, 0L, 0);
924: return yp;
925: }
926:
927: (void) fseek (fp, 0L, 2);
928: (void) fwrite (mmdlm1, 1, strlen (mmdlm1), fp);
929: if (fflush (fp))
930: padios ("temporary file", "write error on");
931: (void) fseek (fp, 0L, 2);
932: pos1 = ftell (fp);
933:
934: yp = fp;
935: if (pop_retr (Msgs[msgnum].m_top, pop_action) == NOTOK)
936: padios (NULLCP, "%s", response);
937: yp = NULL;
938:
939: (void) fseek (fp, 0L, 2);
940: pos2 = ftell (fp);
941: (void) fwrite (mmdlm2, 1, strlen (mmdlm2), fp);
942: if (fflush (fp))
943: padios ("temporary file", "write error on");
944:
945: Msgs[msgnum].m_start = pos1;
946: Msgs[msgnum].m_stop = pos2;
947:
948: mp -> msgstats[msgnum] &= ~VIRTUAL;
949: }
950: #endif BPOP
951:
952: m_eomsbr ((int (*)()) 0); /* XXX */
953: (void) fseek (fp, Msgs[msgnum].m_start, 0);
954: return fp;
955: }
956:
957: /* */
958:
959: static int check_folder (scansw)
960: int scansw;
961: {
962: int flags,
963: i,
964: low,
965: hgh,
966: msgp;
967: struct stat st;
968:
969: #ifdef BPOP
970: if (pmsh)
971: return 0;
972: #endif BPOP
973:
974: if (fmsh) {
975: if (stat (mp -> foldpath, &st) == NOTOK)
976: padios (mp -> foldpath, "unable to stat");
977: if (mtime == st.st_mtime)
978: return 0;
979: mtime = st.st_mtime;
980:
981: low = mp -> hghmsg + 1;
982: m_fmsg (mp);
983:
984: if (!(mp = m_gmsg (fmsh)))
985: padios (NULLCP, "unable to re-read folder %s", fmsh);
986:
987: hgh = mp -> hghmsg;
988:
989: for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++) {
990: if (Msgs[msgp].m_top != NOTOK) {
991: (void) close (Msgs[msgp].m_top);
992: Msgs[msgp].m_top = NOTOK;
993: numfds--;
994: }
995: if (Msgs[msgp].m_scanl) {
996: free (Msgs[msgp].m_scanl);
997: Msgs[msgp].m_scanl = NULL;
998: }
999: }
1000:
1001: m_init ();
1002:
1003: if (modified || low > hgh)
1004: return 1;
1005: goto check_vmh;
1006: }
1007: if (fstat (fileno (fp), &st) == NOTOK)
1008: padios (mp -> foldpath, "unable to fstat");
1009: if (mtime == st.st_mtime)
1010: return 0;
1011: mode = (int) (st.st_mode & 0777);
1012: mtime = st.st_mtime;
1013:
1014: if ((msgp = read_file (Msgs[mp -> hghmsg].m_stop, mp -> hghmsg + 1)) < 1)
1015: padios (NULLCP, "no messages in %s", mp -> foldpath); /* XXX */
1016: if (msgp >= MAXFOLDER)
1017: padios (NULLCP, "more than %d messages in %s", MAXFOLDER,
1018: mp -> foldpath);
1019: if (msgp <= mp -> hghmsg)
1020: return 0; /* XXX */
1021:
1022: if ((mp = m_remsg (mp, 0, msgp)) == NULL)
1023: padios (NULLCP, "unable to allocate folder storage");
1024:
1025: low = mp -> hghmsg + 1, hgh = msgp;
1026: flags = scansw ? m_seqflag (mp, "unseen") : 0;
1027: for (i = mp -> hghmsg + 1; i <= msgp; i++) {
1028: mp -> msgstats[i] = EXISTS | flags;
1029: mp -> nummsg++;
1030: }
1031: mp -> hghmsg = msgp;
1032: m_init ();
1033:
1034: check_vmh: ;
1035: if (vmh)
1036: return 1;
1037:
1038: advise (NULLCP, "new messages have arrived!\007");
1039: if (scansw)
1040: scanrange (low, hgh);
1041:
1042: return 1;
1043: }
1044:
1045: /* */
1046:
1047: static scanrange (low, hgh)
1048: int low,
1049: hgh;
1050: {
1051: char buffer[BUFSIZ];
1052:
1053: (void) sprintf (buffer, "%d-%d", low, hgh);
1054: scanstring (buffer);
1055: }
1056:
1057:
1058: static scanstring (arg)
1059: char *arg;
1060: {
1061: char *cp,
1062: **ap,
1063: *vec[MAXARGS];
1064:
1065: if ((cp = m_find (cmd_name = "scan")) != NULL) {
1066: ap = brkstring (cp = getcpy (cp), " ", "\n");
1067: ap = copyip (ap, vec);
1068: }
1069: else
1070: ap = vec;
1071: *ap++ = arg;
1072: *ap = NULL;
1073: m_init ();
1074: scancmd (vec);
1075: if (cp != NULL)
1076: free (cp);
1077: }
1078:
1079: /* */
1080:
1081: readids (id)
1082: int id;
1083: {
1084: register int cur,
1085: flags,
1086: i,
1087: msgnum;
1088:
1089: if (mp -> curmsg == 0)
1090: m_setcur (mp, mp -> lowmsg);
1091: if (id <= 0 || (flags = m_seqflag (mp, "unseen")) == 0)
1092: return;
1093:
1094: for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
1095: mp -> msgstats[msgnum] |= flags;
1096:
1097: if (id != 1) {
1098: cur = mp -> curmsg;
1099:
1100: for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
1101: if ((i = readid (msgnum)) > 0 && i < id) {
1102: cur = msgnum + 1;
1103: mp -> msgstats[msgnum] &= ~flags;
1104: break;
1105: }
1106: for (i = mp -> lowmsg; i < msgnum; i++)
1107: mp -> msgstats[i] &= ~flags;
1108:
1109: if (cur > mp -> hghmsg)
1110: cur = mp -> hghmsg;
1111:
1112: m_setcur (mp, cur);
1113: }
1114:
1115: if ((gap = 1 < id && id < (i = readid (mp -> lowmsg)) ? id : 0) && !vmh)
1116: advise (NULLCP, "gap in ID:s, last seen %d, lowest present %d\n",
1117: id - 1, i);
1118: }
1119:
1120: /* */
1121:
1122: int readid (msgnum)
1123: int msgnum;
1124: {
1125: int i,
1126: state;
1127: #ifdef BPOP
1128: int arg1,
1129: arg2,
1130: arg3;
1131: #endif BPOP
1132: char *bp,
1133: buf[BUFSIZ],
1134: name[NAMESZ];
1135: register FILE *zp;
1136:
1137: if (Msgs[msgnum].m_bboard_id)
1138: return Msgs[msgnum].m_bboard_id;
1139: #ifdef BPOP
1140: if (pmsh) {
1141: if (Msgs[msgnum].m_top == 0)
1142: padios (NULLCP, "readid (%d) botch", msgnum);
1143: if (pop_list (Msgs[msgnum].m_top, (int *) 0, &arg1, &arg2, &arg3) == OK
1144: && arg3 > 0)
1145: return (Msgs[msgnum].m_bboard_id = arg3);
1146: }
1147: #endif BPOP
1148:
1149: zp = msh_ready (msgnum, 0);
1150: for (state = FLD;;)
1151: switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
1152: case FLD:
1153: case FLDEOF:
1154: case FLDPLUS:
1155: if (uleq (name, BBoard_ID)) {
1156: bp = getcpy (buf);
1157: while (state == FLDPLUS) {
1158: state = m_getfld (state, name, buf, sizeof buf, zp);
1159: bp = add (buf, bp);
1160: }
1161: i = atoi (bp);
1162: free (bp);
1163: if (i > 0)
1164: return (Msgs[msgnum].m_bboard_id = i);
1165: else
1166: continue;
1167: }
1168: while (state == FLDPLUS)
1169: state = m_getfld (state, name, buf, sizeof buf, zp);
1170: if (state != FLDEOF)
1171: continue;
1172:
1173: default:
1174: return 0;
1175: }
1176: }
1177:
1178: /* */
1179:
1180: display_info (scansw)
1181: int scansw;
1182: {
1183: int flags,
1184: sd;
1185:
1186: interactive = isatty (fileno (stdout));
1187: if (sp == NULL) {
1188: if ((sd = dup (fileno (stdout))) == NOTOK)
1189: padios ("standard output", "unable to dup");
1190: #ifndef BSD42 /* XXX */
1191: #ifdef FIOCLEX
1192: (void) ioctl (sd, FIOCLEX, NULL);
1193: #endif FIOCLEX
1194: #endif not BSD42
1195: if ((sp = fdopen (sd, "w")) == NULL)
1196: padios ("standard output", "unable to fdopen");
1197: }
1198:
1199: (void) putenv ("mhfolder", mp -> foldpath);
1200: if (vmh)
1201: return;
1202:
1203: if (myname) {
1204: printf ("Reading ");
1205: if (SOprintf ("%s", myname))
1206: printf ("%s", myname);
1207: printf (", currently at message %d of %d\n",
1208: mp -> curmsg, mp -> hghmsg);
1209: }
1210: else {
1211: printf ("Reading ");
1212: if (fmsh)
1213: printf ("+%s", fmsh);
1214: else
1215: printf ("%s", mp -> foldpath);
1216: printf (", currently at message %d of %d\n",
1217: mp -> curmsg, mp -> hghmsg);
1218: }
1219:
1220: if ((flags = m_seqflag (mp, "unseen"))
1221: && scansw
1222: && (mp -> msgstats[mp -> hghmsg] & flags))
1223: scanstring ("unseen");
1224: }
1225:
1226: /* */
1227:
1228: static write_ids () {
1229: int i = 0,
1230: flags,
1231: msgnum;
1232: char buffer[80];
1233:
1234: if (pfd <= 1)
1235: return;
1236:
1237: if (flags = m_seqflag (mp, "unseen"))
1238: for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
1239: if (!(mp -> msgstats[msgnum] & flags)) {
1240: if (Msgs[msgnum].m_bboard_id == 0)
1241: (void) readid (msgnum);
1242: if ((i = Msgs[msgnum].m_bboard_id) > 0)
1243: break;
1244: }
1245:
1246: (void) sprintf (buffer, "%d %d\n", i, Msgs[mp -> hghmsg].m_bboard_id);
1247: (void) write (pfd, buffer, sizeof buffer);
1248: (void) close (pfd);
1249: pfd = NOTOK;
1250: }
1251:
1252: /* */
1253:
1254: static quit () {
1255: int i,
1256: md,
1257: msgnum;
1258: char *cp,
1259: tmpfil[BUFSIZ],
1260: map1[BUFSIZ],
1261: map2[BUFSIZ];
1262: struct stat st;
1263: FILE *dp;
1264:
1265: if (!(mp -> msgflags & MODIFIED) || mp -> msgflags & READONLY || fmsh) {
1266: if (vmh)
1267: (void) rc2peer (RC_FIN, 0, NULLCP);
1268: return;
1269: }
1270:
1271: if (vmh)
1272: (void) ttyNaux (NULLCMD, "FAST");
1273: cp = NULL;
1274: if ((dp = lkfopen (mp -> foldpath, "r")) == NULL) {
1275: advise (mp -> foldpath, "unable to lock");
1276: if (vmh) {
1277: (void) ttyR (NULLCMD);
1278: (void) pFIN ();
1279: }
1280: return;
1281: }
1282: if (fstat (fileno (dp), &st) == NOTOK) {
1283: advise (mp -> foldpath, "unable to stat");
1284: goto release;
1285: }
1286: if (mtime != st.st_mtime) {
1287: advise (NULLCP, "new messages have arrived, no update");
1288: goto release;
1289: }
1290: mode = (int) (st.st_mode & 0777);
1291:
1292: if (mp -> nummsg == 0) {
1293: cp = concat ("Zero file \"", mp -> foldpath, "\"? ", NULLCP);
1294: if (getanswer (cp)) {
1295: if ((i = creat (mp -> foldpath, mode)) != NOTOK)
1296: (void) close (i);
1297: else
1298: advise (mp -> foldpath, "error zero'ing");
1299: (void) unlink (map_name (mp -> foldpath));/* XXX */
1300: }
1301: goto release;
1302: }
1303:
1304: cp = concat ("Update file \"", mp -> foldpath, "\"? ", NULLCP);
1305: if (!getanswer (cp))
1306: goto release;
1307: (void) strcpy (tmpfil, m_backup (mp -> foldpath));
1308: if ((md = mbx_open (tmpfil, st.st_uid, st.st_gid, mode)) == NOTOK) {
1309: advise (tmpfil, "unable to open");
1310: goto release;
1311: }
1312:
1313: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1314: if (mp -> msgstats[msgnum] & EXISTS
1315: && pack (tmpfil, md, msgnum) == NOTOK) {
1316: (void) mbx_close (tmpfil, md);
1317: (void) unlink (tmpfil);
1318: (void) unlink (map_name (tmpfil));
1319: goto release;
1320: }
1321: (void) mbx_close (tmpfil, md);
1322:
1323: if (rename (tmpfil, mp -> foldpath) == NOTOK)
1324: admonish (mp -> foldpath, "unable to rename %s to", tmpfil);
1325: else {
1326: (void) strcpy (map1, map_name (tmpfil));
1327: (void) strcpy (map2, map_name (mp -> foldpath));
1328:
1329: if (rename (map1, map2) == NOTOK) {
1330: admonish (map2, "unable to rename %s to", map1);
1331: (void) unlink (map1);
1332: (void) unlink (map2);
1333: }
1334: }
1335:
1336: release: ;
1337: if (cp)
1338: free (cp);
1339: (void) lkfclose (dp, mp -> foldpath);
1340: if (vmh) {
1341: (void) ttyR (NULLCMD);
1342: (void) pFIN ();
1343: }
1344: }
1345:
1346: /* */
1347:
1348: static int getargs (prompt, sw, cmdp)
1349: char *prompt;
1350: struct swit *sw;
1351: struct Cmd *cmdp;
1352: {
1353: int i;
1354: char *cp;
1355: static char buffer[BUFSIZ];
1356:
1357: told_to_quit = 0;
1358: for (;;) {
1359: interrupted = 0;
1360: #ifdef BSD42
1361: switch (setjmp (sigenv)) {
1362: case OK:
1363: should_intr = 1;
1364: break;
1365:
1366: default:
1367: should_intr = 0;
1368: if (interrupted && !told_to_quit) {
1369: (void) putchar ('\n');
1370: continue;
1371: }
1372: if (ppid > 0)
1373: (void) kill (ppid, SIGEMT);
1374: return EOF;
1375: }
1376: #endif BSD42
1377: if (interactive) {
1378: printf ("%s", prompt);
1379: (void) fflush (stdout);
1380: }
1381: for (cp = buffer; (i = getchar ()) != '\n';) {
1382: #ifndef BSD42
1383: if (interrupted && !told_to_quit) {
1384: buffer[0] = NULL;
1385: (void) putchar ('\n');
1386: break;
1387: }
1388: if (told_to_quit || i == EOF) {
1389: if (ppid > 0)
1390: (void) kill (ppid, SIGEMT);
1391: return EOF;
1392: }
1393: #else BSD42
1394: if (i == EOF)
1395: longjmp (sigenv, DONE);
1396: #endif BSD42
1397: if (cp < &buffer[sizeof buffer - 2])
1398: *cp++ = i;
1399: }
1400: *cp = NULL;
1401:
1402: if (buffer[0] == NULL)
1403: continue;
1404: if (buffer[0] == '?') {
1405: printf ("commands:\n");
1406: printsw (ALL, sw, "");
1407: printf ("type CTRL-D or use ``quit'' to leave %s\n",
1408: invo_name);
1409: continue;
1410: }
1411:
1412: if (parse (buffer, cmdp) == NOTOK)
1413: continue;
1414:
1415: switch (i = smatch (cmdp -> args[0], sw)) {
1416: case AMBIGSW:
1417: ambigsw (cmdp -> args[0], sw);
1418: continue;
1419: case UNKWNSW:
1420: printf ("say what: ``%s'' -- type ? (or help) for help\n",
1421: cmdp -> args[0]);
1422: continue;
1423: default:
1424: #ifdef BSD42
1425: should_intr = 0;
1426: #endif BSD42
1427: return i;
1428: }
1429: }
1430: }
1431:
1432: /* */
1433:
1434: static int getcmds (sw, cmdp, scansw)
1435: struct swit *sw;
1436: struct Cmd *cmdp;
1437: int scansw;
1438: {
1439: int i;
1440: struct record rcs,
1441: *rc = &rcs;
1442:
1443: initrc (rc);
1444:
1445: for (;;)
1446: switch (peer2rc (rc)) {
1447: case RC_QRY:
1448: (void) pQRY (rc -> rc_data, scansw);
1449: break;
1450:
1451: case RC_CMD:
1452: if ((i = pCMD (rc -> rc_data, sw, cmdp)) != NOTOK)
1453: return i;
1454: break;
1455:
1456: case RC_FIN:
1457: if (ppid > 0)
1458: (void) kill (ppid, SIGEMT);
1459: return EOF;
1460:
1461: case RC_XXX:
1462: padios (NULLCP, "%s", rc -> rc_data);
1463:
1464: default:
1465: (void) fmt2peer (RC_ERR, "pLOOP protocol screw-up");
1466: done (1);
1467: }
1468: }
1469:
1470: /* */
1471:
1472: static int parse (buffer, cmdp)
1473: char *buffer;
1474: struct Cmd *cmdp;
1475: {
1476: int argp = 0;
1477: char c,
1478: *cp,
1479: *pp;
1480:
1481: cmdp -> line[0] = NULL;
1482: pp = cmdp -> args[argp++] = cmdp -> line;
1483: cmdp -> redirect = NULL;
1484: cmdp -> direction = STDIO;
1485: cmdp -> stream = NULL;
1486:
1487: for (cp = buffer; c = *cp; cp++)
1488: if (!isspace (c))
1489: break;
1490: if (c == NULL) {
1491: if (vmh)
1492: (void) fmt2peer (RC_EOF, "null command");
1493: return NOTOK;
1494: }
1495:
1496: while (c = *cp++) {
1497: if (isspace (c)) {
1498: while (isspace (c))
1499: c = *cp++;
1500: if (c == NULL)
1501: break;
1502: *pp++ = NULL;
1503: cmdp -> args[argp++] = pp;
1504: *pp = NULL;
1505: }
1506:
1507: switch (c) {
1508: case '"':
1509: for (;;) {
1510: switch (c = *cp++) {
1511: case NULL:
1512: padvise (NULLCP, "unmatched \"");
1513: return NOTOK;
1514: case '"':
1515: break;
1516: case QUOTE:
1517: if ((c = *cp++) == NULL)
1518: goto no_quoting;
1519: default:
1520: *pp++ = c;
1521: continue;
1522: }
1523: break;
1524: }
1525: continue;
1526:
1527: case QUOTE:
1528: if ((c = *cp++) == NULL) {
1529: no_quoting: ;
1530: padvise (NULLCP, "the newline character can not be quoted");
1531: return NOTOK;
1532: }
1533:
1534: default: ;
1535: *pp++ = c;
1536: continue;
1537:
1538: case '>':
1539: case '|':
1540: if (pp == cmdp -> line) {
1541: padvise (NULLCP, "invalid null command");
1542: return NOTOK;
1543: }
1544: if (*cmdp -> args[argp - 1] == NULL)
1545: argp--;
1546: cmdp -> direction = c == '>' ? CRTIO : PIPIO;
1547: if (cmdp -> direction == CRTIO && (c = *cp) == '>') {
1548: cmdp -> direction = APPIO;
1549: cp++;
1550: }
1551: cmdp -> redirect = pp + 1;/* sigh */
1552: for (; c = *cp; cp++)
1553: if (!isspace (c))
1554: break;
1555: if (c == NULL) {
1556: padvise (NULLCP, cmdp -> direction != PIPIO
1557: ? "missing name for redirect"
1558: : "invalid null command");
1559: return NOTOK;
1560: }
1561: (void) strcpy (cmdp -> redirect, cp);
1562: if (cmdp -> direction != PIPIO) {
1563: for (; *cp; cp++)
1564: if (isspace (*cp)) {
1565: padvise (NULLCP, "bad name for redirect");
1566: return NOTOK;
1567: }
1568: if (expand (cmdp -> redirect) == NOTOK)
1569: return NOTOK;
1570: }
1571: break;
1572: }
1573: break;
1574: }
1575:
1576: *pp++ = NULL;
1577: cmdp -> args[argp] = NULL;
1578:
1579: return OK;
1580: }
1581:
1582: /* */
1583:
1584: int expand (redirect)
1585: char *redirect;
1586: {
1587: char *cp,
1588: *pp;
1589: char path[BUFSIZ];
1590: struct passwd *pw;
1591:
1592: if (*redirect != '~')
1593: return OK;
1594:
1595: if (cp = index (pp = redirect + 1, '/'))
1596: *cp++ = NULL;
1597: if (*pp == NULL)
1598: pp = mypath;
1599: else
1600: if (pw = getpwnam (pp))
1601: pp = pw -> pw_dir;
1602: else {
1603: padvise (NULLCP, "unknown user: %s", pp);
1604: return NOTOK;
1605: }
1606:
1607: (void) sprintf (path, "%s/%s", pp, cp ? cp : "");
1608: (void) strcpy (redirect, path);
1609: return OK;
1610: }
1611:
1612: /* */
1613:
1614: static int init_io (cmdp, vio)
1615: register struct Cmd *cmdp;
1616: int vio;
1617: {
1618: int io,
1619: result;
1620:
1621: io = vmh;
1622:
1623: vmh = vio;
1624: result = initaux_io (cmdp);
1625: vmh = io;
1626:
1627: return result;
1628: }
1629:
1630:
1631: static int initaux_io (cmdp)
1632: register struct Cmd *cmdp;
1633: {
1634: char *mode;
1635:
1636: switch (cmdp -> direction) {
1637: case STDIO:
1638: return OK;
1639:
1640: case CRTIO:
1641: case APPIO:
1642: mode = cmdp -> direction == CRTIO ? "write" : "append";
1643: if ((cmdp -> stream = fopen (cmdp -> redirect, mode)) == NULL) {
1644: padvise (cmdp -> redirect, "unable to %s ", mode);
1645: cmdp -> direction = STDIO;
1646: return NOTOK;
1647: }
1648: break;
1649:
1650: case PIPIO:
1651: if ((cmdp -> stream = popen (cmdp -> redirect, "w")) == NULL) {
1652: padvise (cmdp -> redirect, "unable to pipe");
1653: cmdp -> direction = STDIO;
1654: return NOTOK;
1655: }
1656: (void) signal (SIGPIPE, pipeser);
1657: broken_pipe = 0;
1658: break;
1659:
1660: default:
1661: padios (NULLCP, "unknown redirection for command");
1662: }
1663:
1664: (void) fflush (stdout);
1665: if (dup2 (fileno (cmdp -> stream), fileno (stdout)) == NOTOK)
1666: padios ("standard output", "unable to dup2");
1667: clearerr (stdout);
1668:
1669: return OK;
1670: }
1671:
1672: /* */
1673:
1674: static fin_io (cmdp, vio)
1675: register struct Cmd *cmdp;
1676: int vio;
1677: {
1678: int io;
1679:
1680: io = vmh;
1681:
1682: vmh = vio;
1683: finaux_io (cmdp);
1684: vmh = io;
1685: }
1686:
1687:
1688: static int finaux_io (cmdp)
1689: register struct Cmd *cmdp;
1690: {
1691: switch (cmdp -> direction) {
1692: case STDIO:
1693: return;
1694:
1695: case CRTIO:
1696: case APPIO:
1697: (void) fflush (stdout);
1698: (void) close (fileno (stdout));
1699: if (ferror (stdout))
1700: padvise (NULLCP, "problems writing %s", cmdp -> redirect);
1701: (void) fclose (cmdp -> stream);
1702: break;
1703:
1704: case PIPIO:
1705: (void) fflush (stdout);
1706: (void) close (fileno (stdout));
1707: (void) pclose (cmdp -> stream);
1708: (void) signal (SIGPIPE, SIG_DFL);
1709: break;
1710:
1711: default:
1712: padios (NULLCP, "unknown redirection for command");
1713: }
1714:
1715: if (dup2 (fileno (sp), fileno (stdout)) == NOTOK)
1716: padios ("standard output", "unable to dup2");
1717: clearerr (stdout);
1718:
1719: cmdp -> direction = STDIO;
1720: }
1721:
1722: /* */
1723:
1724: static m_init () {
1725: int msgnum;
1726:
1727: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1728: mp -> msgstats[msgnum] &= ~SELECTED;
1729: mp -> lowsel = mp -> hghsel = mp -> numsel = 0;
1730: }
1731:
1732:
1733: m_reset () {
1734: write_ids ();
1735: m_fmsg (mp);
1736: myname = NULL;
1737: #ifdef BPOP
1738: if (pmsh) {
1739: (void) pop_done ();
1740: pmsh = 0;
1741: }
1742: #endif BPOP
1743: }
1744:
1745: /* */
1746:
1747: void m_setcur (mp, msgnum)
1748: register struct msgs *mp;
1749: register int msgnum;
1750: {
1751: if (mp -> curmsg == msgnum)
1752: return;
1753:
1754: if (mp -> curmsg && Msgs[mp -> curmsg].m_scanl) {
1755: free (Msgs[mp -> curmsg].m_scanl);
1756: Msgs[mp -> curmsg].m_scanl = NULL;
1757: }
1758: if (Msgs[msgnum].m_scanl) {
1759: free (Msgs[msgnum].m_scanl);
1760: Msgs[msgnum].m_scanl = NULL;
1761: }
1762:
1763: mp -> curmsg = msgnum;
1764: }
1765:
1766: /* */
1767:
1768: /* ARGSUSED */
1769:
1770: static int intrser (i)
1771: int i;
1772: {
1773: #ifndef BSD42
1774: (void) signal (SIGINT, intrser);
1775: #endif not BSD42
1776:
1777: discard (stdout);
1778:
1779: interrupted++;
1780: #ifdef BSD42
1781: if (should_intr)
1782: longjmp (sigenv, NOTOK);
1783: #endif BSD42
1784: }
1785:
1786:
1787: /* ARGSUSED */
1788:
1789: static int pipeser (i)
1790: int i;
1791: {
1792: #ifndef BSD42
1793: (void) signal (SIGPIPE, pipeser);
1794: #endif not BSD42
1795:
1796: if (broken_pipe++ == 0)
1797: fprintf (stderr, "broken pipe\n");
1798: told_to_quit++;
1799: interrupted++;
1800: #ifdef BSD42
1801: if (should_intr)
1802: longjmp (sigenv, NOTOK);
1803: #endif BSD42
1804: }
1805:
1806:
1807: /* ARGSUSED */
1808:
1809: static int quitser (i)
1810: int i;
1811: {
1812: #ifndef BSD42
1813: (void) signal (SIGQUIT, quitser);
1814: #endif BSD42
1815:
1816: told_to_quit++;
1817: interrupted++;
1818: #ifdef BSD42
1819: if (should_intr)
1820: longjmp (sigenv, NOTOK);
1821: #endif BSD42
1822: }
1823:
1824: /* */
1825:
1826: static int pINI () {
1827: int i,
1828: vrsn;
1829: char *bp;
1830: struct record rcs,
1831: *rc = &rcs;
1832:
1833: initrc (rc);
1834:
1835: switch (peer2rc (rc)) {
1836: case RC_INI:
1837: bp = rc -> rc_data;
1838: while (isspace (*bp))
1839: bp++;
1840: if (sscanf (bp, "%d", &vrsn) != 1) {
1841: bad_init: ;
1842: (void) fmt2peer (RC_ERR, "bad init \"%s\"", rc -> rc_data);
1843: done (1);
1844: }
1845: if (vrsn != RC_VRSN) {
1846: (void) fmt2peer (RC_ERR, "version %d unsupported", vrsn);
1847: done (1);
1848: }
1849:
1850: while (*bp && !isspace (*bp))
1851: bp++;
1852: while (isspace (*bp))
1853: bp++;
1854: if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0)
1855: goto bad_init;
1856: if (numwins > NWIN)
1857: numwins = NWIN;
1858:
1859: for (i = 1; i <= numwins; i++) {
1860: while (*bp && !isspace (*bp))
1861: bp++;
1862: while (isspace (*bp))
1863: bp++;
1864: if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0)
1865: goto bad_init;
1866: }
1867: (void) rc2peer (RC_ACK, 0, NULLCP);
1868: return OK;
1869:
1870: case RC_XXX:
1871: padios (NULLCP, "%s", rc -> rc_data);
1872:
1873: default:
1874: (void) fmt2peer (RC_ERR, "pINI protocol screw-up");
1875: done (1); /* NOTREACHED */
1876: }
1877: }
1878:
1879: /* */
1880:
1881: /* ARGSUSED */
1882:
1883: static int pQRY (str, scansw)
1884: char *str;
1885: int scansw;
1886: {
1887: if (pQRY1 (scansw) == NOTOK || pQRY2 () == NOTOK)
1888: return NOTOK;
1889:
1890: (void) rc2peer (RC_EOF, 0, NULLCP);
1891: return OK;
1892: }
1893:
1894: /* */
1895:
1896: static int pQRY1 (scansw)
1897: int scansw;
1898: {
1899: int oldhgh;
1900: static int lastlow = 0,
1901: lastcur = 0,
1902: lasthgh = 0,
1903: lastnum = 0;
1904:
1905: oldhgh = mp -> hghmsg;
1906: if (check_folder (scansw) && oldhgh < mp -> hghmsg) {
1907: switch (winX (STATUS)) {
1908: case NOTOK:
1909: return NOTOK;
1910:
1911: case OK:
1912: printf ("new messages have arrived!");
1913: (void) fflush (stdout);
1914: (void) fflush (stderr);
1915: _exit (0); /* NOTREACHED */
1916:
1917: default:
1918: lastlow = lastcur = lasthgh = lastnum = 0;
1919: break;
1920: }
1921:
1922: switch (winX (DISPLAY)) {
1923: case NOTOK:
1924: return NOTOK;
1925:
1926: case OK:
1927: scanrange (oldhgh + 1, mp -> hghmsg);
1928: (void) fflush (stdout);
1929: (void) fflush (stderr);
1930: _exit (0); /* NOTREACHED */
1931:
1932: default:
1933: break;
1934: }
1935: return OK;
1936: }
1937:
1938: if (gap)
1939: switch (winX (STATUS)) {
1940: case NOTOK:
1941: return NOTOK;
1942:
1943: case OK:
1944: printf ("%s: gap in ID:s, last seen %d, lowest present %d\n",
1945: myname ? myname : fmsh ? fmsh : mp -> foldpath, gap - 1,
1946: readid (mp -> lowmsg));
1947: (void) fflush (stdout);
1948: (void) fflush (stderr);
1949: _exit (0); /* NOTREACHED */
1950:
1951: default:
1952: gap = 0;
1953: return OK;
1954: }
1955:
1956: if (mp -> lowmsg != lastlow
1957: || mp -> curmsg != lastcur
1958: || mp -> hghmsg != lasthgh
1959: || mp -> nummsg != lastnum)
1960: switch (winX (STATUS)) {
1961: case NOTOK:
1962: return NOTOK;
1963:
1964: case OK:
1965: foldcmd (NULLVP);
1966: (void) fflush (stdout);
1967: (void) fflush (stderr);
1968: _exit (0); /* NOTREACHED */
1969:
1970: default:
1971: lastlow = mp -> lowmsg;
1972: lastcur = mp -> curmsg;
1973: lasthgh = mp -> hghmsg;
1974: lastnum = mp -> nummsg;
1975: return OK;
1976: }
1977:
1978: return OK;
1979: }
1980:
1981: /* */
1982:
1983: static int pQRY2 () {
1984: int i,
1985: j,
1986: k,
1987: msgnum,
1988: n;
1989: static int cur = 0,
1990: num = 0,
1991: lo = 0,
1992: hi = 0;
1993:
1994: if (mp -> nummsg == 0 && mp -> nummsg != num)
1995: switch (winX (SCAN)) {
1996: case NOTOK:
1997: return NOTOK;
1998:
1999: case OK:
2000: printf ("empty!");
2001: (void) fflush (stdout);
2002: (void) fflush (stderr);
2003: _exit (0); /* NOTREACHED */
2004:
2005: default:
2006: num = mp -> nummsg;
2007: return OK;
2008: }
2009: num = mp -> nummsg;
2010:
2011: i = 0;
2012: j = (k = windows[SCAN]) / 2;
2013: for (msgnum = mp -> curmsg; msgnum <= mp -> hghmsg; msgnum++)
2014: if (mp -> msgstats[msgnum] & EXISTS)
2015: i++;
2016: if (i-- > 0)
2017: if (topcur)
2018: k = i >= k ? 1 : k - i;
2019: else
2020: k -= i > j ? j : i;
2021:
2022: i = j = 0;
2023: n = 1;
2024: for (msgnum = mp -> curmsg; msgnum >= mp -> lowmsg; msgnum--)
2025: if (mp -> msgstats[msgnum] & EXISTS) {
2026: i = msgnum;
2027: if (j == 0)
2028: j = msgnum;
2029: if (n++ >= k)
2030: break;
2031: }
2032: for (msgnum = mp -> curmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
2033: if (mp -> msgstats[msgnum] & EXISTS) {
2034: if (i == 0)
2035: i = msgnum;
2036: j = msgnum;
2037: if (n++ >= windows[SCAN])
2038: break;
2039: }
2040: if (!topcur
2041: && lo > 0
2042: && hi > 0
2043: && mp -> msgstats[lo] & EXISTS
2044: && mp -> msgstats[hi] & EXISTS
2045: && (lo < mp -> curmsg
2046: || (lo == mp -> curmsg && lo == mp -> lowmsg))
2047: && (mp -> curmsg < hi
2048: || (hi == mp -> curmsg && hi == mp -> hghmsg))
2049: && hi - lo == j - i)
2050: i = lo, j = hi;
2051:
2052: if (mp -> curmsg != cur || modified)
2053: switch (winN (NULLCMD, SCAN, 0)) {
2054: case NOTOK:
2055: return NOTOK;
2056:
2057: case OK:
2058: return OK;
2059:
2060: default:
2061: scanrange (lo = i, hi = j);
2062: cur = mp -> curmsg;
2063: (void) winR (NULLCMD);
2064: return OK;
2065: }
2066:
2067: return OK;
2068: }
2069:
2070: /* */
2071:
2072: static int pCMD (str, sw, cmdp)
2073: char *str;
2074: struct swit *sw;
2075: struct Cmd *cmdp;
2076: {
2077: int i;
2078:
2079: if (*str == '?')
2080: switch (winX (DISPLAY)) {
2081: case NOTOK:
2082: return NOTOK;
2083:
2084: case OK:
2085: printf ("commands:\n");
2086: printsw (ALL, sw, "");
2087: printf ("type ``quit'' to leave %s\n", invo_name);
2088: (void) fflush (stdout);
2089: (void) fflush (stderr);
2090: _exit (0); /* NOTREACHED */
2091:
2092: default:
2093: (void) rc2peer (RC_EOF, 0, NULLCP);
2094: return NOTOK;
2095: }
2096:
2097: if (parse (str, cmdp) == NOTOK)
2098: return NOTOK;
2099:
2100: switch (i = smatch (cmdp -> args[0], sw)) {
2101: case AMBIGSW:
2102: switch (winX (DISPLAY)) {
2103: case NOTOK:
2104: return NOTOK;
2105:
2106: case OK:
2107: ambigsw (cmdp -> args[0], sw);
2108: (void) fflush (stdout);
2109: (void) fflush (stderr);
2110: _exit (0); /* NOTREACHED */
2111:
2112: default:
2113: (void) rc2peer (RC_EOF, 0, NULLCP);
2114: return NOTOK;
2115: }
2116:
2117: case UNKWNSW:
2118: (void) fmt2peer (RC_ERR,
2119: "say what: ``%s'' -- type ? (or help) for help",
2120: cmdp -> args[0]);
2121: return NOTOK;
2122:
2123: default:
2124: return i;
2125: }
2126: }
2127:
2128: /* */
2129:
2130: static int pFIN () {
2131: int status;
2132:
2133: switch (setjmp (peerenv)) {
2134: case OK:
2135: (void) signal (SIGALRM, alrmser);
2136: (void) alarm (ALARM);
2137:
2138: status = peerwait ();
2139:
2140: (void) alarm (0);
2141: return status;
2142:
2143: default:
2144: return NOTOK;
2145: }
2146: }
2147:
2148:
2149: static int peerwait () {
2150: struct record rcs,
2151: *rc = &rcs;
2152:
2153: initrc (rc);
2154:
2155: switch (peer2rc (rc)) {
2156: case RC_QRY:
2157: case RC_CMD:
2158: (void) rc2peer (RC_FIN, 0, NULLCP);
2159: return OK;
2160:
2161: case RC_XXX:
2162: advise (NULLCP, "%s", rc -> rc_data);
2163: return NOTOK;
2164:
2165: default:
2166: (void) fmt2peer (RC_FIN, "pLOOP protocol screw-up");
2167: return NOTOK;
2168: }
2169: }
2170:
2171:
2172: /* ARGSUSED */
2173:
2174: static int alrmser (i)
2175: int i;
2176: {
2177: longjmp (peerenv, DONE);
2178: }
2179:
2180: /* */
2181:
2182: static int ttyNaux (cmdp, s)
2183: register struct Cmd *cmdp;
2184: char *s;
2185: {
2186: struct record rcs,
2187: *rc = &rcs;
2188:
2189: initrc (rc);
2190:
2191: if (cmdp && init_io (cmdp, vmh) == NOTOK)
2192: return NOTOK;
2193:
2194: if (!fmsh)
2195: (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
2196:
2197: vmhtty = NOTOK;
2198: switch (rc2rc (RC_TTY, s ? strlen (s) : 0, s, rc)) {
2199: case RC_ACK:
2200: vmhtty = OK; /* fall */
2201: case RC_ERR:
2202: break;
2203:
2204: case RC_XXX:
2205: padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
2206:
2207: default:
2208: (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
2209: done (1); /* NOTREACHED */
2210: }
2211:
2212: #ifdef SIGTSTP
2213: (void) signal (SIGTSTP, tstat);
2214: #endif SIGTSTP
2215: return vmhtty;
2216: }
2217:
2218: /* */
2219:
2220: static int ttyR (cmdp)
2221: register struct Cmd *cmdp;
2222: {
2223: struct record rcs,
2224: *rc = &rcs;
2225:
2226: #ifdef SIGTSTP
2227: (void) signal (SIGTSTP, SIG_IGN);
2228: #endif SIGTSTP
2229:
2230: if (vmhtty != OK)
2231: return NOTOK;
2232:
2233: initrc (rc);
2234:
2235: if (cmdp)
2236: fin_io (cmdp, 0);
2237:
2238: vmhtty = NOTOK;
2239: switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
2240: case RC_ACK:
2241: (void) rc2peer (RC_EOF, 0, NULLCP);
2242: return OK;
2243:
2244: case RC_XXX:
2245: padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
2246:
2247: default:
2248: (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
2249: done (1); /* NOTREACHED */
2250: }
2251: }
2252:
2253: /* */
2254:
2255: static int winN (cmdp, n, eof)
2256: register struct Cmd *cmdp;
2257: int n,
2258: eof;
2259: {
2260: int i,
2261: pd[2];
2262: char buffer[BUFSIZ];
2263: struct record rcs,
2264: *rc = &rcs;
2265:
2266: if (vmhpid == NOTOK)
2267: return OK;
2268:
2269: initrc (rc);
2270:
2271: if (!fmsh)
2272: (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
2273:
2274: vmhpid = OK;
2275:
2276: (void) sprintf (buffer, "%d", n);
2277: switch (str2rc (RC_WIN, buffer, rc)) {
2278: case RC_ACK:
2279: break;
2280:
2281: case RC_ERR:
2282: return NOTOK;
2283:
2284: case RC_XXX:
2285: padios (NULLCP, "%s", rc -> rc_data);
2286:
2287: default:
2288: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2289: done (1);
2290: }
2291:
2292: if (pipe (pd) == NOTOK) {
2293: (void) err2peer (RC_ERR, "pipe", "unable to");
2294: return NOTOK;
2295: }
2296:
2297: switch (vmhpid = fork ()) {
2298: case NOTOK:
2299: (void) err2peer (RC_ERR, "fork", "unable to");
2300: (void) close (pd[0]);
2301: (void) close (pd[1]);
2302: return NOTOK;
2303:
2304: case OK:
2305: (void) close (pd[1]);
2306: (void) signal (SIGPIPE, SIG_IGN);
2307: while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
2308: switch (rc2rc (RC_DATA, i, buffer, rc)) {
2309: case RC_ACK:
2310: break;
2311:
2312: case RC_ERR:
2313: _exit (1);
2314:
2315: case RC_XXX:
2316: advise (NULLCP, "%s", rc -> rc_data);
2317: _exit (2);
2318:
2319: default:
2320: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2321: _exit (2);
2322: }
2323: if (i == OK)
2324: switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
2325: case RC_ACK:
2326: if (eof)
2327: (void) rc2peer (RC_EOF, 0, NULLCP);
2328: i = 0;
2329: break;
2330:
2331: case RC_XXX:
2332: advise (NULLCP, "%s", rc -> rc_data);
2333: i = 2;
2334: break;
2335:
2336: default:
2337: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2338: i = 2;
2339: break;
2340: }
2341: if (i == NOTOK)
2342: (void) err2peer (RC_ERR, "pipe", "error reading from");
2343: (void) close (pd[0]);
2344: _exit (i != NOTOK ? i : 1);
2345:
2346: default:
2347: if ((vmhfd0 = dup (fileno (stdin))) == NOTOK)
2348: padios ("standard input", "unable to dup");
2349: if ((vmhfd1 = dup (fileno (stdout))) == NOTOK)
2350: padios ("standard output", "unable to dup");
2351: if ((vmhfd2 = dup (fileno (stderr))) == NOTOK)
2352: padios ("diagnostic output", "unable to dup");
2353:
2354: (void) close (0);
2355: if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
2356: (void) dup2 (i, fileno (stdin));
2357: (void) close (i);
2358: }
2359:
2360: (void) fflush (stdout);
2361: if (dup2 (pd[1], fileno (stdout)) == NOTOK)
2362: padios ("standard output", "unable to dup2");
2363: clearerr (stdout);
2364:
2365: (void) fflush (stderr);
2366: if (dup2 (pd[1], fileno (stderr)) == NOTOK)
2367: padios ("diagnostic output", "unable to dup2");
2368: clearerr (stderr);
2369:
2370: if (cmdp && init_io (cmdp, 0) == NOTOK)
2371: return NOTOK;
2372: pstat = signal (SIGPIPE, pipeser);
2373: broken_pipe = 1;
2374:
2375: (void) close (pd[0]);
2376: (void) close (pd[1]);
2377:
2378: return vmhpid;
2379: }
2380: }
2381:
2382: /* */
2383:
2384: static int winR (cmdp)
2385: register struct Cmd *cmdp;
2386: {
2387: int status;
2388:
2389: if (vmhpid <= OK)
2390: return NOTOK;
2391:
2392: if (cmdp)
2393: fin_io (cmdp, 0);
2394:
2395: if (dup2 (vmhfd0, fileno (stdin)) == NOTOK)
2396: padios ("standard input", "unable to dup2");
2397: clearerr (stdin);
2398: (void) close (vmhfd0);
2399:
2400: (void) fflush (stdout);
2401: if (dup2 (vmhfd1, fileno (stdout)) == NOTOK)
2402: padios ("standard output", "unable to dup2");
2403: clearerr (stdout);
2404: (void) close (vmhfd1);
2405:
2406: (void) fflush (stderr);
2407: if (dup2 (vmhfd2, fileno (stderr)) == NOTOK)
2408: padios ("diagnostic output", "unable to dup2");
2409: clearerr (stderr);
2410: (void) close (vmhfd2);
2411:
2412: (void) signal (SIGPIPE, pstat);
2413:
2414: if ((status = pidwait (vmhpid, OK)) == 2)
2415: done (1);
2416:
2417: vmhpid = OK;
2418: return (status == 0 ? OK : NOTOK);
2419: }
2420:
2421: /* */
2422:
2423: static int winX (n)
2424: int n;
2425: {
2426: int i,
2427: pid,
2428: pd[2];
2429: char buffer[BUFSIZ];
2430: struct record rcs,
2431: *rc = &rcs;
2432:
2433: initrc (rc);
2434:
2435: if (!fmsh)
2436: (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
2437:
2438: (void) sprintf (buffer, "%d", n);
2439: switch (str2rc (RC_WIN, buffer, rc)) {
2440: case RC_ACK:
2441: break;
2442:
2443: case RC_ERR:
2444: return NOTOK;
2445:
2446: case RC_XXX:
2447: padios (NULLCP, "%s", rc -> rc_data);
2448:
2449: default:
2450: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2451: done (1);
2452: }
2453:
2454: if (pipe (pd) == NOTOK) {
2455: (void) err2peer (RC_ERR, "pipe", "unable to");
2456: return NOTOK;
2457: }
2458:
2459: switch (pid = fork ()) {
2460: case NOTOK:
2461: (void) err2peer (RC_ERR, "fork", "unable to");
2462: (void) close (pd[0]);
2463: (void) close (pd[1]);
2464: return NOTOK;
2465:
2466: case OK:
2467: (void) close (fileno (stdin));
2468: if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
2469: (void) dup2 (i, fileno (stdin));
2470: (void) close (i);
2471: }
2472: (void) dup2 (pd[1], fileno (stdout));
2473: (void) dup2 (pd[1], fileno (stderr));
2474: (void) close (pd[0]);
2475: (void) close (pd[1]);
2476: vmhpid = NOTOK;
2477: return OK;
2478:
2479: default:
2480: (void) close (pd[1]);
2481: while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
2482: switch (rc2rc (RC_DATA, i, buffer, rc)) {
2483: case RC_ACK:
2484: break;
2485:
2486: case RC_ERR:
2487: (void) close (pd[0]);
2488: (void) pidwait (pid, OK);
2489: return NOTOK;
2490:
2491: case RC_XXX:
2492: padios (NULLCP, "%s", rc -> rc_data);
2493:
2494: default:
2495: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2496: done (1);
2497: }
2498: if (i == OK)
2499: switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
2500: case RC_ACK:
2501: break;
2502:
2503: case RC_XXX:
2504: padios (NULLCP, "%s", rc -> rc_data);
2505:
2506: default:
2507: (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
2508: done (1);
2509: }
2510: if (i == NOTOK)
2511: (void) err2peer (RC_ERR, "pipe", "error reading from");
2512:
2513: (void) close (pd[0]);
2514: (void) pidwait (pid, OK);
2515: return (i != NOTOK ? pid : NOTOK);
2516: }
2517: }
2518:
2519: /* */
2520:
2521: /* VARARGS2 */
2522:
2523: void padios (what, fmt, a, b, c, d, e, f)
2524: char *what,
2525: *fmt,
2526: *a,
2527: *b,
2528: *c,
2529: *d,
2530: *e,
2531: *f;
2532: {
2533: if (vmh) {
2534: (void) err2peer (RC_FIN, what, fmt, a, b, c, d, e, f);
2535: (void) rcdone ();
2536: }
2537: else
2538: advise (what, fmt, a, b, c, d, e, f);
2539:
2540: done (1);
2541: }
2542:
2543:
2544: /* VARARGS2 */
2545:
2546: void padvise (what, fmt, a, b, c, d, e, f)
2547: char *what,
2548: *fmt,
2549: *a,
2550: *b,
2551: *c,
2552: *d,
2553: *e,
2554: *f;
2555: {
2556: if (vmh)
2557: (void) err2peer (RC_ERR, what, fmt, a, b, c, d, e, f);
2558: else
2559: advise (what, fmt, a, b, c, d, e, f);
2560: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.