]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
(direct_output_for_insert): Set glyph row's
[gnu-emacs] / lib-src / emacsclient.c
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999 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 signal
25
26 #include <stdio.h>
27 #include <getopt.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31
32 char *getenv (), *getwd ();
33 char *getcwd ();
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. */
43 char *progname;
44
45 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
46 int nowait = 0;
47
48 void print_help_and_exit ();
49
50 struct option longopts[] =
51 {
52 { "no-wait", no_argument, NULL, 'n' },
53 { "help", no_argument, NULL, 'H' },
54 { "version", no_argument, NULL, 'V' },
55 { 0 }
56 };
57
58 /* Decode the options from argv and argc.
59 The global variable `optind' will say how many arguments we used up. */
60
61 void
62 decode_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, "emacsclient %s\n", VERSION);
87 exit (1);
88 break;
89
90 case 'H':
91 default:
92 print_help_and_exit ();
93 }
94 }
95 }
96
97 void
98 print_help_and_exit ()
99 {
100 fprintf (stderr,
101 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
102 progname);
103 fprintf (stderr,
104 "Or %s --version\n",
105 progname);
106 fprintf (stderr,
107 "Report bugs to bug-gnu-emacs@gnu.org.\n");
108 exit (1);
109 }
110
111 /* Return a copy of NAME, inserting a &
112 before each &, each space, and any initial -.
113 Change spaces to underscores, too, so that the
114 return value never contains a space. */
115
116 char *
117 quote_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 {
129 *q++ = '&';
130 *q++ = '_';
131 p++;
132 }
133 else
134 {
135 if (*p == '&' || (*p == '-' && p == name))
136 *q++ = '&';
137 *q++ = *p++;
138 }
139 }
140 *q++ = 0;
141
142 return copy;
143 }
144
145 /* Like malloc but get fatal error if memory is exhausted. */
146
147 long *
148 xmalloc (size)
149 unsigned int size;
150 {
151 long *result = (long *) malloc (size);
152 if (result == NULL)
153 {
154 perror ("malloc");
155 exit (1);
156 }
157 return result;
158 }
159 \f
160 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
161
162 main (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
174 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
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>
180 #include <sys/stat.h>
181 #include <errno.h>
182
183 extern char *strerror ();
184 extern int errno;
185
186 int
187 main (argc, argv)
188 int argc;
189 char **argv;
190 {
191 char *system_name;
192 int system_name_length;
193 int s, i;
194 FILE *out, *in;
195 struct sockaddr_un server;
196 char *homedir, *cwd, *str;
197 char string[BUFSIZ];
198
199 progname = argv[0];
200
201 /* Process options. */
202 decode_options (argc, argv);
203
204 if (argc - optind < 1)
205 print_help_and_exit ();
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;
218
219 {
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 }
235 }
236
237 #ifndef SERVER_HOME_DIR
238 {
239 struct stat statbfr;
240
241 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
242
243 if (stat (server.sun_path, &statbfr) == -1)
244 {
245 if (errno == ENOENT)
246 fprintf (stderr,
247 "%s: can't find socket; have you started the server?\n",
248 argv[0]);
249 else
250 fprintf (stderr, "%s: can't stat %s: %s\n",
251 argv[0], server.sun_path, strerror (errno));
252 exit (1);
253 }
254 if (statbfr.st_uid != geteuid ())
255 {
256 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
257 exit (1);
258 }
259 }
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);
267 strcat (server.sun_path, "/.emacs-server-");
268 strcat (server.sun_path, system_name);
269 #endif
270
271 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
272 < 0)
273 {
274 fprintf (stderr, "%s: ", argv[0]);
275 perror ("connect");
276 exit (1);
277 }
278
279 /* We use the stream OUT to send our command to the server. */
280 if ((out = fdopen (s, "r+")) == NULL)
281 {
282 fprintf (stderr, "%s: ", argv[0]);
283 perror ("fdopen");
284 exit (1);
285 }
286
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
299 #ifdef BSD_SYSTEM
300 cwd = getwd (string);
301 #else
302 cwd = getcwd (string, sizeof string);
303 #endif
304 if (cwd == 0)
305 {
306 /* getwd puts message in STRING if it fails. */
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));
314 exit (1);
315 }
316
317 if (nowait)
318 fprintf (out, "-nowait ");
319
320 for (i = optind; i < argc; i++)
321 {
322 if (*argv[i] == '+')
323 {
324 char *p = argv[i] + 1;
325 while (*p >= '0' && *p <= '9') p++;
326 if (*p != 0)
327 fprintf (out, "%s/", quote_file_name (cwd));
328 }
329 else if (*argv[i] != '/')
330 fprintf (out, "%s/", quote_file_name (cwd));
331
332 fprintf (out, "%s ", quote_file_name (argv[i]));
333 }
334 fprintf (out, "\n");
335 fflush (out);
336
337 /* Maybe wait for an answer. */
338 if (nowait)
339 return 0;
340
341 printf ("Waiting for Emacs...");
342 fflush (stdout);
343
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. */
348
349 while (str = fgets (string, BUFSIZ, in))
350 printf ("%s", str);
351
352 return 0;
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>
360 #include <sys/utsname.h>
361 #include <stdio.h>
362 #include <errno.h>
363 extern int errno;
364
365 char *getwd (), *getcwd (), *getenv ();
366 struct utsname system_name;
367
368 main (argc, argv)
369 int argc;
370 char **argv;
371 {
372 int s;
373 key_t key;
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);
380 struct msqid_ds * msg_st;
381 char *homedir, buf[BUFSIZ];
382 char gwdirb[BUFSIZ];
383 char *cwd;
384 char *temp;
385
386 progname = argv[0];
387
388 /* Process options. */
389 decode_options (argc, argv);
390
391 if (argc - optind < 1)
392 print_help_and_exit ();
393
394 /*
395 * Create a message queue using ~/.emacs-server as the path for ftok
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);
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
411 creat (buf, 0600);
412 key = ftok (buf, 1); /* unlikely to be anyone else using it */
413 s = msgget (key, 0600 | IPC_CREAT);
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. */
422 #ifdef BSD_SYSTEM
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 {
439 #ifdef BSD_SYSTEM
440 fprintf (stderr, "%s: %s\n", argv[0], cwd);
441 #else
442 fprintf (stderr, "%s: Cannot get current working directory: %s\n",
443 argv[0], strerror (errno));
444 #endif
445 exit (1);
446 }
447
448 msgp->mtext[0] = 0;
449 used = 0;
450
451 if (nowait)
452 {
453 strcat (msgp->mtext, "-nowait ");
454 used += 8;
455 }
456
457 argc -= optind;
458 argv += optind;
459
460 while (argc)
461 {
462 int need_cwd = 0;
463 char *modified_arg = argv[0];
464
465 if (*modified_arg == '+')
466 {
467 char *p = modified_arg + 1;
468 while (*p >= '0' && *p <= '9') p++;
469 if (*p != 0)
470 need_cwd = 1;
471 }
472 else if (*modified_arg != '/')
473 need_cwd = 1;
474
475 modified_arg = quote_file_name (modified_arg);
476
477 if (need_cwd)
478 /* Overestimate in case we have to quote something in CWD. */
479 used += 2 * strlen (cwd);
480 used += strlen (modified_arg) + 1;
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)
490 strcat (msgp->mtext, quote_file_name (cwd));
491
492 strcat (msgp->mtext, modified_arg);
493 strcat (msgp->mtext, " ");
494 argv++; argc--;
495 }
496 strcat (msgp->mtext, "\n");
497 #ifdef HPUX /* HPUX has a bug. */
498 if (strlen (msgp->mtext) >= 512)
499 {
500 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
501 exit (1);
502 }
503 #endif
504 msgp->mtype = 1;
505 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
506 {
507 fprintf (stderr, "%s: ", progname);
508 perror ("msgsnd");
509 exit (1);
510 }
511
512 /* Maybe wait for an answer. */
513 if (nowait)
514 return 0;
515
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
522 printf ("\n");
523 if (*buf)
524 printf ("%s\n", buf);
525 exit (0);
526 }
527
528 #endif /* HAVE_SYSVIPC */
529
530 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
531 \f
532 #ifndef HAVE_STRERROR
533 char *
534 strerror (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 */