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