diff options
Diffstat (limited to 'libtecla-1.6.3/html/gl_io_mode.html')
-rw-r--r-- | libtecla-1.6.3/html/gl_io_mode.html | 634 |
1 files changed, 634 insertions, 0 deletions
diff --git a/libtecla-1.6.3/html/gl_io_mode.html b/libtecla-1.6.3/html/gl_io_mode.html new file mode 100644 index 0000000..42d27dc --- /dev/null +++ b/libtecla-1.6.3/html/gl_io_mode.html @@ -0,0 +1,634 @@ +Content-type: text/html + +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<HTML><HEAD><TITLE>Man page of gl_io_mode</TITLE> +</HEAD><BODY> +<H1>gl_io_mode</H1> +Section: C Library Functions (3)<BR><A HREF="#index">Index</A> +<A HREF="index.html">Return to Main Contents</A><HR> + +<A NAME="lbAB"> </A> +<H2>NAME</H2> + +<BR> gl_io_mode, gl_raw_io, gl_normal_io, gl_tty_signals, gl_abandon_line, +<BR> gl_handle_signal, gl_pending_io - How to use gl_get_line() from an external event loop. +<A NAME="lbAC"> </A> +<H2>SYNOPSIS</H2> + +<PRE> +#include <<A HREF="file:///usr/include/libtecla.h">libtecla.h</A>> + +int gl_io_mode(GetLine *gl, GlIOMode mode); + +int gl_raw_io(GetLine *gl); + +int gl_normal_io(GetLine *gl); + +int gl_tty_signals(void (*term_handler)(int), + void (*susp_handler)(int), + void (*cont_handler)(int), + void (*size_handler)(int)); + +void gl_abandon_line(GetLine *gl); + +void gl_handle_signal(int signo, GetLine *gl, int ngl); + +GlPendingIO gl_pending_io(GetLine *gl); + +</PRE> + +<P> +<A NAME="lbAD"> </A> +<H2>DESCRIPTION</H2> + +<P> +The <B>gl_get_line()</B> function, which is documented separately in +the <B><A HREF="gl_get_line.html">gl_get_line</A>(3)</B> man page, supports two different I/O modes. +These are selected by calling the <B>gl_io_mode()</B> function. +<P> +<P> +<PRE> + int gl_io_mode(GetLine *gl, GlIOMode mode); +</PRE> + +<P> +<P> +The <B>mode</B> argument of this function specifies the new I/O mode, +and must be one of the following. +<P> +<P> +<PRE> + GL_NORMAL_MODE - Select the normal blocking-I/O mode. + In this mode <B>gl_get_line()</B> + doesn't return until either an error + occurs of the user finishes entering a + new line. This mode is the focus of + the <B><A HREF="gl_get_line.html">gl_get_line</A>(3)</B> man page. + + GL_SERVER_MODE - Select non-blocking server I/O mode. + In this mode, since non-blocking + terminal I/O is used, the entry of + each new input line typically requires + many calls to <B>gl_get_line()</B> from + an external I/O-driven event loop. + This mode is the focus of this man + page. +</PRE> + +<P> +<P> +Newly created <B>GetLine</B> objects start in normal I/O +mode, so to switch to non-blocking server mode requires an +initial call to <B>gl_io_mode()</B>. +<P> +<A NAME="lbAE"> </A> +<H2>SERVER I/O MODE</H2> + +<P> +In non-blocking server I/O mode, the application is required +to have an event loop which calls <B>gl_get_line()</B> +whenever the terminal file descriptor can do the type I/O +that <B>gl_get_line()</B> is waiting for. To determine which +type of I/O <B>gl_get_line()</B> is waiting for, the +application calls the <B>gl_pending_io()</B> function. +<P> +<P> +<PRE> + GlPendingIO gl_pending_io(GetLine *gl); +</PRE> + +<P> +<P> +The return value of this function is one of the following two +enumerated values. +<P> +<P> +<PRE> + GLP_READ - gl_get_line() is waiting to write a + character to the terminal. + + GLP_WRITE - gl_get_line() is waiting to read a + character from the keyboad. +</PRE> + +<P> +<P> +If the application is using either the <B>select()</B> or <B>poll()</B> +system calls to watch for I/O on a group of file descriptors, then it +should call the <B>gl_pending_io()</B> function before each call to +these functions to see which direction of I/O it should tell them to +watch for, and configure their arguments accordingly. In the case of +the <B>select()</B> system call, this means using the <B>FD_SET()</B> +macro to add the terminal file descriptor either to the set of file +descriptors to be watched for readability, or the set to be watched +for writability. +<P> +As in normal I/O mode, the return value of <B>gl_get_line()</B> is +either a pointer to a completed input line, or <B>NULL</B>. However, +whereas in normal I/O mode a <B>NULL</B> return value always means that +an error occurred, in non-blocking server mode, <B>NULL</B> is also +returned when <B>gl_get_line()</B> can't read or write to the terminal +without blocking. Thus in non-blocking server mode, in order to +determine when a <B>NULL</B> return value signifies that an error +occurred or not, it is necessary to call the <B>gl_return_status()</B> +function. If this function returns the enumerated value, +<B>GLR_BLOCKED</B>, as documented in the <B><A HREF="gl_get_line.html">gl_get_line</A>(3)</B> man page, +this means that <B>gl_get_line()</B> is waiting for I/O, and no error +has occurred. +<P> +When <B>gl_get_line()</B> returns <B>NULL</B> and +<B>gl_return_status()</B> indicates that this is due to blocked +terminal I/O, the application should call <B>gl_get_line()</B> again +when the type of I/O reported by <B>gl_pending_io()</B> becomes +possible. The <B>prompt</B>, <B>start_line</B> and <B>start_pos</B> +arguments of <B>gl_get_line()</B> will be ignored on these calls. If +you need to change the prompt of the line that is currently being +edited, then you can call the <B>gl_replace_prompt()</B> function +(documented in the <B><A HREF="gl_get_line.html">gl_get_line</A>(3) man page) between calls to +gl_get_line()</B>. +<P> +<A NAME="lbAF"> </A> +<H2>GIVING UP THE TERMINAL</H2> + +<P> +A complication that is unique to non-blocking server mode is that it +requires that the terminal be left in raw mode between calls to +<B>gl_get_line()</B>. If this weren't the case, the external event loop +wouldn't be able to detect individual key-presses, and the basic line +editing implemented by the terminal driver would clash with the +editing provided by <B>gl_get_line()</B>. What this means is that any +time that the terminal needs to be used for other things than entering +a new input line with <B>gl_get_line()</B>, it needs to be restored to +a usable state. In particular, whenever the process is suspended or +terminated, the terminal must be returned to a normal state. If this +isn't done, then depending on the characteristics of the shell that +was used to invoke the program, the user may end up with a hung +terminal. To this end, the <B>gl_normal_io()</B> function is provided +for switching the terminal back to the state that it was in when raw +mode was last established. +<P> +<P> +<PRE> + int gl_normal_io(GetLine *gl); +</PRE> + +<P> +<P> +What this function does is first flush any pending output to the +terminal, then move the cursor to the start of the terminal line which +follows the end of the incompletely entered input line. At this point +it is safe to suspend or terminate the process, and it is safe for the +application to read and write to the terminal. To resume entry of the +input line, the application should call the <B>gl_raw_io()</B> +function. +<P> +<P> +<PRE> + int gl_raw_io(GetLine *gl); +</PRE> + +<P> +<P> +This function starts a new line, redisplays the partially completed +input line (if any), restores the cursor position within this line to +where it was when <B>gl_normal_io()</B> was called, then switches back +to raw, non-blocking terminal mode ready to continue entry of the +input line when <B>gl_get_line()</B> is next called. +<P> +Note that in non-blocking server mode, if <B>gl_get_line()</B> is +called after a call to <B>gl_normal_io()</B>, without an intervening +call to <B>gl_raw_io()</B>, <B>gl_get_line()</B> will call +<B>gl_raw_mode()</B> itself, and the terminal will remain in this mode +when <B>gl_get_line()</B> returns. +<P> +<A NAME="lbAG"> </A> +<H2>SIGNAL HANDLING</H2> + +<P> +In the previous section it was pointed out that in non-blocking server +mode, the terminal must be restored to a sane state whenever a signal +is received that either suspends or terminates the process. In normal +I/O mode, this is done for you by <B>gl_get_line()</B>, but in +non-blocking server mode, since the terminal is left in raw mode +between calls to <B>gl_get_line()</B>, this signal handling has to be +done by the application. Since there are many signals that can suspend +or terminate a process, as well as other signals that are important to +<B>gl_get_line()</B>, such as the <B>SIGWINCH</B> signal, which tells it +when the terminal size has changed, the <B>gl_tty_signals()</B> +function is provided for installing signal handlers for all pertinent +signals. +<P> +<P> +<PRE> + int gl_tty_signals(void (*term_handler)(int), + void (*susp_handler)(int), + void (*cont_handler)(int), + void (*size_handler)(int)); +</PRE> + +<P> +<P> +What this does is use <B>gl_get_line()</B>'s internal list of signals +to assign specified signal handlers to groups of signals. The +arguments of this function are as follows. +<P> +<P> +<PRE> + term_handler - This is the signal handler that is to be + used to trap signals that by default + terminate any process that receives + them (eg. SIGINT or SIGTERM). + + susp_handler - This is the signal handler that is to be + used to trap signals that by default + suspend any process that receives them, + (eg. SIGTSTP or SIGTTOU). + + cont_handler - This is the signal handler that is to be + used to trap signals that are usually + sent when a process resumes after being + suspended (usually SIGCONT). Beware that there is + nothing to stop a user from sending one of these + signals at other times. + + size_handler - This signal handler is used to trap + signals that are sent to processes when + their controlling terminals are resized + by the user (eg. SIGWINCH). +</PRE> + +<P> +<P> +These arguments can all be the same, if so desired, and you can +specify <B>SIG_IGN</B> (ignore this signal) or <B>SIG_DFL</B> (use the +system-provided default signal handler) instead of a function where +pertinent. In particular, it is rarely useful to trap <B>SIGCONT</B>, +so the <B>cont_handler</B> argument will usually be <B>SIG_DFL</B> or +<B>SIG_IGN</B>. +<P> +The <B>gl_tty_signals()</B> function uses the POSIX <B>sigaction()</B> +function to install these signal handlers, and it is careful to use +the <B>sa_mask</B> member of each sigaction structure to ensure that +only one of these signals is ever delivered at a time. This guards +against different instances of these signal handlers from +simultaneously trying to write to common global data, such as a shared +<B>sigsetjmp()</B> buffer or a signal-received flag. +<P> +The signal handlers that are installed by this function, should call +the <B>gl_handle_signal(). +<P> +<P> +</B><PRE> + void gl_handle_signal(int signo, GetLine *gl, int ngl); +</PRE> + +<P> +<P> +The <B>signo</B> argument tells this function which signal it is being +asked to respond to, and the <B>gl</B> argument should be a pointer to +the first element of an array of <B>ngl</B> <B>GetLine</B> objects. If +your application only has one of these objects, just pass its pointer +as the <B>gl</B> argument and specify <B>ngl</B> as <B>1</B>. +<P> +Depending on the signal that is being handled, this function does +different things. +<P> +<A NAME="lbAH"> </A> +<H3>Terminal resize signals (SIGWINCH)</H3> + +<P> +If the signal indicates that the terminal was resized, then it +arranges for the next call to <B>gl_get_line()</B> to ask the terminal +for its new size and redraw the input line accordingly. In order that +<B>gl_get_line()</B> be called as soon as possible to do this, +<B>gl_handle_signal()</B> also arranges that the next call to +<B>gl_pending_io()</B> will return <B>GLP_WRITE</B>. Thus if the +application waits for I/O in <B>select()</B> or <B>poll()</B>, then the +application needs to ensure that these functions will be reliably +aborted when a signal is caught and handled by the application. More +on this below. +<P> +<A NAME="lbAI"> </A> +<H2>Process termination signals.</H2> + +<P> +If the signal that was caught is one of those that by default +terminates any process that receives it, then <B>gl_handle_signal()</B> +does the following steps. +<P> +1. First it blocks the delivery of all signals that can be +<BR> blocked (ie. <B>SIGKILL</B> and <B>SIGSTOP</B> can't be blocked) +<P> +2. Next it calls <B>gl_normal_io()</B> for each of the <B>ngl</B> +<BR> <B>GetLine</B> objects. Note that this does nothing to any of the +<BR> <B>GetLine</B> objects that aren't currently in raw mode. +<P> +3. Next it sets the signal handler of the signal to its default, +<BR> process-termination disposition. +<P> +4. Next it re-sends the process the signal that was caught. +<P> +5. Finally it unblocks delivery of this signal, which +<BR> results in the process being terminated. +<P> +<A NAME="lbAJ"> </A> +<H2>Process suspension signals.</H2> + +<P> +If the default disposition of the signal is to suspend the process, +the same steps are executed as for process termination signals, except +that when the process is later resumed, <B>gl_handle_signal()</B> +continues, and does the following steps. +<P> +6. It re-blocks delivery of the signal. +<P> +7. It reinstates the signal handler of the signal to the one +<BR> that was displaced when its default disposition was substituted. +<P> +8. For any of the <B>GetLine</B> objects that were in raw mode when +<BR> <B>gl_handle_signal()</B> was called, <B>gl_handle_signal()</B> then +<BR> calls <B>gl_raw_io()</B>, to resume entry of the input lines on +<BR> those terminals. +<P> +9. Finally, it restores the signal process mask to how it +<BR> was when <B>gl_handle_signal()</B> was called. +<P> +Note that the process is suspended or terminated using the original +signal that was caught, rather than using the uncatchable +<B>SIGSTOP</B> and <B>SIGKILL</B> signals. This is important, because +when a process is suspended or terminated, the parent of the process +may wish to use the status value returned by the <B>wait()</B> system +call to figure out which signal was responsible. In particular, most +shells use this information to print a corresponding message to the +terminal. Users would be rightly confused if when their process +received a <B>SIGPIPE</B> signal, the program responded by sending +itself a <B>SIGKILL</B> signal, and the shell then printed out the +provocative statement, "Killed!". +<P> +<A NAME="lbAK"> </A> +<H2>INTERRUPTING THE EVENT LOOP</H2> + +<P> +If a signal is caught and handled when the application's event loop is +waiting in <B>select()</B> or <B>poll()</B>, these functions will be +aborted with <B>errno</B> set to <B>EINTR</B>. When this happens the +event loop should call <B>gl_pending_io()</B>, before calling +<B>select()</B> or <B>poll()</B> again. It should then arrange for +<B>select()</B> or <B>poll()</B> to wait for the type of I/O that this +reports. This is necessary, because any signal handler which calls +<B>gl_handle_signal()</B>, will frequently change the type of I/O that +<B>gl_get_line()</B> is waiting for. +<P> +Unfortunately, if a signal arrives between the statements which +configure the arguments of <B>select()</B> or <B>poll()</B> and the +calls to these functions, then the signal will not be seen by these +functions, which will then not be aborted. If these functions are +waiting for keyboard input from the user when the signal is received, +and the signal handler arranges to redraw the input line to accomodate +a terminal resize or the resumption of the process, then this +redisplay will be end up being delayed until the user hits the next +key. Apart from puzzling the user, this clearly isn't a serious +problem. However there is a way, albeit complicated, to completely +avoid this race condition. The following steps illustrate this. +<P> +1. Block all of the signals that <B>gl_get_line()</B> catches, +<BR> by passing the signal set returned by <B>gl_list_signals()</B> to +<BR> <B>sigprocmask()</B>. +<P> +2. Call <B>gl_pending_io()</B> and set up the arguments of +<BR> <B>select()</B> or <B>poll()</B> accordingly. +<P> +3. Call <B>sigsetjmp()</B> with a non-zero <B>savesigs</B> argument. +<P> +4. Initially this <B>sigsetjmp()</B> statement will return zero, +<BR> indicating that control isn't resuming there after a matching +<BR> call to <B>siglongjmp()</B>. +<P> +5. Replace all of the handlers of the signals that <B>gl_get_line()</B> +<BR> is configured to catch, with a signal handler that first records +<BR> the number of the signal that was caught, in a file-scope variable, +<BR> then calls <B>siglongjmp()</B> with a non-zero value argument, to +<BR> return execution to the above <B>sigsetjmp()</B> +<BR> statement. Registering these signal handlers can conveniently be +<BR> done using the <B>gl_tty_signals()</B> function. +<P> +6. Set the file-scope variable that the above signal handler uses to +<BR> record any signal that is caught to -1, so that we can check +<BR> whether a signal was caught by seeing if it contains a valid signal +<BR> number. +<P> +7. Now unblock the signals that were blocked in step 1. Any signal +<BR> that was received by the process in between step 1 and now will +<BR> now be delivered, and trigger our signal handler, as will any +<BR> signal that is received until we block these signals again. +<P> +8. Now call <B>select()</B> or <B>poll()</B>. +<P> +9. When <B>select()</B> returns, again block the signals that were +<BR> unblocked in step 7. +<P> +If a signal is arrived any time during the above steps, our signal +handler will be triggered and cause control to return to the +<B>sigsetjmp()</B> statement, where this time, <B>sigsetjmp()</B> will +return non-zero, indicating that a signal was caught. When this +happens we simply skip the above block of statements, and continue +with the following statements, which are executed regardless of +whether or not a signal is caught. Note that when <B>sigsetjmp()</B> +returns, regardless of why it returned, the process signal mask is +returned to how it was when <B>sigsetjmp()</B> was called. Thus the +following statements are always executed with all of our signals +blocked. +<P> +9. Reinstate the signal handlers that were displaced in step 5. +<P> +10. Check wether a signal was caught, by checking the file-scope +<BR> variable that the signal handler records signal numbers in. +<P> +11. If a signal was caught, send this signal to the application +<BR> again, and unblock just this signal, so that it invokes the +<BR> signal handler which we just reinstated in step 10. +<P> +12. Unblock all of the signals that were blocked in step 7. +<P> +Since this is complicated, note that <B>demo3.c</B> includes a working +example of how to do this. The method used there however, is more +general than the above. What it provides is a wrapper function around +<B>select()</B> which encompasses steps 3 to 11. In this wrapper, +rather than use <B>gl_list_signals()</B> to figure out the signals to +block, and and <B>gl_tty_signals()</B> to assign and revert signal +handlers, one of its arguments is a <B>sigset_t</B> which specifies +which signals to block and assign signal handlers to. This function +thus doesn't depend on <B>gl_get_line()</B> and can thus be used in +other situations where race-condition-free signal handling is +required. +<P> +<A NAME="lbAL"> </A> +<H2>SIGNALS CAUGHT BY GL_GET_LINE</H2> + +<P> +Since the application is expected to handle signals in non-blocking +server mode, <B>gl_get_line()</B> doesn't attempt to duplicate this +when it is being called. If one of the signals that it is configured +to catch is sent to the application while <B>gl_get_line()</B> is being +called, <B>gl_get_line()</B> reinstates the caller's signal handlers, +then just before returning, re-sends the signal to the process to let +the application's signal handler handle it. If the process isn't +terminated by this signal, <B>gl_get_line()</B> returns <B>NULL</B>, and +a following call to <B>gl_return_status()</B> returns the enumerated +value <B>GLR_SIGNAL</B>. +<P> +<A NAME="lbAM"> </A> +<H2>ABORTING LINE INPUT</H2> + +<P> +Often, rather than letting it terminate the process, applications +respond to the SIGINT user-interrupt signal by aborting the current +input line. The way to do this in non-blocking server-I/O mode is to +not call <B>gl_handle_signal()</B> when this signal is caught, but +instead to call the <B>gl_abandon_line()</B>. +<P> +<P> +<PRE> + void gl_abandon_line(GetLine *gl); +</PRE> + +<P> +<P> +This function arranges that when <B>gl_get_line()</B> is next called, +it first flushes any pending output to the terminal, then discardes +the current input line, outputs a new prompt on the next line, and +finally starts accepting input of a new input line from the user. +<P> +<A NAME="lbAN"> </A> +<H2>SIGNAL SAFE FUNCTIONS</H2> + +<P> +Provided that certain rules are followed, the following functions can +have been written to be safely callable from signal handlers. Other +functions in this library should not be called from signal handlers. +<P> +<P> +<PRE> + gl_normal_io() + gl_raw_io() + gl_handle_signal() + gl_abandon_line() +</PRE> + +<P> +<P> +In order for this to be true, all signal handlers that call these +functions must be registered in such a way that only one instance of +any one of them can be running at one time. The way to do this is to +use the POSIX <B>sigaction()</B> function to register all signal +handlers, and when doing this, use the <B>sa_mask</B> member of the +corresponding sigaction structure, to indicate that all of the signals +who's handlers invoke the above functions, should be blocked when the +current signal is being handled. This prevents two signal handlers +from operating on a <B>GetLine</B> object at the same time. +<P> +To prevent signal handlers from accessing a <B>GetLine</B> object while +<B>gl_get_line()</B> or any of its associated public functions are +operating on it, all public functions associated with +<B>gl_get_line()</B>, including <B>gl_get_line()</B> itself, temporarily +block the delivery of signals when they are accessing <B>GetLine</B> +objects. Beware that the only signals that they block are the signals +that <B>gl_get_line()</B> is currently configured to catch, so be sure +that if you call any of the above functions from signal handlers, that +the signals that these handlers are assigned to are configured to be +caught by <B>gl_get_line()</B> (see <B>gl_trap_signal()</B>). +<P> +<A NAME="lbAO"> </A> +<H2>USING TIMEOUTS TO POLL</H2> + +<P> +If instead of using <B>select()</B> or <B>poll()</B> to wait for I/O, +your application just needs to get out of <B>gl_get_line()</B> +periodically to briefly do something else before returning to accept +input from the user, this can be done in non-blocking server mode by +using the <B>gl_inactivity_timeout()</B> function (see +<B><A HREF="gl_get_line.html">gl_get_line</A>(3)</B>), to specify that a callback function that +returns <B>GLTO_CONTINUE</B> should be called whenever +<B>gl_get_line()</B> has been waiting for I/O for more than a specified +amount of time. +<P> +When this callback is triggered, <B>gl_get_line()</B> will return +<B>NULL</B>, and a following call to <B>gl_return_status()</B> will +return <B>GLR_BLOCKED</B>. +<P> +Beware that <B>gl_get_line()</B> won't return until the user +hasn't typed a key for the specified interval, so if the +interval is long, and the user keeps typing, +<B>gl_get_line()</B> may not return for a while. In other +words there is no guarantee that it will return in the time +specified. +<P> +<A NAME="lbAP"> </A> +<H2>THE SERVER DEMO PROGRAM</H2> + +<P> +The <B>demo3</B> program that is distributed with the library, provides +a working example of how to use non-blocking server I/O mode in a real +program. As far as the user is concerned, this program operates +identically to the main demo program (called <B>demo</B>), except that +whereas the main demo program uses the normal blocking I/O mode, +<B>demo3</B> using non-blocking I/O and an external event loop. The +source code can be found in <B>demo3.c</B>, and the comments therein +explain the various steps. +<P> +<A NAME="lbAQ"> </A> +<H2>FILES</H2> + +<PRE> +libtecla.a - The tecla library +libtecla.h - The tecla header file. +</PRE> + +<P> +<A NAME="lbAR"> </A> +<H2>SEE ALSO</H2> + +<P> +<PRE> +<A HREF="libtecla.html">libtecla</A>(3), <A HREF="gl_get_line.html">gl_get_line</A>(3), <A HREF="tecla.html">tecla</A>(7), <A HREF="ef_expand_file.html">ef_expand_file</A>(3), +<A HREF="cpl_complete_word.html">cpl_complete_word</A>(3), <A HREF="pca_lookup_file.html">pca_lookup_file</A>(3) +</PRE> + +<P> +<A NAME="lbAS"> </A> +<H2>AUTHOR</H2> + +Martin Shepherd (<A HREF="mailto:mcs@astro.caltech.edu">mcs@astro.caltech.edu</A>) +<P> + +<HR> +<A NAME="index"> </A><H2>Index</H2> +<DL> +<DT><A HREF="#lbAB">NAME</A><DD> +<DT><A HREF="#lbAC">SYNOPSIS</A><DD> +<DT><A HREF="#lbAD">DESCRIPTION</A><DD> +<DT><A HREF="#lbAE">SERVER I/O MODE</A><DD> +<DT><A HREF="#lbAF">GIVING UP THE TERMINAL</A><DD> +<DT><A HREF="#lbAG">SIGNAL HANDLING</A><DD> +<DL> +<DT><A HREF="#lbAH">Terminal resize signals (SIGWINCH)</A><DD> +</DL> +<DT><A HREF="#lbAI">Process termination signals.</A><DD> +<DT><A HREF="#lbAJ">Process suspension signals.</A><DD> +<DT><A HREF="#lbAK">INTERRUPTING THE EVENT LOOP</A><DD> +<DT><A HREF="#lbAL">SIGNALS CAUGHT BY GL_GET_LINE</A><DD> +<DT><A HREF="#lbAM">ABORTING LINE INPUT</A><DD> +<DT><A HREF="#lbAN">SIGNAL SAFE FUNCTIONS</A><DD> +<DT><A HREF="#lbAO">USING TIMEOUTS TO POLL</A><DD> +<DT><A HREF="#lbAP">THE SERVER DEMO PROGRAM</A><DD> +<DT><A HREF="#lbAQ">FILES</A><DD> +<DT><A HREF="#lbAR">SEE ALSO</A><DD> +<DT><A HREF="#lbAS">AUTHOR</A><DD> +</DL> +<HR> +This document was created by +<A HREF="/cgi-bin/man/man2html">man2html</A>, +using the manual pages.<BR> +Time: 22:21:57 GMT, November 09, 2014 +</BODY> +</HTML> |