]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
(decode_options): Update version output.
[gnu-emacs] / lib-src / emacsclient.c
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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.
10
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.
15
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. */
20
21
22 #define NO_SHORTNAMES
23 #include <../src/config.h>
24 #undef read
25 #undef write
26 #undef open
27 #undef close
28 #undef signal
29
30 #include <stdio.h>
31 #include <getopt.h>
32 #ifdef STDC_HEADERS
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 char *getenv (), *getwd ();
40 char *getcwd ();
41
42 /* This is defined with -D from the compilation command,
43 which extracts it from ../lisp/version.el. */
44
45 #ifndef VERSION
46 #define VERSION "unspecified"
47 #endif
48 \f
49 /* Name used to invoke this program. */
50 char *progname;
51
52 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
53 int nowait = 0;
54
55 void print_help_and_exit ();
56
57 struct option longopts[] =
58 {
59 { "no-wait", no_argument, NULL, 'n' },
60 { "help", no_argument, NULL, 'H' },
61 { "version", no_argument, NULL, 'V' },
62 { 0 }
63 };
64
65 /* Decode the options from argv and argc.
66 The global variable `optind' will say how many arguments we used up. */
67
68 void
69 decode_options (argc, argv)
70 int argc;
71 char **argv;
72 {
73 while (1)
74 {
75 int opt = getopt_long (argc, argv,
76 "VHn", longopts, 0);
77
78 if (opt == EOF)
79 break;
80
81 switch (opt)
82 {
83 case 0:
84 /* If getopt returns 0, then it has already processed a
85 long-named option. We should do nothing. */
86 break;
87
88 case 'n':
89 nowait = 1;
90 break;
91
92 case 'V':
93 fprintf (stderr, "emacsclient %s\n", VERSION);
94 exit (1);
95 break;
96
97 case 'H':
98 default:
99 print_help_and_exit ();
100 }
101 }
102 }
103
104 void
105 print_help_and_exit ()
106 {
107 fprintf (stderr,
108 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
109 progname);
110 fprintf (stderr,
111 "Report bugs to bug-gnu-emacs@gnu.org.\n");
112 exit (1);
113 }
114
115 /* Return a copy of NAME, inserting a &
116 before each &, each space, and any initial -.
117 Change spaces to underscores, too, so that the
118 return value never contains a space. */
119
120 char *
121 quote_file_name (name)
122 char *name;
123 {
124 char *copy = (char *) malloc (strlen (name) * 2 + 1);
125 char *p, *q;
126
127 p = name;
128 q = copy;
129 while (*p)
130 {
131 if (*p == ' ')
132 {
133 *q++ = '&';
134 *q++ = '_';
135 p++;
136 }
137 else
138 {
139 if (*p == '&' || (*p == '-' && p == name))
140 *q++ = '&';
141 *q++ = *p++;
142 }
143 }
144 *q++ = 0;
145
146 return copy;
147 }
148
149 /* Like malloc but get fatal error if memory is exhausted. */
150
151 long *
152 xmalloc (size)
153 unsigned int size;
154 {
155 long *result = (long *) malloc (size);
156 if (result == NULL)
157 {
158 perror ("malloc");
159 exit (1);
160 }
161 return result;
162 }
163 \f
164 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
165
166 main (argc, argv)
167 int argc;
168 char **argv;
169 {
170 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
171 argv[0]);
172 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
173 exit (1);
174 }
175
176 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
177
178 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
179 /* BSD code is very different from SYSV IPC code */
180
181 #include <sys/types.h>
182 #include <sys/socket.h>
183 #include <sys/un.h>
184 #include <sys/stat.h>
185 #include <errno.h>
186
187 extern char *strerror ();
188 extern int errno;
189
190 int
191 main (argc, argv)
192 int argc;
193 char **argv;
194 {
195 char *system_name;
196 int system_name_length;
197 int s, i;
198 FILE *out, *in;
199 struct sockaddr_un server;
200 char *homedir, *cwd, *str;
201 char string[BUFSIZ];
202
203 progname = argv[0];
204
205 /* Process options. */
206 decode_options (argc, argv);
207
208 if (argc - optind < 1)
209 print_help_and_exit ();
210
211 /*
212 * Open up an AF_UNIX socket in this person's home directory
213 */
214
215 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
216 {
217 fprintf (stderr, "%s: ", argv[0]);
218 perror ("socket");
219 exit (1);
220 }
221 server.sun_family = AF_UNIX;
222
223 {
224 system_name_length = 32;
225
226 while (1)
227 {
228 system_name = (char *) xmalloc (system_name_length + 1);
229
230 /* system_name must be null-terminated string. */
231 system_name[system_name_length] = '\0';
232
233 if (gethostname (system_name, system_name_length) == 0)
234 break;
235
236 free (system_name);
237 system_name_length *= 2;
238 }
239 }
240
241 #ifndef SERVER_HOME_DIR
242 {
243 struct stat statbfr;
244
245 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
246
247 if (stat (server.sun_path, &statbfr) == -1)
248 {
249 if (errno == ENOENT)
250 fprintf (stderr,
251 "%s: can't find socket; have you started the server?\n",
252 argv[0]);
253 else
254 fprintf (stderr, "%s: can't stat %s: %s\n",
255 argv[0], server.sun_path, strerror (errno));
256 exit (1);
257 }
258 if (statbfr.st_uid != geteuid ())
259 {
260 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
261 exit (1);
262 }
263 }
264 #else
265 if ((homedir = getenv ("HOME")) == NULL)
266 {
267 fprintf (stderr, "%s: No home directory\n", argv[0]);
268 exit (1);
269 }
270 strcpy (server.sun_path, homedir);
271 strcat (server.sun_path, "/.emacs-server-");
272 strcat (server.sun_path, system_name);
273 #endif
274
275 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
276 < 0)
277 {
278 fprintf (stderr, "%s: ", argv[0]);
279 perror ("connect");
280 exit (1);
281 }
282
283 /* We use the stream OUT to send our command to the server. */
284 if ((out = fdopen (s, "r+")) == NULL)
285 {
286 fprintf (stderr, "%s: ", argv[0]);
287 perror ("fdopen");
288 exit (1);
289 }
290
291 /* We use the stream IN to read the response.
292 We used to use just one stream for both output and input
293 on the socket, but reversing direction works nonportably:
294 on some systems, the output appears as the first input;
295 on other systems it does not. */
296 if ((in = fdopen (s, "r+")) == NULL)
297 {
298 fprintf (stderr, "%s: ", argv[0]);
299 perror ("fdopen");
300 exit (1);
301 }
302
303 #ifdef BSD_SYSTEM
304 cwd = getwd (string);
305 #else
306 cwd = getcwd (string, sizeof string);
307 #endif
308 if (cwd == 0)
309 {
310 /* getwd puts message in STRING if it fails. */
311 fprintf (stderr, "%s: %s (%s)\n", argv[0],
312 #ifdef BSD_SYSTEM
313 string,
314 #else
315 "Cannot get current working directory",
316 #endif
317 strerror (errno));
318 exit (1);
319 }
320
321 if (nowait)
322 fprintf (out, "-nowait ");
323
324 for (i = optind; i < argc; i++)
325 {
326 if (*argv[i] == '+')
327 {
328 char *p = argv[i] + 1;
329 while (*p >= '0' && *p <= '9') p++;
330 if (*p != 0)
331 fprintf (out, "%s/", quote_file_name (cwd));
332 }
333 else if (*argv[i] != '/')
334 fprintf (out, "%s/", quote_file_name (cwd));
335
336 fprintf (out, "%s ", quote_file_name (argv[i]));
337 }
338 fprintf (out, "\n");
339 fflush (out);
340
341 /* Maybe wait for an answer. */
342 if (nowait)
343 return 0;
344
345 printf ("Waiting for Emacs...");
346 fflush (stdout);
347
348 /* Now, wait for an answer and print any messages. On some systems,
349 the first line we read will actually be the output we just sent.
350 We can't predict whether that will happen, so if it does, we
351 detect it by recognizing `Client: ' at the beginning. */
352
353 while (str = fgets (string, BUFSIZ, in))
354 printf ("%s", str);
355
356 return 0;
357 }
358
359 #else /* This is the SYSV IPC section */
360
361 #include <sys/types.h>
362 #include <sys/ipc.h>
363 #include <sys/msg.h>
364 #include <sys/utsname.h>
365 #include <stdio.h>
366 #include <errno.h>
367 extern int errno;
368
369 char *getwd (), *getcwd (), *getenv ();
370 struct utsname system_name;
371
372 main (argc, argv)
373 int argc;
374 char **argv;
375 {
376 int s;
377 key_t key;
378 /* Size of text allocated in MSGP. */
379 int size_allocated = BUFSIZ;
380 /* Amount of text used in MSGP. */
381 int used;
382 struct msgbuf *msgp
383 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
384 struct msqid_ds * msg_st;
385 char *homedir, buf[BUFSIZ];
386 char gwdirb[BUFSIZ];
387 char *cwd;
388 char *temp;
389
390 progname = argv[0];
391
392 /* Process options. */
393 decode_options (argc, argv);
394
395 if (argc - optind < 1)
396 print_help_and_exit ();
397
398 /*
399 * Create a message queue using ~/.emacs-server as the path for ftok
400 */
401 if ((homedir = getenv ("HOME")) == NULL)
402 {
403 fprintf (stderr, "%s: No home directory\n", argv[0]);
404 exit (1);
405 }
406 strcpy (buf, homedir);
407 #ifndef HAVE_LONG_FILE_NAMES
408 /* If file names are short, we can't fit the host name. */
409 strcat (buf, "/.emacs-server");
410 #else
411 strcat (buf, "/.emacs-server-");
412 uname (&system_name);
413 strcat (buf, system_name.nodename);
414 #endif
415 creat (buf, 0600);
416 key = ftok (buf, 1); /* unlikely to be anyone else using it */
417 s = msgget (key, 0600 | IPC_CREAT);
418 if (s == -1)
419 {
420 fprintf (stderr, "%s: ", argv[0]);
421 perror ("msgget");
422 exit (1);
423 }
424
425 /* Determine working dir, so we can prefix it to all the arguments. */
426 #ifdef BSD_SYSTEM
427 temp = getwd (gwdirb);
428 #else
429 temp = getcwd (gwdirb, sizeof gwdirb);
430 #endif
431
432 cwd = gwdirb;
433 if (temp != 0)
434 {
435 /* On some systems, cwd can look like `@machine/...';
436 ignore everything before the first slash in such a case. */
437 while (*cwd && *cwd != '/')
438 cwd++;
439 strcat (cwd, "/");
440 }
441 else
442 {
443 #ifdef BSD_SYSTEM
444 fprintf (stderr, "%s: %s\n", argv[0], cwd);
445 #else
446 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
447 argv[0], strerror (errno));
448 #endif
449 exit (1);
450 }
451
452 msgp->mtext[0] = 0;
453 used = 0;
454
455 if (nowait)
456 {
457 strcat (msgp->mtext, "-nowait ");
458 used += 8;
459 }
460
461 argc -= optind;
462 argv += optind;
463
464 while (argc)
465 {
466 int need_cwd = 0;
467 char *modified_arg = argv[0];
468
469 if (*modified_arg == '+')
470 {
471 char *p = modified_arg + 1;
472 while (*p >= '0' && *p <= '9') p++;
473 if (*p != 0)
474 need_cwd = 1;
475 }
476 else if (*modified_arg != '/')
477 need_cwd = 1;
478
479 modified_arg = quote_file_name (modified_arg);
480
481 if (need_cwd)
482 /* Overestimate in case we have to quote something in CWD. */
483 used += 2 * strlen (cwd);
484 used += strlen (modified_arg) + 1;
485 while (used + 2 > size_allocated)
486 {
487 size_allocated *= 2;
488 msgp = (struct msgbuf *) realloc (msgp,
489 (sizeof (struct msgbuf)
490 + size_allocated));
491 }
492
493 if (need_cwd)
494 strcat (msgp->mtext, quote_file_name (cwd));
495
496 strcat (msgp->mtext, modified_arg);
497 strcat (msgp->mtext, " ");
498 argv++; argc--;
499 }
500 strcat (msgp->mtext, "\n");
501 #ifdef HPUX /* HPUX has a bug. */
502 if (strlen (msgp->mtext) >= 512)
503 {
504 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
505 exit (1);
506 }
507 #endif
508 msgp->mtype = 1;
509 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
510 {
511 fprintf (stderr, "%s: ", progname);
512 perror ("msgsnd");
513 exit (1);
514 }
515
516 /* Maybe wait for an answer. */
517 if (nowait)
518 return 0;
519
520 printf ("Waiting for Emacs...");
521 fflush (stdout);
522
523 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
524 strcpy (buf, msgp->mtext);
525
526 printf ("\n");
527 if (*buf)
528 printf ("%s\n", buf);
529 exit (0);
530 }
531
532 #endif /* HAVE_SYSVIPC */
533
534 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
535 \f
536 #ifndef HAVE_STRERROR
537 char *
538 strerror (errnum)
539 int errnum;
540 {
541 extern char *sys_errlist[];
542 extern int sys_nerr;
543
544 if (errnum >= 0 && errnum < sys_nerr)
545 return sys_errlist[errnum];
546 return (char *) "Unknown error";
547 }
548
549 #endif /* ! HAVE_STRERROR */