]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
(last): New function.
[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
33 char *getenv (), *getwd ();
34 char *getcwd ();
35 int geteuid ();
36
37 /* This is defined with -D from the compilation command,
38 which extracts it from ../lisp/version.el. */
39
40 #ifndef VERSION
41 #define VERSION "unspecified"
42 #endif
43 \f
44 /* Name used to invoke this program. */
45 char *progname;
46
47 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
48 int nowait = 0;
49
50 struct option longopts[] =
51 {
52 { "no-wait", no_argument, NULL, 'n' },
53 { "help", no_argument, NULL, 'H' },
54 { "version", no_argument, NULL, 'V' },
55 { 0 }
56 };
57
58 /* Decode the options from argv and argc.
59 The global variable `optind' will say how many arguments we used up. */
60
61 void
62 decode_options (argc, argv)
63 int argc;
64 char **argv;
65 {
66 while (1)
67 {
68 int opt = getopt_long (argc, argv,
69 "VHn", longopts, 0);
70
71 if (opt == EOF)
72 break;
73
74 switch (opt)
75 {
76 case 0:
77 /* If getopt returns 0, then it has already processed a
78 long-named option. We should do nothing. */
79 break;
80
81 case 'n':
82 nowait = 1;
83 break;
84
85 case 'V':
86 fprintf (stderr, "Version %s\n", VERSION);
87 exit (1);
88 break;
89
90 case 'H':
91 default:
92 print_help_and_exit ();
93 }
94 }
95 }
96
97 print_help_and_exit ()
98 {
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);
105 }
106
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. */
111
112 char *
113 quote_file_name (name)
114 char *name;
115 {
116 char *copy = (char *) malloc (strlen (name) * 2 + 1);
117 char *p, *q;
118
119 p = name;
120 q = copy;
121 while (*p)
122 {
123 if (*p == ' ')
124 {
125 *q++ = '&';
126 *q++ = '_';
127 p++;
128 }
129 else
130 {
131 if (*p == '&' || (*p == '-' && p == name))
132 *q++ = '&';
133 *q++ = *p++;
134 }
135 }
136 *q++ = 0;
137
138 return copy;
139 }
140
141 #ifdef C_ALLOCA
142 /* Like malloc but get fatal error if memory is exhausted. */
143
144 char *
145 xmalloc (size)
146 unsigned int size;
147 {
148 char *result = (char *) malloc (size);
149 if (result == NULL)
150 {
151 perror ("malloc");
152 exit (1);
153 }
154 return result;
155 }
156 #endif /* C_ALLOCA */
157 \f
158 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
159
160 main (argc, argv)
161 int argc;
162 char **argv;
163 {
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);
168 }
169
170 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
171
172 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
173 /* BSD code is very different from SYSV IPC code */
174
175 #include <sys/types.h>
176 #include <sys/socket.h>
177 #include <sys/un.h>
178 #include <sys/stat.h>
179 #include <errno.h>
180
181 extern char *strerror ();
182 extern int errno;
183
184 int
185 main (argc, argv)
186 int argc;
187 char **argv;
188 {
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];
195
196 progname = argv[0];
197
198 /* Process options. */
199 decode_options (argc, argv);
200
201 if (argc - optind < 1)
202 print_help_and_exit ();
203
204 /*
205 * Open up an AF_UNIX socket in this person's home directory
206 */
207
208 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
209 {
210 fprintf (stderr, "%s: ", argv[0]);
211 perror ("socket");
212 exit (1);
213 }
214 server.sun_family = AF_UNIX;
215 #ifndef SERVER_HOME_DIR
216 {
217 struct stat statbfr;
218
219 gethostname (system_name, sizeof (system_name));
220 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
221
222 if (stat (server.sun_path, &statbfr) == -1)
223 {
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);
232 }
233 if (statbfr.st_uid != geteuid ())
234 {
235 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
236 exit (1);
237 }
238 }
239 #else
240 if ((homedir = getenv ("HOME")) == NULL)
241 {
242 fprintf (stderr, "%s: No home directory\n", argv[0]);
243 exit (1);
244 }
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
250
251 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
252 < 0)
253 {
254 fprintf (stderr, "%s: ", argv[0]);
255 perror ("connect");
256 exit (1);
257 }
258
259 /* We use the stream OUT to send our command to the server. */
260 if ((out = fdopen (s, "r+")) == NULL)
261 {
262 fprintf (stderr, "%s: ", argv[0]);
263 perror ("fdopen");
264 exit (1);
265 }
266
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)
273 {
274 fprintf (stderr, "%s: ", argv[0]);
275 perror ("fdopen");
276 exit (1);
277 }
278
279 #ifdef BSD_SYSTEM
280 cwd = getwd (string);
281 #else
282 cwd = getcwd (string, sizeof string);
283 #endif
284 if (cwd == 0)
285 {
286 /* getwd puts message in STRING if it fails. */
287 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
288 exit (1);
289 }
290
291 if (nowait)
292 fprintf (out, "-nowait ");
293
294 for (i = optind; i < argc; i++)
295 {
296 if (*argv[i] == '+')
297 {
298 char *p = argv[i] + 1;
299 while (*p >= '0' && *p <= '9') p++;
300 if (*p != 0)
301 fprintf (out, "%s/", cwd);
302 }
303 else if (*argv[i] != '/')
304 fprintf (out, "%s/", cwd);
305
306 fprintf (out, "%s ", quote_file_name (argv[i]));
307 }
308 fprintf (out, "\n");
309 fflush (out);
310
311 /* Maybe wait for an answer. */
312 if (nowait)
313 return 0;
314
315 printf ("Waiting for Emacs...");
316 fflush (stdout);
317
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. */
322
323 while (str = fgets (string, BUFSIZ, in))
324 printf ("%s", str);
325
326 return 0;
327 }
328
329 #else /* This is the SYSV IPC section */
330
331 #include <sys/types.h>
332 #include <sys/ipc.h>
333 #include <sys/msg.h>
334 #include <sys/utsname.h>
335 #include <stdio.h>
336
337 char *getwd (), *getcwd (), *getenv ();
338 struct utsname system_name;
339
340 main (argc, argv)
341 int argc;
342 char **argv;
343 {
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;
357
358 progname = argv[0];
359
360 /* Process options. */
361 decode_options (argc, argv);
362
363 if (argc - optind < 1)
364 print_help_and_exit ();
365
366 /*
367 * Create a message queue using ~/.emacs-server as the path for ftok
368 */
369 if ((homedir = getenv ("HOME")) == NULL)
370 {
371 fprintf (stderr, "%s: No home directory\n", argv[0]);
372 exit (1);
373 }
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)
387 {
388 fprintf (stderr, "%s: ", argv[0]);
389 perror ("msgget");
390 exit (1);
391 }
392
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
399
400 cwd = gwdirb;
401 if (temp != 0)
402 {
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, "/");
408 }
409 else
410 {
411 fprintf (stderr, "%s: %s\n", argv[0], cwd);
412 exit (1);
413 }
414
415 msgp->mtext[0] = 0;
416 used = 0;
417
418 if (nowait)
419 {
420 strcat (msgp->mtext, "-nowait ");
421 used += 8;
422 }
423
424 argc -= optind;
425 argv += optind;
426
427 while (argc)
428 {
429 int need_cwd = 0;
430 char *modified_arg = argv[0];
431
432 if (*modified_arg == '+')
433 {
434 char *p = modified_arg + 1;
435 while (*p >= '0' && *p <= '9') p++;
436 if (*p != 0)
437 need_cwd = 1;
438 }
439 else if (*modified_arg != '/')
440 need_cwd = 1;
441
442 modified_arg = quote_file_name (modified_arg);
443
444 if (need_cwd)
445 used += strlen (cwd);
446 used += strlen (modified_arg) + 1;
447 while (used + 2 > size_allocated)
448 {
449 size_allocated *= 2;
450 msgp = (struct msgbuf *) realloc (msgp,
451 (sizeof (struct msgbuf)
452 + size_allocated));
453 }
454
455 if (need_cwd)
456 strcat (msgp->mtext, cwd);
457
458 strcat (msgp->mtext, modified_arg);
459 strcat (msgp->mtext, " ");
460 argv++; argc--;
461 }
462 strcat (msgp->mtext, "\n");
463 #ifdef HPUX /* HPUX has a bug. */
464 if (strlen (msgp->mtext) >= 512)
465 {
466 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
467 exit (1);
468 }
469 #endif
470 msgp->mtype = 1;
471 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
472 {
473 fprintf (stderr, "%s: ", progname);
474 perror ("msgsnd");
475 exit (1);
476 }
477
478 /* Maybe wait for an answer. */
479 if (nowait)
480 return 0;
481
482 printf ("Waiting for Emacs...");
483 fflush (stdout);
484
485 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
486 strcpy (buf, msgp->mtext);
487
488 printf ("\n");
489 if (*buf)
490 printf ("%s\n", buf);
491 exit (0);
492 }
493
494 #endif /* HAVE_SYSVIPC */
495
496 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
497 \f
498 #ifndef HAVE_STRERROR
499 char *
500 strerror (errnum)
501 int errnum;
502 {
503 extern char *sys_errlist[];
504 extern int sys_nerr;
505
506 if (errnum >= 0 && errnum < sys_nerr)
507 return sys_errlist[errnum];
508 return (char *) "Unknown error";
509 }
510
511 #endif /* ! HAVE_STRERROR */