Some fixes to follow coding conventions in files from Gnus.
[emacs.git] / lib-src / emacsclient.c
blobf16b126b7510201c8e5e14e318f9a71aa2091628
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 <stdio.h>
28 #include <getopt.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #ifdef VMS
34 # include "vms-pwd.h"
35 #else
36 # include <pwd.h>
37 #endif /* not VMS */
39 char *getenv (), *getwd ();
40 char *getcwd ();
42 /* This is defined with -D from the compilation command,
43 which extracts it from ../lisp/version.el. */
45 #ifndef VERSION
46 #define VERSION "unspecified"
47 #endif
49 /* Name used to invoke this program. */
50 char *progname;
52 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
53 int nowait = 0;
55 void print_help_and_exit ();
57 struct option longopts[] =
59 { "no-wait", no_argument, NULL, 'n' },
60 { "help", no_argument, NULL, 'H' },
61 { "version", no_argument, NULL, 'V' },
62 { "alternate-editor",required_argument, NULL, 'a' },
63 { 0 }
67 const char * alternate_editor = NULL;
69 /* Decode the options from argv and argc.
70 The global variable `optind' will say how many arguments we used up. */
72 void
73 decode_options (argc, argv)
74 int argc;
75 char **argv;
77 while (1)
79 int opt = getopt_long (argc, argv,
80 "VHna:", longopts, 0);
82 if (opt == EOF)
83 break;
85 alternate_editor = getenv ("ALTERNATE_EDITOR");
87 switch (opt)
89 case 0:
90 /* If getopt returns 0, then it has already processed a
91 long-named option. We should do nothing. */
92 break;
94 case 'a':
95 alternate_editor = optarg;
96 break;
98 case 'n':
99 nowait = 1;
100 break;
102 case 'V':
103 fprintf (stderr, "emacsclient %s\n", VERSION);
104 exit (1);
105 break;
107 case 'H':
108 default:
109 print_help_and_exit ();
114 void
115 print_help_and_exit ()
117 fprintf (stderr,
118 "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
119 progname);
120 fprintf (stderr,
121 "Or %s --version\n",
122 progname);
123 fprintf (stderr,
124 "Report bugs to bug-gnu-emacs@gnu.org.\n");
125 exit (1);
128 /* Return a copy of NAME, inserting a &
129 before each &, each space, and any initial -.
130 Change spaces to underscores, too, so that the
131 return value never contains a space. */
133 char *
134 quote_file_name (name)
135 char *name;
137 char *copy = (char *) malloc (strlen (name) * 2 + 1);
138 char *p, *q;
140 p = name;
141 q = copy;
142 while (*p)
144 if (*p == ' ')
146 *q++ = '&';
147 *q++ = '_';
148 p++;
150 else
152 if (*p == '&' || (*p == '-' && p == name))
153 *q++ = '&';
154 *q++ = *p++;
157 *q++ = 0;
160 return copy;
163 /* Like malloc but get fatal error if memory is exhausted. */
165 long *
166 xmalloc (size)
167 unsigned int size;
169 long *result = (long *) malloc (size);
170 if (result == NULL)
172 perror ("malloc");
173 exit (1);
175 return result;
179 Try to run a different command, or --if no alternate editor is
180 defined-- exit with an errorcode.
182 void
183 fail (argc, argv)
184 int argc;
185 char **argv;
187 if (alternate_editor)
189 int i = optind -1 ;
190 execvp (alternate_editor, argv + i);
191 return;
193 else
195 exit (1);
202 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
205 main (argc, argv)
206 int argc;
207 char **argv;
209 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
210 argv[0]);
211 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
213 fail (argc, argv);
216 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
218 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
219 /* BSD code is very different from SYSV IPC code */
221 #include <sys/types.h>
222 #include <sys/socket.h>
223 #include <sys/un.h>
224 #include <sys/stat.h>
225 #include <errno.h>
227 extern char *strerror ();
228 extern int errno;
230 /* Three possibilities:
231 2 - can't be `stat'ed (sets errno)
232 1 - isn't owned by us
233 0 - success: none of the above */
235 static int
236 socket_status (socket_name)
237 char *socket_name;
239 struct stat statbfr;
241 if (stat (socket_name, &statbfr) == -1)
242 return 2;
244 if (statbfr.st_uid != geteuid ())
245 return 1;
247 return 0;
251 main (argc, argv)
252 int argc;
253 char **argv;
255 char *system_name;
256 int system_name_length;
257 int s, i;
258 FILE *out, *in;
259 struct sockaddr_un server;
260 #ifdef SERVER_HOME_DIR
261 char *homedir;
262 #endif
263 char *cwd, *str;
264 char string[BUFSIZ];
266 progname = argv[0];
268 /* Process options. */
269 decode_options (argc, argv);
271 if (argc - optind < 1)
272 print_help_and_exit ();
275 * Open up an AF_UNIX socket in this person's home directory
278 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
280 fprintf (stderr, "%s: ", argv[0]);
281 perror ("socket");
282 fail (argc, argv);
285 server.sun_family = AF_UNIX;
288 system_name_length = 32;
290 while (1)
292 system_name = (char *) xmalloc (system_name_length + 1);
294 /* system_name must be null-terminated string. */
295 system_name[system_name_length] = '\0';
297 if (gethostname (system_name, system_name_length) == 0)
298 break;
300 free (system_name);
301 system_name_length *= 2;
305 #ifndef SERVER_HOME_DIR
307 int sock_status = 0;
309 sprintf (server.sun_path, "/tmp/esrv%d-%s", (int) geteuid (), system_name);
311 /* See if the socket exists, and if it's owned by us. */
312 sock_status = socket_status (server.sun_path);
313 if (sock_status)
315 /* Failing that, see if LOGNAME or USER exist and differ from
316 our euid. If so, look for a socket based on the UID
317 associated with the name. This is reminiscent of the logic
318 that init_editfns uses to set the global Vuser_full_name. */
320 char *user_name = (char *) getenv ("LOGNAME");
321 if (!user_name)
322 user_name = (char *) getenv ("USER");
324 if (user_name)
326 struct passwd *pw = getpwnam (user_name);
327 if (pw && (pw->pw_uid != geteuid ()))
329 /* We're running under su, apparently. */
330 sprintf (server.sun_path, "/tmp/esrv%d-%s",
331 (int) pw->pw_uid, system_name);
332 sock_status = socket_status (server.sun_path);
337 switch (sock_status)
339 case 1:
340 /* There's a socket, but it isn't owned by us. This is OK if
341 we are root. */
342 if (0 != geteuid ())
344 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
345 fail (argc, argv);
347 break;
349 case 2:
350 /* `stat' failed */
351 if (errno == ENOENT)
352 fprintf (stderr,
353 "%s: can't find socket; have you started the server?\n",
354 argv[0]);
355 else
356 fprintf (stderr, "%s: can't stat %s: %s\n",
357 argv[0], server.sun_path, strerror (errno));
358 fail (argc, argv);
359 break;
362 #else
363 if ((homedir = getenv ("HOME")) == NULL)
365 fprintf (stderr, "%s: No home directory\n", argv[0]);
366 fail (argc, argv);
368 strcpy (server.sun_path, homedir);
369 strcat (server.sun_path, "/.emacs-server-");
370 strcat (server.sun_path, system_name);
371 #endif
373 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
374 < 0)
376 fprintf (stderr, "%s: ", argv[0]);
377 perror ("connect");
378 fail (argc, argv);
381 /* We use the stream OUT to send our command to the server. */
382 if ((out = fdopen (s, "r+")) == NULL)
384 fprintf (stderr, "%s: ", argv[0]);
385 perror ("fdopen");
386 fail (argc, argv);
389 /* We use the stream IN to read the response.
390 We used to use just one stream for both output and input
391 on the socket, but reversing direction works nonportably:
392 on some systems, the output appears as the first input;
393 on other systems it does not. */
394 if ((in = fdopen (s, "r+")) == NULL)
396 fprintf (stderr, "%s: ", argv[0]);
397 perror ("fdopen");
398 fail (argc, argv);
401 #ifdef BSD_SYSTEM
402 cwd = getwd (string);
403 #else
404 cwd = getcwd (string, sizeof string);
405 #endif
406 if (cwd == 0)
408 /* getwd puts message in STRING if it fails. */
409 fprintf (stderr, "%s: %s (%s)\n", argv[0],
410 #ifdef BSD_SYSTEM
411 string,
412 #else
413 "Cannot get current working directory",
414 #endif
415 strerror (errno));
416 fail (argc, argv);
419 if (nowait)
420 fprintf (out, "-nowait ");
422 for (i = optind; i < argc; i++)
424 if (*argv[i] == '+')
426 char *p = argv[i] + 1;
427 while (*p >= '0' && *p <= '9') p++;
428 if (*p != 0)
429 fprintf (out, "%s/", quote_file_name (cwd));
431 else if (*argv[i] != '/')
432 fprintf (out, "%s/", quote_file_name (cwd));
434 fprintf (out, "%s ", quote_file_name (argv[i]));
436 fprintf (out, "\n");
437 fflush (out);
439 /* Maybe wait for an answer. */
440 if (nowait)
441 return 0;
443 printf ("Waiting for Emacs...");
444 fflush (stdout);
446 /* Now, wait for an answer and print any messages. On some systems,
447 the first line we read will actually be the output we just sent.
448 We can't predict whether that will happen, so if it does, we
449 detect it by recognizing `Client: ' at the beginning. */
451 while (str = fgets (string, BUFSIZ, in))
452 printf ("%s", str);
454 return 0;
457 #else /* This is the SYSV IPC section */
459 #include <sys/types.h>
460 #include <sys/ipc.h>
461 #include <sys/msg.h>
462 #include <sys/utsname.h>
463 #include <stdio.h>
464 #include <errno.h>
465 extern int errno;
467 char *getwd (), *getcwd (), *getenv ();
468 struct utsname system_name;
470 main (argc, argv)
471 int argc;
472 char **argv;
474 int s;
475 key_t key;
476 /* Size of text allocated in MSGP. */
477 int size_allocated = BUFSIZ;
478 /* Amount of text used in MSGP. */
479 int used;
480 struct msgbuf *msgp
481 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
482 struct msqid_ds * msg_st;
483 char *homedir, buf[BUFSIZ];
484 char gwdirb[BUFSIZ];
485 char *cwd;
486 char *temp;
488 progname = argv[0];
490 /* Process options. */
491 decode_options (argc, argv);
493 if (argc - optind < 1)
494 print_help_and_exit ();
497 * Create a message queue using ~/.emacs-server as the path for ftok
499 if ((homedir = getenv ("HOME")) == NULL)
501 fprintf (stderr, "%s: No home directory\n", argv[0]);
502 exit (1);
504 strcpy (buf, homedir);
505 #ifndef HAVE_LONG_FILE_NAMES
506 /* If file names are short, we can't fit the host name. */
507 strcat (buf, "/.emacs-server");
508 #else
509 strcat (buf, "/.emacs-server-");
510 uname (&system_name);
511 strcat (buf, system_name.nodename);
512 #endif
513 creat (buf, 0600);
514 key = ftok (buf, 1); /* unlikely to be anyone else using it */
515 s = msgget (key, 0600 | IPC_CREAT);
516 if (s == -1)
518 fprintf (stderr, "%s: ", argv[0]);
519 perror ("msgget");
520 exit (1);
523 /* Determine working dir, so we can prefix it to all the arguments. */
524 #ifdef BSD_SYSTEM
525 temp = getwd (gwdirb);
526 #else
527 temp = getcwd (gwdirb, sizeof gwdirb);
528 #endif
530 cwd = gwdirb;
531 if (temp != 0)
533 /* On some systems, cwd can look like `@machine/...';
534 ignore everything before the first slash in such a case. */
535 while (*cwd && *cwd != '/')
536 cwd++;
537 strcat (cwd, "/");
539 else
541 #ifdef BSD_SYSTEM
542 fprintf (stderr, "%s: %s\n", argv[0], cwd);
543 #else
544 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
545 argv[0], strerror (errno));
546 #endif
547 fail (argc, argv);
550 msgp->mtext[0] = 0;
551 used = 0;
553 if (nowait)
555 strcat (msgp->mtext, "-nowait ");
556 used += 8;
559 argc -= optind;
560 argv += optind;
562 while (argc)
564 int need_cwd = 0;
565 char *modified_arg = argv[0];
567 if (*modified_arg == '+')
569 char *p = modified_arg + 1;
570 while (*p >= '0' && *p <= '9') p++;
571 if (*p != 0)
572 need_cwd = 1;
574 else if (*modified_arg != '/')
575 need_cwd = 1;
577 modified_arg = quote_file_name (modified_arg);
579 if (need_cwd)
580 /* Overestimate in case we have to quote something in CWD. */
581 used += 2 * strlen (cwd);
582 used += strlen (modified_arg) + 1;
583 while (used + 2 > size_allocated)
585 size_allocated *= 2;
586 msgp = (struct msgbuf *) realloc (msgp,
587 (sizeof (struct msgbuf)
588 + size_allocated));
591 if (need_cwd)
592 strcat (msgp->mtext, quote_file_name (cwd));
594 strcat (msgp->mtext, modified_arg);
595 strcat (msgp->mtext, " ");
596 argv++; argc--;
598 strcat (msgp->mtext, "\n");
599 #ifdef HPUX /* HPUX has a bug. */
600 if (strlen (msgp->mtext) >= 512)
602 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
603 fail (argc, argv);
605 #endif
606 msgp->mtype = 1;
607 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
609 fprintf (stderr, "%s: ", progname);
610 perror ("msgsnd");
611 fail (argc, argv);
614 /* Maybe wait for an answer. */
615 if (nowait)
616 return 0;
618 printf ("Waiting for Emacs...");
619 fflush (stdout);
621 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
622 strcpy (buf, msgp->mtext);
624 printf ("\n");
625 if (*buf)
626 printf ("%s\n", buf);
627 exit (0);
630 #endif /* HAVE_SYSVIPC */
632 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
634 #ifndef HAVE_STRERROR
635 char *
636 strerror (errnum)
637 int errnum;
639 extern char *sys_errlist[];
640 extern int sys_nerr;
642 if (errnum >= 0 && errnum < sys_nerr)
643 return sys_errlist[errnum];
644 return (char *) "Unknown error";
647 #endif /* ! HAVE_STRERROR */