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