diff options
Diffstat (limited to 'lib-src/emacsclient.c')
| -rw-r--r-- | lib-src/emacsclient.c | 575 |
1 files changed, 258 insertions, 317 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 5e1c2d61b89..021ac6eb247 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* Client process that communicates with GNU Emacs acting as server. | 1 | /* Client process that communicates with GNU Emacs acting as server. |
| 2 | Copyright (C) 1986-1987, 1994, 1999-2011 Free Software Foundation, Inc. | 2 | |
| 3 | Copyright (C) 1986-1987, 1994, 1999-2012 Free Software Foundation, Inc. | ||
| 3 | 4 | ||
| 4 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 5 | 6 | ||
| @@ -21,7 +22,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 21 | 22 | ||
| 22 | #ifdef WINDOWSNT | 23 | #ifdef WINDOWSNT |
| 23 | 24 | ||
| 24 | /* config.h defines these, which disables sockets altogether! */ | 25 | /* ms-w32.h defines these, which disables sockets altogether! */ |
| 25 | # undef _WINSOCKAPI_ | 26 | # undef _WINSOCKAPI_ |
| 26 | # undef _WINSOCK_H | 27 | # undef _WINSOCK_H |
| 27 | 28 | ||
| @@ -43,6 +44,10 @@ char *w32_getenv (char *); | |||
| 43 | 44 | ||
| 44 | #else /* !WINDOWSNT */ | 45 | #else /* !WINDOWSNT */ |
| 45 | 46 | ||
| 47 | # ifdef HAVE_NTGUI | ||
| 48 | # include <windows.h> | ||
| 49 | # endif /* HAVE_NTGUI */ | ||
| 50 | |||
| 46 | # include "syswait.h" | 51 | # include "syswait.h" |
| 47 | 52 | ||
| 48 | # ifdef HAVE_INET_SOCKETS | 53 | # ifdef HAVE_INET_SOCKETS |
| @@ -83,10 +88,7 @@ char *w32_getenv (char *); | |||
| 83 | 88 | ||
| 84 | 89 | ||
| 85 | 90 | ||
| 86 | char *getenv (const char *), *getwd (char *); | 91 | char *getenv (const char *); |
| 87 | #ifdef HAVE_GETCWD | ||
| 88 | char *(getcwd) (char *, size_t); | ||
| 89 | #endif | ||
| 90 | 92 | ||
| 91 | #ifndef VERSION | 93 | #ifndef VERSION |
| 92 | #define VERSION "unspecified" | 94 | #define VERSION "unspecified" |
| @@ -112,12 +114,10 @@ char *(getcwd) (char *, size_t); | |||
| 112 | /* Additional space when allocating buffers for filenames, etc. */ | 114 | /* Additional space when allocating buffers for filenames, etc. */ |
| 113 | #define EXTRA_SPACE 100 | 115 | #define EXTRA_SPACE 100 |
| 114 | 116 | ||
| 115 | /* Use this to suppress gcc's `...may be used before initialized' warnings. */ | 117 | #ifdef min |
| 116 | #ifdef lint | 118 | #undef min |
| 117 | # define IF_LINT(Code) Code | ||
| 118 | #else | ||
| 119 | # define IF_LINT(Code) /* empty */ | ||
| 120 | #endif | 119 | #endif |
| 120 | #define min(x, y) (((x) < (y)) ? (x) : (y)) | ||
| 121 | 121 | ||
| 122 | 122 | ||
| 123 | /* Name used to invoke this program. */ | 123 | /* Name used to invoke this program. */ |
| @@ -141,6 +141,9 @@ int current_frame = 1; | |||
| 141 | /* The display on which Emacs should work. --display. */ | 141 | /* The display on which Emacs should work. --display. */ |
| 142 | const char *display = NULL; | 142 | const char *display = NULL; |
| 143 | 143 | ||
| 144 | /* The alternate display we should try if Emacs does not support display. */ | ||
| 145 | const char *alt_display = NULL; | ||
| 146 | |||
| 144 | /* The parent window ID, if we are opening a frame via XEmbed. */ | 147 | /* The parent window ID, if we are opening a frame via XEmbed. */ |
| 145 | char *parent_id = NULL; | 148 | char *parent_id = NULL; |
| 146 | 149 | ||
| @@ -152,7 +155,7 @@ int tty = 0; | |||
| 152 | const char *alternate_editor = NULL; | 155 | const char *alternate_editor = NULL; |
| 153 | 156 | ||
| 154 | /* If non-NULL, the filename of the UNIX socket. */ | 157 | /* If non-NULL, the filename of the UNIX socket. */ |
| 155 | char *socket_name = NULL; | 158 | const char *socket_name = NULL; |
| 156 | 159 | ||
| 157 | /* If non-NULL, the filename of the authentication file. */ | 160 | /* If non-NULL, the filename of the authentication file. */ |
| 158 | const char *server_file = NULL; | 161 | const char *server_file = NULL; |
| @@ -164,8 +167,7 @@ int emacs_pid = 0; | |||
| 164 | be used for the new frame */ | 167 | be used for the new frame */ |
| 165 | const char *frame_parameters = NULL; | 168 | const char *frame_parameters = NULL; |
| 166 | 169 | ||
| 167 | static void print_help_and_exit (void) NO_RETURN; | 170 | static _Noreturn void print_help_and_exit (void); |
| 168 | static void fail (void) NO_RETURN; | ||
| 169 | 171 | ||
| 170 | 172 | ||
| 171 | struct option longopts[] = | 173 | struct option longopts[] = |
| @@ -184,9 +186,7 @@ struct option longopts[] = | |||
| 184 | { "socket-name", required_argument, NULL, 's' }, | 186 | { "socket-name", required_argument, NULL, 's' }, |
| 185 | #endif | 187 | #endif |
| 186 | { "server-file", required_argument, NULL, 'f' }, | 188 | { "server-file", required_argument, NULL, 'f' }, |
| 187 | #ifndef WINDOWSNT | ||
| 188 | { "display", required_argument, NULL, 'd' }, | 189 | { "display", required_argument, NULL, 'd' }, |
| 189 | #endif | ||
| 190 | { "parent-id", required_argument, NULL, 'p' }, | 190 | { "parent-id", required_argument, NULL, 'p' }, |
| 191 | { 0, 0, 0, 0 } | 191 | { 0, 0, 0, 0 } |
| 192 | }; | 192 | }; |
| @@ -209,21 +209,6 @@ xmalloc (size_t size) | |||
| 209 | /* From sysdep.c */ | 209 | /* From sysdep.c */ |
| 210 | #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME) | 210 | #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME) |
| 211 | 211 | ||
| 212 | /* From lisp.h */ | ||
| 213 | #ifndef DIRECTORY_SEP | ||
| 214 | #define DIRECTORY_SEP '/' | ||
| 215 | #endif | ||
| 216 | #ifndef IS_DIRECTORY_SEP | ||
| 217 | #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) | ||
| 218 | #endif | ||
| 219 | #ifndef IS_DEVICE_SEP | ||
| 220 | #ifndef DEVICE_SEP | ||
| 221 | #define IS_DEVICE_SEP(_c_) 0 | ||
| 222 | #else | ||
| 223 | #define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP) | ||
| 224 | #endif | ||
| 225 | #endif | ||
| 226 | |||
| 227 | char *get_current_dir_name (void); | 212 | char *get_current_dir_name (void); |
| 228 | 213 | ||
| 229 | /* Return the current working directory. Returns NULL on errors. | 214 | /* Return the current working directory. Returns NULL on errors. |
| @@ -235,7 +220,7 @@ get_current_dir_name (void) | |||
| 235 | char *buf; | 220 | char *buf; |
| 236 | const char *pwd; | 221 | const char *pwd; |
| 237 | struct stat dotstat, pwdstat; | 222 | struct stat dotstat, pwdstat; |
| 238 | /* If PWD is accurate, use it instead of calling getwd. PWD is | 223 | /* If PWD is accurate, use it instead of calling getcwd. PWD is |
| 239 | sometimes a nicer name, and using it may avoid a fatal error if a | 224 | sometimes a nicer name, and using it may avoid a fatal error if a |
| 240 | parent directory is searchable but not readable. */ | 225 | parent directory is searchable but not readable. */ |
| 241 | if ((pwd = egetenv ("PWD")) != 0 | 226 | if ((pwd = egetenv ("PWD")) != 0 |
| @@ -252,7 +237,6 @@ get_current_dir_name (void) | |||
| 252 | buf = (char *) xmalloc (strlen (pwd) + 1); | 237 | buf = (char *) xmalloc (strlen (pwd) + 1); |
| 253 | strcpy (buf, pwd); | 238 | strcpy (buf, pwd); |
| 254 | } | 239 | } |
| 255 | #ifdef HAVE_GETCWD | ||
| 256 | else | 240 | else |
| 257 | { | 241 | { |
| 258 | size_t buf_size = 1024; | 242 | size_t buf_size = 1024; |
| @@ -279,20 +263,6 @@ get_current_dir_name (void) | |||
| 279 | } | 263 | } |
| 280 | } | 264 | } |
| 281 | } | 265 | } |
| 282 | #else | ||
| 283 | else | ||
| 284 | { | ||
| 285 | /* We need MAXPATHLEN here. */ | ||
| 286 | buf = (char *) xmalloc (MAXPATHLEN + 1); | ||
| 287 | if (getwd (buf) == NULL) | ||
| 288 | { | ||
| 289 | int tmp_errno = errno; | ||
| 290 | free (buf); | ||
| 291 | errno = tmp_errno; | ||
| 292 | return NULL; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | #endif | ||
| 296 | return buf; | 266 | return buf; |
| 297 | } | 267 | } |
| 298 | #endif | 268 | #endif |
| @@ -402,32 +372,6 @@ w32_getenv (char *envvar) | |||
| 402 | return NULL; | 372 | return NULL; |
| 403 | } | 373 | } |
| 404 | 374 | ||
| 405 | void | ||
| 406 | w32_set_user_model_id (void) | ||
| 407 | { | ||
| 408 | HMODULE shell; | ||
| 409 | HRESULT (WINAPI * set_user_model) (wchar_t * id); | ||
| 410 | |||
| 411 | /* On Windows 7 and later, we need to set the user model ID | ||
| 412 | to associate emacsclient launched files with Emacs frames | ||
| 413 | in the UI. */ | ||
| 414 | shell = LoadLibrary ("shell32.dll"); | ||
| 415 | if (shell) | ||
| 416 | { | ||
| 417 | set_user_model | ||
| 418 | = (void *) GetProcAddress (shell, | ||
| 419 | "SetCurrentProcessExplicitAppUserModelID"); | ||
| 420 | /* If the function is defined, then we are running on Windows 7 | ||
| 421 | or newer, and the UI uses this to group related windows | ||
| 422 | together. Since emacs, runemacs, emacsclient are related, we | ||
| 423 | want them grouped even though the executables are different, | ||
| 424 | so we need to set a consistent ID between them. */ | ||
| 425 | if (set_user_model) | ||
| 426 | set_user_model (L"GNU.Emacs"); | ||
| 427 | |||
| 428 | FreeLibrary (shell); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | 375 | ||
| 432 | int | 376 | int |
| 433 | w32_window_app (void) | 377 | w32_window_app (void) |
| @@ -447,19 +391,19 @@ w32_window_app (void) | |||
| 447 | return window_app; | 391 | return window_app; |
| 448 | } | 392 | } |
| 449 | 393 | ||
| 450 | /* | 394 | /* execvp wrapper for Windows. Quotes arguments with embedded spaces. |
| 451 | execvp wrapper for Windows. Quotes arguments with embedded spaces. | ||
| 452 | 395 | ||
| 453 | This is necessary due to the broken implementation of exec* routines in | 396 | This is necessary due to the broken implementation of exec* routines in |
| 454 | the Microsoft libraries: they concatenate the arguments together without | 397 | the Microsoft libraries: they concatenate the arguments together without |
| 455 | quoting special characters, and pass the result to CreateProcess, with | 398 | quoting special characters, and pass the result to CreateProcess, with |
| 456 | predictably bad results. By contrast, POSIX execvp passes the arguments | 399 | predictably bad results. By contrast, POSIX execvp passes the arguments |
| 457 | directly into the argv array of the child process. | 400 | directly into the argv array of the child process. */ |
| 458 | */ | 401 | |
| 459 | int | 402 | int |
| 460 | w32_execvp (const char *path, char **argv) | 403 | w32_execvp (const char *path, char **argv) |
| 461 | { | 404 | { |
| 462 | int i; | 405 | int i; |
| 406 | extern int execvp (const char*, char **); | ||
| 463 | 407 | ||
| 464 | /* Required to allow a .BAT script as alternate editor. */ | 408 | /* Required to allow a .BAT script as alternate editor. */ |
| 465 | argv[0] = (char *) alternate_editor; | 409 | argv[0] = (char *) alternate_editor; |
| @@ -622,48 +566,52 @@ decode_options (int argc, char **argv) | |||
| 622 | Without the -c option, we used to set `display' to $DISPLAY by | 566 | Without the -c option, we used to set `display' to $DISPLAY by |
| 623 | default, but this changed the default behavior and is sometimes | 567 | default, but this changed the default behavior and is sometimes |
| 624 | inconvenient. So we force users to use "--display $DISPLAY" if | 568 | inconvenient. So we force users to use "--display $DISPLAY" if |
| 625 | they want Emacs to connect to their current display. */ | 569 | they want Emacs to connect to their current display. |
| 570 | |||
| 571 | Some window systems have a notion of default display not | ||
| 572 | reflected in the DISPLAY variable. If the user didn't give us an | ||
| 573 | explicit display, try this platform-specific after trying the | ||
| 574 | display in DISPLAY (if any). */ | ||
| 626 | if (!current_frame && !tty && !display) | 575 | if (!current_frame && !tty && !display) |
| 627 | { | 576 | { |
| 628 | display = egetenv ("DISPLAY"); | 577 | /* Set these here so we use a default_display only when the user |
| 629 | #ifdef NS_IMPL_COCOA | 578 | didn't give us an explicit display. */ |
| 630 | /* Under Cocoa, we don't really use displays the same way as in X, | 579 | #if defined (NS_IMPL_COCOA) |
| 631 | so provide a dummy. */ | 580 | alt_display = "ns"; |
| 632 | if (!display || strlen (display) == 0) | 581 | #elif defined (HAVE_NTGUI) |
| 633 | display = "ns"; | 582 | alt_display = "w32"; |
| 634 | #endif | 583 | #endif |
| 584 | |||
| 585 | display = egetenv ("DISPLAY"); | ||
| 586 | } | ||
| 587 | |||
| 588 | if (!display) | ||
| 589 | { | ||
| 590 | display = alt_display; | ||
| 591 | alt_display = NULL; | ||
| 635 | } | 592 | } |
| 636 | 593 | ||
| 637 | /* A null-string display is invalid. */ | 594 | /* A null-string display is invalid. */ |
| 638 | if (display && strlen (display) == 0) | 595 | if (display && strlen (display) == 0) |
| 639 | display = NULL; | 596 | display = NULL; |
| 640 | 597 | ||
| 641 | #ifdef WINDOWSNT | ||
| 642 | /* Emacs on Windows does not support GUI and console frames in the same | ||
| 643 | instance. So, it makes sense to treat the -t and -c options as | ||
| 644 | equivalent, and open a new frame regardless of whether the running | ||
| 645 | instance is GUI or console. Ideally, we would only set tty = 1 when | ||
| 646 | the instance is running in a console, but alas we don't know that. | ||
| 647 | The simplest workaround is to always ask for a tty frame, and let | ||
| 648 | server.el check whether it makes sense. */ | ||
| 649 | if (tty || !current_frame) | ||
| 650 | { | ||
| 651 | display = (const char *) ttyname; | ||
| 652 | current_frame = 0; | ||
| 653 | tty = 1; | ||
| 654 | } | ||
| 655 | #endif | ||
| 656 | |||
| 657 | /* If no display is available, new frames are tty frames. */ | 598 | /* If no display is available, new frames are tty frames. */ |
| 658 | if (!current_frame && !display) | 599 | if (!current_frame && !display) |
| 659 | tty = 1; | 600 | tty = 1; |
| 660 | 601 | ||
| 661 | /* --no-wait implies --current-frame on ttys when there are file | ||
| 662 | arguments or expressions given. */ | ||
| 663 | if (nowait && tty && argc - optind > 0) | ||
| 664 | current_frame = 1; | ||
| 665 | |||
| 666 | #ifdef WINDOWSNT | 602 | #ifdef WINDOWSNT |
| 603 | /* Emacs on Windows does not support graphical and text terminal | ||
| 604 | frames in the same instance. So, treat the -t and -c options as | ||
| 605 | equivalent, and open a new frame on the server's terminal. | ||
| 606 | Ideally, we would only set tty = 1 when the serve is running in a | ||
| 607 | console, but alas we don't know that. As a workaround, always | ||
| 608 | ask for a tty frame, and let server.el figure it out. */ | ||
| 609 | if (!current_frame) | ||
| 610 | { | ||
| 611 | display = NULL; | ||
| 612 | tty = 1; | ||
| 613 | } | ||
| 614 | |||
| 667 | if (alternate_editor && alternate_editor[0] == '\0') | 615 | if (alternate_editor && alternate_editor[0] == '\0') |
| 668 | { | 616 | { |
| 669 | message (TRUE, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\ | 617 | message (TRUE, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\ |
| @@ -674,7 +622,7 @@ an empty string"); | |||
| 674 | } | 622 | } |
| 675 | 623 | ||
| 676 | 624 | ||
| 677 | static void | 625 | static _Noreturn void |
| 678 | print_help_and_exit (void) | 626 | print_help_and_exit (void) |
| 679 | { | 627 | { |
| 680 | /* Spaces and tabs are significant in this message; they're chosen so the | 628 | /* Spaces and tabs are significant in this message; they're chosen so the |
| @@ -717,12 +665,11 @@ Report bugs with M-x report-emacs-bug.\n", progname); | |||
| 717 | exit (EXIT_SUCCESS); | 665 | exit (EXIT_SUCCESS); |
| 718 | } | 666 | } |
| 719 | 667 | ||
| 720 | /* | 668 | /* Try to run a different command, or --if no alternate editor is |
| 721 | Try to run a different command, or --if no alternate editor is | 669 | defined-- exit with an errorcode. |
| 722 | defined-- exit with an errorcode. | 670 | Uses argv, but gets it from the global variable main_argv. */ |
| 723 | Uses argv, but gets it from the global variable main_argv. | 671 | |
| 724 | */ | 672 | static _Noreturn void |
| 725 | static void | ||
| 726 | fail (void) | 673 | fail (void) |
| 727 | { | 674 | { |
| 728 | if (alternate_editor) | 675 | if (alternate_editor) |
| @@ -755,16 +702,15 @@ main (int argc, char **argv) | |||
| 755 | #define AUTH_KEY_LENGTH 64 | 702 | #define AUTH_KEY_LENGTH 64 |
| 756 | #define SEND_BUFFER_SIZE 4096 | 703 | #define SEND_BUFFER_SIZE 4096 |
| 757 | 704 | ||
| 758 | extern char *strerror (int); | ||
| 759 | |||
| 760 | /* Buffer to accumulate data to send in TCP connections. */ | 705 | /* Buffer to accumulate data to send in TCP connections. */ |
| 761 | char send_buffer[SEND_BUFFER_SIZE + 1]; | 706 | char send_buffer[SEND_BUFFER_SIZE + 1]; |
| 762 | int sblen = 0; /* Fill pointer for the send buffer. */ | 707 | int sblen = 0; /* Fill pointer for the send buffer. */ |
| 763 | /* Socket used to communicate with the Emacs server process. */ | 708 | /* Socket used to communicate with the Emacs server process. */ |
| 764 | HSOCKET emacs_socket = 0; | 709 | HSOCKET emacs_socket = 0; |
| 765 | 710 | ||
| 766 | /* On Windows, the socket library was historically separate from the standard | 711 | /* On Windows, the socket library was historically separate from the |
| 767 | C library, so errors are handled differently. */ | 712 | standard C library, so errors are handled differently. */ |
| 713 | |||
| 768 | static void | 714 | static void |
| 769 | sock_err_message (const char *function_name) | 715 | sock_err_message (const char *function_name) |
| 770 | { | 716 | { |
| @@ -792,33 +738,35 @@ sock_err_message (const char *function_name) | |||
| 792 | static void | 738 | static void |
| 793 | send_to_emacs (HSOCKET s, const char *data) | 739 | send_to_emacs (HSOCKET s, const char *data) |
| 794 | { | 740 | { |
| 795 | while (data) | 741 | size_t dlen; |
| 742 | |||
| 743 | if (!data) | ||
| 744 | return; | ||
| 745 | |||
| 746 | dlen = strlen (data); | ||
| 747 | while (*data) | ||
| 796 | { | 748 | { |
| 797 | size_t dlen = strlen (data); | 749 | size_t part = min (dlen, SEND_BUFFER_SIZE - sblen); |
| 798 | if (dlen + sblen >= SEND_BUFFER_SIZE) | 750 | memcpy (&send_buffer[sblen], data, part); |
| 799 | { | 751 | data += part; |
| 800 | int part = SEND_BUFFER_SIZE - sblen; | 752 | sblen += part; |
| 801 | strncpy (&send_buffer[sblen], data, part); | ||
| 802 | data += part; | ||
| 803 | sblen = SEND_BUFFER_SIZE; | ||
| 804 | } | ||
| 805 | else if (dlen) | ||
| 806 | { | ||
| 807 | strcpy (&send_buffer[sblen], data); | ||
| 808 | data = NULL; | ||
| 809 | sblen += dlen; | ||
| 810 | } | ||
| 811 | else | ||
| 812 | break; | ||
| 813 | 753 | ||
| 814 | if (sblen == SEND_BUFFER_SIZE | 754 | if (sblen == SEND_BUFFER_SIZE |
| 815 | || (sblen > 0 && send_buffer[sblen-1] == '\n')) | 755 | || (sblen > 0 && send_buffer[sblen-1] == '\n')) |
| 816 | { | 756 | { |
| 817 | int sent = send (s, send_buffer, sblen, 0); | 757 | int sent = send (s, send_buffer, sblen, 0); |
| 758 | if (sent < 0) | ||
| 759 | { | ||
| 760 | message (TRUE, "%s: failed to send %d bytes to socket: %s\n", | ||
| 761 | progname, sblen, strerror (errno)); | ||
| 762 | fail (); | ||
| 763 | } | ||
| 818 | if (sent != sblen) | 764 | if (sent != sblen) |
| 819 | strcpy (send_buffer, &send_buffer[sent]); | 765 | memmove (send_buffer, &send_buffer[sent], sblen - sent); |
| 820 | sblen -= sent; | 766 | sblen -= sent; |
| 821 | } | 767 | } |
| 768 | |||
| 769 | dlen -= part; | ||
| 822 | } | 770 | } |
| 823 | } | 771 | } |
| 824 | 772 | ||
| @@ -867,7 +815,7 @@ quote_argument (HSOCKET s, const char *str) | |||
| 867 | 815 | ||
| 868 | 816 | ||
| 869 | /* The inverse of quote_argument. Removes quoting in string STR by | 817 | /* The inverse of quote_argument. Removes quoting in string STR by |
| 870 | modifying the string in place. Returns STR. */ | 818 | modifying the string in place. Returns STR. */ |
| 871 | 819 | ||
| 872 | static char * | 820 | static char * |
| 873 | unquote_argument (char *str) | 821 | unquote_argument (char *str) |
| @@ -950,41 +898,41 @@ initialize_sockets (void) | |||
| 950 | #endif /* WINDOWSNT */ | 898 | #endif /* WINDOWSNT */ |
| 951 | 899 | ||
| 952 | 900 | ||
| 953 | /* | 901 | /* Read the information needed to set up a TCP comm channel with |
| 954 | * Read the information needed to set up a TCP comm channel with | 902 | the Emacs server: host, port, and authentication string. */ |
| 955 | * the Emacs server: host, port, and authentication string. | 903 | |
| 956 | */ | ||
| 957 | static int | 904 | static int |
| 958 | get_server_config (struct sockaddr_in *server, char *authentication) | 905 | get_server_config (const char *config_file, struct sockaddr_in *server, |
| 906 | char *authentication) | ||
| 959 | { | 907 | { |
| 960 | char dotted[32]; | 908 | char dotted[32]; |
| 961 | char *port; | 909 | char *port; |
| 962 | FILE *config = NULL; | 910 | FILE *config = NULL; |
| 963 | 911 | ||
| 964 | if (file_name_absolute_p (server_file)) | 912 | if (file_name_absolute_p (config_file)) |
| 965 | config = fopen (server_file, "rb"); | 913 | config = fopen (config_file, "rb"); |
| 966 | else | 914 | else |
| 967 | { | 915 | { |
| 968 | const char *home = egetenv ("HOME"); | 916 | const char *home = egetenv ("HOME"); |
| 969 | 917 | ||
| 970 | if (home) | 918 | if (home) |
| 971 | { | 919 | { |
| 972 | char *path = xmalloc (strlen (home) + strlen (server_file) | 920 | char *path = xmalloc (strlen (home) + strlen (config_file) |
| 973 | + EXTRA_SPACE); | 921 | + EXTRA_SPACE); |
| 974 | strcpy (path, home); | 922 | strcpy (path, home); |
| 975 | strcat (path, "/.emacs.d/server/"); | 923 | strcat (path, "/.emacs.d/server/"); |
| 976 | strcat (path, server_file); | 924 | strcat (path, config_file); |
| 977 | config = fopen (path, "rb"); | 925 | config = fopen (path, "rb"); |
| 978 | free (path); | 926 | free (path); |
| 979 | } | 927 | } |
| 980 | #ifdef WINDOWSNT | 928 | #ifdef WINDOWSNT |
| 981 | if (!config && (home = egetenv ("APPDATA"))) | 929 | if (!config && (home = egetenv ("APPDATA"))) |
| 982 | { | 930 | { |
| 983 | char *path = xmalloc (strlen (home) + strlen (server_file) | 931 | char *path = xmalloc (strlen (home) + strlen (config_file) |
| 984 | + EXTRA_SPACE); | 932 | + EXTRA_SPACE); |
| 985 | strcpy (path, home); | 933 | strcpy (path, home); |
| 986 | strcat (path, "/.emacs.d/server/"); | 934 | strcat (path, "/.emacs.d/server/"); |
| 987 | strcat (path, server_file); | 935 | strcat (path, config_file); |
| 988 | config = fopen (path, "rb"); | 936 | config = fopen (path, "rb"); |
| 989 | free (path); | 937 | free (path); |
| 990 | } | 938 | } |
| @@ -1019,32 +967,28 @@ get_server_config (struct sockaddr_in *server, char *authentication) | |||
| 1019 | } | 967 | } |
| 1020 | 968 | ||
| 1021 | static HSOCKET | 969 | static HSOCKET |
| 1022 | set_tcp_socket (void) | 970 | set_tcp_socket (const char *local_server_file) |
| 1023 | { | 971 | { |
| 1024 | HSOCKET s; | 972 | HSOCKET s; |
| 1025 | struct sockaddr_in server; | 973 | struct sockaddr_in server; |
| 1026 | struct linger l_arg = {1, 1}; | 974 | struct linger l_arg = {1, 1}; |
| 1027 | char auth_string[AUTH_KEY_LENGTH + 1]; | 975 | char auth_string[AUTH_KEY_LENGTH + 1]; |
| 1028 | 976 | ||
| 1029 | if (! get_server_config (&server, auth_string)) | 977 | if (! get_server_config (local_server_file, &server, auth_string)) |
| 1030 | return INVALID_SOCKET; | 978 | return INVALID_SOCKET; |
| 1031 | 979 | ||
| 1032 | if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) | 980 | if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) |
| 1033 | message (FALSE, "%s: connected to remote socket at %s\n", | 981 | message (FALSE, "%s: connected to remote socket at %s\n", |
| 1034 | progname, inet_ntoa (server.sin_addr)); | 982 | progname, inet_ntoa (server.sin_addr)); |
| 1035 | 983 | ||
| 1036 | /* | 984 | /* Open up an AF_INET socket. */ |
| 1037 | * Open up an AF_INET socket | ||
| 1038 | */ | ||
| 1039 | if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | 985 | if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) |
| 1040 | { | 986 | { |
| 1041 | sock_err_message ("socket"); | 987 | sock_err_message ("socket"); |
| 1042 | return INVALID_SOCKET; | 988 | return INVALID_SOCKET; |
| 1043 | } | 989 | } |
| 1044 | 990 | ||
| 1045 | /* | 991 | /* Set up the socket. */ |
| 1046 | * Set up the socket | ||
| 1047 | */ | ||
| 1048 | if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) | 992 | if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) |
| 1049 | { | 993 | { |
| 1050 | sock_err_message ("connect"); | 994 | sock_err_message ("connect"); |
| @@ -1053,9 +997,7 @@ set_tcp_socket (void) | |||
| 1053 | 997 | ||
| 1054 | setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg); | 998 | setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg); |
| 1055 | 999 | ||
| 1056 | /* | 1000 | /* Send the authentication. */ |
| 1057 | * Send the authentication | ||
| 1058 | */ | ||
| 1059 | auth_string[AUTH_KEY_LENGTH] = '\0'; | 1001 | auth_string[AUTH_KEY_LENGTH] = '\0'; |
| 1060 | 1002 | ||
| 1061 | send_to_emacs (s, "-auth "); | 1003 | send_to_emacs (s, "-auth "); |
| @@ -1178,7 +1120,7 @@ handle_sigcont (int signalnum) | |||
| 1178 | else | 1120 | else |
| 1179 | { | 1121 | { |
| 1180 | /* We are in the background; cancel the continue. */ | 1122 | /* We are in the background; cancel the continue. */ |
| 1181 | kill (getpid (), SIGSTOP); | 1123 | raise (SIGSTOP); |
| 1182 | } | 1124 | } |
| 1183 | 1125 | ||
| 1184 | signal (signalnum, handle_sigcont); | 1126 | signal (signalnum, handle_sigcont); |
| @@ -1189,7 +1131,7 @@ handle_sigcont (int signalnum) | |||
| 1189 | going to sleep. Normally the suspend is initiated by Emacs via | 1131 | going to sleep. Normally the suspend is initiated by Emacs via |
| 1190 | server-handle-suspend-tty, but if the server gets out of sync with | 1132 | server-handle-suspend-tty, but if the server gets out of sync with |
| 1191 | reality, we may get a SIGTSTP on C-z. Handling this signal and | 1133 | reality, we may get a SIGTSTP on C-z. Handling this signal and |
| 1192 | notifying Emacs about it should get things under control again. */ | 1134 | notifying Emacs about it should get things under control again. */ |
| 1193 | 1135 | ||
| 1194 | static void | 1136 | static void |
| 1195 | handle_sigtstp (int signalnum) | 1137 | handle_sigtstp (int signalnum) |
| @@ -1205,7 +1147,7 @@ handle_sigtstp (int signalnum) | |||
| 1205 | sigprocmask (SIG_BLOCK, NULL, &set); | 1147 | sigprocmask (SIG_BLOCK, NULL, &set); |
| 1206 | sigdelset (&set, signalnum); | 1148 | sigdelset (&set, signalnum); |
| 1207 | signal (signalnum, SIG_DFL); | 1149 | signal (signalnum, SIG_DFL); |
| 1208 | kill (getpid (), signalnum); | 1150 | raise (signalnum); |
| 1209 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ | 1151 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ |
| 1210 | signal (signalnum, handle_sigtstp); | 1152 | signal (signalnum, handle_sigtstp); |
| 1211 | 1153 | ||
| @@ -1236,15 +1178,12 @@ init_signals (void) | |||
| 1236 | 1178 | ||
| 1237 | 1179 | ||
| 1238 | static HSOCKET | 1180 | static HSOCKET |
| 1239 | set_local_socket (void) | 1181 | set_local_socket (const char *local_socket_name) |
| 1240 | { | 1182 | { |
| 1241 | HSOCKET s; | 1183 | HSOCKET s; |
| 1242 | struct sockaddr_un server; | 1184 | struct sockaddr_un server; |
| 1243 | 1185 | ||
| 1244 | /* | 1186 | /* Open up an AF_UNIX socket in this person's home directory. */ |
| 1245 | * Open up an AF_UNIX socket in this person's home directory | ||
| 1246 | */ | ||
| 1247 | |||
| 1248 | if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) | 1187 | if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) |
| 1249 | { | 1188 | { |
| 1250 | message (TRUE, "%s: socket: %s\n", progname, strerror (errno)); | 1189 | message (TRUE, "%s: socket: %s\n", progname, strerror (errno)); |
| @@ -1254,27 +1193,20 @@ set_local_socket (void) | |||
| 1254 | server.sun_family = AF_UNIX; | 1193 | server.sun_family = AF_UNIX; |
| 1255 | 1194 | ||
| 1256 | { | 1195 | { |
| 1257 | int sock_status = 0; | 1196 | int sock_status; |
| 1258 | int default_sock = !socket_name; | 1197 | int use_tmpdir = 0; |
| 1259 | int saved_errno = 0; | 1198 | int saved_errno; |
| 1260 | const char *server_name = "server"; | 1199 | const char *server_name = local_socket_name; |
| 1261 | const char *tmpdir IF_LINT ( = NULL); | 1200 | const char *tmpdir IF_LINT ( = NULL); |
| 1262 | char *tmpdir_storage = NULL; | 1201 | char *tmpdir_storage = NULL; |
| 1263 | char *socket_name_storage = NULL; | 1202 | char *socket_name_storage = NULL; |
| 1264 | 1203 | ||
| 1265 | if (socket_name && !strchr (socket_name, '/') | 1204 | if (!strchr (local_socket_name, '/') && !strchr (local_socket_name, '\\')) |
| 1266 | && !strchr (socket_name, '\\')) | ||
| 1267 | { | 1205 | { |
| 1268 | /* socket_name is a file name component. */ | 1206 | /* socket_name is a file name component. */ |
| 1269 | server_name = socket_name; | ||
| 1270 | socket_name = NULL; | ||
| 1271 | default_sock = 1; /* Try both UIDs. */ | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | if (default_sock) | ||
| 1275 | { | ||
| 1276 | long uid = geteuid (); | 1207 | long uid = geteuid (); |
| 1277 | ptrdiff_t tmpdirlen; | 1208 | ptrdiff_t tmpdirlen; |
| 1209 | use_tmpdir = 1; | ||
| 1278 | tmpdir = egetenv ("TMPDIR"); | 1210 | tmpdir = egetenv ("TMPDIR"); |
| 1279 | if (!tmpdir) | 1211 | if (!tmpdir) |
| 1280 | { | 1212 | { |
| @@ -1286,33 +1218,34 @@ set_local_socket (void) | |||
| 1286 | if (n > 0) | 1218 | if (n > 0) |
| 1287 | { | 1219 | { |
| 1288 | tmpdir = tmpdir_storage = xmalloc (n); | 1220 | tmpdir = tmpdir_storage = xmalloc (n); |
| 1289 | confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n); | 1221 | confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir_storage, n); |
| 1290 | } | 1222 | } |
| 1291 | else | 1223 | else |
| 1292 | #endif | 1224 | #endif |
| 1293 | tmpdir = "/tmp"; | 1225 | tmpdir = "/tmp"; |
| 1294 | } | 1226 | } |
| 1295 | tmpdirlen = strlen (tmpdir); | 1227 | tmpdirlen = strlen (tmpdir); |
| 1296 | socket_name = socket_name_storage = | 1228 | socket_name_storage = |
| 1297 | xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); | 1229 | xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); |
| 1298 | strcpy (socket_name, tmpdir); | 1230 | strcpy (socket_name_storage, tmpdir); |
| 1299 | sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); | 1231 | sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid); |
| 1300 | strcat (socket_name + tmpdirlen, server_name); | 1232 | strcat (socket_name_storage + tmpdirlen, server_name); |
| 1233 | local_socket_name = socket_name_storage; | ||
| 1301 | } | 1234 | } |
| 1302 | 1235 | ||
| 1303 | if (strlen (socket_name) < sizeof (server.sun_path)) | 1236 | if (strlen (local_socket_name) < sizeof (server.sun_path)) |
| 1304 | strcpy (server.sun_path, socket_name); | 1237 | strcpy (server.sun_path, local_socket_name); |
| 1305 | else | 1238 | else |
| 1306 | { | 1239 | { |
| 1307 | message (TRUE, "%s: socket-name %s too long\n", | 1240 | message (TRUE, "%s: socket-name %s too long\n", |
| 1308 | progname, socket_name); | 1241 | progname, local_socket_name); |
| 1309 | fail (); | 1242 | fail (); |
| 1310 | } | 1243 | } |
| 1311 | 1244 | ||
| 1312 | /* See if the socket exists, and if it's owned by us. */ | 1245 | /* See if the socket exists, and if it's owned by us. */ |
| 1313 | sock_status = socket_status (server.sun_path); | 1246 | sock_status = socket_status (server.sun_path); |
| 1314 | saved_errno = errno; | 1247 | saved_errno = errno; |
| 1315 | if (sock_status && default_sock) | 1248 | if (sock_status && use_tmpdir) |
| 1316 | { | 1249 | { |
| 1317 | /* Failing that, see if LOGNAME or USER exist and differ from | 1250 | /* Failing that, see if LOGNAME or USER exist and differ from |
| 1318 | our euid. If so, look for a socket based on the UID | 1251 | our euid. If so, look for a socket based on the UID |
| @@ -1333,21 +1266,21 @@ set_local_socket (void) | |||
| 1333 | /* We're running under su, apparently. */ | 1266 | /* We're running under su, apparently. */ |
| 1334 | long uid = pw->pw_uid; | 1267 | long uid = pw->pw_uid; |
| 1335 | ptrdiff_t tmpdirlen = strlen (tmpdir); | 1268 | ptrdiff_t tmpdirlen = strlen (tmpdir); |
| 1336 | socket_name = xmalloc (tmpdirlen + strlen (server_name) | 1269 | char *user_socket_name |
| 1337 | + EXTRA_SPACE); | 1270 | = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); |
| 1338 | strcpy (socket_name, tmpdir); | 1271 | strcpy (user_socket_name, tmpdir); |
| 1339 | sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); | 1272 | sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid); |
| 1340 | strcat (socket_name + tmpdirlen, server_name); | 1273 | strcat (user_socket_name + tmpdirlen, server_name); |
| 1341 | 1274 | ||
| 1342 | if (strlen (socket_name) < sizeof (server.sun_path)) | 1275 | if (strlen (user_socket_name) < sizeof (server.sun_path)) |
| 1343 | strcpy (server.sun_path, socket_name); | 1276 | strcpy (server.sun_path, user_socket_name); |
| 1344 | else | 1277 | else |
| 1345 | { | 1278 | { |
| 1346 | message (TRUE, "%s: socket-name %s too long\n", | 1279 | message (TRUE, "%s: socket-name %s too long\n", |
| 1347 | progname, socket_name); | 1280 | progname, user_socket_name); |
| 1348 | exit (EXIT_FAILURE); | 1281 | exit (EXIT_FAILURE); |
| 1349 | } | 1282 | } |
| 1350 | free (socket_name); | 1283 | free (user_socket_name); |
| 1351 | 1284 | ||
| 1352 | sock_status = socket_status (server.sun_path); | 1285 | sock_status = socket_status (server.sun_path); |
| 1353 | saved_errno = errno; | 1286 | saved_errno = errno; |
| @@ -1401,6 +1334,7 @@ static HSOCKET | |||
| 1401 | set_socket (int no_exit_if_error) | 1334 | set_socket (int no_exit_if_error) |
| 1402 | { | 1335 | { |
| 1403 | HSOCKET s; | 1336 | HSOCKET s; |
| 1337 | const char *local_server_file = server_file; | ||
| 1404 | 1338 | ||
| 1405 | INITIALIZE (); | 1339 | INITIALIZE (); |
| 1406 | 1340 | ||
| @@ -1408,7 +1342,7 @@ set_socket (int no_exit_if_error) | |||
| 1408 | /* Explicit --socket-name argument. */ | 1342 | /* Explicit --socket-name argument. */ |
| 1409 | if (socket_name) | 1343 | if (socket_name) |
| 1410 | { | 1344 | { |
| 1411 | s = set_local_socket (); | 1345 | s = set_local_socket (socket_name); |
| 1412 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1346 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1413 | return s; | 1347 | return s; |
| 1414 | message (TRUE, "%s: error accessing socket \"%s\"\n", | 1348 | message (TRUE, "%s: error accessing socket \"%s\"\n", |
| @@ -1418,30 +1352,29 @@ set_socket (int no_exit_if_error) | |||
| 1418 | #endif | 1352 | #endif |
| 1419 | 1353 | ||
| 1420 | /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */ | 1354 | /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */ |
| 1421 | if (!server_file) | 1355 | if (!local_server_file) |
| 1422 | server_file = egetenv ("EMACS_SERVER_FILE"); | 1356 | local_server_file = egetenv ("EMACS_SERVER_FILE"); |
| 1423 | 1357 | ||
| 1424 | if (server_file) | 1358 | if (local_server_file) |
| 1425 | { | 1359 | { |
| 1426 | s = set_tcp_socket (); | 1360 | s = set_tcp_socket (local_server_file); |
| 1427 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1361 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1428 | return s; | 1362 | return s; |
| 1429 | 1363 | ||
| 1430 | message (TRUE, "%s: error accessing server file \"%s\"\n", | 1364 | message (TRUE, "%s: error accessing server file \"%s\"\n", |
| 1431 | progname, server_file); | 1365 | progname, local_server_file); |
| 1432 | exit (EXIT_FAILURE); | 1366 | exit (EXIT_FAILURE); |
| 1433 | } | 1367 | } |
| 1434 | 1368 | ||
| 1435 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | 1369 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 1436 | /* Implicit local socket. */ | 1370 | /* Implicit local socket. */ |
| 1437 | s = set_local_socket (); | 1371 | s = set_local_socket ("server"); |
| 1438 | if (s != INVALID_SOCKET) | 1372 | if (s != INVALID_SOCKET) |
| 1439 | return s; | 1373 | return s; |
| 1440 | #endif | 1374 | #endif |
| 1441 | 1375 | ||
| 1442 | /* Implicit server file. */ | 1376 | /* Implicit server file. */ |
| 1443 | server_file = "server"; | 1377 | s = set_tcp_socket ("server"); |
| 1444 | s = set_tcp_socket (); | ||
| 1445 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1378 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1446 | return s; | 1379 | return s; |
| 1447 | 1380 | ||
| @@ -1456,10 +1389,37 @@ set_socket (int no_exit_if_error) | |||
| 1456 | exit (EXIT_FAILURE); | 1389 | exit (EXIT_FAILURE); |
| 1457 | } | 1390 | } |
| 1458 | 1391 | ||
| 1459 | #ifdef WINDOWSNT | 1392 | #ifdef HAVE_NTGUI |
| 1460 | FARPROC set_fg; /* Pointer to AllowSetForegroundWindow. */ | 1393 | FARPROC set_fg; /* Pointer to AllowSetForegroundWindow. */ |
| 1461 | FARPROC get_wc; /* Pointer to RealGetWindowClassA. */ | 1394 | FARPROC get_wc; /* Pointer to RealGetWindowClassA. */ |
| 1462 | 1395 | ||
| 1396 | void | ||
| 1397 | w32_set_user_model_id (void) | ||
| 1398 | { | ||
| 1399 | HMODULE shell; | ||
| 1400 | HRESULT (WINAPI * set_user_model) (wchar_t * id); | ||
| 1401 | |||
| 1402 | /* On Windows 7 and later, we need to set the user model ID | ||
| 1403 | to associate emacsclient launched files with Emacs frames | ||
| 1404 | in the UI. */ | ||
| 1405 | shell = LoadLibrary ("shell32.dll"); | ||
| 1406 | if (shell) | ||
| 1407 | { | ||
| 1408 | set_user_model | ||
| 1409 | = (void *) GetProcAddress (shell, | ||
| 1410 | "SetCurrentProcessExplicitAppUserModelID"); | ||
| 1411 | /* If the function is defined, then we are running on Windows 7 | ||
| 1412 | or newer, and the UI uses this to group related windows | ||
| 1413 | together. Since emacs, runemacs, emacsclient are related, we | ||
| 1414 | want them grouped even though the executables are different, | ||
| 1415 | so we need to set a consistent ID between them. */ | ||
| 1416 | if (set_user_model) | ||
| 1417 | set_user_model (L"GNU.Emacs"); | ||
| 1418 | |||
| 1419 | FreeLibrary (shell); | ||
| 1420 | } | ||
| 1421 | } | ||
| 1422 | |||
| 1463 | BOOL CALLBACK | 1423 | BOOL CALLBACK |
| 1464 | w32_find_emacs_process (HWND hWnd, LPARAM lParam) | 1424 | w32_find_emacs_process (HWND hWnd, LPARAM lParam) |
| 1465 | { | 1425 | { |
| @@ -1484,10 +1444,9 @@ w32_find_emacs_process (HWND hWnd, LPARAM lParam) | |||
| 1484 | return FALSE; | 1444 | return FALSE; |
| 1485 | } | 1445 | } |
| 1486 | 1446 | ||
| 1487 | /* | 1447 | /* Search for a window of class "Emacs" and owned by a process with |
| 1488 | * Search for a window of class "Emacs" and owned by a process with | 1448 | process id = emacs_pid. If found, allow it to grab the focus. */ |
| 1489 | * process id = emacs_pid. If found, allow it to grab the focus. | 1449 | |
| 1490 | */ | ||
| 1491 | void | 1450 | void |
| 1492 | w32_give_focus (void) | 1451 | w32_give_focus (void) |
| 1493 | { | 1452 | { |
| @@ -1509,7 +1468,7 @@ w32_give_focus (void) | |||
| 1509 | && (get_wc = GetProcAddress (user32, "RealGetWindowClassA"))) | 1468 | && (get_wc = GetProcAddress (user32, "RealGetWindowClassA"))) |
| 1510 | EnumWindows (w32_find_emacs_process, (LPARAM) 0); | 1469 | EnumWindows (w32_find_emacs_process, (LPARAM) 0); |
| 1511 | } | 1470 | } |
| 1512 | #endif | 1471 | #endif /* HAVE_NTGUI */ |
| 1513 | 1472 | ||
| 1514 | /* Start the emacs daemon and try to connect to it. */ | 1473 | /* Start the emacs daemon and try to connect to it. */ |
| 1515 | 1474 | ||
| @@ -1573,19 +1532,19 @@ main (int argc, char **argv) | |||
| 1573 | int rl = 0, needlf = 0; | 1532 | int rl = 0, needlf = 0; |
| 1574 | char *cwd, *str; | 1533 | char *cwd, *str; |
| 1575 | char string[BUFSIZ+1]; | 1534 | char string[BUFSIZ+1]; |
| 1576 | int null_socket_name IF_LINT ( = 0); | ||
| 1577 | int null_server_file IF_LINT ( = 0); | ||
| 1578 | int start_daemon_if_needed; | 1535 | int start_daemon_if_needed; |
| 1579 | int exit_status = EXIT_SUCCESS; | 1536 | int exit_status = EXIT_SUCCESS; |
| 1580 | 1537 | ||
| 1581 | main_argv = argv; | 1538 | main_argv = argv; |
| 1582 | progname = argv[0]; | 1539 | progname = argv[0]; |
| 1583 | 1540 | ||
| 1584 | #ifdef WINDOWSNT | 1541 | #ifdef HAVE_NTGUI |
| 1585 | /* On Windows 7 and later, we need to explicitly associate emacsclient | 1542 | /* On Windows 7 and later, we need to explicitly associate |
| 1586 | with emacs so the UI behaves sensibly. */ | 1543 | emacsclient with emacs so the UI behaves sensibly. This |
| 1544 | association does no harm if we're not actually connecting to an | ||
| 1545 | Emacs using a window display. */ | ||
| 1587 | w32_set_user_model_id (); | 1546 | w32_set_user_model_id (); |
| 1588 | #endif | 1547 | #endif /* HAVE_NTGUI */ |
| 1589 | 1548 | ||
| 1590 | /* Process options. */ | 1549 | /* Process options. */ |
| 1591 | decode_options (argc, argv); | 1550 | decode_options (argc, argv); |
| @@ -1602,14 +1561,6 @@ main (int argc, char **argv) | |||
| 1602 | in case of failure to connect. */ | 1561 | in case of failure to connect. */ |
| 1603 | start_daemon_if_needed = (alternate_editor | 1562 | start_daemon_if_needed = (alternate_editor |
| 1604 | && (alternate_editor[0] == '\0')); | 1563 | && (alternate_editor[0] == '\0')); |
| 1605 | if (start_daemon_if_needed) | ||
| 1606 | { | ||
| 1607 | /* set_socket changes the values for socket_name and | ||
| 1608 | server_file, we need to reset them, if they were NULL before | ||
| 1609 | for the second call to set_socket. */ | ||
| 1610 | null_socket_name = (socket_name == NULL); | ||
| 1611 | null_server_file = (server_file == NULL); | ||
| 1612 | } | ||
| 1613 | 1564 | ||
| 1614 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); | 1565 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); |
| 1615 | if (emacs_socket == INVALID_SOCKET) | 1566 | if (emacs_socket == INVALID_SOCKET) |
| @@ -1617,37 +1568,25 @@ main (int argc, char **argv) | |||
| 1617 | if (! start_daemon_if_needed) | 1568 | if (! start_daemon_if_needed) |
| 1618 | fail (); | 1569 | fail (); |
| 1619 | 1570 | ||
| 1620 | /* Reset socket_name and server_file if they were NULL | ||
| 1621 | before the set_socket call. */ | ||
| 1622 | if (null_socket_name) | ||
| 1623 | socket_name = NULL; | ||
| 1624 | if (null_server_file) | ||
| 1625 | server_file = NULL; | ||
| 1626 | |||
| 1627 | start_daemon_and_retry_set_socket (); | 1571 | start_daemon_and_retry_set_socket (); |
| 1628 | } | 1572 | } |
| 1629 | 1573 | ||
| 1630 | cwd = get_current_dir_name (); | 1574 | cwd = get_current_dir_name (); |
| 1631 | if (cwd == 0) | 1575 | if (cwd == 0) |
| 1632 | { | 1576 | { |
| 1633 | /* getwd puts message in STRING if it fails. */ | ||
| 1634 | message (TRUE, "%s: %s\n", progname, | 1577 | message (TRUE, "%s: %s\n", progname, |
| 1635 | "Cannot get current working directory"); | 1578 | "Cannot get current working directory"); |
| 1636 | fail (); | 1579 | fail (); |
| 1637 | } | 1580 | } |
| 1638 | 1581 | ||
| 1639 | #ifdef WINDOWSNT | 1582 | #ifdef HAVE_NTGUI |
| 1583 | if (display && !strcmp (display, "w32")) | ||
| 1640 | w32_give_focus (); | 1584 | w32_give_focus (); |
| 1641 | #endif | 1585 | #endif /* HAVE_NTGUI */ |
| 1642 | 1586 | ||
| 1643 | /* Send over our environment and current directory. */ | 1587 | /* Send over our environment and current directory. */ |
| 1644 | if (!current_frame) | 1588 | if (!current_frame) |
| 1645 | { | 1589 | { |
| 1646 | #ifndef WINDOWSNT | ||
| 1647 | /* This is defined in stdlib.h on MS-Windows. It's defined in | ||
| 1648 | unistd.h on some POSIX hosts, but not all (Bug#10155). */ | ||
| 1649 | extern char **environ; | ||
| 1650 | #endif | ||
| 1651 | int i; | 1590 | int i; |
| 1652 | for (i = 0; environ[i]; i++) | 1591 | for (i = 0; environ[i]; i++) |
| 1653 | { | 1592 | { |
| @@ -1689,10 +1628,10 @@ main (int argc, char **argv) | |||
| 1689 | send_to_emacs (emacs_socket, " "); | 1628 | send_to_emacs (emacs_socket, " "); |
| 1690 | } | 1629 | } |
| 1691 | 1630 | ||
| 1692 | /* If using the current frame, send tty information to Emacs anyway. | 1631 | /* Unless we are certain we don't want to occupy the tty, send our |
| 1693 | In daemon mode, Emacs may need to occupy this tty if no other | 1632 | tty information to Emacs. For example, in daemon mode Emacs may |
| 1694 | frame is available. */ | 1633 | need to occupy this tty if no other frame is available. */ |
| 1695 | if (tty || (current_frame && !eval)) | 1634 | if (!current_frame || !eval) |
| 1696 | { | 1635 | { |
| 1697 | const char *tty_type, *tty_name; | 1636 | const char *tty_type, *tty_name; |
| 1698 | 1637 | ||
| @@ -1790,7 +1729,7 @@ main (int argc, char **argv) | |||
| 1790 | /* Now, wait for an answer and print any messages. */ | 1729 | /* Now, wait for an answer and print any messages. */ |
| 1791 | while (exit_status == EXIT_SUCCESS) | 1730 | while (exit_status == EXIT_SUCCESS) |
| 1792 | { | 1731 | { |
| 1793 | char *p; | 1732 | char *p, *end_p; |
| 1794 | do | 1733 | do |
| 1795 | { | 1734 | { |
| 1796 | errno = 0; | 1735 | errno = 0; |
| @@ -1805,61 +1744,82 @@ main (int argc, char **argv) | |||
| 1805 | 1744 | ||
| 1806 | string[rl] = '\0'; | 1745 | string[rl] = '\0'; |
| 1807 | 1746 | ||
| 1808 | p = string + strlen (string) - 1; | 1747 | /* Loop over all NL-terminated messages. */ |
| 1809 | while (p > string && *p == '\n') | 1748 | for (end_p = p = string; end_p != NULL && *end_p != '\0'; p = end_p) |
| 1810 | *p-- = 0; | 1749 | { |
| 1750 | end_p = strchr (p, '\n'); | ||
| 1751 | if (end_p != NULL) | ||
| 1752 | *end_p++ = '\0'; | ||
| 1811 | 1753 | ||
| 1812 | if (strprefix ("-emacs-pid ", string)) | 1754 | if (strprefix ("-emacs-pid ", p)) |
| 1813 | { | 1755 | { |
| 1814 | /* -emacs-pid PID: The process id of the Emacs process. */ | 1756 | /* -emacs-pid PID: The process id of the Emacs process. */ |
| 1815 | emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); | 1757 | emacs_pid = strtol (p + strlen ("-emacs-pid"), NULL, 10); |
| 1816 | } | 1758 | } |
| 1817 | else if (strprefix ("-window-system-unsupported ", string)) | 1759 | else if (strprefix ("-window-system-unsupported ", p)) |
| 1818 | { | 1760 | { |
| 1819 | /* -window-system-unsupported: Emacs was compiled without X | 1761 | /* -window-system-unsupported: Emacs was compiled without support |
| 1820 | support. Try again on the terminal. */ | 1762 | for whatever window system we tried. Try the alternate |
| 1821 | nowait = 0; | 1763 | display, or, failing that, try the terminal. */ |
| 1822 | tty = 1; | 1764 | if (alt_display) |
| 1823 | goto retry; | 1765 | { |
| 1824 | } | 1766 | display = alt_display; |
| 1825 | else if (strprefix ("-print ", string)) | 1767 | alt_display = NULL; |
| 1826 | { | 1768 | } |
| 1827 | /* -print STRING: Print STRING on the terminal. */ | 1769 | else |
| 1828 | str = unquote_argument (string + strlen ("-print ")); | 1770 | { |
| 1829 | if (needlf) | 1771 | nowait = 0; |
| 1830 | printf ("\n"); | 1772 | tty = 1; |
| 1831 | printf ("%s", str); | 1773 | } |
| 1832 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 1774 | |
| 1833 | } | 1775 | goto retry; |
| 1834 | else if (strprefix ("-error ", string)) | 1776 | } |
| 1835 | { | 1777 | else if (strprefix ("-print ", p)) |
| 1836 | /* -error DESCRIPTION: Signal an error on the terminal. */ | 1778 | { |
| 1837 | str = unquote_argument (string + strlen ("-error ")); | 1779 | /* -print STRING: Print STRING on the terminal. */ |
| 1838 | if (needlf) | 1780 | str = unquote_argument (p + strlen ("-print ")); |
| 1839 | printf ("\n"); | 1781 | if (needlf) |
| 1840 | fprintf (stderr, "*ERROR*: %s", str); | 1782 | printf ("\n"); |
| 1841 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 1783 | printf ("%s", str); |
| 1842 | exit_status = EXIT_FAILURE; | 1784 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; |
| 1843 | } | 1785 | } |
| 1786 | else if (strprefix ("-print-nonl ", p)) | ||
| 1787 | { | ||
| 1788 | /* -print-nonl STRING: Print STRING on the terminal. | ||
| 1789 | Used to continue a preceding -print command. */ | ||
| 1790 | str = unquote_argument (p + strlen ("-print-nonl ")); | ||
| 1791 | printf ("%s", str); | ||
| 1792 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 1793 | } | ||
| 1794 | else if (strprefix ("-error ", p)) | ||
| 1795 | { | ||
| 1796 | /* -error DESCRIPTION: Signal an error on the terminal. */ | ||
| 1797 | str = unquote_argument (p + strlen ("-error ")); | ||
| 1798 | if (needlf) | ||
| 1799 | printf ("\n"); | ||
| 1800 | fprintf (stderr, "*ERROR*: %s", str); | ||
| 1801 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 1802 | exit_status = EXIT_FAILURE; | ||
| 1803 | } | ||
| 1844 | #ifdef SIGSTOP | 1804 | #ifdef SIGSTOP |
| 1845 | else if (strprefix ("-suspend ", string)) | 1805 | else if (strprefix ("-suspend ", p)) |
| 1846 | { | 1806 | { |
| 1847 | /* -suspend: Suspend this terminal, i.e., stop the process. */ | 1807 | /* -suspend: Suspend this terminal, i.e., stop the process. */ |
| 1848 | if (needlf) | 1808 | if (needlf) |
| 1849 | printf ("\n"); | 1809 | printf ("\n"); |
| 1850 | needlf = 0; | 1810 | needlf = 0; |
| 1851 | kill (0, SIGSTOP); | 1811 | kill (0, SIGSTOP); |
| 1852 | } | 1812 | } |
| 1853 | #endif | 1813 | #endif |
| 1854 | else | 1814 | else |
| 1855 | { | 1815 | { |
| 1856 | /* Unknown command. */ | 1816 | /* Unknown command. */ |
| 1857 | if (needlf) | 1817 | if (needlf) |
| 1858 | printf ("\n"); | 1818 | printf ("\n"); |
| 1859 | printf ("*ERROR*: Unknown message: %s", string); | 1819 | needlf = 0; |
| 1860 | needlf = string[0] | 1820 | printf ("*ERROR*: Unknown message: %s\n", p); |
| 1861 | == '\0' ? needlf : string[strlen (string) - 1] != '\n'; | 1821 | } |
| 1862 | } | 1822 | } |
| 1863 | } | 1823 | } |
| 1864 | 1824 | ||
| 1865 | if (needlf) | 1825 | if (needlf) |
| @@ -1875,22 +1835,3 @@ main (int argc, char **argv) | |||
| 1875 | } | 1835 | } |
| 1876 | 1836 | ||
| 1877 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ | 1837 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ |
| 1878 | |||
| 1879 | |||
| 1880 | #ifndef HAVE_STRERROR | ||
| 1881 | char * | ||
| 1882 | strerror (errnum) | ||
| 1883 | int errnum; | ||
| 1884 | { | ||
| 1885 | extern char *sys_errlist[]; | ||
| 1886 | extern int sys_nerr; | ||
| 1887 | |||
| 1888 | if (errnum >= 0 && errnum < sys_nerr) | ||
| 1889 | return sys_errlist[errnum]; | ||
| 1890 | return (char *) "Unknown error"; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | #endif /* ! HAVE_STRERROR */ | ||
| 1894 | |||
| 1895 | |||
| 1896 | /* emacsclient.c ends here */ | ||