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