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