comparison lib-src/gnuserv.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ec9a17fef872
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* -*-C-*-
2 Server code for handling requests from clients and forwarding them
3 on to the GNU Emacs process.
4
5 This file is part of GNU Emacs.
6
7 Copying is permitted under those conditions described by the GNU
8 General Public License.
9
10 Copyright (C) 1989 Free Software Foundation, Inc.
11
12 Author: Andy Norman (ange@hplb.hpl.hp.com), based on 'etc/server.c'
13 from the 18.52 GNU Emacs distribution.
14
15 Please mail bugs and suggestions to the author at the above address.
16 */
17
18 /* HISTORY
19 * 11-Nov-1990 bristor@simba
20 * Added EOT stuff.
21 */
22
23 /*
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.
27 *
28 * (If gnuserv came bundled with your emacs, the README file is probably
29 * ../etc/gnuserv.README relative to the directory containing this file)
30 */
31
32 #if 0
33 static char rcsid [] = "!Header: gnuserv.c,v 2.1 95/02/16 11:58:27 arup alpha !";
34 #endif
35
36 #include "gnuserv.h"
37
38 #ifdef USE_LITOUT
39 #ifdef linux
40 #include <bsd/sgtty.h>
41 #else
42 #include <sgtty.h>
43 #endif
44 #endif
45
46 #ifdef AIX
47 #include <sys/select.h>
48 #endif
49
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <unistd.h>
55 #include <string.h>
56
57 #if !defined(SYSV_IPC) && !defined(UNIX_DOMAIN_SOCKETS) && \
58 !defined(INTERNET_DOMAIN_SOCKETS)
59 main ()
60 {
61 fprintf (stderr,"Sorry, the Emacs server is only supported on systems that have\n");
62 fprintf (stderr,"Unix Domain sockets, Internet Domain sockets or System V IPC\n");
63 exit (1);
64 } /* main */
65 #else /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */
66
67 #ifdef SYSV_IPC
68
69 int ipc_qid = 0; /* ipc message queue id */
70 int ipc_wpid = 0; /* watchdog task pid */
71
72
73 /*
74 ipc_exit -- clean up the queue id and queue, then kill the watchdog task
75 if it exists. exit with the given status.
76 */
77 void ipc_exit(stat)
78 int stat;
79 {
80 msgctl(ipc_qid,IPC_RMID,0);
81
82 if (ipc_wpid != 0)
83 kill(ipc_wpid,SIGKILL);
84
85 exit(stat);
86 } /* ipc_exit */
87
88
89 /*
90 ipc_handle_signal -- catch the signal given and clean up.
91 */
92 void ipc_handle_signal(sig)
93 int sig;
94 {
95 ipc_exit(0);
96 } /* ipc_handle_signal */
97
98
99 /*
100 ipc_spawn_watchdog -- spawn a watchdog task to clean up the message queue should the
101 server process die.
102 */
103 void ipc_spawn_watchdog()
104 {
105 if ((ipc_wpid = fork()) == 0) { /* child process */
106 int ppid = getppid(); /* parent's process id */
107
108 setpgrp(); /* gnu kills process group on exit */
109
110 while (1) {
111 if (kill(ppid,0) < 0) { /* ppid is no longer valid, parent may have died */
112 ipc_exit(0);
113 } /* if */
114
115 sleep(10); /* have another go later */
116 } /* while */
117 } /* if */
118
119 } /* ipc_spawn_watchdog */
120
121
122 /*
123 ipc_init -- initialize server, setting the global msqid that can be listened on.
124 */
125 void ipc_init(msgpp)
126 struct msgbuf **msgpp;
127 {
128 key_t key; /* messge key */
129 char buf[GSERV_BUFSZ]; /* pathname for key */
130
131 sprintf(buf,"/tmp/gsrv%d",(int)geteuid());
132 creat(buf,0600);
133 key = ftok(buf,1);
134
135 if ((ipc_qid = msgget(key,0600|IPC_CREAT)) == -1) {
136 perror(progname);
137 fprintf(stderr,"%s: unable to create msg queue\n",progname);
138 ipc_exit(1);
139 } /* if */
140
141 ipc_spawn_watchdog();
142
143 signal(SIGTERM,ipc_handle_signal);
144 signal(SIGINT,ipc_handle_signal);
145
146 if ((*msgpp = (struct msgbuf *)
147 malloc(sizeof **msgpp + GSERV_BUFSZ)) == NULL) {
148 fprintf(stderr,
149 "%s: unable to allocate space for message buffer\n",progname);
150 ipc_exit(1);
151 } /* if */
152
153 } /* ipc_init */
154
155
156 /*
157 handle_ipc_request -- accept a request from a client, pass the request on
158 to the GNU Emacs process, then wait for its reply and
159 pass that on to the client.
160 */
161 void handle_ipc_request(msgp)
162 struct msgbuf *msgp; /* message buffer */
163 {
164 struct msqid_ds msg_st; /* message status */
165 char buf[GSERV_BUFSZ];
166 int len; /* length of message / read */
167 int s, result_len; /* tag fields on the response from emacs */
168 int offset = 0;
169 int total = 1; /* # bytes that will actually be sent off */
170
171 if ((len = msgrcv(ipc_qid,msgp,GSERV_BUFSZ-1,1,0)) < 0) {
172 perror(progname);
173 fprintf(stderr,"%s: unable to receive\n",progname);
174 ipc_exit(1);
175 } /* if */
176
177 msgctl(ipc_qid,IPC_STAT,&msg_st);
178 strncpy(buf,msgp->mtext,len);
179 buf[len] = '\0'; /* terminate */
180
181 printf("%d %s",ipc_qid,buf);
182 fflush(stdout);
183
184 /* now for the response from gnu */
185 msgp->mtext[0] = '\0';
186
187 #if 0
188 if ((len = read(0,buf,GSERV_BUFSZ-1)) < 0) {
189 perror(progname);
190 fprintf(stderr,"%s: unable to read\n",progname);
191 ipc_exit(1);
192 } /* if */
193
194 sscanf(buf,"%d:%[^\n]\n",&junk,msgp->mtext);
195 #else
196
197 /* read in "n/m:" (n=client fd, m=message length) */
198
199 while (offset < (GSERV_BUFSZ-1) &&
200 ((len = read(0,buf+offset,1)) > 0) &&
201 buf[offset] != ':') {
202 offset += len;
203 }
204
205 if (len < 0) {
206 perror(progname);
207 fprintf(stderr,"%s: unable to read\n",progname);
208 exit(1);
209 }
210
211 /* parse the response from emacs, getting client fd & result length */
212 buf[offset] = '\0';
213 sscanf(buf,"%d/%d", &s, &result_len);
214
215 while (result_len > 0) {
216 if ((len = read(0,buf,min2(result_len, GSERV_BUFSZ - 1))) < 0) {
217 perror(progname);
218 fprintf(stderr,"%s: unable to read\n",progname);
219 exit(1);
220 }
221
222 /* Send this string off, but only if we have enough space */
223
224 if (GSERV_BUFSZ > total) {
225 if (total + len <= GSERV_BUFSZ)
226 buf[len] = 0;
227 else
228 buf[GSERV_BUFSZ - total] = 0;
229
230 send_string(s,buf);
231 total += strlen(buf);
232 }
233
234 result_len -= len;
235 }
236
237 /* eat the newline */
238 while ((len = read(0,buf,1)) == 0)
239 ;
240 if (len < 0) {
241 perror(progname);
242 fprintf(stderr,"%s: unable to read\n",progname);
243 exit(1);
244 }
245 if (buf[0] != '\n') {
246 fprintf(stderr,"%s: garbage after result [%c]\n",progname, buf[0]);
247 exit(1);
248 }
249 #endif
250
251 /* Send a response back to the client. */
252
253 msgp->mtype = msg_st.msg_lspid;
254 if (msgsnd(ipc_qid,msgp,strlen(msgp->mtext)+1,0) < 0)
255 perror("msgsend(gnuserv)");
256
257 } /* handle_ipc_request */
258 #endif /* SYSV_IPC */
259
260
261 #if defined(INTERNET_DOMAIN_SOCKETS) || defined(UNIX_DOMAIN_SOCKETS)
262 /*
263 echo_request -- read request from a given socket descriptor, and send the information
264 to stdout (the gnu process).
265 */
266 static void
267 echo_request (int s)
268 {
269 char buf[GSERV_BUFSZ];
270 int len;
271
272 printf("%d ",s);
273
274 /* read until we get a newline or no characters */
275 while ((len = recv(s,buf,GSERV_BUFSZ-1,0)) > 0) {
276 buf[len] = '\0';
277 printf("%s",buf);
278
279 if (buf[len-1] == EOT_CHR) {
280 fflush(stdout);
281 break; /* end of message */
282 }
283
284 } /* while */
285
286 if (len < 0) {
287 perror(progname);
288 fprintf(stderr,"%s: unable to recv\n",progname);
289 exit(1);
290 } /* if */
291
292 } /* echo_request */
293
294
295 /*
296 handle_response -- accept a response from stdin (the gnu process) and pass the
297 information on to the relevant client.
298 */
299 static void
300 handle_response (void)
301 {
302 char buf[GSERV_BUFSZ+1];
303 int offset=0;
304 int s;
305 int len;
306 int result_len;
307
308 /* read in "n/m:" (n=client fd, m=message length) */
309 while (offset < GSERV_BUFSZ &&
310 ((len = read(0,buf+offset,1)) > 0) &&
311 buf[offset] != ':') {
312 offset += len;
313 }
314
315 if (len < 0) {
316 perror(progname);
317 fprintf(stderr,"%s: unable to read\n",progname);
318 exit(1);
319 }
320
321 /* parse the response from emacs, getting client fd & result length */
322 buf[offset] = '\0';
323 sscanf(buf,"%d/%d", &s, &result_len);
324
325 while (result_len > 0) {
326 if ((len = read(0,buf,min2(result_len,GSERV_BUFSZ))) < 0) {
327 perror(progname);
328 fprintf(stderr,"%s: unable to read\n",progname);
329 exit(1);
330 }
331 buf[len] = '\0';
332 send_string(s,buf);
333 result_len -= len;
334 }
335
336 /* eat the newline */
337 while ((len = read(0,buf,1)) == 0)
338 ;
339 if (len < 0) {
340 perror(progname);
341 fprintf(stderr,"%s: unable to read\n",progname);
342 exit(1);
343 }
344 if (buf[0] != '\n') {
345 fprintf(stderr,"%s: garbage after result\n",progname);
346 exit(1);
347 }
348 close(s);
349
350 } /* handle_response */
351 #endif /* INTERNET_DOMAIN_SOCKETS || UNIX_DOMAIN_SOCKETS */
352
353
354 #ifdef INTERNET_DOMAIN_SOCKETS
355 struct entry {
356 u_long host_addr;
357 struct entry *next;
358 };
359
360 struct entry *permitted_hosts[TABLE_SIZE];
361
362 #ifdef AUTH_MAGIC_COOKIE
363 # include <X11/X.h>
364 # include <X11/Xauth.h>
365
366 static Xauth *server_xauth = NULL;
367 #endif
368
369 static int
370 timed_read (int fd, char *buf, int max, int timeout, int one_line)
371 {
372 fd_set rmask;
373 struct timeval tv; /* = {timeout, 0}; */
374 char c = 0;
375 int nbytes = 0;
376 int r;
377
378 tv.tv_sec = timeout;
379 tv.tv_usec = 0;
380
381 FD_ZERO(&rmask);
382 FD_SET(fd, &rmask);
383
384 do {
385 r = select(fd + 1, &rmask, NULL, NULL, &tv);
386
387 if (r > 0) {
388 if (read (fd, &c, 1) == 1 ){
389 *buf++ = c;
390 ++nbytes;
391 } else {
392 printf ("read error on socket\004\n");
393 return -1;
394 }
395 } else if (r == 0) {
396 printf ("read timed out\004\n");
397 return -1;
398 } else {
399 printf ("error in select\004\n");
400 return -1;
401 }
402 } while ((nbytes < max) && !(one_line && (c == '\n')));
403
404 --buf;
405 if (one_line && *buf == '\n') {
406 *buf = 0;
407 }
408
409 return nbytes;
410 }
411
412
413
414 /*
415 permitted -- return whether a given host is allowed to connect to the server.
416 */
417 static int
418 permitted (u_long host_addr, int fd)
419 {
420 int key;
421 struct entry *entry;
422
423 char auth_protocol[128];
424 char buf[1024];
425 int auth_data_len;
426
427 if (fd > 0) {
428 /* we are checking permission on a real connection */
429
430 /* Read auth protocol name */
431
432 if (timed_read(fd, auth_protocol, AUTH_NAMESZ, AUTH_TIMEOUT, 1) <= 0)
433 return FALSE;
434
435 if (strcmp (auth_protocol, DEFAUTH_NAME) &&
436 strcmp (auth_protocol, MCOOKIE_NAME)) {
437 printf ("authentication protocol (%s) from client is invalid...\n",
438 auth_protocol);
439 printf ("... Was the client an old version of gnuclient/gnudoit?\004\n");
440
441 return FALSE;
442 }
443
444 if (!strcmp(auth_protocol, MCOOKIE_NAME)) {
445
446 /*
447 * doing magic cookie auth
448 */
449
450 if (timed_read(fd, buf, 10, AUTH_TIMEOUT, 1) <= 0)
451 return FALSE;
452
453 auth_data_len = atoi(buf);
454
455 if (timed_read(fd, buf, auth_data_len, AUTH_TIMEOUT, 0) != auth_data_len)
456 return FALSE;
457
458 #ifdef AUTH_MAGIC_COOKIE
459 if (server_xauth && server_xauth->data &&
460 !memcmp(buf, server_xauth->data, auth_data_len)) {
461 return TRUE;
462 }
463 #else
464 printf ("client tried Xauth, but server is not compiled with Xauth\n");
465 #endif
466
467 /*
468 * auth failed, but allow this to fall through to the GNU_SECURE
469 * protocol....
470 */
471
472 printf ("Xauth authentication failed, trying GNU_SECURE auth...\004\n");
473
474 }
475
476 /* Other auth protocols go here, and should execute only if the
477 * auth_protocol name matches.
478 */
479
480 }
481
482
483 /* Now, try the old GNU_SECURE stuff... */
484
485 /* First find the hash key */
486 key = HASH(host_addr) % TABLE_SIZE;
487
488 /* Now check the chain for that hash key */
489 for(entry=permitted_hosts[key]; entry != NULL; entry=entry->next)
490 if (host_addr == entry->host_addr)
491 return(TRUE);
492
493 return(FALSE);
494
495 } /* permitted */
496
497
498 /*
499 add_host -- add the given host to the list of permitted hosts, provided it isn't
500 already there.
501 */
502 static void
503 add_host (u_long host_addr)
504 {
505 int key;
506 struct entry *new_entry;
507
508 if (!permitted(host_addr, -1)) {
509 if ((new_entry = (struct entry *) malloc(sizeof(struct entry))) == NULL) {
510 fprintf(stderr,"%s: unable to malloc space for permitted host entry\n",
511 progname);
512 exit(1);
513 } /* if */
514
515 new_entry->host_addr = host_addr;
516 key = HASH(host_addr) % TABLE_SIZE;
517 new_entry->next = permitted_hosts[key];
518 permitted_hosts[key] = new_entry;
519 } /* if */
520
521 } /* add_host */
522
523
524 /*
525 setup_table -- initialise the table of hosts allowed to contact the server,
526 by reading from the file specified by the GNU_SECURE
527 environment variable
528 Put in the local machine, and, if a security file is specifed,
529 add each host that is named in the file.
530 Return the number of hosts added.
531 */
532 static int
533 setup_table (void)
534 {
535 FILE *host_file;
536 char *file_name;
537 char hostname[HOSTNAMSZ];
538 u_int host_addr;
539 int i, hosts=0;
540
541 /* Make sure every entry is null */
542 for (i=0; i<TABLE_SIZE; i++)
543 permitted_hosts[i] = NULL;
544
545 gethostname(hostname,HOSTNAMSZ);
546
547 if ((host_addr = internet_addr(hostname)) == -1) {
548 fprintf(stderr,"%s: unable to find %s in /etc/hosts or from YP",
549 progname,hostname);
550 exit(1);
551 } /* if */
552
553 #ifdef AUTH_MAGIC_COOKIE
554
555 server_xauth = XauGetAuthByAddr (FamilyInternet,
556 sizeof(host_addr), (char *)&host_addr,
557 strlen(MCOOKIE_SCREEN), MCOOKIE_SCREEN,
558 strlen(MCOOKIE_X_NAME), MCOOKIE_X_NAME);
559 hosts++;
560
561 #endif /* AUTH_MAGIC_COOKIE */
562
563
564 #if 0 /* Don't even want to allow access from the local host by default */
565 add_host(host_addr); /* add local host */
566 #endif
567
568 if (((file_name = getenv("GNU_SECURE")) != NULL && /* security file */
569 (host_file = fopen(file_name,"r")) != NULL)) { /* opened ok */
570 while ((fscanf(host_file,"%s",hostname) != EOF)) /* find a host */
571 if ((host_addr = internet_addr(hostname)) != -1) {/* get its addr */
572 add_host(host_addr); /* add the addr */
573 hosts++;
574 }
575 fclose(host_file);
576 } /* if */
577
578 return hosts;
579 } /* setup_table */
580
581
582 /*
583 internet_init -- initialize server, returning an internet socket that can
584 be listened on.
585 */
586 static int
587 internet_init (void)
588 {
589 int ls; /* socket descriptor */
590 struct servent *sp; /* pointer to service information */
591 struct sockaddr_in server; /* for local socket address */
592 char *ptr; /* ptr to return from getenv */
593
594 if (setup_table() == 0)
595 return -1;
596
597 /* clear out address structure */
598 memset((char *)&server,0,sizeof(struct sockaddr_in));
599
600 /* Set up address structure for the listen socket. */
601 server.sin_family = AF_INET;
602 server.sin_addr.s_addr = INADDR_ANY;
603
604 /* Find the information for the gnu server
605 * in order to get the needed port number.
606 */
607 if ((ptr=getenv("GNU_PORT")) != NULL)
608 server.sin_port = htons(atoi(ptr));
609 else if ((sp = getservbyname ("gnuserv", "tcp")) == NULL)
610 server.sin_port = htons(DEFAULT_PORT+getuid());
611 else
612 server.sin_port = sp->s_port;
613
614 /* Create the listen socket. */
615 if ((ls = socket (AF_INET,SOCK_STREAM, 0)) == -1) {
616 perror(progname);
617 fprintf(stderr,"%s: unable to create socket\n",progname);
618 exit(1);
619 } /* if */
620
621 /* Bind the listen address to the socket. */
622 if (bind(ls,(struct sockaddr *) &server,sizeof(struct sockaddr_in)) == -1) {
623 perror(progname);
624 fprintf(stderr,"%s: unable to bind socket\n",progname);
625 exit(1);
626 } /* if */
627
628 /* Initiate the listen on the socket so remote users
629 * can connect.
630 */
631 if (listen(ls,20) == -1) {
632 perror(progname);
633 fprintf(stderr,"%s: unable to listen\n",progname);
634 exit(1);
635 } /* if */
636
637 return(ls);
638
639 } /* internet_init */
640
641
642 /*
643 handle_internet_request -- accept a request from a client and send the information
644 to stdout (the gnu process).
645 */
646 static void
647 handle_internet_request (int ls)
648 {
649 int s;
650 int addrlen = sizeof(struct sockaddr_in);
651 struct sockaddr_in peer; /* for peer socket address */
652
653 memset((char *)&peer,0,sizeof(struct sockaddr_in));
654
655 if ((s = accept(ls,(struct sockaddr *)&peer,&addrlen)) == -1) {
656 perror(progname);
657 fprintf(stderr,"%s: unable to accept\n",progname);
658 exit(1);
659 } /* if */
660
661 /* Check that access is allowed - if not return crud to the client */
662 if (!permitted(peer.sin_addr.s_addr, s)) {
663 send_string(s,"gnudoit: Connection refused\ngnudoit: unable to connect to remote");
664 close(s);
665
666 printf("Refused connection from %s\004\n", inet_ntoa(peer.sin_addr));
667 return;
668 } /* if */
669
670 echo_request(s);
671
672 } /* handle_internet_request */
673 #endif /* INTERNET_DOMAIN_SOCKETS */
674
675
676 #ifdef UNIX_DOMAIN_SOCKETS
677 /*
678 unix_init -- initialize server, returning an unix-domain socket that can
679 be listened on.
680 */
681 static int
682 unix_init (void)
683 {
684 int ls; /* socket descriptor */
685 struct sockaddr_un server; /* unix socket address */
686 int bindlen;
687
688 if ((ls = socket(AF_UNIX,SOCK_STREAM, 0)) < 0) {
689 perror(progname);
690 fprintf(stderr,"%s: unable to create socket\n",progname);
691 exit(1);
692 } /* if */
693
694 /* Set up address structure for the listen socket. */
695 #ifdef HIDE_UNIX_SOCKET
696 sprintf(server.sun_path,"/tmp/gsrvdir%d",(int)geteuid());
697 if (mkdir(server.sun_path, 0700) < 0) {
698 /* assume it already exists, and try to set perms */
699 if (chmod(server.sun_path, 0700) < 0) {
700 perror(progname);
701 fprintf(stderr,"%s: can't set permissions on %s\n",
702 progname, server.sun_path);
703 exit(1);
704 }
705 }
706 strcat(server.sun_path,"/gsrv");
707 unlink(server.sun_path); /* remove old file if it exists */
708 #else /* HIDE_UNIX_SOCKET */
709 sprintf(server.sun_path,"/tmp/gsrv%d",(int)geteuid());
710 unlink(server.sun_path); /* remove old file if it exists */
711 #endif /* HIDE_UNIX_SOCKET */
712
713 server.sun_family = AF_UNIX;
714 #ifdef HAVE_SOCKADDR_SUN_LEN
715 /* See W. R. Stevens "Advanced Programming in the Unix Environment"
716 p. 502 */
717 bindlen = (sizeof (server.sun_len) + sizeof (server.sun_family)
718 + strlen (server.sun_path) + 1);
719 server.sun_len = bindlen;
720 #else
721 bindlen = strlen (server.sun_path) + sizeof (server.sun_family);
722 #endif
723
724 if (bind(ls,(struct sockaddr *)&server,bindlen) < 0) {
725 perror(progname);
726 fprintf(stderr,"%s: unable to bind socket\n",progname);
727 exit(1);
728 } /* if */
729
730 chmod(server.sun_path,0700); /* only this user can send commands */
731
732 if (listen(ls,20) < 0) {
733 perror(progname);
734 fprintf(stderr,"%s: unable to listen\n",progname);
735 exit(1);
736 } /* if */
737
738 /* #### there are also better ways of dealing with this when
739 sigvec() is present. */
740 #if defined (HAVE_SIGPROCMASK)
741 {
742 sigset_t _mask;
743 sigemptyset (&_mask);
744 sigaddset (&_mask, SIGPIPE);
745 sigprocmask (SIG_BLOCK, &_mask, NULL);
746 }
747 #else
748 signal(SIGPIPE,SIG_IGN); /* in case user kills client */
749 #endif
750
751 return(ls);
752
753 } /* unix_init */
754
755
756 /*
757 handle_unix_request -- accept a request from a client and send the information
758 to stdout (the gnu process).
759 */
760 static void
761 handle_unix_request (int ls)
762 {
763 int s;
764 int len = sizeof(struct sockaddr_un);
765 struct sockaddr_un server; /* for unix socket address */
766
767 server.sun_family = AF_UNIX;
768
769 if ((s = accept(ls,(struct sockaddr *)&server,&len)) < 0) {
770 perror(progname);
771 fprintf(stderr,"%s: unable to accept\n",progname);
772 } /* if */
773
774 echo_request(s);
775
776 } /* handle_unix_request */
777 #endif /* UNIX_DOMAIN_SOCKETS */
778
779
780 void
781 main(argc,argv)
782 int argc;
783 char *argv[];
784 {
785 int chan; /* temporary channel number */
786 #ifdef INTERNET_DOMAIN_SOCKETS
787 int ils = -1; /* internet domain listen socket */
788 #endif
789 #ifdef UNIX_DOMAIN_SOCKETS
790 int uls = -1; /* unix domain listen socket */
791 #endif
792 #ifdef SYSV_IPC
793 struct msgbuf *msgp; /* message buffer */
794 #endif /* SYSV_IPC */
795
796 progname = argv[0];
797
798 for(chan=3; chan < _NFILE; close(chan++)) /* close unwanted channels */
799 ;
800
801 #ifdef USE_LITOUT
802 {
803 /* this is to allow ^D to pass to emacs */
804 int d = LLITOUT;
805 (void) ioctl(fileno(stdout), TIOCLBIS, &d);
806 }
807 #endif
808
809 #ifdef SYSV_IPC
810 ipc_init(&msgp); /* get a msqid to listen on, and a message buffer */
811 #endif /* SYSV_IPC */
812
813 #ifdef INTERNET_DOMAIN_SOCKETS
814 ils = internet_init(); /* get a internet domain socket to listen on */
815 #endif /* INTERNET_DOMAIN_SOCKETS */
816
817 #ifdef UNIX_DOMAIN_SOCKETS
818 uls = unix_init(); /* get a unix domain socket to listen on */
819 #endif /* UNIX_DOMAIN_SOCKETS */
820
821 while (1) {
822 #ifdef SYSV_IPC
823 handle_ipc_request(msgp);
824 #else /* NOT SYSV_IPC */
825 fd_set rmask;
826 FD_ZERO(&rmask);
827 FD_SET(fileno(stdin), &rmask);
828 if (uls >= 0)
829 FD_SET(uls, &rmask);
830 if (ils >= 0)
831 FD_SET(ils, &rmask);
832
833 if (select(max2(fileno(stdin),max2(uls,ils)) + 1, &rmask,
834 (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) < 0) {
835 perror(progname);
836 fprintf(stderr,"%s: unable to select\n",progname);
837 exit(1);
838 } /* if */
839
840 #ifdef UNIX_DOMAIN_SOCKETS
841 if (uls > 0 && FD_ISSET(uls, &rmask))
842 handle_unix_request(uls);
843 #endif
844
845 #ifdef INTERNET_DOMAIN_SOCKETS
846 if (ils > 0 && FD_ISSET(ils, &rmask))
847 handle_internet_request(ils);
848 #endif /* INTERNET_DOMAIN_SOCKETS */
849
850 if (FD_ISSET(fileno(stdin), &rmask)) /* from stdin (gnu process) */
851 handle_response();
852 #endif /* NOT SYSV_IPC */
853 } /* while */
854
855 } /* main */
856
857 #endif /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */