|
|
1.1 root 1: /* Communication subprocess for GNU Emacs acting as server.
2: Copyright (C) 1986, 1987 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 1, 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, 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: /* This must precede sys/signal.h on certain machines. */
28: #include <sys/types.h>
29: /* This must precede config.h on certain machines. */
30: #include <sys/signal.h>
31:
32: #define NO_SHORTNAMES
33: #include "../src/config.h"
34: #undef read
35: #undef write
36: #undef open
37: #undef close
38:
39:
40: #if !defined(BSD) && !defined(HAVE_SYSVIPC)
41: #include <stdio.h>
42:
43: main ()
44: {
45: fprintf (stderr, "Sorry, the Emacs server is supported only on Berkeley Unix\n");
46: fprintf (stderr, "or System V systems with IPC\n");
47: exit (1);
48: }
49:
50: #else /* BSD or HAVE_SYSVIPC */
51:
52: #if defined (BSD) && ! defined (HAVE_SYSVIPC)
53: /* BSD code is very different from SYSV IPC code */
54:
55: #include <sys/file.h>
56: #include <sys/types.h>
57: #include <sys/socket.h>
58: #include <sys/un.h>
59: #include <stdio.h>
60: #include <errno.h>
61:
62: extern int errno;
63:
64: main ()
65: {
66: char system_name[32];
67: int s, infd, fromlen;
68: struct sockaddr_un server, fromunix;
69: char *homedir;
70: char *str, string[BUFSIZ], code[BUFSIZ];
71: FILE *infile;
72: FILE **openfiles;
73: int openfiles_size;
74:
75: char *getenv ();
76:
77: openfiles_size = 20;
78: openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *));
79: if (openfiles == 0)
80: abort ();
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: perror ("socket");
89: exit (1);
90: }
91: server.sun_family = AF_UNIX;
92: #ifndef SERVER_HOME_DIR
93: gethostname (system_name, sizeof (system_name));
94: sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
95:
96: if (unlink (server.sun_path) == -1 && errno != ENOENT)
97: {
98: perror ("unlink");
99: exit (1);
100: }
101: #else
102: if ((homedir = getenv ("HOME")) == NULL)
103: {
104: fprintf (stderr,"No home directory\n");
105: exit (1);
106: }
107: strcpy (server.sun_path, homedir);
108: strcat (server.sun_path, "/.emacs_server");
109: /* Delete anyone else's old server. */
110: unlink (server.sun_path);
111: #endif
112:
113: if (bind (s, &server, strlen (server.sun_path) + 2) < 0)
114: {
115: perror ("bind");
116: exit (1);
117: }
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;
138: infd = accept (s, &fromunix, &fromlen); /* open socket fd */
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/ipc.h>
226: #include <sys/msg.h>
227: #include <setjmp.h>
228:
229: jmp_buf msgenv;
230:
231: void /* void here fixes bug on sgi.
232: Let's hope this doesn't break other systems. */
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");
306: exit (1);
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 /* SYSV IPC */
327:
328: #endif /* BSD && IPC */
329:
330:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.