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