|
|
1.1 ! root 1: /* vmh.c - visual front-end to mh */ ! 2: ! 3: /* TODO: ! 4: Pass signals to client during execution ! 5: ! 6: Get stand-alone SO/SE/CE to work under #ifdef SYS5 ! 7: ! 8: Figure out a way for the user to say how big the Scan/Display ! 9: windows should be. ! 10: ! 11: If curses ever gets fixed, then XYZ code can be removed ! 12: */ ! 13: ! 14: #include <curses.h> ! 15: #undef OK /* tricky */ ! 16: #include "../h/mh.h" ! 17: #include "../h/vmhsbr.h" ! 18: #include <ctype.h> ! 19: #include <errno.h> ! 20: #include <setjmp.h> ! 21: #include <signal.h> ! 22: #ifndef sigmask ! 23: #define sigmask(s) (1 << ((s) - 1)) ! 24: #endif not sigmask ! 25: #ifndef BSD42 ! 26: struct iovec { ! 27: char *iov_base; ! 28: int iov_len; ! 29: }; ! 30: #else BSD42 ! 31: #include <sys/types.h> ! 32: #include <sys/uio.h> ! 33: #endif BSD42 ! 34: ! 35: #define ALARM ((unsigned int) 10) ! 36: #define PAUSE ((unsigned int) 2) ! 37: ! 38: #define abs(a) ((a) > 0 ? (a) : -(a)) ! 39: #define SMALLMOVE 1 ! 40: #define LARGEMOVE 10 ! 41: ! 42: ! 43: #define XYZ /* XXX */ ! 44: ! 45: /* */ ! 46: ! 47: static struct swit switches[] = { ! 48: #define PRMPTSW 0 ! 49: "prompt string", 6, ! 50: ! 51: #define PROGSW 1 ! 52: "vmhproc program", 7, ! 53: #define NPROGSW 2 ! 54: "novmhproc", 9, ! 55: ! 56: #define HELPSW 3 ! 57: "help", 4, ! 58: ! 59: NULL, NULL ! 60: }; ! 61: ! 62: /* */ ! 63: /* PEERS */ ! 64: static int PEERpid = NOTOK; ! 65: ! 66: static jmp_buf PEERctx; ! 67: ! 68: ! 69: /* WINDOWS */ ! 70: static char *myprompt = "(%s) "; ! 71: ! 72: static WINDOW *Scan; ! 73: static WINDOW *Status; ! 74: static WINDOW *Display; ! 75: static WINDOW *Command; ! 76: ! 77: #define NWIN 3 ! 78: static int numwins; ! 79: WINDOW *windows[NWIN + 1]; ! 80: ! 81: ! 82: /* LINES */ ! 83: ! 84: struct line { ! 85: int l_no; ! 86: char *l_buf; ! 87: struct line *l_prev; ! 88: struct line *l_next; ! 89: }; ! 90: ! 91: static struct line *lhead = NULL; ! 92: static struct line *ltop = NULL; ! 93: static struct line *ltail = NULL; ! 94: ! 95: static int did_less = 0; ! 96: static int smallmove = SMALLMOVE; ! 97: static int largemove = LARGEMOVE; ! 98: ! 99: ! 100: /* TTYS */ ! 101: ! 102: static int tty_ready = NOTOK; ! 103: ! 104: static int intrc; ! 105: #ifndef SYS5 ! 106: #define ERASE sg.sg_erase ! 107: #define KILL sg.sg_kill ! 108: static struct sgttyb sg; ! 109: ! 110: #define EOFC tc.t_eofc ! 111: #define INTR tc.t_intrc ! 112: static struct tchars tc; ! 113: #else SYS5 ! 114: #define ERASE sg.c_cc[VERASE] ! 115: #define KILL sg.c_cc[VKILL] ! 116: #define EOFC sg.c_cc[VEOF] ! 117: #define INTR sg.c_cc[VINTR] ! 118: static struct termio sg; ! 119: #endif SYS5 ! 120: ! 121: #ifndef TIOCGLTC ! 122: #define WERASC ('W' & 037) ! 123: #else TIOCGLTC ! 124: #define WERASC ltc.t_werasc ! 125: static struct ltchars ltc; ! 126: #endif TIOCGLTC ! 127: ! 128: ! 129: #ifndef SYS5 ! 130: int _putchar (); ! 131: #endif not SYS5 ! 132: char *tgoto (); ! 133: ! 134: extern int errno; ! 135: extern int sys_nerr; ! 136: extern char *sys_errlist[]; ! 137: ! 138: static int PEERinit(), pINI(), pLOOP(), pTTY(), pWIN(), pWINaux(), pFIN(), ! 139: WINinit(), WINgetstr(), WINwritev(), WINless(), WINputc(), ladvance(), ! 140: lretreat(), lgo(), TTYinit(), ALRMser(), PIPEser(), SIGser(), TSTPser(); ! 141: static void vmh(), lreset(), linsert(), TTYon(), TTYoff(), foreground(), ! 142: sideground(), adorn(); ! 143: ! 144: ! 145: /* */ ! 146: ! 147: /* ARGSUSED */ ! 148: ! 149: main(argc, argv) ! 150: int argc; ! 151: char *argv[]; ! 152: { ! 153: int vecp = 1, ! 154: nprog = 0; ! 155: char *cp, ! 156: buffer[BUFSIZ], ! 157: **ap, ! 158: **argp, ! 159: *arguments[MAXARGS], ! 160: *vec[MAXARGS]; ! 161: ! 162: invo_name = r1bindex (argv[0], '/'); ! 163: if ((cp = m_find (invo_name)) != NULL) { ! 164: ap = brkstring (cp = getcpy (cp), " ", "\n"); ! 165: ap = copyip (ap, arguments); ! 166: } ! 167: else ! 168: ap = arguments; ! 169: (void) copyip (argv + 1, ap); ! 170: argp = arguments; ! 171: ! 172: /* */ ! 173: ! 174: while (cp = *argp++) ! 175: if (*cp == '-') ! 176: switch (smatch (++cp, switches)) { ! 177: case AMBIGSW: ! 178: ambigsw (cp, switches); ! 179: done (1); ! 180: case UNKWNSW: ! 181: vec[vecp++] = --cp; ! 182: continue; ! 183: case HELPSW: ! 184: (void) sprintf (buffer, "%s [switches for vmhproc]", ! 185: invo_name); ! 186: help (buffer, switches); ! 187: done (1); ! 188: ! 189: case PRMPTSW: ! 190: if (!(myprompt = *argp++) || *myprompt == '-') ! 191: adios (NULLCP, "missing argument to %s", argp[-2]); ! 192: continue; ! 193: ! 194: case PROGSW: ! 195: if (!(vmhproc = *argp++) || *vmhproc == '-') ! 196: adios (NULLCP, "missing argument to %s", argp[-2]); ! 197: continue; ! 198: case NPROGSW: ! 199: nprog++; ! 200: continue; ! 201: } ! 202: else ! 203: vec[vecp++] = cp; ! 204: ! 205: /* */ ! 206: ! 207: if (TTYinit (nprog) == NOTOK || WINinit (nprog) == NOTOK) { ! 208: vec[vecp] = NULL; ! 209: ! 210: vec[0] = r1bindex (vmhproc, '/'); ! 211: execvp (vmhproc, vec); ! 212: adios (vmhproc, "unable to exec"); ! 213: } ! 214: TTYoff (); ! 215: (void) PEERinit (vecp, vec); ! 216: TTYon (); ! 217: ! 218: vmh (); ! 219: ! 220: done (0); ! 221: } ! 222: ! 223: /* */ ! 224: ! 225: static void ! 226: vmh() ! 227: { ! 228: char buffer[BUFSIZ]; ! 229: ! 230: for (;;) { ! 231: (void) pLOOP (RC_QRY, NULLCP); ! 232: ! 233: wmove (Command, 0, 0); ! 234: wprintw (Command, myprompt, invo_name); ! 235: wclrtoeol (Command); ! 236: wrefresh (Command); ! 237: ! 238: switch (WINgetstr (Command, buffer)) { ! 239: case NOTOK: ! 240: break; ! 241: ! 242: case OK: ! 243: done (0); /* NOTREACHED */ ! 244: ! 245: default: ! 246: if (*buffer) ! 247: (void) pLOOP (RC_CMD, buffer); ! 248: break; ! 249: } ! 250: } ! 251: } ! 252: ! 253: /* PEERS */ ! 254: ! 255: static int ! 256: PEERinit(vecp, vec) ! 257: int vecp; ! 258: char *vec[]; ! 259: { ! 260: int pfd0[2], ! 261: pfd1[2]; ! 262: char buf1[BUFSIZ], ! 263: buf2[BUFSIZ]; ! 264: ! 265: if (pipe (pfd0) == NOTOK || pipe (pfd1) == NOTOK) ! 266: adios ("pipe", "unable to"); ! 267: switch (PEERpid = vfork ()) { ! 268: case NOTOK: ! 269: adios ("vfork", "unable to");/* NOTREACHED */ ! 270: ! 271: case OK: ! 272: (void) close (pfd0[0]); ! 273: (void) close (pfd1[1]); ! 274: ! 275: vec[vecp++] = "-vmhread"; ! 276: (void) sprintf (buf1, "%d", pfd1[0]); ! 277: vec[vecp++] = buf1; ! 278: vec[vecp++] = "-vmhwrite"; ! 279: (void) sprintf (buf2, "%d", pfd0[1]); ! 280: vec[vecp++] = buf2; ! 281: vec[vecp] = NULL; ! 282: ! 283: (void) signal (SIGINT, SIG_DFL); ! 284: (void) signal (SIGQUIT, SIG_DFL); ! 285: ! 286: vec[0] = r1bindex (vmhproc, '/'); ! 287: execvp (vmhproc, vec); ! 288: perror (vmhproc); ! 289: _exit (-1); /* NOTREACHED */ ! 290: ! 291: default: ! 292: (void) close (pfd0[1]); ! 293: (void) close (pfd1[0]); ! 294: ! 295: (void) rcinit (pfd0[0], pfd1[1]); ! 296: return pINI (); ! 297: } ! 298: } ! 299: ! 300: /* */ ! 301: ! 302: static int ! 303: pINI() ! 304: { ! 305: register char *bp; ! 306: char buffer[BUFSIZ]; ! 307: struct record rcs; ! 308: register struct record *rc = &rcs; ! 309: register WINDOW **w; ! 310: ! 311: initrc (rc); ! 312: ! 313: bp = buffer; ! 314: (void) sprintf (bp, "%d %d", RC_VRSN, numwins); ! 315: bp += strlen (bp); ! 316: for (w = windows; *w; w++) { ! 317: (void) sprintf (bp, " %d", (*w) -> _maxy); ! 318: bp += strlen (bp); ! 319: } ! 320: ! 321: switch (str2rc (RC_INI, buffer, rc)) { ! 322: case RC_ACK: ! 323: return OK; ! 324: ! 325: case RC_ERR: ! 326: if (rc -> rc_len) ! 327: adios (NULLCP, "%s", rc -> rc_data); ! 328: else ! 329: adios (NULLCP, "pINI peer error"); ! 330: ! 331: case RC_XXX: ! 332: adios (NULLCP, "%s", rc -> rc_data); ! 333: ! 334: default: ! 335: adios (NULLCP, "pINI protocol screw-up"); ! 336: } ! 337: /* NOTREACHED */ ! 338: } ! 339: ! 340: /* */ ! 341: ! 342: static int ! 343: pLOOP(code, str) ! 344: char code, *str; ! 345: { ! 346: int i; ! 347: struct record rcs; ! 348: register struct record *rc = &rcs; ! 349: ! 350: initrc (rc); ! 351: ! 352: (void) str2peer (code, str); ! 353: for (;;) ! 354: switch (peer2rc (rc)) { ! 355: case RC_TTY: ! 356: if (pTTY (rc) == NOTOK) ! 357: return NOTOK; ! 358: break; ! 359: ! 360: case RC_WIN: ! 361: if (sscanf (rc -> rc_data, "%d", &i) != 1 ! 362: || i <= 0 ! 363: || i > numwins) { ! 364: (void) fmt2peer (RC_ERR, "no such window \"%s\"", ! 365: rc -> rc_data); ! 366: return NOTOK; ! 367: } ! 368: if (pWIN (windows[i - 1]) == NOTOK) ! 369: return NOTOK; ! 370: break; ! 371: ! 372: case RC_EOF: ! 373: return OK; ! 374: ! 375: case RC_ERR: ! 376: if (rc -> rc_len) ! 377: adorn (NULLCP, "%s", rc -> rc_data); ! 378: else ! 379: adorn (NULLCP, "pLOOP(%s) peer error", ! 380: code == RC_QRY ? "QRY" : "CMD"); ! 381: return NOTOK; ! 382: ! 383: case RC_FIN: ! 384: if (rc -> rc_len) ! 385: adorn (NULLCP, "%s", rc -> rc_data); ! 386: (void) rcdone (); ! 387: i = pidwait (PEERpid, OK); ! 388: PEERpid = NOTOK; ! 389: done (i); ! 390: ! 391: case RC_XXX: ! 392: adios (NULLCP, "%s", rc -> rc_data); ! 393: ! 394: default: ! 395: adios (NULLCP, "pLOOP(%s) protocol screw-up", ! 396: code == RC_QRY ? "QRY" : "CMD"); ! 397: } ! 398: } ! 399: ! 400: /* */ ! 401: ! 402: static int ! 403: pTTY(r) ! 404: register struct record *r; ! 405: { ! 406: SIGDECL (*hstat)(), (*istat)(), (*qstat)(), (*tstat)(); ! 407: struct record rcs; ! 408: register struct record *rc = &rcs; ! 409: ! 410: initrc (rc); ! 411: ! 412: TTYoff (); ! 413: ! 414: hstat = signal (SIGHUP, SIG_IGN); ! 415: istat = signal (SIGINT, SIG_IGN); ! 416: qstat = signal (SIGQUIT, SIG_IGN); ! 417: tstat = signal (SIGTERM, SIG_IGN); ! 418: ! 419: (void) rc2rc (RC_ACK, 0, NULLCP, rc); ! 420: ! 421: (void) signal (SIGHUP, hstat); ! 422: (void) signal (SIGINT, istat); ! 423: (void) signal (SIGQUIT, qstat); ! 424: (void) signal (SIGTERM, tstat); ! 425: ! 426: TTYon (); ! 427: ! 428: if (r -> rc_len && strcmp (r -> rc_data, "FAST") == 0) ! 429: goto no_refresh; ! 430: ! 431: #ifdef SIGTSTP ! 432: (void) signal (SIGTSTP, SIG_IGN); ! 433: #endif SIGTSTP ! 434: #ifndef SYS5 ! 435: if (SO) ! 436: tputs (SO, 0, _putchar); ! 437: #endif not SYS5 ! 438: fprintf (stdout, "Type any key to continue... "); ! 439: (void) fflush (stdout); ! 440: #ifndef SYS5 ! 441: if (SE) ! 442: tputs (SE, 0, _putchar); ! 443: #endif not SYS5 ! 444: (void) getc (stdin); ! 445: #ifdef SIGTSTP ! 446: (void) signal (SIGTSTP, TSTPser); ! 447: #endif SIGTSTP ! 448: ! 449: wrefresh (curscr); ! 450: ! 451: no_refresh: ; ! 452: switch (rc -> rc_type) { ! 453: case RC_EOF: ! 454: (void) rc2peer (RC_ACK, 0, NULLCP); ! 455: return OK; ! 456: ! 457: case RC_ERR: ! 458: if (rc -> rc_len) ! 459: adorn (NULLCP, "%s", rc -> rc_data); ! 460: else ! 461: adorn (NULLCP, "pTTY peer error"); ! 462: return NOTOK; ! 463: ! 464: case RC_XXX: ! 465: adios (NULLCP, "%s", rc -> rc_data); ! 466: ! 467: default: ! 468: adios (NULLCP, "pTTY protocol screw-up"); ! 469: } ! 470: /* NOTREACHED */ ! 471: } ! 472: ! 473: /* */ ! 474: ! 475: static int ! 476: pWIN(w) ! 477: register WINDOW *w; ! 478: { ! 479: int i; ! 480: ! 481: did_less = 0; ! 482: if ((i = pWINaux (w)) == OK && did_less) ! 483: (void) WINless (w, 1); ! 484: ! 485: lreset (); ! 486: ! 487: return i; ! 488: } ! 489: ! 490: /* */ ! 491: ! 492: static int ! 493: pWINaux(w) ! 494: register WINDOW *w; ! 495: { ! 496: register int n; ! 497: int eol; ! 498: register char c, ! 499: *bp; ! 500: struct record rcs; ! 501: register struct record *rc = &rcs; ! 502: ! 503: initrc (rc); ! 504: ! 505: werase (w); ! 506: wmove (w, 0, 0); ! 507: #ifdef XYZ ! 508: if (w == Status) ! 509: wstandout (w); ! 510: #endif XYZ ! 511: ! 512: for (eol = 0;;) ! 513: switch (rc2rc (RC_ACK, 0, NULLCP, rc)) { ! 514: case RC_DATA: ! 515: if (eol && WINputc (w, '\n') == ERR && WINless (w, 0)) ! 516: goto flush; ! 517: for (bp = rc -> rc_data, n = rc -> rc_len; n-- > 0; ) { ! 518: if ((c = *bp++) == '\n') ! 519: linsert (w); ! 520: if (WINputc (w, c) == ERR) ! 521: if (n == 0 && c == '\n') ! 522: eol++; ! 523: else ! 524: if (WINless (w, 0)) { ! 525: flush: ; ! 526: (void) fmt2peer (RC_ERR, "flush window"); ! 527: #ifdef XYZ /* should NEVER happen... */ ! 528: if (w == Status) ! 529: wstandend (w); ! 530: #endif XYZ ! 531: wrefresh (w); ! 532: return NOTOK; ! 533: } ! 534: } ! 535: break; ! 536: ! 537: case RC_EOF: ! 538: (void) rc2peer (RC_ACK, 0, NULLCP); ! 539: #ifdef XYZ ! 540: if (w == Status) ! 541: wstandend (w); ! 542: #endif XYZ ! 543: wrefresh (w); ! 544: return OK; ! 545: ! 546: case RC_ERR: ! 547: if (rc -> rc_len) ! 548: adorn (NULLCP, "%s", rc -> rc_data); ! 549: else ! 550: adorn (NULLCP, "pWIN peer error"); ! 551: return NOTOK; ! 552: ! 553: case RC_XXX: ! 554: adios (NULLCP, "%s", rc -> rc_data); ! 555: ! 556: default: ! 557: adios (NULLCP, "pWIN protocol screw-up"); ! 558: } ! 559: /* NOTREACHED */ ! 560: } ! 561: ! 562: /* */ ! 563: ! 564: static int ! 565: pFIN() ! 566: { ! 567: int status; ! 568: ! 569: if (PEERpid <= OK) ! 570: return OK; ! 571: ! 572: (void) rc2peer (RC_FIN, 0, NULLCP); ! 573: (void) rcdone (); ! 574: ! 575: switch (setjmp (PEERctx)) { ! 576: case OK: ! 577: (void) signal (SIGALRM, ALRMser); ! 578: (void) alarm (ALARM); ! 579: ! 580: status = pidwait (PEERpid, OK); ! 581: ! 582: (void) alarm (0); ! 583: break; ! 584: ! 585: default: ! 586: (void) kill (PEERpid, SIGKILL); ! 587: status = NOTOK; ! 588: break; ! 589: } ! 590: PEERpid = NOTOK; ! 591: ! 592: return status; ! 593: } ! 594: ! 595: /* WINDOWS */ ! 596: ! 597: static int ! 598: WINinit(nprog) ! 599: { ! 600: register int lines, ! 601: top, ! 602: bottom; ! 603: ! 604: foreground (); ! 605: if (initscr () == ERR) ! 606: if (nprog) ! 607: return NOTOK; ! 608: else ! 609: adios (NULLCP, "could not initialize terminal"); ! 610: #ifdef SIGTSTP ! 611: (void) signal (SIGTSTP, SIG_DFL); ! 612: #endif SIGTSTP ! 613: sideground (); ! 614: ! 615: if (CM == NULL) ! 616: if (nprog) ! 617: return NOTOK; ! 618: else ! 619: adios (NULLCP, ! 620: "sorry, your terminal isn't powerful enough to run %s", ! 621: invo_name); ! 622: ! 623: #ifndef SYS5 ! 624: if (tgetflag ("xt") || tgetnum ("sg") > 0) ! 625: SO = SE = US = UE = NULL; ! 626: #endif not SYS5 ! 627: ! 628: if ((lines = LINES - 1) < 11) ! 629: adios (NULLCP, "screen too small"); ! 630: if ((top = lines / 3 + 1) > LINES / 4 + 2) ! 631: top--; ! 632: bottom = lines - top - 2; ! 633: ! 634: numwins = 0; ! 635: Scan = windows[numwins++] = newwin (top, COLS, 0, 0); ! 636: Status = windows[numwins++] = newwin (1, COLS, top, 0); ! 637: #ifndef XYZ ! 638: wstandout (Status); ! 639: #endif XYZ ! 640: Display = windows[numwins++] = newwin (bottom, COLS, top + 1, 0); ! 641: Command = newwin (1, COLS - 1, top + 1 + bottom, 0); ! 642: windows[numwins] = NULL; ! 643: ! 644: largemove = Display -> _maxy / 2 + 2; ! 645: return OK; ! 646: } ! 647: ! 648: /* */ ! 649: ! 650: static int ! 651: WINgetstr(w, buffer) ! 652: register WINDOW *w; ! 653: char *buffer; ! 654: { ! 655: register int c; ! 656: register char *bp; ! 657: ! 658: bp = buffer; ! 659: *bp = NULL; ! 660: ! 661: for (;;) { ! 662: switch (c = toascii (wgetch (w))) { ! 663: case ERR: ! 664: adios (NULLCP, "wgetch lost"); ! 665: ! 666: case '\f': ! 667: wrefresh (curscr); ! 668: break; ! 669: ! 670: case '\r': ! 671: case '\n': ! 672: *bp = NULL; ! 673: if (bp > buffer) { ! 674: leaveok (curscr, FALSE); ! 675: wmove (w, 0, w -> _curx - (bp - buffer)); ! 676: wrefresh (w); ! 677: leaveok (curscr, TRUE); ! 678: } ! 679: return DONE; ! 680: ! 681: default: ! 682: if (c == intrc) { ! 683: wprintw (w, " "); ! 684: wstandout (w); ! 685: wprintw (w, "Interrupt"); ! 686: wstandend (w); ! 687: wrefresh (w); ! 688: *buffer = NULL; ! 689: return NOTOK; ! 690: } ! 691: if (c == EOFC) { ! 692: if (bp <= buffer) ! 693: return OK; ! 694: break; ! 695: } ! 696: if (c == ERASE) { ! 697: if (bp <= buffer) ! 698: continue; ! 699: bp--, w -> _curx--; ! 700: wclrtoeol (w); ! 701: break; ! 702: } ! 703: if (c == KILL) { ! 704: if (bp <= buffer) ! 705: continue; ! 706: w -> _curx -= bp - buffer; ! 707: bp = buffer; ! 708: wclrtoeol (w); ! 709: break; ! 710: } ! 711: if (c == WERASC) { ! 712: if (bp <= buffer) ! 713: continue; ! 714: do { ! 715: bp--, w -> _curx--; ! 716: } while (isspace (*bp) && bp > buffer); ! 717: ! 718: if (bp > buffer) { ! 719: do { ! 720: bp--, w -> _curx--; ! 721: } while (!isspace (*bp) && bp > buffer); ! 722: if (isspace (*bp)) ! 723: bp++, w -> _curx++; ! 724: } ! 725: wclrtoeol (w); ! 726: break; ! 727: } ! 728: ! 729: if (c >= ' ' && c < '\177') ! 730: (void) waddch (w, *bp++ = c); ! 731: break; ! 732: } ! 733: ! 734: wrefresh (w); ! 735: } ! 736: } ! 737: ! 738: /* */ ! 739: ! 740: static int ! 741: WINwritev(w, iov, n) ! 742: register WINDOW *w; ! 743: register struct iovec *iov; ! 744: register int n; ! 745: { ! 746: register int i; ! 747: ! 748: werase (w); ! 749: wmove (w, 0, 0); ! 750: for (i = 0; i < n; i++, iov++) ! 751: wprintw (w, "%*.*s", iov -> iov_len, iov -> iov_len, iov -> iov_base); ! 752: wrefresh (w); ! 753: ! 754: sleep (PAUSE); ! 755: ! 756: return OK; ! 757: } ! 758: ! 759: /* */ ! 760: ! 761: static struct { ! 762: char *h_msg; ! 763: int *h_val; ! 764: } hlpmsg[] = { ! 765: " forward backwards", NULL, ! 766: " ------- ---------", NULL, ! 767: "next screen SPACE", NULL, ! 768: "next %d line%s RETURN y", &smallmove, ! 769: "next %d line%s EOT u", &largemove, ! 770: "go g G", NULL, ! 771: "", NULL, ! 772: "refresh CTRL-L", NULL, ! 773: "quit q", NULL, ! 774: ! 775: NULL, NULL ! 776: }; ! 777: ! 778: /* */ ! 779: ! 780: static int ! 781: WINless(w, fin) ! 782: register WINDOW *w; ! 783: int fin; ! 784: { ! 785: register int c, ! 786: i, ! 787: n; ! 788: int nfresh, ! 789: #ifdef notdef ! 790: nlatch, ! 791: #endif notdef ! 792: nwait; ! 793: char *cp; ! 794: register struct line *lbottom; ! 795: ! 796: did_less++; ! 797: ! 798: cp = NULL; ! 799: #ifdef notdef ! 800: if (fin) ! 801: ltop = NULL; ! 802: #endif notdef ! 803: lbottom = NULL; ! 804: nfresh = 1; ! 805: nwait = 0; ! 806: wrefresh (w); ! 807: ! 808: for (;;) { ! 809: if (nfresh || nwait) { ! 810: nfresh = 0; ! 811: #ifdef notdef ! 812: nlatch = 1; ! 813: ! 814: once_only: ; ! 815: #endif notdef ! 816: werase (w); ! 817: wmove (w, 0, 0); ! 818: ! 819: if (ltop == NULL) ! 820: if (fin) { ! 821: (void) lgo (ltail -> l_no - w -> _maxy + 1); ! 822: if (ltop == NULL) ! 823: ltop = lhead; ! 824: } ! 825: else ! 826: ltop = lbottom && lbottom -> l_prev ? lbottom -> l_prev ! 827: : lbottom; ! 828: ! 829: for (lbottom = ltop; lbottom; lbottom = lbottom -> l_next) ! 830: if (waddstr (w, lbottom -> l_buf) == ERR ! 831: || waddch (w, '\n') == ERR) ! 832: break; ! 833: if (lbottom == NULL) ! 834: if (fin) { ! 835: #ifdef notdef ! 836: if (nlatch && (ltail -> l_no >= w -> _maxy)) { ! 837: (void) lgo (ltail -> l_no - w -> _maxy + 1); ! 838: nlatch = 0; ! 839: goto once_only; ! 840: } ! 841: #endif notdef ! 842: lbottom = ltail; ! 843: while (waddstr (w, "~\n") != ERR) ! 844: continue; ! 845: } ! 846: else { ! 847: wrefresh (w); ! 848: return 0; ! 849: } ! 850: ! 851: if (!nwait) ! 852: wrefresh (w); ! 853: } ! 854: ! 855: wmove (Command, 0, 0); ! 856: if (cp) { ! 857: wstandout (Command); ! 858: wprintw (Command, "%s", cp); ! 859: wstandend (Command); ! 860: cp = NULL; ! 861: } ! 862: else ! 863: wprintw (Command, fin ? "top:%d bot:%d end:%d" : "top:%d bot:%d", ! 864: ltop -> l_no, lbottom -> l_no, ltail -> l_no); ! 865: wprintw (Command, ">> "); ! 866: wclrtoeol (Command); ! 867: wrefresh (Command); ! 868: ! 869: c = toascii (wgetch (Command)); ! 870: ! 871: werase (Command); ! 872: wrefresh (Command); ! 873: ! 874: if (nwait) { ! 875: nwait = 0; ! 876: wrefresh (w); ! 877: } ! 878: ! 879: n = 0; ! 880: again: ; ! 881: switch (c) { ! 882: case ' ': ! 883: ltop = lbottom -> l_next; ! 884: nfresh++; ! 885: break; ! 886: ! 887: case '\r': ! 888: case '\n': ! 889: case 'e': ! 890: case 'j': ! 891: if (n) ! 892: smallmove = n; ! 893: if (ladvance (smallmove)) ! 894: nfresh++; ! 895: break; ! 896: ! 897: case 'y': ! 898: case 'k': ! 899: if (n) ! 900: smallmove = n; ! 901: if (lretreat (smallmove)) ! 902: nfresh++; ! 903: break; ! 904: ! 905: case 'd': ! 906: eof: ; ! 907: if (n) ! 908: largemove = n; ! 909: if (ladvance (largemove)) ! 910: nfresh++; ! 911: break; ! 912: ! 913: case 'u': ! 914: if (n) ! 915: largemove = n; ! 916: if (lretreat (largemove)) ! 917: nfresh++; ! 918: break; ! 919: ! 920: case 'g': ! 921: if (lgo (n ? n : 1)) ! 922: nfresh++; ! 923: break; ! 924: ! 925: case 'G': ! 926: if (lgo (n ? n : ltail -> l_no - w -> _maxy + 1)) ! 927: nfresh++; ! 928: break; ! 929: ! 930: case '\f': ! 931: case 'r': ! 932: wrefresh (curscr); ! 933: break; ! 934: ! 935: case 'h': ! 936: case '?': ! 937: werase (w); ! 938: wmove (w, 0, 0); ! 939: for (i = 0; hlpmsg[i].h_msg; i++) { ! 940: if (hlpmsg[i].h_val) ! 941: wprintw (w, hlpmsg[i].h_msg, *hlpmsg[i].h_val, ! 942: *hlpmsg[i].h_val != 1 ? "s" : ""); ! 943: else ! 944: (void) waddstr (w, hlpmsg[i].h_msg); ! 945: (void) waddch (w, '\n'); ! 946: } ! 947: wrefresh (w); ! 948: nwait++; ! 949: break; ! 950: ! 951: case 'q': ! 952: return 1; ! 953: ! 954: default: ! 955: if (c == EOFC) ! 956: goto eof; ! 957: ! 958: if (isdigit (c)) { ! 959: wmove (Command, 0, 0); ! 960: i = 0; ! 961: while (isdigit (c)) { ! 962: wprintw (Command, "%c", c); ! 963: wrefresh (Command); ! 964: i = i * 10 + c - '0'; ! 965: c = toascii (wgetch (Command)); ! 966: } ! 967: werase (Command); ! 968: wrefresh (Command); ! 969: ! 970: if (i > 0) { ! 971: n = i; ! 972: goto again; ! 973: } ! 974: cp = "bad number"; ! 975: } ! 976: else ! 977: cp = "not understood"; ! 978: break; ! 979: } ! 980: } ! 981: } ! 982: ! 983: /* */ ! 984: ! 985: ! 986: static int ! 987: WINputc(w, c) ! 988: register WINDOW *w; ! 989: register char c; ! 990: { ! 991: register int x, ! 992: y; ! 993: ! 994: if (w != Scan) ! 995: switch (c) { ! 996: default: ! 997: if (c < ' ' || c == '\177') ! 998: return (waddch (w, '^') != ERR ? waddch (w, c ^ 0100) ! 999: : ERR);/* else fall */ ! 1000: ! 1001: case '\t': ! 1002: case '\n': ! 1003: return waddch (w, c); ! 1004: } ! 1005: ! 1006: if ((x = w -> _curx) < 0 || x >= w -> _maxx ! 1007: || (y = w -> _cury) < 0 || y >= w -> _maxy) ! 1008: return DONE; ! 1009: ! 1010: switch (c) { ! 1011: case '\t': ! 1012: for (x = 8 - (x & 0x07); x > 0; x--) ! 1013: if (WINputc (w, ' ') == ERR) ! 1014: return ERR; ! 1015: break; ! 1016: ! 1017: case '\n': ! 1018: if (++y < w -> _maxy) ! 1019: (void) waddch (w, c); ! 1020: else ! 1021: wclrtoeol (w); ! 1022: break; ! 1023: ! 1024: default: ! 1025: if (c < ' ' || c == '\177') { ! 1026: if (WINputc (w, '^') == ERR || WINputc (w, c ^ 0100) == ERR) ! 1027: return ERR; ! 1028: break; ! 1029: } ! 1030: if (++x < w -> _maxx) ! 1031: (void) waddch (w, c); ! 1032: break; ! 1033: } ! 1034: return DONE; ! 1035: } ! 1036: ! 1037: /* LINES */ ! 1038: ! 1039: static void ! 1040: lreset() ! 1041: { ! 1042: register struct line *lp, ! 1043: *mp; ! 1044: ! 1045: for (lp = lhead; lp; lp = mp) { ! 1046: mp = lp -> l_next; ! 1047: free (lp -> l_buf); ! 1048: free ((char *) lp); ! 1049: } ! 1050: lhead = ltop = ltail = NULL; ! 1051: } ! 1052: ! 1053: ! 1054: static void ! 1055: linsert(w) ! 1056: WINDOW *w; ! 1057: { ! 1058: register char *cp; ! 1059: register struct line *lp; ! 1060: ! 1061: if ((lp = (struct line *) calloc ((unsigned) 1, sizeof *lp)) == NULL) ! 1062: adios (NULLCP, "unable to allocate line storage"); ! 1063: ! 1064: lp -> l_no = (ltail ? ltail -> l_no : 0) + 1; ! 1065: lp -> l_buf = getcpy (w -> _y[w -> _cury]); ! 1066: for (cp = lp -> l_buf + strlen (lp -> l_buf) - 1; cp >= lp -> l_buf; cp--) ! 1067: if (isspace (*cp)) ! 1068: *cp = NULL; ! 1069: else ! 1070: break; ! 1071: ! 1072: if (lhead == NULL) ! 1073: lhead = lp; ! 1074: if (ltop == NULL) ! 1075: ltop = lp; ! 1076: if (ltail) ! 1077: ltail -> l_next = lp; ! 1078: lp -> l_prev = ltail; ! 1079: ltail = lp; ! 1080: } ! 1081: ! 1082: /* */ ! 1083: ! 1084: static int ! 1085: ladvance(n) ! 1086: int n; ! 1087: { ! 1088: register int i; ! 1089: register struct line *lp; ! 1090: ! 1091: for (i = 0, lp = ltop; i < n && lp; i++, lp = lp -> l_next) ! 1092: continue; ! 1093: ! 1094: if (ltop == lp) ! 1095: return 0; ! 1096: ! 1097: ltop = lp; ! 1098: return 1; ! 1099: } ! 1100: ! 1101: ! 1102: static int ! 1103: lretreat(n) ! 1104: int n; ! 1105: { ! 1106: register int i; ! 1107: register struct line *lp; ! 1108: ! 1109: for (i = 0, lp = ltop; i < n && lp; i++, lp = lp -> l_prev) ! 1110: if (!lp -> l_prev) ! 1111: break; ! 1112: ! 1113: if (ltop == lp) ! 1114: return 0; ! 1115: ! 1116: ltop = lp; ! 1117: return 1; ! 1118: } ! 1119: ! 1120: /* */ ! 1121: ! 1122: static int ! 1123: lgo(n) ! 1124: int n; ! 1125: { ! 1126: register int i, ! 1127: j; ! 1128: register struct line *lp; ! 1129: ! 1130: if ((i = n - (lp = lhead) -> l_no) > (j = abs (n - ltop -> l_no))) ! 1131: i = j, lp = ltop; ! 1132: if (i > (j = abs (ltail -> l_no - n))) ! 1133: i = j, lp = ltail; ! 1134: ! 1135: if (n >= lp -> l_no) { ! 1136: for (; lp; lp = lp -> l_next) ! 1137: if (lp -> l_no == n) ! 1138: break; ! 1139: } ! 1140: else { ! 1141: for (; lp; lp = lp -> l_prev) ! 1142: if (lp -> l_no == n) ! 1143: break; ! 1144: if (!lp) ! 1145: lp = lhead; ! 1146: } ! 1147: ! 1148: if (ltop == lp) ! 1149: return 0; ! 1150: ! 1151: ltop = lp; ! 1152: return 1; ! 1153: } ! 1154: ! 1155: /* TTYS */ ! 1156: ! 1157: static int ! 1158: TTYinit(nprog) ! 1159: { ! 1160: if (!isatty (fileno (stdin)) || !isatty (fileno (stdout))) ! 1161: if (nprog) ! 1162: return NOTOK; ! 1163: else ! 1164: adios (NULLCP, "not a tty"); ! 1165: ! 1166: foreground (); ! 1167: #ifndef SYS5 ! 1168: if (ioctl (fileno (stdin), TIOCGETP, (char *) &sg) == NOTOK) ! 1169: adios ("failed", "ioctl TIOCGETP"); ! 1170: if (ioctl (fileno (stdin), TIOCGETC, (char *) &tc) == NOTOK) ! 1171: adios ("failed", "ioctl TIOCGETC"); ! 1172: #else SYS5 ! 1173: if (ioctl (fileno (stdin), TCGETA, &sg) == NOTOK) ! 1174: adios ("failed", "ioctl TCGETA"); ! 1175: #endif SYS5 ! 1176: #ifdef TIOCGLTC ! 1177: if (ioctl (fileno (stdin), TIOCGLTC, (char *) <c) == NOTOK) ! 1178: adios ("failed", "ioctl TIOCGLTC"); ! 1179: #endif TIOCGLTC ! 1180: intrc = INTR; ! 1181: sideground (); ! 1182: ! 1183: tty_ready = OK; ! 1184: ! 1185: (void) signal (SIGPIPE, PIPEser); ! 1186: ! 1187: return OK; ! 1188: } ! 1189: ! 1190: /* */ ! 1191: ! 1192: static void ! 1193: TTYon() ! 1194: { ! 1195: if (tty_ready == DONE) ! 1196: return; ! 1197: ! 1198: INTR = NOTOK; ! 1199: #ifndef SYS5 ! 1200: (void) ioctl (fileno (stdin), TIOCSETC, (char *) &tc); ! 1201: #else SYS5 ! 1202: (void) ioctl (fileno (stdin), TCSETA, &sg); ! 1203: #endif SYS5 ! 1204: ! 1205: (void) crmode (); ! 1206: (void) noecho (); ! 1207: (void) nonl (); ! 1208: scrollok (curscr, FALSE); ! 1209: ! 1210: discard (stdin); ! 1211: ! 1212: tty_ready = DONE; ! 1213: ! 1214: (void) signal (SIGHUP, SIGser); ! 1215: (void) signal (SIGINT, SIGser); ! 1216: (void) signal (SIGQUIT, SIGser); ! 1217: #ifdef SIGTSTP ! 1218: (void) signal (SIGTSTP, TSTPser); ! 1219: #endif SIGTSTP ! 1220: } ! 1221: ! 1222: /* */ ! 1223: ! 1224: static void ! 1225: TTYoff() ! 1226: { ! 1227: if (tty_ready == NOTOK) ! 1228: return; ! 1229: ! 1230: INTR = intrc; ! 1231: #ifndef SYS5 ! 1232: (void) ioctl (fileno (stdin), TIOCSETC, (char *) &tc); ! 1233: #else SYS5 ! 1234: (void) ioctl (fileno (stdin), TCSETA, &sg); ! 1235: #endif SYS5 ! 1236: ! 1237: leaveok (curscr, TRUE); ! 1238: mvcur (0, COLS - 1, LINES - 1, 0); ! 1239: endwin (); ! 1240: if (tty_ready == DONE) { ! 1241: #ifndef SYS5 ! 1242: if (CE) ! 1243: tputs (CE, 0, _putchar); ! 1244: else ! 1245: #endif SYS5 ! 1246: fprintf (stdout, "\r\n"); ! 1247: } ! 1248: (void) fflush (stdout); ! 1249: ! 1250: tty_ready = NOTOK; ! 1251: ! 1252: (void) signal (SIGHUP, SIG_DFL); ! 1253: (void) signal (SIGINT, SIG_DFL); ! 1254: (void) signal (SIGQUIT, SIG_DFL); ! 1255: #ifdef SIGTSTP ! 1256: (void) signal (SIGTSTP, SIG_DFL); ! 1257: #endif SIGTSTP ! 1258: } ! 1259: ! 1260: /* */ ! 1261: ! 1262: static void ! 1263: foreground() ! 1264: { ! 1265: #ifdef TIOCGPGRP ! 1266: int pgrp, ! 1267: tpgrp; ! 1268: SIGDECL (*tstat)(); ! 1269: ! 1270: if ((pgrp = getpgrp (0)) == NOTOK) ! 1271: adios ("process group", "unable to determine"); ! 1272: for (;;) { ! 1273: if (ioctl (fileno (stdin), TIOCGPGRP, (char *) &tpgrp) == NOTOK) ! 1274: adios ("tty's process group", "unable to determine"); ! 1275: if (pgrp == tpgrp) ! 1276: break; ! 1277: ! 1278: tstat = signal (SIGTTIN, SIG_DFL); ! 1279: (void) kill (0, SIGTTIN); ! 1280: (void) signal (SIGTTIN, tstat); ! 1281: } ! 1282: ! 1283: (void) signal (SIGTTIN, SIG_IGN); ! 1284: (void) signal (SIGTTOU, SIG_IGN); ! 1285: (void) signal (SIGTSTP, SIG_IGN); ! 1286: #endif TIOCGPGRP ! 1287: } ! 1288: ! 1289: static void ! 1290: sideground() ! 1291: { ! 1292: #ifdef TIOCGPGRP ! 1293: (void) signal (SIGTTIN, SIG_DFL); ! 1294: (void) signal (SIGTTOU, SIG_DFL); ! 1295: (void) signal (SIGTSTP, SIG_DFL); ! 1296: #endif TIOCGPGRP ! 1297: } ! 1298: ! 1299: /* SIGNALS */ ! 1300: ! 1301: /* ARGSUSED */ ! 1302: ! 1303: static int ! 1304: ALRMser(sig) ! 1305: int sig; ! 1306: { ! 1307: longjmp (PEERctx, DONE); ! 1308: } ! 1309: ! 1310: ! 1311: #ifdef BSD42 ! 1312: /* ARGSUSED */ ! 1313: #endif BSD42 ! 1314: ! 1315: static int ! 1316: PIPEser(sig) ! 1317: int sig; ! 1318: { ! 1319: #ifndef BSD42 ! 1320: (void) signal (sig, SIG_IGN); ! 1321: #endif BSD42 ! 1322: ! 1323: adios (NULLCP, "lost peer"); ! 1324: } ! 1325: ! 1326: ! 1327: #ifdef BSD42 ! 1328: /* ARGSUSED */ ! 1329: #endif BSD42 ! 1330: ! 1331: static int ! 1332: SIGser(sig) ! 1333: int sig; ! 1334: { ! 1335: #ifndef BSD42 ! 1336: (void) signal (sig, SIG_IGN); ! 1337: #endif BSD42 ! 1338: ! 1339: done (1); ! 1340: } ! 1341: ! 1342: ! 1343: #ifdef SIGTSTP ! 1344: static int ! 1345: TSTPser(sig) ! 1346: int sig; ! 1347: { ! 1348: tputs (tgoto (CM, 0, LINES - 1), 0, _putchar); ! 1349: (void) fflush (stdout); ! 1350: ! 1351: TTYoff (); ! 1352: #ifdef BSD42 ! 1353: (void) sigsetmask (sigblock (0) & ~sigmask (SIGTSTP)); ! 1354: #endif BSD42 ! 1355: ! 1356: (void) kill (getpid (), sig); ! 1357: ! 1358: #ifdef BSD42 ! 1359: (void) sigblock (sigmask (SIGTSTP)); ! 1360: #endif BSD42 ! 1361: TTYon (); ! 1362: ! 1363: wrefresh (curscr); ! 1364: } ! 1365: #endif SIGTSTP ! 1366: ! 1367: /* MISCELLANY */ ! 1368: ! 1369: void ! 1370: done (status) ! 1371: int status; ! 1372: { ! 1373: TTYoff (); ! 1374: (void) pFIN (); ! 1375: ! 1376: exit (status); ! 1377: } ! 1378: ! 1379: /* */ ! 1380: ! 1381: /* VARARGS2 */ ! 1382: ! 1383: static void ! 1384: adorn(what, fmt, a, b, c, d, e, f) ! 1385: char *what, *fmt, *a, *b, *c, *d, *e, *f; ! 1386: { ! 1387: char *cp = invo_name; ! 1388: ! 1389: invo_name = NULL; ! 1390: advise (what, fmt, a, b, c, d, e, f); ! 1391: invo_name = cp; ! 1392: } ! 1393: ! 1394: /* */ ! 1395: ! 1396: /* VARARGS3 */ ! 1397: void ! 1398: advertise(what, tail, fmt, a, b, c, d, e, f) ! 1399: char *what, *tail, *fmt, *a, *b, *c, *d, *e, *f; ! 1400: { ! 1401: int eindex = errno; ! 1402: char buffer[BUFSIZ], ! 1403: err[BUFSIZ]; ! 1404: struct iovec iob[20]; ! 1405: register struct iovec *iov = iob; ! 1406: ! 1407: (void) fflush (stdout); ! 1408: ! 1409: (void) fflush (stderr); ! 1410: ! 1411: if (invo_name) { ! 1412: iov -> iov_len = strlen (iov -> iov_base = invo_name); ! 1413: iov++; ! 1414: iov -> iov_len = strlen (iov -> iov_base = ": "); ! 1415: iov++; ! 1416: } ! 1417: ! 1418: (void) sprintf (buffer, fmt, a, b, c, d, e, f); ! 1419: iov -> iov_len = strlen (iov -> iov_base = buffer); ! 1420: iov++; ! 1421: if (what) { ! 1422: if (*what) { ! 1423: iov -> iov_len = strlen (iov -> iov_base = " "); ! 1424: iov++; ! 1425: iov -> iov_len = strlen (iov -> iov_base = what); ! 1426: iov++; ! 1427: iov -> iov_len = strlen (iov -> iov_base = ": "); ! 1428: iov++; ! 1429: } ! 1430: if (eindex > 0 && eindex < sys_nerr) ! 1431: iov -> iov_len = strlen (iov -> iov_base = sys_errlist[eindex]); ! 1432: else { ! 1433: (void) sprintf (err, "Error %d", eindex); ! 1434: iov -> iov_len = strlen (iov -> iov_base = err); ! 1435: } ! 1436: iov++; ! 1437: } ! 1438: if (tail && *tail) { ! 1439: iov -> iov_len = strlen (iov -> iov_base = ", "); ! 1440: iov++; ! 1441: iov -> iov_len = strlen (iov -> iov_base = tail); ! 1442: iov++; ! 1443: } ! 1444: iov -> iov_len = strlen (iov -> iov_base = "\n"); ! 1445: iov++; ! 1446: ! 1447: if (tty_ready == DONE) ! 1448: (void) WINwritev (Display, iob, iov - iob); ! 1449: else ! 1450: (void) writev (fileno (stderr), iob, iov - iob); ! 1451: } ! 1452: ! 1453: /* */ ! 1454: ! 1455: #ifndef BSD42 ! 1456: static int ! 1457: writev(fd, iov, n) ! 1458: register int fd; ! 1459: register struct iovec *iov; ! 1460: register int n; ! 1461: { ! 1462: register int i, ! 1463: j; ! 1464: ! 1465: for (i = j = 0; i < n; i++, iov++) ! 1466: if (write (fd, iov -> iov_base, iov -> iov_len) != iov -> iov_len) ! 1467: break; ! 1468: else ! 1469: j += iov -> iov_len; ! 1470: ! 1471: return j; ! 1472: } ! 1473: #endif BSD42
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.