(decode_mode_spec): For %Z and %z, put keyboard and
[emacs.git] / lib-src / emacsclient.c
blob999be2c2a8c14139db333ceb42a019a596085625
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994 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 read
25 #undef write
26 #undef open
27 #undef close
28 #undef signal
30 #include <stdio.h>
31 #include <getopt.h>
33 char *getenv (), *getwd ();
34 char *getcwd ();
35 int geteuid ();
37 /* This is defined with -D from the compilation command,
38 which extracts it from ../lisp/version.el. */
40 #ifndef VERSION
41 #define VERSION "unspecified"
42 #endif
44 /* Name used to invoke this program. */
45 char *progname;
47 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
48 int nowait = 0;
50 struct option longopts[] =
52 { "no-wait", no_argument, NULL, 'n' },
53 { "help", no_argument, NULL, 'H' },
54 { "version", no_argument, NULL, 'V' },
55 { 0 }
58 /* Decode the options from argv and argc.
59 The global variable `optind' will say how many arguments we used up. */
61 void
62 decode_options (argc, argv)
63 int argc;
64 char **argv;
66 while (1)
68 int opt = getopt_long (argc, argv,
69 "VHn", longopts, 0);
71 if (opt == EOF)
72 break;
74 switch (opt)
76 case 0:
77 /* If getopt returns 0, then it has already processed a
78 long-named option. We should do nothing. */
79 break;
81 case 'n':
82 nowait = 1;
83 break;
85 case 'V':
86 fprintf (stderr, "Version %s\n", VERSION);
87 exit (1);
88 break;
90 case 'H':
91 default:
92 print_help_and_exit ();
97 print_help_and_exit ()
99 fprintf (stderr,
100 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
101 progname);
102 fprintf (stderr,
103 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
104 exit (1);
107 /* Return a copy of NAME, inserting a &
108 before each &, each space, and any initial -.
109 Change spaces to underscores, too, so that the
110 return value never contains a space. */
112 char *
113 quote_file_name (name)
114 char *name;
116 char *copy = (char *) malloc (strlen (name) * 2 + 1);
117 char *p, *q;
119 p = name;
120 q = copy;
121 while (*p)
123 if (*p == ' ')
125 *q++ = '&';
126 *q++ = '_';
127 p++;
129 else
131 if (*p == '&' || (*p == '-' && p == name))
132 *q++ = '&';
133 *q++ = *p++;
136 *q++ = 0;
138 return copy;
141 #ifdef C_ALLOCA
142 /* Like malloc but get fatal error if memory is exhausted. */
144 char *
145 xmalloc (size)
146 unsigned int size;
148 char *result = (char *) malloc (size);
149 if (result == NULL)
151 perror ("malloc");
152 exit (1);
154 return result;
156 #endif /* C_ALLOCA */
158 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
160 main (argc, argv)
161 int argc;
162 char **argv;
164 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
165 argv[0]);
166 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
167 exit (1);
170 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
172 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
173 /* BSD code is very different from SYSV IPC code */
175 #include <sys/types.h>
176 #include <sys/socket.h>
177 #include <sys/un.h>
178 #include <sys/stat.h>
179 #include <errno.h>
181 extern char *strerror ();
182 extern int errno;
185 main (argc, argv)
186 int argc;
187 char **argv;
189 char system_name[32];
190 int s, i;
191 FILE *out, *in;
192 struct sockaddr_un server;
193 char *homedir, *cwd, *str;
194 char string[BUFSIZ];
196 progname = argv[0];
198 /* Process options. */
199 decode_options (argc, argv);
201 if (argc - optind < 1)
202 print_help_and_exit ();
205 * Open up an AF_UNIX socket in this person's home directory
208 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
210 fprintf (stderr, "%s: ", argv[0]);
211 perror ("socket");
212 exit (1);
214 server.sun_family = AF_UNIX;
215 #ifndef SERVER_HOME_DIR
217 struct stat statbfr;
219 gethostname (system_name, sizeof (system_name));
220 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
222 if (stat (server.sun_path, &statbfr) == -1)
224 if (errno == ENOENT)
225 fprintf (stderr,
226 "%s: can't find socket; have you started the server?\n",
227 argv[0]);
228 else
229 fprintf (stderr, "%s: can't stat %s: %s\n",
230 argv[0], server.sun_path, strerror (errno));
231 exit (1);
233 if (statbfr.st_uid != geteuid ())
235 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
236 exit (1);
239 #else
240 if ((homedir = getenv ("HOME")) == NULL)
242 fprintf (stderr, "%s: No home directory\n", argv[0]);
243 exit (1);
245 strcpy (server.sun_path, homedir);
246 strcat (server.sun_path, "/.emacs-server-");
247 gethostname (system_name, sizeof (system_name));
248 strcat (server.sun_path, system_name);
249 #endif
251 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
252 < 0)
254 fprintf (stderr, "%s: ", argv[0]);
255 perror ("connect");
256 exit (1);
259 /* We use the stream OUT to send our command to the server. */
260 if ((out = fdopen (s, "r+")) == NULL)
262 fprintf (stderr, "%s: ", argv[0]);
263 perror ("fdopen");
264 exit (1);
267 /* We use the stream IN to read the response.
268 We used to use just one stream for both output and input
269 on the socket, but reversing direction works nonportably:
270 on some systems, the output appears as the first input;
271 on other systems it does not. */
272 if ((in = fdopen (s, "r+")) == NULL)
274 fprintf (stderr, "%s: ", argv[0]);
275 perror ("fdopen");
276 exit (1);
279 #ifdef BSD_SYSTEM
280 cwd = getwd (string);
281 #else
282 cwd = getcwd (string, sizeof string);
283 #endif
284 if (cwd == 0)
286 /* getwd puts message in STRING if it fails. */
287 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
288 exit (1);
291 if (nowait)
292 fprintf (out, "-nowait ");
294 for (i = optind; i < argc; i++)
296 if (*argv[i] == '+')
298 char *p = argv[i] + 1;
299 while (*p >= '0' && *p <= '9') p++;
300 if (*p != 0)
301 fprintf (out, "%s/", cwd);
303 else if (*argv[i] != '/')
304 fprintf (out, "%s/", cwd);
306 fprintf (out, "%s ", quote_file_name (argv[i]));
308 fprintf (out, "\n");
309 fflush (out);
311 /* Maybe wait for an answer. */
312 if (nowait)
313 return 0;
315 printf ("Waiting for Emacs...");
316 fflush (stdout);
318 /* Now, wait for an answer and print any messages. On some systems,
319 the first line we read will actually be the output we just sent.
320 We can't predict whether that will happen, so if it does, we
321 detect it by recognizing `Client: ' at the beginning. */
323 while (str = fgets (string, BUFSIZ, in))
324 printf ("%s", str);
326 return 0;
329 #else /* This is the SYSV IPC section */
331 #include <sys/types.h>
332 #include <sys/ipc.h>
333 #include <sys/msg.h>
334 #include <sys/utsname.h>
335 #include <stdio.h>
337 char *getwd (), *getcwd (), *getenv ();
338 struct utsname system_name;
340 main (argc, argv)
341 int argc;
342 char **argv;
344 int s;
345 key_t key;
346 /* Size of text allocated in MSGP. */
347 int size_allocated = BUFSIZ;
348 /* Amount of text used in MSGP. */
349 int used;
350 struct msgbuf *msgp
351 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
352 struct msqid_ds * msg_st;
353 char *homedir, buf[BUFSIZ];
354 char gwdirb[BUFSIZ];
355 char *cwd;
356 char *temp;
358 progname = argv[0];
360 /* Process options. */
361 decode_options (argc, argv);
363 if (argc - optind < 1)
364 print_help_and_exit ();
367 * Create a message queue using ~/.emacs-server as the path for ftok
369 if ((homedir = getenv ("HOME")) == NULL)
371 fprintf (stderr, "%s: No home directory\n", argv[0]);
372 exit (1);
374 strcpy (buf, homedir);
375 #ifndef HAVE_LONG_FILE_NAMES
376 /* If file names are short, we can't fit the host name. */
377 strcat (buf, "/.emacs-server");
378 #else
379 strcat (buf, "/.emacs-server-");
380 uname (&system_name);
381 strcat (buf, system_name.nodename);
382 #endif
383 creat (buf, 0600);
384 key = ftok (buf, 1); /* unlikely to be anyone else using it */
385 s = msgget (key, 0600 | IPC_CREAT);
386 if (s == -1)
388 fprintf (stderr, "%s: ", argv[0]);
389 perror ("msgget");
390 exit (1);
393 /* Determine working dir, so we can prefix it to all the arguments. */
394 #ifdef BSD_SYSTEM
395 temp = getwd (gwdirb);
396 #else
397 temp = getcwd (gwdirb, sizeof gwdirb);
398 #endif
400 cwd = gwdirb;
401 if (temp != 0)
403 /* On some systems, cwd can look like `@machine/...';
404 ignore everything before the first slash in such a case. */
405 while (*cwd && *cwd != '/')
406 cwd++;
407 strcat (cwd, "/");
409 else
411 fprintf (stderr, "%s: %s\n", argv[0], cwd);
412 exit (1);
415 msgp->mtext[0] = 0;
416 used = 0;
418 if (nowait)
420 strcat (msgp->mtext, "-nowait ");
421 used += 8;
424 argc -= optind;
425 argv += optind;
427 while (argc)
429 int need_cwd = 0;
430 char *modified_arg = argv[0];
432 if (*modified_arg == '+')
434 char *p = modified_arg + 1;
435 while (*p >= '0' && *p <= '9') p++;
436 if (*p != 0)
437 need_cwd = 1;
439 else if (*modified_arg != '/')
440 need_cwd = 1;
442 modified_arg = quote_file_name (modified_arg);
444 if (need_cwd)
445 used += strlen (cwd);
446 used += strlen (modified_arg) + 1;
447 while (used + 2 > size_allocated)
449 size_allocated *= 2;
450 msgp = (struct msgbuf *) realloc (msgp,
451 (sizeof (struct msgbuf)
452 + size_allocated));
455 if (need_cwd)
456 strcat (msgp->mtext, cwd);
458 strcat (msgp->mtext, modified_arg);
459 strcat (msgp->mtext, " ");
460 argv++; argc--;
462 strcat (msgp->mtext, "\n");
463 #ifdef HPUX /* HPUX has a bug. */
464 if (strlen (msgp->mtext) >= 512)
466 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
467 exit (1);
469 #endif
470 msgp->mtype = 1;
471 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
473 fprintf (stderr, "%s: ", progname);
474 perror ("msgsnd");
475 exit (1);
478 /* Maybe wait for an answer. */
479 if (nowait)
480 return 0;
482 printf ("Waiting for Emacs...");
483 fflush (stdout);
485 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
486 strcpy (buf, msgp->mtext);
488 printf ("\n");
489 if (*buf)
490 printf ("%s\n", buf);
491 exit (0);
494 #endif /* HAVE_SYSVIPC */
496 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
498 #ifndef HAVE_STRERROR
499 char *
500 strerror (errnum)
501 int errnum;
503 extern char *sys_errlist[];
504 extern int sys_nerr;
506 if (errnum >= 0 && errnum < sys_nerr)
507 return sys_errlist[errnum];
508 return (char *) "Unknown error";
511 #endif /* ! HAVE_STRERROR */