Annotation of OpenXM_contrib2/fep/fep_main.c, Revision 1.4
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)) {
260: execvp (*commandv, commandv, 0);
261: perror (*commandv);
262: exit (1);
263: }
264:
265: get_pty_master ();
266: fix_tty ();
267:
268: if (histlen < 0) {
269: if (getenv ("HISTLEN"))
270: histlen = atoi (getenv ("HISTLEN"));
271: else
272: histlen = DFL_HISTLEN;
273: }
274:
275: init_hist (histlen);
276: init_edit_params ();
277:
278: /*
279: * Initialize output buffer.
280: */
281: if (!output_buffer->b_buf) {
282: int size;
283:
284: if ((size = atoi (look_var ("buffer"))) <= 0)
285: size = 5120;
286: if (!set_buffer (output_buffer, size)) {
287: fprintf (stderr, "Can't allocate enough momory\n");
288: kill_process ();
289: exit (1);
290: }
291: }
292:
293: if (ptyflag) {
294: child_pid = fork ();
295: if (child_pid < 0) {
296: perror ("fork");
297: kill_process ();
298: exit (1);
299: }
300: if (child_pid == 0)
301: exec_to_command (commandv);
302: }
303: fix_signal ();
304:
305: input_handler ();
306: }
307:
308: fix_signal ()
309: {
310: #ifdef SIGWINCH
1.3 noro 311: #if defined(sun)
312: void sigwinch (int);
313: #else
1.1 noro 314: void sigwinch __P((int));
315: #endif
1.3 noro 316: #endif
1.1 noro 317:
318: sighup = signal (SIGHUP, terminate);
319: sigchld = signal (SIGCHLD, catchsig);
320: sigtstp = signal (SIGTSTP, SIG_IGN);
321: signal (SIGINT, (void(*)())send_int_sig);
322: #ifdef SIGWINCH
323: (void) signal(SIGWINCH, sigwinch);
324: #endif
325: }
326:
327: recover_signal ()
328: {
329:
330: (void) signal (SIGHUP, sighup);
331: (void) signal (SIGCHLD, sigchld);
332: (void) signal (SIGTSTP, sigtstp);
333: }
334:
335: input_handler()
336: {
337: char *inputline;
338: char *getline ();
339:
340: /*
341: * Get slave tty descriptor for auto-tty-fix
342: */
343: if ((slave = open (slave_tty, O_RDONLY)) < 0)
344: perror ("open");
345:
346: while (inputline = getline ()) {
347: /*
348: * XXX: nbyte should be greater than 0 only for ^@ input in emacs.
349: * This solution is very ugly.. but it will takes a half day
350: * to fix this problem in more right way. I will fix this problem
351: * in future release.
352: */
353: register int nbyte = max (strlen (inputline), 1);
354:
355: /*
356: * Write to master pty
357: */
358: write (master, inputline, nbyte);
359:
360: /*
361: * NOTE:
362: * Saving command line to output buffer is done in getline().
363: * Because inputline here is converted by alias.
364: */
365:
366: #ifdef STAT
367: stat_ibyte += nbyte;
368: #endif
369:
370: /*
371: * Write to script file.
372: */
373: if (Through == OFF && Transparency == OFF && script_fp)
374: fwrite (inputline, sizeof(CHAR), strlen (inputline), script_fp);
375: }
376: terminate (0);
377: }
378:
379: #define INPUT_BUFFER_SIZE 1024
380:
381: #ifdef USE_TIMEOUT
382: /*
383: * NOTE:
384: * Now these time mechanism is not used.
385: * Terminal status is get at every input from stdin.
386: */
387: struct timeval timeout_0s = {0L, 0L};
388: struct timeval timeout_500ms = {0L, 500000L};
389: struct timeval timeout_1s = {1L, 0L};
390: struct timeval timeout_5s = {5L, 0L};
391: struct timeval timeout_10s = {10L, 0L};
392: struct timeval timeout_60s = {60L, 0L};
393:
394: #define TIMEOUT_IMMID &timeout_500ms
395: #define TIMEOUT_SOON &timeout_1s
396: #define TIMEOUT_SHORT &timeout_5s
397: #define TIMEOUT_MID &timeout_10s
398: #define TIMEOUT_LONG &timeout_60s
399: #define TIMEOUT_FOREVER (struct timeval *)0
400: #define TIMEOUT_NOBLOCK &timeout_0s
401:
402: struct timeval *timeout_list[] = {
403: TIMEOUT_IMMID,
404: TIMEOUT_SOON,
405: TIMEOUT_SHORT,
406: TIMEOUT_MID,
407: TIMEOUT_LONG,
408: TIMEOUT_FOREVER
409: };
410: #else
411: struct timeval timeout_0s = {0L, 0L};
412: #define TIMEOUT_FOREVER (struct timeval *)0
413: #define TIMEOUT_NOBLOCK &timeout_0s
414: #endif
415:
416: struct timeval *notimeout[] = {
417: TIMEOUT_FOREVER
418: };
419:
420: getcharacter()
421: {
422: char c;
423: int n;
424: int nfound;
425: fd_set readfd, writefd, exceptfd;
426: #ifdef USE_TIMEOUT
427: struct timeval **timeout = auto_tty_fix ? timeout_list : notimeout;
428: #else
429: struct timeval **timeout = notimeout;
430: #endif
431: extern int errno;
432:
433:
434: /*
435: * Sorry, this cording depends to an implementation of getc().
436: */
437: FD_ZERO(&writefd);
438: FD_ZERO(&exceptfd);
439:
440: RETRY:
441: readfd = selectmask;
442:
443: #ifdef STAT
444: stat_nselect++;
445: #endif
446: while ((nfound = select (selectnfds, &readfd, 0, 0, *timeout)) < 0)
447: if (errno != EINTR) {
448: perror ("select");
449: terminate(0);
450: }
451:
452: /*
453: * Found output from pty.
454: */
455: if (FD_ISSET(master, &readfd)) {
456: int nbyte;
457:
458: /*
459: * Read from pty.
460: */
461: nbyte = buf_read (master, output_buffer);
462:
463: if (nbyte > 0) {
464: /*
465: * Write to stdout
466: */
467: write (1, output_buffer->b_lastbuf, nbyte);
468:
469: /*
470: * Write to script file
471: */
472: if (script_fp)
473: fwrite (output_buffer->b_lastbuf,
474: sizeof(CHAR), nbyte, script_fp);
475:
476: #ifdef STAT
477: stat_obyte += nbyte;
478: #endif
479: }
480: else if (nbyte < 0) {
481: perror ("read");
482: #ifdef STAT
483: stat_rerror++;
484: #endif
485: }
486: }
487:
488: /*
489: * Found input from terminal
490: */
491: if (FD_ISSET(fileno(stdin), &readfd)) {
492:
493: #ifndef USE_TIMEOUT
494: /*
495: * Look slave tty mode before every input.
496: * This will be done only before real input from stdin, because
497: * if character remained in FILE buffer, control goes to RETURNCHAR
498: * label.
499: */
500: if (Through == OFF && auto_tty_fix)
501: (void) fix_transparency ();
502: #endif
503:
504: RETURNCHAR:
505: if ((c = getc (stdin)) == EOF) {
506: if (debug)
507: printf ("EOF chatched\n");
508: terminate (0);
509: }
510: else
511: return (c & CHARMASK);
512: }
513:
514: #ifdef USE_TIMEOUT
515: /*
516: * In the case of timeout.
517: */
518: if (nfound == 0) {
519:
520: /*
521: * Only to make sure
522: */
523: if (!auto_tty_fix) {
524: printf ("Timeout should not happen!!\n");
525: timeout = notimeout;
526: goto RETRY;
527: }
528:
529: (void) fix_transparency ();
530: ++timeout;
531:
532: if (debug)
533: errorBell();
534: }
535: #endif
536:
537: goto RETRY;
538: }
539:
540: int set_buffer (bp, size)
541: BUFFER *bp;
542: int size;
543: {
544: char *newbuf, *malloc(), *realloc();
545:
546: if (bp->b_buf)
547: newbuf = (char *) realloc (bp->b_buf, size);
548: else {
549: newbuf = (char *) malloc (size);
550: bp->b_count = bp->b_next = 0;
551: }
552:
553: if (newbuf == 0)
554: return (0);
555:
556: bp->b_buf = newbuf;
557: bp->b_max = size;
558: bp->b_hiwater = size * 4 / 5;
559:
560: if (bp->b_next > bp->b_hiwater) {
561: bp->b_count = bp->b_next;
562: bp->b_next = 0;
563: }
564: return (1);
565: }
566:
567: int buf_read (fd, bp)
568: int fd; /* file discriptor */
569: BUFFER *bp; /* buffer pointer */
570: {
571: int nbyte;
572:
573: /*
574: * save previous next pointer
575: */
576: bp->b_lastbuf = bp->b_buf + bp->b_next;
577:
578: /*
579: * read from fd as possible
580: */
581: nbyte = read (fd, bp->b_buf + bp->b_next, bp->b_max - bp->b_next);
582:
583: /*
584: * move next read pointer
585: */
586: bp->b_next += nbyte;
587:
588: /*
589: * If count has not reached high-water mark, increment count
590: * by read count.
591: */
592: if (bp->b_count < bp->b_hiwater)
593: bp->b_count += nbyte;
594:
595: /*
596: * If next pointer goes further than high-water mark, discard contents
597: * after next pointer, and move next pointer to buffer top.
598: */
599: if (bp->b_next > bp->b_hiwater) {
600: bp->b_count = bp->b_next;
601: bp->b_next = 0;
602: }
603:
604: return (nbyte);
605: }
606:
607: buf_put (bp, s)
608: BUFFER *bp; /* buffer pointer */
609: char *s; /* string pointer */
610: {
611: int nbyte;
612: int slen;
613:
614: nbyte = strlen (s);
615:
616: while (nbyte > 0) {
617:
618: slen = min (bp->b_max - bp->b_next, nbyte);
619: strncpy (bp->b_buf + bp->b_next, s, slen);
620: s += slen;
621: nbyte -= slen;
622: bp->b_next += slen;
623:
624: if (bp->b_count < bp->b_hiwater)
625: bp->b_count += slen;
626:
627: if (bp->b_next > bp->b_hiwater) {
628: bp->b_count = bp->b_next;
629: bp->b_next = 0;
630: }
631: }
632: }
633:
634: swallow_output()
635: {
636: fd_set readfd = mastermask;
637: int r;
638: int nbyte;
639: int ncount = 10;
640:
641: while (
642: ncount-- &&
643: select (selectnfds, &readfd, 0, 0, TIMEOUT_NOBLOCK) > 0 &&
644: FD_ISSET(master, &mastermask)
645: ) {
646: nbyte = buf_read (master, output_buffer);
647: if (nbyte > 0) {
648: write (1, output_buffer->b_lastbuf, nbyte);
649: #ifdef STAT
650: stat_obyte += nbyte;
651: stat_nselect++;
652: #endif
653:
654: /*
655: * Write to script file
656: */
657: if (script_fp)
658: fwrite (output_buffer->b_lastbuf,
659: sizeof(CHAR), nbyte, script_fp);
660: }
661: else if (nbyte < 0) {
662: perror ("read");
663: #ifdef STAT
664: stat_rerror++;
665: #endif
666: }
667: }
668: return;
669: }
670:
671: #include <sys/wait.h>
672: #ifdef AIX
673: #include <sys/m_wait.h>
674: #endif
675:
676: void
677: catchsig(n)
678: int n;
679: {
680: int status;
681: struct rusage ru;
682:
683: if (wait3 (&status, WNOHANG | WUNTRACED, &ru) != child_pid)
684: return;
685: if (WIFSTOPPED (status) /* || WIFSIGNALED (status) */) {
686: if (debug) {
687: message ("Child has sttoped!!\n");
688: }
689: suspend ();
690: return;
691: }
692: terminate (0);
693: }
694:
695: exec_to_command(argv)
696: char *argv[];
697: {
698: int t;
699:
700: /*
701: * Disconnect control terminal
702: */
703: t = open ("/dev/tty", 2);
704: if (t >= 0) {
705: #ifndef __CYGWIN32__
706: ioctl (t, TIOCNOTTY, (char *) 0);
707: #endif
708: (void) close (t);
709: }
710:
711: get_pty_slave ();
712:
713: (void) close (master);
714: dup2 (slave, 0);
715: dup2 (slave, 1);
716: dup2 (slave, 2);
717: (void) close (slave);
718:
719: #ifdef TERMIOS
720: tcsetattr(0, TCSANOW, &slave_ttymode);
721: #elif defined(TIOCSETN)
722: ioctl (0, TIOCSETN, (char *) & slave_ttymode);
723: #endif
724: execvp (*argv, argv, 0);
725: perror (*argv);
726: exit (1);
727: }
728:
729: #ifdef TERMIOS
730: fix_tty()
731: {
732: int i;
733: master_ttymode = initial_ttymode;
734: slave_ttymode = initial_ttymode;
735: master_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK|ICANON);
736:
737: for (i = 0; i < NCCS; i++)
738: master_ttymode.c_cc[i] = _POSIX_VDISABLE;
739:
740: master_ttymode.c_cc[VMIN] = 1;
741: master_ttymode.c_cc[VTIME] = 0;
742: slave_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK);
743: slave_ttymode.c_iflag &= ~(ICRNL);
744: slave_ttymode.c_oflag &= ~(ONLCR);
745: tcsetattr(0, TCSANOW, &master_ttymode);
746: }
747:
748: #elif defined(TIOCSETN)
749:
750: fix_tty()
751: {
752: struct tchars tcbuf;
753: struct ltchars lcbuf;
754:
755: master_ttymode = initial_ttymode;
756: slave_ttymode = initial_ttymode;
757: tcbuf = tchars_buf;
758: lcbuf = ltchars_buf;
759:
760: master_ttymode.sg_flags |= CBREAK;
761: master_ttymode.sg_flags &= ~ECHO;
762:
763: slave_ttymode.sg_erase = -1;
764: slave_ttymode.sg_kill = -1;
765: slave_ttymode.sg_flags &= ~(ECHO|CRMOD);
766:
767: tcbuf.t_intrc = -1;
768: tcbuf.t_quitc = -1;
769: #ifdef AIX
770: tcbuf.t_eofc = 0;
771: #else
772: tcbuf.t_eofc = -1;
773: #endif
774: tcbuf.t_brkc = -1;
775:
776: lcbuf.t_suspc = -1;
777: lcbuf.t_dsuspc = -1;
778: lcbuf.t_rprntc = -1;
779: lcbuf.t_flushc = -1;
780: lcbuf.t_werasc = -1;
781: lcbuf.t_lnextc = -1;
782:
783: ioctl (0, TIOCSETN, (char *) & master_ttymode);
784: ioctl (0, TIOCSETC, (char *) & tcbuf);
785: ioctl (0, TIOCSLTC, (char *) & lcbuf);
786: }
787: #endif
788:
789: kill_process()
790: {
791:
792: if (child_pid)
793: (void) killpg (child_pid, SIGTERM);
794: }
795:
796: void
797: terminate(n)
798: int n;
799: {
800: extern int errno;
801:
802: /*
803: * Save history if 'history-file' is set
804: */
805: {
806: char *cp, *mk_home_relative(), *look_var();
807: char buf [256];
808: int num;
809:
810: if (look_var ("savehist") && (cp = look_var ("history-file"))) {
811:
812: num = lookd_var ("savehist");
813: strcpy (buf, mk_home_relative (cp));
814: save_history (buf, num);
815: }
816: }
817:
818: /*
819: * If scripting, close script file.
820: */
821: if (script_fp)
822: fclose (script_fp);
823:
824: (void) signal (SIGCHLD, SIG_IGN);
825: if (killpg (child_pid, SIGTERM) < 0 && errno != ESRCH)
826: if (killpg (child_pid, SIGHUP) < 0)
827: if (killpg (child_pid, SIGKILL) < 0)
828: perror ("kill");
829:
830: #ifdef TERMIOS
831: tcsetattr(0, TCSANOW, &initial_ttymode);
832: #elif defined(TIOCSETN)
833: ioctl (0, TIOCSETN, (char *) & initial_ttymode);
834: ioctl (0, TIOCSETC, (char *) & tchars_buf);
835: ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
836: #endif
837: exit (0);
838: }
839:
840: send_int_sig() {
841: #ifndef __CYGWIN__
842: kill(child_pid,SIGINT);
843: #endif
844: return 0;
845: }
846:
847: get_pty_master()
848: {
849: char c;
850: struct stat stb;
851: int i;
852:
853: if (ptyflag == 0) {
854: master = 1;
855: return;
856: }
857: #ifdef __CYGWIN32__
1.2 noro 858: sprintf (master_tty, "/dev/ptmx");
859: master = open (master_tty, O_RDWR);
860: if (master >= 0) {
861: char *name;
862: name = (char *)ptsname(master);
863: if ( name != 0 ) {
864: strcpy(slave_tty, name);
1.1 noro 865: goto FOUND;
866: }
867: }
868: #else
869: for (c = 'p'; c <= 's'; c++) {
870: for (i = 0; i < 16; i++) {
871: sprintf (master_tty, "/dev/pty%c%x", c, i);
872: master = open (master_tty, O_RDWR);
873: if (master >= 0) {
874: sprintf (slave_tty, "/dev/tty%c%x", c, i);
875: goto FOUND;
876: }
877: }
878: }
879: #endif
880: /*
881: * Can't get master tty
882: */
883: if (master < 0) {
884: fprintf (stderr, "Couldn't open pseudo tty\n");
885: kill_process ();
886: exit (1);
887: }
888:
889: FOUND:
890: #ifdef TERMIOS
891: tcgetattr(0, &initial_ttymode);
892: #elif defined(TIOCSETN)
893: ioctl (0, TIOCGETP, (char *) &initial_ttymode);
894: ioctl (0, TIOCGETC, (char *) &tchars_buf);
895: ioctl (0, TIOCGETD, (char *) &line_desc);
896: ioctl (0, TIOCGLTC, (char *) <chars_buf);
897: ioctl (0, TIOCLGET, (char *) &lmode_buf);
898: #endif
899:
900: #ifdef TIOCGWINSZ
901: {
902: struct winsize win;
903:
904: if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
905: lines = win.ws_row;
906: columns = win.ws_col;
907: }
908: }
909: #endif
910:
911: #ifdef KANJI
912: # if defined(TIOCKGET) && defined(TIOCKSET)
913: ioctl (0, TIOCKGET, (char *) &kmode_buf);
914: # endif
915: # if defined(TIOCKGETC) && defined(TIOCKSETC)
916: ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
917: # endif
918: #endif /* KANJI */
919:
920: FD_ZERO(&stdinmask);
921: FD_ZERO(&mastermask);
922: FD_ZERO(&selectmask);
923: FD_SET(fileno(stdin), &stdinmask);
924: FD_SET(master, &mastermask);
925: FD_SET(fileno(stdin), &selectmask);
926: FD_SET(master, &selectmask);
927: selectnfds = max (fileno(stdin), master) + 1;
928:
929: return;
930: }
931:
932: get_pty_slave()
933: {
934:
935: slave = open (slave_tty, 2);
936: if (slave < 0) {
937: perror (slave_tty);
938: exit (1);
939: }
940: #ifdef TERMIOS
941: tcsetattr(slave, TCSANOW, &initial_ttymode);
942: #elif defined(TIOCSETN)
943: ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
944: ioctl (slave, TIOCSETC, (char *) &tchars_buf);
945: ioctl (slave, TIOCSLTC, (char *) <chars_buf);
946: ioctl (slave, TIOCLSET, (char *) &lmode_buf);
947: ioctl (slave, TIOCSETD, (char *) &line_desc);
948: #endif
949:
950: #ifdef KANJI
951: # if defined(TIOCKGET) && defined(TIOCKSET)
952: ioctl (slave, TIOCKSET, (char *) &kmode_buf);
953: # endif
954: # if defined(TIOCKGETC) && defined(TIOCKSETC)
955: ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
956: # endif
957: #endif /* KANJI */
958:
959: #ifdef TIOCSWINSZ
960: {
961: struct winsize win;
962:
963: win.ws_row = lines;
964: win.ws_col = columns;
965: (void) ioctl (slave, TIOCSWINSZ, &win);
966: }
967: #endif
968: }
969:
970: recover_tty()
971: {
972: #ifdef TERMIOS
973: tcsetattr(0, TCSANOW, &initial_ttymode);
974: #elif defined(TIOCSETN)
975: ioctl (0, TIOCSETN, (char *) & initial_ttymode);
976: ioctl (0, TIOCSETC, (char *) & tchars_buf);
977: ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
978: #endif
979: }
980:
981: suspend()
982: {
983: long pid;
1.3 noro 984: #if defined(sun)
985: void (*func) (int);
986: #else
1.1 noro 987: void (*func) __P((int));
1.3 noro 988: #endif
1.1 noro 989: #ifndef __CYGWIN32__
990: int omask;
991: #endif
992: extern int errno;
993:
994: pid = getpid ();
995: /* reset signal handler so kill below stops us */
996: func = signal (SIGCHLD, SIG_IGN);
997: signal (SIGTSTP, SIG_DFL);
998: recover_tty();
999: #define mask(s) (1 << ((s)-1))
1.3 noro 1000: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1001: omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
1002: #endif
1003: kill (0, SIGTSTP);
1004:
1005: if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
1006: printf ("Where my child has gone?!\n");
1007: terminate (0);
1008: }
1009: killpg (child_pid, SIGCONT);
1010: kill (0, SIGCONT);
1011: signal (SIGCHLD, func);
1012: signal (SIGTSTP, SIG_IGN);
1.3 noro 1013: #if !defined(__CYGWIN32__) && !defined(sun)
1.1 noro 1014: sigblock (mask (SIGTSTP));
1015: #endif
1016: fix_tty ();
1017: if (look_var ("auto-repaint"))
1018: fep_repaint(0);
1019: }
1020:
1021: look_cmdinfo (command)
1022: char *command;
1023: {
1024: struct cmdinfo *p;
1025: char *allocAndCopyThere();
1026:
1027: if (strcmp (prompt, "") != 0)
1028: return;
1029:
1030: for (p = cmdinfo_tab; p->command; p++) {
1031: if (strcmp (command, p->command) == 0) {
1032: prompt = allocAndCopyThere (p->prompt);
1033: set_var ("prompt", p->prompt);
1034: set_var ("delimiters", p->delimiters);
1035: break;
1036: }
1037: }
1038: }
1039:
1040:
1041: usageAndExit()
1042: {
1043:
1044: printf ("Usage: %s [-emacs|-vi] command\n", myself);
1045: exit (1);
1046: }
1047:
1048: #ifdef SIGWINCH
1049: /*
1050: * Propagate window size changes to the slave tty.
1051: */
1.4 ! ohara 1052: void sigwinch(int dummy)
1.1 noro 1053: {
1054: #ifdef TIOCGWINSZ /* 4.3BSD */
1055: struct winsize win;
1056:
1057: if (ioctl (0, TIOCGWINSZ, (char *)&win) >= 0) {
1058: (void) ioctl (slave, TIOCSWINSZ, (char *)&win);
1059: set_var ("crt", itoa (win.ws_row));
1060: set_var ("showhist", itoa (win.ws_row - 1));
1061: }
1062: #else
1063: #ifdef TIOCGSIZE /* SONY NEWS OS2.2 */
1064: struct ttysize win;
1065:
1066: if (ioctl(0, TIOCGSIZE, (char *)&win) >= 0) {
1067: (void) ioctl(slave, TIOCSSIZE, (char *)&win);
1068: set_var ("crt", itoa (win.ts_lines));
1069: set_var ("showhist", itoa (win.ts_lines - 1));
1070: }
1071: #endif /* TIOCGWINSZ */
1072: #endif /* TIOCGSIZE */
1073: }
1074: #endif /* SIGWINCH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>