aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorMiles Bader2007-08-29 05:28:10 +0000
committerMiles Bader2007-08-29 05:28:10 +0000
commit8d9cc0b7ea1893059df8788129998e9a71ec07f3 (patch)
tree4caa326ed8de37c8c0a859c7071593362832d37e /lib-src
parentcb5b9015b372175f1fc90cb7ba3f43298c621509 (diff)
parent5142de65ce179e846514ec7355274ab22822a85c (diff)
downloademacs-8d9cc0b7ea1893059df8788129998e9a71ec07f3.tar.gz
emacs-8d9cc0b7ea1893059df8788129998e9a71ec07f3.zip
Merge multi-tty branch
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-866
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/ChangeLog54
-rw-r--r--lib-src/emacsclient.c805
-rw-r--r--lib-src/makefile.w32-in2
3 files changed, 693 insertions, 168 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index 9d7d076ca46..266453ae975 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,3 +1,57 @@
12007-08-29 Dan Nicolaescu <dann@ics.uci.edu>
2
3 * emacsclient.c (w32_execvp): Move definition before use.
4 (decode_options): Don't use a tty on mac carbon or windows.
5
62007-08-29 Jason Rumney <jasonr@gnu.org>
7
8 * emacsclient.c (SEND_STRING, SEND_QUOTED): Remove obfuscation
9 macros.
10 (quote_argument, set_tcp_socket, handle_sigcont, handle_sigtstp):
11 (main): Expand removed macros inline.
12 (main) [WINDOWSNT]: Don't call ttyname. Don't recognize -suspend
13 option.
14 (main) [NO_SOCKETS_IN_FILE_SYSTEM]: Don't call init_signals.
15
162007-08-29 Karoly Lorentey <lorentey@elte.hu>
17
18 * emacsclient.c (signal.h): New include.
19 (sys/stat.h, errno.h): Always include, even on WINDOWSNT.
20 (DIRECTORY_SEP, IS_DIRECTORY_SEP, IS_DEVICE_SEP, IS_ANY_SEP): Copy
21 definitions here from src/lisp.h.
22 (main_argc, main_argv, current_frame, window_system, tty): New
23 variables.
24 (longopts): Add tty, current-frame.
25 (xmalloc, xstrdup): New functions.
26 (get_current_dir_name): New function, copied from src/sysdep.c.
27 (decode_options): Set display from environment. Add tty and
28 current_frame options. Make --no-wait imply --current-frame,
29 except when it is the only option given. Make sure no frame is
30 opened when --current-frame is set.
31 (print_help_and_exit): Document tty and current-frame options.
32 (fail): Change arguments to void.
33 (main): When sockets are not defined, set main_argc, main_argv,
34 and call fail() with no arguments.
35 (emacs_socket): New variable (moved out from main `s').
36 (quote_file_name): Rename to quote_argument.
37 (quote_argument): New name for old quote_file_name.
38 (unquote_argument, strprefix, pass_signal_to_emacs)
39 (handle_sigcont, handle_sigtstp, init_signals): New functions.
40 (set_local_socket): Initialize saved_errno to 0. If socket-name
41 is too long, call `fail' rather than `exit'.
42 (main): Doc update. Set main_argc, main_argv. New var `str'.
43 Don't need a filename or argument if tty or window_system set.
44 Call fail with no arguments. Use get_current_dir_name to send
45 over the current directory. Send version number to Emacs for
46 verification. If tty is set, check TERM, and pass name and type
47 to Emacs. Pass window_system to Emacs. Move sending of eval to
48 optind loop. Send -position, -file to Emacs. Call fsync after
49 fflush. Check for a client/server version match. Handle
50 -emacs-pid, -window-system-unsupported, -print, -error, -suspend
51 commands. Don't exit prematurely on --no-wait, let Emacs close
52 the connection for us. When creating a new frame, send
53 environment and pwd to Emacs. Send current-frame to Emacs.
54
12007-08-25 Eli Zaretskii <eliz@gnu.org> 552007-08-25 Eli Zaretskii <eliz@gnu.org>
2 56
3 * Makefile.in (rcs2log, rcs-checkin, grep-changelog, vcdiff): 57 * Makefile.in (rcs2log, rcs-checkin, grep-changelog, vcdiff):
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 9edba132134..ae7ff12e17d 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -76,7 +76,31 @@ Boston, MA 02110-1301, USA. */
76# include <pwd.h> 76# include <pwd.h>
77#endif /* not WINDOWSNT */ 77#endif /* not WINDOWSNT */
78#endif /* not VMS */ 78#endif /* not VMS */
79#include <sys/stat.h>
79 80
81#include <signal.h>
82#include <errno.h>
83
84/* From lisp.h */
85#ifndef DIRECTORY_SEP
86#define DIRECTORY_SEP '/'
87#endif
88#ifndef IS_DIRECTORY_SEP
89#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
90#endif
91#ifndef IS_DEVICE_SEP
92#ifndef DEVICE_SEP
93#define IS_DEVICE_SEP(_c_) 0
94#else
95#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
96#endif
97#endif
98#ifndef IS_ANY_SEP
99#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
100#endif
101
102
103
80char *getenv (), *getwd (); 104char *getenv (), *getwd ();
81char *(getcwd) (); 105char *(getcwd) ();
82 106
@@ -84,8 +108,6 @@ char *(getcwd) ();
84#define VERSION "unspecified" 108#define VERSION "unspecified"
85#endif 109#endif
86 110
87#define SEND_STRING(data) (send_to_emacs (s, (data)))
88#define SEND_QUOTED(data) (quote_file_name (s, (data)))
89 111
90#ifndef EXIT_SUCCESS 112#ifndef EXIT_SUCCESS
91#define EXIT_SUCCESS 0 113#define EXIT_SUCCESS 0
@@ -110,15 +132,30 @@ char *(getcwd) ();
110/* Name used to invoke this program. */ 132/* Name used to invoke this program. */
111char *progname; 133char *progname;
112 134
135/* The first argument to main. */
136int main_argc;
137
138/* The second argument to main. */
139char **main_argv;
140
113/* Nonzero means don't wait for a response from Emacs. --no-wait. */ 141/* Nonzero means don't wait for a response from Emacs. --no-wait. */
114int nowait = 0; 142int nowait = 0;
115 143
116/* Nonzero means args are expressions to be evaluated. --eval. */ 144/* Nonzero means args are expressions to be evaluated. --eval. */
117int eval = 0; 145int eval = 0;
118 146
147/* Nonzero means don't open a new frame. --current-frame. */
148int current_frame = 0;
149
150/* Nonzero means open a new graphical frame. */
151int window_system = 0;
152
119/* The display on which Emacs should work. --display. */ 153/* The display on which Emacs should work. --display. */
120char *display = NULL; 154char *display = NULL;
121 155
156/* Nonzero means open a new Emacs frame on the current terminal. */
157int tty = 0;
158
122/* If non-NULL, the name of an editor to fallback to if the server 159/* If non-NULL, the name of an editor to fallback to if the server
123 is not running. --alternate-editor. */ 160 is not running. --alternate-editor. */
124const char *alternate_editor = NULL; 161const char *alternate_editor = NULL;
@@ -140,6 +177,8 @@ struct option longopts[] =
140 { "eval", no_argument, NULL, 'e' }, 177 { "eval", no_argument, NULL, 'e' },
141 { "help", no_argument, NULL, 'H' }, 178 { "help", no_argument, NULL, 'H' },
142 { "version", no_argument, NULL, 'V' }, 179 { "version", no_argument, NULL, 'V' },
180 { "tty", no_argument, NULL, 't' },
181 { "current-frame", no_argument, NULL, 'c' },
143 { "alternate-editor", required_argument, NULL, 'a' }, 182 { "alternate-editor", required_argument, NULL, 'a' },
144#ifndef NO_SOCKETS_IN_FILE_SYSTEM 183#ifndef NO_SOCKETS_IN_FILE_SYSTEM
145 { "socket-name", required_argument, NULL, 's' }, 184 { "socket-name", required_argument, NULL, 's' },
@@ -149,6 +188,111 @@ struct option longopts[] =
149 { 0, 0, 0, 0 } 188 { 0, 0, 0, 0 }
150}; 189};
151 190
191
192/* Like malloc but get fatal error if memory is exhausted. */
193
194long *
195xmalloc (size)
196 unsigned int size;
197{
198 long *result = (long *) malloc (size);
199 if (result == NULL)
200 {
201 perror ("malloc");
202 exit (EXIT_FAILURE);
203 }
204 return result;
205}
206
207/* Like strdup but get a fatal error if memory is exhausted. */
208
209char *
210xstrdup (const char *s)
211{
212 char *result = strdup (s);
213 if (result == NULL)
214 {
215 perror ("strdup");
216 exit (EXIT_FAILURE);
217 }
218 return result;
219}
220
221/* From sysdep.c */
222#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
223
224/* Return the current working directory. Returns NULL on errors.
225 Any other returned value must be freed with free. This is used
226 only when get_current_dir_name is not defined on the system. */
227char*
228get_current_dir_name ()
229{
230 char *buf;
231 char *pwd;
232 struct stat dotstat, pwdstat;
233 /* If PWD is accurate, use it instead of calling getwd. PWD is
234 sometimes a nicer name, and using it may avoid a fatal error if a
235 parent directory is searchable but not readable. */
236 if ((pwd = getenv ("PWD")) != 0
237 && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
238 && stat (pwd, &pwdstat) == 0
239 && stat (".", &dotstat) == 0
240 && dotstat.st_ino == pwdstat.st_ino
241 && dotstat.st_dev == pwdstat.st_dev
242#ifdef MAXPATHLEN
243 && strlen (pwd) < MAXPATHLEN
244#endif
245 )
246 {
247 buf = (char *) xmalloc (strlen (pwd) + 1);
248 if (!buf)
249 return NULL;
250 strcpy (buf, pwd);
251 }
252#ifdef HAVE_GETCWD
253 else
254 {
255 size_t buf_size = 1024;
256 buf = (char *) xmalloc (buf_size);
257 if (!buf)
258 return NULL;
259 for (;;)
260 {
261 if (getcwd (buf, buf_size) == buf)
262 break;
263 if (errno != ERANGE)
264 {
265 int tmp_errno = errno;
266 free (buf);
267 errno = tmp_errno;
268 return NULL;
269 }
270 buf_size *= 2;
271 buf = (char *) realloc (buf, buf_size);
272 if (!buf)
273 return NULL;
274 }
275 }
276#else
277 else
278 {
279 /* We need MAXPATHLEN here. */
280 buf = (char *) xmalloc (MAXPATHLEN + 1);
281 if (!buf)
282 return NULL;
283 if (getwd (buf) == NULL)
284 {
285 int tmp_errno = errno;
286 free (buf);
287 errno = tmp_errno;
288 return NULL;
289 }
290 }
291#endif
292 return buf;
293}
294#endif
295
152/* Message functions. */ 296/* Message functions. */
153 297
154#ifdef WINDOWSNT 298#ifdef WINDOWSNT
@@ -165,7 +309,41 @@ w32_window_app ()
165 309
166 return window_app; 310 return window_app;
167} 311}
168#endif 312
313/*
314 execvp wrapper for Windows. Quotes arguments with embedded spaces.
315
316 This is necessary due to the broken implementation of exec* routines in
317 the Microsoft libraries: they concatenate the arguments together without
318 quoting special characters, and pass the result to CreateProcess, with
319 predictably bad results. By contrast, Posix execvp passes the arguments
320 directly into the argv array of the child process.
321*/
322int
323w32_execvp (path, argv)
324 char *path;
325 char **argv;
326{
327 int i;
328
329 /* Required to allow a .BAT script as alternate editor. */
330 argv[0] = (char *) alternate_editor;
331
332 for (i = 0; argv[i]; i++)
333 if (strchr (argv[i], ' '))
334 {
335 char *quoted = alloca (strlen (argv[i]) + 3);
336 sprintf (quoted, "\"%s\"", argv[i]);
337 argv[i] = quoted;
338 }
339
340 return execvp (path, argv);
341}
342
343#undef execvp
344#define execvp w32_execvp
345
346#endif /* WINDOWSNT */
169 347
170void 348void
171message (int is_error, char *message, ...) 349message (int is_error, char *message, ...)
@@ -204,16 +382,19 @@ decode_options (argc, argv)
204 char **argv; 382 char **argv;
205{ 383{
206 alternate_editor = getenv ("ALTERNATE_EDITOR"); 384 alternate_editor = getenv ("ALTERNATE_EDITOR");
385 display = getenv ("DISPLAY");
386 if (display && strlen (display) == 0)
387 display = NULL;
207 388
208 while (1) 389 while (1)
209 { 390 {
210 int opt = getopt_long (argc, argv, 391 int opt = getopt_long (argc, argv,
211#ifndef NO_SOCKETS_IN_FILE_SYSTEM 392#ifndef NO_SOCKETS_IN_FILE_SYSTEM
212 "VHnea:s:f:d:", 393 "VHnea:s:f:d:tc",
213#else 394#else
214 "VHnea:f:d:", 395 "VHnea:f:d:tc",
215#endif 396#endif
216 longopts, 0); 397 longopts, 0);
217 398
218 if (opt == EOF) 399 if (opt == EOF)
219 break; 400 break;
@@ -256,6 +437,14 @@ decode_options (argc, argv)
256 exit (EXIT_SUCCESS); 437 exit (EXIT_SUCCESS);
257 break; 438 break;
258 439
440 case 't':
441 tty = 1;
442 break;
443
444 case 'c':
445 current_frame = 1;
446 break;
447
259 case 'H': 448 case 'H':
260 print_help_and_exit (); 449 print_help_and_exit ();
261 break; 450 break;
@@ -266,21 +455,49 @@ decode_options (argc, argv)
266 break; 455 break;
267 } 456 }
268 } 457 }
458
459 if (!tty && display)
460 window_system = 1;
461#if !defined (WINDOWSNT) && !defined (HAVE_CARBON)
462 else
463 tty = 1;
464#endif
465
466 /* --no-wait implies --current-frame on ttys when there are file
467 arguments or expressions given. */
468 if (nowait && tty && argc - optind > 0)
469 current_frame = 1;
470
471 if (current_frame)
472 {
473 tty = 0;
474 window_system = 0;
475 }
476
477 if (tty)
478 window_system = 0;
269} 479}
270 480
481
271void 482void
272print_help_and_exit () 483print_help_and_exit ()
273{ 484{
485 /* Spaces and tabs are significant in this message; they're chosen so the
486 message aligns properly both in a tty and in a Windows message box.
487 Please try to preserve them; otherwise the output is very hard to read
488 when using emacsclientw. */
274 message (FALSE, 489 message (FALSE,
275 "Usage: %s [OPTIONS] FILE...\n\ 490 "Usage: %s [OPTIONS] FILE...\n\
276Tell the Emacs server to visit the specified files.\n\ 491Tell the Emacs server to visit the specified files.\n\
277Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ 492Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
278\n\ 493\n\
279The following OPTIONS are accepted:\n\ 494The following OPTIONS are accepted:\n\
280\n\
281-V, --version Just print version info and return\n\ 495-V, --version Just print version info and return\n\
282-H, --help Print this usage information message\n\ 496-H, --help Print this usage information message\n\
283-e, --eval Evaluate FILE arguments as Lisp expressions\n\ 497-t, --tty Open a new Emacs frame on the current terminal\n\
498-c, --current-frame Do not create a new frame;\n\
499 use the current Emacs frame\n\
500-e, --eval Evaluate the FILE arguments as ELisp expressions\n\
284-n, --no-wait Don't wait for the server to return\n\ 501-n, --no-wait Don't wait for the server to return\n\
285-d, --display=DISPLAY Visit the file in the given display\n" 502-d, --display=DISPLAY Visit the file in the given display\n"
286#ifndef NO_SOCKETS_IN_FILE_SYSTEM 503#ifndef NO_SOCKETS_IN_FILE_SYSTEM
@@ -290,66 +507,26 @@ The following OPTIONS are accepted:\n\
290"-f, --server-file=FILENAME\n\ 507"-f, --server-file=FILENAME\n\
291 Set filename of the TCP authentication file\n\ 508 Set filename of the TCP authentication file\n\
292-a, --alternate-editor=EDITOR\n\ 509-a, --alternate-editor=EDITOR\n\
293 Editor to fallback to if server is not running\n\ 510 Editor to fallback to if the server is not running\n\
294\n\ 511\n\
295Report bugs to bug-gnu-emacs@gnu.org.\n", progname); 512Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
296 exit (EXIT_SUCCESS); 513 exit (EXIT_SUCCESS);
297} 514}
298 515
299
300#ifdef WINDOWSNT
301
302/*
303 execvp wrapper for Windows. Quotes arguments with embedded spaces.
304
305 This is necessary due to the broken implementation of exec* routines in
306 the Microsoft libraries: they concatenate the arguments together without
307 quoting special characters, and pass the result to CreateProcess, with
308 predictably bad results. By contrast, Posix execvp passes the arguments
309 directly into the argv array of the child process.
310*/
311int
312w32_execvp (path, argv)
313 char *path;
314 char **argv;
315{
316 int i;
317
318 /* Required to allow a .BAT script as alternate editor. */
319 argv[0] = (char *) alternate_editor;
320
321 for (i = 0; argv[i]; i++)
322 if (strchr (argv[i], ' '))
323 {
324 char *quoted = alloca (strlen (argv[i]) + 3);
325 sprintf (quoted, "\"%s\"", argv[i]);
326 argv[i] = quoted;
327 }
328
329 return execvp (path, argv);
330}
331
332#undef execvp
333#define execvp w32_execvp
334
335#endif /* WINDOWSNT */
336
337/* 516/*
338 Try to run a different command, or --if no alternate editor is 517 Try to run a different command, or --if no alternate editor is
339 defined-- exit with an errorcode. 518 defined-- exit with an errorcode.
340*/ 519*/
341void 520void
342fail (argc, argv) 521fail (void)
343 int argc;
344 char **argv;
345{ 522{
346 if (alternate_editor) 523 if (alternate_editor)
347 { 524 {
348 int i = optind - 1; 525 int i = optind - 1;
349 526
350 execvp (alternate_editor, argv + i); 527 execvp (alternate_editor, main_argv + i);
351 message (TRUE, "%s: error executing alternate editor \"%s\"\n", 528 message (TRUE, "%s: error executing alternate editor \"%s\"\n",
352 progname, alternate_editor); 529 progname, alternate_editor);
353 } 530 }
354 exit (EXIT_FAILURE); 531 exit (EXIT_FAILURE);
355} 532}
@@ -362,10 +539,13 @@ main (argc, argv)
362 int argc; 539 int argc;
363 char **argv; 540 char **argv;
364{ 541{
365 message (TRUE, "%s: Sorry, the Emacs server is supported only\non systems with Berkely sockets.\n", 542 main_argc = argc;
543 main_argv = argv;
544 progname = argv[0];
545 message (TRUE, "%s: Sorry, the Emacs server is supported only\n"
546 "on systems with Berkeley sockets.\n",
366 argv[0]); 547 argv[0]);
367 548 fail ();
368 fail (argc, argv);
369} 549}
370 550
371#else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ 551#else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
@@ -376,8 +556,6 @@ main (argc, argv)
376# include <sys/types.h> 556# include <sys/types.h>
377# include <sys/socket.h> 557# include <sys/socket.h>
378# include <sys/un.h> 558# include <sys/un.h>
379# include <sys/stat.h>
380# include <errno.h>
381#endif 559#endif
382 560
383#define AUTH_KEY_LENGTH 64 561#define AUTH_KEY_LENGTH 64
@@ -389,6 +567,8 @@ extern int errno;
389/* Buffer to accumulate data to send in TCP connections. */ 567/* Buffer to accumulate data to send in TCP connections. */
390char send_buffer[SEND_BUFFER_SIZE + 1]; 568char send_buffer[SEND_BUFFER_SIZE + 1];
391int sblen = 0; /* Fill pointer for the send buffer. */ 569int sblen = 0; /* Fill pointer for the send buffer. */
570/* Socket used to communicate with the Emacs server process. */
571HSOCKET emacs_socket = 0;
392 572
393/* Let's send the data to Emacs when either 573/* Let's send the data to Emacs when either
394 - the data ends in "\n", or 574 - the data ends in "\n", or
@@ -429,18 +609,21 @@ send_to_emacs (s, data)
429 } 609 }
430} 610}
431 611
432/* In NAME, insert a & before each &, each space, each newline, and 612
613/* In STR, insert a & before each &, each space, each newline, and
433 any initial -. Change spaces to underscores, too, so that the 614 any initial -. Change spaces to underscores, too, so that the
434 return value never contains a space. */ 615 return value never contains a space.
616
617 Does not change the string. Outputs the result to STREAM. */
435void 618void
436quote_file_name (s, name) 619quote_argument (s, str)
437 HSOCKET s; 620 HSOCKET s;
438 char *name; 621 char *str;
439{ 622{
440 char *copy = (char *) malloc (strlen (name) * 2 + 1); 623 char *copy = (char *) xmalloc (strlen (str) * 2 + 1);
441 char *p, *q; 624 char *p, *q;
442 625
443 p = name; 626 p = str;
444 q = copy; 627 q = copy;
445 while (*p) 628 while (*p)
446 { 629 {
@@ -458,18 +641,54 @@ quote_file_name (s, name)
458 } 641 }
459 else 642 else
460 { 643 {
461 if (*p == '&' || (*p == '-' && p == name)) 644 if (*p == '&' || (*p == '-' && p == str))
462 *q++ = '&'; 645 *q++ = '&';
463 *q++ = *p++; 646 *q++ = *p++;
464 } 647 }
465 } 648 }
466 *q++ = 0; 649 *q++ = 0;
467 650
468 SEND_STRING (copy); 651 send_to_emacs (s, copy);
469 652
470 free (copy); 653 free (copy);
471} 654}
472 655
656
657/* The inverse of quote_argument. Removes quoting in string STR by
658 modifying the string in place. Returns STR. */
659
660char *
661unquote_argument (str)
662 char *str;
663{
664 char *p, *q;
665
666 if (! str)
667 return str;
668
669 p = str;
670 q = str;
671 while (*p)
672 {
673 if (*p == '&')
674 {
675 p++;
676 if (*p == '&')
677 *p = '&';
678 else if (*p == '_')
679 *p = ' ';
680 else if (*p == 'n')
681 *p = '\n';
682 else if (*p == '-')
683 *p = '-';
684 }
685 *q++ = *p++;
686 }
687 *q = 0;
688 return str;
689}
690
691
473int 692int
474file_name_absolute_p (filename) 693file_name_absolute_p (filename)
475 const unsigned char *filename; 694 const unsigned char *filename;
@@ -551,6 +770,7 @@ initialize_sockets ()
551 atexit (close_winsock); 770 atexit (close_winsock);
552} 771}
553#endif /* WINDOWSNT */ 772#endif /* WINDOWSNT */
773
554 774
555/* 775/*
556 * Read the information needed to set up a TCP comm channel with 776 * Read the information needed to set up a TCP comm channel with
@@ -661,13 +881,32 @@ set_tcp_socket ()
661 */ 881 */
662 auth_string[AUTH_KEY_LENGTH] = '\0'; 882 auth_string[AUTH_KEY_LENGTH] = '\0';
663 883
664 SEND_STRING ("-auth "); 884 send_to_emacs (s, "-auth ");
665 SEND_STRING (auth_string); 885 send_to_emacs (s, auth_string);
666 SEND_STRING ("\n"); 886 send_to_emacs (s, "\n");
667 887
668 return s; 888 return s;
669} 889}
670 890
891
892/* Returns 1 if PREFIX is a prefix of STRING. */
893static int
894strprefix (char *prefix, char *string)
895{
896 int i;
897 if (! prefix)
898 return 1;
899
900 if (!string)
901 return 0;
902
903 for (i = 0; prefix[i]; i++)
904 if (!string[i] || string[i] != prefix[i])
905 return 0;
906 return 1;
907}
908
909
671#if !defined (NO_SOCKETS_IN_FILE_SYSTEM) 910#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
672 911
673/* Three possibilities: 912/* Three possibilities:
@@ -690,6 +929,93 @@ socket_status (socket_name)
690 return 0; 929 return 0;
691} 930}
692 931
932
933/* A signal handler that passes the signal to the Emacs process.
934 Useful for SIGWINCH. */
935
936SIGTYPE
937pass_signal_to_emacs (int signalnum)
938{
939 int old_errno = errno;
940
941 if (emacs_pid)
942 kill (emacs_pid, signalnum);
943
944 signal (signalnum, pass_signal_to_emacs);
945 errno = old_errno;
946}
947
948/* Signal handler for SIGCONT; notify the Emacs process that it can
949 now resume our tty frame. */
950
951SIGTYPE
952handle_sigcont (int signalnum)
953{
954 int old_errno = errno;
955
956 if (tcgetpgrp (1) == getpgrp ())
957 {
958 /* We are in the foreground. */
959 send_to_emacs (emacs_socket, "-resume \n");
960 }
961 else
962 {
963 /* We are in the background; cancel the continue. */
964 kill (getpid (), SIGSTOP);
965 }
966
967 signal (signalnum, handle_sigcont);
968 errno = old_errno;
969}
970
971/* Signal handler for SIGTSTP; notify the Emacs process that we are
972 going to sleep. Normally the suspend is initiated by Emacs via
973 server-handle-suspend-tty, but if the server gets out of sync with
974 reality, we may get a SIGTSTP on C-z. Handling this signal and
975 notifying Emacs about it should get things under control again. */
976
977SIGTYPE
978handle_sigtstp (int signalnum)
979{
980 int old_errno = errno;
981 sigset_t set;
982
983 if (emacs_socket)
984 send_to_emacs (emacs_socket, "-suspend \n");
985
986 /* Unblock this signal and call the default handler by temprarily
987 changing the handler and resignalling. */
988 sigprocmask (SIG_BLOCK, NULL, &set);
989 sigdelset (&set, signalnum);
990 signal (signalnum, SIG_DFL);
991 kill (getpid (), signalnum);
992 sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
993 signal (signalnum, handle_sigtstp);
994
995 errno = old_errno;
996}
997/* Set up signal handlers before opening a frame on the current tty. */
998
999void
1000init_signals (void)
1001{
1002 /* Set up signal handlers. */
1003 signal (SIGWINCH, pass_signal_to_emacs);
1004
1005 /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of
1006 deciding which terminal the signal came from. C-g is now a
1007 normal input event on secondary terminals. */
1008#if 0
1009 signal (SIGINT, pass_signal_to_emacs);
1010 signal (SIGQUIT, pass_signal_to_emacs);
1011#endif
1012
1013 signal (SIGCONT, handle_sigcont);
1014 signal (SIGTSTP, handle_sigtstp);
1015 signal (SIGTTOU, handle_sigtstp);
1016}
1017
1018
693HSOCKET 1019HSOCKET
694set_local_socket () 1020set_local_socket ()
695{ 1021{
@@ -711,30 +1037,31 @@ set_local_socket ()
711 { 1037 {
712 int sock_status = 0; 1038 int sock_status = 0;
713 int default_sock = !socket_name; 1039 int default_sock = !socket_name;
714 int saved_errno; 1040 int saved_errno = 0;
1041
715 char *server_name = "server"; 1042 char *server_name = "server";
716 1043
717 if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) 1044 if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
718 { /* socket_name is a file name component. */ 1045 { /* socket_name is a file name component. */
719 server_name = socket_name; 1046 server_name = socket_name;
720 socket_name = NULL; 1047 socket_name = NULL;
721 default_sock = 1; /* Try both UIDs. */ 1048 default_sock = 1; /* Try both UIDs. */
722 } 1049 }
723 1050
724 if (default_sock) 1051 if (default_sock)
725 { 1052 {
726 socket_name = alloca (100 + strlen (server_name)); 1053 socket_name = alloca (100 + strlen (server_name));
727 sprintf (socket_name, "/tmp/emacs%d/%s", 1054 sprintf (socket_name, "/tmp/emacs%d/%s",
728 (int) geteuid (), server_name); 1055 (int) geteuid (), server_name);
729 } 1056 }
730 1057
731 if (strlen (socket_name) < sizeof (server.sun_path)) 1058 if (strlen (socket_name) < sizeof (server.sun_path))
732 strcpy (server.sun_path, socket_name); 1059 strcpy (server.sun_path, socket_name);
733 else 1060 else
734 { 1061 {
735 message (TRUE, "%s: socket-name %s too long", 1062 message (TRUE, "%s: socket-name %s too long",
736 progname, socket_name); 1063 progname, socket_name);
737 exit (EXIT_FAILURE); 1064 fail ();
738 } 1065 }
739 1066
740 /* See if the socket exists, and if it's owned by us. */ 1067 /* See if the socket exists, and if it's owned by us. */
@@ -773,7 +1100,7 @@ set_local_socket ()
773 } 1100 }
774 1101
775 sock_status = socket_status (server.sun_path); 1102 sock_status = socket_status (server.sun_path);
776 saved_errno = errno; 1103 saved_errno = errno;
777 } 1104 }
778 else 1105 else
779 errno = saved_errno; 1106 errno = saved_errno;
@@ -783,26 +1110,26 @@ set_local_socket ()
783 switch (sock_status) 1110 switch (sock_status)
784 { 1111 {
785 case 1: 1112 case 1:
786 /* There's a socket, but it isn't owned by us. This is OK if 1113 /* There's a socket, but it isn't owned by us. This is OK if
787 we are root. */ 1114 we are root. */
788 if (0 != geteuid ()) 1115 if (0 != geteuid ())
789 { 1116 {
790 message (TRUE, "%s: Invalid socket owner\n", progname); 1117 message (TRUE, "%s: Invalid socket owner\n", progname);
791 return INVALID_SOCKET; 1118 return INVALID_SOCKET;
792 } 1119 }
793 break; 1120 break;
794 1121
795 case 2: 1122 case 2:
796 /* `stat' failed */ 1123 /* `stat' failed */
797 if (saved_errno == ENOENT) 1124 if (saved_errno == ENOENT)
798 message (TRUE, 1125 message (TRUE,
799 "%s: can't find socket; have you started the server?\n\ 1126 "%s: can't find socket; have you started the server?\n\
800To start the server in Emacs, type \"M-x server-start\".\n", 1127To start the server in Emacs, type \"M-x server-start\".\n",
801 progname); 1128 progname);
802 else 1129 else
803 message (TRUE, "%s: can't stat %s: %s\n", 1130 message (TRUE, "%s: can't stat %s: %s\n",
804 progname, server.sun_path, strerror (saved_errno)); 1131 progname, server.sun_path, strerror (saved_errno));
805 return INVALID_SOCKET; 1132 return INVALID_SOCKET;
806 } 1133 }
807 } 1134 }
808 1135
@@ -830,10 +1157,9 @@ set_socket ()
830 { 1157 {
831 s = set_local_socket (); 1158 s = set_local_socket ();
832 if ((s != INVALID_SOCKET) || alternate_editor) 1159 if ((s != INVALID_SOCKET) || alternate_editor)
833 return s; 1160 return s;
834
835 message (TRUE, "%s: error accessing socket \"%s\"", 1161 message (TRUE, "%s: error accessing socket \"%s\"",
836 progname, socket_name); 1162 progname, socket_name);
837 exit (EXIT_FAILURE); 1163 exit (EXIT_FAILURE);
838 } 1164 }
839#endif 1165#endif
@@ -846,10 +1172,10 @@ set_socket ()
846 { 1172 {
847 s = set_tcp_socket (); 1173 s = set_tcp_socket ();
848 if ((s != INVALID_SOCKET) || alternate_editor) 1174 if ((s != INVALID_SOCKET) || alternate_editor)
849 return s; 1175 return s;
850 1176
851 message (TRUE, "%s: error accessing server file \"%s\"", 1177 message (TRUE, "%s: error accessing server file \"%s\"",
852 progname, server_file); 1178 progname, server_file);
853 exit (EXIT_FAILURE); 1179 exit (EXIT_FAILURE);
854 } 1180 }
855 1181
@@ -938,129 +1264,274 @@ main (argc, argv)
938 int argc; 1264 int argc;
939 char **argv; 1265 char **argv;
940{ 1266{
941 HSOCKET s;
942 int i, rl, needlf = 0; 1267 int i, rl, needlf = 0;
943 char *cwd; 1268 char *cwd, *str;
944 char string[BUFSIZ+1]; 1269 char string[BUFSIZ+1];
945 1270
1271 main_argc = argc;
1272 main_argv = argv;
946 progname = argv[0]; 1273 progname = argv[0];
947 1274
948 /* Process options. */ 1275 /* Process options. */
949 decode_options (argc, argv); 1276 decode_options (argc, argv);
950 1277
951 if ((argc - optind < 1) && !eval) 1278 if ((argc - optind < 1) && !eval && !tty && !window_system)
952 { 1279 {
953 message (TRUE, "%s: file name or argument required\nTry `%s --help' for more information\n", 1280 message (TRUE, "%s: file name or argument required\n"
954 progname, progname); 1281 "Try `%s --help' for more information\n",
1282 progname, progname);
955 exit (EXIT_FAILURE); 1283 exit (EXIT_FAILURE);
956 } 1284 }
957 1285
958 if ((s = set_socket ()) == INVALID_SOCKET) 1286 if ((emacs_socket = set_socket ()) == INVALID_SOCKET)
959 fail (argc, argv); 1287 fail ();
960 1288
961#ifdef HAVE_GETCWD 1289
962 cwd = getcwd (string, sizeof string); 1290 cwd = get_current_dir_name ();
963#else
964 cwd = getwd (string);
965#endif
966 if (cwd == 0) 1291 if (cwd == 0)
967 { 1292 {
968 /* getwd puts message in STRING if it fails. */ 1293 /* getwd puts message in STRING if it fails. */
969 message (TRUE, "%s: %s (%s)\n", progname, 1294 message (TRUE, "%s: %s\n", progname,
970#ifdef HAVE_GETCWD 1295 "Cannot get current working directory");
971 "Cannot get current working directory", 1296 fail ();
972#else
973 string,
974#endif
975 strerror (errno));
976 fail (argc, argv);
977 } 1297 }
978 1298
979#ifdef WINDOWSNT 1299#ifdef WINDOWSNT
980 w32_give_focus (); 1300 w32_give_focus ();
981#endif 1301#endif
982 1302
1303 /* First of all, send our version number for verification. */
1304 send_to_emacs (emacs_socket, "-version ");
1305 send_to_emacs (emacs_socket, VERSION);
1306 send_to_emacs (emacs_socket, " ");
1307
1308 /* Send over our environment. */
1309 if (!current_frame)
1310 {
1311 extern char **environ;
1312 int i;
1313 for (i = 0; environ[i]; i++)
1314 {
1315 char *name = xstrdup (environ[i]);
1316 char *value = strchr (name, '=');
1317 send_to_emacs (emacs_socket, "-env ");
1318 quote_argument (emacs_socket, environ[i]);
1319 send_to_emacs (emacs_socket, " ");
1320 }
1321 }
1322
1323 /* Send over our current directory. */
1324 if (!current_frame)
1325 {
1326 send_to_emacs (emacs_socket, "-dir ");
1327 quote_argument (emacs_socket, cwd);
1328 send_to_emacs (emacs_socket, "/");
1329 send_to_emacs (emacs_socket, " ");
1330 }
1331
1332 retry:
983 if (nowait) 1333 if (nowait)
984 SEND_STRING ("-nowait "); 1334 send_to_emacs (emacs_socket, "-nowait ");
985 1335
986 if (eval) 1336 if (current_frame)
987 SEND_STRING ("-eval "); 1337 send_to_emacs (emacs_socket, "-current-frame ");
988 1338
989 if (display) 1339 if (display)
990 { 1340 {
991 SEND_STRING ("-display "); 1341 send_to_emacs (emacs_socket, "-display ");
992 SEND_QUOTED (display); 1342 quote_argument (emacs_socket, display);
993 SEND_STRING (" "); 1343 send_to_emacs (emacs_socket, " ");
1344 }
1345
1346 if (tty)
1347 {
1348 char *type = getenv ("TERM");
1349 char *tty_name = NULL;
1350#ifndef WINDOWSNT
1351 tty_name = ttyname (fileno (stdin));
1352#endif
1353
1354 if (! tty_name)
1355 {
1356 message (TRUE, "%s: could not get terminal name\n", progname);
1357 fail ();
1358 }
1359
1360 if (! type)
1361 {
1362 message (TRUE, "%s: please set the TERM variable to your terminal type\n",
1363 progname);
1364 fail ();
1365 }
1366
1367 if (! strcmp (type, "eterm"))
1368 {
1369 /* This causes nasty, MULTI_KBOARD-related input lockouts. */
1370 message (TRUE, "%s: opening a frame in an Emacs term buffer"
1371 " is not supported\n", progname);
1372 fail ();
1373 }
1374#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
1375 init_signals ();
1376#endif
1377
1378 send_to_emacs (emacs_socket, "-tty ");
1379 quote_argument (emacs_socket, tty_name);
1380 send_to_emacs (emacs_socket, " ");
1381 quote_argument (emacs_socket, type);
1382 send_to_emacs (emacs_socket, " ");
994 } 1383 }
995 1384
1385 if (window_system)
1386 send_to_emacs (emacs_socket, "-window-system ");
1387
996 if ((argc - optind > 0)) 1388 if ((argc - optind > 0))
997 { 1389 {
998 for (i = optind; i < argc; i++) 1390 for (i = optind; i < argc; i++)
999 { 1391 {
1392 int relative = 0;
1393
1000 if (eval) 1394 if (eval)
1001 ; /* Don't prepend any cwd or anything like that. */ 1395 {
1002 else if (*argv[i] == '+') 1396 /* Don't prepend cwd or anything like that. */
1003 { 1397 send_to_emacs (emacs_socket, "-eval ");
1398 quote_argument (emacs_socket, argv[i]);
1399 send_to_emacs (emacs_socket, " ");
1400 continue;
1401 }
1402
1403 if (*argv[i] == '+')
1404 {
1004 char *p = argv[i] + 1; 1405 char *p = argv[i] + 1;
1005 while (isdigit ((unsigned char) *p) || *p == ':') p++; 1406 while (isdigit ((unsigned char) *p) || *p == ':') p++;
1006 if (*p != 0) 1407 if (*p == 0)
1007 { 1408 {
1008 SEND_QUOTED (cwd); 1409 send_to_emacs (emacs_socket, "-position ");
1009 SEND_STRING ("/"); 1410 quote_argument (emacs_socket, argv[i]);
1010 } 1411 send_to_emacs (emacs_socket, " ");
1011 } 1412 continue;
1413 }
1414 else
1415 relative = 1;
1416 }
1012 else if (! file_name_absolute_p (argv[i])) 1417 else if (! file_name_absolute_p (argv[i]))
1013 { 1418 relative = 1;
1014 SEND_QUOTED (cwd); 1419
1015 SEND_STRING ("/"); 1420 send_to_emacs (emacs_socket, "-file ");
1016 } 1421 if (relative)
1017 1422 {
1018 SEND_QUOTED (argv[i]); 1423 quote_argument (emacs_socket, cwd);
1019 SEND_STRING (" "); 1424 send_to_emacs (emacs_socket, "/");
1020 } 1425 }
1426 quote_argument (emacs_socket, argv[i]);
1427 send_to_emacs (emacs_socket, " ");
1428 }
1021 } 1429 }
1022 else 1430 else
1023 { 1431 {
1024 while (fgets (string, BUFSIZ, stdin)) 1432 if (!tty && !window_system)
1025 { 1433 {
1026 SEND_QUOTED (string); 1434 while ((str = fgets (string, BUFSIZ, stdin)))
1027 } 1435 {
1028 SEND_STRING (" "); 1436 if (eval)
1437 send_to_emacs (emacs_socket, "-eval ");
1438 else
1439 send_to_emacs (emacs_socket, "-file ");
1440 quote_argument (emacs_socket, str);
1441 }
1442 send_to_emacs (emacs_socket, " ");
1443 }
1029 } 1444 }
1030 1445
1031 SEND_STRING ("\n"); 1446 send_to_emacs (emacs_socket, "\n");
1032 1447
1033 /* Maybe wait for an answer. */ 1448 /* Wait for an answer. */
1034 if (!nowait) 1449 if (!eval && !tty && !nowait)
1035 { 1450 {
1036 if (!eval) 1451 printf ("Waiting for Emacs...");
1452 needlf = 2;
1453 }
1454 fflush (stdout);
1455 fsync (1);
1456
1457 /* Now, wait for an answer and print any messages. */
1458 while ((rl = recv (emacs_socket, string, BUFSIZ, 0)) > 0)
1459 {
1460 char *p;
1461 string[rl] = '\0';
1462
1463 p = string + strlen (string) - 1;
1464 while (p > string && *p == '\n')
1465 *p-- = 0;
1466
1467 if (strprefix ("-good-version ", string))
1037 { 1468 {
1038 printf ("Waiting for Emacs..."); 1469 /* -good-version: The versions match. */
1039 needlf = 2;
1040 } 1470 }
1041 fflush (stdout); 1471 else if (strprefix ("-emacs-pid ", string))
1042 1472 {
1043 /* Now, wait for an answer and print any messages. */ 1473 /* -emacs-pid PID: The process id of the Emacs process. */
1044 while ((rl = recv (s, string, BUFSIZ, 0)) > 0) 1474 emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
1475 }
1476 else if (strprefix ("-window-system-unsupported ", string))
1045 { 1477 {
1046 string[rl] = '\0'; 1478 /* -window-system-unsupported: Emacs was compiled without X
1047 if (needlf == 2) 1479 support. Try again on the terminal. */
1480 window_system = 0;
1481 nowait = 0;
1482 tty = 1;
1483 goto retry;
1484 }
1485 else if (strprefix ("-print ", string))
1486 {
1487 /* -print STRING: Print STRING on the terminal. */
1488 str = unquote_argument (string + strlen ("-print "));
1489 if (needlf)
1048 printf ("\n"); 1490 printf ("\n");
1049 printf ("%s", string); 1491 printf ("%s", str);
1050 needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n'; 1492 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
1493 }
1494 else if (strprefix ("-error ", string))
1495 {
1496 /* -error DESCRIPTION: Signal an error on the terminal. */
1497 str = unquote_argument (string + strlen ("-error "));
1498 if (needlf)
1499 printf ("\n");
1500 fprintf (stderr, "*ERROR*: %s", str);
1501 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
1502 }
1503#ifndef WINDOWSNT
1504 else if (strprefix ("-suspend ", string))
1505 {
1506 /* -suspend: Suspend this terminal, i.e., stop the process. */
1507 if (needlf)
1508 printf ("\n");
1509 needlf = 0;
1510 kill (0, SIGSTOP);
1511 }
1512#endif
1513 else
1514 {
1515 /* Unknown command. */
1516 if (needlf)
1517 printf ("\n");
1518 printf ("*ERROR*: Unknown message: %s", string);
1519 needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n';
1051 } 1520 }
1052
1053 if (needlf)
1054 printf ("\n");
1055 fflush (stdout);
1056 } 1521 }
1057 1522
1058 CLOSE_SOCKET (s); 1523 if (needlf)
1524 printf ("\n");
1525 fflush (stdout);
1526 fsync (1);
1527
1528 CLOSE_SOCKET (emacs_socket);
1059 return EXIT_SUCCESS; 1529 return EXIT_SUCCESS;
1060} 1530}
1061 1531
1062#endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ 1532#endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
1063 1533
1534
1064#ifndef HAVE_STRERROR 1535#ifndef HAVE_STRERROR
1065char * 1536char *
1066strerror (errnum) 1537strerror (errnum)
diff --git a/lib-src/makefile.w32-in b/lib-src/makefile.w32-in
index 3076b85dbd8..c21401154eb 100644
--- a/lib-src/makefile.w32-in
+++ b/lib-src/makefile.w32-in
@@ -24,7 +24,7 @@ ALL = make-docfile hexl ctags etags movemail ebrowse sorted-doc digest-doc emacs
24 24
25.PHONY: $(ALL) 25.PHONY: $(ALL)
26 26
27VERSION = 22.1.50 27VERSION = 23.0.51
28 28
29LOCAL_FLAGS = -DWINDOWSNT -DDOS_NT -DSTDC_HEADERS=1 -DNO_LDAV=1 \ 29LOCAL_FLAGS = -DWINDOWSNT -DDOS_NT -DSTDC_HEADERS=1 -DNO_LDAV=1 \
30 -DNO_ARCHIVES=1 -DHAVE_CONFIG_H=1 -I../nt/inc \ 30 -DNO_ARCHIVES=1 -DHAVE_CONFIG_H=1 -I../nt/inc \