(defface menu): Doc fix.
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
efb859b4 1/* Client process that communicates with GNU Emacs acting as server.
de073ce3
GM
2 Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001
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
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
46cec291
RS
21
22
23#define NO_SHORTNAMES
18160b98 24#include <../src/config.h>
4e23f2ba 25#undef signal
46cec291 26
8f9aaa0a
RS
27#include <stdio.h>
28#include <getopt.h>
79f13bba
DL
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
8f9aaa0a 32
9f637eea
GM
33#ifdef VMS
34# include "vms-pwd.h"
35#else
36# include <pwd.h>
37#endif /* not VMS */
38
8f9aaa0a
RS
39char *getenv (), *getwd ();
40char *getcwd ();
8f9aaa0a
RS
41
42/* This is defined with -D from the compilation command,
43 which extracts it from ../lisp/version.el. */
44
45#ifndef VERSION
46#define VERSION "unspecified"
47#endif
48\f
49/* Name used to invoke this program. */
50char *progname;
51
749ae770 52/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
53int nowait = 0;
54
7f3bff3e
AS
55void print_help_and_exit ();
56
8f9aaa0a
RS
57struct option longopts[] =
58{
749ae770 59 { "no-wait", no_argument, NULL, 'n' },
8f9aaa0a
RS
60 { "help", no_argument, NULL, 'H' },
61 { "version", no_argument, NULL, 'V' },
97e3214d 62 { "alternate-editor",required_argument, NULL, 'a' },
8f9aaa0a
RS
63 { 0 }
64};
65
97e3214d
GM
66
67const char * alternate_editor = NULL;
68
8f9aaa0a 69/* Decode the options from argv and argc.
5212210c 70 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 71
5212210c 72void
8f9aaa0a
RS
73decode_options (argc, argv)
74 int argc;
75 char **argv;
76{
77 while (1)
78 {
79 int opt = getopt_long (argc, argv,
97e3214d 80 "VHna:", longopts, 0);
8f9aaa0a
RS
81
82 if (opt == EOF)
83 break;
84
97e3214d
GM
85 alternate_editor = getenv ("ALTERNATE_EDITOR");
86
8f9aaa0a
RS
87 switch (opt)
88 {
89 case 0:
90 /* If getopt returns 0, then it has already processed a
91 long-named option. We should do nothing. */
92 break;
97e3214d
GM
93
94 case 'a':
95 alternate_editor = optarg;
96 break;
97
8f9aaa0a
RS
98 case 'n':
99 nowait = 1;
100 break;
101
102 case 'V':
b4e94f42 103 fprintf (stderr, "emacsclient %s\n", VERSION);
8f9aaa0a
RS
104 exit (1);
105 break;
46cec291 106
8f9aaa0a
RS
107 case 'H':
108 default:
109 print_help_and_exit ();
110 }
111 }
8f9aaa0a
RS
112}
113
7f3bff3e 114void
8f9aaa0a
RS
115print_help_and_exit ()
116{
117 fprintf (stderr,
97e3214d 118 "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
8f9aaa0a 119 progname);
4852ed0e
RS
120 fprintf (stderr,
121 "Or %s --version\n",
122 progname);
8f9aaa0a 123 fprintf (stderr,
b4e94f42 124 "Report bugs to bug-gnu-emacs@gnu.org.\n");
8f9aaa0a
RS
125 exit (1);
126}
5212210c 127
f1db6a73
RS
128/* Return a copy of NAME, inserting a &
129 before each &, each space, and any initial -.
5212210c
RS
130 Change spaces to underscores, too, so that the
131 return value never contains a space. */
132
133char *
134quote_file_name (name)
135 char *name;
136{
137 char *copy = (char *) malloc (strlen (name) * 2 + 1);
138 char *p, *q;
139
140 p = name;
141 q = copy;
142 while (*p)
143 {
144 if (*p == ' ')
145 {
f1db6a73 146 *q++ = '&';
5212210c
RS
147 *q++ = '_';
148 p++;
149 }
150 else
151 {
f1db6a73
RS
152 if (*p == '&' || (*p == '-' && p == name))
153 *q++ = '&';
5212210c
RS
154 *q++ = *p++;
155 }
156 }
f1db6a73 157 *q++ = 0;
5212210c 158
97e3214d 159
5212210c
RS
160 return copy;
161}
0c76956f 162
0c76956f
RS
163/* Like malloc but get fatal error if memory is exhausted. */
164
5497dfdb 165long *
0c76956f
RS
166xmalloc (size)
167 unsigned int size;
168{
5f32a712 169 long *result = (long *) malloc (size);
0c76956f
RS
170 if (result == NULL)
171 {
172 perror ("malloc");
173 exit (1);
174 }
175 return result;
176}
8f9aaa0a 177\f
97e3214d
GM
178/*
179 Try to run a different command, or --if no alternate editor is
180 defined-- exit with an errorcode.
181*/
de073ce3 182void
97e3214d
GM
183fail (argc, argv)
184 int argc;
185 char **argv;
186{
187 if (alternate_editor)
188 {
189 int i = optind -1 ;
190 execvp (alternate_editor, argv + i);
191 }
192 else
193 {
194 exit (1);
195 }
196}
197
198
199
200\f
b135a7cf 201#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291 202
de073ce3 203int
46cec291
RS
204main (argc, argv)
205 int argc;
206 char **argv;
207{
208 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
209 argv[0]);
210 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
97e3214d
GM
211
212 fail (argc, argv);
46cec291
RS
213}
214
215#else /* HAVE_SOCKETS or HAVE_SYSVIPC */
216
1e523e3d 217#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
218/* BSD code is very different from SYSV IPC code */
219
220#include <sys/types.h>
221#include <sys/socket.h>
222#include <sys/un.h>
efb859b4 223#include <sys/stat.h>
46cec291
RS
224#include <errno.h>
225
92af894f 226extern char *strerror ();
46cec291
RS
227extern int errno;
228
9f637eea
GM
229/* Three possibilities:
230 2 - can't be `stat'ed (sets errno)
231 1 - isn't owned by us
232 0 - success: none of the above */
233
234static int
235socket_status (socket_name)
236 char *socket_name;
237{
238 struct stat statbfr;
239
240 if (stat (socket_name, &statbfr) == -1)
241 return 2;
242
243 if (statbfr.st_uid != geteuid ())
244 return 1;
245
246 return 0;
247}
248
340ff9de 249int
46cec291
RS
250main (argc, argv)
251 int argc;
252 char **argv;
253{
a2b3f2b5
RS
254 char *system_name;
255 int system_name_length;
46cec291 256 int s, i;
23a7488d 257 FILE *out, *in;
46cec291 258 struct sockaddr_un server;
571512de
EZ
259#ifdef SERVER_HOME_DIR
260 char *homedir;
261#endif
262 char *cwd, *str;
46cec291 263 char string[BUFSIZ];
8f9aaa0a
RS
264
265 progname = argv[0];
46cec291 266
8f9aaa0a 267 /* Process options. */
5212210c 268 decode_options (argc, argv);
46cec291 269
5212210c 270 if (argc - optind < 1)
8f9aaa0a 271 print_help_and_exit ();
46cec291
RS
272
273 /*
274 * Open up an AF_UNIX socket in this person's home directory
275 */
276
277 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
278 {
279 fprintf (stderr, "%s: ", argv[0]);
280 perror ("socket");
97e3214d 281 fail (argc, argv);
46cec291 282 }
97e3214d 283
46cec291 284 server.sun_family = AF_UNIX;
c5fee545 285
efb859b4 286 {
a2b3f2b5
RS
287 system_name_length = 32;
288
289 while (1)
290 {
291 system_name = (char *) xmalloc (system_name_length + 1);
292
293 /* system_name must be null-terminated string. */
294 system_name[system_name_length] = '\0';
295
296 if (gethostname (system_name, system_name_length) == 0)
297 break;
298
299 free (system_name);
300 system_name_length *= 2;
301 }
c5fee545
KH
302 }
303
304#ifndef SERVER_HOME_DIR
305 {
9f637eea 306 int sock_status = 0;
efb859b4 307
efb859b4
JB
308 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
309
9f637eea
GM
310 /* See if the socket exists, and if it's owned by us. */
311 sock_status = socket_status (server.sun_path);
312 if (sock_status)
efb859b4 313 {
9f637eea
GM
314 /* Failing that, see if LOGNAME or USER exist and differ from
315 our euid. If so, look for a socket based on the UID
316 associated with the name. This is reminiscent of the logic
317 that init_editfns uses to set the global Vuser_full_name. */
318
319 char *user_name = (char *) getenv ("LOGNAME");
320 if (!user_name)
321 user_name = (char *) getenv ("USER");
322
323 if (user_name)
324 {
325 struct passwd *pw = getpwnam (user_name);
326 if (pw && (pw->pw_uid != geteuid ()))
327 {
328 /* We're running under su, apparently. */
329 sprintf (server.sun_path, "/tmp/esrv%d-%s",
330 pw->pw_uid, system_name);
331 sock_status = socket_status (server.sun_path);
332 }
333 }
efb859b4 334 }
9f637eea
GM
335
336 switch (sock_status)
337 {
338 case 1:
339 /* There's a socket, but it isn't owned by us. This is OK if
340 we are root. */
341 if (0 != geteuid ())
342 {
343 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
344 fail (argc, argv);
345 }
346 break;
347
348 case 2:
349 /* `stat' failed */
350 if (errno == ENOENT)
351 fprintf (stderr,
352 "%s: can't find socket; have you started the server?\n",
353 argv[0]);
354 else
355 fprintf (stderr, "%s: can't stat %s: %s\n",
356 argv[0], server.sun_path, strerror (errno));
357 fail (argc, argv);
358 break;
359 }
efb859b4 360 }
46cec291
RS
361#else
362 if ((homedir = getenv ("HOME")) == NULL)
363 {
364 fprintf (stderr, "%s: No home directory\n", argv[0]);
97e3214d 365 fail (argc, argv);
46cec291
RS
366 }
367 strcpy (server.sun_path, homedir);
b135a7cf 368 strcat (server.sun_path, "/.emacs-server-");
b135a7cf 369 strcat (server.sun_path, system_name);
46cec291
RS
370#endif
371
4e23f2ba
JB
372 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
373 < 0)
46cec291
RS
374 {
375 fprintf (stderr, "%s: ", argv[0]);
376 perror ("connect");
97e3214d 377 fail (argc, argv);
46cec291 378 }
23a7488d
RS
379
380 /* We use the stream OUT to send our command to the server. */
46cec291
RS
381 if ((out = fdopen (s, "r+")) == NULL)
382 {
383 fprintf (stderr, "%s: ", argv[0]);
384 perror ("fdopen");
97e3214d 385 fail (argc, argv);
46cec291
RS
386 }
387
23a7488d
RS
388 /* We use the stream IN to read the response.
389 We used to use just one stream for both output and input
390 on the socket, but reversing direction works nonportably:
391 on some systems, the output appears as the first input;
392 on other systems it does not. */
393 if ((in = fdopen (s, "r+")) == NULL)
394 {
395 fprintf (stderr, "%s: ", argv[0]);
396 perror ("fdopen");
97e3214d 397 fail (argc, argv);
23a7488d
RS
398 }
399
e397a017 400#ifdef BSD_SYSTEM
46cec291 401 cwd = getwd (string);
ee6a193c
RS
402#else
403 cwd = getcwd (string, sizeof string);
404#endif
46cec291
RS
405 if (cwd == 0)
406 {
407 /* getwd puts message in STRING if it fails. */
bd252662
RS
408 fprintf (stderr, "%s: %s (%s)\n", argv[0],
409#ifdef BSD_SYSTEM
410 string,
411#else
412 "Cannot get current working directory",
413#endif
414 strerror (errno));
97e3214d 415 fail (argc, argv);
46cec291
RS
416 }
417
5212210c
RS
418 if (nowait)
419 fprintf (out, "-nowait ");
292d74a3 420
5212210c
RS
421 for (i = optind; i < argc; i++)
422 {
46cec291
RS
423 if (*argv[i] == '+')
424 {
425 char *p = argv[i] + 1;
426 while (*p >= '0' && *p <= '9') p++;
427 if (*p != 0)
0343a017 428 fprintf (out, "%s/", quote_file_name (cwd));
46cec291
RS
429 }
430 else if (*argv[i] != '/')
0343a017 431 fprintf (out, "%s/", quote_file_name (cwd));
5212210c
RS
432
433 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
434 }
435 fprintf (out, "\n");
436 fflush (out);
437
292d74a3
RS
438 /* Maybe wait for an answer. */
439 if (nowait)
440 return 0;
441
46cec291
RS
442 printf ("Waiting for Emacs...");
443 fflush (stdout);
444
23a7488d
RS
445 /* Now, wait for an answer and print any messages. On some systems,
446 the first line we read will actually be the output we just sent.
447 We can't predict whether that will happen, so if it does, we
448 detect it by recognizing `Client: ' at the beginning. */
46cec291 449
23a7488d 450 while (str = fgets (string, BUFSIZ, in))
46cec291 451 printf ("%s", str);
23a7488d 452
340ff9de 453 return 0;
46cec291
RS
454}
455
456#else /* This is the SYSV IPC section */
457
458#include <sys/types.h>
459#include <sys/ipc.h>
460#include <sys/msg.h>
b135a7cf 461#include <sys/utsname.h>
46cec291 462#include <stdio.h>
bd252662
RS
463#include <errno.h>
464extern int errno;
46cec291 465
1518a9eb 466char *getwd (), *getcwd (), *getenv ();
b135a7cf 467struct utsname system_name;
1518a9eb 468
46cec291
RS
469main (argc, argv)
470 int argc;
471 char **argv;
472{
473 int s;
474 key_t key;
1518a9eb
RS
475 /* Size of text allocated in MSGP. */
476 int size_allocated = BUFSIZ;
477 /* Amount of text used in MSGP. */
478 int used;
479 struct msgbuf *msgp
480 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
46cec291
RS
481 struct msqid_ds * msg_st;
482 char *homedir, buf[BUFSIZ];
483 char gwdirb[BUFSIZ];
484 char *cwd;
485 char *temp;
8f9aaa0a
RS
486
487 progname = argv[0];
488
489 /* Process options. */
5212210c 490 decode_options (argc, argv);
46cec291 491
5212210c 492 if (argc - optind < 1)
8f9aaa0a 493 print_help_and_exit ();
46cec291
RS
494
495 /*
b135a7cf 496 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
497 */
498 if ((homedir = getenv ("HOME")) == NULL)
499 {
500 fprintf (stderr, "%s: No home directory\n", argv[0]);
501 exit (1);
502 }
503 strcpy (buf, homedir);
b135a7cf
RS
504#ifndef HAVE_LONG_FILE_NAMES
505 /* If file names are short, we can't fit the host name. */
506 strcat (buf, "/.emacs-server");
507#else
508 strcat (buf, "/.emacs-server-");
509 uname (&system_name);
510 strcat (buf, system_name.nodename);
511#endif
46cec291
RS
512 creat (buf, 0600);
513 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 514 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
515 if (s == -1)
516 {
517 fprintf (stderr, "%s: ", argv[0]);
518 perror ("msgget");
519 exit (1);
520 }
521
522 /* Determine working dir, so we can prefix it to all the arguments. */
e397a017 523#ifdef BSD_SYSTEM
46cec291
RS
524 temp = getwd (gwdirb);
525#else
526 temp = getcwd (gwdirb, sizeof gwdirb);
527#endif
528
529 cwd = gwdirb;
530 if (temp != 0)
531 {
532 /* On some systems, cwd can look like `@machine/...';
533 ignore everything before the first slash in such a case. */
534 while (*cwd && *cwd != '/')
535 cwd++;
536 strcat (cwd, "/");
537 }
538 else
539 {
bd252662 540#ifdef BSD_SYSTEM
26396b1b 541 fprintf (stderr, "%s: %s\n", argv[0], cwd);
bd252662
RS
542#else
543 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
544 argv[0], strerror (errno));
545#endif
97e3214d 546 fail (argc, argv);
46cec291
RS
547 }
548
549 msgp->mtext[0] = 0;
1518a9eb 550 used = 0;
5212210c
RS
551
552 if (nowait)
553 {
554 strcat (msgp->mtext, "-nowait ");
555 used += 8;
556 }
557
558 argc -= optind;
559 argv += optind;
560
46cec291
RS
561 while (argc)
562 {
1518a9eb 563 int need_cwd = 0;
cd33a5a0 564 char *modified_arg = argv[0];
292d74a3 565
5212210c 566 if (*modified_arg == '+')
46cec291 567 {
cd33a5a0 568 char *p = modified_arg + 1;
46cec291
RS
569 while (*p >= '0' && *p <= '9') p++;
570 if (*p != 0)
1518a9eb 571 need_cwd = 1;
46cec291 572 }
cd33a5a0 573 else if (*modified_arg != '/')
1518a9eb
RS
574 need_cwd = 1;
575
5212210c
RS
576 modified_arg = quote_file_name (modified_arg);
577
1518a9eb 578 if (need_cwd)
0343a017
KH
579 /* Overestimate in case we have to quote something in CWD. */
580 used += 2 * strlen (cwd);
cd33a5a0 581 used += strlen (modified_arg) + 1;
1518a9eb
RS
582 while (used + 2 > size_allocated)
583 {
584 size_allocated *= 2;
585 msgp = (struct msgbuf *) realloc (msgp,
586 (sizeof (struct msgbuf)
587 + size_allocated));
588 }
589
590 if (need_cwd)
0343a017 591 strcat (msgp->mtext, quote_file_name (cwd));
46cec291 592
cd33a5a0 593 strcat (msgp->mtext, modified_arg);
46cec291
RS
594 strcat (msgp->mtext, " ");
595 argv++; argc--;
596 }
597 strcat (msgp->mtext, "\n");
1518a9eb
RS
598#ifdef HPUX /* HPUX has a bug. */
599 if (strlen (msgp->mtext) >= 512)
600 {
18a2fa91 601 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
97e3214d 602 fail (argc, argv);
1518a9eb
RS
603 }
604#endif
46cec291
RS
605 msgp->mtype = 1;
606 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
607 {
defb80d7 608 fprintf (stderr, "%s: ", progname);
46cec291 609 perror ("msgsnd");
97e3214d 610 fail (argc, argv);
46cec291 611 }
292d74a3
RS
612
613 /* Maybe wait for an answer. */
614 if (nowait)
615 return 0;
616
46cec291
RS
617 printf ("Waiting for Emacs...");
618 fflush (stdout);
619
620 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
621 strcpy (buf, msgp->mtext);
622
dc3c30fe
KH
623 printf ("\n");
624 if (*buf)
625 printf ("%s\n", buf);
46cec291
RS
626 exit (0);
627}
628
629#endif /* HAVE_SYSVIPC */
630
631#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
632\f
633#ifndef HAVE_STRERROR
634char *
635strerror (errnum)
636 int errnum;
637{
638 extern char *sys_errlist[];
639 extern int sys_nerr;
640
641 if (errnum >= 0 && errnum < sys_nerr)
642 return sys_errlist[errnum];
643 return (char *) "Unknown error";
644}
645
646#endif /* ! HAVE_STRERROR */