Annotation of OpenXM_contrib2/fep/fep_main.c, Revision 1.6
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: }
1.6 ! noro 869: #if defined(__CYGWIN32__) || defined(__linux__)
1.2 noro 870: sprintf (master_tty, "/dev/ptmx");
871: master = open (master_tty, O_RDWR);
872: if (master >= 0) {
1.6 ! noro 873: #if defined(__linux__)
! 874: char name[BUFSIZ];
! 875: grantpt(master);
! 876: unlockpt(master);
! 877: if ( !ptsname_r(master,name,sizeof(name)) ) {
! 878: strcpy(slave_tty, name);
! 879: goto FOUND;
! 880: }
! 881: #else
1.2 noro 882: char *name;
883: name = (char *)ptsname(master);
884: if ( name != 0 ) {
885: strcpy(slave_tty, name);
1.1 noro 886: goto FOUND;
887: }
1.6 ! noro 888: #endif
1.1 noro 889: }
890: #else
891: for (c = 'p'; c <= 's'; c++) {
892: for (i = 0; i < 16; i++) {
893: sprintf (master_tty, "/dev/pty%c%x", c, i);
894: master = open (master_tty, O_RDWR);
895: if (master >= 0) {
896: sprintf (slave_tty, "/dev/tty%c%x", c, i);
897: goto FOUND;
898: }
899: }
900: }
901: #endif
902: /*
903: * Can't get master tty
904: */
905: if (master < 0) {
906: fprintf (stderr, "Couldn't open pseudo tty\n");
907: kill_process ();
908: exit (1);
909: }
910:
911: FOUND:
912: #ifdef TERMIOS
913: tcgetattr(0, &initial_ttymode);
914: #elif defined(TIOCSETN)
915: ioctl (0, TIOCGETP, (char *) &initial_ttymode);
916: ioctl (0, TIOCGETC, (char *) &tchars_buf);
917: ioctl (0, TIOCGETD, (char *) &line_desc);
918: ioctl (0, TIOCGLTC, (char *) <chars_buf);
919: ioctl (0, TIOCLGET, (char *) &lmode_buf);
920: #endif
921:
922: #ifdef TIOCGWINSZ
923: {
924: struct winsize win;
925:
926: if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
927: lines = win.ws_row;
928: columns = win.ws_col;
929: }
930: }
931: #endif
932:
933: #ifdef KANJI
934: # if defined(TIOCKGET) && defined(TIOCKSET)
935: ioctl (0, TIOCKGET, (char *) &kmode_buf);
936: # endif
937: # if defined(TIOCKGETC) && defined(TIOCKSETC)
938: ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
939: # endif
940: #endif /* KANJI */
941:
942: FD_ZERO(&stdinmask);
943: FD_ZERO(&mastermask);
944: FD_ZERO(&selectmask);
945: FD_SET(fileno(stdin), &stdinmask);
946: FD_SET(master, &mastermask);
947: FD_SET(fileno(stdin), &selectmask);
948: FD_SET(master, &selectmask);
949: selectnfds = max (fileno(stdin), master) + 1;
950:
951: return;
952: }
953:
954: get_pty_slave()
955: {
956:
957: slave = open (slave_tty, 2);
958: if (slave < 0) {
959: perror (slave_tty);
960: exit (1);
961: }
962: #ifdef TERMIOS
963: tcsetattr(slave, TCSANOW, &initial_ttymode);
964: #elif defined(TIOCSETN)
965: ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
966: ioctl (slave, TIOCSETC, (char *) &tchars_buf);
967: ioctl (slave, TIOCSLTC, (char *) <chars_buf);
968: ioctl (slave, TIOCLSET, (char *) &lmode_buf);
969: ioctl (slave, TIOCSETD, (char *) &line_desc);
970: #endif
971:
972: #ifdef KANJI
973: # if defined(TIOCKGET) && defined(TIOCKSET)
974: ioctl (slave, TIOCKSET, (char *) &kmode_buf);
975: # endif
976: # if defined(TIOCKGETC) && defined(TIOCKSETC)
977: ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
978: # endif
979: #endif /* KANJI */
980:
981: #ifdef TIOCSWINSZ
982: {
983: struct winsize win;
984:
985: win.ws_row = lines;
986: win.ws_col = columns;
987: (void) ioctl (slave, TIOCSWINSZ, &win);
988: }
989: #endif
990: }
991:
992: recover_tty()
993: {
994: #ifdef TERMIOS
995: tcsetattr(0, TCSANOW, &initial_ttymode);
996: #elif defined(TIOCSETN)
997: ioctl (0, TIOCSETN, (char *) & initial_ttymode);
998: ioctl (0, TIOCSETC, (char *) & tchars_buf);
999: ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
1000: #endif
1001: }
1002:
1003: suspend()
1004: {
1005: long pid;
1.3 noro 1006: #if defined(sun)
1007: void (*func) (int);
1008: #else
1.1 noro 1009: void (*func) __P((int));
1.3 noro 1010: #endif
1.1 noro 1011: #ifndef __CYGWIN32__
1012: int omask;
1013: #endif
1014: extern int errno;
1015:
1016: pid = getpid ();
1017: /* reset signal handler so kill below stops us */
1018: func = signal (SIGCHLD, SIG_IGN);
1019: signal (SIGTSTP, SIG_DFL);
1020: recover_tty();
1021: #define mask(s) (1 << ((s)-1))
1.3 noro 1022: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1023: omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
1024: #endif
1025: kill (0, SIGTSTP);
1026:
1027: if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
1028: printf ("Where my child has gone?!\n");
1029: terminate (0);
1030: }
1031: killpg (child_pid, SIGCONT);
1032: kill (0, SIGCONT);
1033: signal (SIGCHLD, func);
1034: signal (SIGTSTP, SIG_IGN);
1.3 noro 1035: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1036: sigblock (mask (SIGTSTP));
1037: #endif
1038: fix_tty ();
1039: if (look_var ("auto-repaint"))
1040: fep_repaint(0);
1041: }
1042:
1043: look_cmdinfo (command)
1044: char *command;
1045: {
1046: struct cmdinfo *p;
1047: char *allocAndCopyThere();
1048:
1049: if (strcmp (prompt, "") != 0)
1050: return;
1051:
1052: for (p = cmdinfo_tab; p->command; p++) {
1053: if (strcmp (command, p->command) == 0) {
1054: prompt = allocAndCopyThere (p->prompt);
1055: set_var ("prompt", p->prompt);
1056: set_var ("delimiters", p->delimiters);
1057: break;
1058: }
1059: }
1060: }
1061:
1062:
1063: usageAndExit()
1064: {
1065:
1066: printf ("Usage: %s [-emacs|-vi] command\n", myself);
1067: exit (1);
1068: }
1069:
1070: #ifdef SIGWINCH
1071: /*
1072: * Propagate window size changes to the slave tty.
1073: */
1.4 ohara 1074: void sigwinch(int dummy)
1.1 noro 1075: {
1076: #ifdef TIOCGWINSZ /* 4.3BSD */
1077: struct winsize win;
1078:
1079: if (ioctl (0, TIOCGWINSZ, (char *)&win) >= 0) {
1080: (void) ioctl (slave, TIOCSWINSZ, (char *)&win);
1081: set_var ("crt", itoa (win.ws_row));
1082: set_var ("showhist", itoa (win.ws_row - 1));
1083: }
1084: #else
1085: #ifdef TIOCGSIZE /* SONY NEWS OS2.2 */
1086: struct ttysize win;
1087:
1088: if (ioctl(0, TIOCGSIZE, (char *)&win) >= 0) {
1089: (void) ioctl(slave, TIOCSSIZE, (char *)&win);
1090: set_var ("crt", itoa (win.ts_lines));
1091: set_var ("showhist", itoa (win.ts_lines - 1));
1092: }
1093: #endif /* TIOCGWINSZ */
1094: #endif /* TIOCGSIZE */
1095: }
1096: #endif /* SIGWINCH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>