(ange-ftp-tmp-name-template): Use temporary-file-directory.
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
efb859b4 1/* Client process that communicates with GNU Emacs acting as server.
92af894f 2 Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
46cec291
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
92af894f 8the Free Software Foundation; either version 2, or (at your option)
46cec291
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
46cec291
RS
20
21
22#define NO_SHORTNAMES
18160b98 23#include <../src/config.h>
46cec291
RS
24#undef read
25#undef write
26#undef open
46cec291 27#undef close
4e23f2ba 28#undef signal
46cec291 29
8f9aaa0a
RS
30#include <stdio.h>
31#include <getopt.h>
7f3bff3e
AS
32#ifdef STDC_HEADERS
33#include <stdlib.h>
34#endif
79f13bba
DL
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
8f9aaa0a
RS
38
39char *getenv (), *getwd ();
40char *getcwd ();
8f9aaa0a
RS
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. */
50char *progname;
51
749ae770 52/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
53int nowait = 0;
54
7f3bff3e
AS
55void print_help_and_exit ();
56
8f9aaa0a
RS
57struct option longopts[] =
58{
749ae770 59 { "no-wait", no_argument, NULL, 'n' },
8f9aaa0a
RS
60 { "help", no_argument, NULL, 'H' },
61 { "version", no_argument, NULL, 'V' },
62 { 0 }
63};
64
65/* Decode the options from argv and argc.
5212210c 66 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 67
5212210c 68void
8f9aaa0a
RS
69decode_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;
46cec291 96
8f9aaa0a
RS
97 case 'H':
98 default:
99 print_help_and_exit ();
100 }
101 }
8f9aaa0a
RS
102}
103
7f3bff3e 104void
8f9aaa0a
RS
105print_help_and_exit ()
106{
107 fprintf (stderr,
749ae770 108 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
8f9aaa0a
RS
109 progname);
110 fprintf (stderr,
111 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
112 exit (1);
113}
5212210c 114
f1db6a73
RS
115/* Return a copy of NAME, inserting a &
116 before each &, each space, and any initial -.
5212210c
RS
117 Change spaces to underscores, too, so that the
118 return value never contains a space. */
119
120char *
121quote_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 {
f1db6a73 133 *q++ = '&';
5212210c
RS
134 *q++ = '_';
135 p++;
136 }
137 else
138 {
f1db6a73
RS
139 if (*p == '&' || (*p == '-' && p == name))
140 *q++ = '&';
5212210c
RS
141 *q++ = *p++;
142 }
143 }
f1db6a73 144 *q++ = 0;
5212210c
RS
145
146 return copy;
147}
0c76956f
RS
148
149#ifdef C_ALLOCA
150/* Like malloc but get fatal error if memory is exhausted. */
151
152char *
153xmalloc (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 */
8f9aaa0a 165\f
b135a7cf 166#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291
RS
167
168main (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
1e523e3d 180#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
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>
efb859b4 186#include <sys/stat.h>
46cec291
RS
187#include <errno.h>
188
92af894f 189extern char *strerror ();
46cec291
RS
190extern int errno;
191
340ff9de 192int
46cec291
RS
193main (argc, argv)
194 int argc;
195 char **argv;
196{
197 char system_name[32];
198 int s, i;
23a7488d 199 FILE *out, *in;
46cec291
RS
200 struct sockaddr_un server;
201 char *homedir, *cwd, *str;
202 char string[BUFSIZ];
8f9aaa0a
RS
203
204 progname = argv[0];
46cec291 205
8f9aaa0a 206 /* Process options. */
5212210c 207 decode_options (argc, argv);
46cec291 208
5212210c 209 if (argc - optind < 1)
8f9aaa0a 210 print_help_and_exit ();
46cec291
RS
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
efb859b4
JB
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 {
c0acc3e1
JB
232 if (errno == ENOENT)
233 fprintf (stderr,
18a2fa91
KH
234 "%s: can't find socket; have you started the server?\n",
235 argv[0]);
c0acc3e1 236 else
18a2fa91
KH
237 fprintf (stderr, "%s: can't stat %s: %s\n",
238 argv[0], server.sun_path, strerror (errno));
efb859b4
JB
239 exit (1);
240 }
b135a7cf 241 if (statbfr.st_uid != geteuid ())
efb859b4 242 {
18a2fa91 243 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
efb859b4
JB
244 exit (1);
245 }
246 }
46cec291
RS
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);
b135a7cf
RS
254 strcat (server.sun_path, "/.emacs-server-");
255 gethostname (system_name, sizeof (system_name));
256 strcat (server.sun_path, system_name);
46cec291
RS
257#endif
258
4e23f2ba
JB
259 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
260 < 0)
46cec291
RS
261 {
262 fprintf (stderr, "%s: ", argv[0]);
263 perror ("connect");
264 exit (1);
265 }
23a7488d
RS
266
267 /* We use the stream OUT to send our command to the server. */
46cec291
RS
268 if ((out = fdopen (s, "r+")) == NULL)
269 {
270 fprintf (stderr, "%s: ", argv[0]);
271 perror ("fdopen");
272 exit (1);
273 }
274
23a7488d
RS
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
e397a017 287#ifdef BSD_SYSTEM
46cec291 288 cwd = getwd (string);
ee6a193c
RS
289#else
290 cwd = getcwd (string, sizeof string);
291#endif
46cec291
RS
292 if (cwd == 0)
293 {
294 /* getwd puts message in STRING if it fails. */
bd252662
RS
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));
46cec291
RS
302 exit (1);
303 }
304
5212210c
RS
305 if (nowait)
306 fprintf (out, "-nowait ");
292d74a3 307
5212210c
RS
308 for (i = optind; i < argc; i++)
309 {
46cec291
RS
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);
5212210c
RS
319
320 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
321 }
322 fprintf (out, "\n");
323 fflush (out);
324
292d74a3
RS
325 /* Maybe wait for an answer. */
326 if (nowait)
327 return 0;
328
46cec291
RS
329 printf ("Waiting for Emacs...");
330 fflush (stdout);
331
23a7488d
RS
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. */
46cec291 336
23a7488d 337 while (str = fgets (string, BUFSIZ, in))
46cec291 338 printf ("%s", str);
23a7488d 339
340ff9de 340 return 0;
46cec291
RS
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>
b135a7cf 348#include <sys/utsname.h>
46cec291 349#include <stdio.h>
bd252662
RS
350#include <errno.h>
351extern int errno;
46cec291 352
1518a9eb 353char *getwd (), *getcwd (), *getenv ();
b135a7cf 354struct utsname system_name;
1518a9eb 355
46cec291
RS
356main (argc, argv)
357 int argc;
358 char **argv;
359{
360 int s;
361 key_t key;
1518a9eb
RS
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);
46cec291
RS
368 struct msqid_ds * msg_st;
369 char *homedir, buf[BUFSIZ];
370 char gwdirb[BUFSIZ];
371 char *cwd;
372 char *temp;
8f9aaa0a
RS
373
374 progname = argv[0];
375
376 /* Process options. */
5212210c 377 decode_options (argc, argv);
46cec291 378
5212210c 379 if (argc - optind < 1)
8f9aaa0a 380 print_help_and_exit ();
46cec291
RS
381
382 /*
b135a7cf 383 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
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);
b135a7cf
RS
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
46cec291
RS
399 creat (buf, 0600);
400 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 401 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
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. */
e397a017 410#ifdef BSD_SYSTEM
46cec291
RS
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 {
bd252662 427#ifdef BSD_SYSTEM
26396b1b 428 fprintf (stderr, "%s: %s\n", argv[0], cwd);
bd252662
RS
429#else
430 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
431 argv[0], strerror (errno));
432#endif
46cec291
RS
433 exit (1);
434 }
435
436 msgp->mtext[0] = 0;
1518a9eb 437 used = 0;
5212210c
RS
438
439 if (nowait)
440 {
441 strcat (msgp->mtext, "-nowait ");
442 used += 8;
443 }
444
445 argc -= optind;
446 argv += optind;
447
46cec291
RS
448 while (argc)
449 {
1518a9eb 450 int need_cwd = 0;
cd33a5a0 451 char *modified_arg = argv[0];
292d74a3 452
5212210c 453 if (*modified_arg == '+')
46cec291 454 {
cd33a5a0 455 char *p = modified_arg + 1;
46cec291
RS
456 while (*p >= '0' && *p <= '9') p++;
457 if (*p != 0)
1518a9eb 458 need_cwd = 1;
46cec291 459 }
cd33a5a0 460 else if (*modified_arg != '/')
1518a9eb
RS
461 need_cwd = 1;
462
5212210c
RS
463 modified_arg = quote_file_name (modified_arg);
464
1518a9eb
RS
465 if (need_cwd)
466 used += strlen (cwd);
cd33a5a0 467 used += strlen (modified_arg) + 1;
1518a9eb
RS
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)
46cec291
RS
477 strcat (msgp->mtext, cwd);
478
cd33a5a0 479 strcat (msgp->mtext, modified_arg);
46cec291
RS
480 strcat (msgp->mtext, " ");
481 argv++; argc--;
482 }
483 strcat (msgp->mtext, "\n");
1518a9eb
RS
484#ifdef HPUX /* HPUX has a bug. */
485 if (strlen (msgp->mtext) >= 512)
486 {
18a2fa91 487 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
488 exit (1);
489 }
490#endif
46cec291
RS
491 msgp->mtype = 1;
492 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
493 {
defb80d7 494 fprintf (stderr, "%s: ", progname);
46cec291
RS
495 perror ("msgsnd");
496 exit (1);
497 }
292d74a3
RS
498
499 /* Maybe wait for an answer. */
500 if (nowait)
501 return 0;
502
46cec291
RS
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
dc3c30fe
KH
509 printf ("\n");
510 if (*buf)
511 printf ("%s\n", buf);
46cec291
RS
512 exit (0);
513}
514
515#endif /* HAVE_SYSVIPC */
516
517#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
518\f
519#ifndef HAVE_STRERROR
520char *
521strerror (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 */