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 sprintf (server
.sun_path
, "/tmp/esrv%d-%s", geteuid (), system_name
);
230 if (stat (server
.sun_path
, &statbfr
) == -1)
234 "%s: can't find socket; have you started the server?\n",
237 fprintf (stderr
, "%s: can't stat %s: %s\n",
238 argv
[0], server
.sun_path
, strerror (errno
));
241 if (statbfr
.st_uid
!= geteuid ())
243 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
248 if ((homedir
= getenv ("HOME")) == NULL
)
250 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
253 strcpy (server
.sun_path
, homedir
);
254 strcat (server
.sun_path
, "/.emacs-server-");
255 gethostname (system_name
, sizeof (system_name
));
256 strcat (server
.sun_path
, system_name
);
259 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
262 fprintf (stderr
, "%s: ", argv
[0]);
267 /* We use the stream OUT to send our command to the server. */
268 if ((out
= fdopen (s
, "r+")) == NULL
)
270 fprintf (stderr
, "%s: ", argv
[0]);
275 /* We use the stream IN to read the response.
276 We used to use just one stream for both output and input
277 on the socket, but reversing direction works nonportably:
278 on some systems, the output appears as the first input;
279 on other systems it does not. */
280 if ((in
= fdopen (s
, "r+")) == NULL
)
282 fprintf (stderr
, "%s: ", argv
[0]);
288 cwd
= getwd (string
);
290 cwd
= getcwd (string
, sizeof string
);
294 /* getwd puts message in STRING if it fails. */
295 fprintf (stderr
, "%s: %s (%s)\n", argv
[0],
299 "Cannot get current working directory",
306 fprintf (out
, "-nowait ");
308 for (i
= optind
; i
< argc
; i
++)
312 char *p
= argv
[i
] + 1;
313 while (*p
>= '0' && *p
<= '9') p
++;
315 fprintf (out
, "%s/", cwd
);
317 else if (*argv
[i
] != '/')
318 fprintf (out
, "%s/", cwd
);
320 fprintf (out
, "%s ", quote_file_name (argv
[i
]));
325 /* Maybe wait for an answer. */
329 printf ("Waiting for Emacs...");
332 /* Now, wait for an answer and print any messages. On some systems,
333 the first line we read will actually be the output we just sent.
334 We can't predict whether that will happen, so if it does, we
335 detect it by recognizing `Client: ' at the beginning. */
337 while (str
= fgets (string
, BUFSIZ
, in
))
343 #else /* This is the SYSV IPC section */
345 #include <sys/types.h>
348 #include <sys/utsname.h>
353 char *getwd (), *getcwd (), *getenv ();
354 struct utsname system_name
;
362 /* Size of text allocated in MSGP. */
363 int size_allocated
= BUFSIZ
;
364 /* Amount of text used in MSGP. */
367 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
368 struct msqid_ds
* msg_st
;
369 char *homedir
, buf
[BUFSIZ
];
376 /* Process options. */
377 decode_options (argc
, argv
);
379 if (argc
- optind
< 1)
380 print_help_and_exit ();
383 * Create a message queue using ~/.emacs-server as the path for ftok
385 if ((homedir
= getenv ("HOME")) == NULL
)
387 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
390 strcpy (buf
, homedir
);
391 #ifndef HAVE_LONG_FILE_NAMES
392 /* If file names are short, we can't fit the host name. */
393 strcat (buf
, "/.emacs-server");
395 strcat (buf
, "/.emacs-server-");
396 uname (&system_name
);
397 strcat (buf
, system_name
.nodename
);
400 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
401 s
= msgget (key
, 0600 | IPC_CREAT
);
404 fprintf (stderr
, "%s: ", argv
[0]);
409 /* Determine working dir, so we can prefix it to all the arguments. */
411 temp
= getwd (gwdirb
);
413 temp
= getcwd (gwdirb
, sizeof gwdirb
);
419 /* On some systems, cwd can look like `@machine/...';
420 ignore everything before the first slash in such a case. */
421 while (*cwd
&& *cwd
!= '/')
428 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
430 fprintf (stderr
, "%s: Cannot get current working directory: %s\n",
431 argv
[0], strerror (errno
));
441 strcat (msgp
->mtext
, "-nowait ");
451 char *modified_arg
= argv
[0];
453 if (*modified_arg
== '+')
455 char *p
= modified_arg
+ 1;
456 while (*p
>= '0' && *p
<= '9') p
++;
460 else if (*modified_arg
!= '/')
463 modified_arg
= quote_file_name (modified_arg
);
466 used
+= strlen (cwd
);
467 used
+= strlen (modified_arg
) + 1;
468 while (used
+ 2 > size_allocated
)
471 msgp
= (struct msgbuf
*) realloc (msgp
,
472 (sizeof (struct msgbuf
)
477 strcat (msgp
->mtext
, cwd
);
479 strcat (msgp
->mtext
, modified_arg
);
480 strcat (msgp
->mtext
, " ");
483 strcat (msgp
->mtext
, "\n");
484 #ifdef HPUX /* HPUX has a bug. */
485 if (strlen (msgp
->mtext
) >= 512)
487 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
492 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
494 fprintf (stderr
, "%s: ", progname
);
499 /* Maybe wait for an answer. */
503 printf ("Waiting for Emacs...");
506 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
507 strcpy (buf
, msgp
->mtext
);
511 printf ("%s\n", buf
);
515 #endif /* HAVE_SYSVIPC */
517 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
519 #ifndef HAVE_STRERROR
524 extern char *sys_errlist
[];
527 if (errnum
>= 0 && errnum
< sys_nerr
)
528 return sys_errlist
[errnum
];
529 return (char *) "Unknown error";
532 #endif /* ! HAVE_STRERROR */