]> code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
(main) [HAVE_SOCKETS]: Use two separate stdio
[gnu-emacs] / 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
75 if (argc < 2)
76 {
77 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
78 exit (1);
79 }
80
81 /*
82 * Open up an AF_UNIX socket in this person's home directory
83 */
84
85 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
86 {
87 fprintf (stderr, "%s: ", argv[0]);
88 perror ("socket");
89 exit (1);
90 }
91 server.sun_family = AF_UNIX;
92 #ifndef SERVER_HOME_DIR
93 {
94 struct stat statbfr;
95
96 gethostname (system_name, sizeof (system_name));
97 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
98
99 if (stat (server.sun_path, &statbfr) == -1)
100 {
101 if (errno == ENOENT)
102 fprintf (stderr,
103 "%s: can't find socket; have you started the server?\n",
104 argv[0]);
105 else
106 fprintf (stderr, "%s: can't stat %s: %s\n",
107 argv[0], server.sun_path, strerror (errno));
108 exit (1);
109 }
110 if (statbfr.st_uid != geteuid ())
111 {
112 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
113 exit (1);
114 }
115 }
116 #else
117 if ((homedir = getenv ("HOME")) == NULL)
118 {
119 fprintf (stderr, "%s: No home directory\n", argv[0]);
120 exit (1);
121 }
122 strcpy (server.sun_path, homedir);
123 strcat (server.sun_path, "/.emacs-server-");
124 gethostname (system_name, sizeof (system_name));
125 strcat (server.sun_path, system_name);
126 #endif
127
128 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
129 < 0)
130 {
131 fprintf (stderr, "%s: ", argv[0]);
132 perror ("connect");
133 exit (1);
134 }
135
136 /* We use the stream OUT to send our command to the server. */
137 if ((out = fdopen (s, "r+")) == NULL)
138 {
139 fprintf (stderr, "%s: ", argv[0]);
140 perror ("fdopen");
141 exit (1);
142 }
143
144 /* We use the stream IN to read the response.
145 We used to use just one stream for both output and input
146 on the socket, but reversing direction works nonportably:
147 on some systems, the output appears as the first input;
148 on other systems it does not. */
149 if ((in = fdopen (s, "r+")) == NULL)
150 {
151 fprintf (stderr, "%s: ", argv[0]);
152 perror ("fdopen");
153 exit (1);
154 }
155
156 #ifdef BSD
157 cwd = getwd (string);
158 #else
159 cwd = getcwd (string, sizeof string);
160 #endif
161 if (cwd == 0)
162 {
163 /* getwd puts message in STRING if it fails. */
164 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
165 exit (1);
166 }
167
168 for (i = 1; i < argc; i++)
169 {
170 if (*argv[i] == '+')
171 {
172 char *p = argv[i] + 1;
173 while (*p >= '0' && *p <= '9') p++;
174 if (*p != 0)
175 fprintf (out, "%s/", cwd);
176 }
177 else if (*argv[i] != '/')
178 fprintf (out, "%s/", cwd);
179 fprintf (out, "%s ", argv[i]);
180 }
181 fprintf (out, "\n");
182 fflush (out);
183
184 printf ("Waiting for Emacs...");
185 fflush (stdout);
186
187 /* Now, wait for an answer and print any messages. On some systems,
188 the first line we read will actually be the output we just sent.
189 We can't predict whether that will happen, so if it does, we
190 detect it by recognizing `Client: ' at the beginning. */
191
192 while (str = fgets (string, BUFSIZ, in))
193 printf ("%s", str);
194
195 return 0;
196 }
197
198 #else /* This is the SYSV IPC section */
199
200 #include <sys/types.h>
201 #include <sys/ipc.h>
202 #include <sys/msg.h>
203 #include <sys/utsname.h>
204 #include <stdio.h>
205
206 char *getwd (), *getcwd (), *getenv ();
207 struct utsname system_name;
208
209 main (argc, argv)
210 int argc;
211 char **argv;
212 {
213 int s;
214 key_t key;
215 /* Size of text allocated in MSGP. */
216 int size_allocated = BUFSIZ;
217 /* Amount of text used in MSGP. */
218 int used;
219 struct msgbuf *msgp
220 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated);
221 struct msqid_ds * msg_st;
222 char *homedir, buf[BUFSIZ];
223 char gwdirb[BUFSIZ];
224 char *cwd;
225 char *temp;
226 char *progname = argv[0];
227
228 if (argc < 2)
229 {
230 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
231 exit (1);
232 }
233
234 /*
235 * Create a message queue using ~/.emacs-server as the path for ftok
236 */
237 if ((homedir = getenv ("HOME")) == NULL)
238 {
239 fprintf (stderr, "%s: No home directory\n", argv[0]);
240 exit (1);
241 }
242 strcpy (buf, homedir);
243 #ifndef HAVE_LONG_FILE_NAMES
244 /* If file names are short, we can't fit the host name. */
245 strcat (buf, "/.emacs-server");
246 #else
247 strcat (buf, "/.emacs-server-");
248 uname (&system_name);
249 strcat (buf, system_name.nodename);
250 #endif
251 creat (buf, 0600);
252 key = ftok (buf, 1); /* unlikely to be anyone else using it */
253 s = msgget (key, 0600 | IPC_CREAT);
254 if (s == -1)
255 {
256 fprintf (stderr, "%s: ", argv[0]);
257 perror ("msgget");
258 exit (1);
259 }
260
261 /* Determine working dir, so we can prefix it to all the arguments. */
262 #ifdef BSD
263 temp = getwd (gwdirb);
264 #else
265 temp = getcwd (gwdirb, sizeof gwdirb);
266 #endif
267
268 cwd = gwdirb;
269 if (temp != 0)
270 {
271 /* On some systems, cwd can look like `@machine/...';
272 ignore everything before the first slash in such a case. */
273 while (*cwd && *cwd != '/')
274 cwd++;
275 strcat (cwd, "/");
276 }
277 else
278 {
279 fprintf (stderr, "%s: %s\n", argv[0], cwd);
280 exit (1);
281 }
282
283 msgp->mtext[0] = 0;
284 used = 0;
285 argc--; argv++;
286 while (argc)
287 {
288 int need_cwd = 0;
289 char *modified_arg = argv[0];
290 if (*modified_arg == '+')
291 {
292 char *p = modified_arg + 1;
293 while (*p >= '0' && *p <= '9') p++;
294 if (*p != 0)
295 need_cwd = 1;
296 }
297 else if (*modified_arg != '/')
298 need_cwd = 1;
299
300 if (need_cwd)
301 used += strlen (cwd);
302 used += strlen (modified_arg) + 1;
303 while (used + 2 > size_allocated)
304 {
305 size_allocated *= 2;
306 msgp = (struct msgbuf *) realloc (msgp,
307 (sizeof (struct msgbuf)
308 + size_allocated));
309 }
310
311 if (need_cwd)
312 strcat (msgp->mtext, cwd);
313
314 strcat (msgp->mtext, modified_arg);
315 strcat (msgp->mtext, " ");
316 argv++; argc--;
317 }
318 strcat (msgp->mtext, "\n");
319 #ifdef HPUX /* HPUX has a bug. */
320 if (strlen (msgp->mtext) >= 512)
321 {
322 fprintf (stderr, "%s: args too long for msgsnd\n", progname);
323 exit (1);
324 }
325 #endif
326 msgp->mtype = 1;
327 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
328 {
329 fprintf (stderr, "%s: ", progname);
330 perror ("msgsnd");
331 exit (1);
332 }
333 /*
334 * Now, wait for an answer
335 */
336 printf ("Waiting for Emacs...");
337 fflush (stdout);
338
339 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */
340 strcpy (buf, msgp->mtext);
341
342 printf ("\n");
343 if (*buf)
344 printf ("%s\n", buf);
345 exit (0);
346 }
347
348 #endif /* HAVE_SYSVIPC */
349
350 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
351 \f
352 #ifndef HAVE_STRERROR
353 char *
354 strerror (errnum)
355 int errnum;
356 {
357 extern char *sys_errlist[];
358 extern int sys_nerr;
359
360 if (errnum >= 0 && errnum < sys_nerr)
361 return sys_errlist[errnum];
362 return (char *) "Unknown error";
363 }
364
365 #endif /* ! HAVE_STRERROR */