Mercurial > emacs
comparison lib-src/emacsclient.c @ 53229:33c3c7c16e13
lib-src/emacsclient.c: Implemented --here option (open a new Emacs tty). Needs more work.
(here): New variable.
(decode_options): Use it.
(ec_get_tty, ec_set_tty, init_tty, window_change, hang_up_signal): New functions.
(window_change_signal, init_signals, reset_tty, init_pty, copy_from_to): Ditto.
(pty_conversation): Ditto.
(main): Use them.
(master, pty_name, old_tty, tty, old_tty_valid, tty_erase_char): New variables.
(flow_control, meta_key, _sobuf, in_conversation, quit_conversation): Ditto.
lisp/server.el (server-process-filter): Added support for opening a new terminal frame.
dispextern.h (get_frame_size): Renamed to get_tty_size, added tty_output parameter.
dispnew.c (Fredraw_frame): fflush the current terminal instead of stdout.
(direct_output_for_insert, direct_output_forward_char, update_frame_1): Ditto.
(Fding, bitch_at_user): Ditto.
(update_frame_1): Count pending output for current terminal instead of stdout.
(window_change_signal): Resize all terminals.
(change_frame_size): Don't resize all terminals to the same size.
frame.c (Vterminal_frame): Removed.
(syms_of_frame): Removed declaration of Vterminal_frame.
(make_terminal_frame): Set the top frame of the terminal to the new frame.
(Fmake_terminal_frame): Get a new frame size from get_tty_size, don't copy it.
(do_switch_frame): Handle terminal frame visibility.
(next_frame, prev_frame): Skip over frames on different terminals.
frame.h (Vterminal_frame): Removed.
keyboard.c (input_fd): Removed.
(read_avail_input): Removed first argument from read_socket_hook.
Try to read from each available tty, until one succeeds.
(Fsuspend_emacs): Don't suspend if there are multiple terminals.
lisp.h (get_frame_size): Removed superflous declaration.
xterm.c (Xtread_socket): Removed first parameter.
macterm.h (XTread_socket): Ditto.
w32inevt.c (w32_console_read_socket): Ditto.
w32term.c (w32_read_socket): Ditto.
sysdep.c (input_fd): Removed.
(change_input_fd): Removed.
(discard_tty_input): Discard pending input on _all_ input descriptors.
(stuff_char, tabs_safe_p): Use current terminal instead of input_fd.
(init_baud_rate, request_sigio, unrequest_sigio): Ditto.
(init_sys_modes, reset_sys_modes): Ditto.
(narrow_foreground_group, widen_foreground_group): Use stdin.
(init_sys_modes, reset_sys_modes): otty parameter renamed to tty_out.
(get_frame_size): Renamed to get_tty_size, added tty_out parameter.
term.c (read_socket_hook): Removed first parameter.
(clear_end_of_line): Use updating_frame, if possible.
(write_glyphs, insert_glyphs, ins_del_lines): Ditto.
(term_init): Renamed get_frame_size to get_tty_size.
termchar.h (struct tty_output): New entries: top_frame,
previous_terminal_frame.
termhooks.h (read_socket_hook): Removed first parameter.
window.c (init_window_once): Removed reference to Vterminal_frame.
xdisp.c (previous_terminal_frame): Moved to struct tty_output.
(redisplay_internal): Updated to use previous_terminal_frame in tty_output.
Allow for simultaneous refresh of multiple ttys.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-5
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Fri, 26 Dec 2003 04:24:54 +0000 |
parents | 5c74e66d6c36 |
children | 22aaf1e5fbe6 |
comparison
equal
deleted
inserted
replaced
53228:c5b253fd2504 | 53229:33c3c7c16e13 |
---|---|
39 # include "vms-pwd.h" | 39 # include "vms-pwd.h" |
40 #else | 40 #else |
41 # include <pwd.h> | 41 # include <pwd.h> |
42 #endif /* not VMS */ | 42 #endif /* not VMS */ |
43 | 43 |
44 | |
45 /****************************************/ | |
46 | |
47 #include <errno.h> | |
48 #include <signal.h> | |
49 | |
50 #ifndef INCLUDED_FCNTL | |
51 #define INCLUDED_FCNTL | |
52 #include <fcntl.h> | |
53 #endif | |
54 | |
55 #ifdef HAVE_TERMIOS | |
56 #ifndef NO_TERMIO | |
57 #include <termio.h> | |
58 #endif | |
59 #include <termios.h> | |
60 #endif /* not HAVE_TERMIOS */ | |
61 | |
62 #ifdef __GNU_LIBRARY__ | |
63 #include <sys/ioctl.h> | |
64 #include <termios.h> | |
65 #endif | |
66 | |
67 #if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H) | |
68 #include <unistd.h> | |
69 #endif | |
70 | |
71 | |
72 | |
73 /* Try to establish the correct character to disable terminal functions | |
74 in a system-independent manner. Note that USG (at least) define | |
75 _POSIX_VDISABLE as 0! */ | |
76 | |
77 #ifdef _POSIX_VDISABLE | |
78 #define CDISABLE _POSIX_VDISABLE | |
79 #else /* not _POSIX_VDISABLE */ | |
80 #ifdef CDEL | |
81 #undef CDISABLE | |
82 #define CDISABLE CDEL | |
83 #else /* not CDEL */ | |
84 #define CDISABLE 255 | |
85 #endif /* not CDEL */ | |
86 #endif /* not _POSIX_VDISABLE */ | |
87 | |
88 | |
89 | |
90 /****************************************/ | |
91 | |
44 char *getenv (), *getwd (); | 92 char *getenv (), *getwd (); |
45 char *getcwd (); | 93 char *getcwd (); |
46 | 94 |
47 /* This is defined with -D from the compilation command, | 95 /* This is defined with -D from the compilation command, |
48 which extracts it from ../lisp/version.el. */ | 96 which extracts it from ../lisp/version.el. */ |
60 /* Nonzero means args are expressions to be evaluated. --eval. */ | 108 /* Nonzero means args are expressions to be evaluated. --eval. */ |
61 int eval = 0; | 109 int eval = 0; |
62 | 110 |
63 /* The display on which Emacs should work. --display. */ | 111 /* The display on which Emacs should work. --display. */ |
64 char *display = NULL; | 112 char *display = NULL; |
113 | |
114 /* Nonzero means open a new Emacs frame on the current terminal. */ | |
115 int here = 0; | |
65 | 116 |
66 /* If non-NULL, the name of an editor to fallback to if the server | 117 /* If non-NULL, the name of an editor to fallback to if the server |
67 is not running. --alternate-editor. */ | 118 is not running. --alternate-editor. */ |
68 const char * alternate_editor = NULL; | 119 const char * alternate_editor = NULL; |
69 | 120 |
76 { | 127 { |
77 { "no-wait", no_argument, NULL, 'n' }, | 128 { "no-wait", no_argument, NULL, 'n' }, |
78 { "eval", no_argument, NULL, 'e' }, | 129 { "eval", no_argument, NULL, 'e' }, |
79 { "help", no_argument, NULL, 'H' }, | 130 { "help", no_argument, NULL, 'H' }, |
80 { "version", no_argument, NULL, 'V' }, | 131 { "version", no_argument, NULL, 'V' }, |
132 { "here", no_argument, NULL, 'h' }, | |
81 { "alternate-editor", required_argument, NULL, 'a' }, | 133 { "alternate-editor", required_argument, NULL, 'a' }, |
82 { "socket-name", required_argument, NULL, 's' }, | 134 { "socket-name", required_argument, NULL, 's' }, |
83 { "display", required_argument, NULL, 'd' }, | 135 { "display", required_argument, NULL, 'd' }, |
84 { 0, 0, 0, 0 } | 136 { 0, 0, 0, 0 } |
85 }; | 137 }; |
93 char **argv; | 145 char **argv; |
94 { | 146 { |
95 while (1) | 147 while (1) |
96 { | 148 { |
97 int opt = getopt_long (argc, argv, | 149 int opt = getopt_long (argc, argv, |
98 "VHnea:s:d:", longopts, 0); | 150 "VHnea:s:d:h", longopts, 0); |
99 | 151 |
100 if (opt == EOF) | 152 if (opt == EOF) |
101 break; | 153 break; |
102 | 154 |
103 alternate_editor = getenv ("ALTERNATE_EDITOR"); | 155 alternate_editor = getenv ("ALTERNATE_EDITOR"); |
132 case 'V': | 184 case 'V': |
133 printf ("emacsclient %s\n", VERSION); | 185 printf ("emacsclient %s\n", VERSION); |
134 exit (0); | 186 exit (0); |
135 break; | 187 break; |
136 | 188 |
189 case 'h': | |
190 here = 1; | |
191 break; | |
192 | |
137 case 'H': | 193 case 'H': |
138 print_help_and_exit (); | 194 print_help_and_exit (); |
139 break; | 195 break; |
140 | 196 |
141 default: | 197 default: |
142 fprintf (stderr, "Try `%s --help' for more information\n", progname); | 198 fprintf (stderr, "Try `%s --help' for more information\n", progname); |
143 exit (1); | 199 exit (1); |
144 break; | 200 break; |
145 } | 201 } |
146 } | 202 } |
203 | |
204 if (here) { | |
205 nowait = 0; | |
206 display = 0; | |
207 } | |
208 | |
147 } | 209 } |
148 | 210 |
149 void | 211 void |
150 print_help_and_exit () | 212 print_help_and_exit () |
151 { | 213 { |
155 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ | 217 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ |
156 \n\ | 218 \n\ |
157 The following OPTIONS are accepted:\n\ | 219 The following OPTIONS are accepted:\n\ |
158 -V, --version Just print a version info and return\n\ | 220 -V, --version Just print a version info and return\n\ |
159 -H, --help Print this usage information message\n\ | 221 -H, --help Print this usage information message\n\ |
222 -h, --here Open a new Emacs frame on the current terminal\n\ | |
160 -n, --no-wait Don't wait for the server to return\n\ | 223 -n, --no-wait Don't wait for the server to return\n\ |
161 -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ | 224 -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ |
162 -d, --display=DISPLAY Visit the file in the given display\n\ | 225 -d, --display=DISPLAY Visit the file in the given display\n\ |
163 -s, --socket-name=FILENAME\n\ | 226 -s, --socket-name=FILENAME\n\ |
164 Set the filename of the UNIX socket for communication\n\ | 227 Set the filename of the UNIX socket for communication\n\ |
245 { | 308 { |
246 exit (1); | 309 exit (1); |
247 } | 310 } |
248 } | 311 } |
249 | 312 |
313 | |
314 #ifdef HAVE_TERMIOS | |
315 | |
316 /* Adapted from emacs_get_tty() in sysdep.c. */ | |
317 int | |
318 ec_get_tty (int fd, struct termios *settings) | |
319 { | |
320 bzero (settings, sizeof (struct termios)); | |
321 if (tcgetattr (fd, settings) < 0) | |
322 return -1; | |
323 return 0; | |
324 } | |
325 | |
326 /* Adapted from emacs_set_tty() in sysdep.c. */ | |
327 int | |
328 ec_set_tty (int fd, struct termios *settings, int flushp) | |
329 { | |
330 /* Set the primary parameters - baud rate, character size, etcetera. */ | |
331 | |
332 int i; | |
333 /* We have those nifty POSIX tcmumbleattr functions. | |
334 William J. Smith <wjs@wiis.wang.com> writes: | |
335 "POSIX 1003.1 defines tcsetattr to return success if it was | |
336 able to perform any of the requested actions, even if some | |
337 of the requested actions could not be performed. | |
338 We must read settings back to ensure tty setup properly. | |
339 AIX requires this to keep tty from hanging occasionally." */ | |
340 /* This make sure that we don't loop indefinitely in here. */ | |
341 for (i = 0 ; i < 10 ; i++) | |
342 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0) | |
343 { | |
344 if (errno == EINTR) | |
345 continue; | |
346 else | |
347 return -1; | |
348 } | |
349 else | |
350 { | |
351 struct termios new; | |
352 | |
353 bzero (&new, sizeof (new)); | |
354 /* Get the current settings, and see if they're what we asked for. */ | |
355 tcgetattr (fd, &new); | |
356 /* We cannot use memcmp on the whole structure here because under | |
357 * aix386 the termios structure has some reserved field that may | |
358 * not be filled in. | |
359 */ | |
360 if ( new.c_iflag == settings->c_iflag | |
361 && new.c_oflag == settings->c_oflag | |
362 && new.c_cflag == settings->c_cflag | |
363 && new.c_lflag == settings->c_lflag | |
364 && memcmp (new.c_cc, settings->c_cc, NCCS) == 0) | |
365 break; | |
366 else | |
367 continue; | |
368 } | |
369 return 0; | |
370 } | |
371 | |
372 int master; | |
373 char *pty_name; | |
374 | |
375 struct termios old_tty; | |
376 struct termios tty; | |
377 int old_tty_valid; | |
378 | |
379 int tty_erase_char; | |
380 int flow_control = 0; | |
381 int meta_key = 0; | |
382 char _sobuf[BUFSIZ]; | |
383 | |
384 /* Adapted from init_sys_modes() in sysdep.c. */ | |
385 int | |
386 init_tty () | |
387 { | |
388 if (! isatty (0)) | |
389 { | |
390 fprintf (stderr, "%s: Input is not a terminal", "init_tty"); | |
391 return 0; | |
392 } | |
393 | |
394 ec_get_tty (0, &old_tty); | |
395 old_tty_valid = 1; | |
396 tty = old_tty; | |
397 | |
398 tty_erase_char = old_tty.c_cc[VERASE]; | |
399 | |
400 tty.c_iflag |= (IGNBRK); /* Ignore break condition */ | |
401 tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ | |
402 #ifdef INLCR | |
403 tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ | |
404 #endif | |
405 #ifdef ISTRIP | |
406 tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ | |
407 #endif | |
408 tty.c_lflag &= ~ECHO; /* Disable echo */ | |
409 tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */ | |
410 #ifdef IEXTEN | |
411 tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ | |
412 #endif | |
413 tty.c_lflag |= ISIG; /* Enable signals */ | |
414 if (flow_control) | |
415 { | |
416 tty.c_iflag |= IXON; /* Enable start/stop output control */ | |
417 #ifdef IXANY | |
418 tty.c_iflag &= ~IXANY; | |
419 #endif /* IXANY */ | |
420 } | |
421 else | |
422 tty.c_iflag &= ~IXON; /* Disable start/stop output control */ | |
423 tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL | |
424 on output */ | |
425 tty.c_oflag &= ~TAB3; /* Disable tab expansion */ | |
426 #ifdef CS8 | |
427 if (meta_key) | |
428 { | |
429 tty.c_cflag |= CS8; /* allow 8th bit on input */ | |
430 tty.c_cflag &= ~PARENB; /* Don't check parity */ | |
431 } | |
432 #endif | |
433 tty.c_cc[VINTR] = CDISABLE; | |
434 tty.c_cc[VQUIT] = CDISABLE; | |
435 tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ | |
436 tty.c_cc[VTIME] = 0; /* no matter how long that takes. */ | |
437 #ifdef VSWTCH | |
438 tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */ | |
439 #endif | |
440 | |
441 #ifdef VSUSP | |
442 tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ | |
443 #endif /* VSUSP */ | |
444 #ifdef V_DSUSP | |
445 tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ | |
446 #endif /* V_DSUSP */ | |
447 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ | |
448 tty.c_cc[VDSUSP] = CDISABLE; | |
449 #endif /* VDSUSP */ | |
450 #ifdef VLNEXT | |
451 tty.c_cc[VLNEXT] = CDISABLE; | |
452 #endif /* VLNEXT */ | |
453 #ifdef VREPRINT | |
454 tty.c_cc[VREPRINT] = CDISABLE; | |
455 #endif /* VREPRINT */ | |
456 #ifdef VWERASE | |
457 tty.c_cc[VWERASE] = CDISABLE; | |
458 #endif /* VWERASE */ | |
459 #ifdef VDISCARD | |
460 tty.c_cc[VDISCARD] = CDISABLE; | |
461 #endif /* VDISCARD */ | |
462 | |
463 if (flow_control) | |
464 { | |
465 #ifdef VSTART | |
466 tty.c_cc[VSTART] = '\021'; | |
467 #endif /* VSTART */ | |
468 #ifdef VSTOP | |
469 tty.c_cc[VSTOP] = '\023'; | |
470 #endif /* VSTOP */ | |
471 } | |
472 else | |
473 { | |
474 #ifdef VSTART | |
475 tty.c_cc[VSTART] = CDISABLE; | |
476 #endif /* VSTART */ | |
477 #ifdef VSTOP | |
478 tty.c_cc[VSTOP] = CDISABLE; | |
479 #endif /* VSTOP */ | |
480 } | |
481 | |
482 #ifdef SET_LINE_DISCIPLINE | |
483 /* Need to explicitly request TERMIODISC line discipline or | |
484 Ultrix's termios does not work correctly. */ | |
485 tty.c_line = SET_LINE_DISCIPLINE; | |
486 #endif | |
487 | |
488 #ifdef AIX | |
489 #ifndef IBMR2AIX | |
490 /* AIX enhanced edit loses NULs, so disable it. */ | |
491 tty.c_line = 0; | |
492 tty.c_iflag &= ~ASCEDIT; | |
493 #else | |
494 tty.c_cc[VSTRT] = 255; | |
495 tty.c_cc[VSTOP] = 255; | |
496 tty.c_cc[VSUSP] = 255; | |
497 tty.c_cc[VDSUSP] = 255; | |
498 #endif /* IBMR2AIX */ | |
499 if (flow_control) | |
500 { | |
501 #ifdef VSTART | |
502 tty.c_cc[VSTART] = '\021'; | |
503 #endif /* VSTART */ | |
504 #ifdef VSTOP | |
505 tty.c_cc[VSTOP] = '\023'; | |
506 #endif /* VSTOP */ | |
507 } | |
508 /* Also, PTY overloads NUL and BREAK. | |
509 don't ignore break, but don't signal either, so it looks like NUL. | |
510 This really serves a purpose only if running in an XTERM window | |
511 or via TELNET or the like, but does no harm elsewhere. */ | |
512 tty.c_iflag &= ~IGNBRK; | |
513 tty.c_iflag &= ~BRKINT; | |
514 #endif /* AIX */ | |
515 | |
516 ec_set_tty (0, &tty, 0); | |
517 | |
518 /* This code added to insure that, if flow-control is not to be used, | |
519 we have an unlocked terminal at the start. */ | |
520 | |
521 #ifdef TCXONC | |
522 if (!flow_control) ioctl (0, TCXONC, 1); | |
523 #endif | |
524 #ifndef APOLLO | |
525 #ifdef TIOCSTART | |
526 if (!flow_control) ioctl (0, TIOCSTART, 0); | |
527 #endif | |
528 #endif | |
529 | |
530 #if defined (HAVE_TERMIOS) || defined (HPUX9) | |
531 #ifdef TCOON | |
532 if (!flow_control) tcflow (0, TCOON); | |
533 #endif | |
534 #endif | |
535 | |
536 #ifdef _IOFBF | |
537 /* This symbol is defined on recent USG systems. | |
538 Someone says without this call USG won't really buffer the file | |
539 even with a call to setbuf. */ | |
540 setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); | |
541 #else | |
542 setbuf (stdout, (char *) _sobuf); | |
543 #endif | |
544 | |
545 return 1; | |
546 } | |
547 | |
548 void | |
549 window_change () | |
550 { | |
551 int width, height; | |
552 | |
553 #ifdef TIOCGWINSZ | |
554 { | |
555 /* BSD-style. */ | |
556 struct winsize size; | |
557 | |
558 if (ioctl (0, TIOCGWINSZ, &size) == -1) | |
559 width = height = 0; | |
560 else | |
561 { | |
562 width = size.ws_col; | |
563 height = size.ws_row; | |
564 } | |
565 } | |
566 #else | |
567 #ifdef TIOCGSIZE | |
568 { | |
569 /* SunOS - style. */ | |
570 struct ttysize size; | |
571 | |
572 if (ioctl (0, TIOCGSIZE, &size) == -1) | |
573 width = height = 0; | |
574 else | |
575 { | |
576 width = size.ts_cols; | |
577 height = size.ts_lines; | |
578 } | |
579 } | |
580 #endif /* not SunOS-style */ | |
581 #endif /* not BSD-style */ | |
582 | |
583 #ifdef TIOCSWINSZ | |
584 { | |
585 /* BSD-style. */ | |
586 struct winsize size; | |
587 size.ws_row = height; | |
588 size.ws_col = width; | |
589 | |
590 ioctl (master, TIOCSWINSZ, &size); | |
591 } | |
592 #else | |
593 #ifdef TIOCSSIZE | |
594 { | |
595 /* SunOS - style. */ | |
596 struct ttysize size; | |
597 size.ts_lines = height; | |
598 size.ts_cols = width; | |
599 | |
600 ioctl (master, TIOCGSIZE, &size); | |
601 } | |
602 #endif /* not SunOS-style */ | |
603 #endif /* not BSD-style */ | |
604 } | |
605 | |
606 int in_conversation = 0; | |
607 int quit_conversation = 0; | |
608 | |
609 SIGTYPE | |
610 hang_up_signal (int signalnum) | |
611 { | |
612 int old_errno = errno; | |
613 | |
614 if (! in_conversation) | |
615 return; | |
616 | |
617 quit_conversation = 1; | |
618 | |
619 errno = old_errno; | |
620 } | |
621 | |
622 SIGTYPE | |
623 window_change_signal (int signalnum) | |
624 { | |
625 int old_errno = errno; | |
626 | |
627 if (! in_conversation) | |
628 goto end; | |
629 | |
630 window_change(); | |
631 | |
632 end: | |
633 signal (SIGWINCH, window_change_signal); | |
634 errno = old_errno; | |
635 } | |
636 | |
637 int | |
638 init_signals () | |
639 { | |
640 /* Set up signal handlers. */ | |
641 signal (SIGWINCH, window_change_signal); | |
642 signal (SIGHUP, hang_up_signal); | |
643 | |
644 return 1; | |
645 } | |
646 | |
647 | |
648 | |
649 /* Adapted from reset_sys_modes in sysdep.c. */ | |
650 int | |
651 reset_tty () | |
652 { | |
653 fflush (stdout); | |
654 #ifdef BSD_SYSTEM | |
655 #ifndef BSD4_1 | |
656 /* Avoid possible loss of output when changing terminal modes. */ | |
657 fsync (fileno (stdout)); | |
658 #endif | |
659 #endif | |
660 | |
661 #ifdef F_SETFL | |
662 #ifdef O_NDELAY | |
663 fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY); | |
664 #endif | |
665 #endif /* F_SETFL */ | |
666 | |
667 if (old_tty_valid) | |
668 while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR) | |
669 ; | |
670 | |
671 return 1; | |
672 } | |
673 | |
674 | |
675 int | |
676 init_pty () | |
677 { | |
678 master = getpt (); | |
679 if (master < 0) | |
680 return 0; | |
681 | |
682 if (grantpt (master) < 0 || unlockpt (master) < 0) | |
683 goto close_master; | |
684 pty_name = strdup (ptsname (master)); | |
685 if (! pty_name) | |
686 goto close_master; | |
687 | |
688 /* Propagate window size. */ | |
689 window_change (); | |
690 | |
691 return 1; | |
692 | |
693 close_master: | |
694 close (master); | |
695 return 0; | |
696 } | |
697 | |
698 int | |
699 copy_from_to (int in, int out) | |
700 { | |
701 static char buf[BUFSIZ]; | |
702 int nread = read (in, &buf, BUFSIZ); | |
703 if (nread == 0) | |
704 return 1; /* EOF */ | |
705 else if (nread < 0 && errno != EAGAIN) | |
706 return 0; /* Error */ | |
707 else if (nread > 0) | |
708 { | |
709 int r = 0; | |
710 int written = 0; | |
711 | |
712 do { | |
713 r = write (out, &buf, nread); | |
714 } while ((r < 0 && errno == EAGAIN) | |
715 || (r > 0 && (written += r) && written != nread)); | |
716 | |
717 if (r < 0) | |
718 return 0; /* Error */ | |
719 } | |
720 return 1; | |
721 } | |
722 | |
723 int | |
724 pty_conversation () | |
725 { | |
726 fd_set set; | |
727 | |
728 in_conversation = 1; | |
729 | |
730 while (! quit_conversation) { | |
731 int res; | |
732 | |
733 FD_ZERO (&set); | |
734 FD_SET (master, &set); | |
735 FD_SET (1, &set); | |
736 res = select (FD_SETSIZE, &set, NULL, NULL, NULL); | |
737 if (res < 0) | |
738 { | |
739 if (errno != EINTR) | |
740 return 0; | |
741 } | |
742 else if (res > 0) | |
743 { | |
744 if (FD_ISSET (master, &set)) | |
745 { | |
746 /* Copy Emacs output to stdout. */ | |
747 if (! copy_from_to (master, 0)) | |
748 return 1; | |
749 } | |
750 if (FD_ISSET (1, &set)) | |
751 { | |
752 /* Forward user input to Emacs. */ | |
753 if (! copy_from_to (1, master)) | |
754 return 1; | |
755 } | |
756 } | |
757 } | |
758 return 1; | |
759 } | |
760 | |
761 #endif /* HAVE_TERMIOS */ | |
250 | 762 |
251 | 763 |
252 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) | 764 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) |
253 | 765 |
254 int | 766 int |
310 progname = argv[0]; | 822 progname = argv[0]; |
311 | 823 |
312 /* Process options. */ | 824 /* Process options. */ |
313 decode_options (argc, argv); | 825 decode_options (argc, argv); |
314 | 826 |
315 if ((argc - optind < 1) && !eval) | 827 if ((argc - optind < 1) && !eval && !here) |
316 { | 828 { |
317 fprintf (stderr, "%s: file name or argument required\n", progname); | 829 fprintf (stderr, "%s: file name or argument required\n", progname); |
318 fprintf (stderr, "Try `%s --help' for more information\n", progname); | 830 fprintf (stderr, "Try `%s --help' for more information\n", progname); |
319 exit (1); | 831 exit (1); |
320 } | 832 } |
482 fprintf (out, "-display "); | 994 fprintf (out, "-display "); |
483 quote_file_name (display, out); | 995 quote_file_name (display, out); |
484 fprintf (out, " "); | 996 fprintf (out, " "); |
485 } | 997 } |
486 | 998 |
999 if (here) | |
1000 { | |
1001 if (! init_signals ()) | |
1002 { | |
1003 fprintf (stderr, "%s: ", argv[0]); | |
1004 perror ("fdopen"); | |
1005 fail (argc, argv); | |
1006 } | |
1007 | |
1008 if (! init_tty ()) | |
1009 { | |
1010 reset_tty (); | |
1011 fprintf (stderr, "%s: ", argv[0]); | |
1012 perror ("fdopen"); | |
1013 fail (argc, argv); | |
1014 } | |
1015 | |
1016 if (! init_pty ()) | |
1017 { | |
1018 reset_tty (); | |
1019 fprintf (stderr, "%s: ", argv[0]); | |
1020 perror ("fdopen"); | |
1021 fail (argc, argv); | |
1022 } | |
1023 | |
1024 fprintf (out, "-pty "); | |
1025 quote_file_name (pty_name, out); | |
1026 fprintf (out, " "); | |
1027 quote_file_name (getenv("TERM"), out); | |
1028 fprintf (out, " "); | |
1029 } | |
1030 | |
487 if ((argc - optind > 0)) | 1031 if ((argc - optind > 0)) |
488 { | 1032 { |
489 for (i = optind; i < argc; i++) | 1033 for (i = optind; i < argc; i++) |
490 { | 1034 { |
491 if (eval) | 1035 if (eval) |
510 fprintf (out, " "); | 1054 fprintf (out, " "); |
511 } | 1055 } |
512 } | 1056 } |
513 else | 1057 else |
514 { | 1058 { |
515 while ((str = fgets (string, BUFSIZ, stdin))) | 1059 if (!here) |
516 { | 1060 { |
517 quote_file_name (str, out); | 1061 while ((str = fgets (string, BUFSIZ, stdin))) |
518 } | 1062 { |
519 fprintf (out, " "); | 1063 quote_file_name (str, out); |
1064 } | |
1065 fprintf (out, " "); | |
1066 } | |
520 } | 1067 } |
521 | 1068 |
522 fprintf (out, "\n"); | 1069 fprintf (out, "\n"); |
523 fflush (out); | 1070 fflush (out); |
524 | 1071 |
525 /* Maybe wait for an answer. */ | 1072 /* Maybe wait for an answer. */ |
526 if (nowait) | 1073 if (nowait) |
527 return 0; | 1074 { |
528 | 1075 reset_tty (); |
1076 return 0; | |
1077 } | |
1078 | |
1079 if (here) | |
1080 { | |
1081 if (! pty_conversation ()) | |
1082 { | |
1083 reset_tty (); | |
1084 fprintf (stderr, "%s: ", argv[0]); | |
1085 perror ("fdopen"); | |
1086 fail (argc, argv); | |
1087 } | |
1088 close (master); | |
1089 reset_tty (); | |
1090 return 0; | |
1091 } | |
1092 | |
529 if (!eval) | 1093 if (!eval) |
530 { | 1094 { |
531 printf ("Waiting for Emacs..."); | 1095 printf ("Waiting for Emacs..."); |
532 needlf = 2; | 1096 needlf = 2; |
533 } | 1097 } |
544 | 1108 |
545 if (needlf) | 1109 if (needlf) |
546 printf ("\n"); | 1110 printf ("\n"); |
547 fflush (stdout); | 1111 fflush (stdout); |
548 | 1112 |
1113 reset_tty (); | |
549 return 0; | 1114 return 0; |
550 } | 1115 } |
551 | 1116 |
552 #endif /* HAVE_SOCKETS */ | 1117 #endif /* HAVE_SOCKETS */ |
553 | 1118 |