|
|
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 distributed in the hope that it will be useful,
7: but without any warranty. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing.
11:
12: Everyone is granted permission to copy, modify and redistribute
13: GNU Emacs, but only under the conditions described in the
14: document "GNU Emacs copying permission notice". An exact copy
15: of the document is supposed to have been given to you along with
16: GNU Emacs so that you can know how you may redistribute it all.
17: It should be in a file named COPYING. Among other things, the
18: copyright notice and this notice must be preserved on all copies. */
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
28: #include "../src/config.h"
29: #undef read
30: #undef write
31: #undef open
32: #undef close
33:
34:
35: #if !defined(BSD) && !defined(HAVE_SYSVIPC)
36: #include <stdio.h>
37:
38: main ()
39: {
40: fprintf (stderr, "Sorry, the Emacs server is supported only on Berkeley Unix\n");
41: fprintf (stderr, "or System V systems with IPC\n");
42: exit (1);
43: }
44:
45: #else /* BSD or HAVE_SYSVIPC */
46:
47: #if defined (BSD) && ! defined (HAVE_SYSVIPC)
48: /* BSD code is very different from SYSV IPC code */
49:
50: #include <sys/file.h>
51: #include <sys/types.h>
52: #include <sys/socket.h>
53: #include <sys/signal.h>
54: #include <sys/un.h>
55: #include <stdio.h>
56: #include <errno.h>
57:
58: extern int errno;
59:
60: main ()
61: {
62: int s, infd, fromlen;
63: struct sockaddr_un server, fromunix;
64: char *homedir;
65: char *str, string[BUFSIZ], code[BUFSIZ];
66: FILE *infile;
67: FILE **openfiles;
68: int openfiles_size;
69:
70: char *getenv ();
71:
72: openfiles_size = 20;
73: openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *));
74: if (openfiles == 0)
75: abort ();
76:
77: /*
78: * Open up an AF_UNIX socket in this person's home directory
79: */
80:
81: if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
82: {
83: perror ("socket");
84: exit (1);
85: }
86: server.sun_family = AF_UNIX;
87: if ((homedir = getenv ("HOME")) == NULL)
88: {
89: fprintf (stderr,"No home directory\n");
90: exit (1);
91: }
92: strcpy (server.sun_path, homedir);
93: strcat (server.sun_path, "/.emacs_server");
94: if (bind (s, &server, strlen (server.sun_path) + 2) < 0)
95: {
96: perror ("bind");
97: exit (1);
98: }
99: /*
100: * Now, just wait for everything to come in..
101: */
102: if (listen (s, 5) < 0)
103: {
104: perror ("listen");
105: exit (1);
106: }
107:
108: /* Disable sigpipes in case luser kills client... */
109: signal (SIGPIPE, SIG_IGN);
110: for (;;)
111: {
112: int rmask = (1 << s) + 1;
113: if (select (s + 1, &rmask, 0, 0, 0) < 0)
114: perror ("select");
115: if (rmask & (1 << s)) /* client sends list of filenames */
116: {
117: fromlen = sizeof (fromunix);
118: fromunix.sun_family = AF_UNIX;
119: infd = accept (s, &fromunix, &fromlen); /* open socket fd */
120: if (infd < 0)
121: {
122: if (errno == EMFILE || errno == ENFILE)
123: printf ("Too many clients.\n");
124: else
125: perror ("accept");
126: continue;
127: }
128:
129: if (infd >= openfiles_size)
130: {
131: openfiles_size *= 2;
132: openfiles = (FILE **) realloc (openfiles,
133: openfiles_size * sizeof (FILE *));
134: if (openfiles == 0)
135: abort ();
136: }
137:
138: infile = fdopen (infd, "r+"); /* open stream */
139: if (infile == NULL)
140: {
141: printf ("Too many clients.\n");
142: write (infd, "Too many clients.\n", 18);
143: close (infd); /* Prevent descriptor leak.. */
144: continue;
145: }
146: str = fgets (string, BUFSIZ, infile);
147: if (str == NULL)
148: {
149: perror ("fgets");
150: close (infd); /* Prevent descriptor leak.. */
151: continue;
152: }
153: openfiles[infd] = infile;
154: printf ("Client: %d %s", infd, string);
155: /* If what we read did not end in a newline,
156: it means there is more. Keep reading from the socket
157: and outputting to Emacs, until we get the newline. */
158: while (string[strlen (string) - 1] != '\n')
159: {
160: if (fgets (string, BUFSIZ, infile) == 0)
161: break;
162: printf ("%s", string);
163: }
164: fflush (stdout);
165: fflush (infile);
166: continue;
167: }
168: else if (rmask & 1) /* emacs sends codeword, fd, and string message */
169: {
170: /* Read command codeword and fd */
171: scanf ("%s %d%*c", code, &infd);
172:
173: /* Transfer text from Emacs to the client, up to a newline. */
174: infile = openfiles[infd];
175: while (1)
176: {
177: if (fgets (string, BUFSIZ, stdin) == 0)
178: break;
179: fprintf (infile, "%s", string);
180: if (string[strlen (string) - 1] == '\n')
181: break;
182: }
183: fflush (infile);
184:
185: /* If command is close, close connection to client. */
186: if (strncmp (code, "Close:", 6) == 0)
187: if (infd > 2)
188: {
189: fclose (infile);
190: close (infd);
191: }
192: continue;
193: }
194: }
195: }
196:
197: #else /* This is the SYSV IPC section */
198:
199: #include <sys/types.h>
200: #include <sys/signal.h>
201: #include <sys/ipc.h>
202: #include <sys/msg.h>
203: #include <setjmp.h>
204:
205: jmp_buf msgenv;
206:
207: msgcatch ()
208: {
209: longjmp (msgenv, 1);
210: }
211:
212:
213: /* "THIS has to be fixed. Remember, stderr may not exist...-rlk."
214: Incorrect. This program runs as an inferior of Emacs.
215: Its stderr always exists--rms. */
216: #include <stdio.h>
217:
218: main ()
219: {
220: int s, infd, fromlen;
221: key_t key;
222: struct msgbuf * msgp =
223: (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ);
224: struct msqid_ds msg_st;
225: int p;
226: char *homedir, *getenv ();
227: char string[BUFSIZ];
228: FILE *infile;
229:
230: /*
231: * Create a message queue using ~/.emacs_server as the path for ftok
232: */
233: if ((homedir = getenv ("HOME")) == NULL)
234: {
235: fprintf (stderr,"No home directory\n");
236: exit (1);
237: }
238: strcpy (string, homedir);
239: strcat (string, "/.emacs_server");
240: creat (string, 0600);
241: key = ftok (string, 1); /* unlikely to be anyone else using it */
242: s = msgget (key, 0600 | IPC_CREAT);
243: if (s == -1)
244: {
245: perror ("msgget");
246: exit (1);
247: }
248:
249: /* Fork so we can close connection even if parent dies */
250: p = fork ();
251: if (setjmp (msgenv))
252: {
253: msgctl (s, IPC_RMID, 0);
254: kill (p, SIGKILL);
255: exit (0);
256: }
257: signal (SIGTERM, msgcatch);
258: signal (SIGINT, msgcatch);
259: /* If parent goes away, remove message box and exit */
260: if (p == 0)
261: {
262: p = getppid ();
263: setpgrp (); /* Gnu kills process group on exit */
264: while (1)
265: {
266: if (kill (p, 0) < 0)
267: {
268: msgctl (s, IPC_RMID, 0);
269: exit (0);
270: }
271: sleep (10);
272: }
273: }
274:
275: while (1)
276: {
277: if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0)
278: {
279: perror ("msgrcv");
280: }
281: else
282: {
283: msgctl (s, IPC_STAT, &msg_st);
284: strncpy (string, msgp->mtext, fromlen);
285: string[fromlen] = 0; /* make sure */
286: /* Newline is part of string.. */
287: printf ("Client: %d %s", s, string);
288: fflush (stdout);
289: /* Now, wait for a wakeup */
290: fgets (msgp->mtext, BUFSIZ, stdin);
291: msgp->mtext[strlen (msgp->mtext)-1] = 0;
292: /* strcpy (msgp->mtext, "done");*/
293: msgp->mtype = msg_st.msg_lspid;
294: msgsnd (s, msgp, strlen (msgp->mtext)+1, 0);
295: }
296: }
297: }
298:
299: #endif /* SYSV IPC */
300:
301: #endif /* BSD && IPC */
302:
303:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.