(Fbase64_encode_region): Use SET_PT_BOTH instead of SET_PT
[bpt/emacs.git] / lib-src / emacsclient.c
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #define NO_SHORTNAMES
23 #include <../src/config.h>
24 #undef read
25 #undef write
26 #undef open
27 #undef close
28 #undef signal
29
30 #include <stdio.h>
31 #include <getopt.h>
32 #ifdef STDC_HEADERS
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 char *getenv (), *getwd ();
40 char *getcwd ();
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. */
50 char *progname;
51
52 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
53 int nowait = 0;
54
55 void print_help_and_exit ();
56
57 struct option longopts[] =
58 {
59 { "no-wait", no_argument, NULL, 'n' },
60 { "help", no_argument, NULL, 'H' },
61 { "version", no_argument, NULL, 'V' },
62 { 0 }
63 };
64
65 /* Decode the options from argv and argc.
66 The global variable `optind' will say how many arguments we used up. */
67
68 void
69 decode_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;
96
97 case 'H':
98 default:
99 print_help_and_exit ();
100 }
101 }
102 }
103
104 void
105 print_help_and_exit ()
106 {
107 fprintf (stderr,
108 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
109 progname);
110 fprintf (stderr,
111 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
112 exit (1);
113 }
114
115 /* Return a copy of NAME, inserting a &
116 before each &, each space, and any initial -.
117 Change spaces to underscores, too, so that the
118 return value never contains a space. */
119
120 char *
121 quote_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 {
133 *q++ = '&';
134 *q++ = '_';
135 p++;
136 }
137 else
138 {
139 if (*p == '&' || (*p == '-' && p == name))
140 *q++ = '&';
141 *q++ = *p++;
142 }
143 }
144 *q++ = 0;
145
146 return copy;
147 }
148
149 #ifdef C_ALLOCA
150 /* Like malloc but get fatal error if memory is exhausted. */
151
152 char *
153 xmalloc (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 */
165 \f
166 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
167
168 main (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
180 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
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>
186 #include <sys/stat.h>
187 #include <errno.h>
188
189 extern char *strerror ();
190 extern int errno;
191
192 int
193 main (argc, argv)
194 int argc;
195 char **argv;
196 {
197 char system_name[32];
198 int s, i;
199 FILE *out, *in;
200 struct sockaddr_un server;
201 char *homedir, *cwd, *str;
202 char string[BUFSIZ];
203
204 progname = argv[0];
205
206 /* Process options. */
207 decode_options (argc, argv);
208
209 if (argc - optind < 1)
210 print_help_and_exit ();
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
224 {
225 struct stat statbfr;
226
227 gethostname (system_name, sizeof (system_name));
228 /* system_name must be null-terminated string */
229 system_name[sizeof (system_name) - 1] = '\0';
230 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
231
232 if (stat (server.sun_path, &statbfr) == -1)
233 {
234 if (errno == ENOENT)
235 fprintf (stderr,
236 "%s: can't find socket; have you started the server?\n",
237 argv[0]);
238 else
239 fprintf (stderr, "%s: can't stat %s: %s\n",
240 argv[0], server.sun_path, strerror (errno));
241 exit (1);
242 }
243 if (statbfr.st_uid != geteuid ())
244 {
245 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
246 exit (1);
247 }
248 }
249 #else
250 if ((homedir = getenv ("HOME")) == NULL)
251 {
252 fprintf (stderr, "%s: No home directory\n", argv[0]);
253 exit (1);
254 }
255 strcpy (server.sun_path, homedir);
256 strcat (server.sun_path, "/.emacs-server-");
257 gethostname (system_name, sizeof (system_name));
258 strcat (server.sun_path, system_name);
259 #endif
260
261 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
262 < 0)
263 {
264 fprintf (stderr, "%s: ", argv[0]);
265 perror ("connect");
266 exit (1);
267 }
268
269 /* We use the stream OUT to send our command to the server. */
270 if ((out = fdopen (s, "r+")) == NULL)
271 {
272 fprintf (stderr, "%s: ", argv[0]);
273 perror ("fdopen");
274 exit (1);
275 }
276
277 /* We use the stream IN to read the response.
278 We used to use just one stream for both output and input
279 on the socket, but reversing direction works nonportably:
280 on some systems, the output appears as the first input;
281 on other systems it does not. */
282 if ((in = fdopen (s, "r+")) == NULL)
283 {
284 fprintf (stderr, "%s: ", argv[0]);
285 perror ("fdopen");
286 exit (1);
287 }
288
289 #ifdef BSD_SYSTEM
290 cwd = getwd (string);
291 #else
292 cwd = getcwd (string, sizeof string);
293 #endif
294 if (cwd == 0)
295 {
296 /* getwd puts message in STRING if it fails. */
297 fprintf (stderr, "%s: %s (%s)\n", argv[0],
298 #ifdef BSD_SYSTEM
299 string,
300 #else
301 "Cannot get current working directory",
302 #endif
303 strerror (errno));
304 exit (1);
305 }
306
307 if (nowait)
308 fprintf (out, "-nowait ");
309
310 for (i = optind; i < argc; i++)
311 {
312 if (*argv[i] == '+')
313 {
314 char *p = argv[i] + 1;
315 while (*p >= '0' && *p <= '9') p++;
316 if (*p != 0)
317 fprintf (out, "%s/", cwd);
318 }
319 else if (*argv[i] != '/')
320 fprintf (out, "%s/", cwd);
321
322 fprintf (out, "%s ", quote_file_name (argv[i]));
323 }
324 fprintf (out, "\n");
325 fflush (out);
326
327 /* Maybe wait for an answer. */
328 if (nowait)
329 return 0;
330
331 printf ("Waiting for Emacs...");
332 fflush (stdout);
333
334 /* Now, wait for an answer and print any messages. On some systems,
335 the first line we read will actually be the output we just sent.
336 We can't predict whether that will happen, so if it does, we
337 detect it by recognizing `Client: ' at the beginning. */
338
339 while (str = fgets (string, BUFSIZ, in))
340 printf ("%s", str);
341
342 return 0;
343 }
344
345 #else /* This is the SYSV IPC section */
346
347 #include <sys/types.h>
348 #include <sys/ipc.h>
349 #include <sys/msg.h>
350 #include <sys/utsname.h>
351 #include <stdio.h>
352 #include <errno.h>
353 extern int errno;
354
355 char *getwd (), *getcwd (), *getenv ();
356 struct utsname system_name;
357
358 main (argc, argv)
359 int argc;
360 char **argv;
361 {
362 int s;
363 key_t key;
364 /* Size of text allocated in MSGP. */
365 int size_allocated = BUFSIZ;
366 /* Amount of text used in MSGP. */
367 int used;
368 struct msgbuf *msgp
369 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
370 struct msqid_ds * msg_st;
371 char *homedir, buf[BUFSIZ];
372 char gwdirb[BUFSIZ];
373 char *cwd;
374 char *temp;
375
376 progname = argv[0];
377
378 /* Process options. */
379 decode_options (argc, argv);
380
381 if (argc - optind < 1)
382 print_help_and_exit ();
383
384 /*
385 * Create a message queue using ~/.emacs-server as the path for ftok
386 */
387 if ((homedir = getenv ("HOME")) == NULL)
388 {
389 fprintf (stderr, "%s: No home directory\n", argv[0]);
390 exit (1);
391 }
392 strcpy (buf, homedir);
393 #ifndef HAVE_LONG_FILE_NAMES
394 /* If file names are short, we can't fit the host name. */
395 strcat (buf, "/.emacs-server");
396 #else
397 strcat (buf, "/.emacs-server-");
398 uname (&system_name);
399 strcat (buf, system_name.nodename);
400 #endif
401 creat (buf, 0600);
402 key = ftok (buf, 1); /* unlikely to be anyone else using it */
403 s = msgget (key, 0600 | IPC_CREAT);
404 if (s == -1)
405 {
406 fprintf (stderr, "%s: ", argv[0]);
407 perror ("msgget");
408 exit (1);
409 }
410
411 /* Determine working dir, so we can prefix it to all the arguments. */
412 #ifdef BSD_SYSTEM
413 temp = getwd (gwdirb);
414 #else
415 temp = getcwd (gwdirb, sizeof gwdirb);
416 #endif
417
418 cwd = gwdirb;
419 if (temp != 0)
420 {
421 /* On some systems, cwd can look like `@machine/...';
422 ignore everything before the first slash in such a case. */
423 while (*cwd && *cwd != '/')
424 cwd++;
425 strcat (cwd, "/");
426 }
427 else
428 {
429 #ifdef BSD_SYSTEM
430 fprintf (stderr, "%s: %s\n", argv[0], cwd);
431 #else
432 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
433 argv[0], strerror (errno));
434 #endif
435 exit (1);
436 }
437
438 msgp->mtext[0] = 0;
439 used = 0;
440
441 if (nowait)
442 {
443 strcat (msgp->mtext, "-nowait ");
444 used += 8;
445 }
446
447 argc -= optind;
448 argv += optind;
449
450 while (argc)
451 {
452 int need_cwd = 0;
453 char *modified_arg = argv[0];
454
455 if (*modified_arg == '+')
456 {
457 char *p = modified_arg + 1;
458 while (*p >= '0' && *p <= '9') p++;
459 if (*p != 0)
460 need_cwd = 1;
461 }
462 else if (*modified_arg != '/')
463 need_cwd = 1;
464
465 modified_arg = quote_file_name (modified_arg);
466
467 if (need_cwd)
468 used += strlen (cwd);
469 used += strlen (modified_arg) + 1;
470 while (used + 2 > size_allocated)
471 {
472 size_allocated *= 2;
473 msgp = (struct msgbuf *) realloc (msgp,
474 (sizeof (struct msgbuf)
475 + size_allocated));
476 }
477
478 if (need_cwd)
479 strcat (msgp->mtext, cwd);
480
481 strcat (msgp->mtext, modified_arg);
482 strcat (msgp->mtext, " ");
483 argv++; argc--;
484 }
485 strcat (msgp->mtext, "\n");
486 #ifdef HPUX /* HPUX has a bug. */
487 if (strlen (msgp->mtext) >= 512)
488 {
489 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
490 exit (1);
491 }
492 #endif
493 msgp->mtype = 1;
494 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
495 {
496 fprintf (stderr, "%s: ", progname);
497 perror ("msgsnd");
498 exit (1);
499 }
500
501 /* Maybe wait for an answer. */
502 if (nowait)
503 return 0;
504
505 printf ("Waiting for Emacs...");
506 fflush (stdout);
507
508 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
509 strcpy (buf, msgp->mtext);
510
511 printf ("\n");
512 if (*buf)
513 printf ("%s\n", buf);
514 exit (0);
515 }
516
517 #endif /* HAVE_SYSVIPC */
518
519 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
520 \f
521 #ifndef HAVE_STRERROR
522 char *
523 strerror (errnum)
524 int errnum;
525 {
526 extern char *sys_errlist[];
527 extern int sys_nerr;
528
529 if (errnum >= 0 && errnum < sys_nerr)
530 return sys_errlist[errnum];
531 return (char *) "Unknown error";
532 }
533
534 #endif /* ! HAVE_STRERROR */