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
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
7 * $Id: mux.c 2328 2009-03-22 17:34:39Z kcr $
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_mux_c[] = "$Id: mux.c 2328 2009-03-22 17:34:39Z kcr $";
20 /****************************************************************************/
22 /* Module containing code to wait on multiple file descriptors: */
24 /****************************************************************************/
26 #include <zephyr/zephyr.h>
37 #include <sys/select.h>
41 * mux_end_loop_p - Setting this to true during a mux_loop causes the mux_loop
48 * have_tty - is defined to be true if there is a controlling tty for this
49 * process. When we can no longer access the controlling tty,
50 * the process will die.
53 static int have_tty = 0;
56 * max_source - the maximum file descriptor that a handler was ever
60 static int max_source = -1;
63 * Which file descriptors we're waiting on for input & the accompanying
64 * input handlers & their arguments:
67 static fd_set input_sources;
68 static void (*input_handler[MAX_SOURCES])(void *);
69 static pointer input_handler_arg[MAX_SOURCES];
71 static int check_tty(void);
75 * Requires: mux_init has never been called before
76 * Effects: Initializes the mux module. Must be called before
85 FD_ZERO(&input_sources);
87 for (i=0; i<MAX_SOURCES; i++)
88 input_handler[i] = NULL;
90 have_tty = check_tty();
94 * void mux_add_input_source(int descriptor; void (*handler)(); pointer arg)
95 * Requires: 0<=descriptor<MAX_SOURCES, mux_init has been called
96 * Modifies: Removes the previous input handler if any for descriptor
97 * Effects: Registers handler as the input handler for file descriptor
98 * descriptor. When mux_loop() is running and input is
99 * available on descriptor, handler will be called with
104 mux_add_input_source(int descriptor,
105 void (*handler)(void *),
109 if(descriptor < 0 || descriptor >= MAX_SOURCES)
110 abort(); /* <<<>>> */
113 input_handler[descriptor] = handler;
114 input_handler_arg[descriptor] = arg;
115 FD_SET(descriptor, &input_sources);
116 if(descriptor > max_source)
117 max_source = descriptor;
122 * Requires: mux_init has been called.
123 * Effects: Loops until mux_end_loop_p becomes true. (Sets
124 * mux_end_loop_p false to start). Whenever input is
125 * available on an input source which has a registered
126 * handler (see mux_add_input_source), that handler is
127 * called with its argument. It is guaranteed that if
128 * input is available on a source, its respective input
129 * handler, if any, will eventually be called. No other
130 * ordering guarantees are made. When some signal handler
131 * or input handler eventually sets mux_end_loop_p to
139 fd_set inputs, outputs;
140 struct timeval tv, *tvp;
146 * Exit if mux_end_loop_p has been set to true by a handler:
154 tv.tv_sec = plus_timequeue_events();
155 if (tv.tv_sec > 10) tv.tv_sec = 10;
162 tv.tv_sec = plus_timequeue_events();
170 * Do a select on all the file descriptors we care about to
171 * wait until at least one of them has input available:
173 inputs = input_sources;
177 nfds = ares_fds(achannel, &inputs, &outputs);
178 if (nfds < max_source + 1)
179 nfds = max_source + 1;
180 tvp = ares_timeout(achannel, tvp, &tv);
182 nfds = max_source + 1;
185 i = select(nfds, &inputs, &outputs, NULL, tvp);
189 continue; /* on a signal restart checking mux_loop_end_p */
191 FATAL_TRAP( errno, "while selecting" );
194 if (have_tty && !check_tty()) {
201 ares_process(achannel, &inputs, &outputs);
205 * Call all input handlers whose corresponding file descriptors have
208 for(i=0; i<=max_source; i++)
209 if (FD_ISSET(i, &inputs) && input_handler[i]) {
213 "mux_loop...activity on fd %d, calling %x(%x)\n",
214 i,input_handler[i],input_handler_arg[i]);
216 input_handler[i](input_handler_arg[i]);
226 int tty = open("/dev/tty", O_RDONLY|O_NDELAY);
228 if (tty < 0) return 0;
230 #if defined(_POSIX_VERSION)
231 result = ( ((pgrp = tcgetpgrp(tty)) < 0) ? 0 : 1 );
233 result = ( (ioctl(tty, TIOCGPGRP, &pgrp) < 0) ? 0 : 1 );