Include <stdlib.h> if available.
[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>
32
33char *getenv (), *getwd ();
34char *getcwd ();
35int 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. */
45char *progname;
46
749ae770 47/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
48int nowait = 0;
49
50struct option longopts[] =
51{
749ae770 52 { "no-wait", no_argument, NULL, 'n' },
8f9aaa0a
RS
53 { "help", no_argument, NULL, 'H' },
54 { "version", no_argument, NULL, 'V' },
55 { 0 }
56};
57
58/* Decode the options from argv and argc.
5212210c 59 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 60
5212210c 61void
8f9aaa0a
RS
62decode_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;
46cec291 89
8f9aaa0a
RS
90 case 'H':
91 default:
92 print_help_and_exit ();
93 }
94 }
8f9aaa0a
RS
95}
96
97print_help_and_exit ()
98{
99 fprintf (stderr,
749ae770 100 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
8f9aaa0a
RS
101 progname);
102 fprintf (stderr,
103 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
104 exit (1);
105}
5212210c 106
f1db6a73
RS
107/* Return a copy of NAME, inserting a &
108 before each &, each space, and any initial -.
5212210c
RS
109 Change spaces to underscores, too, so that the
110 return value never contains a space. */
111
112char *
113quote_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 {
f1db6a73 125 *q++ = '&';
5212210c
RS
126 *q++ = '_';
127 p++;
128 }
129 else
130 {
f1db6a73
RS
131 if (*p == '&' || (*p == '-' && p == name))
132 *q++ = '&';
5212210c
RS
133 *q++ = *p++;
134 }
135 }
f1db6a73 136 *q++ = 0;
5212210c
RS
137
138 return copy;
139}
0c76956f
RS
140
141#ifdef C_ALLOCA
142/* Like malloc but get fatal error if memory is exhausted. */
143
144char *
145xmalloc (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 */
8f9aaa0a 157\f
b135a7cf 158#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291
RS
159
160main (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
1e523e3d 172#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
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>
efb859b4 178#include <sys/stat.h>
46cec291
RS
179#include <errno.h>
180
92af894f 181extern char *strerror ();
46cec291
RS
182extern int errno;
183
340ff9de 184int
46cec291
RS
185main (argc, argv)
186 int argc;
187 char **argv;
188{
189 char system_name[32];
190 int s, i;
23a7488d 191 FILE *out, *in;
46cec291
RS
192 struct sockaddr_un server;
193 char *homedir, *cwd, *str;
194 char string[BUFSIZ];
8f9aaa0a
RS
195
196 progname = argv[0];
46cec291 197
8f9aaa0a 198 /* Process options. */
5212210c 199 decode_options (argc, argv);
46cec291 200
5212210c 201 if (argc - optind < 1)
8f9aaa0a 202 print_help_and_exit ();
46cec291
RS
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
efb859b4
JB
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 {
c0acc3e1
JB
224 if (errno == ENOENT)
225 fprintf (stderr,
18a2fa91
KH
226 "%s: can't find socket; have you started the server?\n",
227 argv[0]);
c0acc3e1 228 else
18a2fa91
KH
229 fprintf (stderr, "%s: can't stat %s: %s\n",
230 argv[0], server.sun_path, strerror (errno));
efb859b4
JB
231 exit (1);
232 }
b135a7cf 233 if (statbfr.st_uid != geteuid ())
efb859b4 234 {
18a2fa91 235 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
efb859b4
JB
236 exit (1);
237 }
238 }
46cec291
RS
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);
b135a7cf
RS
246 strcat (server.sun_path, "/.emacs-server-");
247 gethostname (system_name, sizeof (system_name));
248 strcat (server.sun_path, system_name);
46cec291
RS
249#endif
250
4e23f2ba
JB
251 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
252 < 0)
46cec291
RS
253 {
254 fprintf (stderr, "%s: ", argv[0]);
255 perror ("connect");
256 exit (1);
257 }
23a7488d
RS
258
259 /* We use the stream OUT to send our command to the server. */
46cec291
RS
260 if ((out = fdopen (s, "r+")) == NULL)
261 {
262 fprintf (stderr, "%s: ", argv[0]);
263 perror ("fdopen");
264 exit (1);
265 }
266
23a7488d
RS
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
e397a017 279#ifdef BSD_SYSTEM
46cec291 280 cwd = getwd (string);
ee6a193c
RS
281#else
282 cwd = getcwd (string, sizeof string);
283#endif
46cec291
RS
284 if (cwd == 0)
285 {
286 /* getwd puts message in STRING if it fails. */
bd252662
RS
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));
46cec291
RS
294 exit (1);
295 }
296
5212210c
RS
297 if (nowait)
298 fprintf (out, "-nowait ");
292d74a3 299
5212210c
RS
300 for (i = optind; i < argc; i++)
301 {
46cec291
RS
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);
5212210c
RS
311
312 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
313 }
314 fprintf (out, "\n");
315 fflush (out);
316
292d74a3
RS
317 /* Maybe wait for an answer. */
318 if (nowait)
319 return 0;
320
46cec291
RS
321 printf ("Waiting for Emacs...");
322 fflush (stdout);
323
23a7488d
RS
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. */
46cec291 328
23a7488d 329 while (str = fgets (string, BUFSIZ, in))
46cec291 330 printf ("%s", str);
23a7488d 331
340ff9de 332 return 0;
46cec291
RS
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>
b135a7cf 340#include <sys/utsname.h>
46cec291 341#include <stdio.h>
bd252662
RS
342#include <errno.h>
343extern int errno;
46cec291 344
1518a9eb 345char *getwd (), *getcwd (), *getenv ();
b135a7cf 346struct utsname system_name;
1518a9eb 347
46cec291
RS
348main (argc, argv)
349 int argc;
350 char **argv;
351{
352 int s;
353 key_t key;
1518a9eb
RS
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);
46cec291
RS
360 struct msqid_ds * msg_st;
361 char *homedir, buf[BUFSIZ];
362 char gwdirb[BUFSIZ];
363 char *cwd;
364 char *temp;
8f9aaa0a
RS
365
366 progname = argv[0];
367
368 /* Process options. */
5212210c 369 decode_options (argc, argv);
46cec291 370
5212210c 371 if (argc - optind < 1)
8f9aaa0a 372 print_help_and_exit ();
46cec291
RS
373
374 /*
b135a7cf 375 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
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);
b135a7cf
RS
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
46cec291
RS
391 creat (buf, 0600);
392 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 393 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
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. */
e397a017 402#ifdef BSD_SYSTEM
46cec291
RS
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 {
bd252662 419#ifdef BSD_SYSTEM
26396b1b 420 fprintf (stderr, "%s: %s\n", argv[0], cwd);
bd252662
RS
421#else
422 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
423 argv[0], strerror (errno));
424#endif
46cec291
RS
425 exit (1);
426 }
427
428 msgp->mtext[0] = 0;
1518a9eb 429 used = 0;
5212210c
RS
430
431 if (nowait)
432 {
433 strcat (msgp->mtext, "-nowait ");
434 used += 8;
435 }
436
437 argc -= optind;
438 argv += optind;
439
46cec291
RS
440 while (argc)
441 {
1518a9eb 442 int need_cwd = 0;
cd33a5a0 443 char *modified_arg = argv[0];
292d74a3 444
5212210c 445 if (*modified_arg == '+')
46cec291 446 {
cd33a5a0 447 char *p = modified_arg + 1;
46cec291
RS
448 while (*p >= '0' && *p <= '9') p++;
449 if (*p != 0)
1518a9eb 450 need_cwd = 1;
46cec291 451 }
cd33a5a0 452 else if (*modified_arg != '/')
1518a9eb
RS
453 need_cwd = 1;
454
5212210c
RS
455 modified_arg = quote_file_name (modified_arg);
456
1518a9eb
RS
457 if (need_cwd)
458 used += strlen (cwd);
cd33a5a0 459 used += strlen (modified_arg) + 1;
1518a9eb
RS
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)
46cec291
RS
469 strcat (msgp->mtext, cwd);
470
cd33a5a0 471 strcat (msgp->mtext, modified_arg);
46cec291
RS
472 strcat (msgp->mtext, " ");
473 argv++; argc--;
474 }
475 strcat (msgp->mtext, "\n");
1518a9eb
RS
476#ifdef HPUX /* HPUX has a bug. */
477 if (strlen (msgp->mtext) >= 512)
478 {
18a2fa91 479 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
480 exit (1);
481 }
482#endif
46cec291
RS
483 msgp->mtype = 1;
484 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
485 {
defb80d7 486 fprintf (stderr, "%s: ", progname);
46cec291
RS
487 perror ("msgsnd");
488 exit (1);
489 }
292d74a3
RS
490
491 /* Maybe wait for an answer. */
492 if (nowait)
493 return 0;
494
46cec291
RS
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
dc3c30fe
KH
501 printf ("\n");
502 if (*buf)
503 printf ("%s\n", buf);
46cec291
RS
504 exit (0);
505}
506
507#endif /* HAVE_SYSVIPC */
508
509#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
510\f
511#ifndef HAVE_STRERROR
512char *
513strerror (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 */