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