2 Server code for handling requests from clients and forwarding them
3 on to the GNU Emacs process.
5 This file is part of GNU Emacs.
7 Copying is permitted under those conditions described by the GNU
8 General Public License.
10 Copyright (C) 1989 Free Software Foundation, Inc.
12 Author: Andy Norman (ange@hplb.hpl.hp.com), based on 'etc/server.c'
13 from the 18.52 GNU Emacs distribution.
15 Please mail bugs and suggestions to the author at the above address.
19 * 11-Nov-1990 bristor@simba
24 * This file incorporates new features added by Bob Weiner <weiner@mot.com>,
25 * Darrell Kindred <dkindred@cmu.edu> and Arup Mukherjee <arup@cmu.edu>.
26 * Please see the note at the end of the README file for details.
28 * (If gnuserv came bundled with your emacs, the README file is probably
29 * ../etc/gnuserv.README relative to the directory containing this file)
35 char gnuserv_version[] = "gnuserv version" GNUSERV_VERSION;
39 #include <bsd/sgtty.h>
46 #include <sys/select.h>
51 #include <sys/types.h>
56 #endif /* HAVE_UNISTD_H */
60 #endif /* HAVE_STRING_H */
63 #if !defined(SYSV_IPC) && !defined(UNIX_DOMAIN_SOCKETS) && \
64 !defined(INTERNET_DOMAIN_SOCKETS)
68 fputs("Sorry, the Emacs server is only supported on systems that have\n\
69 Unix Domain sockets, Internet Domain sockets or System V IPC\n", stderr);
72 #else /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */
76 /* ipc message queue id */
78 /* watchdog task pid */
82 * clean up the queue id and queue, then kill the watchdog task
83 * if it exists. exit with the given status. **/
85 __attribute__((noreturn))
88 msgctl(ipc_qid, IPC_RMID, 0);
91 kill(ipc_wpid, SIGKILL);
97 * catch the signal given and clean up. **/
99 ipc_handle_signal(int sig)
104 /** ipc_spawn_watchdog
105 * spawn a watchdog task to clean up the message queue should the
106 * server process die. **/
108 ipc_spawn_watchdog(void)
111 if ((ipc_wpid = fork()) == 0) {
112 /* parent's process id */
113 pid_t ppid = getppid();
115 /* gnu kills process group on exit */
119 /* ppid is no longer valid, parent may have died */
120 if (kill(ppid, 0) < 0) {
123 /* else, have another go later */
131 * initialize server, setting the global msqid that can be listened on. **/
133 ipc_init(struct msgbuf **msgpp)
137 /* pathname for key */
138 char buf[GSERV_BUFSZ];
141 SNPRINTF(sz, buf, sizeof(buf),"%s/gsrv%d", tmpdir, (int)geteuid());
145 if ((ipc_qid = msgget(key, 0600 | IPC_CREAT)) == -1) {
147 fprintf(stderr, "%s: unable to create msg queue\n", progname);
150 ipc_spawn_watchdog();
152 signal(SIGTERM, ipc_handle_signal);
153 signal(SIGINT, ipc_handle_signal);
155 *msgpp = (struct msgbuf*)malloc(sizeof **msgpp + GSERV_BUFSZ);
156 if (*msgpp == NULL) {
158 "%s: unable to allocate space for message buffer\n",
165 /** handle_ipc_request
166 * accept a request from a client, pass the request on to the GNU Emacs process,
167 * then wait for its reply and pass that on to the client. **/
169 handle_ipc_request(struct msgbuf *msgp)
172 struct msqid_ds msg_st;
173 char buf[GSERV_BUFSZ];
174 /* length of message / read */
176 /* tag fields on the response from emacs */
179 /* # bytes that will actually be sent off */
182 if ((len = msgrcv(ipc_qid, msgp, GSERV_BUFSZ - 1, 1, 0)) < 0) {