(make-doctor-variables): Eliminate unused variables `elist'
[emacs.git] / lib-src / emacsclient.c
blobc2940294ff9dd003129884939770aecea455fc0f
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)
9 any later version.
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. */
22 #define NO_SHORTNAMES
23 #include <../src/config.h>
24 #undef read
25 #undef write
26 #undef open
27 #undef close
28 #undef signal
31 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
32 #include <stdio.h>
34 main (argc, argv)
35 int argc;
36 char **argv;
38 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
39 argv[0]);
40 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
41 exit (1);
44 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
46 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
47 /* BSD code is very different from SYSV IPC code */
49 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <sys/un.h>
52 #include <sys/stat.h>
53 #include <stdio.h>
54 #include <errno.h>
56 extern char *strerror ();
57 extern int errno;
59 int
60 main (argc, argv)
61 int argc;
62 char **argv;
64 char system_name[32];
65 int s, i;
66 FILE *out, *in;
67 struct sockaddr_un server;
68 char *homedir, *cwd, *str;
69 char string[BUFSIZ];
71 char *getenv (), *getwd ();
72 char *getcwd ();
73 int geteuid ();
74 int nowait = 0;
76 if (argc < 2)
78 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
79 exit (1);
82 /*
83 * Open up an AF_UNIX socket in this person's home directory
86 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
88 fprintf (stderr, "%s: ", argv[0]);
89 perror ("socket");
90 exit (1);
92 server.sun_family = AF_UNIX;
93 #ifndef SERVER_HOME_DIR
95 struct stat statbfr;
97 gethostname (system_name, sizeof (system_name));
98 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
100 if (stat (server.sun_path, &statbfr) == -1)
102 if (errno == ENOENT)
103 fprintf (stderr,
104 "%s: can't find socket; have you started the server?\n",
105 argv[0]);
106 else
107 fprintf (stderr, "%s: can't stat %s: %s\n",
108 argv[0], server.sun_path, strerror (errno));
109 exit (1);
111 if (statbfr.st_uid != geteuid ())
113 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
114 exit (1);
117 #else
118 if ((homedir = getenv ("HOME")) == NULL)
120 fprintf (stderr, "%s: No home directory\n", argv[0]);
121 exit (1);
123 strcpy (server.sun_path, homedir);
124 strcat (server.sun_path, "/.emacs-server-");
125 gethostname (system_name, sizeof (system_name));
126 strcat (server.sun_path, system_name);
127 #endif
129 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
130 < 0)
132 fprintf (stderr, "%s: ", argv[0]);
133 perror ("connect");
134 exit (1);
137 /* We use the stream OUT to send our command to the server. */
138 if ((out = fdopen (s, "r+")) == NULL)
140 fprintf (stderr, "%s: ", argv[0]);
141 perror ("fdopen");
142 exit (1);
145 /* We use the stream IN to read the response.
146 We used to use just one stream for both output and input
147 on the socket, but reversing direction works nonportably:
148 on some systems, the output appears as the first input;
149 on other systems it does not. */
150 if ((in = fdopen (s, "r+")) == NULL)
152 fprintf (stderr, "%s: ", argv[0]);
153 perror ("fdopen");
154 exit (1);
157 #ifdef BSD
158 cwd = getwd (string);
159 #else
160 cwd = getcwd (string, sizeof string);
161 #endif
162 if (cwd == 0)
164 /* getwd puts message in STRING if it fails. */
165 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
166 exit (1);
169 for (i = 1; i < argc; i++)
171 /* If -nowait or --nowait option is used,
172 report it to the server. */
173 if (!strcmp (argv[i], "-nowait")
174 || (!strncmp (argv[i], "--nowait", strlen (argv[i]))
175 && strlen (argv[i]) >= 3))
177 fprintf (out, "-nowait ");
178 nowait = 1;
179 continue;
182 if (*argv[i] == '+')
184 char *p = argv[i] + 1;
185 while (*p >= '0' && *p <= '9') p++;
186 if (*p != 0)
187 fprintf (out, "%s/", cwd);
189 else if (*argv[i] != '/')
190 fprintf (out, "%s/", cwd);
191 fprintf (out, "%s ", argv[i]);
193 fprintf (out, "\n");
194 fflush (out);
196 /* Maybe wait for an answer. */
197 if (nowait)
198 return 0;
200 printf ("Waiting for Emacs...");
201 fflush (stdout);
203 /* Now, wait for an answer and print any messages. On some systems,
204 the first line we read will actually be the output we just sent.
205 We can't predict whether that will happen, so if it does, we
206 detect it by recognizing `Client: ' at the beginning. */
208 while (str = fgets (string, BUFSIZ, in))
209 printf ("%s", str);
211 return 0;
214 #else /* This is the SYSV IPC section */
216 #include <sys/types.h>
217 #include <sys/ipc.h>
218 #include <sys/msg.h>
219 #include <sys/utsname.h>
220 #include <stdio.h>
222 char *getwd (), *getcwd (), *getenv ();
223 struct utsname system_name;
225 main (argc, argv)
226 int argc;
227 char **argv;
229 int s;
230 key_t key;
231 /* Size of text allocated in MSGP. */
232 int size_allocated = BUFSIZ;
233 /* Amount of text used in MSGP. */
234 int used;
235 struct msgbuf *msgp
236 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
237 struct msqid_ds * msg_st;
238 char *homedir, buf[BUFSIZ];
239 char gwdirb[BUFSIZ];
240 char *cwd;
241 char *temp;
242 char *progname = argv[0];
243 int nowait = 0;
245 if (argc < 2)
247 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
248 exit (1);
252 * Create a message queue using ~/.emacs-server as the path for ftok
254 if ((homedir = getenv ("HOME")) == NULL)
256 fprintf (stderr, "%s: No home directory\n", argv[0]);
257 exit (1);
259 strcpy (buf, homedir);
260 #ifndef HAVE_LONG_FILE_NAMES
261 /* If file names are short, we can't fit the host name. */
262 strcat (buf, "/.emacs-server");
263 #else
264 strcat (buf, "/.emacs-server-");
265 uname (&system_name);
266 strcat (buf, system_name.nodename);
267 #endif
268 creat (buf, 0600);
269 key = ftok (buf, 1); /* unlikely to be anyone else using it */
270 s = msgget (key, 0600 | IPC_CREAT);
271 if (s == -1)
273 fprintf (stderr, "%s: ", argv[0]);
274 perror ("msgget");
275 exit (1);
278 /* Determine working dir, so we can prefix it to all the arguments. */
279 #ifdef BSD
280 temp = getwd (gwdirb);
281 #else
282 temp = getcwd (gwdirb, sizeof gwdirb);
283 #endif
285 cwd = gwdirb;
286 if (temp != 0)
288 /* On some systems, cwd can look like `@machine/...';
289 ignore everything before the first slash in such a case. */
290 while (*cwd && *cwd != '/')
291 cwd++;
292 strcat (cwd, "/");
294 else
296 fprintf (stderr, "%s: %s\n", argv[0], cwd);
297 exit (1);
300 msgp->mtext[0] = 0;
301 used = 0;
302 argc--; argv++;
303 while (argc)
305 int need_cwd = 0;
306 char *modified_arg = argv[0];
308 /* If -nowait or --nowait option is used,
309 report it to the server. */
310 if (!strcmp (modified_arg, "-nowait")
311 || (!strncmp (modified_arg, "--nowait", strlen (modified_arg))
312 && strlen (modified_arg) >= 3))
314 modified_arg = "-nowait";
315 nowait = 1;
317 else if (*modified_arg == '+')
319 char *p = modified_arg + 1;
320 while (*p >= '0' && *p <= '9') p++;
321 if (*p != 0)
322 need_cwd = 1;
324 else if (*modified_arg != '/')
325 need_cwd = 1;
327 if (need_cwd)
328 used += strlen (cwd);
329 used += strlen (modified_arg) + 1;
330 while (used + 2 > size_allocated)
332 size_allocated *= 2;
333 msgp = (struct msgbuf *) realloc (msgp,
334 (sizeof (struct msgbuf)
335 + size_allocated));
338 if (need_cwd)
339 strcat (msgp->mtext, cwd);
341 strcat (msgp->mtext, modified_arg);
342 strcat (msgp->mtext, " ");
343 argv++; argc--;
345 strcat (msgp->mtext, "\n");
346 #ifdef HPUX /* HPUX has a bug. */
347 if (strlen (msgp->mtext) >= 512)
349 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
350 exit (1);
352 #endif
353 msgp->mtype = 1;
354 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
356 fprintf (stderr, "%s: ", progname);
357 perror ("msgsnd");
358 exit (1);
361 /* Maybe wait for an answer. */
362 if (nowait)
363 return 0;
365 printf ("Waiting for Emacs...");
366 fflush (stdout);
368 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
369 strcpy (buf, msgp->mtext);
371 printf ("\n");
372 if (*buf)
373 printf ("%s\n", buf);
374 exit (0);
377 #endif /* HAVE_SYSVIPC */
379 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
381 #ifndef HAVE_STRERROR
382 char *
383 strerror (errnum)
384 int errnum;
386 extern char *sys_errlist[];
387 extern int sys_nerr;
389 if (errnum >= 0 && errnum < sys_nerr)
390 return sys_errlist[errnum];
391 return (char *) "Unknown error";
394 #endif /* ! HAVE_STRERROR */