[windows-nt, ms-dos]: Load dos-nt.
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
efb859b4 1/* Client process that communicates with GNU Emacs acting as server.
92af894f 2 Copyright (C) 1986, 1987, 1994 Free Software Foundation, Inc.
46cec291
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
92af894f 8the Free Software Foundation; either version 2, or (at your option)
46cec291
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
46cec291
RS
20
21
22#define NO_SHORTNAMES
18160b98 23#include <../src/config.h>
46cec291
RS
24#undef read
25#undef write
26#undef open
46cec291 27#undef close
4e23f2ba 28#undef signal
46cec291
RS
29
30
b135a7cf 31#if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
46cec291
RS
32#include <stdio.h>
33
34main (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
1e523e3d 46#if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291
RS
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>
efb859b4 52#include <sys/stat.h>
46cec291
RS
53#include <stdio.h>
54#include <errno.h>
55
92af894f 56extern char *strerror ();
46cec291
RS
57extern int errno;
58
340ff9de 59int
46cec291
RS
60main (argc, argv)
61 int argc;
62 char **argv;
63{
64 char system_name[32];
65 int s, i;
23a7488d 66 FILE *out, *in;
46cec291
RS
67 struct sockaddr_un server;
68 char *homedir, *cwd, *str;
69 char string[BUFSIZ];
70
71 char *getenv (), *getwd ();
7e1251a1 72 char *getcwd ();
46cec291 73 int geteuid ();
292d74a3 74 int nowait = 0;
46cec291
RS
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
efb859b4
JB
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 {
c0acc3e1
JB
102 if (errno == ENOENT)
103 fprintf (stderr,
18a2fa91
KH
104 "%s: can't find socket; have you started the server?\n",
105 argv[0]);
c0acc3e1 106 else
18a2fa91
KH
107 fprintf (stderr, "%s: can't stat %s: %s\n",
108 argv[0], server.sun_path, strerror (errno));
efb859b4
JB
109 exit (1);
110 }
b135a7cf 111 if (statbfr.st_uid != geteuid ())
efb859b4 112 {
18a2fa91 113 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
efb859b4
JB
114 exit (1);
115 }
116 }
46cec291
RS
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);
b135a7cf
RS
124 strcat (server.sun_path, "/.emacs-server-");
125 gethostname (system_name, sizeof (system_name));
126 strcat (server.sun_path, system_name);
46cec291
RS
127#endif
128
4e23f2ba
JB
129 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
130 < 0)
46cec291
RS
131 {
132 fprintf (stderr, "%s: ", argv[0]);
133 perror ("connect");
134 exit (1);
135 }
23a7488d
RS
136
137 /* We use the stream OUT to send our command to the server. */
46cec291
RS
138 if ((out = fdopen (s, "r+")) == NULL)
139 {
140 fprintf (stderr, "%s: ", argv[0]);
141 perror ("fdopen");
142 exit (1);
143 }
144
23a7488d
RS
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
ee6a193c 157#ifdef BSD
46cec291 158 cwd = getwd (string);
ee6a193c
RS
159#else
160 cwd = getcwd (string, sizeof string);
161#endif
46cec291
RS
162 if (cwd == 0)
163 {
164 /* getwd puts message in STRING if it fails. */
92af894f 165 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
46cec291
RS
166 exit (1);
167 }
168
169 for (i = 1; i < argc; i++)
170 {
292d74a3
RS
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
46cec291
RS
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
292d74a3
RS
196 /* Maybe wait for an answer. */
197 if (nowait)
198 return 0;
199
46cec291
RS
200 printf ("Waiting for Emacs...");
201 fflush (stdout);
202
23a7488d
RS
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. */
46cec291 207
23a7488d 208 while (str = fgets (string, BUFSIZ, in))
46cec291 209 printf ("%s", str);
23a7488d 210
340ff9de 211 return 0;
46cec291
RS
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>
b135a7cf 219#include <sys/utsname.h>
46cec291
RS
220#include <stdio.h>
221
1518a9eb 222char *getwd (), *getcwd (), *getenv ();
b135a7cf 223struct utsname system_name;
1518a9eb 224
46cec291
RS
225main (argc, argv)
226 int argc;
227 char **argv;
228{
229 int s;
230 key_t key;
1518a9eb
RS
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);
46cec291
RS
237 struct msqid_ds * msg_st;
238 char *homedir, buf[BUFSIZ];
239 char gwdirb[BUFSIZ];
240 char *cwd;
241 char *temp;
defb80d7 242 char *progname = argv[0];
292d74a3 243 int nowait = 0;
46cec291
RS
244
245 if (argc < 2)
246 {
247 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
248 exit (1);
249 }
250
251 /*
b135a7cf 252 * Create a message queue using ~/.emacs-server as the path for ftok
46cec291
RS
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);
b135a7cf
RS
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
46cec291
RS
268 creat (buf, 0600);
269 key = ftok (buf, 1); /* unlikely to be anyone else using it */
61a93162 270 s = msgget (key, 0600 | IPC_CREAT);
46cec291
RS
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 {
26396b1b 296 fprintf (stderr, "%s: %s\n", argv[0], cwd);
46cec291
RS
297 exit (1);
298 }
299
300 msgp->mtext[0] = 0;
1518a9eb 301 used = 0;
46cec291
RS
302 argc--; argv++;
303 while (argc)
304 {
1518a9eb 305 int need_cwd = 0;
cd33a5a0 306 char *modified_arg = argv[0];
292d74a3
RS
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 == '+')
46cec291 318 {
cd33a5a0 319 char *p = modified_arg + 1;
46cec291
RS
320 while (*p >= '0' && *p <= '9') p++;
321 if (*p != 0)
1518a9eb 322 need_cwd = 1;
46cec291 323 }
cd33a5a0 324 else if (*modified_arg != '/')
1518a9eb
RS
325 need_cwd = 1;
326
327 if (need_cwd)
328 used += strlen (cwd);
cd33a5a0 329 used += strlen (modified_arg) + 1;
1518a9eb
RS
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)
46cec291
RS
339 strcat (msgp->mtext, cwd);
340
cd33a5a0 341 strcat (msgp->mtext, modified_arg);
46cec291
RS
342 strcat (msgp->mtext, " ");
343 argv++; argc--;
344 }
345 strcat (msgp->mtext, "\n");
1518a9eb
RS
346#ifdef HPUX /* HPUX has a bug. */
347 if (strlen (msgp->mtext) >= 512)
348 {
18a2fa91 349 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
1518a9eb
RS
350 exit (1);
351 }
352#endif
46cec291
RS
353 msgp->mtype = 1;
354 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
355 {
defb80d7 356 fprintf (stderr, "%s: ", progname);
46cec291
RS
357 perror ("msgsnd");
358 exit (1);
359 }
292d74a3
RS
360
361 /* Maybe wait for an answer. */
362 if (nowait)
363 return 0;
364
46cec291
RS
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
dc3c30fe
KH
371 printf ("\n");
372 if (*buf)
373 printf ("%s\n", buf);
46cec291
RS
374 exit (0);
375}
376
377#endif /* HAVE_SYSVIPC */
378
379#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
27711600
RM
380\f
381#ifndef HAVE_STRERROR
382char *
383strerror (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 */