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,v 1.13 1999/01/22 23:20:23 ghudson Exp $
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,v 1.13 1999/01/22 23:20:23 ghudson Exp $";
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])();
66 static pointer input_handler_arg[MAX_SOURCES];
68 static int check_tty();
72 * Requires: mux_init has never been called before
73 * Effects: Initializes the mux module. Must be called before
81 FD_ZERO(&input_sources);
83 for (i=0; i<MAX_SOURCES; i++)
84 input_handler[i] = NULL;
86 have_tty = check_tty();
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
99 void mux_add_input_source(descriptor, handler, arg)
105 if(descriptor < 0 || descriptor >= MAX_SOURCES)
106 abort(); /* <<<>>> */
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;
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
134 fd_set inputs, outputs;
135 struct timeval tv, *tvp;
141 * Exit if mux_end_loop_p has been set to true by a handler:
155 * Do a select on all the file descriptors we care about to
156 * wait until at least one of them has input available:
158 inputs = input_sources;
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);
167 nfds = max_source + 1;
170 i = select(nfds, &inputs, &outputs, NULL, tvp);
174 continue; /* on a signal restart checking mux_loop_end_p */
176 FATAL_TRAP( errno, "while selecting" );
179 if (have_tty && !check_tty()) {
186 ares_process(achannel, &inputs, &outputs);
190 * Call all input handlers whose corresponding file descriptors have
193 for(i=0; i<=max_source; i++)
194 if (FD_ISSET(i, &inputs) && input_handler[i]) {
198 "mux_loop...activity on fd %d, calling %x(%x)\n",
199 i,input_handler[i],input_handler_arg[i]);
201 input_handler[i](input_handler_arg[i]);
206 static int check_tty()
210 int tty = open("/dev/tty", O_RDONLY|O_NDELAY);
212 if (tty < 0) return 0;
214 #if defined(_POSIX_VERSION)
215 result = ( ((pgrp = tcgetpgrp(tty)) < 0) ? 0 : 1 );
217 result = ( (ioctl(tty, TIOCGPGRP, &pgrp) < 0) ? 0 : 1 );