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