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