]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
(enter_namespace): Fix reallocation of
[gnu-emacs] / lib-src / emacsclient.c
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.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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. */
21
22
23 #define NO_SHORTNAMES
24 #include <../src/config.h>
25 #undef signal
26
27 #include <stdio.h>
28 #include <getopt.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #ifdef VMS
34 # include "vms-pwd.h"
35 #else
36 # include <pwd.h>
37 #endif /* not VMS */
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 { "alternate-editor",required_argument, NULL, 'a' },
63 { 0 }
64 };
65
66
67 const char * alternate_editor = NULL;
68
69 /* Decode the options from argv and argc.
70 The global variable `optind' will say how many arguments we used up. */
71
72 void
73 decode_options (argc, argv)
74 int argc;
75 char **argv;
76 {
77 while (1)
78 {
79 int opt = getopt_long (argc, argv,
80 "VHna:", longopts, 0);
81
82 if (opt == EOF)
83 break;
84
85 alternate_editor = getenv ("ALTERNATE_EDITOR");
86
87 switch (opt)
88 {
89 case 0:
90 /* If getopt returns 0, then it has already processed a
91 long-named option. We should do nothing. */
92 break;
93
94 case 'a':
95 alternate_editor = optarg;
96 break;
97
98 case 'n':
99 nowait = 1;
100 break;
101
102 case 'V':
103 fprintf (stderr, "emacsclient %s\n", VERSION);
104 exit (1);
105 break;
106
107 case 'H':
108 default:
109 print_help_and_exit ();
110 }
111 }
112 }
113
114 void
115 print_help_and_exit ()
116 {
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);
126 }
127
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. */
132
133 char *
134 quote_file_name (name)
135 char *name;
136 {
137 char *copy = (char *) malloc (strlen (name) * 2 + 1);
138 char *p, *q;
139
140 p = name;
141 q = copy;
142 while (*p)
143 {
144 if (*p == ' ')
145 {
146 *q++ = '&';
147 *q++ = '_';
148 p++;
149 }
150 else
151 {
152 if (*p == '&' || (*p == '-' && p == name))
153 *q++ = '&';
154 *q++ = *p++;
155 }
156 }
157 *q++ = 0;
158
159
160 return copy;
161 }
162
163 /* Like malloc but get fatal error if memory is exhausted. */
164
165 long *
166 xmalloc (size)
167 unsigned int size;
168 {
169 long *result = (long *) malloc (size);
170 if (result == NULL)
171 {
172 perror ("malloc");
173 exit (1);
174 }
175 return result;
176 }
177 \f
178 /*
179 Try to run a different command, or --if no alternate editor is
180 defined-- exit with an errorcode.
181 */
182 void
183 fail (argc, argv)
184 int argc;
185 char **argv;
186 {
187 if (alternate_editor)
188 {
189 int i = optind -1 ;
190 execvp (alternate_editor, argv + i);
191 return;
192 }
193 else
194 {
195 exit (1);
196 }
197 }
198
199
200
201 \f
202 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
203
204 int
205 main (argc, argv)
206 int argc;
207 char **argv;
208 {
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");
212
213 fail (argc, argv);
214 }
215
216 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
217
218 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
219 /* BSD code is very different from SYSV IPC code */
220
221 #include <sys/types.h>
222 #include <sys/socket.h>
223 #include <sys/un.h>
224 #include <sys/stat.h>
225 #include <errno.h>
226
227 extern char *strerror ();
228 extern int errno;
229
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 */
234
235 static int
236 socket_status (socket_name)
237 char *socket_name;
238 {
239 struct stat statbfr;
240
241 if (stat (socket_name, &statbfr) == -1)
242 return 2;
243
244 if (statbfr.st_uid != geteuid ())
245 return 1;
246
247 return 0;
248 }
249
250 int
251 main (argc, argv)
252 int argc;
253 char **argv;
254 {
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];
265
266 progname = argv[0];
267
268 /* Process options. */
269 decode_options (argc, argv);
270
271 if (argc - optind < 1)
272 print_help_and_exit ();
273
274 /*
275 * Open up an AF_UNIX socket in this person's home directory
276 */
277
278 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
279 {
280 fprintf (stderr, "%s: ", argv[0]);
281 perror ("socket");
282 fail (argc, argv);
283 }
284
285 server.sun_family = AF_UNIX;
286
287 {
288 system_name_length = 32;
289
290 while (1)
291 {
292 system_name = (char *) xmalloc (system_name_length + 1);
293
294 /* system_name must be null-terminated string. */
295 system_name[system_name_length] = '\0';
296
297 if (gethostname (system_name, system_name_length) == 0)
298 break;
299
300 free (system_name);
301 system_name_length *= 2;
302 }
303 }
304
305 #ifndef SERVER_HOME_DIR
306 {
307 int sock_status = 0;
308
309 sprintf (server.sun_path, "/tmp/esrv%d-%s", (int) geteuid (), system_name);
310
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)
314 {
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. */
319
320 char *user_name = (char *) getenv ("LOGNAME");
321 if (!user_name)
322 user_name = (char *) getenv ("USER");
323
324 if (user_name)
325 {
326 struct passwd *pw = getpwnam (user_name);
327 if (pw && (pw->pw_uid != geteuid ()))
328 {
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);
333 }
334 }
335 }
336
337 switch (sock_status)
338 {
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 ())
343 {
344 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
345 fail (argc, argv);
346 }
347 break;
348
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;
360 }
361 }
362 #else
363 if ((homedir = getenv ("HOME")) == NULL)
364 {
365 fprintf (stderr, "%s: No home directory\n", argv[0]);
366 fail (argc, argv);
367 }
368 strcpy (server.sun_path, homedir);
369 strcat (server.sun_path, "/.emacs-server-");
370 strcat (server.sun_path, system_name);
371 #endif
372
373 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
374 < 0)
375 {
376 fprintf (stderr, "%s: ", argv[0]);
377 perror ("connect");
378 fail (argc, argv);
379 }
380
381 /* We use the stream OUT to send our command to the server. */
382 if ((out = fdopen (s, "r+")) == NULL)
383 {
384 fprintf (stderr, "%s: ", argv[0]);
385 perror ("fdopen");
386 fail (argc, argv);
387 }
388
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)
395 {
396 fprintf (stderr, "%s: ", argv[0]);
397 perror ("fdopen");
398 fail (argc, argv);
399 }
400
401 #ifdef BSD_SYSTEM
402 cwd = getwd (string);
403 #else
404 cwd = getcwd (string, sizeof string);
405 #endif
406 if (cwd == 0)
407 {
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);
417 }
418
419 if (nowait)
420 fprintf (out, "-nowait ");
421
422 for (i = optind; i < argc; i++)
423 {
424 if (*argv[i] == '+')
425 {
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));
430 }
431 else if (*argv[i] != '/')
432 fprintf (out, "%s/", quote_file_name (cwd));
433
434 fprintf (out, "%s ", quote_file_name (argv[i]));
435 }
436 fprintf (out, "\n");
437 fflush (out);
438
439 /* Maybe wait for an answer. */
440 if (nowait)
441 return 0;
442
443 printf ("Waiting for Emacs...");
444 fflush (stdout);
445
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. */
450
451 while (str = fgets (string, BUFSIZ, in))
452 printf ("%s", str);
453
454 return 0;
455 }
456
457 #else /* This is the SYSV IPC section */
458
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;
466
467 char *getwd (), *getcwd (), *getenv ();
468 struct utsname system_name;
469
470 main (argc, argv)
471 int argc;
472 char **argv;
473 {
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;
487
488 progname = argv[0];
489
490 /* Process options. */
491 decode_options (argc, argv);
492
493 if (argc - optind < 1)
494 print_help_and_exit ();
495
496 /*
497 * Create a message queue using ~/.emacs-server as the path for ftok
498 */
499 if ((homedir = getenv ("HOME")) == NULL)
500 {
501 fprintf (stderr, "%s: No home directory\n", argv[0]);
502 exit (1);
503 }
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)
517 {
518 fprintf (stderr, "%s: ", argv[0]);
519 perror ("msgget");
520 exit (1);
521 }
522
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
529
530 cwd = gwdirb;
531 if (temp != 0)
532 {
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, "/");
538 }
539 else
540 {
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);
548 }
549
550 msgp->mtext[0] = 0;
551 used = 0;
552
553 if (nowait)
554 {
555 strcat (msgp->mtext, "-nowait ");
556 used += 8;
557 }
558
559 argc -= optind;
560 argv += optind;
561
562 while (argc)
563 {
564 int need_cwd = 0;
565 char *modified_arg = argv[0];
566
567 if (*modified_arg == '+')
568 {
569 char *p = modified_arg + 1;
570 while (*p >= '0' && *p <= '9') p++;
571 if (*p != 0)
572 need_cwd = 1;
573 }
574 else if (*modified_arg != '/')
575 need_cwd = 1;
576
577 modified_arg = quote_file_name (modified_arg);
578
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)
584 {
585 size_allocated *= 2;
586 msgp = (struct msgbuf *) realloc (msgp,
587 (sizeof (struct msgbuf)
588 + size_allocated));
589 }
590
591 if (need_cwd)
592 strcat (msgp->mtext, quote_file_name (cwd));
593
594 strcat (msgp->mtext, modified_arg);
595 strcat (msgp->mtext, " ");
596 argv++; argc--;
597 }
598 strcat (msgp->mtext, "\n");
599 #ifdef HPUX /* HPUX has a bug. */
600 if (strlen (msgp->mtext) >= 512)
601 {
602 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
603 fail (argc, argv);
604 }
605 #endif
606 msgp->mtype = 1;
607 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
608 {
609 fprintf (stderr, "%s: ", progname);
610 perror ("msgsnd");
611 fail (argc, argv);
612 }
613
614 /* Maybe wait for an answer. */
615 if (nowait)
616 return 0;
617
618 printf ("Waiting for Emacs...");
619 fflush (stdout);
620
621 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
622 strcpy (buf, msgp->mtext);
623
624 printf ("\n");
625 if (*buf)
626 printf ("%s\n", buf);
627 exit (0);
628 }
629
630 #endif /* HAVE_SYSVIPC */
631
632 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
633 \f
634 #ifndef HAVE_STRERROR
635 char *
636 strerror (errnum)
637 int errnum;
638 {
639 extern char *sys_errlist[];
640 extern int sys_nerr;
641
642 if (errnum >= 0 && errnum < sys_nerr)
643 return sys_errlist[errnum];
644 return (char *) "Unknown error";
645 }
646
647 #endif /* ! HAVE_STRERROR */