(widget-sexp-validate): Fix garbled code.
[emacs.git] / lib-src / emacsclient.c
blobc4e01b616ffb72b5517cc6731f3929776c84b49e
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 char *homedir, *cwd, *str;
257 char string[BUFSIZ];
259 progname = argv[0];
261 /* Process options. */
262 decode_options (argc, argv);
264 if (argc - optind < 1)
265 print_help_and_exit ();
268 * Open up an AF_UNIX socket in this person's home directory
271 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
273 fprintf (stderr, "%s: ", argv[0]);
274 perror ("socket");
275 fail (argc, argv);
278 server.sun_family = AF_UNIX;
281 system_name_length = 32;
283 while (1)
285 system_name = (char *) xmalloc (system_name_length + 1);
287 /* system_name must be null-terminated string. */
288 system_name[system_name_length] = '\0';
290 if (gethostname (system_name, system_name_length) == 0)
291 break;
293 free (system_name);
294 system_name_length *= 2;
298 #ifndef SERVER_HOME_DIR
300 struct stat statbfr;
301 int sock_status = 0;
303 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
305 /* See if the socket exists, and if it's owned by us. */
306 sock_status = socket_status (server.sun_path);
307 if (sock_status)
309 /* Failing that, see if LOGNAME or USER exist and differ from
310 our euid. If so, look for a socket based on the UID
311 associated with the name. This is reminiscent of the logic
312 that init_editfns uses to set the global Vuser_full_name. */
314 char *user_name = (char *) getenv ("LOGNAME");
315 if (!user_name)
316 user_name = (char *) getenv ("USER");
318 if (user_name)
320 struct passwd *pw = getpwnam (user_name);
321 if (pw && (pw->pw_uid != geteuid ()))
323 /* We're running under su, apparently. */
324 sprintf (server.sun_path, "/tmp/esrv%d-%s",
325 pw->pw_uid, system_name);
326 sock_status = socket_status (server.sun_path);
331 switch (sock_status)
333 case 1:
334 /* There's a socket, but it isn't owned by us. This is OK if
335 we are root. */
336 if (0 != geteuid ())
338 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
339 fail (argc, argv);
341 break;
343 case 2:
344 /* `stat' failed */
345 if (errno == ENOENT)
346 fprintf (stderr,
347 "%s: can't find socket; have you started the server?\n",
348 argv[0]);
349 else
350 fprintf (stderr, "%s: can't stat %s: %s\n",
351 argv[0], server.sun_path, strerror (errno));
352 fail (argc, argv);
353 break;
356 #else
357 if ((homedir = getenv ("HOME")) == NULL)
359 fprintf (stderr, "%s: No home directory\n", argv[0]);
360 fail (argc, argv);
362 strcpy (server.sun_path, homedir);
363 strcat (server.sun_path, "/.emacs-server-");
364 strcat (server.sun_path, system_name);
365 #endif
367 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
368 < 0)
370 fprintf (stderr, "%s: ", argv[0]);
371 perror ("connect");
372 fail (argc, argv);
375 /* We use the stream OUT to send our command to the server. */
376 if ((out = fdopen (s, "r+")) == NULL)
378 fprintf (stderr, "%s: ", argv[0]);
379 perror ("fdopen");
380 fail (argc, argv);
383 /* We use the stream IN to read the response.
384 We used to use just one stream for both output and input
385 on the socket, but reversing direction works nonportably:
386 on some systems, the output appears as the first input;
387 on other systems it does not. */
388 if ((in = fdopen (s, "r+")) == NULL)
390 fprintf (stderr, "%s: ", argv[0]);
391 perror ("fdopen");
392 fail (argc, argv);
395 #ifdef BSD_SYSTEM
396 cwd = getwd (string);
397 #else
398 cwd = getcwd (string, sizeof string);
399 #endif
400 if (cwd == 0)
402 /* getwd puts message in STRING if it fails. */
403 fprintf (stderr, "%s: %s (%s)\n", argv[0],
404 #ifdef BSD_SYSTEM
405 string,
406 #else
407 "Cannot get current working directory",
408 #endif
409 strerror (errno));
410 fail (argc, argv);
413 if (nowait)
414 fprintf (out, "-nowait ");
416 for (i = optind; i < argc; i++)
418 if (*argv[i] == '+')
420 char *p = argv[i] + 1;
421 while (*p >= '0' && *p <= '9') p++;
422 if (*p != 0)
423 fprintf (out, "%s/", quote_file_name (cwd));
425 else if (*argv[i] != '/')
426 fprintf (out, "%s/", quote_file_name (cwd));
428 fprintf (out, "%s ", quote_file_name (argv[i]));
430 fprintf (out, "\n");
431 fflush (out);
433 /* Maybe wait for an answer. */
434 if (nowait)
435 return 0;
437 printf ("Waiting for Emacs...");
438 fflush (stdout);
440 /* Now, wait for an answer and print any messages. On some systems,
441 the first line we read will actually be the output we just sent.
442 We can't predict whether that will happen, so if it does, we
443 detect it by recognizing `Client: ' at the beginning. */
445 while (str = fgets (string, BUFSIZ, in))
446 printf ("%s", str);
448 return 0;
451 #else /* This is the SYSV IPC section */
453 #include <sys/types.h>
454 #include <sys/ipc.h>
455 #include <sys/msg.h>
456 #include <sys/utsname.h>
457 #include <stdio.h>
458 #include <errno.h>
459 extern int errno;
461 char *getwd (), *getcwd (), *getenv ();
462 struct utsname system_name;
464 main (argc, argv)
465 int argc;
466 char **argv;
468 int s;
469 key_t key;
470 /* Size of text allocated in MSGP. */
471 int size_allocated = BUFSIZ;
472 /* Amount of text used in MSGP. */
473 int used;
474 struct msgbuf *msgp
475 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
476 struct msqid_ds * msg_st;
477 char *homedir, buf[BUFSIZ];
478 char gwdirb[BUFSIZ];
479 char *cwd;
480 char *temp;
482 progname = argv[0];
484 /* Process options. */
485 decode_options (argc, argv);
487 if (argc - optind < 1)
488 print_help_and_exit ();
491 * Create a message queue using ~/.emacs-server as the path for ftok
493 if ((homedir = getenv ("HOME")) == NULL)
495 fprintf (stderr, "%s: No home directory\n", argv[0]);
496 exit (1);
498 strcpy (buf, homedir);
499 #ifndef HAVE_LONG_FILE_NAMES
500 /* If file names are short, we can't fit the host name. */
501 strcat (buf, "/.emacs-server");
502 #else
503 strcat (buf, "/.emacs-server-");
504 uname (&system_name);
505 strcat (buf, system_name.nodename);
506 #endif
507 creat (buf, 0600);
508 key = ftok (buf, 1); /* unlikely to be anyone else using it */
509 s = msgget (key, 0600 | IPC_CREAT);
510 if (s == -1)
512 fprintf (stderr, "%s: ", argv[0]);
513 perror ("msgget");
514 exit (1);
517 /* Determine working dir, so we can prefix it to all the arguments. */
518 #ifdef BSD_SYSTEM
519 temp = getwd (gwdirb);
520 #else
521 temp = getcwd (gwdirb, sizeof gwdirb);
522 #endif
524 cwd = gwdirb;
525 if (temp != 0)
527 /* On some systems, cwd can look like `@machine/...';
528 ignore everything before the first slash in such a case. */
529 while (*cwd && *cwd != '/')
530 cwd++;
531 strcat (cwd, "/");
533 else
535 #ifdef BSD_SYSTEM
536 fprintf (stderr, "%s: %s\n", argv[0], cwd);
537 #else
538 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
539 argv[0], strerror (errno));
540 #endif
541 fail (argc, argv);
544 msgp->mtext[0] = 0;
545 used = 0;
547 if (nowait)
549 strcat (msgp->mtext, "-nowait ");
550 used += 8;
553 argc -= optind;
554 argv += optind;
556 while (argc)
558 int need_cwd = 0;
559 char *modified_arg = argv[0];
561 if (*modified_arg == '+')
563 char *p = modified_arg + 1;
564 while (*p >= '0' && *p <= '9') p++;
565 if (*p != 0)
566 need_cwd = 1;
568 else if (*modified_arg != '/')
569 need_cwd = 1;
571 modified_arg = quote_file_name (modified_arg);
573 if (need_cwd)
574 /* Overestimate in case we have to quote something in CWD. */
575 used += 2 * strlen (cwd);
576 used += strlen (modified_arg) + 1;
577 while (used + 2 > size_allocated)
579 size_allocated *= 2;
580 msgp = (struct msgbuf *) realloc (msgp,
581 (sizeof (struct msgbuf)
582 + size_allocated));
585 if (need_cwd)
586 strcat (msgp->mtext, quote_file_name (cwd));
588 strcat (msgp->mtext, modified_arg);
589 strcat (msgp->mtext, " ");
590 argv++; argc--;
592 strcat (msgp->mtext, "\n");
593 #ifdef HPUX /* HPUX has a bug. */
594 if (strlen (msgp->mtext) >= 512)
596 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
597 fail (argc, argv);
599 #endif
600 msgp->mtype = 1;
601 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
603 fprintf (stderr, "%s: ", progname);
604 perror ("msgsnd");
605 fail (argc, argv);
608 /* Maybe wait for an answer. */
609 if (nowait)
610 return 0;
612 printf ("Waiting for Emacs...");
613 fflush (stdout);
615 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
616 strcpy (buf, msgp->mtext);
618 printf ("\n");
619 if (*buf)
620 printf ("%s\n", buf);
621 exit (0);
624 #endif /* HAVE_SYSVIPC */
626 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
628 #ifndef HAVE_STRERROR
629 char *
630 strerror (errnum)
631 int errnum;
633 extern char *sys_errlist[];
634 extern int sys_nerr;
636 if (errnum >= 0 && errnum < sys_nerr)
637 return sys_errlist[errnum];
638 return (char *) "Unknown error";
641 #endif /* ! HAVE_STRERROR */