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