(gnus-setup-message): Setup reaper for MML buffers.
[emacs.git] / lib-src / emacsclient.c
blob988bfc4fd4d8fbc682554c8a5fea6aa0ef6cbbbc
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
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.
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
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 #define NO_SHORTNAMES
24 #include <../src/config.h>
25 #undef signal
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <getopt.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
34 #ifdef VMS
35 # include "vms-pwd.h"
36 #else
37 # include <pwd.h>
38 #endif /* not VMS */
40 char *getenv (), *getwd ();
41 char *getcwd ();
43 /* This is defined with -D from the compilation command,
44 which extracts it from ../lisp/version.el. */
46 #ifndef VERSION
47 #define VERSION "unspecified"
48 #endif
50 /* Name used to invoke this program. */
51 char *progname;
53 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
54 int nowait = 0;
56 void print_help_and_exit ();
58 struct option longopts[] =
60 { "no-wait", no_argument, NULL, 'n' },
61 { "help", no_argument, NULL, 'H' },
62 { "version", no_argument, NULL, 'V' },
63 { "alternate-editor",required_argument, NULL, 'a' },
64 { 0 }
68 const char * alternate_editor = NULL;
70 /* Decode the options from argv and argc.
71 The global variable `optind' will say how many arguments we used up. */
73 void
74 decode_options (argc, argv)
75 int argc;
76 char **argv;
78 while (1)
80 int opt = getopt_long (argc, argv,
81 "VHna:", longopts, 0);
83 if (opt == EOF)
84 break;
86 alternate_editor = getenv ("ALTERNATE_EDITOR");
88 switch (opt)
90 case 0:
91 /* If getopt returns 0, then it has already processed a
92 long-named option. We should do nothing. */
93 break;
95 case 'a':
96 alternate_editor = optarg;
97 break;
99 case 'n':
100 nowait = 1;
101 break;
103 case 'V':
104 fprintf (stderr, "emacsclient %s\n", VERSION);
105 exit (1);
106 break;
108 case 'H':
109 default:
110 print_help_and_exit ();
115 void
116 print_help_and_exit ()
118 fprintf (stderr,
119 "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINE[:COLUMN]] FILENAME\n",
120 progname);
121 fprintf (stderr,
122 "Or %s --version\n",
123 progname);
124 fprintf (stderr,
125 "Report bugs to bug-gnu-emacs@gnu.org.\n");
126 exit (1);
129 /* Return a copy of NAME, inserting a &
130 before each &, each space, and any initial -.
131 Change spaces to underscores, too, so that the
132 return value never contains a space. */
134 char *
135 quote_file_name (name)
136 char *name;
138 char *copy = (char *) malloc (strlen (name) * 2 + 1);
139 char *p, *q;
141 p = name;
142 q = copy;
143 while (*p)
145 if (*p == ' ')
147 *q++ = '&';
148 *q++ = '_';
149 p++;
151 else
153 if (*p == '&' || (*p == '-' && p == name))
154 *q++ = '&';
155 *q++ = *p++;
158 *q++ = 0;
161 return copy;
164 /* Like malloc but get fatal error if memory is exhausted. */
166 long *
167 xmalloc (size)
168 unsigned int size;
170 long *result = (long *) malloc (size);
171 if (result == NULL)
173 perror ("malloc");
174 exit (1);
176 return result;
180 Try to run a different command, or --if no alternate editor is
181 defined-- exit with an errorcode.
183 void
184 fail (argc, argv)
185 int argc;
186 char **argv;
188 if (alternate_editor)
190 int i = optind -1 ;
191 execvp (alternate_editor, argv + i);
192 return;
194 else
196 exit (1);
203 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
206 main (argc, argv)
207 int argc;
208 char **argv;
210 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
211 argv[0]);
212 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
214 fail (argc, argv);
217 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
219 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
220 /* BSD code is very different from SYSV IPC code */
222 #include <sys/types.h>
223 #include <sys/socket.h>
224 #include <sys/un.h>
225 #include <sys/stat.h>
226 #include <errno.h>
228 extern char *strerror ();
229 extern int errno;
231 /* Three possibilities:
232 2 - can't be `stat'ed (sets errno)
233 1 - isn't owned by us
234 0 - success: none of the above */
236 static int
237 socket_status (socket_name)
238 char *socket_name;
240 struct stat statbfr;
242 if (stat (socket_name, &statbfr) == -1)
243 return 2;
245 if (statbfr.st_uid != geteuid ())
246 return 1;
248 return 0;
252 main (argc, argv)
253 int argc;
254 char **argv;
256 char *system_name;
257 int system_name_length;
258 int s, i;
259 FILE *out, *in;
260 struct sockaddr_un server;
261 #ifdef SERVER_HOME_DIR
262 char *homedir;
263 #endif
264 char *cwd, *str;
265 char string[BUFSIZ];
267 progname = argv[0];
269 /* Process options. */
270 decode_options (argc, argv);
272 if (argc - optind < 1)
273 print_help_and_exit ();
276 * Open up an AF_UNIX socket in this person's home directory
279 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
281 fprintf (stderr, "%s: ", argv[0]);
282 perror ("socket");
283 fail (argc, argv);
286 server.sun_family = AF_UNIX;
289 system_name_length = 32;
291 while (1)
293 system_name = (char *) xmalloc (system_name_length + 1);
295 /* system_name must be null-terminated string. */
296 system_name[system_name_length] = '\0';
298 if (gethostname (system_name, system_name_length) == 0)
299 break;
301 free (system_name);
302 system_name_length *= 2;
306 #ifndef SERVER_HOME_DIR
308 int sock_status = 0;
310 sprintf (server.sun_path, "/tmp/esrv%d-%s", (int) geteuid (), system_name);
312 /* See if the socket exists, and if it's owned by us. */
313 sock_status = socket_status (server.sun_path);
314 if (sock_status)
316 /* Failing that, see if LOGNAME or USER exist and differ from
317 our euid. If so, look for a socket based on the UID
318 associated with the name. This is reminiscent of the logic
319 that init_editfns uses to set the global Vuser_full_name. */
321 char *user_name = (char *) getenv ("LOGNAME");
322 if (!user_name)
323 user_name = (char *) getenv ("USER");
325 if (user_name)
327 struct passwd *pw = getpwnam (user_name);
328 if (pw && (pw->pw_uid != geteuid ()))
330 /* We're running under su, apparently. */
331 sprintf (server.sun_path, "/tmp/esrv%d-%s",
332 (int) pw->pw_uid, system_name);
333 sock_status = socket_status (server.sun_path);
338 switch (sock_status)
340 case 1:
341 /* There's a socket, but it isn't owned by us. This is OK if
342 we are root. */
343 if (0 != geteuid ())
345 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
346 fail (argc, argv);
348 break;
350 case 2:
351 /* `stat' failed */
352 if (errno == ENOENT)
353 fprintf (stderr,
354 "%s: can't find socket; have you started the server?\n",
355 argv[0]);
356 else
357 fprintf (stderr, "%s: can't stat %s: %s\n",
358 argv[0], server.sun_path, strerror (errno));
359 fail (argc, argv);
360 break;
363 #else
364 if ((homedir = getenv ("HOME")) == NULL)
366 fprintf (stderr, "%s: No home directory\n", argv[0]);
367 fail (argc, argv);
369 strcpy (server.sun_path, homedir);
370 strcat (server.sun_path, "/.emacs-server-");
371 strcat (server.sun_path, system_name);
372 #endif
374 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
375 < 0)
377 fprintf (stderr, "%s: ", argv[0]);
378 perror ("connect");
379 fail (argc, argv);
382 /* We use the stream OUT to send our command to the server. */
383 if ((out = fdopen (s, "r+")) == NULL)
385 fprintf (stderr, "%s: ", argv[0]);
386 perror ("fdopen");
387 fail (argc, argv);
390 /* We use the stream IN to read the response.
391 We used to use just one stream for both output and input
392 on the socket, but reversing direction works nonportably:
393 on some systems, the output appears as the first input;
394 on other systems it does not. */
395 if ((in = fdopen (s, "r+")) == NULL)
397 fprintf (stderr, "%s: ", argv[0]);
398 perror ("fdopen");
399 fail (argc, argv);
402 #ifdef BSD_SYSTEM
403 cwd = getwd (string);
404 #else
405 cwd = getcwd (string, sizeof string);
406 #endif
407 if (cwd == 0)
409 /* getwd puts message in STRING if it fails. */
410 fprintf (stderr, "%s: %s (%s)\n", argv[0],
411 #ifdef BSD_SYSTEM
412 string,
413 #else
414 "Cannot get current working directory",
415 #endif
416 strerror (errno));
417 fail (argc, argv);
420 if (nowait)
421 fprintf (out, "-nowait ");
423 for (i = optind; i < argc; i++)
425 if (*argv[i] == '+')
427 char *p = argv[i] + 1;
428 while (isdigit ((unsigned char) *p) || *p == ':') p++;
429 if (*p != 0)
430 fprintf (out, "%s/", quote_file_name (cwd));
432 else if (*argv[i] != '/')
433 fprintf (out, "%s/", quote_file_name (cwd));
435 fprintf (out, "%s ", quote_file_name (argv[i]));
437 fprintf (out, "\n");
438 fflush (out);
440 /* Maybe wait for an answer. */
441 if (nowait)
442 return 0;
444 printf ("Waiting for Emacs...");
445 fflush (stdout);
447 /* Now, wait for an answer and print any messages. On some systems,
448 the first line we read will actually be the output we just sent.
449 We can't predict whether that will happen, so if it does, we
450 detect it by recognizing `Client: ' at the beginning. */
452 while (str = fgets (string, BUFSIZ, in))
453 printf ("%s", str);
455 return 0;
458 #else /* This is the SYSV IPC section */
460 #include <sys/types.h>
461 #include <sys/ipc.h>
462 #include <sys/msg.h>
463 #include <sys/utsname.h>
464 #include <stdio.h>
465 #include <errno.h>
466 extern int errno;
468 char *getwd (), *getcwd (), *getenv ();
469 struct utsname system_name;
471 main (argc, argv)
472 int argc;
473 char **argv;
475 int s;
476 key_t key;
477 /* Size of text allocated in MSGP. */
478 int size_allocated = BUFSIZ;
479 /* Amount of text used in MSGP. */
480 int used;
481 struct msgbuf *msgp
482 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
483 struct msqid_ds * msg_st;
484 char *homedir, buf[BUFSIZ];
485 char gwdirb[BUFSIZ];
486 char *cwd;
487 char *temp;
489 progname = argv[0];
491 /* Process options. */
492 decode_options (argc, argv);
494 if (argc - optind < 1)
495 print_help_and_exit ();
498 * Create a message queue using ~/.emacs-server as the path for ftok
500 if ((homedir = getenv ("HOME")) == NULL)
502 fprintf (stderr, "%s: No home directory\n", argv[0]);
503 exit (1);
505 strcpy (buf, homedir);
506 #ifndef HAVE_LONG_FILE_NAMES
507 /* If file names are short, we can't fit the host name. */
508 strcat (buf, "/.emacs-server");
509 #else
510 strcat (buf, "/.emacs-server-");
511 uname (&system_name);
512 strcat (buf, system_name.nodename);
513 #endif
514 creat (buf, 0600);
515 key = ftok (buf, 1); /* unlikely to be anyone else using it */
516 s = msgget (key, 0600 | IPC_CREAT);
517 if (s == -1)
519 fprintf (stderr, "%s: ", argv[0]);
520 perror ("msgget");
521 exit (1);
524 /* Determine working dir, so we can prefix it to all the arguments. */
525 #ifdef BSD_SYSTEM
526 temp = getwd (gwdirb);
527 #else
528 temp = getcwd (gwdirb, sizeof gwdirb);
529 #endif
531 cwd = gwdirb;
532 if (temp != 0)
534 /* On some systems, cwd can look like `@machine/...';
535 ignore everything before the first slash in such a case. */
536 while (*cwd && *cwd != '/')
537 cwd++;
538 strcat (cwd, "/");
540 else
542 #ifdef BSD_SYSTEM
543 fprintf (stderr, "%s: %s\n", argv[0], cwd);
544 #else
545 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
546 argv[0], strerror (errno));
547 #endif
548 fail (argc, argv);
551 msgp->mtext[0] = 0;
552 used = 0;
554 if (nowait)
556 strcat (msgp->mtext, "-nowait ");
557 used += 8;
560 argc -= optind;
561 argv += optind;
563 while (argc)
565 int need_cwd = 0;
566 char *modified_arg = argv[0];
568 if (*modified_arg == '+')
570 char *p = modified_arg + 1;
571 while (isdigit (*p) || *p == ':')
572 p++;
573 if (*p != 0)
574 need_cwd = 1;
576 else if (*modified_arg != '/')
577 need_cwd = 1;
579 modified_arg = quote_file_name (modified_arg);
581 if (need_cwd)
582 /* Overestimate in case we have to quote something in CWD. */
583 used += 2 * strlen (cwd);
584 used += strlen (modified_arg) + 1;
585 while (used + 2 > size_allocated)
587 size_allocated *= 2;
588 msgp = (struct msgbuf *) realloc (msgp,
589 (sizeof (struct msgbuf)
590 + size_allocated));
593 if (need_cwd)
594 strcat (msgp->mtext, quote_file_name (cwd));
596 strcat (msgp->mtext, modified_arg);
597 strcat (msgp->mtext, " ");
598 argv++; argc--;
600 strcat (msgp->mtext, "\n");
601 #ifdef HPUX /* HPUX has a bug. */
602 if (strlen (msgp->mtext) >= 512)
604 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
605 fail (argc, argv);
607 #endif
608 msgp->mtype = 1;
609 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
611 fprintf (stderr, "%s: ", progname);
612 perror ("msgsnd");
613 fail (argc, argv);
616 /* Maybe wait for an answer. */
617 if (nowait)
618 return 0;
620 printf ("Waiting for Emacs...");
621 fflush (stdout);
623 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
624 strcpy (buf, msgp->mtext);
626 printf ("\n");
627 if (*buf)
628 printf ("%s\n", buf);
629 exit (0);
632 #endif /* HAVE_SYSVIPC */
634 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
636 #ifndef HAVE_STRERROR
637 char *
638 strerror (errnum)
639 int errnum;
641 extern char *sys_errlist[];
642 extern int sys_nerr;
644 if (errnum >= 0 && errnum < sys_nerr)
645 return sys_errlist[errnum];
646 return (char *) "Unknown error";
649 #endif /* ! HAVE_STRERROR */