Commit | Line | Data |
---|---|---|
efb859b4 | 1 | /* Client process that communicates with GNU Emacs acting as server. |
5c9659d3 | 2 | Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2003, 2004 |
de073ce3 | 3 | Free Software Foundation, Inc. |
46cec291 RS |
4 | |
5 | This file is part of GNU Emacs. | |
6 | ||
7 | GNU Emacs is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
92af894f | 9 | the Free Software Foundation; either version 2, or (at your option) |
46cec291 RS |
10 | any later version. |
11 | ||
12 | GNU Emacs is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU Emacs; see the file COPYING. If not, write to | |
3b7ad313 EN |
19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
46cec291 RS |
21 | |
22 | ||
23 | #define NO_SHORTNAMES | |
e69233c2 PJ |
24 | |
25 | #ifdef HAVE_CONFIG_H | |
2f8fe2f4 | 26 | #include <config.h> |
e69233c2 PJ |
27 | #endif |
28 | ||
4e23f2ba | 29 | #undef signal |
46cec291 | 30 | |
e69233c2 | 31 | #include <ctype.h> |
8f9aaa0a RS |
32 | #include <stdio.h> |
33 | #include <getopt.h> | |
79f13bba DL |
34 | #ifdef HAVE_UNISTD_H |
35 | #include <unistd.h> | |
36 | #endif | |
8f9aaa0a | 37 | |
9f637eea GM |
38 | #ifdef VMS |
39 | # include "vms-pwd.h" | |
40 | #else | |
41 | # include <pwd.h> | |
42 | #endif /* not VMS */ | |
43 | ||
9628b887 | 44 | #include <signal.h> |
4d553a13 | 45 | #include <errno.h> |
9628b887 KL |
46 | |
47 | \f | |
8f9aaa0a RS |
48 | char *getenv (), *getwd (); |
49 | char *getcwd (); | |
8f9aaa0a RS |
50 | |
51 | /* This is defined with -D from the compilation command, | |
52 | which extracts it from ../lisp/version.el. */ | |
53 | ||
54 | #ifndef VERSION | |
55 | #define VERSION "unspecified" | |
56 | #endif | |
57 | \f | |
58 | /* Name used to invoke this program. */ | |
59 | char *progname; | |
60 | ||
0a125897 KL |
61 | /* The first argument to main. */ |
62 | int main_argc; | |
63 | ||
64 | /* The second argument to main. */ | |
65 | char **main_argv; | |
66 | ||
749ae770 | 67 | /* Nonzero means don't wait for a response from Emacs. --no-wait. */ |
8f9aaa0a RS |
68 | int nowait = 0; |
69 | ||
30be2360 SM |
70 | /* Nonzero means args are expressions to be evaluated. --eval. */ |
71 | int eval = 0; | |
72 | ||
77134727 KL |
73 | /* Nonzero means open a new graphical frame. */ |
74 | int window_system = 0; | |
75 | ||
30be2360 SM |
76 | /* The display on which Emacs should work. --display. */ |
77 | char *display = NULL; | |
78 | ||
9628b887 | 79 | /* Nonzero means open a new Emacs frame on the current terminal. */ |
77134727 | 80 | int tty = 0; |
9628b887 | 81 | |
30be2360 SM |
82 | /* If non-NULL, the name of an editor to fallback to if the server |
83 | is not running. --alternate-editor. */ | |
84 | const char * alternate_editor = NULL; | |
85 | ||
3db926be | 86 | /* If non-NULL, the filename of the UNIX socket. */ |
254107e4 RS |
87 | char *socket_name = NULL; |
88 | ||
7f3bff3e AS |
89 | void print_help_and_exit (); |
90 | ||
8f9aaa0a RS |
91 | struct option longopts[] = |
92 | { | |
749ae770 | 93 | { "no-wait", no_argument, NULL, 'n' }, |
30be2360 | 94 | { "eval", no_argument, NULL, 'e' }, |
8f9aaa0a RS |
95 | { "help", no_argument, NULL, 'H' }, |
96 | { "version", no_argument, NULL, 'V' }, | |
b28c910d | 97 | { "tty", no_argument, NULL, 't' }, |
e5299d8d | 98 | { "current-frame", no_argument, NULL, 'c' }, |
3cf8c6aa | 99 | { "alternate-editor", required_argument, NULL, 'a' }, |
254107e4 | 100 | { "socket-name", required_argument, NULL, 's' }, |
30be2360 SM |
101 | { "display", required_argument, NULL, 'd' }, |
102 | { 0, 0, 0, 0 } | |
8f9aaa0a RS |
103 | }; |
104 | ||
105 | /* Decode the options from argv and argc. | |
5212210c | 106 | The global variable `optind' will say how many arguments we used up. */ |
8f9aaa0a | 107 | |
5212210c | 108 | void |
8f9aaa0a RS |
109 | decode_options (argc, argv) |
110 | int argc; | |
111 | char **argv; | |
112 | { | |
b6b6d6d2 | 113 | alternate_editor = getenv ("ALTERNATE_EDITOR"); |
77134727 | 114 | display = getenv ("DISPLAY"); |
8689463a | 115 | if (display && strlen (display) == 0) |
e5299d8d KL |
116 | display = NULL; |
117 | ||
118 | if (display) | |
119 | window_system = 1; | |
120 | else | |
121 | tty = 1; | |
b6b6d6d2 | 122 | |
8f9aaa0a RS |
123 | while (1) |
124 | { | |
125 | int opt = getopt_long (argc, argv, | |
e5299d8d | 126 | "VHnea:s:d:tc", longopts, 0); |
8f9aaa0a RS |
127 | |
128 | if (opt == EOF) | |
129 | break; | |
130 | ||
131 | switch (opt) | |
132 | { | |
133 | case 0: | |
134 | /* If getopt returns 0, then it has already processed a | |
135 | long-named option. We should do nothing. */ | |
136 | break; | |
e69233c2 | 137 | |
97e3214d GM |
138 | case 'a': |
139 | alternate_editor = optarg; | |
140 | break; | |
e69233c2 | 141 | |
254107e4 RS |
142 | case 's': |
143 | socket_name = optarg; | |
144 | break; | |
145 | ||
30be2360 SM |
146 | case 'd': |
147 | display = optarg; | |
148 | break; | |
149 | ||
8f9aaa0a RS |
150 | case 'n': |
151 | nowait = 1; | |
152 | break; | |
153 | ||
30be2360 SM |
154 | case 'e': |
155 | eval = 1; | |
156 | break; | |
157 | ||
8f9aaa0a | 158 | case 'V': |
20c396e8 JB |
159 | printf ("emacsclient %s\n", VERSION); |
160 | exit (0); | |
8f9aaa0a | 161 | break; |
46cec291 | 162 | |
819b8f00 | 163 | case 't': |
77134727 KL |
164 | tty = 1; |
165 | window_system = 0; | |
166 | break; | |
167 | ||
e5299d8d KL |
168 | case 'c': |
169 | window_system = 0; | |
77134727 | 170 | tty = 0; |
9628b887 KL |
171 | break; |
172 | ||
8f9aaa0a | 173 | case 'H': |
8f9aaa0a | 174 | print_help_and_exit (); |
20c396e8 JB |
175 | break; |
176 | ||
177 | default: | |
178 | fprintf (stderr, "Try `%s --help' for more information\n", progname); | |
179 | exit (1); | |
180 | break; | |
8f9aaa0a RS |
181 | } |
182 | } | |
9628b887 | 183 | |
77134727 | 184 | if (tty) { |
9628b887 KL |
185 | nowait = 0; |
186 | display = 0; | |
187 | } | |
8f9aaa0a RS |
188 | } |
189 | ||
7f3bff3e | 190 | void |
8f9aaa0a RS |
191 | print_help_and_exit () |
192 | { | |
20c396e8 JB |
193 | printf ( |
194 | "Usage: %s [OPTIONS] FILE...\n\ | |
30be2360 SM |
195 | Tell the Emacs server to visit the specified files.\n\ |
196 | Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ | |
20c396e8 | 197 | \n\ |
30be2360 SM |
198 | The following OPTIONS are accepted:\n\ |
199 | -V, --version Just print a version info and return\n\ | |
200 | -H, --help Print this usage information message\n\ | |
819b8f00 | 201 | -t, --tty Open a new Emacs frame on the current terminal\n\ |
e5299d8d | 202 | -c, --current-frame Do not create a new frame; use the current Emacs frame\n\ |
30be2360 SM |
203 | -n, --no-wait Don't wait for the server to return\n\ |
204 | -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ | |
205 | -d, --display=DISPLAY Visit the file in the given display\n\ | |
254107e4 RS |
206 | -s, --socket-name=FILENAME\n\ |
207 | Set the filename of the UNIX socket for communication\n\ | |
30be2360 SM |
208 | -a, --alternate-editor=EDITOR\n\ |
209 | Editor to fallback to if the server is not running\n\ | |
20c396e8 | 210 | \n\ |
30be2360 | 211 | Report bugs to bug-gnu-emacs@gnu.org.\n", progname); |
20c396e8 | 212 | exit (0); |
8f9aaa0a | 213 | } |
5212210c | 214 | |
a4cf2096 RS |
215 | /* In NAME, insert a & before each &, each space, each newline, and |
216 | any initial -. Change spaces to underscores, too, so that the | |
5212210c RS |
217 | return value never contains a space. */ |
218 | ||
87209357 EZ |
219 | void |
220 | quote_file_name (name, stream) | |
5212210c | 221 | char *name; |
87209357 | 222 | FILE *stream; |
5212210c RS |
223 | { |
224 | char *copy = (char *) malloc (strlen (name) * 2 + 1); | |
225 | char *p, *q; | |
226 | ||
227 | p = name; | |
228 | q = copy; | |
229 | while (*p) | |
230 | { | |
231 | if (*p == ' ') | |
232 | { | |
f1db6a73 | 233 | *q++ = '&'; |
5212210c RS |
234 | *q++ = '_'; |
235 | p++; | |
236 | } | |
3cf8c6aa SM |
237 | else if (*p == '\n') |
238 | { | |
239 | *q++ = '&'; | |
240 | *q++ = 'n'; | |
241 | p++; | |
242 | } | |
5212210c RS |
243 | else |
244 | { | |
f1db6a73 RS |
245 | if (*p == '&' || (*p == '-' && p == name)) |
246 | *q++ = '&'; | |
5212210c RS |
247 | *q++ = *p++; |
248 | } | |
249 | } | |
f1db6a73 | 250 | *q++ = 0; |
5212210c | 251 | |
87209357 EZ |
252 | fprintf (stream, copy); |
253 | ||
254 | free (copy); | |
5212210c | 255 | } |
0c76956f | 256 | |
0c76956f RS |
257 | /* Like malloc but get fatal error if memory is exhausted. */ |
258 | ||
5497dfdb | 259 | long * |
0c76956f RS |
260 | xmalloc (size) |
261 | unsigned int size; | |
262 | { | |
5f32a712 | 263 | long *result = (long *) malloc (size); |
0c76956f RS |
264 | if (result == NULL) |
265 | { | |
266 | perror ("malloc"); | |
267 | exit (1); | |
268 | } | |
269 | return result; | |
270 | } | |
8f9aaa0a | 271 | \f |
97e3214d GM |
272 | /* |
273 | Try to run a different command, or --if no alternate editor is | |
274 | defined-- exit with an errorcode. | |
275 | */ | |
de073ce3 | 276 | void |
819b8f00 | 277 | fail (void) |
97e3214d GM |
278 | { |
279 | if (alternate_editor) | |
280 | { | |
3cf8c6aa | 281 | int i = optind - 1; |
0a125897 | 282 | execvp (alternate_editor, main_argv + i); |
23431241 | 283 | return; |
97e3214d GM |
284 | } |
285 | else | |
286 | { | |
287 | exit (1); | |
288 | } | |
289 | } | |
290 | ||
6548cf00 | 291 | int emacs_pid; |
9628b887 | 292 | |
da8e1115 KL |
293 | /* A signal handler that passes the signal to the Emacs process. |
294 | Useful for SIGWINCH. */ | |
295 | ||
9628b887 | 296 | SIGTYPE |
428a555e | 297 | pass_signal_to_emacs (int signalnum) |
9628b887 KL |
298 | { |
299 | int old_errno = errno; | |
300 | ||
9f729af5 | 301 | if (emacs_pid) |
428a555e | 302 | kill (emacs_pid, signalnum); |
9f729af5 | 303 | |
428a555e | 304 | signal (signalnum, pass_signal_to_emacs); |
9f729af5 KL |
305 | errno = old_errno; |
306 | } | |
307 | ||
da8e1115 KL |
308 | /* Set up signal handlers before opening a frame on the current tty. */ |
309 | ||
4d553a13 KL |
310 | void |
311 | init_signals (void) | |
9628b887 KL |
312 | { |
313 | /* Set up signal handlers. */ | |
428a555e | 314 | signal (SIGWINCH, pass_signal_to_emacs); |
4ca927b4 KL |
315 | |
316 | /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of | |
317 | deciding which terminal the signal came from. C-g is now a | |
318 | normal input event on secondary terminals. */ | |
319 | #if 0 | |
428a555e KL |
320 | signal (SIGINT, pass_signal_to_emacs); |
321 | signal (SIGQUIT, pass_signal_to_emacs); | |
4ca927b4 | 322 | #endif |
9628b887 KL |
323 | } |
324 | ||
97e3214d | 325 | \f |
30be2360 | 326 | #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) |
46cec291 | 327 | |
de073ce3 | 328 | int |
46cec291 RS |
329 | main (argc, argv) |
330 | int argc; | |
331 | char **argv; | |
332 | { | |
333 | fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n", | |
334 | argv[0]); | |
30be2360 | 335 | fprintf (stderr, "on systems with Berkeley sockets.\n"); |
97e3214d | 336 | |
819b8f00 | 337 | fail (); |
46cec291 RS |
338 | } |
339 | ||
30be2360 | 340 | #else /* HAVE_SOCKETS */ |
46cec291 RS |
341 | |
342 | #include <sys/types.h> | |
343 | #include <sys/socket.h> | |
344 | #include <sys/un.h> | |
efb859b4 | 345 | #include <sys/stat.h> |
46cec291 RS |
346 | #include <errno.h> |
347 | ||
92af894f | 348 | extern char *strerror (); |
46cec291 RS |
349 | extern int errno; |
350 | ||
9f637eea GM |
351 | /* Three possibilities: |
352 | 2 - can't be `stat'ed (sets errno) | |
353 | 1 - isn't owned by us | |
354 | 0 - success: none of the above */ | |
355 | ||
356 | static int | |
357 | socket_status (socket_name) | |
358 | char *socket_name; | |
359 | { | |
360 | struct stat statbfr; | |
361 | ||
362 | if (stat (socket_name, &statbfr) == -1) | |
363 | return 2; | |
364 | ||
365 | if (statbfr.st_uid != geteuid ()) | |
366 | return 1; | |
367 | ||
368 | return 0; | |
369 | } | |
370 | ||
4d553a13 KL |
371 | /* Returns 1 if PREFIX is a prefix of STRING. */ |
372 | static int | |
373 | strprefix (char *prefix, char *string) | |
374 | { | |
375 | int i; | |
376 | if (! prefix) | |
377 | return 1; | |
378 | ||
379 | if (!string) | |
380 | return 0; | |
381 | ||
382 | for (i = 0; prefix[i]; i++) | |
383 | if (!string[i] || string[i] != prefix[i]) | |
384 | return 0; | |
385 | return 1; | |
386 | } | |
387 | ||
340ff9de | 388 | int |
46cec291 RS |
389 | main (argc, argv) |
390 | int argc; | |
391 | char **argv; | |
392 | { | |
3cf8c6aa | 393 | int s, i, needlf = 0; |
23a7488d | 394 | FILE *out, *in; |
46cec291 | 395 | struct sockaddr_un server; |
571512de | 396 | char *cwd, *str; |
46cec291 | 397 | char string[BUFSIZ]; |
8f9aaa0a | 398 | |
0a125897 KL |
399 | main_argc = argc; |
400 | main_argv = argv; | |
8f9aaa0a | 401 | progname = argv[0]; |
46cec291 | 402 | |
8f9aaa0a | 403 | /* Process options. */ |
5212210c | 404 | decode_options (argc, argv); |
46cec291 | 405 | |
77134727 | 406 | if ((argc - optind < 1) && !eval && !tty && !window_system) |
20c396e8 JB |
407 | { |
408 | fprintf (stderr, "%s: file name or argument required\n", progname); | |
409 | fprintf (stderr, "Try `%s --help' for more information\n", progname); | |
410 | exit (1); | |
411 | } | |
46cec291 | 412 | |
e69233c2 | 413 | /* |
46cec291 RS |
414 | * Open up an AF_UNIX socket in this person's home directory |
415 | */ | |
416 | ||
417 | if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) | |
418 | { | |
419 | fprintf (stderr, "%s: ", argv[0]); | |
420 | perror ("socket"); | |
819b8f00 | 421 | fail (); |
46cec291 | 422 | } |
e69233c2 | 423 | |
46cec291 | 424 | server.sun_family = AF_UNIX; |
c5fee545 | 425 | |
c5fee545 | 426 | { |
9f637eea | 427 | int sock_status = 0; |
5c9659d3 | 428 | int default_sock = !socket_name; |
b80bf66e | 429 | int saved_errno = 0; |
819b8f00 | 430 | |
d3a6748c KL |
431 | char *server_name = "server"; |
432 | ||
433 | if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) | |
434 | { /* socket_name is a file name component. */ | |
435 | server_name = socket_name; | |
436 | socket_name = NULL; | |
437 | default_sock = 1; /* Try both UIDs. */ | |
438 | } | |
efb859b4 | 439 | |
d3a6748c | 440 | if (default_sock) |
254107e4 | 441 | { |
d3a6748c KL |
442 | socket_name = alloca (100 + strlen (server_name)); |
443 | sprintf (socket_name, "/tmp/emacs%d/%s", | |
444 | (int) geteuid (), server_name); | |
254107e4 RS |
445 | } |
446 | ||
447 | if (strlen (socket_name) < sizeof (server.sun_path)) | |
448 | strcpy (server.sun_path, socket_name); | |
449 | else | |
819b8f00 KL |
450 | { |
451 | fprintf (stderr, "%s: socket-name %s too long", | |
452 | argv[0], socket_name); | |
453 | fail (); | |
454 | } | |
efb859b4 | 455 | |
9f637eea GM |
456 | /* See if the socket exists, and if it's owned by us. */ |
457 | sock_status = socket_status (server.sun_path); | |
152b6e83 | 458 | saved_errno = errno; |
5c9659d3 | 459 | if (sock_status && default_sock) |
efb859b4 | 460 | { |
9f637eea GM |
461 | /* Failing that, see if LOGNAME or USER exist and differ from |
462 | our euid. If so, look for a socket based on the UID | |
463 | associated with the name. This is reminiscent of the logic | |
464 | that init_editfns uses to set the global Vuser_full_name. */ | |
e69233c2 | 465 | |
9f637eea | 466 | char *user_name = (char *) getenv ("LOGNAME"); |
293f9f2a | 467 | |
9f637eea GM |
468 | if (!user_name) |
469 | user_name = (char *) getenv ("USER"); | |
e69233c2 | 470 | |
9f637eea GM |
471 | if (user_name) |
472 | { | |
473 | struct passwd *pw = getpwnam (user_name); | |
293f9f2a | 474 | |
9f637eea GM |
475 | if (pw && (pw->pw_uid != geteuid ())) |
476 | { | |
477 | /* We're running under su, apparently. */ | |
0734b0d0 SM |
478 | socket_name = alloca (100 + strlen (server_name)); |
479 | sprintf (socket_name, "/tmp/emacs%d/%s", | |
480 | (int) pw->pw_uid, server_name); | |
5c9659d3 SM |
481 | |
482 | if (strlen (socket_name) < sizeof (server.sun_path)) | |
483 | strcpy (server.sun_path, socket_name); | |
484 | else | |
485 | { | |
486 | fprintf (stderr, "%s: socket-name %s too long", | |
487 | argv[0], socket_name); | |
488 | exit (1); | |
489 | } | |
490 | ||
9f637eea | 491 | sock_status = socket_status (server.sun_path); |
b80bf66e | 492 | saved_errno = errno; |
9f637eea | 493 | } |
293f9f2a RS |
494 | else |
495 | errno = saved_errno; | |
9f637eea | 496 | } |
efb859b4 | 497 | } |
e69233c2 | 498 | |
9f637eea GM |
499 | switch (sock_status) |
500 | { | |
501 | case 1: | |
502 | /* There's a socket, but it isn't owned by us. This is OK if | |
503 | we are root. */ | |
504 | if (0 != geteuid ()) | |
505 | { | |
506 | fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); | |
819b8f00 | 507 | fail (); |
9f637eea GM |
508 | } |
509 | break; | |
e69233c2 | 510 | |
9f637eea GM |
511 | case 2: |
512 | /* `stat' failed */ | |
152b6e83 | 513 | if (saved_errno == ENOENT) |
9f637eea | 514 | fprintf (stderr, |
819b8f00 | 515 | "%s: Can't find socket; have you started the server?\n\ |
45adde32 | 516 | To start the server in Emacs, type \"M-x server-start\".\n", |
9f637eea GM |
517 | argv[0]); |
518 | else | |
819b8f00 | 519 | fprintf (stderr, "%s: Can't stat %s: %s\n", |
152b6e83 | 520 | argv[0], server.sun_path, strerror (saved_errno)); |
819b8f00 | 521 | fail (); |
9f637eea GM |
522 | break; |
523 | } | |
efb859b4 | 524 | } |
46cec291 | 525 | |
4e23f2ba JB |
526 | if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) |
527 | < 0) | |
46cec291 RS |
528 | { |
529 | fprintf (stderr, "%s: ", argv[0]); | |
530 | perror ("connect"); | |
819b8f00 | 531 | fail (); |
46cec291 | 532 | } |
23a7488d RS |
533 | |
534 | /* We use the stream OUT to send our command to the server. */ | |
46cec291 RS |
535 | if ((out = fdopen (s, "r+")) == NULL) |
536 | { | |
537 | fprintf (stderr, "%s: ", argv[0]); | |
538 | perror ("fdopen"); | |
819b8f00 | 539 | fail (); |
46cec291 RS |
540 | } |
541 | ||
23a7488d RS |
542 | /* We use the stream IN to read the response. |
543 | We used to use just one stream for both output and input | |
544 | on the socket, but reversing direction works nonportably: | |
545 | on some systems, the output appears as the first input; | |
546 | on other systems it does not. */ | |
547 | if ((in = fdopen (s, "r+")) == NULL) | |
548 | { | |
549 | fprintf (stderr, "%s: ", argv[0]); | |
550 | perror ("fdopen"); | |
819b8f00 | 551 | fail (); |
23a7488d RS |
552 | } |
553 | ||
38732dba | 554 | #ifdef HAVE_GETCWD |
ee6a193c | 555 | cwd = getcwd (string, sizeof string); |
38732dba RS |
556 | #else |
557 | cwd = getwd (string); | |
ee6a193c | 558 | #endif |
46cec291 RS |
559 | if (cwd == 0) |
560 | { | |
561 | /* getwd puts message in STRING if it fails. */ | |
bb5618fe | 562 | |
38732dba | 563 | #ifdef HAVE_GETCWD |
bb5618fe JB |
564 | fprintf (stderr, "%s: %s (%s)\n", argv[0], |
565 | "Cannot get current working directory", strerror (errno)); | |
38732dba | 566 | #else |
bb5618fe | 567 | fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno)); |
bd252662 | 568 | #endif |
819b8f00 | 569 | fail (); |
46cec291 RS |
570 | } |
571 | ||
a9298135 KL |
572 | /* First of all, send our version number for verification. */ |
573 | fprintf (out, "-version %s ", VERSION); | |
574 | ||
5212210c RS |
575 | if (nowait) |
576 | fprintf (out, "-nowait "); | |
292d74a3 | 577 | |
30be2360 SM |
578 | if (eval) |
579 | fprintf (out, "-eval "); | |
580 | ||
581 | if (display) | |
87209357 EZ |
582 | { |
583 | fprintf (out, "-display "); | |
584 | quote_file_name (display, out); | |
585 | fprintf (out, " "); | |
586 | } | |
30be2360 | 587 | |
77134727 | 588 | if (tty) |
9628b887 | 589 | { |
4d553a13 | 590 | char *tty_name = ttyname (fileno (stdin)); |
2fc0cf2a KL |
591 | char *type = getenv ("TERM"); |
592 | ||
4d553a13 | 593 | if (! tty_name) |
2fc0cf2a KL |
594 | { |
595 | fprintf (stderr, "%s: could not get terminal name\n", progname); | |
596 | fail (); | |
597 | } | |
598 | ||
599 | if (! type) | |
600 | { | |
601 | fprintf (stderr, "%s: please set the TERM variable to your terminal type\n", | |
602 | progname); | |
603 | fail (); | |
604 | } | |
605 | ||
606 | if (! strcmp (type, "eterm")) | |
607 | { | |
608 | /* This causes nasty, MULTI_KBOARD-related input lockouts. */ | |
609 | fprintf (stderr, "%s: opening a frame in an Emacs term buffer" | |
610 | " is not supported\n", progname); | |
611 | fail (); | |
612 | } | |
9628b887 | 613 | |
4d553a13 | 614 | init_signals (); |
9628b887 | 615 | |
819b8f00 | 616 | fprintf (out, "-tty "); |
4d553a13 | 617 | quote_file_name (tty_name, out); |
9628b887 | 618 | fprintf (out, " "); |
2fc0cf2a | 619 | quote_file_name (type, out); |
9628b887 KL |
620 | fprintf (out, " "); |
621 | } | |
77134727 KL |
622 | |
623 | if (window_system) | |
624 | fprintf (out, "-window-system "); | |
9628b887 | 625 | |
87209357 | 626 | if ((argc - optind > 0)) |
5212210c | 627 | { |
87209357 | 628 | for (i = optind; i < argc; i++) |
46cec291 | 629 | { |
87209357 EZ |
630 | if (eval) |
631 | ; /* Don't prepend any cwd or anything like that. */ | |
632 | else if (*argv[i] == '+') | |
633 | { | |
634 | char *p = argv[i] + 1; | |
635 | while (isdigit ((unsigned char) *p) || *p == ':') p++; | |
636 | if (*p != 0) | |
637 | { | |
638 | quote_file_name (cwd, out); | |
639 | fprintf (out, "/"); | |
640 | } | |
641 | } | |
642 | else if (*argv[i] != '/') | |
643 | { | |
644 | quote_file_name (cwd, out); | |
645 | fprintf (out, "/"); | |
646 | } | |
647 | ||
648 | quote_file_name (argv[i], out); | |
649 | fprintf (out, " "); | |
46cec291 | 650 | } |
46cec291 | 651 | } |
87209357 EZ |
652 | else |
653 | { | |
77134727 | 654 | if (!tty && !window_system) |
9628b887 KL |
655 | { |
656 | while ((str = fgets (string, BUFSIZ, stdin))) | |
657 | { | |
658 | quote_file_name (str, out); | |
659 | } | |
660 | fprintf (out, " "); | |
661 | } | |
87209357 EZ |
662 | } |
663 | ||
46cec291 RS |
664 | fprintf (out, "\n"); |
665 | fflush (out); | |
666 | ||
292d74a3 RS |
667 | /* Maybe wait for an answer. */ |
668 | if (nowait) | |
9628b887 | 669 | { |
9628b887 KL |
670 | return 0; |
671 | } | |
292d74a3 | 672 | |
77134727 | 673 | if (!eval && !tty) |
30be2360 SM |
674 | { |
675 | printf ("Waiting for Emacs..."); | |
676 | needlf = 2; | |
677 | } | |
46cec291 RS |
678 | fflush (stdout); |
679 | ||
3cf8c6aa | 680 | /* Now, wait for an answer and print any messages. */ |
e69233c2 | 681 | while ((str = fgets (string, BUFSIZ, in))) |
3cf8c6aa | 682 | { |
a9298135 KL |
683 | if (strprefix ("-good-version ", str)) |
684 | { | |
685 | /* OK, we got the green light. */ | |
686 | } | |
687 | else if (strprefix ("-bad-version ", str)) | |
688 | { | |
689 | if (str[strlen (str) - 1] == '\n') | |
690 | str[strlen (str) - 1] = 0; | |
691 | ||
692 | fprintf (stderr, "%s: Version mismatch: Emacs is %s, but we are %s\n", | |
693 | argv[0], str + strlen ("-bad-version "), VERSION); | |
694 | fail (); | |
695 | } | |
696 | else if (strprefix ("-emacs-pid ", str)) | |
4d553a13 | 697 | { |
77134727 KL |
698 | emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); |
699 | } | |
700 | else if (strprefix ("-print ", str)) | |
701 | { | |
702 | if (needlf == 2) | |
703 | printf ("\n"); | |
704 | printf ("%s", str + strlen ("-print ")); | |
705 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | |
706 | } | |
707 | else if (strprefix ("-error ", str)) | |
708 | { | |
709 | if (needlf == 2) | |
710 | printf ("\n"); | |
711 | printf ("*ERROR*: %s", str + strlen ("-print ")); | |
712 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | |
4d553a13 KL |
713 | } |
714 | else | |
715 | { | |
716 | if (needlf == 2) | |
717 | printf ("\n"); | |
77134727 | 718 | printf ("*ERROR*: Unknown message: %s", str); |
4d553a13 KL |
719 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; |
720 | } | |
3cf8c6aa SM |
721 | } |
722 | ||
723 | if (needlf) | |
724 | printf ("\n"); | |
725 | fflush (stdout); | |
23a7488d | 726 | |
340ff9de | 727 | return 0; |
46cec291 RS |
728 | } |
729 | ||
30be2360 | 730 | #endif /* HAVE_SOCKETS */ |
27711600 RM |
731 | \f |
732 | #ifndef HAVE_STRERROR | |
733 | char * | |
734 | strerror (errnum) | |
735 | int errnum; | |
736 | { | |
737 | extern char *sys_errlist[]; | |
738 | extern int sys_nerr; | |
739 | ||
740 | if (errnum >= 0 && errnum < sys_nerr) | |
741 | return sys_errlist[errnum]; | |
742 | return (char *) "Unknown error"; | |
743 | } | |
744 | ||
745 | #endif /* ! HAVE_STRERROR */ | |
ab5796a9 MB |
746 | |
747 | /* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7 | |
748 | (do not change this comment) */ |