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: }