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