Fix broken emacsclient resume on Solaris (by Dan Nicolaescu).
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
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
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
92af894f 9the Free Software Foundation; either version 2, or (at your option)
46cec291
RS
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, 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 48char *getenv (), *getwd ();
5b9562c3 49char *(getcwd) ();
8f9aaa0a 50
8f9aaa0a
RS
51#ifndef VERSION
52#define VERSION "unspecified"
53#endif
54\f
55/* Name used to invoke this program. */
56char *progname;
57
0a125897
KL
58/* The first argument to main. */
59int main_argc;
60
61/* The second argument to main. */
62char **main_argv;
63
749ae770 64/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
65int nowait = 0;
66
30be2360
SM
67/* Nonzero means args are expressions to be evaluated. --eval. */
68int eval = 0;
69
77134727
KL
70/* Nonzero means open a new graphical frame. */
71int window_system = 0;
72
30be2360
SM
73/* The display on which Emacs should work. --display. */
74char *display = NULL;
75
9628b887 76/* Nonzero means open a new Emacs frame on the current terminal. */
77134727 77int tty = 0;
9628b887 78
30be2360
SM
79/* If non-NULL, the name of an editor to fallback to if the server
80 is not running. --alternate-editor. */
81const char * alternate_editor = NULL;
82
3db926be 83/* If non-NULL, the filename of the UNIX socket. */
254107e4
RS
84char *socket_name = NULL;
85
7f3bff3e
AS
86void print_help_and_exit ();
87
8f9aaa0a
RS
88struct option longopts[] =
89{
749ae770 90 { "no-wait", no_argument, NULL, 'n' },
30be2360 91 { "eval", no_argument, NULL, 'e' },
8f9aaa0a
RS
92 { "help", no_argument, NULL, 'H' },
93 { "version", no_argument, NULL, 'V' },
b28c910d 94 { "tty", no_argument, NULL, 't' },
e5299d8d 95 { "current-frame", no_argument, NULL, 'c' },
3cf8c6aa 96 { "alternate-editor", required_argument, NULL, 'a' },
254107e4 97 { "socket-name", required_argument, NULL, 's' },
30be2360
SM
98 { "display", required_argument, NULL, 'd' },
99 { 0, 0, 0, 0 }
8f9aaa0a
RS
100};
101
102/* Decode the options from argv and argc.
5212210c 103 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 104
5212210c 105void
8f9aaa0a
RS
106decode_options (argc, argv)
107 int argc;
108 char **argv;
109{
b6b6d6d2 110 alternate_editor = getenv ("ALTERNATE_EDITOR");
77134727 111 display = getenv ("DISPLAY");
8689463a 112 if (display && strlen (display) == 0)
e5299d8d 113 display = NULL;
0b0d3e0b 114
e5299d8d
KL
115 if (display)
116 window_system = 1;
117 else
118 tty = 1;
b6b6d6d2 119
8f9aaa0a
RS
120 while (1)
121 {
122 int opt = getopt_long (argc, argv,
e5299d8d 123 "VHnea:s:d:tc", longopts, 0);
8f9aaa0a
RS
124
125 if (opt == EOF)
126 break;
127
128 switch (opt)
129 {
130 case 0:
131 /* If getopt returns 0, then it has already processed a
132 long-named option. We should do nothing. */
133 break;
e69233c2 134
97e3214d
GM
135 case 'a':
136 alternate_editor = optarg;
137 break;
e69233c2 138
254107e4
RS
139 case 's':
140 socket_name = optarg;
141 break;
142
30be2360
SM
143 case 'd':
144 display = optarg;
145 break;
146
8f9aaa0a
RS
147 case 'n':
148 nowait = 1;
149 break;
150
30be2360
SM
151 case 'e':
152 eval = 1;
153 break;
154
8f9aaa0a 155 case 'V':
20c396e8 156 printf ("emacsclient %s\n", VERSION);
65396510 157 exit (EXIT_SUCCESS);
8f9aaa0a 158 break;
46cec291 159
819b8f00 160 case 't':
77134727
KL
161 tty = 1;
162 window_system = 0;
163 break;
164
e5299d8d
KL
165 case 'c':
166 window_system = 0;
77134727 167 tty = 0;
9628b887 168 break;
0b0d3e0b 169
8f9aaa0a 170 case 'H':
8f9aaa0a 171 print_help_and_exit ();
20c396e8
JB
172 break;
173
174 default:
175 fprintf (stderr, "Try `%s --help' for more information\n", progname);
65396510 176 exit (EXIT_FAILURE);
20c396e8 177 break;
8f9aaa0a
RS
178 }
179 }
9628b887 180
77134727 181 if (tty) {
9628b887
KL
182 nowait = 0;
183 display = 0;
184 }
8f9aaa0a
RS
185}
186
7f3bff3e 187void
8f9aaa0a
RS
188print_help_and_exit ()
189{
20c396e8
JB
190 printf (
191 "Usage: %s [OPTIONS] FILE...\n\
30be2360
SM
192Tell the Emacs server to visit the specified files.\n\
193Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
20c396e8 194\n\
30be2360
SM
195The following OPTIONS are accepted:\n\
196-V, --version Just print a version info and return\n\
197-H, --help Print this usage information message\n\
819b8f00 198-t, --tty Open a new Emacs frame on the current terminal\n\
e5299d8d 199-c, --current-frame Do not create a new frame; use the current Emacs frame\n\
30be2360
SM
200-n, --no-wait Don't wait for the server to return\n\
201-e, --eval Evaluate the FILE arguments as ELisp expressions\n\
202-d, --display=DISPLAY Visit the file in the given display\n\
254107e4
RS
203-s, --socket-name=FILENAME\n\
204 Set the filename of the UNIX socket for communication\n\
30be2360
SM
205-a, --alternate-editor=EDITOR\n\
206 Editor to fallback to if the server is not running\n\
20c396e8 207\n\
30be2360 208Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
65396510 209 exit (EXIT_SUCCESS);
8f9aaa0a 210}
5212210c 211
9002956f
KL
212/* Like malloc but get fatal error if memory is exhausted. */
213
214long *
215xmalloc (size)
216 unsigned int size;
217{
218 long *result = (long *) malloc (size);
219 if (result == NULL)
220 {
221 perror ("malloc");
ab4b17be 222 exit (EXIT_FAILURE);
9002956f
KL
223 }
224 return result;
225}
226
227/* Like strdup but get a fatal error if memory is exhausted. */
228
229char *
230xstrdup (const char *s)
231{
232 char *result = strdup (s);
233 if (result == NULL)
234 {
235 perror ("strdup");
ab4b17be 236 exit (EXIT_FAILURE);
9002956f
KL
237 }
238 return result;
239}
240
0b0d3e0b 241/* In STR, insert a & before each &, each space, each newline, and
a4cf2096 242 any initial -. Change spaces to underscores, too, so that the
0b0d3e0b
KL
243 return value never contains a space.
244
245 Does not change the string. Outputs the result to STREAM. */
5212210c 246
87209357 247void
0b0d3e0b
KL
248quote_argument (str, stream)
249 char *str;
87209357 250 FILE *stream;
5212210c 251{
9002956f 252 char *copy = (char *) xmalloc (strlen (str) * 2 + 1);
5212210c
RS
253 char *p, *q;
254
0b0d3e0b 255 p = str;
5212210c
RS
256 q = copy;
257 while (*p)
258 {
259 if (*p == ' ')
260 {
f1db6a73 261 *q++ = '&';
5212210c
RS
262 *q++ = '_';
263 p++;
264 }
3cf8c6aa
SM
265 else if (*p == '\n')
266 {
267 *q++ = '&';
268 *q++ = 'n';
269 p++;
270 }
5212210c
RS
271 else
272 {
0b0d3e0b 273 if (*p == '&' || (*p == '-' && p == str))
f1db6a73 274 *q++ = '&';
5212210c
RS
275 *q++ = *p++;
276 }
277 }
f1db6a73 278 *q++ = 0;
5212210c 279
60879731 280 fprintf (stream, "%s", copy);
87209357
EZ
281
282 free (copy);
5212210c 283}
0c76956f 284
0b0d3e0b
KL
285
286/* The inverse of quote_argument. Removes quoting in string STR by
287 modifying the string in place. Returns STR. */
288
289char *
290unquote_argument (str)
291 char *str;
292{
293 char *p, *q;
294
295 if (! str)
296 return str;
297
298 p = str;
299 q = str;
300 while (*p)
301 {
302 if (*p == '&')
303 {
304 p++;
305 if (*p == '&')
306 *p = '&';
307 else if (*p == '_')
308 *p = ' ';
309 else if (*p == 'n')
310 *p = '\n';
311 else if (*p == '-')
312 *p = '-';
313 }
314 *q++ = *p++;
315 }
316 *q = 0;
317 return str;
318}
319
8f9aaa0a 320\f
97e3214d
GM
321/*
322 Try to run a different command, or --if no alternate editor is
323 defined-- exit with an errorcode.
324*/
de073ce3 325void
819b8f00 326fail (void)
97e3214d
GM
327{
328 if (alternate_editor)
329 {
3cf8c6aa 330 int i = optind - 1;
0a125897 331 execvp (alternate_editor, main_argv + i);
23431241 332 return;
97e3214d
GM
333 }
334 else
335 {
65396510 336 exit (EXIT_FAILURE);
97e3214d
GM
337 }
338}
339
0b0d3e0b 340/* The process id of Emacs. */
6548cf00 341int emacs_pid;
9628b887 342
0b0d3e0b
KL
343/* File handles for communicating with Emacs. */
344FILE *out, *in;
345
da8e1115
KL
346/* A signal handler that passes the signal to the Emacs process.
347 Useful for SIGWINCH. */
348
9628b887 349SIGTYPE
428a555e 350pass_signal_to_emacs (int signalnum)
9628b887
KL
351{
352 int old_errno = errno;
353
9f729af5 354 if (emacs_pid)
428a555e 355 kill (emacs_pid, signalnum);
9f729af5 356
428a555e 357 signal (signalnum, pass_signal_to_emacs);
9f729af5
KL
358 errno = old_errno;
359}
360
0b0d3e0b
KL
361/* Signal handler for SIGCONT; notify the Emacs process that it can
362 now resume our tty frame. */
363
364SIGTYPE
365handle_sigcont (int signalnum)
366{
367 int old_errno = errno;
368
369 if (tcgetpgrp (1) == getpgrp ())
370 {
371 /* We are in the foreground. */
372 fprintf (out, "-resume \n");
373 fflush (out);
374 fsync (fileno (out));
375 }
376 else
377 {
378 /* We are in the background; cancel the continue. */
379 kill (getpid (), SIGSTOP);
380 }
c6c53c3e
KL
381
382 signal (signalnum, handle_sigcont);
0b0d3e0b
KL
383 errno = old_errno;
384}
385
386/* Signal handler for SIGTSTP; notify the Emacs process that we are
387 going to sleep. Normally the suspend is initiated by Emacs via
388 server-handle-suspend-tty, but if the server gets out of sync with
389 reality, we may get a SIGTSTP on C-z. Handling this signal and
390 notifying Emacs about it should get things under control again. */
391
392SIGTYPE
393handle_sigtstp (int signalnum)
394{
395 int old_errno = errno;
396 sigset_t set;
397
398 if (out)
399 {
400 fprintf (out, "-suspend \n");
401 fflush (out);
402 fsync (fileno (out));
403 }
404
405 /* Unblock this signal and call the default handler by temprarily
406 changing the handler and resignalling. */
407 sigprocmask (SIG_BLOCK, NULL, &set);
408 sigdelset (&set, signalnum);
409 signal (signalnum, SIG_DFL);
410 kill (getpid (), signalnum);
411 sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
412 signal (signalnum, handle_sigtstp);
413
414 errno = old_errno;
415}
416
da8e1115 417/* Set up signal handlers before opening a frame on the current tty. */
0b0d3e0b 418
4d553a13
KL
419void
420init_signals (void)
9628b887
KL
421{
422 /* Set up signal handlers. */
428a555e 423 signal (SIGWINCH, pass_signal_to_emacs);
4ca927b4
KL
424
425 /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of
426 deciding which terminal the signal came from. C-g is now a
427 normal input event on secondary terminals. */
428#if 0
428a555e
KL
429 signal (SIGINT, pass_signal_to_emacs);
430 signal (SIGQUIT, pass_signal_to_emacs);
4ca927b4 431#endif
0b0d3e0b
KL
432
433 signal (SIGCONT, handle_sigcont);
434 signal (SIGTSTP, handle_sigtstp);
435 signal (SIGTTOU, handle_sigtstp);
9628b887
KL
436}
437
97e3214d 438\f
30be2360 439#if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291 440
de073ce3 441int
46cec291
RS
442main (argc, argv)
443 int argc;
444 char **argv;
445{
446 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
447 argv[0]);
30be2360 448 fprintf (stderr, "on systems with Berkeley sockets.\n");
97e3214d 449
819b8f00 450 fail ();
46cec291
RS
451}
452
30be2360 453#else /* HAVE_SOCKETS */
46cec291
RS
454
455#include <sys/types.h>
456#include <sys/socket.h>
457#include <sys/un.h>
efb859b4 458#include <sys/stat.h>
46cec291
RS
459#include <errno.h>
460
92af894f 461extern char *strerror ();
46cec291
RS
462extern int errno;
463
9f637eea
GM
464/* Three possibilities:
465 2 - can't be `stat'ed (sets errno)
466 1 - isn't owned by us
467 0 - success: none of the above */
468
469static int
470socket_status (socket_name)
471 char *socket_name;
472{
473 struct stat statbfr;
474
475 if (stat (socket_name, &statbfr) == -1)
476 return 2;
477
478 if (statbfr.st_uid != geteuid ())
479 return 1;
480
481 return 0;
482}
483
4d553a13
KL
484/* Returns 1 if PREFIX is a prefix of STRING. */
485static int
486strprefix (char *prefix, char *string)
487{
488 int i;
489 if (! prefix)
490 return 1;
491
492 if (!string)
493 return 0;
0b0d3e0b 494
4d553a13
KL
495 for (i = 0; prefix[i]; i++)
496 if (!string[i] || string[i] != prefix[i])
497 return 0;
498 return 1;
499}
500
340ff9de 501int
46cec291
RS
502main (argc, argv)
503 int argc;
504 char **argv;
505{
3cf8c6aa 506 int s, i, needlf = 0;
46cec291 507 struct sockaddr_un server;
571512de 508 char *cwd, *str;
46cec291 509 char string[BUFSIZ];
8f9aaa0a 510
0a125897
KL
511 main_argc = argc;
512 main_argv = argv;
8f9aaa0a 513 progname = argv[0];
46cec291 514
8f9aaa0a 515 /* Process options. */
5212210c 516 decode_options (argc, argv);
46cec291 517
77134727 518 if ((argc - optind < 1) && !eval && !tty && !window_system)
20c396e8
JB
519 {
520 fprintf (stderr, "%s: file name or argument required\n", progname);
521 fprintf (stderr, "Try `%s --help' for more information\n", progname);
65396510 522 exit (EXIT_FAILURE);
20c396e8 523 }
46cec291 524
e69233c2 525 /*
46cec291
RS
526 * Open up an AF_UNIX socket in this person's home directory
527 */
528
529 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
530 {
531 fprintf (stderr, "%s: ", argv[0]);
532 perror ("socket");
819b8f00 533 fail ();
46cec291 534 }
e69233c2 535
46cec291 536 server.sun_family = AF_UNIX;
c5fee545 537
c5fee545 538 {
9f637eea 539 int sock_status = 0;
5c9659d3 540 int default_sock = !socket_name;
b80bf66e 541 int saved_errno = 0;
0b0d3e0b 542
d3a6748c 543 char *server_name = "server";
0b0d3e0b 544
d3a6748c
KL
545 if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
546 { /* socket_name is a file name component. */
547 server_name = socket_name;
548 socket_name = NULL;
549 default_sock = 1; /* Try both UIDs. */
550 }
efb859b4 551
d3a6748c 552 if (default_sock)
254107e4 553 {
d3a6748c
KL
554 socket_name = alloca (100 + strlen (server_name));
555 sprintf (socket_name, "/tmp/emacs%d/%s",
556 (int) geteuid (), server_name);
254107e4
RS
557 }
558
559 if (strlen (socket_name) < sizeof (server.sun_path))
560 strcpy (server.sun_path, socket_name);
561 else
819b8f00
KL
562 {
563 fprintf (stderr, "%s: socket-name %s too long",
564 argv[0], socket_name);
565 fail ();
566 }
efb859b4 567
9f637eea
GM
568 /* See if the socket exists, and if it's owned by us. */
569 sock_status = socket_status (server.sun_path);
152b6e83 570 saved_errno = errno;
5c9659d3 571 if (sock_status && default_sock)
efb859b4 572 {
9f637eea
GM
573 /* Failing that, see if LOGNAME or USER exist and differ from
574 our euid. If so, look for a socket based on the UID
575 associated with the name. This is reminiscent of the logic
576 that init_editfns uses to set the global Vuser_full_name. */
e69233c2 577
9f637eea 578 char *user_name = (char *) getenv ("LOGNAME");
293f9f2a 579
9f637eea
GM
580 if (!user_name)
581 user_name = (char *) getenv ("USER");
e69233c2 582
9f637eea
GM
583 if (user_name)
584 {
585 struct passwd *pw = getpwnam (user_name);
293f9f2a 586
9f637eea
GM
587 if (pw && (pw->pw_uid != geteuid ()))
588 {
589 /* We're running under su, apparently. */
0734b0d0
SM
590 socket_name = alloca (100 + strlen (server_name));
591 sprintf (socket_name, "/tmp/emacs%d/%s",
592 (int) pw->pw_uid, server_name);
5c9659d3
SM
593
594 if (strlen (socket_name) < sizeof (server.sun_path))
595 strcpy (server.sun_path, socket_name);
596 else
597 {
598 fprintf (stderr, "%s: socket-name %s too long",
599 argv[0], socket_name);
65396510 600 exit (EXIT_FAILURE);
5c9659d3
SM
601 }
602
9f637eea 603 sock_status = socket_status (server.sun_path);
b80bf66e 604 saved_errno = errno;
9f637eea 605 }
293f9f2a
RS
606 else
607 errno = saved_errno;
9f637eea 608 }
efb859b4 609 }
e69233c2 610
9f637eea
GM
611 switch (sock_status)
612 {
613 case 1:
614 /* There's a socket, but it isn't owned by us. This is OK if
615 we are root. */
616 if (0 != geteuid ())
617 {
618 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
819b8f00 619 fail ();
9f637eea
GM
620 }
621 break;
e69233c2 622
9f637eea
GM
623 case 2:
624 /* `stat' failed */
152b6e83 625 if (saved_errno == ENOENT)
9f637eea 626 fprintf (stderr,
9002956f 627 "%s: can't find socket; have you started the server?\n\
45adde32 628To start the server in Emacs, type \"M-x server-start\".\n",
9f637eea
GM
629 argv[0]);
630 else
9002956f 631 fprintf (stderr, "%s: can't stat %s: %s\n",
152b6e83 632 argv[0], server.sun_path, strerror (saved_errno));
819b8f00 633 fail ();
9f637eea
GM
634 break;
635 }
efb859b4 636 }
46cec291 637
4e23f2ba
JB
638 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
639 < 0)
46cec291
RS
640 {
641 fprintf (stderr, "%s: ", argv[0]);
642 perror ("connect");
819b8f00 643 fail ();
46cec291 644 }
23a7488d 645
9002956f 646 /* We use the stream OUT to send our commands to the server. */
46cec291
RS
647 if ((out = fdopen (s, "r+")) == NULL)
648 {
649 fprintf (stderr, "%s: ", argv[0]);
650 perror ("fdopen");
819b8f00 651 fail ();
46cec291
RS
652 }
653
9002956f 654 /* We use the stream IN to read the responses.
23a7488d
RS
655 We used to use just one stream for both output and input
656 on the socket, but reversing direction works nonportably:
657 on some systems, the output appears as the first input;
658 on other systems it does not. */
659 if ((in = fdopen (s, "r+")) == NULL)
660 {
661 fprintf (stderr, "%s: ", argv[0]);
662 perror ("fdopen");
819b8f00 663 fail ();
23a7488d
RS
664 }
665
38732dba 666#ifdef HAVE_GETCWD
ee6a193c 667 cwd = getcwd (string, sizeof string);
38732dba
RS
668#else
669 cwd = getwd (string);
ee6a193c 670#endif
46cec291
RS
671 if (cwd == 0)
672 {
673 /* getwd puts message in STRING if it fails. */
bb5618fe 674
38732dba 675#ifdef HAVE_GETCWD
bb5618fe 676 fprintf (stderr, "%s: %s (%s)\n", argv[0],
9002956f 677 "cannot get current working directory", strerror (errno));
38732dba 678#else
bb5618fe 679 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
bd252662 680#endif
819b8f00 681 fail ();
46cec291
RS
682 }
683
a9298135
KL
684 /* First of all, send our version number for verification. */
685 fprintf (out, "-version %s ", VERSION);
0b0d3e0b 686
9002956f
KL
687 /* Send over our environment. */
688 {
689 extern char **environ;
690 int i;
691 for (i = 0; environ[i]; i++)
692 {
693 char *name = xstrdup (environ[i]);
694 char *value = strchr (name, '=');
695 if (value && strlen (value) > 1)
696 {
697 *value++ = 0;
698 fprintf (out, "-env ");
699 quote_argument (name, out);
700 fprintf (out, " ");
701 quote_argument (value, out);
702 fprintf (out, " ");
703 fflush (out);
704 }
705 free (name);
706 }
707 }
708
6afdd335 709 retry:
5212210c
RS
710 if (nowait)
711 fprintf (out, "-nowait ");
292d74a3 712
30be2360 713 if (display)
87209357
EZ
714 {
715 fprintf (out, "-display ");
0b0d3e0b 716 quote_argument (display, out);
87209357
EZ
717 fprintf (out, " ");
718 }
30be2360 719
77134727 720 if (tty)
9628b887 721 {
4d553a13 722 char *tty_name = ttyname (fileno (stdin));
2fc0cf2a 723 char *type = getenv ("TERM");
0b0d3e0b 724
4d553a13 725 if (! tty_name)
2fc0cf2a
KL
726 {
727 fprintf (stderr, "%s: could not get terminal name\n", progname);
728 fail ();
729 }
730
731 if (! type)
732 {
733 fprintf (stderr, "%s: please set the TERM variable to your terminal type\n",
734 progname);
735 fail ();
736 }
737
738 if (! strcmp (type, "eterm"))
739 {
740 /* This causes nasty, MULTI_KBOARD-related input lockouts. */
741 fprintf (stderr, "%s: opening a frame in an Emacs term buffer"
742 " is not supported\n", progname);
743 fail ();
744 }
0b0d3e0b 745
4d553a13 746 init_signals ();
0b0d3e0b 747
819b8f00 748 fprintf (out, "-tty ");
0b0d3e0b 749 quote_argument (tty_name, out);
9628b887 750 fprintf (out, " ");
0b0d3e0b 751 quote_argument (type, out);
9628b887
KL
752 fprintf (out, " ");
753 }
77134727
KL
754
755 if (window_system)
756 fprintf (out, "-window-system ");
0b0d3e0b 757
87209357 758 if ((argc - optind > 0))
5212210c 759 {
87209357 760 for (i = optind; i < argc; i++)
46cec291 761 {
0b0d3e0b
KL
762 int relative = 0;
763
87209357 764 if (eval)
0b0d3e0b
KL
765 {
766 /* Don't prepend any cwd or anything like that. */
767 fprintf (out, "-eval ");
768 quote_argument (argv[i], out);
769 fprintf (out, " ");
770 continue;
771 }
772
773 if (*argv[i] == '+')
774 {
87209357
EZ
775 char *p = argv[i] + 1;
776 while (isdigit ((unsigned char) *p) || *p == ':') p++;
0b0d3e0b
KL
777 if (*p == 0)
778 {
779 fprintf (out, "-position ");
780 quote_argument (argv[i], out);
781 fprintf (out, " ");
782 continue;
783 }
784 else
785 relative = 1;
786 }
787 else if (*argv[i] != '/')
788 relative = 1;
789
790 fprintf (out, "-file ");
791 if (relative)
792 {
793 quote_argument (cwd, out);
794 fprintf (out, "/");
795 }
796 quote_argument (argv[i], out);
797 fprintf (out, " ");
798 }
46cec291 799 }
87209357
EZ
800 else
801 {
77134727 802 if (!tty && !window_system)
9628b887
KL
803 {
804 while ((str = fgets (string, BUFSIZ, stdin)))
805 {
0b0d3e0b
KL
806 if (eval)
807 fprintf (out, "-eval ");
808 else
809 fprintf (out, "-file ");
810 quote_argument (str, out);
9628b887
KL
811 }
812 fprintf (out, " ");
813 }
87209357 814 }
0b0d3e0b 815
46cec291
RS
816 fprintf (out, "\n");
817 fflush (out);
0b0d3e0b 818 fsync (fileno (out));
46cec291 819
fc2040c0
KL
820 /* Wait for an answer. */
821 if (!eval && !tty && !nowait)
30be2360
SM
822 {
823 printf ("Waiting for Emacs...");
824 needlf = 2;
825 }
46cec291 826 fflush (stdout);
0b0d3e0b 827 fsync (1);
46cec291 828
3cf8c6aa 829 /* Now, wait for an answer and print any messages. */
e69233c2 830 while ((str = fgets (string, BUFSIZ, in)))
3cf8c6aa 831 {
0b0d3e0b
KL
832 char *p = str + strlen (str) - 1;
833 while (p > str && *p == '\n')
834 *p-- = 0;
835
a9298135
KL
836 if (strprefix ("-good-version ", str))
837 {
6afdd335 838 /* -good-version: The versions match. */
a9298135 839 }
a9298135 840 else if (strprefix ("-emacs-pid ", str))
4d553a13 841 {
6afdd335 842 /* -emacs-pid PID: The process id of the Emacs process. */
77134727
KL
843 emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
844 }
6afdd335
KL
845 else if (strprefix ("-window-system-unsupported ", str))
846 {
847 /* -window-system-unsupported: Emacs was compiled without X
848 support. Try again on the terminal. */
849 window_system = 0;
850 nowait = 0;
851 tty = 1;
852 goto retry;
853 }
77134727
KL
854 else if (strprefix ("-print ", str))
855 {
6afdd335 856 /* -print STRING: Print STRING on the terminal. */
0b0d3e0b
KL
857 str = unquote_argument (str + strlen ("-print "));
858 if (needlf)
77134727 859 printf ("\n");
0b0d3e0b
KL
860 printf ("%s", str);
861 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
77134727
KL
862 }
863 else if (strprefix ("-error ", str))
864 {
6afdd335 865 /* -error DESCRIPTION: Signal an error on the terminal. */
0b0d3e0b
KL
866 str = unquote_argument (str + strlen ("-error "));
867 if (needlf)
868 printf ("\n");
869 printf ("*ERROR*: %s", str);
870 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
871 }
872 else if (strprefix ("-suspend ", str))
873 {
6afdd335 874 /* -suspend: Suspend this terminal, i.e., stop the process. */
0b0d3e0b 875 if (needlf)
77134727 876 printf ("\n");
0b0d3e0b
KL
877 needlf = 0;
878 kill (0, SIGSTOP);
4d553a13
KL
879 }
880 else
881 {
6afdd335 882 /* Unknown command. */
0b0d3e0b 883 if (needlf)
4d553a13 884 printf ("\n");
77134727 885 printf ("*ERROR*: Unknown message: %s", str);
4d553a13
KL
886 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
887 }
3cf8c6aa
SM
888 }
889
890 if (needlf)
891 printf ("\n");
892 fflush (stdout);
0b0d3e0b 893 fsync (1);
23a7488d 894
65396510 895 return EXIT_SUCCESS;
46cec291
RS
896}
897
30be2360 898#endif /* HAVE_SOCKETS */
27711600
RM
899\f
900#ifndef HAVE_STRERROR
901char *
902strerror (errnum)
903 int errnum;
904{
905 extern char *sys_errlist[];
906 extern int sys_nerr;
907
908 if (errnum >= 0 && errnum < sys_nerr)
909 return sys_errlist[errnum];
910 return (char *) "Unknown error";
911}
912
913#endif /* ! HAVE_STRERROR */
ab5796a9
MB
914
915/* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
916 (do not change this comment) */
65396510
TTN
917
918/* emacsclient.c ends here */