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