]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
Set category of kinsoku-bol and kinsoku-eol for
[gnu-emacs] / 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
33 char *getenv (), *getwd ();
34 char *getcwd ();
35 int 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. */
45 char *progname;
46
47 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
48 int nowait = 0;
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, "Version %s\n", VERSION);
87 exit (1);
88 break;
89
90 case 'H':
91 default:
92 print_help_and_exit ();
93 }
94 }
95 }
96
97 print_help_and_exit ()
98 {
99 fprintf (stderr,
100 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
101 progname);
102 fprintf (stderr,
103 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
104 exit (1);
105 }
106
107 /* Return a copy of NAME, inserting a &
108 before each &, each space, and any initial -.
109 Change spaces to underscores, too, so that the
110 return value never contains a space. */
111
112 char *
113 quote_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 {
125 *q++ = '&';
126 *q++ = '_';
127 p++;
128 }
129 else
130 {
131 if (*p == '&' || (*p == '-' && p == name))
132 *q++ = '&';
133 *q++ = *p++;
134 }
135 }
136 *q++ = 0;
137
138 return copy;
139 }
140 \f
141 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
142
143 main (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
155 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
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>
161 #include <sys/stat.h>
162 #include <errno.h>
163
164 extern char *strerror ();
165 extern int errno;
166
167 int
168 main (argc, argv)
169 int argc;
170 char **argv;
171 {
172 char system_name[32];
173 int s, i;
174 FILE *out, *in;
175 struct sockaddr_un server;
176 char *homedir, *cwd, *str;
177 char string[BUFSIZ];
178
179 progname = argv[0];
180
181 /* Process options. */
182 decode_options (argc, argv);
183
184 if (argc - optind < 1)
185 print_help_and_exit ();
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
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 {
207 if (errno == ENOENT)
208 fprintf (stderr,
209 "%s: can't find socket; have you started the server?\n",
210 argv[0]);
211 else
212 fprintf (stderr, "%s: can't stat %s: %s\n",
213 argv[0], server.sun_path, strerror (errno));
214 exit (1);
215 }
216 if (statbfr.st_uid != geteuid ())
217 {
218 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
219 exit (1);
220 }
221 }
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);
229 strcat (server.sun_path, "/.emacs-server-");
230 gethostname (system_name, sizeof (system_name));
231 strcat (server.sun_path, system_name);
232 #endif
233
234 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
235 < 0)
236 {
237 fprintf (stderr, "%s: ", argv[0]);
238 perror ("connect");
239 exit (1);
240 }
241
242 /* We use the stream OUT to send our command to the server. */
243 if ((out = fdopen (s, "r+")) == NULL)
244 {
245 fprintf (stderr, "%s: ", argv[0]);
246 perror ("fdopen");
247 exit (1);
248 }
249
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
262 #ifdef BSD_SYSTEM
263 cwd = getwd (string);
264 #else
265 cwd = getcwd (string, sizeof string);
266 #endif
267 if (cwd == 0)
268 {
269 /* getwd puts message in STRING if it fails. */
270 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
271 exit (1);
272 }
273
274 if (nowait)
275 fprintf (out, "-nowait ");
276
277 for (i = optind; i < argc; i++)
278 {
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);
288
289 fprintf (out, "%s ", quote_file_name (argv[i]));
290 }
291 fprintf (out, "\n");
292 fflush (out);
293
294 /* Maybe wait for an answer. */
295 if (nowait)
296 return 0;
297
298 printf ("Waiting for Emacs...");
299 fflush (stdout);
300
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. */
305
306 while (str = fgets (string, BUFSIZ, in))
307 printf ("%s", str);
308
309 return 0;
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>
317 #include <sys/utsname.h>
318 #include <stdio.h>
319
320 char *getwd (), *getcwd (), *getenv ();
321 struct utsname system_name;
322
323 main (argc, argv)
324 int argc;
325 char **argv;
326 {
327 int s;
328 key_t key;
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);
335 struct msqid_ds * msg_st;
336 char *homedir, buf[BUFSIZ];
337 char gwdirb[BUFSIZ];
338 char *cwd;
339 char *temp;
340
341 progname = argv[0];
342
343 /* Process options. */
344 decode_options (argc, argv);
345
346 if (argc - optind < 1)
347 print_help_and_exit ();
348
349 /*
350 * Create a message queue using ~/.emacs-server as the path for ftok
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);
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
366 creat (buf, 0600);
367 key = ftok (buf, 1); /* unlikely to be anyone else using it */
368 s = msgget (key, 0600 | IPC_CREAT);
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. */
377 #ifdef BSD_SYSTEM
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 {
394 fprintf (stderr, "%s: %s\n", argv[0], cwd);
395 exit (1);
396 }
397
398 msgp->mtext[0] = 0;
399 used = 0;
400
401 if (nowait)
402 {
403 strcat (msgp->mtext, "-nowait ");
404 used += 8;
405 }
406
407 argc -= optind;
408 argv += optind;
409
410 while (argc)
411 {
412 int need_cwd = 0;
413 char *modified_arg = argv[0];
414
415 if (*modified_arg == '+')
416 {
417 char *p = modified_arg + 1;
418 while (*p >= '0' && *p <= '9') p++;
419 if (*p != 0)
420 need_cwd = 1;
421 }
422 else if (*modified_arg != '/')
423 need_cwd = 1;
424
425 modified_arg = quote_file_name (modified_arg);
426
427 if (need_cwd)
428 used += strlen (cwd);
429 used += strlen (modified_arg) + 1;
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)
439 strcat (msgp->mtext, cwd);
440
441 strcat (msgp->mtext, modified_arg);
442 strcat (msgp->mtext, " ");
443 argv++; argc--;
444 }
445 strcat (msgp->mtext, "\n");
446 #ifdef HPUX /* HPUX has a bug. */
447 if (strlen (msgp->mtext) >= 512)
448 {
449 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
450 exit (1);
451 }
452 #endif
453 msgp->mtype = 1;
454 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
455 {
456 fprintf (stderr, "%s: ", progname);
457 perror ("msgsnd");
458 exit (1);
459 }
460
461 /* Maybe wait for an answer. */
462 if (nowait)
463 return 0;
464
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
471 printf ("\n");
472 if (*buf)
473 printf ("%s\n", buf);
474 exit (0);
475 }
476
477 #endif /* HAVE_SYSVIPC */
478
479 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
480 \f
481 #ifndef HAVE_STRERROR
482 char *
483 strerror (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 */