Annotation of OpenXM_contrib2/fep/fep_main.c, Revision 1.5
1.1 noro 1: /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
2:
3: #ifndef lint
4: static char rcsid[]=
5: "$Id: fep_main.c,v 4.11 1993/06/10 02:51:28 utashiro Exp $ (SRA)";
6: #endif /* lint */
7:
8: #include <stdio.h>
9: #include <signal.h>
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include <sys/ioctl.h>
1.3 noro 13: #if defined(sun)
14: #include <sys/fcntl.h>
15: #include <sys/ttold.h>
16: #endif
1.1 noro 17: #ifdef TERMIOS
18: #include <termios.h>
19: #if defined(__linux__) || defined(__CYGWIN__)
20: #ifndef _POSIX_VDISABLE
21: #define _POSIX_VDISABLE '\0'
22: #endif
23: #endif
24: #else
25: #include <sgtty.h>
26: #endif
27: #include <sys/file.h>
28: #include <sys/time.h>
29: #include <sys/resource.h>
30: #include <sys/errno.h>
31:
32: #include "fep_defs.h"
33: #include "fep_glob.h"
34: #include "fep_funcs.h"
35: #ifdef STAT
36: #include "fep_stat.h"
37: #endif
38:
39: #ifndef lint
40: static char fep_defsrc[] = FEP_DEFS;
41: static char fep_globrc[] = FEP_GLOB;
42: static char fep_funcsrc[] = FEP_FUNCS;
43: #ifdef STAT
44: static char fep_statrc[] = FEP_STAT;
45: #endif
46: #endif /* lint */
47:
48: char *myself; /* the command name */
49: char *prompt = ""; /* prompt string */
50: char *delimiters = DEFAULT_DELIMITERS;
51: /* delimiter characters */
52: int master; /* file discriptor for pty master */
53: int slave; /* file discriptor for pty slave */
54: fd_set mastermask; /* 1<<master */
55: fd_set stdinmask; /* 1<<fileno(stdin) */
56: fd_set selectmask; /* stdinmask | mastermask */
57: int selectnfds; /* max (fileno(stdin), master) + 1*/
58: int child_pid; /* child pid */
59: int ptyflag = ON; /* flag to use pty or not */
60: int histlen = -1; /* history length */
61: int debug = OFF; /* debug switch */
62: int auto_tty_fix = ON; /* fix tty mode automaticaly */
63: FILE *script_fp = NULL; /* script file pointer */
1.3 noro 64: #if defined(sun)
65: void catchsig (int); /* function take care SIGCHILD */
66: #else
1.1 noro 67: void catchsig __P((int)); /* function take care SIGCHILD */
1.3 noro 68: #endif
1.1 noro 69:
70: #ifdef TERMIOS
71: #define ttystruct termios
72: #elif defined(TIOCSETN)
73: #define ttystruct sgttyb
74: #endif
75: struct ttystruct initial_ttymode; /* initial tty mode */
76: struct ttystruct master_ttymode; /* master tty mode */
77: struct ttystruct slave_ttymode; /* slave tty mode */
78:
79: int lines; /* terminal line size */
80: int columns; /* terminal coulumn size */
81: char *term_clear; /* terminal clear code */
82:
1.3 noro 83: #if defined(sun)
84: void (*sighup)(int), (*sigchld)(int), (*sigtstp)(int);
85: #else
1.1 noro 86: void (*sighup) __P((int)), (*sigchld) __P((int)), (*sigtstp) __P((int));
1.3 noro 87: #endif
1.1 noro 88: /* function buffer for signal */
89:
90: #ifdef TIOCSETN
91: struct tchars tchars_buf; /* tty characters */
92: struct ltchars ltchars_buf; /* tty characters */
93: #endif
94: int lmode_buf; /* local mode */
95: int line_desc; /* line descipline */
96: #ifdef KANJI
97: struct jtchars jtchars_buf; /* kanji tty characters */
98: int kmode_buf; /* kanji mode */
99: #endif /* KANJI */
100:
101: char master_tty[16]; /* master tty name */
102: char slave_tty[16]; /* slave tty name */
103:
104: BUFFER iobuffer; /* buffer self */
105: BUFFER *output_buffer = &iobuffer; /* buffer pointer */
106:
107: struct cmdinfo {
108: char *command;
109: char *prompt;
110: char *delimiters;
111: } cmdinfo_tab [] = {
112: {"/bin/sh", "$ ", " \t()<>{};&|='\""},
113: {"sh", "$ ", " \t()<>{};&|='\""},
114: {"jsh", "$ ", " \t()<>{};&|='\""},
115: {"/bin/csh", "% ", " \t()<>{};&|='\""},
116: {"csh", "% ", " \t()<>{};&|='\""},
117: {"jcsh", "% ", " \t()<>{};&|='\""},
118: {"/usr/ucb/dbx", "(dbx) ", " \t>"},
119: {"dbx", "(dbx) ", " \t>"},
120: {"/etc/lpc", "lpc> ", " \t"},
121: {"lpc", "lpc> ", " \t"},
122: {"/usr/ucb/mail", "& ", " \t"},
123: {"mail", "& ", " \t"},
124: {"/usr/lib/sendmail", "> ", " \t"},
125: {"sendmail", "> ", " \t"},
126: {"/usr/sra/calc", "CALC: ", " \t"},
127: {"calc", "CALC: ", " \t"},
128: {0, 0}
129: };
130:
131: main(argc, argv)
132: int argc;
133: char *argv[];
134: {
135: int i;
136: char *cp;
137: char *getenv();
138: char **commandv;
139: char *allocAndCopyThere();
140:
141: myself = argv[0];
142:
143: setvbuf(stdin, NULL, _IONBF, 0);
144: setvbuf(stdout, NULL, _IONBF, 0);
145: setvbuf(stderr, NULL, _IONBF, 0);
146:
147: /*
148: * Initialize binding table
149: */
150: init_bind_table ();
151:
152: /*
153: * Set default variables before process arguments.
154: */
155: set_default_vars ();
156:
157:
158: /*
159: * Look environment variable first.
160: */
161: /* EDITMODE */
162: if ((cp=getenv("EDITMODE")) && (eq(cp,"emacs")||eq(cp,"vi")))
163: set_only_var ("editmode", cp);
164: /* USER */
165: if (cp=getenv("USER"))
166: set_only_var ("user", cp);
167: /* HOME */
168: if (cp=getenv("HOME"))
169: set_only_var ("home", cp);
170: /* TERM */
171: if (cp=getenv("TERM"))
172: set_only_var ("term", cp);
173: /* SHELL */
174: if (cp=getenv("SHELL"))
175: set_only_var ("shell", cp);
176:
177: /*
178: * Check arguments.
179: */
180: while (argv[1] && argv[1][0] == '-') {
181: switch (argv[1][1]) {
182:
183: case '\0': /* - */
184: ptyflag = 0;
185: break;
186:
187: case 'd': /* -d */
188: debug = ON;
189: break;
190:
191: case 'e': /* -emacs */
192: if (strcmp (argv[1], "-emacs") == 0)
193: set_only_var ("editmode", "emacs");
194: else
195: goto DEFAULT;
196: break;
197:
198: case 'h': /* -h */
199: if (argv[1][2] == '\0') {
200: argv++;
201: argc--;
202: if (argc == 1)
203: usageAndExit ();
204: histlen = atoi (argv[1]);
205: }
206: else {
207: histlen = atoi (&argv[1] + 2);
208: }
209: break;
210:
211: case 'p': /* -p */
212: if (argv[1][2] == '\0') {
213: argv++;
214: argc--;
215: if (argc == 1)
216: usageAndExit ();
217: prompt = allocAndCopyThere (argv[1]);
218: }
219: else {
220: prompt = allocAndCopyThere (argv[1] + 2);
221: }
222: break;
223:
224: case 'v': /* -vi */
225: if (strcmp (argv[1], "-vi") == 0)
226: set_only_var ("editmode", "vi");
227: else
228: goto DEFAULT;
229: break;
230: DEFAULT:
231: default:
232: printf ("Unknown option \"%s\"\n", argv[1]);
233: }
234: argv++;
235: argc--;
236: }
237: fflush (stdout);
238:
239: if (argc < 2 && ptyflag) {
240: usageAndExit ();
241: }
242:
243: look_cmdinfo (argv[1]);
244:
245: /*
246: * Set variable of command name.
247: */
248: {
249: char *cp = argv[1], *rindex();
250:
251: if (any ('/', cp))
252: cp = rindex (cp, '/') + 1;
253: set_var (cp, "1");
254: set_var ("command", cp);
255: }
256:
257: commandv = &argv[1];
258:
259: if (! isatty (0)) {
1.5 ! ohara 260: #if defined(__INTERIX)
! 261: execvp (*commandv, commandv);
! 262: #else
1.1 noro 263: execvp (*commandv, commandv, 0);
1.5 ! ohara 264: #endif
1.1 noro 265: perror (*commandv);
266: exit (1);
267: }
268:
269: get_pty_master ();
270: fix_tty ();
271:
272: if (histlen < 0) {
273: if (getenv ("HISTLEN"))
274: histlen = atoi (getenv ("HISTLEN"));
275: else
276: histlen = DFL_HISTLEN;
277: }
278:
279: init_hist (histlen);
280: init_edit_params ();
281:
282: /*
283: * Initialize output buffer.
284: */
285: if (!output_buffer->b_buf) {
286: int size;
287:
288: if ((size = atoi (look_var ("buffer"))) <= 0)
289: size = 5120;
290: if (!set_buffer (output_buffer, size)) {
291: fprintf (stderr, "Can't allocate enough momory\n");
292: kill_process ();
293: exit (1);
294: }
295: }
296:
297: if (ptyflag) {
298: child_pid = fork ();
299: if (child_pid < 0) {
300: perror ("fork");
301: kill_process ();
302: exit (1);
303: }
304: if (child_pid == 0)
305: exec_to_command (commandv);
306: }
307: fix_signal ();
308:
309: input_handler ();
310: }
311:
312: fix_signal ()
313: {
314: #ifdef SIGWINCH
1.3 noro 315: #if defined(sun)
316: void sigwinch (int);
317: #else
1.1 noro 318: void sigwinch __P((int));
319: #endif
1.3 noro 320: #endif
1.1 noro 321:
322: sighup = signal (SIGHUP, terminate);
323: sigchld = signal (SIGCHLD, catchsig);
324: sigtstp = signal (SIGTSTP, SIG_IGN);
325: signal (SIGINT, (void(*)())send_int_sig);
326: #ifdef SIGWINCH
327: (void) signal(SIGWINCH, sigwinch);
328: #endif
329: }
330:
331: recover_signal ()
332: {
333:
334: (void) signal (SIGHUP, sighup);
335: (void) signal (SIGCHLD, sigchld);
336: (void) signal (SIGTSTP, sigtstp);
337: }
338:
339: input_handler()
340: {
341: char *inputline;
342: char *getline ();
343:
344: /*
345: * Get slave tty descriptor for auto-tty-fix
346: */
347: if ((slave = open (slave_tty, O_RDONLY)) < 0)
348: perror ("open");
349:
350: while (inputline = getline ()) {
351: /*
352: * XXX: nbyte should be greater than 0 only for ^@ input in emacs.
353: * This solution is very ugly.. but it will takes a half day
354: * to fix this problem in more right way. I will fix this problem
355: * in future release.
356: */
357: register int nbyte = max (strlen (inputline), 1);
358:
359: /*
360: * Write to master pty
361: */
362: write (master, inputline, nbyte);
363:
364: /*
365: * NOTE:
366: * Saving command line to output buffer is done in getline().
367: * Because inputline here is converted by alias.
368: */
369:
370: #ifdef STAT
371: stat_ibyte += nbyte;
372: #endif
373:
374: /*
375: * Write to script file.
376: */
377: if (Through == OFF && Transparency == OFF && script_fp)
378: fwrite (inputline, sizeof(CHAR), strlen (inputline), script_fp);
379: }
380: terminate (0);
381: }
382:
383: #define INPUT_BUFFER_SIZE 1024
384:
385: #ifdef USE_TIMEOUT
386: /*
387: * NOTE:
388: * Now these time mechanism is not used.
389: * Terminal status is get at every input from stdin.
390: */
391: struct timeval timeout_0s = {0L, 0L};
392: struct timeval timeout_500ms = {0L, 500000L};
393: struct timeval timeout_1s = {1L, 0L};
394: struct timeval timeout_5s = {5L, 0L};
395: struct timeval timeout_10s = {10L, 0L};
396: struct timeval timeout_60s = {60L, 0L};
397:
398: #define TIMEOUT_IMMID &timeout_500ms
399: #define TIMEOUT_SOON &timeout_1s
400: #define TIMEOUT_SHORT &timeout_5s
401: #define TIMEOUT_MID &timeout_10s
402: #define TIMEOUT_LONG &timeout_60s
403: #define TIMEOUT_FOREVER (struct timeval *)0
404: #define TIMEOUT_NOBLOCK &timeout_0s
405:
406: struct timeval *timeout_list[] = {
407: TIMEOUT_IMMID,
408: TIMEOUT_SOON,
409: TIMEOUT_SHORT,
410: TIMEOUT_MID,
411: TIMEOUT_LONG,
412: TIMEOUT_FOREVER
413: };
414: #else
415: struct timeval timeout_0s = {0L, 0L};
416: #define TIMEOUT_FOREVER (struct timeval *)0
417: #define TIMEOUT_NOBLOCK &timeout_0s
418: #endif
419:
420: struct timeval *notimeout[] = {
421: TIMEOUT_FOREVER
422: };
423:
424: getcharacter()
425: {
426: char c;
427: int n;
428: int nfound;
429: fd_set readfd, writefd, exceptfd;
430: #ifdef USE_TIMEOUT
431: struct timeval **timeout = auto_tty_fix ? timeout_list : notimeout;
432: #else
433: struct timeval **timeout = notimeout;
434: #endif
435: extern int errno;
436:
437:
438: /*
439: * Sorry, this cording depends to an implementation of getc().
440: */
441: FD_ZERO(&writefd);
442: FD_ZERO(&exceptfd);
443:
444: RETRY:
445: readfd = selectmask;
446:
447: #ifdef STAT
448: stat_nselect++;
449: #endif
450: while ((nfound = select (selectnfds, &readfd, 0, 0, *timeout)) < 0)
451: if (errno != EINTR) {
452: perror ("select");
453: terminate(0);
454: }
455:
456: /*
457: * Found output from pty.
458: */
459: if (FD_ISSET(master, &readfd)) {
460: int nbyte;
461:
462: /*
463: * Read from pty.
464: */
465: nbyte = buf_read (master, output_buffer);
466:
467: if (nbyte > 0) {
468: /*
469: * Write to stdout
470: */
471: write (1, output_buffer->b_lastbuf, nbyte);
472:
473: /*
474: * Write to script file
475: */
476: if (script_fp)
477: fwrite (output_buffer->b_lastbuf,
478: sizeof(CHAR), nbyte, script_fp);
479:
480: #ifdef STAT
481: stat_obyte += nbyte;
482: #endif
483: }
484: else if (nbyte < 0) {
485: perror ("read");
486: #ifdef STAT
487: stat_rerror++;
488: #endif
489: }
490: }
491:
492: /*
493: * Found input from terminal
494: */
495: if (FD_ISSET(fileno(stdin), &readfd)) {
496:
497: #ifndef USE_TIMEOUT
498: /*
499: * Look slave tty mode before every input.
500: * This will be done only before real input from stdin, because
501: * if character remained in FILE buffer, control goes to RETURNCHAR
502: * label.
503: */
504: if (Through == OFF && auto_tty_fix)
505: (void) fix_transparency ();
506: #endif
507:
508: RETURNCHAR:
509: if ((c = getc (stdin)) == EOF) {
510: if (debug)
511: printf ("EOF chatched\n");
512: terminate (0);
513: }
514: else
515: return (c & CHARMASK);
516: }
517:
518: #ifdef USE_TIMEOUT
519: /*
520: * In the case of timeout.
521: */
522: if (nfound == 0) {
523:
524: /*
525: * Only to make sure
526: */
527: if (!auto_tty_fix) {
528: printf ("Timeout should not happen!!\n");
529: timeout = notimeout;
530: goto RETRY;
531: }
532:
533: (void) fix_transparency ();
534: ++timeout;
535:
536: if (debug)
537: errorBell();
538: }
539: #endif
540:
541: goto RETRY;
542: }
543:
544: int set_buffer (bp, size)
545: BUFFER *bp;
546: int size;
547: {
548: char *newbuf, *malloc(), *realloc();
549:
550: if (bp->b_buf)
551: newbuf = (char *) realloc (bp->b_buf, size);
552: else {
553: newbuf = (char *) malloc (size);
554: bp->b_count = bp->b_next = 0;
555: }
556:
557: if (newbuf == 0)
558: return (0);
559:
560: bp->b_buf = newbuf;
561: bp->b_max = size;
562: bp->b_hiwater = size * 4 / 5;
563:
564: if (bp->b_next > bp->b_hiwater) {
565: bp->b_count = bp->b_next;
566: bp->b_next = 0;
567: }
568: return (1);
569: }
570:
571: int buf_read (fd, bp)
572: int fd; /* file discriptor */
573: BUFFER *bp; /* buffer pointer */
574: {
575: int nbyte;
576:
577: /*
578: * save previous next pointer
579: */
580: bp->b_lastbuf = bp->b_buf + bp->b_next;
581:
582: /*
583: * read from fd as possible
584: */
585: nbyte = read (fd, bp->b_buf + bp->b_next, bp->b_max - bp->b_next);
586:
587: /*
588: * move next read pointer
589: */
590: bp->b_next += nbyte;
591:
592: /*
593: * If count has not reached high-water mark, increment count
594: * by read count.
595: */
596: if (bp->b_count < bp->b_hiwater)
597: bp->b_count += nbyte;
598:
599: /*
600: * If next pointer goes further than high-water mark, discard contents
601: * after next pointer, and move next pointer to buffer top.
602: */
603: if (bp->b_next > bp->b_hiwater) {
604: bp->b_count = bp->b_next;
605: bp->b_next = 0;
606: }
607:
608: return (nbyte);
609: }
610:
611: buf_put (bp, s)
612: BUFFER *bp; /* buffer pointer */
613: char *s; /* string pointer */
614: {
615: int nbyte;
616: int slen;
617:
618: nbyte = strlen (s);
619:
620: while (nbyte > 0) {
621:
622: slen = min (bp->b_max - bp->b_next, nbyte);
623: strncpy (bp->b_buf + bp->b_next, s, slen);
624: s += slen;
625: nbyte -= slen;
626: bp->b_next += slen;
627:
628: if (bp->b_count < bp->b_hiwater)
629: bp->b_count += slen;
630:
631: if (bp->b_next > bp->b_hiwater) {
632: bp->b_count = bp->b_next;
633: bp->b_next = 0;
634: }
635: }
636: }
637:
638: swallow_output()
639: {
640: fd_set readfd = mastermask;
641: int r;
642: int nbyte;
643: int ncount = 10;
644:
645: while (
646: ncount-- &&
647: select (selectnfds, &readfd, 0, 0, TIMEOUT_NOBLOCK) > 0 &&
648: FD_ISSET(master, &mastermask)
649: ) {
650: nbyte = buf_read (master, output_buffer);
651: if (nbyte > 0) {
652: write (1, output_buffer->b_lastbuf, nbyte);
653: #ifdef STAT
654: stat_obyte += nbyte;
655: stat_nselect++;
656: #endif
657:
658: /*
659: * Write to script file
660: */
661: if (script_fp)
662: fwrite (output_buffer->b_lastbuf,
663: sizeof(CHAR), nbyte, script_fp);
664: }
665: else if (nbyte < 0) {
666: perror ("read");
667: #ifdef STAT
668: stat_rerror++;
669: #endif
670: }
671: }
672: return;
673: }
674:
675: #include <sys/wait.h>
676: #ifdef AIX
677: #include <sys/m_wait.h>
678: #endif
679:
1.5 ! ohara 680: #if defined(__INTERIX)
! 681: #define wait3(s,opt,rp) (waitpid((-1),(s),(opt)))
! 682: #endif
! 683:
1.1 noro 684: void
685: catchsig(n)
686: int n;
687: {
688: int status;
689: struct rusage ru;
690:
691: if (wait3 (&status, WNOHANG | WUNTRACED, &ru) != child_pid)
692: return;
693: if (WIFSTOPPED (status) /* || WIFSIGNALED (status) */) {
694: if (debug) {
695: message ("Child has sttoped!!\n");
696: }
697: suspend ();
698: return;
699: }
700: terminate (0);
701: }
702:
703: exec_to_command(argv)
704: char *argv[];
705: {
706: int t;
707:
708: /*
709: * Disconnect control terminal
710: */
711: t = open ("/dev/tty", 2);
712: if (t >= 0) {
1.5 ! ohara 713: #if !defined(__CYGWIN32__) && !defined(__INTERIX)
1.1 noro 714: ioctl (t, TIOCNOTTY, (char *) 0);
715: #endif
716: (void) close (t);
717: }
718:
719: get_pty_slave ();
720:
721: (void) close (master);
722: dup2 (slave, 0);
723: dup2 (slave, 1);
724: dup2 (slave, 2);
725: (void) close (slave);
726:
727: #ifdef TERMIOS
728: tcsetattr(0, TCSANOW, &slave_ttymode);
729: #elif defined(TIOCSETN)
730: ioctl (0, TIOCSETN, (char *) & slave_ttymode);
731: #endif
1.5 ! ohara 732: #if defined(__INTERIX)
! 733: execvp (*argv, argv);
! 734: #else
1.1 noro 735: execvp (*argv, argv, 0);
1.5 ! ohara 736: #endif
1.1 noro 737: perror (*argv);
738: exit (1);
739: }
740:
741: #ifdef TERMIOS
742: fix_tty()
743: {
744: int i;
745: master_ttymode = initial_ttymode;
746: slave_ttymode = initial_ttymode;
747: master_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK|ICANON);
748:
749: for (i = 0; i < NCCS; i++)
750: master_ttymode.c_cc[i] = _POSIX_VDISABLE;
751:
752: master_ttymode.c_cc[VMIN] = 1;
753: master_ttymode.c_cc[VTIME] = 0;
754: slave_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK);
755: slave_ttymode.c_iflag &= ~(ICRNL);
756: slave_ttymode.c_oflag &= ~(ONLCR);
757: tcsetattr(0, TCSANOW, &master_ttymode);
758: }
759:
760: #elif defined(TIOCSETN)
761:
762: fix_tty()
763: {
764: struct tchars tcbuf;
765: struct ltchars lcbuf;
766:
767: master_ttymode = initial_ttymode;
768: slave_ttymode = initial_ttymode;
769: tcbuf = tchars_buf;
770: lcbuf = ltchars_buf;
771:
772: master_ttymode.sg_flags |= CBREAK;
773: master_ttymode.sg_flags &= ~ECHO;
774:
775: slave_ttymode.sg_erase = -1;
776: slave_ttymode.sg_kill = -1;
777: slave_ttymode.sg_flags &= ~(ECHO|CRMOD);
778:
779: tcbuf.t_intrc = -1;
780: tcbuf.t_quitc = -1;
781: #ifdef AIX
782: tcbuf.t_eofc = 0;
783: #else
784: tcbuf.t_eofc = -1;
785: #endif
786: tcbuf.t_brkc = -1;
787:
788: lcbuf.t_suspc = -1;
789: lcbuf.t_dsuspc = -1;
790: lcbuf.t_rprntc = -1;
791: lcbuf.t_flushc = -1;
792: lcbuf.t_werasc = -1;
793: lcbuf.t_lnextc = -1;
794:
795: ioctl (0, TIOCSETN, (char *) & master_ttymode);
796: ioctl (0, TIOCSETC, (char *) & tcbuf);
797: ioctl (0, TIOCSLTC, (char *) & lcbuf);
798: }
799: #endif
800:
801: kill_process()
802: {
803:
804: if (child_pid)
805: (void) killpg (child_pid, SIGTERM);
806: }
807:
808: void
809: terminate(n)
810: int n;
811: {
812: extern int errno;
813:
814: /*
815: * Save history if 'history-file' is set
816: */
817: {
818: char *cp, *mk_home_relative(), *look_var();
819: char buf [256];
820: int num;
821:
822: if (look_var ("savehist") && (cp = look_var ("history-file"))) {
823:
824: num = lookd_var ("savehist");
825: strcpy (buf, mk_home_relative (cp));
826: save_history (buf, num);
827: }
828: }
829:
830: /*
831: * If scripting, close script file.
832: */
833: if (script_fp)
834: fclose (script_fp);
835:
836: (void) signal (SIGCHLD, SIG_IGN);
837: if (killpg (child_pid, SIGTERM) < 0 && errno != ESRCH)
838: if (killpg (child_pid, SIGHUP) < 0)
839: if (killpg (child_pid, SIGKILL) < 0)
840: perror ("kill");
841:
842: #ifdef TERMIOS
843: tcsetattr(0, TCSANOW, &initial_ttymode);
844: #elif defined(TIOCSETN)
845: ioctl (0, TIOCSETN, (char *) & initial_ttymode);
846: ioctl (0, TIOCSETC, (char *) & tchars_buf);
847: ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
848: #endif
849: exit (0);
850: }
851:
852: send_int_sig() {
853: #ifndef __CYGWIN__
854: kill(child_pid,SIGINT);
855: #endif
856: return 0;
857: }
858:
859: get_pty_master()
860: {
861: char c;
862: struct stat stb;
863: int i;
864:
865: if (ptyflag == 0) {
866: master = 1;
867: return;
868: }
869: #ifdef __CYGWIN32__
1.2 noro 870: sprintf (master_tty, "/dev/ptmx");
871: master = open (master_tty, O_RDWR);
872: if (master >= 0) {
873: char *name;
874: name = (char *)ptsname(master);
875: if ( name != 0 ) {
876: strcpy(slave_tty, name);
1.1 noro 877: goto FOUND;
878: }
879: }
880: #else
881: for (c = 'p'; c <= 's'; c++) {
882: for (i = 0; i < 16; i++) {
883: sprintf (master_tty, "/dev/pty%c%x", c, i);
884: master = open (master_tty, O_RDWR);
885: if (master >= 0) {
886: sprintf (slave_tty, "/dev/tty%c%x", c, i);
887: goto FOUND;
888: }
889: }
890: }
891: #endif
892: /*
893: * Can't get master tty
894: */
895: if (master < 0) {
896: fprintf (stderr, "Couldn't open pseudo tty\n");
897: kill_process ();
898: exit (1);
899: }
900:
901: FOUND:
902: #ifdef TERMIOS
903: tcgetattr(0, &initial_ttymode);
904: #elif defined(TIOCSETN)
905: ioctl (0, TIOCGETP, (char *) &initial_ttymode);
906: ioctl (0, TIOCGETC, (char *) &tchars_buf);
907: ioctl (0, TIOCGETD, (char *) &line_desc);
908: ioctl (0, TIOCGLTC, (char *) <chars_buf);
909: ioctl (0, TIOCLGET, (char *) &lmode_buf);
910: #endif
911:
912: #ifdef TIOCGWINSZ
913: {
914: struct winsize win;
915:
916: if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
917: lines = win.ws_row;
918: columns = win.ws_col;
919: }
920: }
921: #endif
922:
923: #ifdef KANJI
924: # if defined(TIOCKGET) && defined(TIOCKSET)
925: ioctl (0, TIOCKGET, (char *) &kmode_buf);
926: # endif
927: # if defined(TIOCKGETC) && defined(TIOCKSETC)
928: ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
929: # endif
930: #endif /* KANJI */
931:
932: FD_ZERO(&stdinmask);
933: FD_ZERO(&mastermask);
934: FD_ZERO(&selectmask);
935: FD_SET(fileno(stdin), &stdinmask);
936: FD_SET(master, &mastermask);
937: FD_SET(fileno(stdin), &selectmask);
938: FD_SET(master, &selectmask);
939: selectnfds = max (fileno(stdin), master) + 1;
940:
941: return;
942: }
943:
944: get_pty_slave()
945: {
946:
947: slave = open (slave_tty, 2);
948: if (slave < 0) {
949: perror (slave_tty);
950: exit (1);
951: }
952: #ifdef TERMIOS
953: tcsetattr(slave, TCSANOW, &initial_ttymode);
954: #elif defined(TIOCSETN)
955: ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
956: ioctl (slave, TIOCSETC, (char *) &tchars_buf);
957: ioctl (slave, TIOCSLTC, (char *) <chars_buf);
958: ioctl (slave, TIOCLSET, (char *) &lmode_buf);
959: ioctl (slave, TIOCSETD, (char *) &line_desc);
960: #endif
961:
962: #ifdef KANJI
963: # if defined(TIOCKGET) && defined(TIOCKSET)
964: ioctl (slave, TIOCKSET, (char *) &kmode_buf);
965: # endif
966: # if defined(TIOCKGETC) && defined(TIOCKSETC)
967: ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
968: # endif
969: #endif /* KANJI */
970:
971: #ifdef TIOCSWINSZ
972: {
973: struct winsize win;
974:
975: win.ws_row = lines;
976: win.ws_col = columns;
977: (void) ioctl (slave, TIOCSWINSZ, &win);
978: }
979: #endif
980: }
981:
982: recover_tty()
983: {
984: #ifdef TERMIOS
985: tcsetattr(0, TCSANOW, &initial_ttymode);
986: #elif defined(TIOCSETN)
987: ioctl (0, TIOCSETN, (char *) & initial_ttymode);
988: ioctl (0, TIOCSETC, (char *) & tchars_buf);
989: ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
990: #endif
991: }
992:
993: suspend()
994: {
995: long pid;
1.3 noro 996: #if defined(sun)
997: void (*func) (int);
998: #else
1.1 noro 999: void (*func) __P((int));
1.3 noro 1000: #endif
1.1 noro 1001: #ifndef __CYGWIN32__
1002: int omask;
1003: #endif
1004: extern int errno;
1005:
1006: pid = getpid ();
1007: /* reset signal handler so kill below stops us */
1008: func = signal (SIGCHLD, SIG_IGN);
1009: signal (SIGTSTP, SIG_DFL);
1010: recover_tty();
1011: #define mask(s) (1 << ((s)-1))
1.3 noro 1012: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1013: omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
1014: #endif
1015: kill (0, SIGTSTP);
1016:
1017: if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
1018: printf ("Where my child has gone?!\n");
1019: terminate (0);
1020: }
1021: killpg (child_pid, SIGCONT);
1022: kill (0, SIGCONT);
1023: signal (SIGCHLD, func);
1024: signal (SIGTSTP, SIG_IGN);
1.3 noro 1025: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1026: sigblock (mask (SIGTSTP));
1027: #endif
1028: fix_tty ();
1029: if (look_var ("auto-repaint"))
1030: fep_repaint(0);
1031: }
1032:
1033: look_cmdinfo (command)
1034: char *command;
1035: {
1036: struct cmdinfo *p;
1037: char *allocAndCopyThere();
1038:
1039: if (strcmp (prompt, "") != 0)
1040: return;
1041:
1042: for (p = cmdinfo_tab; p->command; p++) {
1043: if (strcmp (command, p->command) == 0) {
1044: prompt = allocAndCopyThere (p->prompt);
1045: set_var ("prompt", p->prompt);
1046: set_var ("delimiters", p->delimiters);
1047: break;
1048: }
1049: }
1050: }
1051:
1052:
1053: usageAndExit()
1054: {
1055:
1056: printf ("Usage: %s [-emacs|-vi] command\n", myself);
1057: exit (1);
1058: }
1059:
1060: #ifdef SIGWINCH
1061: /*
1062: * Propagate window size changes to the slave tty.
1063: */
1.4 ohara 1064: void sigwinch(int dummy)
1.1 noro 1065: {
1066: #ifdef TIOCGWINSZ /* 4.3BSD */
1067: struct winsize win;
1068:
1069: if (ioctl (0, TIOCGWINSZ, (char *)&win) >= 0) {
1070: (void) ioctl (slave, TIOCSWINSZ, (char *)&win);
1071: set_var ("crt", itoa (win.ws_row));
1072: set_var ("showhist", itoa (win.ws_row - 1));
1073: }
1074: #else
1075: #ifdef TIOCGSIZE /* SONY NEWS OS2.2 */
1076: struct ttysize win;
1077:
1078: if (ioctl(0, TIOCGSIZE, (char *)&win) >= 0) {
1079: (void) ioctl(slave, TIOCSSIZE, (char *)&win);
1080: set_var ("crt", itoa (win.ts_lines));
1081: set_var ("showhist", itoa (win.ts_lines - 1));
1082: }
1083: #endif /* TIOCGWINSZ */
1084: #endif /* TIOCGSIZE */
1085: }
1086: #endif /* SIGWINCH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>