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