(menu-bar-custom-menu): Add several more menu items.
[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}
8f9aaa0a 140\f
b135a7cf 141#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291
RS
142
143main (argc, argv)
144 int argc;
145 char **argv;
146{
147 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
148 argv[0]);
149 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
150 exit (1);
151}
152
153#else /* HAVE_SOCKETS or HAVE_SYSVIPC */
154
1e523e3d 155#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
156/* BSD code is very different from SYSV IPC code */
157
158#include <sys/types.h>
159#include <sys/socket.h>
160#include <sys/un.h>
efb859b4 161#include <sys/stat.h>
46cec291
RS
162#include <errno.h>
163
92af894f 164extern char *strerror ();
46cec291
RS
165extern int errno;
166
340ff9de 167int
46cec291
RS
168main (argc, argv)
169 int argc;
170 char **argv;
171{
172 char system_name[32];
173 int s, i;
23a7488d 174 FILE *out, *in;
46cec291
RS
175 struct sockaddr_un server;
176 char *homedir, *cwd, *str;
177 char string[BUFSIZ];
8f9aaa0a
RS
178
179 progname = argv[0];
46cec291 180
8f9aaa0a 181 /* Process options. */
5212210c 182 decode_options (argc, argv);
46cec291 183
5212210c 184 if (argc - optind < 1)
8f9aaa0a 185 print_help_and_exit ();
46cec291
RS
186
187 /*
188 * Open up an AF_UNIX socket in this person's home directory
189 */
190
191 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
192 {
193 fprintf (stderr, "%s: ", argv[0]);
194 perror ("socket");
195 exit (1);
196 }
197 server.sun_family = AF_UNIX;
198#ifndef SERVER_HOME_DIR
efb859b4
JB
199 {
200 struct stat statbfr;
201
202 gethostname (system_name, sizeof (system_name));
203 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
204
205 if (stat (server.sun_path, &statbfr) == -1)
206 {
c0acc3e1
JB
207 if (errno == ENOENT)
208 fprintf (stderr,
18a2fa91
KH
209 "%s: can't find socket; have you started the server?\n",
210 argv[0]);
c0acc3e1 211 else
18a2fa91
KH
212 fprintf (stderr, "%s: can't stat %s: %s\n",
213 argv[0], server.sun_path, strerror (errno));
efb859b4
JB
214 exit (1);
215 }
b135a7cf 216 if (statbfr.st_uid != geteuid ())
efb859b4 217 {
18a2fa91 218 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
efb859b4
JB
219 exit (1);
220 }
221 }
46cec291
RS
222#else
223 if ((homedir = getenv ("HOME")) == NULL)
224 {
225 fprintf (stderr, "%s: No home directory\n", argv[0]);
226 exit (1);
227 }
228 strcpy (server.sun_path, homedir);
b135a7cf
RS
229 strcat (server.sun_path, "/.emacs-server-");
230 gethostname (system_name, sizeof (system_name));
231 strcat (server.sun_path, system_name);
46cec291
RS
232#endif
233
4e23f2ba
JB
234 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
235 < 0)
46cec291
RS
236 {
237 fprintf (stderr, "%s: ", argv[0]);
238 perror ("connect");
239 exit (1);
240 }
23a7488d
RS
241
242 /* We use the stream OUT to send our command to the server. */
46cec291
RS
243 if ((out = fdopen (s, "r+")) == NULL)
244 {
245 fprintf (stderr, "%s: ", argv[0]);
246 perror ("fdopen");
247 exit (1);
248 }
249
23a7488d
RS
250 /* We use the stream IN to read the response.
251 We used to use just one stream for both output and input
252 on the socket, but reversing direction works nonportably:
253 on some systems, the output appears as the first input;
254 on other systems it does not. */
255 if ((in = fdopen (s, "r+")) == NULL)
256 {
257 fprintf (stderr, "%s: ", argv[0]);
258 perror ("fdopen");
259 exit (1);
260 }
261
e397a017 262#ifdef BSD_SYSTEM
46cec291 263 cwd = getwd (string);
ee6a193c
RS
264#else
265 cwd = getcwd (string, sizeof string);
266#endif
46cec291
RS
267 if (cwd == 0)
268 {
269 /* getwd puts message in STRING if it fails. */
92af894f 270 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
46cec291
RS
271 exit (1);
272 }
273
5212210c
RS
274 if (nowait)
275 fprintf (out, "-nowait ");
292d74a3 276
5212210c
RS
277 for (i = optind; i < argc; i++)
278 {
46cec291
RS
279 if (*argv[i] == '+')
280 {
281 char *p = argv[i] + 1;
282 while (*p >= '0' && *p <= '9') p++;
283 if (*p != 0)
284 fprintf (out, "%s/", cwd);
285 }
286 else if (*argv[i] != '/')
287 fprintf (out, "%s/", cwd);
5212210c
RS
288
289 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
290 }
291 fprintf (out, "\n");
292 fflush (out);
293
292d74a3
RS
294 /* Maybe wait for an answer. */
295 if (nowait)
296 return 0;
297
46cec291
RS
298 printf ("Waiting for Emacs...");
299 fflush (stdout);
300
23a7488d
RS
301 /* Now, wait for an answer and print any messages. On some systems,
302 the first line we read will actually be the output we just sent.
303 We can't predict whether that will happen, so if it does, we
304 detect it by recognizing `Client: ' at the beginning. */
46cec291 305
23a7488d 306 while (str = fgets (string, BUFSIZ, in))
46cec291 307 printf ("%s", str);
23a7488d 308
340ff9de 309 return 0;
46cec291
RS
310}
311
312#else /* This is the SYSV IPC section */
313
314#include <sys/types.h>
315#include <sys/ipc.h>
316#include <sys/msg.h>
b135a7cf 317#include <sys/utsname.h>
46cec291
RS
318#include <stdio.h>
319
1518a9eb 320char *getwd (), *getcwd (), *getenv ();
b135a7cf 321struct utsname system_name;
1518a9eb 322
46cec291
RS
323main (argc, argv)
324 int argc;
325 char **argv;
326{
327 int s;
328 key_t key;
1518a9eb
RS
329 /* Size of text allocated in MSGP. */
330 int size_allocated = BUFSIZ;
331 /* Amount of text used in MSGP. */
332 int used;
333 struct msgbuf *msgp
334 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
46cec291
RS
335 struct msqid_ds * msg_st;
336 char *homedir, buf[BUFSIZ];
337 char gwdirb[BUFSIZ];
338 char *cwd;
339 char *temp;
8f9aaa0a
RS
340
341 progname = argv[0];
342
343 /* Process options. */
5212210c 344 decode_options (argc, argv);
46cec291 345
5212210c 346 if (argc - optind < 1)
8f9aaa0a 347 print_help_and_exit ();
46cec291
RS
348
349 /*
b135a7cf 350 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
351 */
352 if ((homedir = getenv ("HOME")) == NULL)
353 {
354 fprintf (stderr, "%s: No home directory\n", argv[0]);
355 exit (1);
356 }
357 strcpy (buf, homedir);
b135a7cf
RS
358#ifndef HAVE_LONG_FILE_NAMES
359 /* If file names are short, we can't fit the host name. */
360 strcat (buf, "/.emacs-server");
361#else
362 strcat (buf, "/.emacs-server-");
363 uname (&system_name);
364 strcat (buf, system_name.nodename);
365#endif
46cec291
RS
366 creat (buf, 0600);
367 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 368 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
369 if (s == -1)
370 {
371 fprintf (stderr, "%s: ", argv[0]);
372 perror ("msgget");
373 exit (1);
374 }
375
376 /* Determine working dir, so we can prefix it to all the arguments. */
e397a017 377#ifdef BSD_SYSTEM
46cec291
RS
378 temp = getwd (gwdirb);
379#else
380 temp = getcwd (gwdirb, sizeof gwdirb);
381#endif
382
383 cwd = gwdirb;
384 if (temp != 0)
385 {
386 /* On some systems, cwd can look like `@machine/...';
387 ignore everything before the first slash in such a case. */
388 while (*cwd && *cwd != '/')
389 cwd++;
390 strcat (cwd, "/");
391 }
392 else
393 {
26396b1b 394 fprintf (stderr, "%s: %s\n", argv[0], cwd);
46cec291
RS
395 exit (1);
396 }
397
398 msgp->mtext[0] = 0;
1518a9eb 399 used = 0;
5212210c
RS
400
401 if (nowait)
402 {
403 strcat (msgp->mtext, "-nowait ");
404 used += 8;
405 }
406
407 argc -= optind;
408 argv += optind;
409
46cec291
RS
410 while (argc)
411 {
1518a9eb 412 int need_cwd = 0;
cd33a5a0 413 char *modified_arg = argv[0];
292d74a3 414
5212210c 415 if (*modified_arg == '+')
46cec291 416 {
cd33a5a0 417 char *p = modified_arg + 1;
46cec291
RS
418 while (*p >= '0' && *p <= '9') p++;
419 if (*p != 0)
1518a9eb 420 need_cwd = 1;
46cec291 421 }
cd33a5a0 422 else if (*modified_arg != '/')
1518a9eb
RS
423 need_cwd = 1;
424
5212210c
RS
425 modified_arg = quote_file_name (modified_arg);
426
1518a9eb
RS
427 if (need_cwd)
428 used += strlen (cwd);
cd33a5a0 429 used += strlen (modified_arg) + 1;
1518a9eb
RS
430 while (used + 2 > size_allocated)
431 {
432 size_allocated *= 2;
433 msgp = (struct msgbuf *) realloc (msgp,
434 (sizeof (struct msgbuf)
435 + size_allocated));
436 }
437
438 if (need_cwd)
46cec291
RS
439 strcat (msgp->mtext, cwd);
440
cd33a5a0 441 strcat (msgp->mtext, modified_arg);
46cec291
RS
442 strcat (msgp->mtext, " ");
443 argv++; argc--;
444 }
445 strcat (msgp->mtext, "\n");
1518a9eb
RS
446#ifdef HPUX /* HPUX has a bug. */
447 if (strlen (msgp->mtext) >= 512)
448 {
18a2fa91 449 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
450 exit (1);
451 }
452#endif
46cec291
RS
453 msgp->mtype = 1;
454 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
455 {
defb80d7 456 fprintf (stderr, "%s: ", progname);
46cec291
RS
457 perror ("msgsnd");
458 exit (1);
459 }
292d74a3
RS
460
461 /* Maybe wait for an answer. */
462 if (nowait)
463 return 0;
464
46cec291
RS
465 printf ("Waiting for Emacs...");
466 fflush (stdout);
467
468 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
469 strcpy (buf, msgp->mtext);
470
dc3c30fe
KH
471 printf ("\n");
472 if (*buf)
473 printf ("%s\n", buf);
46cec291
RS
474 exit (0);
475}
476
477#endif /* HAVE_SYSVIPC */
478
479#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
480\f
481#ifndef HAVE_STRERROR
482char *
483strerror (errnum)
484 int errnum;
485{
486 extern char *sys_errlist[];
487 extern int sys_nerr;
488
489 if (errnum >= 0 && errnum < sys_nerr)
490 return sys_errlist[errnum];
491 return (char *) "Unknown error";
492}
493
494#endif /* ! HAVE_STRERROR */