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>
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$";
20 /****************************************************************************/
22 /* Module containing code to wait on multiple file descriptors: */
24 /****************************************************************************/
26 #include <zephyr/zephyr.h>
34 #include <sys/select.h>
38 * mux_end_loop_p - Setting this to true during a mux_loop causes the mux_loop
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.
50 static int have_tty = 0;
53 * max_source - the maximum file descriptor that a handler was ever
57 static int max_source = -1;
60 * Which file descriptors we're waiting on for input & the accompanying
61 * input handlers & their arguments:
64 static fd_set input_sources;
65 static void (*input_handler[MAX_SOURCES])(void *);
66 static pointer input_handler_arg[MAX_SOURCES];
68 static int check_tty(void);
72 * Requires: mux_init has never been called before
73 * Effects: Initializes the mux module. Must be called before
82 FD_ZERO(&input_sources);
84 for (i=0; i<MAX_SOURCES; i++)
85 input_handler[i] = NULL;
87 have_tty = check_tty();
91 * void mux_add_input_source(int descriptor; void (*handler)(); pointer arg)
92 * Requires: 0<=descriptor<MAX_SOURCES, mux_init has been called
93 * Modifies: Removes the previous input handler if any for descriptor
94 * Effects: Registers handler as the input handler for file descriptor
95 * descriptor. When mux_loop() is running and input is
96 * available on descriptor, handler will be called with
101 mux_add_input_source(int descriptor,
102 void (*handler)(void *),
106 if(descriptor < 0 || descriptor >= MAX_SOURCES)
107 abort(); /* <<<>>> */
110 input_handler[descriptor] = handler;
111 input_handler_arg[descriptor] = arg;
112 FD_SET(descriptor, &input_sources);
113 if(descriptor > max_source)
114 max_source = descriptor;
119 * Requires: mux_init has been called.
120 * Effects: Loops until mux_end_loop_p becomes true. (Sets
121 * mux_end_loop_p false to start). Whenever input is
122 * available on an input source which has a registered
123 * handler (see mux_add_input_source), that handler is
124 * called with its argument. It is guaranteed that if
125 * input is available on a source, its respective input
126 * handler, if any, will eventually be called. No other
127 * ordering guarantees are made. When some signal handler
128 * or input handler eventually sets mux_end_loop_p to
136 fd_set inputs, outputs;
137 struct timeval tv, *tvp;
143 * Exit if mux_end_loop_p has been set to true by a handler:
157 * Do a select on all the file descriptors we care about to
158 * wait until at least one of them has input available:
160 inputs = input_sources;
164 nfds = ares_fds(achannel, &inputs, &outputs);
165 if (nfds < max_source + 1)
166 nfds = max_source + 1;
167 tvp = ares_timeout(achannel, tvp, &tv);
169 nfds = max_source + 1;
172 i = select(nfds, &inputs, &outputs, NULL, tvp);
176 continue; /* on a signal restart checking mux_loop_end_p */
178 FATAL_TRAP( errno, "while selecting" );
181 if (have_tty && !check_tty()) {
188 ares_process(achannel, &inputs, &outputs);
192 * Call all input handlers whose corresponding file descriptors have
195 for(i=0; i<=max_source; i++)
196 if (FD_ISSET(i, &inputs) && input_handler[i]) {
200 "mux_loop...activity on fd %d, calling %x(%x)\n",
201 i,input_handler[i],input_handler_arg[i]);
203 input_handler[i](input_handler_arg[i]);
213 int tty = open("/dev/tty", O_RDONLY|O_NDELAY);
215 if (tty < 0) return 0;
217 #if defined(_POSIX_VERSION)
218 result = ( ((pgrp = tcgetpgrp(tty)) < 0) ? 0 : 1 );
220 result = ( (ioctl(tty, TIOCGPGRP, &pgrp) < 0) ? 0 : 1 );