]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/mux.c
finalize -3
[1ts-debian.git] / zephyr / zwgc / mux.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It is one of the source files comprising zwgc, the Zephyr WindowGram
3  * client.
4  *
5  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
6  *
7  *      $Id$
8  *
9  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h".
12  */
13
14 #include <sysdep.h>
15
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_mux_c[] = "$Id$";
18 #endif
19
20 /****************************************************************************/
21 /*                                                                          */
22 /*        Module containing code to wait on multiple file descriptors:      */
23 /*                                                                          */
24 /****************************************************************************/
25
26 #include <zephyr/zephyr.h>
27 #include "main.h"
28 #include "mux.h"
29 #include "error.h"
30 #include "zwgc.h"
31 #include "pointer.h"
32
33 #ifdef _AIX
34 #include <sys/select.h>
35 #endif
36
37 /*
38  * mux_end_loop_p - Setting this to true during a mux_loop causes the mux_loop
39  *                  to be exited.
40  */
41
42 int mux_end_loop_p;
43
44 /*
45  * have_tty - is defined to be true if there is a controlling tty for this
46  *            process.  When we can no longer access the controlling tty,
47  *            the process will die.
48  */
49
50 static int have_tty = 0;
51
52 /*
53  * max_source - the maximum file descriptor that a handler was ever
54  *              registered for:
55  */
56
57 static int max_source = -1;
58
59 /*
60  * Which file descriptors we're waiting on for input & the accompanying
61  * input handlers & their arguments:
62  */
63
64 static fd_set input_sources;
65 static void (*input_handler[MAX_SOURCES])();
66 static pointer input_handler_arg[MAX_SOURCES];
67
68 static int check_tty();
69
70 /*
71  *    void mux_init()
72  *        Requires: mux_init has never been called before
73  *        Effects: Initializes the mux module.  Must be called before
74  *                 any other mux call.
75  */
76
77 void mux_init()
78 {
79     int i;
80
81     FD_ZERO(&input_sources);
82     
83     for (i=0; i<MAX_SOURCES; i++)
84       input_handler[i] = NULL;
85
86     have_tty = check_tty();
87 }
88
89 /*
90  *    void mux_add_input_source(int descriptor; void (*handler)(); pointer arg)
91  *        Requires: 0<=descriptor<MAX_SOURCES, mux_init has been called
92  *        Modifies: Removes the previous input handler if any for descriptor
93  *        Effects: Registers handler as the input handler for file descriptor
94  *                 descriptor.  When mux_loop() is running and input is
95  *                 available on descriptor, handler will be called with
96  *                 argument arg.
97  */
98
99 void mux_add_input_source(descriptor, handler, arg)
100      int descriptor;
101      void (*handler)();
102      pointer arg;
103 {
104 #ifdef DEBUG
105     if(descriptor < 0 || descriptor >= MAX_SOURCES)
106       abort(); /* <<<>>> */
107 #endif
108     
109     input_handler[descriptor] = handler;
110     input_handler_arg[descriptor] = arg;
111     FD_SET(descriptor, &input_sources);
112     if(descriptor > max_source)
113       max_source = descriptor;
114 }
115
116 /*
117  *    void mux_loop()
118  *        Requires: mux_init has been called.
119  *        Effects: Loops until mux_end_loop_p becomes true.  (Sets
120  *                 mux_end_loop_p false to start).  Whenever input is
121  *                 available on an input source which has a registered
122  *                 handler (see mux_add_input_source), that handler is
123  *                 called with its argument.  It is guaranteed that if
124  *                 input is available on a source, its respective input
125  *                 handler, if any, will eventually be called.  No other
126  *                 ordering guarantees are made.  When some signal handler
127  *                 or input handler eventually sets mux_end_loop_p to
128  *                 true, we return.
129  */
130
131 void mux_loop()
132 {
133     int i, nfds;
134     fd_set inputs, outputs;
135     struct timeval tv, *tvp;
136
137     mux_end_loop_p = 0;
138
139     for (;;) {
140         /*
141          * Exit if mux_end_loop_p has been set to true by a handler:
142          */
143         if (mux_end_loop_p)
144           break;
145
146         if (have_tty) {
147             tv.tv_sec = 10;
148             tv.tv_usec = 0;
149             tvp = &tv;
150         } else {
151             tvp = NULL;
152         }
153
154         /*
155          * Do a select on all the file descriptors we care about to
156          * wait until at least one of them has input available:
157          */
158         inputs = input_sources;
159         FD_ZERO(&outputs);
160
161 #ifdef HAVE_ARES
162         nfds = ares_fds(achannel, &inputs, &outputs);
163         if (nfds < max_source + 1)
164             nfds = max_source + 1;
165         tvp = ares_timeout(achannel, tvp, &tv);
166 #else
167         nfds = max_source + 1;
168 #endif
169
170         i = select(nfds, &inputs, &outputs, NULL, tvp);
171
172         if (i == -1) {
173             if (errno == EINTR)
174                 continue;    /* on a signal restart checking mux_loop_end_p */
175             else
176                 FATAL_TRAP( errno, "while selecting" );
177         }
178         else if (i == 0) {
179             if (have_tty && !check_tty()) {
180                 mux_end_loop_p = 1;
181                 continue;
182             }
183         }
184
185 #ifdef HAVE_ARES
186         ares_process(achannel, &inputs, &outputs);
187 #endif
188
189         /*
190          * Call all input handlers whose corresponding file descriptors have
191          * input:
192          */
193         for(i=0; i<=max_source; i++)
194           if (FD_ISSET(i, &inputs) && input_handler[i]) {
195 #ifdef DEBUG
196               if (zwgc_debug)
197                 fprintf(stderr,
198                         "mux_loop...activity on fd %d, calling %x(%x)\n",
199                         i,input_handler[i],input_handler_arg[i]);
200 #endif
201               input_handler[i](input_handler_arg[i]);
202           }
203     }
204 }
205
206 static int check_tty()
207 {
208     register int result;
209     int pgrp;
210     int tty = open("/dev/tty", O_RDONLY|O_NDELAY);
211
212     if (tty < 0) return 0;
213
214 #if defined(_POSIX_VERSION)
215     result = ( ((pgrp = tcgetpgrp(tty)) < 0)      ? 0 : 1 );
216 #else
217     result = ( (ioctl(tty, TIOCGPGRP, &pgrp) < 0) ? 0 : 1 );
218 #endif
219
220     close(tty);
221     return(result);
222 }