Mercurial > hg > xemacs-beta
comparison lib-src/emacsclient.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | bcdc7deadc19 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Client process that communicates with GNU Emacs acting as server. | |
2 Copyright (C) 1986, 1987, 1993, 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 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: FSF 19.28. */ | |
22 | |
23 #define NO_SHORTNAMES | |
24 #include <../src/config.h> | |
25 #undef read | |
26 #undef write | |
27 #undef open | |
28 #undef close | |
29 #undef signal | |
30 | |
31 #if __STDC__ || defined(STDC_HEADERS) | |
32 #include <stdlib.h> | |
33 #include <unistd.h> | |
34 #include <fcntl.h> /* for creat() */ | |
35 #include <string.h> | |
36 #endif | |
37 | |
38 #if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC) | |
39 #include <stdio.h> | |
40 | |
41 main (argc, argv) | |
42 int argc; | |
43 char **argv; | |
44 { | |
45 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n", | |
46 argv[0]); | |
47 fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n"); | |
48 exit (1); | |
49 } | |
50 | |
51 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */ | |
52 | |
53 #if ! defined (HAVE_SYSVIPC) | |
54 /* BSD code is very different from SYSV IPC code */ | |
55 | |
56 #include <sys/types.h> | |
57 #include <sys/socket.h> | |
58 #include <sys/un.h> | |
59 #include <sys/stat.h> | |
60 #include <stdio.h> | |
61 #include <errno.h> | |
62 | |
63 extern char *strerror (); | |
64 extern int errno; | |
65 | |
66 void | |
67 main (argc, argv) | |
68 int argc; | |
69 char **argv; | |
70 { | |
71 char system_name[256]; | |
72 int s, i; | |
73 FILE *out; | |
74 struct sockaddr_un server; | |
75 char *cwd, *str; | |
76 char string[BUFSIZ]; | |
77 | |
78 if (argc < 2) | |
79 { | |
80 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]); | |
81 exit (1); | |
82 } | |
83 | |
84 /* | |
85 * Open up an AF_UNIX socket in this person's home directory | |
86 */ | |
87 | |
88 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) | |
89 { | |
90 fprintf (stderr, "%s: ", argv[0]); | |
91 perror ("socket"); | |
92 exit (1); | |
93 } | |
94 server.sun_family = AF_UNIX; | |
95 #ifndef SERVER_HOME_DIR | |
96 { | |
97 struct stat statbfr; | |
98 | |
99 gethostname (system_name, sizeof (system_name)); | |
100 sprintf (server.sun_path, "/tmp/esrv%d-%s", (int) geteuid (), system_name); | |
101 | |
102 if (stat (server.sun_path, &statbfr) == -1) | |
103 { | |
104 if (errno == ENOENT) | |
105 fprintf (stderr, | |
106 "Can't find socket; have you started the server?\n"); | |
107 else | |
108 perror ("stat"); | |
109 exit (1); | |
110 } | |
111 if (statbfr.st_uid != geteuid()) | |
112 { | |
113 fprintf (stderr, "Illegal socket owner\n"); | |
114 exit (1); | |
115 } | |
116 } | |
117 #else | |
118 if (getenv ("HOME") == NULL) | |
119 { | |
120 fprintf (stderr, "%s: No home directory\n", argv[0]); | |
121 exit (1); | |
122 } | |
123 sprintf (server.sun_path, "/tmp/esrv%d", geteuid ()); | |
124 #if 0 | |
125 strcpy (server.sun_path, getenv ("HOME")); | |
126 strcat (server.sun_path, "/.emacs_server"); | |
127 #endif | |
128 #endif /* SERVER_HOME_DIR */ | |
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 if ((out = (FILE *) fdopen (s, "r+")) == NULL) | |
137 { | |
138 fprintf (stderr, "%s: ", argv[0]); | |
139 perror ("fdopen"); | |
140 exit (1); | |
141 } | |
142 | |
143 #ifdef BSD | |
144 cwd = (char *) getwd (string); | |
145 #else | |
146 cwd = (char *) getcwd (string, sizeof (string)); | |
147 #endif | |
148 | |
149 if (cwd == 0) | |
150 { | |
151 /* getwd puts message in STRING if it fails. */ | |
152 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno)); | |
153 exit (1); | |
154 } | |
155 | |
156 for (i = 1; i < argc; i++) | |
157 { | |
158 if (*argv[i] == '+') | |
159 { | |
160 char *p = argv[i] + 1; | |
161 while (*p >= '0' && *p <= '9') p++; | |
162 if (*p != 0) | |
163 fprintf (out, "%s/", cwd); | |
164 } | |
165 else if (*argv[i] != '/') | |
166 fprintf (out, "%s/", cwd); | |
167 fprintf (out, "%s ", argv[i]); | |
168 } | |
169 fprintf (out, "\n"); | |
170 fflush (out); | |
171 | |
172 printf ("Waiting for Emacs..."); | |
173 fflush (stdout); | |
174 | |
175 rewind (out); /* re-read the output */ | |
176 str = fgets (string, BUFSIZ, out); | |
177 | |
178 /* Now, wait for an answer and print any messages. */ | |
179 | |
180 while ((str = fgets (string, BUFSIZ, out))) | |
181 printf ("%s", str); | |
182 | |
183 exit (0); | |
184 } | |
185 | |
186 #else /* This is the SYSV IPC section */ | |
187 | |
188 #include <sys/types.h> | |
189 #include <sys/ipc.h> | |
190 #include <sys/msg.h> | |
191 #include <stdio.h> | |
192 | |
193 char *getwd (); | |
194 #if !__STDC__ && !defined(STDC_HEADERS) | |
195 char *getcwd (), *getenv (); | |
196 #endif | |
197 | |
198 void | |
199 main (argc, argv) | |
200 int argc; | |
201 char **argv; | |
202 { | |
203 int s; | |
204 key_t key; | |
205 /* Size of text allocated in MSGP. */ | |
206 int size_allocated = BUFSIZ; | |
207 /* Amount of text used in MSGP. */ | |
208 int used; | |
209 struct msgbuf *msgp | |
210 = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated); | |
211 #if 0 | |
212 struct msqid_ds * msg_st; | |
213 #endif /* 0 */ | |
214 char *homedir, buf[BUFSIZ]; | |
215 char gwdirb[BUFSIZ]; | |
216 char *cwd; | |
217 char *temp; | |
218 char progname[BUFSIZ]; | |
219 | |
220 strcpy (progname, argv[0]); | |
221 | |
222 if (argc < 2) | |
223 { | |
224 fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]); | |
225 exit (1); | |
226 } | |
227 | |
228 /* | |
229 * Create a message queue using ~/.emacs_server as the path for ftok | |
230 */ | |
231 if ((homedir = getenv ("HOME")) == NULL) | |
232 { | |
233 fprintf (stderr, "%s: No home directory\n", argv[0]); | |
234 exit (1); | |
235 } | |
236 strcpy (buf, homedir); | |
237 strcat (buf, "/.emacs_server"); | |
238 creat (buf, 0600); | |
239 key = ftok (buf, 1); /* unlikely to be anyone else using it */ | |
240 s = msgget (key, 0600 | IPC_CREAT); | |
241 if (s == -1) | |
242 { | |
243 fprintf (stderr, "%s: ", argv[0]); | |
244 perror ("msgget"); | |
245 exit (1); | |
246 } | |
247 | |
248 /* Determine working dir, so we can prefix it to all the arguments. */ | |
249 #ifdef BSD | |
250 temp = getwd (gwdirb); | |
251 #else | |
252 temp = getcwd (gwdirb, sizeof gwdirb); | |
253 #endif | |
254 | |
255 cwd = gwdirb; | |
256 if (temp != 0) | |
257 { | |
258 /* On some systems, cwd can look like `@machine/...'; | |
259 ignore everything before the first slash in such a case. */ | |
260 while (*cwd && *cwd != '/') | |
261 cwd++; | |
262 strcat (cwd, "/"); | |
263 } | |
264 else | |
265 { | |
266 fprintf (stderr, cwd); | |
267 exit (1); | |
268 } | |
269 | |
270 msgp->mtext[0] = 0; | |
271 used = 0; | |
272 argc--; argv++; | |
273 while (argc) | |
274 { | |
275 int need_cwd = 0; | |
276 char *modified_arg = argv[0]; | |
277 if (*modified_arg == '+') | |
278 { | |
279 char *p = modified_arg + 1; | |
280 while (*p >= '0' && *p <= '9') p++; | |
281 if (*p != 0) | |
282 need_cwd = 1; | |
283 } | |
284 else if (*modified_arg != '/') | |
285 need_cwd = 1; | |
286 | |
287 if (need_cwd) | |
288 used += strlen (cwd); | |
289 used += strlen (modified_arg) + 1; | |
290 while (used + 2 > size_allocated) | |
291 { | |
292 size_allocated *= 2; | |
293 msgp = (struct msgbuf *) realloc (msgp, | |
294 (sizeof (struct msgbuf) | |
295 + size_allocated)); | |
296 } | |
297 if (need_cwd) | |
298 strcat (msgp->mtext, cwd); | |
299 | |
300 strcat (msgp->mtext, modified_arg); | |
301 strcat (msgp->mtext, " "); | |
302 argv++; argc--; | |
303 } | |
304 strcat (msgp->mtext, "\n"); | |
305 #ifdef HPUX /* HPUX has a bug. */ | |
306 if (strlen (msgp->mtext) >= 512) | |
307 { | |
308 fprintf (stderr, "emacsclient: args too long for msgsnd\n"); | |
309 exit (1); | |
310 } | |
311 #endif | |
312 msgp->mtype = 1; | |
313 if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0) | |
314 { | |
315 fprintf (stderr, "%s: ", progname); | |
316 perror ("msgsnd"); | |
317 exit (1); | |
318 } | |
319 /* | |
320 * Now, wait for an answer | |
321 */ | |
322 printf ("Waiting for Emacs..."); | |
323 fflush (stdout); | |
324 | |
325 msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */ | |
326 strcpy (buf, msgp->mtext); | |
327 | |
328 printf ("\n%s\n", buf); | |
329 exit (0); | |
330 } | |
331 | |
332 #endif /* HAVE_SYSVIPC */ | |
333 | |
334 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */ | |
335 | |
336 #ifndef HAVE_STRERROR | |
337 char * | |
338 strerror (errnum) | |
339 int errnum; | |
340 { | |
341 extern char *sys_errlist[]; | |
342 extern int sys_nerr; | |
343 | |
344 if (errnum >= 0 && errnum < sys_nerr) | |
345 return sys_errlist[errnum]; | |
346 return (char *) "Unknown error"; | |
347 } | |
348 | |
349 #endif /* ! HAVE_STRERROR */ |