Include errno.h.
[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. */
92af894f 287 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
46cec291
RS
288 exit (1);
289 }
290
5212210c
RS
291 if (nowait)
292 fprintf (out, "-nowait ");
292d74a3 293
5212210c
RS
294 for (i = optind; i < argc; i++)
295 {
46cec291
RS
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);
5212210c
RS
305
306 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
307 }
308 fprintf (out, "\n");
309 fflush (out);
310
292d74a3
RS
311 /* Maybe wait for an answer. */
312 if (nowait)
313 return 0;
314
46cec291
RS
315 printf ("Waiting for Emacs...");
316 fflush (stdout);
317
23a7488d
RS
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. */
46cec291 322
23a7488d 323 while (str = fgets (string, BUFSIZ, in))
46cec291 324 printf ("%s", str);
23a7488d 325
340ff9de 326 return 0;
46cec291
RS
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>
b135a7cf 334#include <sys/utsname.h>
46cec291
RS
335#include <stdio.h>
336
1518a9eb 337char *getwd (), *getcwd (), *getenv ();
b135a7cf 338struct utsname system_name;
1518a9eb 339
46cec291
RS
340main (argc, argv)
341 int argc;
342 char **argv;
343{
344 int s;
345 key_t key;
1518a9eb
RS
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);
46cec291
RS
352 struct msqid_ds * msg_st;
353 char *homedir, buf[BUFSIZ];
354 char gwdirb[BUFSIZ];
355 char *cwd;
356 char *temp;
8f9aaa0a
RS
357
358 progname = argv[0];
359
360 /* Process options. */
5212210c 361 decode_options (argc, argv);
46cec291 362
5212210c 363 if (argc - optind < 1)
8f9aaa0a 364 print_help_and_exit ();
46cec291
RS
365
366 /*
b135a7cf 367 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
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);
b135a7cf
RS
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
46cec291
RS
383 creat (buf, 0600);
384 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 385 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
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. */
e397a017 394#ifdef BSD_SYSTEM
46cec291
RS
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 {
26396b1b 411 fprintf (stderr, "%s: %s\n", argv[0], cwd);
46cec291
RS
412 exit (1);
413 }
414
415 msgp->mtext[0] = 0;
1518a9eb 416 used = 0;
5212210c
RS
417
418 if (nowait)
419 {
420 strcat (msgp->mtext, "-nowait ");
421 used += 8;
422 }
423
424 argc -= optind;
425 argv += optind;
426
46cec291
RS
427 while (argc)
428 {
1518a9eb 429 int need_cwd = 0;
cd33a5a0 430 char *modified_arg = argv[0];
292d74a3 431
5212210c 432 if (*modified_arg == '+')
46cec291 433 {
cd33a5a0 434 char *p = modified_arg + 1;
46cec291
RS
435 while (*p >= '0' && *p <= '9') p++;
436 if (*p != 0)
1518a9eb 437 need_cwd = 1;
46cec291 438 }
cd33a5a0 439 else if (*modified_arg != '/')
1518a9eb
RS
440 need_cwd = 1;
441
5212210c
RS
442 modified_arg = quote_file_name (modified_arg);
443
1518a9eb
RS
444 if (need_cwd)
445 used += strlen (cwd);
cd33a5a0 446 used += strlen (modified_arg) + 1;
1518a9eb
RS
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)
46cec291
RS
456 strcat (msgp->mtext, cwd);
457
cd33a5a0 458 strcat (msgp->mtext, modified_arg);
46cec291
RS
459 strcat (msgp->mtext, " ");
460 argv++; argc--;
461 }
462 strcat (msgp->mtext, "\n");
1518a9eb
RS
463#ifdef HPUX /* HPUX has a bug. */
464 if (strlen (msgp->mtext) >= 512)
465 {
18a2fa91 466 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
467 exit (1);
468 }
469#endif
46cec291
RS
470 msgp->mtype = 1;
471 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
472 {
defb80d7 473 fprintf (stderr, "%s: ", progname);
46cec291
RS
474 perror ("msgsnd");
475 exit (1);
476 }
292d74a3
RS
477
478 /* Maybe wait for an answer. */
479 if (nowait)
480 return 0;
481
46cec291
RS
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
dc3c30fe
KH
488 printf ("\n");
489 if (*buf)
490 printf ("%s\n", buf);
46cec291
RS
491 exit (0);
492}
493
494#endif /* HAVE_SYSVIPC */
495
496#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
497\f
498#ifndef HAVE_STRERROR
499char *
500strerror (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 */