Mercurial > emacs
annotate lib-src/emacsserver.c @ 4774:8e36034f65e2
(doprnt): Use a fixed buffer to store the format
specification, but only if we are sure it will fit. Otherwise,
use alloca () to get enouhg space. Don't allow negative size
specifications to core dump; instead, treat them as positive
("%-20d" == "%20d").
author | Brian Fox <bfox@gnu.org> |
---|---|
date | Wed, 22 Sep 1993 18:12:09 +0000 |
parents | 1fc792473491 |
children | 16e98db8cc1b |
rev | line source |
---|---|
204 | 1 /* Communication subprocess for GNU Emacs acting as server. |
620 | 2 Copyright (C) 1986, 1987, 1992 Free Software Foundation, Inc. |
204 | 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 | |
620 | 8 the Free Software Foundation; either version 2, or (at your option) |
204 | 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
20 | |
21 /* The GNU Emacs edit server process is run as a subprocess of Emacs | |
22 under control of the file lisp/server.el. | |
23 This program accepts communication from client (program emacsclient.c) | |
24 and passes their commands (consisting of keyboard characters) | |
25 up to the Emacs which then executes them. */ | |
26 | |
27 #define NO_SHORTNAMES | |
4696
1fc792473491
Include <config.h> instead of "config.h".
Roland McGrath <roland@gnu.org>
parents:
4178
diff
changeset
|
28 #include <../src/config.h> |
204 | 29 #undef read |
30 #undef write | |
31 #undef open | |
32 #undef close | |
3393 | 33 #undef signal |
204 | 34 |
35 | |
36 #if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC) | |
37 #include <stdio.h> | |
38 | |
39 main () | |
40 { | |
41 fprintf (stderr, "Sorry, the Emacs server is supported only on systems\n"); | |
42 fprintf (stderr, "with Berkeley sockets or System V IPC.\n"); | |
43 exit (1); | |
44 } | |
45 | |
46 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */ | |
47 | |
48 #if ! defined (HAVE_SYSVIPC) | |
49 /* BSD code is very different from SYSV IPC code */ | |
50 | |
4178
57e52e312188
Include types.h before file.h.
Richard M. Stallman <rms@gnu.org>
parents:
3594
diff
changeset
|
51 #include <sys/types.h> |
204 | 52 #include <sys/file.h> |
53 #include <sys/socket.h> | |
54 #include <sys/signal.h> | |
55 #include <sys/un.h> | |
56 #include <stdio.h> | |
57 #include <errno.h> | |
58 | |
59 extern int errno; | |
60 | |
61 main () | |
62 { | |
470 | 63 char system_name[32]; |
204 | 64 int s, infd, fromlen; |
65 struct sockaddr_un server, fromunix; | |
66 char *homedir; | |
67 char *str, string[BUFSIZ], code[BUFSIZ]; | |
68 FILE *infile; | |
69 FILE **openfiles; | |
70 int openfiles_size; | |
71 | |
72 int geteuid (); | |
73 char *getenv (); | |
74 | |
75 openfiles_size = 20; | |
76 openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *)); | |
77 if (openfiles == 0) | |
78 abort (); | |
79 | |
80 /* | |
81 * Open up an AF_UNIX socket in this person's home directory | |
82 */ | |
83 | |
84 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) | |
85 { | |
86 perror ("socket"); | |
87 exit (1); | |
88 } | |
89 server.sun_family = AF_UNIX; | |
470 | 90 #ifndef SERVER_HOME_DIR |
91 gethostname (system_name, sizeof (system_name)); | |
92 sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name); | |
93 | |
94 if (unlink (server.sun_path) == -1 && errno != ENOENT) | |
95 { | |
96 perror ("unlink"); | |
97 exit (1); | |
98 } | |
99 #else | |
100 if ((homedir = getenv ("HOME")) == NULL) | |
204 | 101 { |
102 fprintf (stderr,"No home directory\n"); | |
103 exit (1); | |
104 } | |
105 strcpy (server.sun_path, homedir); | |
106 strcat (server.sun_path, "/.emacs_server"); | |
470 | 107 /* Delete anyone else's old server. */ |
108 unlink (server.sun_path); | |
204 | 109 #endif |
110 | |
3594
aacca1901f73
* emacsserver.c (main): When we're passing a `struct sockaddr_un'
Jim Blandy <jimb@redhat.com>
parents:
3393
diff
changeset
|
111 if (bind (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) < 0) |
204 | 112 { |
113 perror ("bind"); | |
114 exit (1); | |
115 } | |
116 /* Only this user can send commands to this Emacs. */ | |
117 chmod (server.sun_path, 0600); | |
118 /* | |
119 * Now, just wait for everything to come in.. | |
120 */ | |
121 if (listen (s, 5) < 0) | |
122 { | |
123 perror ("listen"); | |
124 exit (1); | |
125 } | |
126 | |
127 /* Disable sigpipes in case luser kills client... */ | |
128 signal (SIGPIPE, SIG_IGN); | |
129 for (;;) | |
130 { | |
131 int rmask = (1 << s) + 1; | |
132 if (select (s + 1, &rmask, 0, 0, 0) < 0) | |
133 perror ("select"); | |
134 if (rmask & (1 << s)) /* client sends list of filenames */ | |
135 { | |
136 fromlen = sizeof (fromunix); | |
137 fromunix.sun_family = AF_UNIX; | |
3594
aacca1901f73
* emacsserver.c (main): When we're passing a `struct sockaddr_un'
Jim Blandy <jimb@redhat.com>
parents:
3393
diff
changeset
|
138 infd = accept (s, (struct sockaddr *) &fromunix, &fromlen); /* open socket fd */ |
204 | 139 if (infd < 0) |
140 { | |
141 if (errno == EMFILE || errno == ENFILE) | |
142 printf ("Too many clients.\n"); | |
143 else | |
144 perror ("accept"); | |
145 continue; | |
146 } | |
147 | |
148 if (infd >= openfiles_size) | |
149 { | |
150 openfiles_size *= 2; | |
151 openfiles = (FILE **) realloc (openfiles, | |
152 openfiles_size * sizeof (FILE *)); | |
153 if (openfiles == 0) | |
154 abort (); | |
155 } | |
156 | |
157 infile = fdopen (infd, "r+"); /* open stream */ | |
158 if (infile == NULL) | |
159 { | |
160 printf ("Too many clients.\n"); | |
161 write (infd, "Too many clients.\n", 18); | |
162 close (infd); /* Prevent descriptor leak.. */ | |
163 continue; | |
164 } | |
165 str = fgets (string, BUFSIZ, infile); | |
166 if (str == NULL) | |
167 { | |
168 perror ("fgets"); | |
169 close (infd); /* Prevent descriptor leak.. */ | |
170 continue; | |
171 } | |
172 openfiles[infd] = infile; | |
173 printf ("Client: %d %s", infd, string); | |
174 /* If what we read did not end in a newline, | |
175 it means there is more. Keep reading from the socket | |
176 and outputting to Emacs, until we get the newline. */ | |
177 while (string[strlen (string) - 1] != '\n') | |
178 { | |
179 if (fgets (string, BUFSIZ, infile) == 0) | |
180 break; | |
181 printf ("%s", string); | |
182 } | |
183 fflush (stdout); | |
184 fflush (infile); | |
185 continue; | |
186 } | |
187 else if (rmask & 1) /* emacs sends codeword, fd, and string message */ | |
188 { | |
189 /* Read command codeword and fd */ | |
190 clearerr (stdin); | |
191 scanf ("%s %d%*c", code, &infd); | |
192 if (ferror (stdin) || feof (stdin)) | |
193 { | |
194 fprintf (stderr, "server: error reading from standard input\n"); | |
195 exit (1); | |
196 } | |
197 | |
198 /* Transfer text from Emacs to the client, up to a newline. */ | |
199 infile = openfiles[infd]; | |
200 while (1) | |
201 { | |
202 if (fgets (string, BUFSIZ, stdin) == 0) | |
203 break; | |
204 fprintf (infile, "%s", string); | |
205 if (string[strlen (string) - 1] == '\n') | |
206 break; | |
207 } | |
208 fflush (infile); | |
209 | |
210 /* If command is close, close connection to client. */ | |
211 if (strncmp (code, "Close:", 6) == 0) | |
212 if (infd > 2) | |
213 { | |
214 fclose (infile); | |
215 close (infd); | |
216 } | |
217 continue; | |
218 } | |
219 } | |
220 } | |
221 | |
222 #else /* This is the SYSV IPC section */ | |
223 | |
224 #include <sys/types.h> | |
225 #include <sys/signal.h> | |
226 #include <sys/ipc.h> | |
227 #include <sys/msg.h> | |
228 #include <setjmp.h> | |
229 | |
230 jmp_buf msgenv; | |
231 | |
620 | 232 SIGTYPE |
204 | 233 msgcatch () |
234 { | |
235 longjmp (msgenv, 1); | |
236 } | |
237 | |
238 | |
239 /* "THIS has to be fixed. Remember, stderr may not exist...-rlk." | |
240 Incorrect. This program runs as an inferior of Emacs. | |
241 Its stderr always exists--rms. */ | |
242 #include <stdio.h> | |
243 | |
244 main () | |
245 { | |
246 int s, infd, fromlen; | |
247 key_t key; | |
248 struct msgbuf * msgp = | |
249 (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ); | |
250 struct msqid_ds msg_st; | |
251 int p; | |
252 char *homedir, *getenv (); | |
253 char string[BUFSIZ]; | |
254 FILE *infile; | |
255 | |
256 /* | |
257 * Create a message queue using ~/.emacs_server as the path for ftok | |
258 */ | |
259 if ((homedir = getenv ("HOME")) == NULL) | |
260 { | |
261 fprintf (stderr,"No home directory\n"); | |
262 exit (1); | |
263 } | |
264 strcpy (string, homedir); | |
265 strcat (string, "/.emacs_server"); | |
266 creat (string, 0600); | |
267 key = ftok (string, 1); /* unlikely to be anyone else using it */ | |
268 s = msgget (key, 0600 | IPC_CREAT); | |
269 if (s == -1) | |
270 { | |
271 perror ("msgget"); | |
272 exit (1); | |
273 } | |
274 | |
275 /* Fork so we can close connection even if parent dies */ | |
276 p = fork (); | |
277 if (setjmp (msgenv)) | |
278 { | |
279 msgctl (s, IPC_RMID, 0); | |
280 kill (p, SIGKILL); | |
281 exit (0); | |
282 } | |
283 signal (SIGTERM, msgcatch); | |
284 signal (SIGINT, msgcatch); | |
285 /* If parent goes away, remove message box and exit */ | |
286 if (p == 0) | |
287 { | |
288 p = getppid (); | |
289 setpgrp (); /* Gnu kills process group on exit */ | |
290 while (1) | |
291 { | |
292 if (kill (p, 0) < 0) | |
293 { | |
294 msgctl (s, IPC_RMID, 0); | |
295 exit (0); | |
296 } | |
297 sleep (10); | |
298 } | |
299 } | |
300 | |
301 while (1) | |
302 { | |
303 if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0) | |
304 { | |
305 perror ("msgrcv"); | |
470 | 306 exit (1); |
204 | 307 } |
308 else | |
309 { | |
310 msgctl (s, IPC_STAT, &msg_st); | |
311 strncpy (string, msgp->mtext, fromlen); | |
312 string[fromlen] = 0; /* make sure */ | |
313 /* Newline is part of string.. */ | |
314 printf ("Client: %d %s", s, string); | |
315 fflush (stdout); | |
316 /* Now, wait for a wakeup */ | |
317 fgets (msgp->mtext, BUFSIZ, stdin); | |
318 msgp->mtext[strlen (msgp->mtext)-1] = 0; | |
319 /* strcpy (msgp->mtext, "done");*/ | |
320 msgp->mtype = msg_st.msg_lspid; | |
321 msgsnd (s, msgp, strlen (msgp->mtext)+1, 0); | |
322 } | |
323 } | |
324 } | |
325 | |
326 #endif /* HAVE_SYSVIPC */ | |
327 | |
328 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */ |