]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
[HAVE_SYSVIPC]: Include errno.h, as in the other case.
[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],
288 #ifdef BSD_SYSTEM
289 string,
290 #else
291 "Cannot get current working directory",
292 #endif
293 strerror (errno));
294 exit (1);
295 }
296
297 if (nowait)
298 fprintf (out, "-nowait ");
299
300 for (i = optind; i < argc; i++)
301 {
302 if (*argv[i] == '+')
303 {
304 char *p = argv[i] + 1;
305 while (*p >= '0' && *p <= '9') p++;
306 if (*p != 0)
307 fprintf (out, "%s/", cwd);
308 }
309 else if (*argv[i] != '/')
310 fprintf (out, "%s/", cwd);
311
312 fprintf (out, "%s ", quote_file_name (argv[i]));
313 }
314 fprintf (out, "\n");
315 fflush (out);
316
317 /* Maybe wait for an answer. */
318 if (nowait)
319 return 0;
320
321 printf ("Waiting for Emacs...");
322 fflush (stdout);
323
324 /* Now, wait for an answer and print any messages. On some systems,
325 the first line we read will actually be the output we just sent.
326 We can't predict whether that will happen, so if it does, we
327 detect it by recognizing `Client: ' at the beginning. */
328
329 while (str = fgets (string, BUFSIZ, in))
330 printf ("%s", str);
331
332 return 0;
333 }
334
335 #else /* This is the SYSV IPC section */
336
337 #include <sys/types.h>
338 #include <sys/ipc.h>
339 #include <sys/msg.h>
340 #include <sys/utsname.h>
341 #include <stdio.h>
342 #include <errno.h>
343 extern int errno;
344
345 char *getwd (), *getcwd (), *getenv ();
346 struct utsname system_name;
347
348 main (argc, argv)
349 int argc;
350 char **argv;
351 {
352 int s;
353 key_t key;
354 /* Size of text allocated in MSGP. */
355 int size_allocated = BUFSIZ;
356 /* Amount of text used in MSGP. */
357 int used;
358 struct msgbuf *msgp
359 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
360 struct msqid_ds * msg_st;
361 char *homedir, buf[BUFSIZ];
362 char gwdirb[BUFSIZ];
363 char *cwd;
364 char *temp;
365
366 progname = argv[0];
367
368 /* Process options. */
369 decode_options (argc, argv);
370
371 if (argc - optind < 1)
372 print_help_and_exit ();
373
374 /*
375 * Create a message queue using ~/.emacs-server as the path for ftok
376 */
377 if ((homedir = getenv ("HOME")) == NULL)
378 {
379 fprintf (stderr, "%s: No home directory\n", argv[0]);
380 exit (1);
381 }
382 strcpy (buf, homedir);
383 #ifndef HAVE_LONG_FILE_NAMES
384 /* If file names are short, we can't fit the host name. */
385 strcat (buf, "/.emacs-server");
386 #else
387 strcat (buf, "/.emacs-server-");
388 uname (&system_name);
389 strcat (buf, system_name.nodename);
390 #endif
391 creat (buf, 0600);
392 key = ftok (buf, 1); /* unlikely to be anyone else using it */
393 s = msgget (key, 0600 | IPC_CREAT);
394 if (s == -1)
395 {
396 fprintf (stderr, "%s: ", argv[0]);
397 perror ("msgget");
398 exit (1);
399 }
400
401 /* Determine working dir, so we can prefix it to all the arguments. */
402 #ifdef BSD_SYSTEM
403 temp = getwd (gwdirb);
404 #else
405 temp = getcwd (gwdirb, sizeof gwdirb);
406 #endif
407
408 cwd = gwdirb;
409 if (temp != 0)
410 {
411 /* On some systems, cwd can look like `@machine/...';
412 ignore everything before the first slash in such a case. */
413 while (*cwd && *cwd != '/')
414 cwd++;
415 strcat (cwd, "/");
416 }
417 else
418 {
419 #ifdef BSD_SYSTEM
420 fprintf (stderr, "%s: %s\n", argv[0], cwd);
421 #else
422 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
423 argv[0], strerror (errno));
424 #endif
425 exit (1);
426 }
427
428 msgp->mtext[0] = 0;
429 used = 0;
430
431 if (nowait)
432 {
433 strcat (msgp->mtext, "-nowait ");
434 used += 8;
435 }
436
437 argc -= optind;
438 argv += optind;
439
440 while (argc)
441 {
442 int need_cwd = 0;
443 char *modified_arg = argv[0];
444
445 if (*modified_arg == '+')
446 {
447 char *p = modified_arg + 1;
448 while (*p >= '0' && *p <= '9') p++;
449 if (*p != 0)
450 need_cwd = 1;
451 }
452 else if (*modified_arg != '/')
453 need_cwd = 1;
454
455 modified_arg = quote_file_name (modified_arg);
456
457 if (need_cwd)
458 used += strlen (cwd);
459 used += strlen (modified_arg) + 1;
460 while (used + 2 > size_allocated)
461 {
462 size_allocated *= 2;
463 msgp = (struct msgbuf *) realloc (msgp,
464 (sizeof (struct msgbuf)
465 + size_allocated));
466 }
467
468 if (need_cwd)
469 strcat (msgp->mtext, cwd);
470
471 strcat (msgp->mtext, modified_arg);
472 strcat (msgp->mtext, " ");
473 argv++; argc--;
474 }
475 strcat (msgp->mtext, "\n");
476 #ifdef HPUX /* HPUX has a bug. */
477 if (strlen (msgp->mtext) >= 512)
478 {
479 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
480 exit (1);
481 }
482 #endif
483 msgp->mtype = 1;
484 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
485 {
486 fprintf (stderr, "%s: ", progname);
487 perror ("msgsnd");
488 exit (1);
489 }
490
491 /* Maybe wait for an answer. */
492 if (nowait)
493 return 0;
494
495 printf ("Waiting for Emacs...");
496 fflush (stdout);
497
498 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
499 strcpy (buf, msgp->mtext);
500
501 printf ("\n");
502 if (*buf)
503 printf ("%s\n", buf);
504 exit (0);
505 }
506
507 #endif /* HAVE_SYSVIPC */
508
509 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
510 \f
511 #ifndef HAVE_STRERROR
512 char *
513 strerror (errnum)
514 int errnum;
515 {
516 extern char *sys_errlist[];
517 extern int sys_nerr;
518
519 if (errnum >= 0 && errnum < sys_nerr)
520 return sys_errlist[errnum];
521 return (char *) "Unknown error";
522 }
523
524 #endif /* ! HAVE_STRERROR */