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>
33 char *getenv (), *getwd ();
37 /* This is defined with -D from the compilation command,
38 which extracts it from ../lisp/version.el. */
41 #define VERSION "unspecified"
44 /* Name used to invoke this program. */
47 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
50 struct option longopts
[] =
52 { "no-wait", no_argument
, NULL
, 'n' },
53 { "help", no_argument
, NULL
, 'H' },
54 { "version", no_argument
, NULL
, 'V' },
58 /* Decode the options from argv and argc.
59 The global variable `optind' will say how many arguments we used up. */
62 decode_options (argc
, argv
)
68 int opt
= getopt_long (argc
, argv
,
77 /* If getopt returns 0, then it has already processed a
78 long-named option. We should do nothing. */
86 fprintf (stderr
, "Version %s\n", VERSION
);
92 print_help_and_exit ();
97 print_help_and_exit ()
100 "Usage: %s [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
103 "Report bugs to bug-gnu-emacs@prep.ai.mit.edu.\n");
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. */
113 quote_file_name (name
)
116 char *copy
= (char *) malloc (strlen (name
) * 2 + 1);
131 if (*p
== '&' || (*p
== '-' && p
== name
))
142 /* Like malloc but get fatal error if memory is exhausted. */
148 char *result
= (char *) malloc (size
);
156 #endif /* C_ALLOCA */
158 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
164 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
166 fprintf (stderr
, "on systems with Berkeley sockets or System V IPC.\n");
170 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
172 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
173 /* BSD code is very different from SYSV IPC code */
175 #include <sys/types.h>
176 #include <sys/socket.h>
178 #include <sys/stat.h>
181 extern char *strerror ();
189 char system_name
[32];
192 struct sockaddr_un server
;
193 char *homedir
, *cwd
, *str
;
198 /* Process options. */
199 decode_options (argc
, argv
);
201 if (argc
- optind
< 1)
202 print_help_and_exit ();
205 * Open up an AF_UNIX socket in this person's home directory
208 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
210 fprintf (stderr
, "%s: ", argv
[0]);
214 server
.sun_family
= AF_UNIX
;
215 #ifndef SERVER_HOME_DIR
219 gethostname (system_name
, sizeof (system_name
));
220 sprintf (server
.sun_path
, "/tmp/esrv%d-%s", geteuid (), system_name
);
222 if (stat (server
.sun_path
, &statbfr
) == -1)
226 "%s: can't find socket; have you started the server?\n",
229 fprintf (stderr
, "%s: can't stat %s: %s\n",
230 argv
[0], server
.sun_path
, strerror (errno
));
233 if (statbfr
.st_uid
!= geteuid ())
235 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
240 if ((homedir
= getenv ("HOME")) == NULL
)
242 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
245 strcpy (server
.sun_path
, homedir
);
246 strcat (server
.sun_path
, "/.emacs-server-");
247 gethostname (system_name
, sizeof (system_name
));
248 strcat (server
.sun_path
, system_name
);
251 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
254 fprintf (stderr
, "%s: ", argv
[0]);
259 /* We use the stream OUT to send our command to the server. */
260 if ((out
= fdopen (s
, "r+")) == NULL
)
262 fprintf (stderr
, "%s: ", argv
[0]);
267 /* We use the stream IN to read the response.
268 We used to use just one stream for both output and input
269 on the socket, but reversing direction works nonportably:
270 on some systems, the output appears as the first input;
271 on other systems it does not. */
272 if ((in
= fdopen (s
, "r+")) == NULL
)
274 fprintf (stderr
, "%s: ", argv
[0]);
280 cwd
= getwd (string
);
282 cwd
= getcwd (string
, sizeof string
);
286 /* getwd puts message in STRING if it fails. */
287 fprintf (stderr
, "%s: %s (%s)\n", argv
[0],
291 "Cannot get current working directory",
298 fprintf (out
, "-nowait ");
300 for (i
= optind
; i
< argc
; i
++)
304 char *p
= argv
[i
] + 1;
305 while (*p
>= '0' && *p
<= '9') p
++;
307 fprintf (out
, "%s/", cwd
);
309 else if (*argv
[i
] != '/')
310 fprintf (out
, "%s/", cwd
);
312 fprintf (out
, "%s ", quote_file_name (argv
[i
]));
317 /* Maybe wait for an answer. */
321 printf ("Waiting for Emacs...");
324 /* Now, wait for an answer and print any messages. On some systems,
325 the first line we read will actually be the output we just sent.
326 We can't predict whether that will happen, so if it does, we
327 detect it by recognizing `Client: ' at the beginning. */
329 while (str
= fgets (string
, BUFSIZ
, in
))
335 #else /* This is the SYSV IPC section */
337 #include <sys/types.h>
340 #include <sys/utsname.h>
345 char *getwd (), *getcwd (), *getenv ();
346 struct utsname system_name
;
354 /* Size of text allocated in MSGP. */
355 int size_allocated
= BUFSIZ
;
356 /* Amount of text used in MSGP. */
359 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
360 struct msqid_ds
* msg_st
;
361 char *homedir
, buf
[BUFSIZ
];
368 /* Process options. */
369 decode_options (argc
, argv
);
371 if (argc
- optind
< 1)
372 print_help_and_exit ();
375 * Create a message queue using ~/.emacs-server as the path for ftok
377 if ((homedir
= getenv ("HOME")) == NULL
)
379 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
382 strcpy (buf
, homedir
);
383 #ifndef HAVE_LONG_FILE_NAMES
384 /* If file names are short, we can't fit the host name. */
385 strcat (buf
, "/.emacs-server");
387 strcat (buf
, "/.emacs-server-");
388 uname (&system_name
);
389 strcat (buf
, system_name
.nodename
);
392 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
393 s
= msgget (key
, 0600 | IPC_CREAT
);
396 fprintf (stderr
, "%s: ", argv
[0]);
401 /* Determine working dir, so we can prefix it to all the arguments. */
403 temp
= getwd (gwdirb
);
405 temp
= getcwd (gwdirb
, sizeof gwdirb
);
411 /* On some systems, cwd can look like `@machine/...';
412 ignore everything before the first slash in such a case. */
413 while (*cwd
&& *cwd
!= '/')
420 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
422 fprintf (stderr
, "%s: Cannot get current working directory: %s\n",
423 argv
[0], strerror (errno
));
433 strcat (msgp
->mtext
, "-nowait ");
443 char *modified_arg
= argv
[0];
445 if (*modified_arg
== '+')
447 char *p
= modified_arg
+ 1;
448 while (*p
>= '0' && *p
<= '9') p
++;
452 else if (*modified_arg
!= '/')
455 modified_arg
= quote_file_name (modified_arg
);
458 used
+= strlen (cwd
);
459 used
+= strlen (modified_arg
) + 1;
460 while (used
+ 2 > size_allocated
)
463 msgp
= (struct msgbuf
*) realloc (msgp
,
464 (sizeof (struct msgbuf
)
469 strcat (msgp
->mtext
, cwd
);
471 strcat (msgp
->mtext
, modified_arg
);
472 strcat (msgp
->mtext
, " ");
475 strcat (msgp
->mtext
, "\n");
476 #ifdef HPUX /* HPUX has a bug. */
477 if (strlen (msgp
->mtext
) >= 512)
479 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
484 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
486 fprintf (stderr
, "%s: ", progname
);
491 /* Maybe wait for an answer. */
495 printf ("Waiting for Emacs...");
498 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
499 strcpy (buf
, msgp
->mtext
);
503 printf ("%s\n", buf
);
507 #endif /* HAVE_SYSVIPC */
509 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
511 #ifndef HAVE_STRERROR
516 extern char *sys_errlist
[];
519 if (errnum
>= 0 && errnum
< sys_nerr
)
520 return sys_errlist
[errnum
];
521 return (char *) "Unknown error";
524 #endif /* ! HAVE_STRERROR */