(latin1-display-reset):
[emacs.git] / lib-src / emacsclient.c
blob03fe66598c8469a1852dc3bb64abcd383b5de59e
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #define NO_SHORTNAMES
23 #include <../src/config.h>
24 #undef signal
26 #include <stdio.h>
27 #include <getopt.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
32 #ifdef VMS
33 # include "vms-pwd.h"
34 #else
35 # include <pwd.h>
36 #endif /* not VMS */
38 char *getenv (), *getwd ();
39 char *getcwd ();
41 /* This is defined with -D from the compilation command,
42 which extracts it from ../lisp/version.el. */
44 #ifndef VERSION
45 #define VERSION "unspecified"
46 #endif
48 /* Name used to invoke this program. */
49 char *progname;
51 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
52 int nowait = 0;
54 void print_help_and_exit ();
56 struct option longopts[] =
58 { "no-wait", no_argument, NULL, 'n' },
59 { "help", no_argument, NULL, 'H' },
60 { "version", no_argument, NULL, 'V' },
61 { "alternate-editor",required_argument, NULL, 'a' },
62 { 0 }
66 const char * alternate_editor = NULL;
68 /* Decode the options from argv and argc.
69 The global variable `optind' will say how many arguments we used up. */
71 void
72 decode_options (argc, argv)
73 int argc;
74 char **argv;
76 while (1)
78 int opt = getopt_long (argc, argv,
79 "VHna:", longopts, 0);
81 if (opt == EOF)
82 break;
84 alternate_editor = getenv ("ALTERNATE_EDITOR");
86 switch (opt)
88 case 0:
89 /* If getopt returns 0, then it has already processed a
90 long-named option. We should do nothing. */
91 break;
93 case 'a':
94 alternate_editor = optarg;
95 break;
97 case 'n':
98 nowait = 1;
99 break;
101 case 'V':
102 fprintf (stderr, "emacsclient %s\n", VERSION);
103 exit (1);
104 break;
106 case 'H':
107 default:
108 print_help_and_exit ();
113 void
114 print_help_and_exit ()
116 fprintf (stderr,
117 "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
118 progname);
119 fprintf (stderr,
120 "Or %s --version\n",
121 progname);
122 fprintf (stderr,
123 "Report bugs to bug-gnu-emacs@gnu.org.\n");
124 exit (1);
127 /* Return a copy of NAME, inserting a &
128 before each &, each space, and any initial -.
129 Change spaces to underscores, too, so that the
130 return value never contains a space. */
132 char *
133 quote_file_name (name)
134 char *name;
136 char *copy = (char *) malloc (strlen (name) * 2 + 1);
137 char *p, *q;
139 p = name;
140 q = copy;
141 while (*p)
143 if (*p == ' ')
145 *q++ = '&';
146 *q++ = '_';
147 p++;
149 else
151 if (*p == '&' || (*p == '-' && p == name))
152 *q++ = '&';
153 *q++ = *p++;
156 *q++ = 0;
159 return copy;
162 /* Like malloc but get fatal error if memory is exhausted. */
164 long *
165 xmalloc (size)
166 unsigned int size;
168 long *result = (long *) malloc (size);
169 if (result == NULL)
171 perror ("malloc");
172 exit (1);
174 return result;
178 Try to run a different command, or --if no alternate editor is
179 defined-- exit with an errorcode.
181 fail (argc, argv)
182 int argc;
183 char **argv;
185 if (alternate_editor)
187 int i = optind -1 ;
188 execvp (alternate_editor, argv + i);
190 else
192 exit (1);
199 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
201 main (argc, argv)
202 int argc;
203 char **argv;
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");
209 fail (argc, argv);
212 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
214 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
215 /* BSD code is very different from SYSV IPC code */
217 #include <sys/types.h>
218 #include <sys/socket.h>
219 #include <sys/un.h>
220 #include <sys/stat.h>
221 #include <errno.h>
223 extern char *strerror ();
224 extern int errno;
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 */
231 static int
232 socket_status (socket_name)
233 char *socket_name;
235 struct stat statbfr;
237 if (stat (socket_name, &statbfr) == -1)
238 return 2;
240 if (statbfr.st_uid != geteuid ())
241 return 1;
243 return 0;
247 main (argc, argv)
248 int argc;
249 char **argv;
251 char *system_name;
252 int system_name_length;
253 int s, i;
254 FILE *out, *in;
255 struct sockaddr_un server;
256 #ifdef SERVER_HOME_DIR
257 char *homedir;
258 #endif
259 char *cwd, *str;
260 char string[BUFSIZ];
262 progname = argv[0];
264 /* Process options. */
265 decode_options (argc, argv);
267 if (argc - optind < 1)
268 print_help_and_exit ();
271 * Open up an AF_UNIX socket in this person's home directory
274 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
276 fprintf (stderr, "%s: ", argv[0]);
277 perror ("socket");
278 fail (argc, argv);
281 server.sun_family = AF_UNIX;
284 system_name_length = 32;
286 while (1)
288 system_name = (char *) xmalloc (system_name_length + 1);
290 /* system_name must be null-terminated string. */
291 system_name[system_name_length] = '\0';
293 if (gethostname (system_name, system_name_length) == 0)
294 break;
296 free (system_name);
297 system_name_length *= 2;
301 #ifndef SERVER_HOME_DIR
303 int sock_status = 0;
305 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
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)
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. */
316 char *user_name = (char *) getenv ("LOGNAME");
317 if (!user_name)
318 user_name = (char *) getenv ("USER");
320 if (user_name)
322 struct passwd *pw = getpwnam (user_name);
323 if (pw && (pw->pw_uid != geteuid ()))
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);
333 switch (sock_status)
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 ())
340 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
341 fail (argc, argv);
343 break;
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;
358 #else
359 if ((homedir = getenv ("HOME")) == NULL)
361 fprintf (stderr, "%s: No home directory\n", argv[0]);
362 fail (argc, argv);
364 strcpy (server.sun_path, homedir);
365 strcat (server.sun_path, "/.emacs-server-");
366 strcat (server.sun_path, system_name);
367 #endif
369 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
370 < 0)
372 fprintf (stderr, "%s: ", argv[0]);
373 perror ("connect");
374 fail (argc, argv);
377 /* We use the stream OUT to send our command to the server. */
378 if ((out = fdopen (s, "r+")) == NULL)
380 fprintf (stderr, "%s: ", argv[0]);
381 perror ("fdopen");
382 fail (argc, argv);
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)
392 fprintf (stderr, "%s: ", argv[0]);
393 perror ("fdopen");
394 fail (argc, argv);
397 #ifdef BSD_SYSTEM
398 cwd = getwd (string);
399 #else
400 cwd = getcwd (string, sizeof string);
401 #endif
402 if (cwd == 0)
404 /* getwd puts message in STRING if it fails. */
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));
412 fail (argc, argv);
415 if (nowait)
416 fprintf (out, "-nowait ");
418 for (i = optind; i < argc; i++)
420 if (*argv[i] == '+')
422 char *p = argv[i] + 1;
423 while (*p >= '0' && *p <= '9') p++;
424 if (*p != 0)
425 fprintf (out, "%s/", quote_file_name (cwd));
427 else if (*argv[i] != '/')
428 fprintf (out, "%s/", quote_file_name (cwd));
430 fprintf (out, "%s ", quote_file_name (argv[i]));
432 fprintf (out, "\n");
433 fflush (out);
435 /* Maybe wait for an answer. */
436 if (nowait)
437 return 0;
439 printf ("Waiting for Emacs...");
440 fflush (stdout);
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. */
447 while (str = fgets (string, BUFSIZ, in))
448 printf ("%s", str);
450 return 0;
453 #else /* This is the SYSV IPC section */
455 #include <sys/types.h>
456 #include <sys/ipc.h>
457 #include <sys/msg.h>
458 #include <sys/utsname.h>
459 #include <stdio.h>
460 #include <errno.h>
461 extern int errno;
463 char *getwd (), *getcwd (), *getenv ();
464 struct utsname system_name;
466 main (argc, argv)
467 int argc;
468 char **argv;
470 int s;
471 key_t key;
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);
478 struct msqid_ds * msg_st;
479 char *homedir, buf[BUFSIZ];
480 char gwdirb[BUFSIZ];
481 char *cwd;
482 char *temp;
484 progname = argv[0];
486 /* Process options. */
487 decode_options (argc, argv);
489 if (argc - optind < 1)
490 print_help_and_exit ();
493 * Create a message queue using ~/.emacs-server as the path for ftok
495 if ((homedir = getenv ("HOME")) == NULL)
497 fprintf (stderr, "%s: No home directory\n", argv[0]);
498 exit (1);
500 strcpy (buf, homedir);
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
509 creat (buf, 0600);
510 key = ftok (buf, 1); /* unlikely to be anyone else using it */
511 s = msgget (key, 0600 | IPC_CREAT);
512 if (s == -1)
514 fprintf (stderr, "%s: ", argv[0]);
515 perror ("msgget");
516 exit (1);
519 /* Determine working dir, so we can prefix it to all the arguments. */
520 #ifdef BSD_SYSTEM
521 temp = getwd (gwdirb);
522 #else
523 temp = getcwd (gwdirb, sizeof gwdirb);
524 #endif
526 cwd = gwdirb;
527 if (temp != 0)
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, "/");
535 else
537 #ifdef BSD_SYSTEM
538 fprintf (stderr, "%s: %s\n", argv[0], cwd);
539 #else
540 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
541 argv[0], strerror (errno));
542 #endif
543 fail (argc, argv);
546 msgp->mtext[0] = 0;
547 used = 0;
549 if (nowait)
551 strcat (msgp->mtext, "-nowait ");
552 used += 8;
555 argc -= optind;
556 argv += optind;
558 while (argc)
560 int need_cwd = 0;
561 char *modified_arg = argv[0];
563 if (*modified_arg == '+')
565 char *p = modified_arg + 1;
566 while (*p >= '0' && *p <= '9') p++;
567 if (*p != 0)
568 need_cwd = 1;
570 else if (*modified_arg != '/')
571 need_cwd = 1;
573 modified_arg = quote_file_name (modified_arg);
575 if (need_cwd)
576 /* Overestimate in case we have to quote something in CWD. */
577 used += 2 * strlen (cwd);
578 used += strlen (modified_arg) + 1;
579 while (used + 2 > size_allocated)
581 size_allocated *= 2;
582 msgp = (struct msgbuf *) realloc (msgp,
583 (sizeof (struct msgbuf)
584 + size_allocated));
587 if (need_cwd)
588 strcat (msgp->mtext, quote_file_name (cwd));
590 strcat (msgp->mtext, modified_arg);
591 strcat (msgp->mtext, " ");
592 argv++; argc--;
594 strcat (msgp->mtext, "\n");
595 #ifdef HPUX /* HPUX has a bug. */
596 if (strlen (msgp->mtext) >= 512)
598 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
599 fail (argc, argv);
601 #endif
602 msgp->mtype = 1;
603 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
605 fprintf (stderr, "%s: ", progname);
606 perror ("msgsnd");
607 fail (argc, argv);
610 /* Maybe wait for an answer. */
611 if (nowait)
612 return 0;
614 printf ("Waiting for Emacs...");
615 fflush (stdout);
617 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
618 strcpy (buf, msgp->mtext);
620 printf ("\n");
621 if (*buf)
622 printf ("%s\n", buf);
623 exit (0);
626 #endif /* HAVE_SYSVIPC */
628 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
630 #ifndef HAVE_STRERROR
631 char *
632 strerror (errnum)
633 int errnum;
635 extern char *sys_errlist[];
636 extern int sys_nerr;
638 if (errnum >= 0 && errnum < sys_nerr)
639 return sys_errlist[errnum];
640 return (char *) "Unknown error";
643 #endif /* ! HAVE_STRERROR */