(both versions): Handle -nowait and --nowait by sending data to the server.
[bpt/emacs.git] / 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
31 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
32 #include <stdio.h>
33
34 main (argc, argv)
35 int argc;
36 char **argv;
37 {
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);
42 }
43
44 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
45
46 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
47 /* BSD code is very different from SYSV IPC code */
48
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>
55
56 extern char *strerror ();
57 extern int errno;
58
59 int
60 main (argc, argv)
61 int argc;
62 char **argv;
63 {
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];
70
71 char *getenv (), *getwd ();
72 char *getcwd ();
73 int geteuid ();
74 int nowait = 0;
75
76 if (argc < 2)
77 {
78 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
79 exit (1);
80 }
81
82 /*
83 * Open up an AF_UNIX socket in this person's home directory
84 */
85
86 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
87 {
88 fprintf (stderr, "%s: ", argv[0]);
89 perror ("socket");
90 exit (1);
91 }
92 server.sun_family = AF_UNIX;
93 #ifndef SERVER_HOME_DIR
94 {
95 struct stat statbfr;
96
97 gethostname (system_name, sizeof (system_name));
98 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
99
100 if (stat (server.sun_path, &statbfr) == -1)
101 {
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);
110 }
111 if (statbfr.st_uid != geteuid ())
112 {
113 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
114 exit (1);
115 }
116 }
117 #else
118 if ((homedir = getenv ("HOME")) == NULL)
119 {
120 fprintf (stderr, "%s: No home directory\n", argv[0]);
121 exit (1);
122 }
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
128
129 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
130 < 0)
131 {
132 fprintf (stderr, "%s: ", argv[0]);
133 perror ("connect");
134 exit (1);
135 }
136
137 /* We use the stream OUT to send our command to the server. */
138 if ((out = fdopen (s, "r+")) == NULL)
139 {
140 fprintf (stderr, "%s: ", argv[0]);
141 perror ("fdopen");
142 exit (1);
143 }
144
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)
151 {
152 fprintf (stderr, "%s: ", argv[0]);
153 perror ("fdopen");
154 exit (1);
155 }
156
157 #ifdef BSD
158 cwd = getwd (string);
159 #else
160 cwd = getcwd (string, sizeof string);
161 #endif
162 if (cwd == 0)
163 {
164 /* getwd puts message in STRING if it fails. */
165 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
166 exit (1);
167 }
168
169 for (i = 1; i < argc; i++)
170 {
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))
176 {
177 fprintf (out, "-nowait ");
178 nowait = 1;
179 continue;
180 }
181
182 if (*argv[i] == '+')
183 {
184 char *p = argv[i] + 1;
185 while (*p >= '0' && *p <= '9') p++;
186 if (*p != 0)
187 fprintf (out, "%s/", cwd);
188 }
189 else if (*argv[i] != '/')
190 fprintf (out, "%s/", cwd);
191 fprintf (out, "%s ", argv[i]);
192 }
193 fprintf (out, "\n");
194 fflush (out);
195
196 /* Maybe wait for an answer. */
197 if (nowait)
198 return 0;
199
200 printf ("Waiting for Emacs...");
201 fflush (stdout);
202
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. */
207
208 while (str = fgets (string, BUFSIZ, in))
209 printf ("%s", str);
210
211 return 0;
212 }
213
214 #else /* This is the SYSV IPC section */
215
216 #include <sys/types.h>
217 #include <sys/ipc.h>
218 #include <sys/msg.h>
219 #include <sys/utsname.h>
220 #include <stdio.h>
221
222 char *getwd (), *getcwd (), *getenv ();
223 struct utsname system_name;
224
225 main (argc, argv)
226 int argc;
227 char **argv;
228 {
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;
244
245 if (argc < 2)
246 {
247 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
248 exit (1);
249 }
250
251 /*
252 * Create a message queue using ~/.emacs-server as the path for ftok
253 */
254 if ((homedir = getenv ("HOME")) == NULL)
255 {
256 fprintf (stderr, "%s: No home directory\n", argv[0]);
257 exit (1);
258 }
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)
272 {
273 fprintf (stderr, "%s: ", argv[0]);
274 perror ("msgget");
275 exit (1);
276 }
277
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
284
285 cwd = gwdirb;
286 if (temp != 0)
287 {
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, "/");
293 }
294 else
295 {
296 fprintf (stderr, "%s: %s\n", argv[0], cwd);
297 exit (1);
298 }
299
300 msgp->mtext[0] = 0;
301 used = 0;
302 argc--; argv++;
303 while (argc)
304 {
305 int need_cwd = 0;
306 char *modified_arg = argv[0];
307
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))
313 {
314 modified_arg = "-nowait";
315 nowait = 1;
316 }
317 else if (*modified_arg == '+')
318 {
319 char *p = modified_arg + 1;
320 while (*p >= '0' && *p <= '9') p++;
321 if (*p != 0)
322 need_cwd = 1;
323 }
324 else if (*modified_arg != '/')
325 need_cwd = 1;
326
327 if (need_cwd)
328 used += strlen (cwd);
329 used += strlen (modified_arg) + 1;
330 while (used + 2 > size_allocated)
331 {
332 size_allocated *= 2;
333 msgp = (struct msgbuf *) realloc (msgp,
334 (sizeof (struct msgbuf)
335 + size_allocated));
336 }
337
338 if (need_cwd)
339 strcat (msgp->mtext, cwd);
340
341 strcat (msgp->mtext, modified_arg);
342 strcat (msgp->mtext, " ");
343 argv++; argc--;
344 }
345 strcat (msgp->mtext, "\n");
346 #ifdef HPUX /* HPUX has a bug. */
347 if (strlen (msgp->mtext) >= 512)
348 {
349 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
350 exit (1);
351 }
352 #endif
353 msgp->mtype = 1;
354 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
355 {
356 fprintf (stderr, "%s: ", progname);
357 perror ("msgsnd");
358 exit (1);
359 }
360
361 /* Maybe wait for an answer. */
362 if (nowait)
363 return 0;
364
365 printf ("Waiting for Emacs...");
366 fflush (stdout);
367
368 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
369 strcpy (buf, msgp->mtext);
370
371 printf ("\n");
372 if (*buf)
373 printf ("%s\n", buf);
374 exit (0);
375 }
376
377 #endif /* HAVE_SYSVIPC */
378
379 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
380 \f
381 #ifndef HAVE_STRERROR
382 char *
383 strerror (errnum)
384 int errnum;
385 {
386 extern char *sys_errlist[];
387 extern int sys_nerr;
388
389 if (errnum >= 0 && errnum < sys_nerr)
390 return sys_errlist[errnum];
391 return (char *) "Unknown error";
392 }
393
394 #endif /* ! HAVE_STRERROR */