(ange-ftp-tmp-name-template): Use temporary-file-directory.
[bpt/emacs.git] / 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 #ifdef STDC_HEADERS
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
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 { 0 }
63 };
64
65 /* Decode the options from argv and argc.
66 The global variable `optind' will say how many arguments we used up. */
67
68 void
69 decode_options (argc, argv)
70 int argc;
71 char **argv;
72 {
73 while (1)
74 {
75 int opt = getopt_long (argc, argv,
76 "VHn", longopts, 0);
77
78 if (opt == EOF)
79 break;
80
81 switch (opt)
82 {
83 case 0:
84 /* If getopt returns 0, then it has already processed a
85 long-named option. We should do nothing. */
86 break;
87
88 case 'n':
89 nowait = 1;
90 break;
91
92 case 'V':
93 fprintf (stderr, "Version %s\n", VERSION);
94 exit (1);
95 break;
96
97 case 'H':
98 default:
99 print_help_and_exit ();
100 }
101 }
102 }
103
104 void
105 print_help_and_exit ()
106 {
107 fprintf (stderr,
108 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
109 progname);
110 fprintf (stderr,
111 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
112 exit (1);
113 }
114
115 /* Return a copy of NAME, inserting a &
116 before each &, each space, and any initial -.
117 Change spaces to underscores, too, so that the
118 return value never contains a space. */
119
120 char *
121 quote_file_name (name)
122 char *name;
123 {
124 char *copy = (char *) malloc (strlen (name) * 2 + 1);
125 char *p, *q;
126
127 p = name;
128 q = copy;
129 while (*p)
130 {
131 if (*p == ' ')
132 {
133 *q++ = '&';
134 *q++ = '_';
135 p++;
136 }
137 else
138 {
139 if (*p == '&' || (*p == '-' && p == name))
140 *q++ = '&';
141 *q++ = *p++;
142 }
143 }
144 *q++ = 0;
145
146 return copy;
147 }
148
149 #ifdef C_ALLOCA
150 /* Like malloc but get fatal error if memory is exhausted. */
151
152 char *
153 xmalloc (size)
154 unsigned int size;
155 {
156 char *result = (char *) malloc (size);
157 if (result == NULL)
158 {
159 perror ("malloc");
160 exit (1);
161 }
162 return result;
163 }
164 #endif /* C_ALLOCA */
165 \f
166 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
167
168 main (argc, argv)
169 int argc;
170 char **argv;
171 {
172 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
173 argv[0]);
174 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
175 exit (1);
176 }
177
178 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
179
180 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
181 /* BSD code is very different from SYSV IPC code */
182
183 #include <sys/types.h>
184 #include <sys/socket.h>
185 #include <sys/un.h>
186 #include <sys/stat.h>
187 #include <errno.h>
188
189 extern char *strerror ();
190 extern int errno;
191
192 int
193 main (argc, argv)
194 int argc;
195 char **argv;
196 {
197 char system_name[32];
198 int s, i;
199 FILE *out, *in;
200 struct sockaddr_un server;
201 char *homedir, *cwd, *str;
202 char string[BUFSIZ];
203
204 progname = argv[0];
205
206 /* Process options. */
207 decode_options (argc, argv);
208
209 if (argc - optind < 1)
210 print_help_and_exit ();
211
212 /*
213 * Open up an AF_UNIX socket in this person's home directory
214 */
215
216 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
217 {
218 fprintf (stderr, "%s: ", argv[0]);
219 perror ("socket");
220 exit (1);
221 }
222 server.sun_family = AF_UNIX;
223 #ifndef SERVER_HOME_DIR
224 {
225 struct stat statbfr;
226
227 gethostname (system_name, sizeof (system_name));
228 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
229
230 if (stat (server.sun_path, &statbfr) == -1)
231 {
232 if (errno == ENOENT)
233 fprintf (stderr,
234 "%s: can't find socket; have you started the server?\n",
235 argv[0]);
236 else
237 fprintf (stderr, "%s: can't stat %s: %s\n",
238 argv[0], server.sun_path, strerror (errno));
239 exit (1);
240 }
241 if (statbfr.st_uid != geteuid ())
242 {
243 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
244 exit (1);
245 }
246 }
247 #else
248 if ((homedir = getenv ("HOME")) == NULL)
249 {
250 fprintf (stderr, "%s: No home directory\n", argv[0]);
251 exit (1);
252 }
253 strcpy (server.sun_path, homedir);
254 strcat (server.sun_path, "/.emacs-server-");
255 gethostname (system_name, sizeof (system_name));
256 strcat (server.sun_path, system_name);
257 #endif
258
259 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
260 < 0)
261 {
262 fprintf (stderr, "%s: ", argv[0]);
263 perror ("connect");
264 exit (1);
265 }
266
267 /* We use the stream OUT to send our command to the server. */
268 if ((out = fdopen (s, "r+")) == NULL)
269 {
270 fprintf (stderr, "%s: ", argv[0]);
271 perror ("fdopen");
272 exit (1);
273 }
274
275 /* We use the stream IN to read the response.
276 We used to use just one stream for both output and input
277 on the socket, but reversing direction works nonportably:
278 on some systems, the output appears as the first input;
279 on other systems it does not. */
280 if ((in = fdopen (s, "r+")) == NULL)
281 {
282 fprintf (stderr, "%s: ", argv[0]);
283 perror ("fdopen");
284 exit (1);
285 }
286
287 #ifdef BSD_SYSTEM
288 cwd = getwd (string);
289 #else
290 cwd = getcwd (string, sizeof string);
291 #endif
292 if (cwd == 0)
293 {
294 /* getwd puts message in STRING if it fails. */
295 fprintf (stderr, "%s: %s (%s)\n", argv[0],
296 #ifdef BSD_SYSTEM
297 string,
298 #else
299 "Cannot get current working directory",
300 #endif
301 strerror (errno));
302 exit (1);
303 }
304
305 if (nowait)
306 fprintf (out, "-nowait ");
307
308 for (i = optind; i < argc; i++)
309 {
310 if (*argv[i] == '+')
311 {
312 char *p = argv[i] + 1;
313 while (*p >= '0' && *p <= '9') p++;
314 if (*p != 0)
315 fprintf (out, "%s/", cwd);
316 }
317 else if (*argv[i] != '/')
318 fprintf (out, "%s/", cwd);
319
320 fprintf (out, "%s ", quote_file_name (argv[i]));
321 }
322 fprintf (out, "\n");
323 fflush (out);
324
325 /* Maybe wait for an answer. */
326 if (nowait)
327 return 0;
328
329 printf ("Waiting for Emacs...");
330 fflush (stdout);
331
332 /* Now, wait for an answer and print any messages. On some systems,
333 the first line we read will actually be the output we just sent.
334 We can't predict whether that will happen, so if it does, we
335 detect it by recognizing `Client: ' at the beginning. */
336
337 while (str = fgets (string, BUFSIZ, in))
338 printf ("%s", str);
339
340 return 0;
341 }
342
343 #else /* This is the SYSV IPC section */
344
345 #include <sys/types.h>
346 #include <sys/ipc.h>
347 #include <sys/msg.h>
348 #include <sys/utsname.h>
349 #include <stdio.h>
350 #include <errno.h>
351 extern int errno;
352
353 char *getwd (), *getcwd (), *getenv ();
354 struct utsname system_name;
355
356 main (argc, argv)
357 int argc;
358 char **argv;
359 {
360 int s;
361 key_t key;
362 /* Size of text allocated in MSGP. */
363 int size_allocated = BUFSIZ;
364 /* Amount of text used in MSGP. */
365 int used;
366 struct msgbuf *msgp
367 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
368 struct msqid_ds * msg_st;
369 char *homedir, buf[BUFSIZ];
370 char gwdirb[BUFSIZ];
371 char *cwd;
372 char *temp;
373
374 progname = argv[0];
375
376 /* Process options. */
377 decode_options (argc, argv);
378
379 if (argc - optind < 1)
380 print_help_and_exit ();
381
382 /*
383 * Create a message queue using ~/.emacs-server as the path for ftok
384 */
385 if ((homedir = getenv ("HOME")) == NULL)
386 {
387 fprintf (stderr, "%s: No home directory\n", argv[0]);
388 exit (1);
389 }
390 strcpy (buf, homedir);
391 #ifndef HAVE_LONG_FILE_NAMES
392 /* If file names are short, we can't fit the host name. */
393 strcat (buf, "/.emacs-server");
394 #else
395 strcat (buf, "/.emacs-server-");
396 uname (&system_name);
397 strcat (buf, system_name.nodename);
398 #endif
399 creat (buf, 0600);
400 key = ftok (buf, 1); /* unlikely to be anyone else using it */
401 s = msgget (key, 0600 | IPC_CREAT);
402 if (s == -1)
403 {
404 fprintf (stderr, "%s: ", argv[0]);
405 perror ("msgget");
406 exit (1);
407 }
408
409 /* Determine working dir, so we can prefix it to all the arguments. */
410 #ifdef BSD_SYSTEM
411 temp = getwd (gwdirb);
412 #else
413 temp = getcwd (gwdirb, sizeof gwdirb);
414 #endif
415
416 cwd = gwdirb;
417 if (temp != 0)
418 {
419 /* On some systems, cwd can look like `@machine/...';
420 ignore everything before the first slash in such a case. */
421 while (*cwd && *cwd != '/')
422 cwd++;
423 strcat (cwd, "/");
424 }
425 else
426 {
427 #ifdef BSD_SYSTEM
428 fprintf (stderr, "%s: %s\n", argv[0], cwd);
429 #else
430 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
431 argv[0], strerror (errno));
432 #endif
433 exit (1);
434 }
435
436 msgp->mtext[0] = 0;
437 used = 0;
438
439 if (nowait)
440 {
441 strcat (msgp->mtext, "-nowait ");
442 used += 8;
443 }
444
445 argc -= optind;
446 argv += optind;
447
448 while (argc)
449 {
450 int need_cwd = 0;
451 char *modified_arg = argv[0];
452
453 if (*modified_arg == '+')
454 {
455 char *p = modified_arg + 1;
456 while (*p >= '0' && *p <= '9') p++;
457 if (*p != 0)
458 need_cwd = 1;
459 }
460 else if (*modified_arg != '/')
461 need_cwd = 1;
462
463 modified_arg = quote_file_name (modified_arg);
464
465 if (need_cwd)
466 used += strlen (cwd);
467 used += strlen (modified_arg) + 1;
468 while (used + 2 > size_allocated)
469 {
470 size_allocated *= 2;
471 msgp = (struct msgbuf *) realloc (msgp,
472 (sizeof (struct msgbuf)
473 + size_allocated));
474 }
475
476 if (need_cwd)
477 strcat (msgp->mtext, cwd);
478
479 strcat (msgp->mtext, modified_arg);
480 strcat (msgp->mtext, " ");
481 argv++; argc--;
482 }
483 strcat (msgp->mtext, "\n");
484 #ifdef HPUX /* HPUX has a bug. */
485 if (strlen (msgp->mtext) >= 512)
486 {
487 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
488 exit (1);
489 }
490 #endif
491 msgp->mtype = 1;
492 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
493 {
494 fprintf (stderr, "%s: ", progname);
495 perror ("msgsnd");
496 exit (1);
497 }
498
499 /* Maybe wait for an answer. */
500 if (nowait)
501 return 0;
502
503 printf ("Waiting for Emacs...");
504 fflush (stdout);
505
506 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
507 strcpy (buf, msgp->mtext);
508
509 printf ("\n");
510 if (*buf)
511 printf ("%s\n", buf);
512 exit (0);
513 }
514
515 #endif /* HAVE_SYSVIPC */
516
517 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
518 \f
519 #ifndef HAVE_STRERROR
520 char *
521 strerror (errnum)
522 int errnum;
523 {
524 extern char *sys_errlist[];
525 extern int sys_nerr;
526
527 if (errnum >= 0 && errnum < sys_nerr)
528 return sys_errlist[errnum];
529 return (char *) "Unknown error";
530 }
531
532 #endif /* ! HAVE_STRERROR */