|
|
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.