Add support for large files. Merge glibc 2.1.2.
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
efb859b4 1/* Client process that communicates with GNU Emacs acting as server.
4ee9629e 2 Copyright (C) 1986, 1987, 1994, 1999 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>
4e23f2ba 24#undef signal
46cec291 25
8f9aaa0a
RS
26#include <stdio.h>
27#include <getopt.h>
79f13bba
DL
28#ifdef HAVE_UNISTD_H
29#include <unistd.h>
30#endif
8f9aaa0a
RS
31
32char *getenv (), *getwd ();
33char *getcwd ();
8f9aaa0a
RS
34
35/* This is defined with -D from the compilation command,
36 which extracts it from ../lisp/version.el. */
37
38#ifndef VERSION
39#define VERSION "unspecified"
40#endif
41\f
42/* Name used to invoke this program. */
43char *progname;
44
749ae770 45/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
46int nowait = 0;
47
7f3bff3e
AS
48void print_help_and_exit ();
49
8f9aaa0a
RS
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':
b4e94f42 86 fprintf (stderr, "emacsclient %s\n", VERSION);
8f9aaa0a
RS
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
7f3bff3e 97void
8f9aaa0a
RS
98print_help_and_exit ()
99{
100 fprintf (stderr,
749ae770 101 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
8f9aaa0a 102 progname);
4852ed0e
RS
103 fprintf (stderr,
104 "Or %s --version\n",
105 progname);
8f9aaa0a 106 fprintf (stderr,
b4e94f42 107 "Report bugs to bug-gnu-emacs@gnu.org.\n");
8f9aaa0a
RS
108 exit (1);
109}
5212210c 110
f1db6a73
RS
111/* Return a copy of NAME, inserting a &
112 before each &, each space, and any initial -.
5212210c
RS
113 Change spaces to underscores, too, so that the
114 return value never contains a space. */
115
116char *
117quote_file_name (name)
118 char *name;
119{
120 char *copy = (char *) malloc (strlen (name) * 2 + 1);
121 char *p, *q;
122
123 p = name;
124 q = copy;
125 while (*p)
126 {
127 if (*p == ' ')
128 {
f1db6a73 129 *q++ = '&';
5212210c
RS
130 *q++ = '_';
131 p++;
132 }
133 else
134 {
f1db6a73
RS
135 if (*p == '&' || (*p == '-' && p == name))
136 *q++ = '&';
5212210c
RS
137 *q++ = *p++;
138 }
139 }
f1db6a73 140 *q++ = 0;
5212210c
RS
141
142 return copy;
143}
0c76956f 144
0c76956f
RS
145/* Like malloc but get fatal error if memory is exhausted. */
146
5497dfdb 147long *
0c76956f
RS
148xmalloc (size)
149 unsigned int size;
150{
5f32a712 151 long *result = (long *) malloc (size);
0c76956f
RS
152 if (result == NULL)
153 {
154 perror ("malloc");
155 exit (1);
156 }
157 return result;
158}
8f9aaa0a 159\f
b135a7cf 160#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291
RS
161
162main (argc, argv)
163 int argc;
164 char **argv;
165{
166 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
167 argv[0]);
168 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
169 exit (1);
170}
171
172#else /* HAVE_SOCKETS or HAVE_SYSVIPC */
173
1e523e3d 174#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
175/* BSD code is very different from SYSV IPC code */
176
177#include <sys/types.h>
178#include <sys/socket.h>
179#include <sys/un.h>
efb859b4 180#include <sys/stat.h>
46cec291
RS
181#include <errno.h>
182
92af894f 183extern char *strerror ();
46cec291
RS
184extern int errno;
185
340ff9de 186int
46cec291
RS
187main (argc, argv)
188 int argc;
189 char **argv;
190{
a2b3f2b5
RS
191 char *system_name;
192 int system_name_length;
46cec291 193 int s, i;
23a7488d 194 FILE *out, *in;
46cec291
RS
195 struct sockaddr_un server;
196 char *homedir, *cwd, *str;
197 char string[BUFSIZ];
8f9aaa0a
RS
198
199 progname = argv[0];
46cec291 200
8f9aaa0a 201 /* Process options. */
5212210c 202 decode_options (argc, argv);
46cec291 203
5212210c 204 if (argc - optind < 1)
8f9aaa0a 205 print_help_and_exit ();
46cec291
RS
206
207 /*
208 * Open up an AF_UNIX socket in this person's home directory
209 */
210
211 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
212 {
213 fprintf (stderr, "%s: ", argv[0]);
214 perror ("socket");
215 exit (1);
216 }
217 server.sun_family = AF_UNIX;
c5fee545 218
efb859b4 219 {
a2b3f2b5
RS
220 system_name_length = 32;
221
222 while (1)
223 {
224 system_name = (char *) xmalloc (system_name_length + 1);
225
226 /* system_name must be null-terminated string. */
227 system_name[system_name_length] = '\0';
228
229 if (gethostname (system_name, system_name_length) == 0)
230 break;
231
232 free (system_name);
233 system_name_length *= 2;
234 }
c5fee545
KH
235 }
236
237#ifndef SERVER_HOME_DIR
238 {
239 struct stat statbfr;
efb859b4 240
efb859b4
JB
241 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
242
243 if (stat (server.sun_path, &statbfr) == -1)
244 {
c0acc3e1
JB
245 if (errno == ENOENT)
246 fprintf (stderr,
18a2fa91
KH
247 "%s: can't find socket; have you started the server?\n",
248 argv[0]);
c0acc3e1 249 else
18a2fa91
KH
250 fprintf (stderr, "%s: can't stat %s: %s\n",
251 argv[0], server.sun_path, strerror (errno));
efb859b4
JB
252 exit (1);
253 }
b135a7cf 254 if (statbfr.st_uid != geteuid ())
efb859b4 255 {
18a2fa91 256 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
efb859b4
JB
257 exit (1);
258 }
259 }
46cec291
RS
260#else
261 if ((homedir = getenv ("HOME")) == NULL)
262 {
263 fprintf (stderr, "%s: No home directory\n", argv[0]);
264 exit (1);
265 }
266 strcpy (server.sun_path, homedir);
b135a7cf 267 strcat (server.sun_path, "/.emacs-server-");
b135a7cf 268 strcat (server.sun_path, system_name);
46cec291
RS
269#endif
270
4e23f2ba
JB
271 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
272 < 0)
46cec291
RS
273 {
274 fprintf (stderr, "%s: ", argv[0]);
275 perror ("connect");
276 exit (1);
277 }
23a7488d
RS
278
279 /* We use the stream OUT to send our command to the server. */
46cec291
RS
280 if ((out = fdopen (s, "r+")) == NULL)
281 {
282 fprintf (stderr, "%s: ", argv[0]);
283 perror ("fdopen");
284 exit (1);
285 }
286
23a7488d
RS
287 /* We use the stream IN to read the response.
288 We used to use just one stream for both output and input
289 on the socket, but reversing direction works nonportably:
290 on some systems, the output appears as the first input;
291 on other systems it does not. */
292 if ((in = fdopen (s, "r+")) == NULL)
293 {
294 fprintf (stderr, "%s: ", argv[0]);
295 perror ("fdopen");
296 exit (1);
297 }
298
e397a017 299#ifdef BSD_SYSTEM
46cec291 300 cwd = getwd (string);
ee6a193c
RS
301#else
302 cwd = getcwd (string, sizeof string);
303#endif
46cec291
RS
304 if (cwd == 0)
305 {
306 /* getwd puts message in STRING if it fails. */
bd252662
RS
307 fprintf (stderr, "%s: %s (%s)\n", argv[0],
308#ifdef BSD_SYSTEM
309 string,
310#else
311 "Cannot get current working directory",
312#endif
313 strerror (errno));
46cec291
RS
314 exit (1);
315 }
316
5212210c
RS
317 if (nowait)
318 fprintf (out, "-nowait ");
292d74a3 319
5212210c
RS
320 for (i = optind; i < argc; i++)
321 {
46cec291
RS
322 if (*argv[i] == '+')
323 {
324 char *p = argv[i] + 1;
325 while (*p >= '0' && *p <= '9') p++;
326 if (*p != 0)
0343a017 327 fprintf (out, "%s/", quote_file_name (cwd));
46cec291
RS
328 }
329 else if (*argv[i] != '/')
0343a017 330 fprintf (out, "%s/", quote_file_name (cwd));
5212210c
RS
331
332 fprintf (out, "%s ", quote_file_name (argv[i]));
46cec291
RS
333 }
334 fprintf (out, "\n");
335 fflush (out);
336
292d74a3
RS
337 /* Maybe wait for an answer. */
338 if (nowait)
339 return 0;
340
46cec291
RS
341 printf ("Waiting for Emacs...");
342 fflush (stdout);
343
23a7488d
RS
344 /* Now, wait for an answer and print any messages. On some systems,
345 the first line we read will actually be the output we just sent.
346 We can't predict whether that will happen, so if it does, we
347 detect it by recognizing `Client: ' at the beginning. */
46cec291 348
23a7488d 349 while (str = fgets (string, BUFSIZ, in))
46cec291 350 printf ("%s", str);
23a7488d 351
340ff9de 352 return 0;
46cec291
RS
353}
354
355#else /* This is the SYSV IPC section */
356
357#include <sys/types.h>
358#include <sys/ipc.h>
359#include <sys/msg.h>
b135a7cf 360#include <sys/utsname.h>
46cec291 361#include <stdio.h>
bd252662
RS
362#include <errno.h>
363extern int errno;
46cec291 364
1518a9eb 365char *getwd (), *getcwd (), *getenv ();
b135a7cf 366struct utsname system_name;
1518a9eb 367
46cec291
RS
368main (argc, argv)
369 int argc;
370 char **argv;
371{
372 int s;
373 key_t key;
1518a9eb
RS
374 /* Size of text allocated in MSGP. */
375 int size_allocated = BUFSIZ;
376 /* Amount of text used in MSGP. */
377 int used;
378 struct msgbuf *msgp
379 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
46cec291
RS
380 struct msqid_ds * msg_st;
381 char *homedir, buf[BUFSIZ];
382 char gwdirb[BUFSIZ];
383 char *cwd;
384 char *temp;
8f9aaa0a
RS
385
386 progname = argv[0];
387
388 /* Process options. */
5212210c 389 decode_options (argc, argv);
46cec291 390
5212210c 391 if (argc - optind < 1)
8f9aaa0a 392 print_help_and_exit ();
46cec291
RS
393
394 /*
b135a7cf 395 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
396 */
397 if ((homedir = getenv ("HOME")) == NULL)
398 {
399 fprintf (stderr, "%s: No home directory\n", argv[0]);
400 exit (1);
401 }
402 strcpy (buf, homedir);
b135a7cf
RS
403#ifndef HAVE_LONG_FILE_NAMES
404 /* If file names are short, we can't fit the host name. */
405 strcat (buf, "/.emacs-server");
406#else
407 strcat (buf, "/.emacs-server-");
408 uname (&system_name);
409 strcat (buf, system_name.nodename);
410#endif
46cec291
RS
411 creat (buf, 0600);
412 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 413 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
414 if (s == -1)
415 {
416 fprintf (stderr, "%s: ", argv[0]);
417 perror ("msgget");
418 exit (1);
419 }
420
421 /* Determine working dir, so we can prefix it to all the arguments. */
e397a017 422#ifdef BSD_SYSTEM
46cec291
RS
423 temp = getwd (gwdirb);
424#else
425 temp = getcwd (gwdirb, sizeof gwdirb);
426#endif
427
428 cwd = gwdirb;
429 if (temp != 0)
430 {
431 /* On some systems, cwd can look like `@machine/...';
432 ignore everything before the first slash in such a case. */
433 while (*cwd && *cwd != '/')
434 cwd++;
435 strcat (cwd, "/");
436 }
437 else
438 {
bd252662 439#ifdef BSD_SYSTEM
26396b1b 440 fprintf (stderr, "%s: %s\n", argv[0], cwd);
bd252662
RS
441#else
442 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
443 argv[0], strerror (errno));
444#endif
46cec291
RS
445 exit (1);
446 }
447
448 msgp->mtext[0] = 0;
1518a9eb 449 used = 0;
5212210c
RS
450
451 if (nowait)
452 {
453 strcat (msgp->mtext, "-nowait ");
454 used += 8;
455 }
456
457 argc -= optind;
458 argv += optind;
459
46cec291
RS
460 while (argc)
461 {
1518a9eb 462 int need_cwd = 0;
cd33a5a0 463 char *modified_arg = argv[0];
292d74a3 464
5212210c 465 if (*modified_arg == '+')
46cec291 466 {
cd33a5a0 467 char *p = modified_arg + 1;
46cec291
RS
468 while (*p >= '0' && *p <= '9') p++;
469 if (*p != 0)
1518a9eb 470 need_cwd = 1;
46cec291 471 }
cd33a5a0 472 else if (*modified_arg != '/')
1518a9eb
RS
473 need_cwd = 1;
474
5212210c
RS
475 modified_arg = quote_file_name (modified_arg);
476
1518a9eb 477 if (need_cwd)
0343a017
KH
478 /* Overestimate in case we have to quote something in CWD. */
479 used += 2 * strlen (cwd);
cd33a5a0 480 used += strlen (modified_arg) + 1;
1518a9eb
RS
481 while (used + 2 > size_allocated)
482 {
483 size_allocated *= 2;
484 msgp = (struct msgbuf *) realloc (msgp,
485 (sizeof (struct msgbuf)
486 + size_allocated));
487 }
488
489 if (need_cwd)
0343a017 490 strcat (msgp->mtext, quote_file_name (cwd));
46cec291 491
cd33a5a0 492 strcat (msgp->mtext, modified_arg);
46cec291
RS
493 strcat (msgp->mtext, " ");
494 argv++; argc--;
495 }
496 strcat (msgp->mtext, "\n");
1518a9eb
RS
497#ifdef HPUX /* HPUX has a bug. */
498 if (strlen (msgp->mtext) >= 512)
499 {
18a2fa91 500 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
501 exit (1);
502 }
503#endif
46cec291
RS
504 msgp->mtype = 1;
505 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
506 {
defb80d7 507 fprintf (stderr, "%s: ", progname);
46cec291
RS
508 perror ("msgsnd");
509 exit (1);
510 }
292d74a3
RS
511
512 /* Maybe wait for an answer. */
513 if (nowait)
514 return 0;
515
46cec291
RS
516 printf ("Waiting for Emacs...");
517 fflush (stdout);
518
519 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
520 strcpy (buf, msgp->mtext);
521
dc3c30fe
KH
522 printf ("\n");
523 if (*buf)
524 printf ("%s\n", buf);
46cec291
RS
525 exit (0);
526}
527
528#endif /* HAVE_SYSVIPC */
529
530#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
531\f
532#ifndef HAVE_STRERROR
533char *
534strerror (errnum)
535 int errnum;
536{
537 extern char *sys_errlist[];
538 extern int sys_nerr;
539
540 if (errnum >= 0 && errnum < sys_nerr)
541 return sys_errlist[errnum];
542 return (char *) "Unknown error";
543}
544
545#endif /* ! HAVE_STRERROR */