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