1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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)
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.
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. */
23 #include <../src/config.h>
39 char *getenv (), *getwd ();
42 /* This is defined with -D from the compilation command,
43 which extracts it from ../lisp/version.el. */
46 #define VERSION "unspecified"
49 /* Name used to invoke this program. */
52 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
55 void print_help_and_exit ();
57 struct option longopts
[] =
59 { "no-wait", no_argument
, NULL
, 'n' },
60 { "help", no_argument
, NULL
, 'H' },
61 { "version", no_argument
, NULL
, 'V' },
65 /* Decode the options from argv and argc.
66 The global variable `optind' will say how many arguments we used up. */
69 decode_options (argc
, argv
)
75 int opt
= getopt_long (argc
, argv
,
84 /* If getopt returns 0, then it has already processed a
85 long-named option. We should do nothing. */
93 fprintf (stderr
, "Version %s\n", VERSION
);
99 print_help_and_exit ();
105 print_help_and_exit ()
108 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
111 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
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. */
121 quote_file_name (name
)
124 char *copy
= (char *) malloc (strlen (name
) * 2 + 1);
139 if (*p
== '&' || (*p
== '-' && p
== name
))
150 /* Like malloc but get fatal error if memory is exhausted. */
156 char *result
= (char *) malloc (size
);
164 #endif /* C_ALLOCA */
166 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
172 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
174 fprintf (stderr
, "on systems with Berkeley sockets or System V IPC.\n");
178 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
180 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
181 /* BSD code is very different from SYSV IPC code */
183 #include <sys/types.h>
184 #include <sys/socket.h>
186 #include <sys/stat.h>
189 extern char *strerror ();
197 char system_name
[32];
200 struct sockaddr_un server
;
201 char *homedir
, *cwd
, *str
;
206 /* Process options. */
207 decode_options (argc
, argv
);
209 if (argc
- optind
< 1)
210 print_help_and_exit ();
213 * Open up an AF_UNIX socket in this person's home directory
216 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
218 fprintf (stderr
, "%s: ", argv
[0]);
222 server
.sun_family
= AF_UNIX
;
223 #ifndef SERVER_HOME_DIR
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
);
232 if (stat (server
.sun_path
, &statbfr
) == -1)
236 "%s: can't find socket; have you started the server?\n",
239 fprintf (stderr
, "%s: can't stat %s: %s\n",
240 argv
[0], server
.sun_path
, strerror (errno
));
243 if (statbfr
.st_uid
!= geteuid ())
245 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
250 if ((homedir
= getenv ("HOME")) == NULL
)
252 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
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
);
261 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
264 fprintf (stderr
, "%s: ", argv
[0]);
269 /* We use the stream OUT to send our command to the server. */
270 if ((out
= fdopen (s
, "r+")) == NULL
)
272 fprintf (stderr
, "%s: ", argv
[0]);
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
)
284 fprintf (stderr
, "%s: ", argv
[0]);
290 cwd
= getwd (string
);
292 cwd
= getcwd (string
, sizeof string
);
296 /* getwd puts message in STRING if it fails. */
297 fprintf (stderr
, "%s: %s (%s)\n", argv
[0],
301 "Cannot get current working directory",
308 fprintf (out
, "-nowait ");
310 for (i
= optind
; i
< argc
; i
++)
314 char *p
= argv
[i
] + 1;
315 while (*p
>= '0' && *p
<= '9') p
++;
317 fprintf (out
, "%s/", cwd
);
319 else if (*argv
[i
] != '/')
320 fprintf (out
, "%s/", cwd
);
322 fprintf (out
, "%s ", quote_file_name (argv
[i
]));
327 /* Maybe wait for an answer. */
331 printf ("Waiting for Emacs...");
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. */
339 while (str
= fgets (string
, BUFSIZ
, in
))
345 #else /* This is the SYSV IPC section */
347 #include <sys/types.h>
350 #include <sys/utsname.h>
355 char *getwd (), *getcwd (), *getenv ();
356 struct utsname system_name
;
364 /* Size of text allocated in MSGP. */
365 int size_allocated
= BUFSIZ
;
366 /* Amount of text used in MSGP. */
369 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
370 struct msqid_ds
* msg_st
;
371 char *homedir
, buf
[BUFSIZ
];
378 /* Process options. */
379 decode_options (argc
, argv
);
381 if (argc
- optind
< 1)
382 print_help_and_exit ();
385 * Create a message queue using ~/.emacs-server as the path for ftok
387 if ((homedir
= getenv ("HOME")) == NULL
)
389 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
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");
397 strcat (buf
, "/.emacs-server-");
398 uname (&system_name
);
399 strcat (buf
, system_name
.nodename
);
402 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
403 s
= msgget (key
, 0600 | IPC_CREAT
);
406 fprintf (stderr
, "%s: ", argv
[0]);
411 /* Determine working dir, so we can prefix it to all the arguments. */
413 temp
= getwd (gwdirb
);
415 temp
= getcwd (gwdirb
, sizeof gwdirb
);
421 /* On some systems, cwd can look like `@machine/...';
422 ignore everything before the first slash in such a case. */
423 while (*cwd
&& *cwd
!= '/')
430 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
432 fprintf (stderr
, "%s: Cannot get current working directory: %s\n",
433 argv
[0], strerror (errno
));
443 strcat (msgp
->mtext
, "-nowait ");
453 char *modified_arg
= argv
[0];
455 if (*modified_arg
== '+')
457 char *p
= modified_arg
+ 1;
458 while (*p
>= '0' && *p
<= '9') p
++;
462 else if (*modified_arg
!= '/')
465 modified_arg
= quote_file_name (modified_arg
);
468 used
+= strlen (cwd
);
469 used
+= strlen (modified_arg
) + 1;
470 while (used
+ 2 > size_allocated
)
473 msgp
= (struct msgbuf
*) realloc (msgp
,
474 (sizeof (struct msgbuf
)
479 strcat (msgp
->mtext
, cwd
);
481 strcat (msgp
->mtext
, modified_arg
);
482 strcat (msgp
->mtext
, " ");
485 strcat (msgp
->mtext
, "\n");
486 #ifdef HPUX /* HPUX has a bug. */
487 if (strlen (msgp
->mtext
) >= 512)
489 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
494 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
496 fprintf (stderr
, "%s: ", progname
);
501 /* Maybe wait for an answer. */
505 printf ("Waiting for Emacs...");
508 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
509 strcpy (buf
, msgp
->mtext
);
513 printf ("%s\n", buf
);
517 #endif /* HAVE_SYSVIPC */
519 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
521 #ifndef HAVE_STRERROR
526 extern char *sys_errlist
[];
529 if (errnum
>= 0 && errnum
< sys_nerr
)
530 return sys_errlist
[errnum
];
531 return (char *) "Unknown error";
534 #endif /* ! HAVE_STRERROR */