diff options
| author | Karoly Lorentey | 2004-01-03 08:31:14 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2004-01-03 08:31:14 +0000 |
| commit | 4d553a13abdadb4bb469bc0b59c003d48066dce5 (patch) | |
| tree | 0b84a435d41801417190e60bf89ffa0305c8c4ac /lib-src | |
| parent | b28c910d1f41815fa4744756852d5f2377d28636 (diff) | |
| download | emacs-4d553a13abdadb4bb469bc0b59c003d48066dce5.tar.gz emacs-4d553a13abdadb4bb469bc0b59c003d48066dce5.zip | |
Portability fixes (now it compiles & runs fine on Solaris).
lib-src/emacsclient.c: Removed tty proxy kludge. Emacs should just
use the same terminal as emacsclient.
(ec_get_tty, ec_set_tty, master, pty_name, old_tty, tty, old_tty_valid)
(tty_erase_char, quit_char, flow_control, meta_key, _sobuf, init_tty)
(window_change, reset_tty, init_pty, copy_from_to)
(pty_conversation): Removed.
(window_change_signal): Just forward the signal to Emacs, don't do
anything else.
(init_signals): Don't set handlers for SIGHUP & SIGINT.
(strprefix): New function.
(main): Don't touch the terminal, simply tell its name to Emacs.
lisp/server.el (server-frames): Changed name and semantics to server-ttys.
(server-tty-live-p): New function.
(server-sentinel): Delete the whole tty, not just the frame.
(server-handle-delete-frame): Removed.
(server-handle-delete-tty): New function. Close the client connection if
the tty is deleted.
(server-start): Clean up server-ttys, not server-frames. Set up
delete-tty-after-functions.
(server-process-filter): Set up server-ttys, not server-frames.
Updated protocol for sending our pid to emacsclient.
(server-buffer-done): Don't delete the client process directly, delete
the tty instead, and rely on the delete-tty hook to close the
connection. Otherwise the terminal could be left in a bad state.
src/cm.c (cmputc): Don't abort on write errors.
src/indent.c: #include <stdio.h>, for termchar.h.
src/window.c: Ditto.
src/xfaces.c: Ditto.
src/sysdep.c (init_sigio, reset_sigio, request_sigio)[!SIGIO]
(unrequest_sigio)[!SIGIO]: If SIGIO is not supported, don't do
anything. (For Solaris.)
(init_sys_modes): Moved tty_set_terminal_modes call back to here,
disable window system check.
(reset_sys_modes): Reset the terminal even if X is running.
src/term.c (Vdelete_tty_after_functions): New variable.
(syms_of_term): Initialize it.
(Fdelete_tty): Updated docs.
(delete_tty): Run delete-tty-after-functions.
(term_init): Removed tty_set_terminal_modes call.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-35
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacsclient.c | 638 |
1 files changed, 48 insertions, 590 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 741f5da2f1e..563a8ba9db0 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -41,54 +41,10 @@ Boston, MA 02111-1307, USA. */ | |||
| 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> | 44 | #include <signal.h> |
| 49 | 45 | #include <errno.h> | |
| 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 | 46 | ||
| 72 | 47 | ||
| 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 | |||
| 92 | char *getenv (), *getwd (); | 48 | char *getenv (), *getwd (); |
| 93 | char *getcwd (); | 49 | char *getcwd (); |
| 94 | 50 | ||
| @@ -314,532 +270,37 @@ fail (void) | |||
| 314 | } | 270 | } |
| 315 | } | 271 | } |
| 316 | 272 | ||
| 317 | |||
| 318 | #ifdef HAVE_TERMIOS | ||
| 319 | |||
| 320 | /* Adapted from emacs_get_tty() in sysdep.c. */ | ||
| 321 | int | ||
| 322 | ec_get_tty (int fd, struct termios *settings) | ||
| 323 | { | ||
| 324 | bzero (settings, sizeof (struct termios)); | ||
| 325 | if (tcgetattr (fd, settings) < 0) | ||
| 326 | return -1; | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* Adapted from emacs_set_tty() in sysdep.c. */ | ||
| 331 | int | ||
| 332 | ec_set_tty (int fd, struct termios *settings, int flushp) | ||
| 333 | { | ||
| 334 | /* Set the primary parameters - baud rate, character size, etcetera. */ | ||
| 335 | |||
| 336 | int i; | ||
| 337 | /* We have those nifty POSIX tcmumbleattr functions. | ||
| 338 | William J. Smith <wjs@wiis.wang.com> writes: | ||
| 339 | "POSIX 1003.1 defines tcsetattr to return success if it was | ||
| 340 | able to perform any of the requested actions, even if some | ||
| 341 | of the requested actions could not be performed. | ||
| 342 | We must read settings back to ensure tty setup properly. | ||
| 343 | AIX requires this to keep tty from hanging occasionally." */ | ||
| 344 | /* This make sure that we don't loop indefinitely in here. */ | ||
| 345 | for (i = 0 ; i < 10 ; i++) | ||
| 346 | if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0) | ||
| 347 | { | ||
| 348 | if (errno == EINTR) | ||
| 349 | continue; | ||
| 350 | else | ||
| 351 | return -1; | ||
| 352 | } | ||
| 353 | else | ||
| 354 | { | ||
| 355 | struct termios new; | ||
| 356 | |||
| 357 | bzero (&new, sizeof (new)); | ||
| 358 | /* Get the current settings, and see if they're what we asked for. */ | ||
| 359 | tcgetattr (fd, &new); | ||
| 360 | /* We cannot use memcmp on the whole structure here because under | ||
| 361 | * aix386 the termios structure has some reserved field that may | ||
| 362 | * not be filled in. | ||
| 363 | */ | ||
| 364 | if ( new.c_iflag == settings->c_iflag | ||
| 365 | && new.c_oflag == settings->c_oflag | ||
| 366 | && new.c_cflag == settings->c_cflag | ||
| 367 | && new.c_lflag == settings->c_lflag | ||
| 368 | && memcmp (new.c_cc, settings->c_cc, NCCS) == 0) | ||
| 369 | break; | ||
| 370 | else | ||
| 371 | continue; | ||
| 372 | } | ||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | int master; | ||
| 377 | char *pty_name; | ||
| 378 | |||
| 379 | struct termios old_tty; | ||
| 380 | struct termios tty; | ||
| 381 | int old_tty_valid; | ||
| 382 | |||
| 383 | int tty_erase_char; | ||
| 384 | int quit_char = 'g' & 037; | ||
| 385 | int flow_control = 0; | ||
| 386 | int meta_key = 0; | ||
| 387 | char _sobuf[BUFSIZ]; | ||
| 388 | int emacs_pid; | 273 | int emacs_pid; |
| 389 | 274 | ||
| 390 | /* Adapted from init_sys_modes() in sysdep.c. */ | 275 | #ifdef nec_ews_svr4 |
| 391 | int | 276 | extern char *_sobuf ; |
| 392 | init_tty () | ||
| 393 | { | ||
| 394 | if (! isatty (0)) | ||
| 395 | { | ||
| 396 | fprintf (stderr, "%s: Input is not a terminal", "init_tty"); | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | ec_get_tty (0, &old_tty); | ||
| 401 | old_tty_valid = 1; | ||
| 402 | tty = old_tty; | ||
| 403 | |||
| 404 | tty_erase_char = old_tty.c_cc[VERASE]; | ||
| 405 | |||
| 406 | tty.c_iflag |= (IGNBRK); /* Ignore break condition */ | ||
| 407 | tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ | ||
| 408 | #ifdef INLCR | ||
| 409 | tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ | ||
| 410 | #endif | ||
| 411 | #ifdef ISTRIP | ||
| 412 | tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ | ||
| 413 | #endif | ||
| 414 | tty.c_lflag &= ~ECHO; /* Disable echo */ | ||
| 415 | tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */ | ||
| 416 | #ifdef IEXTEN | ||
| 417 | tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ | ||
| 418 | #endif | ||
| 419 | tty.c_lflag |= ISIG; /* Enable signals */ | ||
| 420 | if (flow_control) | ||
| 421 | { | ||
| 422 | tty.c_iflag |= IXON; /* Enable start/stop output control */ | ||
| 423 | #ifdef IXANY | ||
| 424 | tty.c_iflag &= ~IXANY; | ||
| 425 | #endif /* IXANY */ | ||
| 426 | } | ||
| 427 | else | ||
| 428 | tty.c_iflag &= ~IXON; /* Disable start/stop output control */ | ||
| 429 | tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL | ||
| 430 | on output */ | ||
| 431 | tty.c_oflag &= ~TAB3; /* Disable tab expansion */ | ||
| 432 | #ifdef CS8 | ||
| 433 | if (meta_key) | ||
| 434 | { | ||
| 435 | tty.c_cflag |= CS8; /* allow 8th bit on input */ | ||
| 436 | tty.c_cflag &= ~PARENB; /* Don't check parity */ | ||
| 437 | } | ||
| 438 | #endif | ||
| 439 | tty.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */ | ||
| 440 | /* Set up C-g for both SIGQUIT and SIGINT. | ||
| 441 | We don't know which we will get, but we handle both alike | ||
| 442 | so which one it really gives us does not matter. */ | ||
| 443 | tty.c_cc[VQUIT] = quit_char; | ||
| 444 | tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ | ||
| 445 | tty.c_cc[VTIME] = 0; /* no matter how long that takes. */ | ||
| 446 | #ifdef VSWTCH | ||
| 447 | tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */ | ||
| 448 | #endif | ||
| 449 | |||
| 450 | #ifdef VSUSP | ||
| 451 | tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ | ||
| 452 | #endif /* VSUSP */ | ||
| 453 | #ifdef V_DSUSP | ||
| 454 | tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ | ||
| 455 | #endif /* V_DSUSP */ | ||
| 456 | #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ | ||
| 457 | tty.c_cc[VDSUSP] = CDISABLE; | ||
| 458 | #endif /* VDSUSP */ | ||
| 459 | #ifdef VLNEXT | ||
| 460 | tty.c_cc[VLNEXT] = CDISABLE; | ||
| 461 | #endif /* VLNEXT */ | ||
| 462 | #ifdef VREPRINT | ||
| 463 | tty.c_cc[VREPRINT] = CDISABLE; | ||
| 464 | #endif /* VREPRINT */ | ||
| 465 | #ifdef VWERASE | ||
| 466 | tty.c_cc[VWERASE] = CDISABLE; | ||
| 467 | #endif /* VWERASE */ | ||
| 468 | #ifdef VDISCARD | ||
| 469 | tty.c_cc[VDISCARD] = CDISABLE; | ||
| 470 | #endif /* VDISCARD */ | ||
| 471 | |||
| 472 | if (flow_control) | ||
| 473 | { | ||
| 474 | #ifdef VSTART | ||
| 475 | tty.c_cc[VSTART] = '\021'; | ||
| 476 | #endif /* VSTART */ | ||
| 477 | #ifdef VSTOP | ||
| 478 | tty.c_cc[VSTOP] = '\023'; | ||
| 479 | #endif /* VSTOP */ | ||
| 480 | } | ||
| 481 | else | ||
| 482 | { | ||
| 483 | #ifdef VSTART | ||
| 484 | tty.c_cc[VSTART] = CDISABLE; | ||
| 485 | #endif /* VSTART */ | ||
| 486 | #ifdef VSTOP | ||
| 487 | tty.c_cc[VSTOP] = CDISABLE; | ||
| 488 | #endif /* VSTOP */ | ||
| 489 | } | ||
| 490 | |||
| 491 | #ifdef SET_LINE_DISCIPLINE | ||
| 492 | /* Need to explicitly request TERMIODISC line discipline or | ||
| 493 | Ultrix's termios does not work correctly. */ | ||
| 494 | tty.c_line = SET_LINE_DISCIPLINE; | ||
| 495 | #endif | ||
| 496 | |||
| 497 | #ifdef AIX | ||
| 498 | #ifndef IBMR2AIX | ||
| 499 | /* AIX enhanced edit loses NULs, so disable it. */ | ||
| 500 | tty.c_line = 0; | ||
| 501 | tty.c_iflag &= ~ASCEDIT; | ||
| 502 | #else | 277 | #else |
| 503 | tty.c_cc[VSTRT] = 255; | 278 | #if defined (USG) || defined (DGUX) |
| 504 | tty.c_cc[VSTOP] = 255; | 279 | unsigned char _sobuf[BUFSIZ+8]; |
| 505 | tty.c_cc[VSUSP] = 255; | ||
| 506 | tty.c_cc[VDSUSP] = 255; | ||
| 507 | #endif /* IBMR2AIX */ | ||
| 508 | if (flow_control) | ||
| 509 | { | ||
| 510 | #ifdef VSTART | ||
| 511 | tty.c_cc[VSTART] = '\021'; | ||
| 512 | #endif /* VSTART */ | ||
| 513 | #ifdef VSTOP | ||
| 514 | tty.c_cc[VSTOP] = '\023'; | ||
| 515 | #endif /* VSTOP */ | ||
| 516 | } | ||
| 517 | /* Also, PTY overloads NUL and BREAK. | ||
| 518 | don't ignore break, but don't signal either, so it looks like NUL. | ||
| 519 | This really serves a purpose only if running in an XTERM window | ||
| 520 | or via TELNET or the like, but does no harm elsewhere. */ | ||
| 521 | tty.c_iflag &= ~IGNBRK; | ||
| 522 | tty.c_iflag &= ~BRKINT; | ||
| 523 | #endif /* AIX */ | ||
| 524 | |||
| 525 | ec_set_tty (0, &tty, 0); | ||
| 526 | |||
| 527 | /* This code added to insure that, if flow-control is not to be used, | ||
| 528 | we have an unlocked terminal at the start. */ | ||
| 529 | |||
| 530 | #ifdef TCXONC | ||
| 531 | if (!flow_control) ioctl (0, TCXONC, 1); | ||
| 532 | #endif | ||
| 533 | #ifndef APOLLO | ||
| 534 | #ifdef TIOCSTART | ||
| 535 | if (!flow_control) ioctl (0, TIOCSTART, 0); | ||
| 536 | #endif | ||
| 537 | #endif | ||
| 538 | |||
| 539 | #if defined (HAVE_TERMIOS) || defined (HPUX9) | ||
| 540 | #ifdef TCOON | ||
| 541 | if (!flow_control) tcflow (0, TCOON); | ||
| 542 | #endif | ||
| 543 | #endif | ||
| 544 | |||
| 545 | #ifdef _IOFBF | ||
| 546 | /* This symbol is defined on recent USG systems. | ||
| 547 | Someone says without this call USG won't really buffer the file | ||
| 548 | even with a call to setbuf. */ | ||
| 549 | setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); | ||
| 550 | #else | 280 | #else |
| 551 | setbuf (stdout, (char *) _sobuf); | 281 | char _sobuf[BUFSIZ]; |
| 282 | #endif | ||
| 552 | #endif | 283 | #endif |
| 553 | |||
| 554 | return 1; | ||
| 555 | } | ||
| 556 | |||
| 557 | void | ||
| 558 | window_change () | ||
| 559 | { | ||
| 560 | int width = 0, height = 0; | ||
| 561 | |||
| 562 | #ifdef TIOCGWINSZ | ||
| 563 | { | ||
| 564 | /* BSD-style. */ | ||
| 565 | struct winsize size; | ||
| 566 | |||
| 567 | if (ioctl (0, TIOCGWINSZ, &size) == -1) | ||
| 568 | width = height = 0; | ||
| 569 | else | ||
| 570 | { | ||
| 571 | width = size.ws_col; | ||
| 572 | height = size.ws_row; | ||
| 573 | } | ||
| 574 | } | ||
| 575 | #else | ||
| 576 | #ifdef TIOCGSIZE | ||
| 577 | { | ||
| 578 | /* SunOS - style. */ | ||
| 579 | struct ttysize size; | ||
| 580 | |||
| 581 | if (ioctl (0, TIOCGSIZE, &size) == -1) | ||
| 582 | width = height = 0; | ||
| 583 | else | ||
| 584 | { | ||
| 585 | width = size.ts_cols; | ||
| 586 | height = size.ts_lines; | ||
| 587 | } | ||
| 588 | } | ||
| 589 | #endif /* not SunOS-style */ | ||
| 590 | #endif /* not BSD-style */ | ||
| 591 | |||
| 592 | #ifdef TIOCSWINSZ | ||
| 593 | { | ||
| 594 | /* BSD-style. */ | ||
| 595 | struct winsize size; | ||
| 596 | size.ws_row = height; | ||
| 597 | size.ws_col = width; | ||
| 598 | |||
| 599 | ioctl (master, TIOCSWINSZ, &size); | ||
| 600 | } | ||
| 601 | #else | ||
| 602 | #ifdef TIOCSSIZE | ||
| 603 | { | ||
| 604 | /* SunOS - style. */ | ||
| 605 | struct ttysize size; | ||
| 606 | size.ts_lines = height; | ||
| 607 | size.ts_cols = width; | ||
| 608 | |||
| 609 | ioctl (master, TIOCGSIZE, &size); | ||
| 610 | } | ||
| 611 | #endif /* not SunOS-style */ | ||
| 612 | #endif /* not BSD-style */ | ||
| 613 | |||
| 614 | if (emacs_pid && width && height) | ||
| 615 | kill (emacs_pid, SIGWINCH); | ||
| 616 | } | ||
| 617 | |||
| 618 | int in_conversation = 0; | ||
| 619 | int quit_conversation = 0; | ||
| 620 | |||
| 621 | SIGTYPE | ||
| 622 | hang_up_signal (int signalnum) | ||
| 623 | { | ||
| 624 | int old_errno = errno; | ||
| 625 | |||
| 626 | if (! in_conversation) | ||
| 627 | return; | ||
| 628 | |||
| 629 | quit_conversation = 1; | ||
| 630 | |||
| 631 | errno = old_errno; | ||
| 632 | } | ||
| 633 | 284 | ||
| 634 | SIGTYPE | 285 | SIGTYPE |
| 635 | window_change_signal (int signalnum) | 286 | window_change_signal (int signalnum) |
| 636 | { | 287 | { |
| 637 | int old_errno = errno; | 288 | int old_errno = errno; |
| 638 | 289 | ||
| 639 | if (! in_conversation) | ||
| 640 | goto end; | ||
| 641 | |||
| 642 | window_change(); | ||
| 643 | |||
| 644 | end: | ||
| 645 | signal (SIGWINCH, window_change_signal); | ||
| 646 | errno = old_errno; | ||
| 647 | } | ||
| 648 | |||
| 649 | SIGTYPE | ||
| 650 | interrupt_signal (int signalnum) | ||
| 651 | { | ||
| 652 | int old_errno = errno; | ||
| 653 | |||
| 654 | /* Forward it to Emacs. */ | ||
| 655 | if (emacs_pid) | 290 | if (emacs_pid) |
| 656 | kill (emacs_pid, SIGINT); | 291 | kill (emacs_pid, SIGWINCH); |
| 657 | 292 | ||
| 293 | signal (SIGWINCH, window_change_signal); | ||
| 658 | errno = old_errno; | 294 | errno = old_errno; |
| 659 | } | 295 | } |
| 660 | 296 | ||
| 661 | int | 297 | void |
| 662 | init_signals () | 298 | init_signals (void) |
| 663 | { | 299 | { |
| 664 | /* Set up signal handlers. */ | 300 | /* Set up signal handlers. */ |
| 665 | signal (SIGWINCH, window_change_signal); | 301 | signal (SIGWINCH, window_change_signal); |
| 666 | signal (SIGHUP, hang_up_signal); | ||
| 667 | signal (SIGINT, interrupt_signal); | ||
| 668 | return 1; | ||
| 669 | } | ||
| 670 | |||
| 671 | |||
| 672 | |||
| 673 | /* Adapted from reset_sys_modes in sysdep.c. */ | ||
| 674 | int | ||
| 675 | reset_tty () | ||
| 676 | { | ||
| 677 | fflush (stdout); | ||
| 678 | #ifdef BSD_SYSTEM | ||
| 679 | #ifndef BSD4_1 | ||
| 680 | /* Avoid possible loss of output when changing terminal modes. */ | ||
| 681 | fsync (fileno (stdout)); | ||
| 682 | #endif | ||
| 683 | #endif | ||
| 684 | |||
| 685 | #ifdef F_SETFL | ||
| 686 | #ifdef O_NDELAY | ||
| 687 | fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY); | ||
| 688 | #endif | ||
| 689 | #endif /* F_SETFL */ | ||
| 690 | |||
| 691 | if (old_tty_valid) | ||
| 692 | while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR) | ||
| 693 | ; | ||
| 694 | |||
| 695 | return 1; | ||
| 696 | } | ||
| 697 | |||
| 698 | |||
| 699 | int | ||
| 700 | init_pty () | ||
| 701 | { | ||
| 702 | master = getpt (); | ||
| 703 | if (master < 0) | ||
| 704 | return 0; | ||
| 705 | |||
| 706 | if (grantpt (master) < 0 || unlockpt (master) < 0) | ||
| 707 | goto close_master; | ||
| 708 | pty_name = strdup (ptsname (master)); | ||
| 709 | if (! pty_name) | ||
| 710 | goto close_master; | ||
| 711 | |||
| 712 | /* Propagate window size. */ | ||
| 713 | window_change (); | ||
| 714 | |||
| 715 | return 1; | ||
| 716 | |||
| 717 | close_master: | ||
| 718 | close (master); | ||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | |||
| 722 | int | ||
| 723 | copy_from_to (int in, int out, int sigio) | ||
| 724 | { | ||
| 725 | static char buf[BUFSIZ]; | ||
| 726 | int nread = read (in, &buf, BUFSIZ); | ||
| 727 | if (nread == 0) | ||
| 728 | return 1; /* EOF */ | ||
| 729 | else if (nread < 0 && errno != EAGAIN) | ||
| 730 | return 0; | ||
| 731 | else if (nread > 0) | ||
| 732 | { | ||
| 733 | int r = 0; | ||
| 734 | int written = 0; | ||
| 735 | |||
| 736 | do { | ||
| 737 | r = write (out, &buf, nread); | ||
| 738 | } while ((r < 0 && errno == EINTR) | ||
| 739 | || (r > 0 && (written += r) && written != nread)); | ||
| 740 | |||
| 741 | if (r < 0) | ||
| 742 | return 0; | ||
| 743 | |||
| 744 | if (sigio && emacs_pid) | ||
| 745 | kill (emacs_pid, SIGIO); | ||
| 746 | } | ||
| 747 | return 1; | ||
| 748 | } | ||
| 749 | |||
| 750 | int | ||
| 751 | pty_conversation (FILE *in) | ||
| 752 | { | ||
| 753 | char *str; | ||
| 754 | char string[BUFSIZ]; | ||
| 755 | fd_set set, rset; | ||
| 756 | int res; | ||
| 757 | |||
| 758 | FD_ZERO (&set); | ||
| 759 | FD_SET (master, &set); | ||
| 760 | FD_SET (1, &set); | ||
| 761 | FD_SET (fileno (in), &set); | ||
| 762 | |||
| 763 | in_conversation = 1; | ||
| 764 | |||
| 765 | while (! quit_conversation) { | ||
| 766 | rset = set; | ||
| 767 | res = select (FD_SETSIZE, &rset, NULL, NULL, NULL); | ||
| 768 | if (res < 0 && errno != EINTR) | ||
| 769 | { | ||
| 770 | reset_tty (); | ||
| 771 | fprintf (stderr, "%s: ", progname); | ||
| 772 | perror ("select"); | ||
| 773 | return 0; /* Error */ | ||
| 774 | } | ||
| 775 | else if (res > 0) | ||
| 776 | { | ||
| 777 | if (FD_ISSET (master, &rset)) | ||
| 778 | { | ||
| 779 | /* Copy Emacs output to stdout. */ | ||
| 780 | if (! copy_from_to (master, 0, 0)) | ||
| 781 | { | ||
| 782 | FD_CLR (master, &set); | ||
| 783 | } | ||
| 784 | } | ||
| 785 | if (FD_ISSET (1, &rset)) | ||
| 786 | { | ||
| 787 | /* Forward user input to Emacs. */ | ||
| 788 | if (! copy_from_to (1, master, 1)) | ||
| 789 | { | ||
| 790 | FD_CLR (master, &set); | ||
| 791 | } | ||
| 792 | } | ||
| 793 | if (FD_ISSET (fileno (in), &rset)) | ||
| 794 | { | ||
| 795 | do { | ||
| 796 | res = read (fileno (in), string, BUFSIZ-1); | ||
| 797 | } while (res < 0 && errno == EINTR); | ||
| 798 | if (res < 0) | ||
| 799 | { | ||
| 800 | reset_tty (); | ||
| 801 | fprintf (stderr, "%s: ", progname); | ||
| 802 | perror ("read"); | ||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | if (!res) | ||
| 806 | { | ||
| 807 | return 1; | ||
| 808 | } | ||
| 809 | |||
| 810 | string[res] = 0; | ||
| 811 | if (string[res-1] == '\n') | ||
| 812 | string[res-1] = 0; | ||
| 813 | |||
| 814 | if (! emacs_pid) | ||
| 815 | { | ||
| 816 | /* Get the pid of the Emacs process. | ||
| 817 | XXX Is there some nifty libc/kernel feature for doing this? | ||
| 818 | */ | ||
| 819 | if (! string[0]) | ||
| 820 | { | ||
| 821 | reset_tty (); | ||
| 822 | fprintf (stderr, "%s: could not get Emacs process id\n" | ||
| 823 | "Maybe this Emacs does not support multiple terminals.\n", progname); | ||
| 824 | return 0; | ||
| 825 | } | ||
| 826 | emacs_pid = strtol (string, NULL, 10); | ||
| 827 | } | ||
| 828 | |||
| 829 | if (! emacs_pid) /* emacs_pid should be set above */ | ||
| 830 | { | ||
| 831 | reset_tty (); | ||
| 832 | fprintf (stderr, "%s: %s\n", progname, string); | ||
| 833 | return 0; | ||
| 834 | } | ||
| 835 | } | ||
| 836 | } | ||
| 837 | } | ||
| 838 | return 1; | ||
| 839 | } | 302 | } |
| 840 | 303 | ||
| 841 | #endif /* HAVE_TERMIOS */ | ||
| 842 | |||
| 843 | 304 | ||
| 844 | #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) | 305 | #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) |
| 845 | 306 | ||
| @@ -886,6 +347,23 @@ socket_status (socket_name) | |||
| 886 | return 0; | 347 | return 0; |
| 887 | } | 348 | } |
| 888 | 349 | ||
| 350 | /* Returns 1 if PREFIX is a prefix of STRING. */ | ||
| 351 | static int | ||
| 352 | strprefix (char *prefix, char *string) | ||
| 353 | { | ||
| 354 | int i; | ||
| 355 | if (! prefix) | ||
| 356 | return 1; | ||
| 357 | |||
| 358 | if (!string) | ||
| 359 | return 0; | ||
| 360 | |||
| 361 | for (i = 0; prefix[i]; i++) | ||
| 362 | if (!string[i] || string[i] != prefix[i]) | ||
| 363 | return 0; | ||
| 364 | return 1; | ||
| 365 | } | ||
| 366 | |||
| 889 | int | 367 | int |
| 890 | main (argc, argv) | 368 | main (argc, argv) |
| 891 | int argc; | 369 | int argc; |
| @@ -1086,31 +564,14 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 1086 | 564 | ||
| 1087 | if (frame) | 565 | if (frame) |
| 1088 | { | 566 | { |
| 1089 | if (! init_signals ()) | 567 | char *tty_name = ttyname (fileno (stdin)); |
| 1090 | { | 568 | if (! tty_name) |
| 1091 | fprintf (stderr, "%s: ", argv[0]); | 569 | fail (); |
| 1092 | perror ("fdopen"); | ||
| 1093 | fail (); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | if (! init_tty ()) | ||
| 1097 | { | ||
| 1098 | reset_tty (); | ||
| 1099 | fprintf (stderr, "%s: ", argv[0]); | ||
| 1100 | perror ("fdopen"); | ||
| 1101 | fail (); | ||
| 1102 | } | ||
| 1103 | 570 | ||
| 1104 | if (! init_pty ()) | 571 | init_signals (); |
| 1105 | { | ||
| 1106 | reset_tty (); | ||
| 1107 | fprintf (stderr, "%s: ", argv[0]); | ||
| 1108 | perror ("fdopen"); | ||
| 1109 | fail (); | ||
| 1110 | } | ||
| 1111 | 572 | ||
| 1112 | fprintf (out, "-tty "); | 573 | fprintf (out, "-tty "); |
| 1113 | quote_file_name (pty_name, out); | 574 | quote_file_name (tty_name, out); |
| 1114 | fprintf (out, " "); | 575 | fprintf (out, " "); |
| 1115 | quote_file_name (getenv("TERM"), out); | 576 | quote_file_name (getenv("TERM"), out); |
| 1116 | fprintf (out, " "); | 577 | fprintf (out, " "); |
| @@ -1160,22 +621,10 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 1160 | /* Maybe wait for an answer. */ | 621 | /* Maybe wait for an answer. */ |
| 1161 | if (nowait) | 622 | if (nowait) |
| 1162 | { | 623 | { |
| 1163 | reset_tty (); | ||
| 1164 | return 0; | 624 | return 0; |
| 1165 | } | 625 | } |
| 1166 | 626 | ||
| 1167 | if (frame) | 627 | if (!eval && !frame) |
| 1168 | { | ||
| 1169 | if (! pty_conversation (out)) | ||
| 1170 | { | ||
| 1171 | reset_tty (); | ||
| 1172 | fail (); | ||
| 1173 | } | ||
| 1174 | reset_tty (); | ||
| 1175 | return 0; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | if (!eval) | ||
| 1179 | { | 628 | { |
| 1180 | printf ("Waiting for Emacs..."); | 629 | printf ("Waiting for Emacs..."); |
| 1181 | needlf = 2; | 630 | needlf = 2; |
| @@ -1185,17 +634,26 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 1185 | /* Now, wait for an answer and print any messages. */ | 634 | /* Now, wait for an answer and print any messages. */ |
| 1186 | while ((str = fgets (string, BUFSIZ, in))) | 635 | while ((str = fgets (string, BUFSIZ, in))) |
| 1187 | { | 636 | { |
| 1188 | if (needlf == 2) | 637 | if (frame) |
| 1189 | printf ("\n"); | 638 | { |
| 1190 | printf ("%s", str); | 639 | if (strprefix ("emacs-pid ", str)) |
| 1191 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 640 | { |
| 641 | emacs_pid = strtol (string + strlen ("emacs-pid"), NULL, 10); | ||
| 642 | } | ||
| 643 | } | ||
| 644 | else | ||
| 645 | { | ||
| 646 | if (needlf == 2) | ||
| 647 | printf ("\n"); | ||
| 648 | printf ("%s", str); | ||
| 649 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 650 | } | ||
| 1192 | } | 651 | } |
| 1193 | 652 | ||
| 1194 | if (needlf) | 653 | if (needlf) |
| 1195 | printf ("\n"); | 654 | printf ("\n"); |
| 1196 | fflush (stdout); | 655 | fflush (stdout); |
| 1197 | 656 | ||
| 1198 | reset_tty (); | ||
| 1199 | return 0; | 657 | return 0; |
| 1200 | } | 658 | } |
| 1201 | 659 | ||