Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.mel.connect.com.au!munnari.OZ.AU!news.hawaii.edu!ames!taligent!uunet!in1.uu.net!vixie!nnrp.vix.com!vixie From: vixie@vix.com (Paul A Vixie) Newsgroups: comp.unix.bsd.bsdi.misc,comp.unix.advocacy Subject: Re: multiple httpds vs threads vs ... (was BSDI Vs. NT...) Followup-To: poster Date: 26 Dec 1995 16:28:27 GMT Organization: Vixie Enterprises Lines: 3073 Message-ID: <VIXIE.95Dec26082827@wisdom.vix.com> References: <taxfree.3.00C439A1@primenet.com> <4be592$6tb@madeline.ins.cwru.edu> <4bhfmp$gei@Mars.mcs.com> <DK5Crs.I77@metrics.com> <4bmsjp$7lv@elf.bsdi.com> NNTP-Posting-Host: wisdom.home.vix.com In-reply-to: torek@elf.bsdi.com's message of 25 Dec 1995 11:04:25 -0800 Xref: euryale.cc.adfa.oz.au comp.unix.bsd.bsdi.misc:1850 comp.unix.advocacy:12670 >There is a third approach---in one way, kind of a compromise between >these two---and that is to provide a mechanism such as poll() or >select() by which a process can implement its own `threading' (except >that these threads can be even lighter-weight than kernel threads). You mean, like this? (Feedback would be appreciated -- BIND is switching to this paradigm soon to avoid running named-xfer or forking at all.) #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 1995-09-25 10:29 PDT by <vixie@gw.home.vix.com>. # Source directory was `/tmp_mnt/wisdom/mnt/files/users/vixie/src/eventlib'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 2235 -r--r--r-- README # 664 -r--r--r-- CHANGES # 1687 -r--r--r-- Makefile # 436 -rw-rw-r-- SysMake # 10086 -r--r--r-- eventlib.mdoc # 13118 -rw-rw-r-- eventlib.lpcat # 25096 -rw-rw-r-- eventlib.pscat # 3291 -r--r--r-- eventlib.h # 2694 -r--r--r-- eventlib_p.h # 8744 -r--r--r-- eventlib.c # 4959 -r--r--r-- timers.c # 5896 -r--r--r-- files.c # 5692 -r--r--r-- signals.c # 2048 -r--r--r-- testfiles.c # 2830 -r--r--r-- testtimers.c # 2176 -r--r--r-- testsignals.c # 140 -r--r--r-- testtimers.data # 90 -r--r--r-- testtimers2.data # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # # ============= README ============== if test -f 'README' && test X"$1" != X"-c"; then echo 'x - skipping README (file already exists)' else echo 'x - extracting README (text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && $Id: README,v 1.2 1995/09/17 23:12:25 vixie Exp $ X Paul Vixie <paul@vix.com> Internet Software Consortium X NAME X evOpen, evClose, evGetNext, evDispatch, evMainLoop, evConsTimeV, X evAddTimeV, evSubTimeV, evCmpTimeV, evSetTimer, evClearTimer, evSelectFD, X evDeselectFD, evSetSignal, evClearSignal, evTimerFunc, evUserFunc, X evSignalFunc - event handling library X DESCRIPTION X This library provides multiple outstanding asynchronous timers and I/O to X a cooperating application. The model is similar to that of the X Toolk- X it, in that events are registered with the library and the application X spends most of its time in the evMainLoop() function. If an application X already has a main loop, it can safely register events with this library X as long as it periodically calls the evGetNext() and evDispatch() func- X tions. (Note that evGetNext() has both polling and blocking modes.) X NOTES X *.lpcat and *.pscat are for users without the BSD 4.4 "mdoc" or "mandoc" macros. Don't run "make clobber" or otherwise delete these files unless you have the means to regenerate them. *.mdoc are NOT standard man pages. X The Makefile supplied with this kit is NOT in the BSD standard. As much as I admire Keith Bostic's 4.3-Reno++ system build environment, I think it was presumptuous of Keith to call it "make." You will have to edit SysMake on some systems (if you do, please send me your changes.) X COPYRIGHT X Copyright (c) 1995 by Internet Software Consortium X Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. X THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. SHAR_EOF $shar_touch -am 0917161295 'README' && chmod 0444 'README' || echo 'restore of README failed' shar_count="`wc -c < 'README'`" test 2235 -eq "$shar_count" || echo "README: original size 2235, current size $shar_count" fi # ============= CHANGES ============== if test -f 'CHANGES' && test X"$1" != X"-c"; then echo 'x - skipping CHANGES (file already exists)' else echo 'x - extracting CHANGES (text)' sed 's/^X//' << 'SHAR_EOF' > 'CHANGES' && $Id: CHANGES,v 1.2 1995/09/17 23:12:25 vixie Exp $ X 17Sep95 1600 PDT -- another bind-workers release, in tar form this time. X 6. strdup() is now provided inside testtimers.c for systems that need it. 5. the test program main()'s are now properly typed and exited. 4. public include file now uses __P and so is pre-ANSI K&R compliant. 3. cleaned up select() setup to allow for non-const timeval pointer X and also to make the whole thing cleaner and more explicit. 2. reformatted source code so that ctags and etags will find all functions. 1. moved system-specific definitions from Makefile to SysMake. X 16Sep95 2030 PDT -- released to bind-workers for comments. SHAR_EOF $shar_touch -am 0917161295 'CHANGES' && chmod 0444 'CHANGES' || echo 'restore of CHANGES failed' shar_count="`wc -c < 'CHANGES'`" test 664 -eq "$shar_count" || echo "CHANGES: original size 664, current size $shar_count" fi # ============= Makefile ============== if test -f 'Makefile' && test X"$1" != X"-c"; then echo 'x - skipping Makefile (file already exists)' else echo 'x - extracting Makefile (text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && #(general options - comment out or change as the mood strikes you) CDEBUG=-g CPPDEBUG=-DDEBUG X ###***===--- No consumer-serviceable parts beyond this point ---===***### X SHELL = /bin/sh CFLAGS = $(CDEBUG) $(CPPDEBUG) $(SYSFLAGS) LIB = libeventlib.a TAR = eventlib.tar TARS = $(TAR) $(TAR).Z $(TAR).gz OBJ = eventlib.o timers.o files.o signals.o TESTS = testtimers testfiles testsignals KIT = README CHANGES Makefile SysMake \ X eventlib.mdoc eventlib.lpcat eventlib.pscat \ X eventlib.h eventlib_p.h \ X eventlib.c timers.c files.c signals.c \ X testfiles.c testtimers.c testsignals.c \ X testtimers.data testtimers2.data X ALL = $(LIB) $(TESTS) X all:; $(SHELL) SysMake all X all-sys: $(ALL) X kit: $(KIT) X shar $(KIT) >kit X tar: $(KIT) X tar cf $(TAR) $(KIT) X compress < $(TAR) > $(TAR).Z X gzip < $(TAR) > $(TAR).gz X FRC: X clean: FRC X rm -f *.o *.a *.core X rm -f $(TESTS) core X clobber: clean X rm -f kit eventlib.lpcat eventlib.pscat X rm -f $(TARS) X $(LIB): $(OBJ) X ar rv $(LIB) $(OBJ) X ranlib $(LIB) X eventlib.pscat: eventlib.mdoc X groff -mdoc eventlib.mdoc >eventlib.pscat X eventlib.lpcat: eventlib.mdoc X nroff -mdoc eventlib.mdoc >eventlib.lpcat X testtimers: testtimers.o $(LIB) X $(CC) -o testtimers testtimers.o $(LIB) $(SYSLIBS) X testfiles: testfiles.o $(LIB) X $(CC) -o testfiles testfiles.o $(LIB) $(SYSLIBS) X testsignals: testsignals.o $(LIB) X $(CC) -o testsignals testsignals.o $(LIB) $(SYSLIBS) X eventlib.o: eventlib.c eventlib.h eventlib_p.h timers.o: timers.c eventlib.h eventlib_p.h files.o: files.c eventlib.h eventlib_p.h signals.o: signals.c eventlib.h eventlib_p.h testtimers.o: testtimers.c eventlib.h testfiles.o: testfiles.c eventlib.h testsignals.o: testsignals.c eventlib.h SHAR_EOF $shar_touch -am 0917161195 'Makefile' && chmod 0444 'Makefile' || echo 'restore of Makefile failed' shar_count="`wc -c < 'Makefile'`" test 1687 -eq "$shar_count" || echo "Makefile: original size 1687, current size $shar_count" fi # ============= SysMake ============== if test -f 'SysMake' && test X"$1" != X"-c"; then echo 'x - skipping SysMake (file already exists)' else echo 'x - extracting SysMake (text)' sed 's/^X//' << 'SHAR_EOF' > 'SysMake' && #! /bin/sh X # $Id:$ X TARGET=$1 shift X case "`uname -s`" in BSD/OS) SYSFLAGS='' X SYSLIBS='' X ;; OSF1) SYSFLAGS='-std1' X SYSLIBS='' X ;; ULTRIX) SYSFLAGS='-Dconst= -DNEED_STRDUP' X SYSLIBS='' X ;; A/UX) SYSFLAGS='-D_POSIX_SOURCE' X SYSLIBS='-lposix' X ;; *) echo unsupported system: "`uname -s`" X exit 1; X ;; esac X echo make SYSFLAGS="$SYSFLAGS" SYSLIBS="$SYSLIBS" ${TARGET}-sys exec make SYSFLAGS="$SYSFLAGS" SYSLIBS="$SYSLIBS" ${TARGET}-sys SHAR_EOF $shar_touch -am 0917161095 'SysMake' && chmod 0664 'SysMake' || echo 'restore of SysMake failed' shar_count="`wc -c < 'SysMake'`" test 436 -eq "$shar_count" || echo "SysMake: original size 436, current size $shar_count" fi # ============= eventlib.mdoc ============== if test -f 'eventlib.mdoc' && test X"$1" != X"-c"; then echo 'x - skipping eventlib.mdoc (file already exists)' else echo 'x - extracting eventlib.mdoc (text)' sed 's/^X//' << 'SHAR_EOF' > 'eventlib.mdoc' && X.\" $Id: eventlib.mdoc,v 1.1 1995/09/17 05:30:26 vixie Exp $ X.\" X.\"Copyright (c) 1995 by Internet Software Consortium X.\" X.\"Permission to use, copy, modify, and distribute this software for any X.\"purpose with or without fee is hereby granted, provided that the above X.\"copyright notice and this permission notice appear in all copies. X.\" X.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X.\"SOFTWARE. X.\" X.Dd September 14, 1995 X.Dt EVENTLIB 3 X.Os BSD 4 X.Sh NAME X.Nm evOpen , X.Nm evClose , X.Nm evGetNext , X.Nm evDispatch , X.Nm evMainLoop , X.Nm evConsTimeV , X.Nm evAddTimeV , X.Nm evSubTimeV , X.Nm evCmpTimeV , X.Nm evSetTimer , X.Nm evClearTimer , X.Nm evSelectFD , X.Nm evDeselectFD , X.Nm evSetSignal , X.Nm evClearSignal , X.Nm evTimerFunc , X.Nm evUserFunc , X.Nm evSignalFunc X.Nd event handling library X.Sh SYNOPSIS X.Fd #include <eventlib.h> X.Fn evOpen "evContext *ctx" X.Fn evClose "evContext ctx" X.Fn evGetNext "evContext ctx" "evEvent *ev" "int options" X.Fn evDispatch "evContext ctx" "evEvent ev" X.Fn evMainLoop "evContext ctx" X.Ft struct timeval X.Fn evConsTimeV "int sec" "int usec" X.Ft struct timeval X.Fn evAddTimeV "struct timeval addend1" "struct timeval addend2" X.Ft struct timeval X.Fn evSubTimeV "struct timeval minuend" "struct timeval subtrahend" X.Ft struct timeval X.Fn evCmpTimeV "struct timeval a" "struct timeval b" X.Fn evSetTimer "evContext ctx" "evTimerFunc func" "void *uap" \ "struct timeval due" "struct timeval inter" "evTimerID *id" X.Fn evClearTimer "evContext ctx" "evTimerID id" X.Fn evSelectFD "evContext ctx" "int fd" "int eventmask" \ "evFileFunc func" "void *uap" "evFileID *id" X.Fn evDeselectFD "evContext ctx" "evFileID id" X.Fn evSetSignal "evContext ctx" "int sig" "evSignalFunc func" "void *uap" \ "evSignalID *ID" X.Fn evClearSignal "evContext ctx" "evSignalID ID" X.Ft typedef void X.Fn (*evTimerFunc) "evContext ctx" "void *uap" \ "struct timeval due" "struct timeval inter" X.Ft typedef void X.Fn (*evFileFunc) "evContext ctx" "void *uap" "int fd" "int eventmask" X.Ft typedef void X.Fn (*evSignalFunc) "evContext ctx" "void *uap" "int sig" X.Sh DESCRIPTION This library provides multiple outstanding asynchronous timers and I/O to a cooperating application. The model is similar to that of the X Toolkit, in that events are registered with the library and the application spends most of its time in the X.Fn evMainLoop function. If an application already has a main loop, it can safely register events with this library as long as it periodically calls the X.Fn evGetNext and X.Fn evDispatch functions. (Note that X.Fn evGetNext has both polling and blocking modes.) X.Pp The function X.Fn evOpen creates an event context which is needed by all the other functions in this library. All information used internally by this library is bound to this context, rather than to static storage. This makes the library ``thread safe,'' and permits other library functions to use events without disrupting the application's use of events. X.Pp The function X.Fn evClose destroys a context that has been created by X.Fn evOpen . All dynamic memory bound to this context will be freed. An implicit X.Fn evTimerClear will be done on all timers set in this event context. An implicit X.Fn evDeselectFD will be done on all file descriptors selected in this event context. X.Pp The function X.Fn evGetNext potentially waits for and then retrieves the next asynchronous event, placing it in the object of the X.Fa ev pointer argument. Two mutually exclusive X.Fa options are available: X.Fa EV_POLL , meaning that X.Fn evGetNext should not block, but rather return X.Dq Fa -1 with X.Fa errno set to X.Fa EWOULDBLOCK if no events have occurred; and X.Fa EV_WAIT , which tells X.Fn evGetNext to block in X.Xr select 2 until the next event occurs. X.Pp The function X.Fn evDispatch dispatches an event retrieved by X.Fn evGetNext . This usually involves calling the function that was associated with the event when the event was registered with X.Fn evSetTimer or X.Fn evSelectFD . All events retrieved by X.Fn evGetNext must be given over to X.Fn evDispatch at some point, since there is some dynamic memory associated with each event. X.Pp The function X.Fn evMainLoop is just: X.Bd -literal -offset indent while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) X if ((x = evDispatch(opaqueCtx, event)) < 0) X break; return (x); X.Ed X.Pp In other words, get events and dispatch them until an error occurs. One such error would be that all the events under this context become unregistered; in that event, there will be nothing to wait for and X.Fn evGetNext becomes an undefined operation. X.Pp The function X.Fn evConsTimeV is a constructor for X.Dq Fa "struct timeval" which allows these structures to be created and then passed as arguments to other functions without the use of temporary variables. (If C had inline constructors, there would be no need for this function.) X.Pp The function X.Fn evAddTimeV adds two X.Dq Fa "struct timeval" values and returns the result as a X.Dq Fa "struct timeval" . X.Pp The function X.Fn evSubTimeV subtracts its second X.Dq Fa "struct timeval" argument from its first X.Dq Fa "struct timeval" argument and returns the result as a X.Dq Fa "struct timeval" . X.Pp The function X.Fn evCmpTimeV compares its two X.Dq Fa "struct timeval" arguments and returns an X.Dq Fa "int" that is less than zero if the first argument specifies an earlier time than the second, or more than zero if the first argument specifies a later time than the second, or equal to zero if both arguments specify the same time. X.Pp The function X.Fn evSetTimer registers a timer event, which will be delivered as a function call to the function specified by the X.Fa func argument. The event will be delivered at time X.Fa due , and then if time X.Fa inter is not equal to X.Dq Fa "evConsTimeV(0,0)" , subsequently at intervals equal to time X.Fa inter . As a special case, specifying a X.Fa due argument equal to X.Dq Fa "evConsTimeV(0,0)" means ``due immediately.'' The X.Fa id argument, if specified as a value other than X.Fa NULL , will be used to store the resulting ``timer \s-1ID\s+1,'' useful as an argument to X.Fn evClearTimer . Note that in a ``one shot'' timer (which has an X.Fa inter argument equal to X.Dq Fa "evConsTimeV(0,0)" X.\" putting the ) after the Dq Fa arg did not work well. --vix ) the user function X.Fa func should deallocate any dynamic memory that is uniquely bound to the X.Fa uap , since no handles to this memory will exist within the event library after a one shot timer has been delivered. X.Pp The function X.Fn evClearTimer will unregister the timer event specified by X.Fa id . Note that if the X.Fa uap specified in the corresponding X.Fn evSetTimer call is uniquely bound to any dynamic memory, then that dynamic memory should be freed by the caller before the handle is lost. After a call to X.Fn evClearTimer , no handles to this X.Fa uap will exist within the event library. X.Pp The function X.Fn evSelectFD registers a file I/O event for the file descriptor specified by X.Fa fd . Bits in the X.Fa eventmask argument are named X.Fa EV_READ , X.Fa EV_WRITE , and X.Fa EV_EXCEPT (corresponding to the ``readable,'' ``writable,'' and ``exceptional'' masks of the system's X.Xr select 2 call. At least one of these bits must be specified. If the X.Fa id argument is not equal to X.Fa NULL , it will be used to store a unique ``file event \s-1ID\s+1'' for this event, which is useful in subsequent calls to X.Fn evDelectFD . X.Pp The function X.Fn evDeselectFD unregisters the ``file event'' specified by the X.Fa id argument. If the corresponding X.Fa uap uniquely points to dynamic memory, that memory should be freed before its handle is lost, since after a call to X.Fn evDeselectFD , no handles to this event's X.Fa uap will remain within the event library. X.Pp X.Fn evSetSignal blocks a signal from delivery and registers the X.Fa func to be called when X.Fn evDispatch discovers that this signal is pending. The X.Fa id argument, if not X.Fa NULL , will be used to store a unique ``signal \s-1ID\s+1'' for this event, which is useful in subsequent calls to X.Fn evClearSignal X.Pp The function X.Fn evClearSignal deregisters the specified signal X.Fa id , unblocking it if it was unblocked before the corresponding X.Fn evSetSignal call. If the corresponding X.Fa uap uniquely points to dynamic memory, that memory should be freed before its handle is lost, since after a call to X.Fn evClearSignal , no handles on this event's X.Fa uap will exist within the event library. X.Sh RETURN VALUES All the functions whose return type is X.Dq Fa "int" use the standard convention of returning zero (0) to indicate success, or returning X.Dq Fa -1 and setting X.Fa errno to indicate failure. Other functions have return values as indicated above. X.Sh ERRORS The possible values for X.Fa errno when one of the X.Dq Fa "int" functions in this library returns X.Dq Fa -1 include those of the Standard C Library and also: X.Bl -tag -width EWOULDBLOCKAA X.It Bq Er EINVAL Some function argument has an unreasonable value. X.It Bq Er EINVAL The specified file descriptor has an integer value greater than the default X.Fa FD_SETSIZE , meaning that the application's limit is higher than the library's. X.It Bq Er ENOENT The specified event \s-1ID\s+1 does not exist. X.It Bq Er EWOULDBLOCK No events have occurred and the X.Fa EV_POLL option was specified. X.It Bq Er EBADF The specified signal was unblocked outside the library. X.El X.Sh SEE ALSO X.Xr select 2 , X.Xr malloc 3 , X.Xr XtMainLoop 3 X.Sh HISTORY The X.Nm eventlib library was designed by Paul Vixie with excellent advice from his friends and with a tip 'o the cap to the X Consortium. SHAR_EOF $shar_touch -am 0916223095 'eventlib.mdoc' && chmod 0444 'eventlib.mdoc' || echo 'restore of eventlib.mdoc failed' shar_count="`wc -c < 'eventlib.mdoc'`" test 10086 -eq "$shar_count" || echo "eventlib.mdoc: original size 10086, current size $shar_count" fi # ============= eventlib.lpcat ============== if test -f 'eventlib.lpcat' && test X"$1" != X"-c"; then echo 'x - skipping eventlib.lpcat (file already exists)' else echo 'x - extracting eventlib.lpcat (binary)' sed 's/^X//' << 'SHAR_EOF' | uudecode && begin 600 eventlib.lpcat M159%3E1,24(H,RD@("`@("`@("`@("`@("`@($)31"!0<F]G<F%M;65R)W,@ M36%N=6%L("`@("`@("`@("`@("`@($5614Y43$E"*#,I"@I."$Y!"$%-"$U% M"$4*("`@("!E"&5V"'9/"$]P"'!E"&5N"&XL(&4(978(=D,(0VP(;&\(;W,( M<V4(92P@90AE=@AV1PA'90AE=`AT3@A.90AE>`AX=`AT+"!E"&5V"'9$"$1I M"&ES"'-P"'!A"&%T"'1C"&-H"&@L(&4(978(=DT(36$(86D(:6X(;DP(3&\( M;V\(;W`(<"P@90AE=@AV0PA#;PAO;@AN<PAS5`A4:0AI;0AM90AE5@A6+`H@ M("`@(&4(978(=D$(060(9&0(9%0(5&D(:6T(;64(958(5BP@90AE=@AV4PA3 M=0AU8@AB5`A4:0AI;0AM90AE5@A6+"!E"&5V"'9#"$-M"&UP"'!4"%1I"&EM M"&UE"&56"%8L(&4(978(=E,(4V4(970(=%0(5&D(:6T(;64(97((<BP@90AE M=@AV0PA#;`AL90AE80AA<@AR5`A4:0AI;0AM90AE<@AR+"!E"&5V"'93"%-E M"&5L"&QE"&5C"&-T"'1&"$9$"$0L"B`@("`@90AE=@AV1`A$90AE<PAS90AE M;`AL90AE8PAC=`AT1@A&1`A$+"!E"&5V"'93"%-E"&5T"'13"%-I"&EG"&=N M"&YA"&%L"&PL(&4(978(=D,(0VP(;&4(96$(87((<E,(4VD(:6<(9VX(;F$( M86P(;"P@90AE=@AV5`A4:0AI;0AM90AE<@AR1@A&=0AU;@AN8PAC+"!E"&5V M"'95"%5S"'-E"&5R"')&"$9U"'5N"&YC"&,L"B`@("`@90AE=@AV4PA3:0AI M9PAG;@AN80AA;`AL1@A&=0AU;@AN8PAC("T@979E;G0@:&%N9&QI;F<@;&EB M<F%R>0H*4PA360A93@A.3PA/4`A04PA320A)4PA3"B`@("`@(P@C:0AI;@AN M8PAC;`AL=0AU9`AD90AE(#P(/&4(978(=F4(96X(;G0(=&P(;&D(:6((8BX( M+F@(:#X(/@H*("`@("!E"&5V"'9/"$]P"'!E"&5N"&XH7PAE7PAV7PA#7PAO M7PAN7PAT7PAE7PAX7PAT(%\(*E\(8U\(=%\(>"D["@H@("`@(&4(978(=D,( M0VP(;&\(;W,(<V4(92A?"&5?"'9?"$-?"&]?"&Y?"'1?"&5?"'A?"'0@7PAC M7PAT7PAX*3L*"B`@("`@90AE=@AV1PA'90AE=`AT3@A.90AE>`AX=`AT*%\( M95\(=E\(0U\(;U\(;E\(=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(95\(=E\( M15\(=E\(95\(;E\(="!?""I?"&5?"'8L(%\(:5\(;E\(="!?"&]?"'!?"'1? M"&E?"&]?"&Y?"',I.PH*("`@("!E"&5V"'9$"$1I"&ES"'-P"'!A"&%T"'1C M"&-H"&@H7PAE7PAV7PA#7PAO7PAN7PAT7PAE7PAX7PAT(%\(8U\(=%\(>"P@ M7PAE7PAV7PA%7PAV7PAE7PAN7PAT(%\(95\(=BD["@H@("`@(&4(978(=DT( M36$(86D(:6X(;DP(3&\(;V\(;W`(<"A?"&5?"'9?"$-?"&]?"&Y?"'1?"&5? M"'A?"'0@7PAC7PAT7PAX*3L*"B`@("`@7PAS7PAT7PAR7PAU7PAC7PAT(%\( M=%\(:5\(;5\(95\(=E\(85\(;`H@("`@(&4(978(=D,(0V\(;VX(;G,(<U0( M5&D(:6T(;64(958(5BA?"&E?"&Y?"'0@7PAS7PAE7PAC+"!?"&E?"&Y?"'0@ M7PAU7PAS7PAE7PAC*3L*"B`@("`@7PAS7PAT7PAR7PAU7PAC7PAT(%\(=%\( M:5\(;5\(95\(=E\(85\(;`H@("`@(&4(978(=D$(060(9&0(9%0(5&D(:6T( M;64(958(5BA?"'-?"'1?"')?"'5?"&-?"'0@7PAT7PAI7PAM7PAE7PAV7PAA M7PAL(%\(85\(9%\(9%\(95\(;E\(9%\(,2P@7PAS7PAT7PAR7PAU7PAC7PAT M(%\(=%\(:5\(;5\(95\(=E\(85\(;"!?"&%?"&1?"&1?"&5?"&Y?"&1?"#(I M.PH*("`@("!?"'-?"'1?"')?"'5?"&-?"'0@7PAT7PAI7PAM7PAE7PAV7PAA M7PAL"B`@("`@90AE=@AV4PA3=0AU8@AB5`A4:0AI;0AM90AE5@A6*%\(<U\( M=%\(<E\(=5\(8U\(="!?"'1?"&E?"&U?"&5?"'9?"&%?"&P@7PAM7PAI7PAN M7PAU7PAE7PAN7PAD+"!?"'-?"'1?"')?"'5?"&-?"'0@7PAT7PAI7PAM7PAE M7PAV7PAA7PAL(%\(<U\(=5\(8E\(=%\(<E\(85\(:%\(95\(;E\(9"D["@H@ M("`@(%\(<U\(=%\(<E\(=5\(8U\(="!?"'1?"&E?"&U?"&5?"'9?"&%?"&P* M("`@("!E"&5V"'9#"$-M"&UP"'!4"%1I"&EM"&UE"&56"%8H7PAS7PAT7PAR M7PAU7PAC7PAT(%\(=%\(:5\(;5\(95\(=E\(85\(;"!?"&$L(%\(<U\(=%\( M<E\(=5\(8U\(="!?"'1?"&E?"&U?"&5?"'9?"&%?"&P@7PAB*3L*"B`@("`@ M90AE=@AV4PA390AE=`AT5`A4:0AI;0AM90AE<@AR*%\(95\(=E\(0U\(;U\( M;E\(=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(95\(=E\(5%\(:5\(;5\(95\( M<E\(1E\(=5\(;E\(8R!?"&9?"'5?"&Y?"&,L(%\(=E\(;U\(:5\(9"!?""I? M"'5?"&%?"'`L"B`@("`@("`@("`@("!?"'-?"'1?"')?"'5?"&-?"'0@7PAT M7PAI7PAM7PAE7PAV7PAA7PAL(%\(9%\(=5\(92P@7PAS7PAT7PAR7PAU7PAC M7PAT(%\(=%\(:5\(;5\(95\(=E\(85\(;"!?"&E?"&Y?"'1?"&5?"'(L(%\( M95\(=E\(5%\(:5\(;5\(95\(<E\(25\(1"!?""I?"&E?"&0I.PH*("`@("!E M"&5V"'9#"$-L"&QE"&5A"&%R"')4"%1I"&EM"&UE"&5R"'(H7PAE7PAV7PA# M7PAO7PAN7PAT7PAE7PAX7PAT(%\(8U\(=%\(>"P@7PAE7PAV7PA47PAI7PAM M7PAE7PAR7PA)7PA$(%\(:5\(9"D["@H@("`@(&4(978(=E,(4V4(96P(;&4( M96,(8W0(=$8(1D0(1"A?"&5?"'9?"$-?"&]?"&Y?"'1?"&5?"'A?"'0@7PAC M7PAT7PAX+"!?"&E?"&Y?"'0@7PAF7PAD+"!?"&E?"&Y?"'0@7PAE7PAV7PAE M7PAN7PAT7PAM7PAA7PAS7PAK+"!?"&5?"'9?"$9?"&E?"&Q?"&5?"$9?"'5? M"&Y?"&,@7PAF7PAU7PAN7PAC+`H@("`@("`@("`@("`@7PAV7PAO7PAI7PAD M(%\(*E\(=5\(85\(<"P@7PAE7PAV7PA&7PAI7PAL7PAE7PA)7PA$(%\(*E\( M:5\(9"D["@H@("`@(&4(978(=D0(1&4(97,(<V4(96P(;&4(96,(8W0(=$8( M1D0(1"A?"&5?"'9?"$-?"&]?"&Y?"'1?"&5?"'A?"'0@7PAC7PAT7PAX+"!? M"&5?"'9?"$9?"&E?"&Q?"&5?"$E?"$0@7PAI7PAD*3L*"B`@("`@90AE=@AV M4PA390AE=`AT4PA3:0AI9PAG;@AN80AA;`AL*%\(95\(=E\(0U\(;U\(;E\( M=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(:5\(;E\(="!?"'-?"&E?"&<L(%\( M95\(=E\(4U\(:5\(9U\(;E\(85\(;%\(1E\(=5\(;E\(8R!?"&9?"'5?"&Y? M"&,L(%\(=E\(;U\(:5\(9"!?""I?"'5?"&%?"'`L"B`@("`@("`@("`@("!? M"&5?"'9?"%-?"&E?"&=?"&Y?"&%?"&Q?"$E?"$0@7P@J7PA)7PA$*3L*"B`@ M("`@90AE=@AV0PA#;`AL90AE80AA<@AR4PA3:0AI9PAG;@AN80AA;`AL*%\( M95\(=E\(0U\(;U\(;E\(=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(95\(=E\( M4U\(:5\(9U\(;E\(85\(;%\(25\(1"!?"$E?"$0I.PH*("`@("!?"'1?"'E? M"'!?"&5?"&1?"&5?"&8@7PAV7PAO7PAI7PAD"B`@("`@*`@H*@@J90AE=@AV M5`A4:0AI;0AM90AE<@AR1@A&=0AU;@AN8PAC*0@I*%\(95\(=E\(0U\(;U\( M;E\(=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(=E\(;U\(:5\(9"!?""I?"'5? M"&%?"'`L(%\(<U\(=%\(<E\(=5\(8U\(="!?"'1?"&E?"&U?"&5?"'9?"&%? M"&P@7PAD7PAU7PAE+`H@("`@("`@("`@("`@7PAS7PAT7PAR7PAU7PAC7PAT M(%\(=%\(:5\(;5\(95\(=E\(85\(;"!?"&E?"&Y?"'1?"&5?"'(I.PH*("`@ M("!?"'1?"'E?"'!?"&5?"&1?"&5?"&8@7PAV7PAO7PAI7PAD"B`@("`@*`@H M*@@J90AE=@AV1@A&:0AI;`AL90AE1@A&=0AU;@AN8PAC*0@I*%\(95\(=E\( M0U\(;U\(;E\(=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(=E\(;U\(:5\(9"!? M""I?"'5?"&%?"'`L(%\(:5\(;E\(="!?"&9?"&0L(%\(:5\(;E\(="!?"&5? M"'9?"&5?"&Y?"'1?"&U?"&%?"'-?"&LI.PH*("`@("!?"'1?"'E?"'!?"&5? M"&1?"&5?"&8@7PAV7PAO7PAI7PAD"B`@("`@*`@H*@@J90AE=@AV4PA3:0AI M9PAG;@AN80AA;`AL1@A&=0AU;@AN8PAC*0@I*%\(95\(=E\(0U\(;U\(;E\( M=%\(95\(>%\(="!?"&-?"'1?"'@L(%\(=E\(;U\(:5\(9"!?""I?"'5?"&%? M"'`L(%\(:5\(;E\(="!?"'-?"&E?"&<I.PH*1`A$10A%4PA30PA#4@A220A) M4`A05`A420A)3PA/3@A."B`@("`@5&AI<R!L:6)R87)Y('!R;W9I9&5S(&UU M;'1I<&QE(&]U='-T86YD:6YG(&%S>6YC:')O;F]U<R!T:6UE<G,@86YD($DO M3R!T;PH@("`@(&$@8V]O<&5R871I;F<@87!P;&EC871I;VXN("!4:&4@;6]D M96P@:7,@<VEM:6QA<B!T;R!T:&%T(&]F('1H92!8(%1O;VQK+0H@("`@(&ET M+"!I;B!T:&%T(&5V96YT<R!A<F4@<F5G:7-T97)E9"!W:71H('1H92!L:6)R M87)Y(&%N9"!T:&4@87!P;&EC871I;VX*("`@("!S<&5N9',@;6]S="!O9B!I M=',@=&EM92!I;B!T:&4@90AE=@AV30A-80AA:0AI;@AN3`A,;PAO;PAO<`AP M*"D@9G5N8W1I;VXN("!)9B!A;B!A<'!L:6-A=&EO;@H@("`@(&%L<F5A9'D@ M:&%S(&$@;6%I;B!L;V]P+"!I="!C86X@<V%F96QY(')E9VES=&5R(&5V96YT M<R!W:71H('1H:7,@;&EB<F%R>0H@("`@(&%S(&QO;F<@87,@:70@<&5R:6]D M:6-A;&QY(&-A;&QS('1H92!E"&5V"'9'"$=E"&5T"'1."$YE"&5X"'AT"'0H M*2!A;F0@90AE=@AV1`A$:0AI<PAS<`AP80AA=`AT8PAC:`AH*"D@9G5N8RT* M("`@("!T:6]N<RX@("A.;W1E('1H870@90AE=@AV1PA'90AE=`AT3@A.90AE M>`AX=`AT*"D@:&%S(&)O=&@@<&]L;&EN9R!A;F0@8FQO8VMI;F<@;6]D97,N M*0H*("`@("!4:&4@9G5N8W1I;VX@90AE=@AV3PA/<`AP90AE;@AN*"D@8W)E M871E<R!A;B!E=F5N="!C;VYT97AT('=H:6-H(&ES(&YE961E9"!B>2!A;&P@ M=&AE"B`@("`@;W1H97(@9G5N8W1I;VYS(&EN('1H:7,@;&EB<F%R>2X@($%L M;"!I;F9O<FUA=&EO;B!U<V5D(&EN=&5R;F%L;'D@8GD@=&AI<PH@("`@(&QI M8G)A<GD@:7,@8F]U;F0@=&\@=&AI<R!C;VYT97AT+"!R871H97(@=&AA;B!T M;R!S=&%T:6,@<W1O<F%G92X@(%1H:7,*("`@("!M86ME<R!T:&4@;&EB<F%R M>2!@8'1H<F5A9"!S869E+"<G(&%N9"!P97)M:71S(&]T:&5R(&QI8G)A<GD@ M9G5N8W1I;VYS('1O"B`@("`@=7-E(&5V96YT<R!W:71H;W5T(&1I<W)U<'1I M;F<@=&AE(&%P<&QI8V%T:6]N)W,@=7-E(&]F(&5V96YT<RX*"B`@("`@5&AE M(&9U;F-T:6]N(&4(978(=D,(0VP(;&\(;W,(<V4(92@I(&1E<W1R;WES(&$@ M8V]N=&5X="!T:&%T(&AA<R!B965N(&-R96%T960@8GD*("`@("!E"&5V"'9/ M"$]P"'!E"&5N"&XH*2X@($%L;"!D>6YA;6EC(&UE;6]R>2!B;W5N9"!T;R!T M:&ES(&-O;G1E>'0@=VEL;"!B92!F<F5E9"X@($%N"B`@("`@:6UP;&EC:70@ M90AE=@AV5`A4:0AI;0AM90AE<@AR0PA#;`AL90AE80AA<@AR*"D@=VEL;"!B M92!D;VYE(&]N(&%L;"!T:6UE<G,@<V5T(&EN('1H:7,@979E;G0@8V]N+0H@ M("`@('1E>'0N("!!;B!I;7!L:6-I="!E"&5V"'9$"$1E"&5S"'-E"&5L"&QE M"&5C"&-T"'1&"$9$"$0H*2!W:6QL(&)E(&1O;F4@;VX@86QL(&9I;&4@9&5S M8W)I<'1O<G,*("`@("!S96QE8W1E9"!I;B!T:&ES(&5V96YT(&-O;G1E>'0N M"@H@("`@(%1H92!F=6YC=&EO;B!E"&5V"'9'"$=E"&5T"'1."$YE"&5X"'AT M"'0H*2!P;W1E;G1I86QL>2!W86ET<R!F;W(@86YD('1H96X@<F5T<FEE=F5S M('1H90H@("`@(&YE>'0@87-Y;F-H<F]N;W5S(&5V96YT+"!P;&%C:6YG(&ET M(&EN('1H92!O8FIE8W0@;V8@=&AE(%\(95\(=B!P;VEN=&5R(&%R9W4M"B`@ M("`@;65N="X@(%1W;R!M=71U86QL>2!E>&-L=7-I=F4@7PAO7PAP7PAT7PAI M7PAO7PAN7PAS(&%R92!A=F%I;&%B;&4Z(%\(15\(5E\(7U\(4%\(3U\(3%\( M3"P@;65A;FEN9PH@("`@('1H870@90AE=@AV1PA'90AE=`AT3@A.90AE>`AX M=`AT*"D@<VAO=6QD(&YO="!B;&]C:RP@8G5T(')A=&AE<B!R971U<FX@8&!? M""U?"#$G)R!W:71H(%\(95\(<E\(<E\(;E\(;PH@("`@('-E="!T;R!?"$5? M"%=?"$]?"%5?"$Q?"$1?"$)?"$Q?"$]?"$-?"$L@:68@;F\@979E;G1S(&AA M=F4@;V-C=7)R960[(&%N9"!?"$5?"%9?"%]?"%=?"$%?"$E?"%0L('=H:6-H M('1E;&QS"B`@("`@90AE=@AV1PA'90AE=`AT3@A.90AE>`AX=`AT*"D@=&\@ M8FQO8VL@:6X@<V5L96-T*#(I('5N=&EL('1H92!N97AT(&5V96YT(&]C8W5R M<RX*"B`@("`@5&AE(&9U;F-T:6]N(&4(978(=D0(1&D(:7,(<W`(<&$(870( M=&,(8V@(:"@I(&1I<W!A=&-H97,@86X@979E;G0@<F5T<FEE=F5D(&)Y(&4( M978(=D<(1V4(970(=$X(3F4(97@(>'0(="@I+@H@("`@(%1H:7,@=7-U86QL M>2!I;G9O;'9E<R!C86QL:6YG('1H92!F=6YC=&EO;B!T:&%T('=A<R!A<W-O M8VEA=&5D('=I=&@@=&AE"B`@("`@979E;G0@=VAE;B!T:&4@979E;G0@=V%S M(')E9VES=&5R960@=VET:"!E"&5V"'93"%-E"&5T"'14"%1I"&EM"&UE"&5R M"'(H*2!O<B!E"&5V"'93"%-E"&5L"&QE"&5C"&-T"'1&"$9$"$0H*2X*("`@ M("!!;&P@979E;G1S(')E=')I979E9"!B>2!E"&5V"'9'"$=E"&5T"'1."$YE M"&5X"'AT"'0H*2!M=7-T(&)E(&=I=F5N(&]V97(@=&\@90AE=@AV1`A$:0AI M<PAS<`AP80AA=`AT8PAC:`AH*"D@870*("`@("!S;VUE('!O:6YT+"!S:6YC M92!T:&5R92!I<R!S;VUE(&1Y;F%M:6,@;65M;W)Y(&%S<V]C:6%T960@=VET M:"!E86-H"B`@("`@979E;G0N"@H@("`@(%1H92!F=6YC=&EO;B!E"&5V"'9- M"$UA"&%I"&EN"&Y,"$QO"&]O"&]P"'`H*2!I<R!J=7-T.@H*("`@("`@("`@ M("!W:&EL92`H*'@@/2!E=D=E=$YE>'0H;W!A<75E0W1X+"`F979E;G0L($56 M7U=!250I*2`]/2`P*0H@("`@("`@("`@("`@("`@("`@:68@*"AX(#T@979$ M:7-P871C:"AO<&%Q=65#='@L(&5V96YT*2D@/"`P*0H@("`@("`@("`@("`@ M("`@("`@("`@("`@("!B<F5A:SL*("`@("`@("`@("!R971U<FX@*'@I.PH* M("`@("!);B!O=&AE<B!W;W)D<RP@9V5T(&5V96YT<R!A;F0@9&ES<&%T8V@@ M=&AE;2!U;G1I;"!A;B!E<G)O<B!O8V-U<G,N("!/;F4*("`@("!S=6-H(&5R M<F]R('=O=6QD(&)E('1H870@86QL('1H92!E=F5N=',@=6YD97(@=&AI<R!C M;VYT97AT(&)E8V]M92!U;G)E9RT*("`@("!I<W1E<F5D.R!I;B!T:&%T(&5V M96YT+"!T:&5R92!W:6QL(&)E(&YO=&AI;F<@=&\@=V%I="!F;W(@86YD(&4( M978(=D<(1V4(970(=$X(3F4(97@(>'0(="@I"B`@("`@8F5C;VUE<R!A;B!U M;F1E9FEN960@;W!E<F%T:6]N+@H*("`@("!4:&4@9G5N8W1I;VX@90AE=@AV M0PA#;PAO;@AN<PAS5`A4:0AI;0AM90AE5@A6*"D@:7,@82!C;VYS=')U8W1O M<B!F;W(@8&!?"'-?"'1?"')?"'5?"&-?"'0@7PAT7PAI7PAM7PAE7PAV7PAA M7PAL)R<@=VAI8V@*("`@("!A;&QO=W,@=&AE<V4@<W1R=6-T=7)E<R!T;R!B M92!C<F5A=&5D(&%N9"!T:&5N('!A<W-E9"!A<R!A<F=U;65N=',@=&\*("`@ M("!O=&AE<B!F=6YC=&EO;G,@=VET:&]U="!T:&4@=7-E(&]F('1E;7!O<F%R M>2!V87)I86)L97,N("`H268@0R!H860@:6YL:6YE"B`@("`@8V]N<W1R=6-T M;W)S+"!T:&5R92!W;W5L9"!B92!N;R!N965D(&9O<B!T:&ES(&9U;F-T:6]N M+BD*"B`@("`@5&AE(&9U;F-T:6]N(&4(978(=D$(060(9&0(9%0(5&D(:6T( M;64(958(5B@I(&%D9',@='=O(&!@7PAS7PAT7PAR7PAU7PAC7PAT(%\(=%\( M:5\(;5\(95\(=E\(85\(;"<G('9A;'5E<R!A;F0@<F5T=7)N<PH@("`@('1H M92!R97-U;'0@87,@82!@8%\(<U\(=%\(<E\(=5\(8U\(="!?"'1?"&E?"&U? M"&5?"'9?"&%?"&PG)RX*"B`@("`@5&AE(&9U;F-T:6]N(&4(978(=E,(4W4( M=6((8E0(5&D(:6T(;64(958(5B@I('-U8G1R86-T<R!I=',@<V5C;VYD(&!@ M7PAS7PAT7PAR7PAU7PAC7PAT(%\(=%\(:5\(;5\(95\(=E\(85\(;"<G(&%R M9W4M"B`@("`@;65N="!F<F]M(&ET<R!F:7)S="!@8%\(<U\(=%\(<E\(=5\( M8U\(="!?"'1?"&E?"&U?"&5?"'9?"&%?"&PG)R!A<F=U;65N="!A;F0@<F5T M=7)N<R!T:&4@<F5S=6QT(&%S"B`@("`@82!@8%\(<U\(=%\(<E\(=5\(8U\( M="!?"'1?"&E?"&U?"&5?"'9?"&%?"&PG)RX*"B`@("`@5&AE(&9U;F-T:6]N M(&4(978(=D,(0VT(;7`(<%0(5&D(:6T(;64(958(5B@I(&-O;7!A<F5S(&ET M<R!T=V\@8&!?"'-?"'1?"')?"'5?"&-?"'0@7PAT7PAI7PAM7PAE7PAV7PAA M7PAL)R<@87)G=6UE;G1S"B`@("`@86YD(')E='5R;G,@86X@8&!?"&E?"&Y? M"'0G)R!T:&%T(&ES(&QE<W,@=&AA;B!Z97)O(&EF('1H92!F:7)S="!A<F=U M;65N="!S<&5C+0H@("`@(&EF:65S(&%N(&5A<FQI97(@=&EM92!T:&%N('1H M92!S96-O;F0L(&]R(&UO<F4@=&AA;B!Z97)O(&EF('1H92!F:7)S="!A<BT* M("`@("!G=6UE;G0@<W!E8VEF:65S(&$@;&%T97(@=&EM92!T:&%N('1H92!S M96-O;F0L(&]R(&5Q=6%L('1O('IE<F\@:68@8F]T:`H@("`@(&%R9W5M96YT M<R!S<&5C:69Y('1H92!S86UE('1I;64N"@H@("`@(%1H92!F=6YC=&EO;B!E M"&5V"'93"%-E"&5T"'14"%1I"&EM"&UE"&5R"'(H*2!R96=I<W1E<G,@82!T M:6UE<B!E=F5N="P@=VAI8V@@=VEL;"!B92!D96QI=BT*("`@("!E<F5D(&%S M(&$@9G5N8W1I;VX@8V%L;"!T;R!T:&4@9G5N8W1I;VX@<W!E8VEF:65D(&)Y M('1H92!?"&9?"'5?"&Y?"&,@87)G=6UE;G0N"B`@("`@5&AE(&5V96YT('=I M;&P@8F4@9&5L:79E<F5D(&%T('1I;64@7PAD7PAU7PAE+"!A;F0@=&AE;B!I M9B!T:6UE(%\(:5\(;E\(=%\(95\(<B!I<R!N;W0*("`@("!E<75A;"!T;R!@ M8%\(95\(=E\(0U\(;U\(;E\(<U\(5%\(:5\(;5\(95\(5E\(*%\(,%\(+%\( M,%\(*2<G+"!S=6)S97%U96YT;'D@870@:6YT97)V86QS(&5Q=6%L('1O('1I M;64*("`@("!?"&E?"&Y?"'1?"&5?"'(N($%S(&$@<W!E8VEA;"!C87-E+"!S M<&5C:69Y:6YG(&$@7PAD7PAU7PAE(&%R9W5M96YT(&5Q=6%L('1O"B`@("`@ M8&!?"&5?"'9?"$-?"&]?"&Y?"'-?"%1?"&E?"&U?"&5?"%9?""A?"#!?""Q? M"#!?""DG)R!M96%N<R!@8&1U92!I;6UE9&EA=&5L>2XG)R`@5&AE(%\(:5\( M9"!A<F=U;65N="P@:68*("`@("!S<&5C:69I960@87,@82!V86QU92!O=&AE M<B!T:&%N(%\(3E\(55\(3%\(3"P@=VEL;"!B92!U<V5D('1O('-T;W)E('1H M92!R97-U;'1I;F<*("`@("!@8'1I;65R($E$+"<G('5S969U;"!A<R!A;B!A M<F=U;65N="!T;R!E"&5V"'9#"$-L"&QE"&5A"&%R"')4"%1I"&EM"&UE"&5R M"'(H*2X@($YO=&4@=&AA="!I;B!A"B`@("`@8&!O;F4@<VAO="<G('1I;65R M("AW:&EC:"!H87,@86X@7PAI7PAN7PAT7PAE7PAR(&%R9W5M96YT(&5Q=6%L M('1O"B`@("`@8&!?"&5?"'9?"$-?"&]?"&Y?"'-?"%1?"&E?"&U?"&5?"%9? M""A?"#!?""Q?"#!?""DG)R`I('1H92!U<V5R(&9U;F-T:6]N(%\(9E\(=5\( M;E\(8R!S:&]U;&0@9&5A;&QO8V%T92!A;GD@9'DM"B`@("`@;F%M:6,@;65M M;W)Y('1H870@:7,@=6YI<75E;'D@8F]U;F0@=&\@=&AE(%\(=5\(85\(<"P@ M<VEN8V4@;F\@:&%N9&QE<R!T;R!T:&ES"B`@("`@;65M;W)Y('=I;&P@97AI M<W0@=VET:&EN('1H92!E=F5N="!L:6)R87)Y(&%F=&5R(&$@;VYE('-H;W0@ M=&EM97(@:&%S"B`@("`@8F5E;B!D96QI=F5R960N"@H@("`@(%1H92!F=6YC M=&EO;B!E"&5V"'9#"$-L"&QE"&5A"&%R"')4"%1I"&EM"&UE"&5R"'(H*2!W M:6QL('5N<F5G:7-T97(@=&AE('1I;65R(&5V96YT('-P96-I9FEE9"!B>0H@ M("`@(%\(:5\(9"X@3F]T92!T:&%T(&EF('1H92!?"'5?"&%?"'`@<W!E8VEF M:65D(&EN('1H92!C;W)R97-P;VYD:6YG(&4(978(=E,(4V4(970(=%0(5&D( M:6T(;64(97((<B@I(&-A;&P*("`@("!I<R!U;FEQ=65L>2!B;W5N9"!T;R!A M;GD@9'EN86UI8R!M96UO<GDL('1H96X@=&AA="!D>6YA;6EC(&UE;6]R>2!S M:&]U;&0*("`@("!B92!F<F5E9"!B>2!T:&4@8V%L;&5R(&)E9F]R92!T:&4@ M:&%N9&QE(&ES(&QO<W0N("!!9G1E<B!A(&-A;&P@=&\*("`@("!E"&5V"'9# M"$-L"&QE"&5A"&%R"')4"%1I"&EM"&UE"&5R"'(H*2P@;F\@:&%N9&QE<R!T M;R!T:&ES(%\(=5\(85\(<"!W:6QL(&5X:7-T('=I=&AI;B!T:&4@979E;G0@ M;&DM"B`@("`@8G)A<GDN"@H@("`@(%1H92!F=6YC=&EO;B!E"&5V"'93"%-E M"&5L"&QE"&5C"&-T"'1&"$9$"$0H*2!R96=I<W1E<G,@82!F:6QE($DO3R!E M=F5N="!F;W(@=&AE(&9I;&4@9&4M"B`@("`@<V-R:7!T;W(@<W!E8VEF:65D M(&)Y(%\(9E\(9"X@0FET<R!I;B!T:&4@7PAE7PAV7PAE7PAN7PAT7PAM7PAA M7PAS7PAK(&%R9W5M96YT(&%R92!N86UE9`H@("`@(%\(15\(5E\(7U\(4E\( M15\(05\(1"P@7PA%7PA67PA?7PA77PA27PA)7PA47PA%+"!A;F0@7PA%7PA6 M7PA?7PA%7PA87PA#7PA%7PA07PA4("AC;W)R97-P;VYD:6YG('1O('1H92!@ M8')E861A8FQE+"<G"B`@("`@8&!W<FET86)L92PG)R!A;F0@8&!E>&-E<'1I M;VYA;"<G(&UA<VMS(&]F('1H92!S>7-T96TG<R!S96QE8W0H,BD@8V%L;"X* M("`@("!!="!L96%S="!O;F4@;V8@=&AE<V4@8FET<R!M=7-T(&)E('-P96-I M9FEE9"X@($EF('1H92!?"&E?"&0@87)G=6UE;G0@:7,@;F]T"B`@("`@97%U M86P@=&\@7PA.7PA57PA,7PA,+"!I="!W:6QL(&)E('5S960@=&\@<W1O<F4@ M82!U;FEQ=64@8&!F:6QE(&5V96YT($E$)R<@9F]R"B`@("`@=&AI<R!E=F5N M="P@=VAI8V@@:7,@=7-E9G5L(&EN('-U8G-E<75E;G0@8V%L;',@=&\@90AE M=@AV1`A$90AE;`AL90AE8PAC=`AT1@A&1`A$*"DN"@H@("`@(%1H92!F=6YC M=&EO;B!E"&5V"'9$"$1E"&5S"'-E"&5L"&QE"&5C"&-T"'1&"$9$"$0H*2!U M;G)E9VES=&5R<R!T:&4@8&!F:6QE(&5V96YT)R<@<W!E8VEF:65D(&)Y"B`@ M("`@=&AE(%\(:5\(9"!A<F=U;65N="X@($EF('1H92!C;W)R97-P;VYD:6YG M(%\(=5\(85\(<"!U;FEQ=65L>2!P;VEN=',@=&\@9'EN86UI8PH@("`@(&UE M;6]R>2P@=&AA="!M96UO<GD@<VAO=6QD(&)E(&9R965D(&)E9F]R92!I=',@ M:&%N9&QE(&ES(&QO<W0L('-I;F-E(&%F+0H@("`@('1E<B!A(&-A;&P@=&\@ M90AE=@AV1`A$90AE<PAS90AE;`AL90AE8PAC=`AT1@A&1`A$*"DL(&YO(&AA M;F1L97,@=&\@=&AI<R!E=F5N="=S(%\(=5\(85\(<"!W:6QL(')E;6%I;@H@ M("`@('=I=&AI;B!T:&4@979E;G0@;&EB<F%R>2X*"B`@("`@90AE=@AV4PA3 M90AE=`AT4PA3:0AI9PAG;@AN80AA;`AL*"D@8FQO8VMS(&$@<VEG;F%L(&9R M;VT@9&5L:79E<GD@86YD(')E9VES=&5R<R!T:&4@7PAF7PAU7PAN7PAC('1O M(&)E"B`@("`@8V%L;&5D('=H96X@90AE=@AV1`A$:0AI<PAS<`AP80AA=`AT M8PAC:`AH*"D@9&ES8V]V97)S('1H870@=&AI<R!S:6=N86P@:7,@<&5N9&EN M9RX@(%1H92!?"&E?"&0*("`@("!A<F=U;65N="P@:68@;F]T(%\(3E\(55\( M3%\(3"P@=VEL;"!B92!U<V5D('1O('-T;W)E(&$@=6YI<75E(&!@<VEG;F%L M($E$)R<@9F]R"B`@("`@=&AI<R!E=F5N="P@=VAI8V@@:7,@=7-E9G5L(&EN M('-U8G-E<75E;G0@8V%L;',@=&\@90AE=@AV0PA#;`AL90AE80AA<@AR4PA3 M:0AI9PAG;@AN80AA;`AL*"D*"B`@("`@5&AE(&9U;F-T:6]N(&4(978(=D,( M0VP(;&4(96$(87((<E,(4VD(:6<(9VX(;F$(86P(;"@I(&1E<F5G:7-T97)S M('1H92!S<&5C:69I960@<VEG;F%L(%\(:5\(9"P@=6XM"B`@("`@8FQO8VMI M;F<@:70@:68@:70@=V%S('5N8FQO8VME9"!B969O<F4@=&AE(&-O<G)E<W!O M;F1I;F<@90AE=@AV4PA390AE=`AT4PA3:0AI9PAG;@AN80AA;`AL*"D*("`@ M("!C86QL+B`@268@=&AE(&-O<G)E<W!O;F1I;F<@7PAU7PAA7PAP('5N:7%U M96QY('!O:6YT<R!T;R!D>6YA;6EC(&UE;6]R>2P@=&AA=`H@("`@(&UE;6]R M>2!S:&]U;&0@8F4@9G)E960@8F5F;W)E(&ET<R!H86YD;&4@:7,@;&]S="P@ M<VEN8V4@869T97(@82!C86QL('1O"B`@("`@90AE=@AV0PA#;`AL90AE80AA M<@AR4PA3:0AI9PAG;@AN80AA;`AL*"DL(&YO(&AA;F1L97,@;VX@=&AI<R!E M=F5N="=S(%\(=5\(85\(<"!W:6QL(&5X:7-T('=I=&AI;B!T:&4*("`@("!E M=F5N="!L:6)R87)Y+@H*4@A210A%5`A450A54@A23@A.(%8(5D$(04P(3%4( M544(15,(4PH@("`@($%L;"!T:&4@9G5N8W1I;VYS('=H;W-E(')E='5R;B!T M>7!E(&ES(&!@7PAI7PAN7PAT)R<@=7-E('1H92!S=&%N9&%R9"!C;VYV96XM M"B`@("`@=&EO;B!O9B!R971U<FYI;F<@>F5R;R`H,"D@=&\@:6YD:6-A=&4@ M<W5C8V5S<RP@;W(@<F5T=7)N:6YG(&!@7P@M7P@Q)R<@86YD"B`@("`@<V5T M=&EN9R!?"&5?"')?"')?"&Y?"&\@=&\@:6YD:6-A=&4@9F%I;'5R92X@($]T M:&5R(&9U;F-T:6]N<R!H879E(')E='5R;B!V86QU97,@87,*("`@("!I;F1I M8V%T960@86)O=F4N"@I%"$52"%)2"%)/"$]2"%)3"%,*("`@("!4:&4@<&]S M<VEB;&4@=F%L=65S(&9O<B!?"&5?"')?"')?"&Y?"&\@=VAE;B!O;F4@;V8@ M=&AE(&!@7PAI7PAN7PAT)R<@9G5N8W1I;VYS(&EN('1H:7,*("`@("!L:6)R M87)Y(')E='5R;G,@8&!?""U?"#$G)R!I;F-L=61E('1H;W-E(&]F('1H92!3 M=&%N9&%R9"!#($QI8G)A<GD@86YD(&%L<V\Z"@H@("`@(%M%24Y604Q=("`@ M("`@(%-O;64@9G5N8W1I;VX@87)G=6UE;G0@:&%S(&%N('5N<F5A<V]N86)L M92!V86QU92X*"B`@("`@6T5)3E9!3%T@("`@("`@5&AE('-P96-I9FEE9"!F M:6QE(&1E<V-R:7!T;W(@:&%S(&%N(&EN=&5G97(@=F%L=64@9W)E871E<@H@ M("`@("`@("`@("`@("`@("`@('1H86X@=&AE(&1E9F%U;'0@7PA&7PA$7PA? M7PA37PA%7PA47PA37PA)7PA:7PA%+"!M96%N:6YG('1H870@=&AE(&%P<&QI M8V$M"B`@("`@("`@("`@("`@("`@("`@=&EO;B=S(&QI;6ET(&ES(&AI9VAE M<B!T:&%N('1H92!L:6)R87)Y)W,N"@H@("`@(%M%3D]%3E1=("`@("`@(%1H M92!S<&5C:69I960@979E;G0@240@9&]E<R!N;W0@97AI<W0N"@H@("`@(%M% M5T]53$1"3$]#2UT@($YO(&5V96YT<R!H879E(&]C8W5R<F5D(&%N9"!T:&4@ M7PA%7PA67PA?7PA07PA/7PA,7PA,(&]P=&EO;B!W87,@<W!E8VDM"B`@("`@ M("`@("`@("`@("`@("`@9FEE9"X*"B`@("`@6T5"041&72`@("`@("`@5&AE M('-P96-I9FEE9"!S:6=N86P@=V%S('5N8FQO8VME9"!O=71S:61E('1H92!L M:6)R87)Y+@H*4PA310A%10A%($$(04P(3%,(4T\(3PH@("`@('-E;&5C="@R M*2P@(&UA;&QO8R@S*2P@(%AT36%I;DQO;W`H,RD*"D@(2$D(25,(4U0(5$\( M3U((4ED(60H@("`@(%1H92!E"&5V"'9E"&5N"&YT"'1L"&QI"&EB"&(@;&EB M<F%R>2!W87,@9&5S:6=N960@8GD@4&%U;"!6:7AI92!W:71H(&5X8V5L;&5N M="!A9'9I8V4*("`@("!F<F]M(&AI<R!F<FEE;F1S(&%N9"!W:71H(&$@=&EP M("=O('1H92!C87`@=&\@=&AE(%@@0V]N<V]R=&EU;2X*"C1T:"!"97)K96QE M>2!$:7-T<FEB=71I;VX@("`@(%-E<'1E;6)E<B`Q-"P@,3DY-2`@("`@("`@ 7("`@("`@("`@("`@("`@("`@("`@-`IE ` end SHAR_EOF $shar_touch -am 0917161295 'eventlib.lpcat' && chmod 0664 'eventlib.lpcat' || echo 'restore of eventlib.lpcat failed' shar_count="`wc -c < 'eventlib.lpcat'`" test 13118 -eq "$shar_count" || echo "eventlib.lpcat: original size 13118, current size $shar_count" fi # ============= eventlib.pscat ============== if test -f 'eventlib.pscat' && test X"$1" != X"-c"; then echo 'x - skipping eventlib.pscat (file already exists)' else echo 'x - extracting eventlib.pscat (text)' sed 's/^X//' << 'SHAR_EOF' > 'eventlib.pscat' && %!PS-Adobe-3.0 %%Creator: groff version 1.09 %%CreationDate: Sun Sep 17 16:12:39 1995 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Courier-Bold %%+ font Courier-Oblique %%+ font Symbol %%+ font Courier %%DocumentSuppliedResources: procset grops 1.09 0 %%Pages: 3 %%PageOrder: Ascend %%Orientation: Portrait %%EndComments %%BeginProlog %%BeginResource: procset grops 1.09 0 /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 72 RES div dup scale LS{ 90 rotate }{ 0 PL translate }ifelse 1 -1 scale }bind def /EP{ level0 restore showpage }bind def /DA{ newpath arcn stroke }bind def /SN{ transform X.25 sub exch .25 sub exch round .25 add exch round .25 add exch itransform }bind def /DL{ SN moveto SN lineto stroke }bind def /DC{ newpath 0 360 arc closepath }bind def /TM matrix def /DE{ TM currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath TM setmatrix }bind def /RC/rcurveto load def /RL/rlineto load def /ST/stroke load def /MT/moveto load def /CL/closepath load def /FL{ currentgray exch setgray fill setgray }bind def /BL/fill load def /LW/setlinewidth load def /RE{ findfont dup maxlength 1 index/FontName known not{1 add}if dict begin { 1 index/FID ne{def}{pop pop}ifelse }forall /Encoding exch def dup/FontName exch def currentdict end definefont pop }bind def /DEFS 0 def /EBEGIN{ moveto DEFS begin }bind def /EEND/end load def /CNT 0 def /level1 0 def /PBEGIN{ /level1 save def translate div 3 1 roll div exch scale neg exch neg exch translate 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit []0 setdash /setstrokeadjust where{ pop false setstrokeadjust }if /setoverprint where{ pop false setoverprint }if newpath /CNT countdictstack def userdict begin /showpage{}def }bind def /PEND{ clear countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Bold %%IncludeResource: font Courier-Bold %%IncludeResource: font Courier-Oblique %%IncludeResource: font Symbol %%IncludeResource: font Courier grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron /scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent /ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen /period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon /semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O /P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex /underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y /z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft /guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl /endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut /dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash /quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen /brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft /logicalnot/minus/registered/macron/degree/plusminus/twosuperior /threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior /ordmasculine/guilsinglright/onequarter/onehalf/threequarters /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash /ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def /Courier@0 ENC0/Courier RE/Courier-Oblique@0 ENC0/Courier-Oblique RE /Courier-Bold@0 ENC0/Courier-Bold RE/Times-Bold@0 ENC0/Times-Bold RE /Times-Roman@0 ENC0/Times-Roman RE %%EndProlog %%Page: 1 1 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF -.834(EVENTLIB \( 3 \))72 48 R(BSD Programmer') 112.632 E 2.5(sM)-.55 G 110.132(anual EVENTLIB)-2.5 F 1.666(\(3\))1.666 G/F1 10/Times-Bold@0 SF -.2(NA)72 108 S(ME).2 E/F2 10/Courier-Bold@0 SF (evOpen)102 120 Q F0(,)A F2(evClose)7.084 E F0(,)A F2(evGetNext)7.084 E F0(,)A F2(evDispatch)7.083 E F0(,)A F2(evMainLoop)7.083 E F0(,)A F2 (evConsTimeV)7.083 E F0(,)A F2(evAddTimeV)7.083 E F0(,)A F2(evSubTimeV) 102 132 Q F0(,)A F2(evCmpTimeV)7.8 E F0(,)A F2(evSetTimer)7.8 E F0(,)A F2(evClearTimer)7.8 E F0(,)A F2(evSelectFD)7.8 E F0(,)A F2(evDeselectFD) 7.8 E F0(,)A F2(evSetSignal)102 144 Q F0(,)A F2(evClearSignal)3.443 E F0 (,)A F2(evTimerFunc)3.443 E F0(,)A F2(evUserFunc)3.443 E F0(,)A F2 (evSignalFunc)3.443 E F0 3.443<ad65>3.443 G -.15(ve)-3.693 G .942 (nt handling).15 F(library)102 156 Q F1(SYNOPSIS)72 180 Q F2 (#include <eventlib.h>)102 192 Q(evOpen)102 210 Q F0(\()A/F3 10 /Courier-Oblique@0 SF(evContext)A/F4 10/Symbol SF(*)6 E F3(ctx)A F0(\);) A F2(evClose)102 228 Q F0(\()A F3(evContext ctx)A F0(\);)A F2(evGetNext) 102 246 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3(evEvent)4.166 E F4 (*)6 E F3(ev)A F0(,)1.666 E F3(int options)4.166 E F0(\);)A F2 (evDispatch)102 264 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3 (evEvent ev)4.166 E F0(\);)A F2(evMainLoop)102 282 Q F0(\()A F3 (evContext ctx)A F0(\);)A F3(struct timeval)102 300 Q F2(evConsTimeV)102 312 Q F0(\()A F3(int sec)A F0(,)1.666 E F3(int usec)4.166 E F0(\);)A F3 (struct timeval)102 330 Q F2(evAddTimeV)102 342 Q F0(\()A F3 (struct timeval addend1)A F0(,)1.666 E F3(struct timeval addend2)4.166 E F0(\);)A F3(struct timeval)102 360 Q F2(evSubTimeV)102 372 Q F0(\()A F3 (struct timeval minuend)A F0(,)1.666 E F3(struct timeval subtrahend) 4.166 E F0(\);)A F3(struct timeval)102 390 Q F2(evCmpTimeV)102 402 Q F0 (\()A F3(struct timeval a)A F0(,)1.666 E F3(struct timeval b)4.166 E F0 (\);)A F2(evSetTimer)102 420 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3(evTimerFunc func)4.166 E F0(,)1.666 E F3(void)4.166 E F4(*)6 E F3 (uap)A F0(,)1.666 E F3(struct timeval due)4.166 E F0(,)1.666 E F3 (struct timeval inter)151.666 432 Q F0(,)1.666 E F3(evTimerID)4.166 E F4 (*)6 E F3(id)A F0(\);)A F2(evClearTimer)102 450 Q F0(\()A F3 (evContext ctx)A F0(,)1.666 E F3(evTimerID id)4.166 E F0(\);)A F2 (evSelectFD)102 468 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3(int fd) 4.166 E F0(,)1.666 E F3(int eventmask)4.166 E F0(,)1.666 E F3 (evFileFunc func)4.166 E F0(,)1.666 E F3(void)4.166 E F4(*)6 E F3(uap)A F0(,)1.666 E F3(evFileID)151.666 480 Q F4(*)6 E F3(id)A F0(\);)A F2 (evDeselectFD)102 498 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3 (evFileID id)4.166 E F0(\);)A F2(evSetSignal)102 516 Q F0(\()A F3 (evContext ctx)A F0(,)1.666 E F3(int sig)4.166 E F0(,)1.666 E F3 (evSignalFunc func)4.166 E F0(,)1.666 E F3(void)4.166 E F4(*)6 E F3(uap) A F0(,)1.666 E F3(evSignalID)151.666 528 Q F4(*)6 E F3(ID)A F0(\);)A F2 (evClearSignal)102 546 Q F0(\()A F3(evContext ctx)A F0(,)1.666 E F3 (evSignalID ID)4.166 E F0(\);)A F3(typedef void)102 564 Q F2(\()102 576 Q F4(*)A F2(evTimerFunc\))A F0(\()A F3(evContext ctx)A F0(,)1.666 E F3 (void)4.166 E F4(*)6 E F3(uap)A F0(,)1.666 E F3(struct timeval due)4.166 E F0(,)1.666 E F3(struct timeval inter)151.666 588 Q F0(\);)A F3 (typedef void)102 606 Q F2(\()102 618 Q F4(*)A F2(evFileFunc\))A F0(\()A F3(evContext ctx)A F0(,)1.666 E F3(void)4.166 E F4(*)6 E F3(uap)A F0(,) 1.666 E F3(int fd)4.166 E F0(,)1.666 E F3(int eventmask)4.166 E F0(\);)A F3(typedef void)102 636 Q F2(\()102 648 Q F4(*)A F2(evSignalFunc\))A F0 (\()A F3(evContext ctx)A F0(,)1.666 E F3(void)4.166 E F4(*)6 E F3(uap)A F0(,)1.666 E F3(int sig)4.166 E F0(\);)A F1(DESCRIPTION)72 672 Q F0 1.121(This library pro)102 684 R 1.122(vides multiple outstanding async\ hronous timers and I/O to a cooperating application.)-.15 F(The)6.122 E 1.167(model is similar to that of the X T)102 696 R 1.167 (oolkit, in that e)-.8 F -.15(ve)-.25 G 1.167(nts are re).15 F 1.167 (gistered with the library and the application)-.15 F .925 (spends most of its time in the)102 708 R F2(evMainLoop)3.425 E F0 -2.407 1.666(\(\) f)D 3.425(unction. If)-1.666 F .925 (an application already has a main loop, it can)3.425 F(4th Berk)72 756 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)-2.5 E 89.595(ution September)-.2 F (14, 1995)2.5 E(1)188.865 E EP %%Page: 2 2 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF -.834(EVENTLIB \( 3 \))72 48 R(BSD Programmer') 112.632 E 2.5(sM)-.55 G 110.132(anual EVENTLIB)-2.5 F 1.666(\(3\))1.666 G 5.011(safely re)102 96 R 5.011(gister e)-.15 F -.15(ve)-.25 G 5.011 (nts with this library as long as it periodically calls the).15 F/F1 10 /Courier-Bold@0 SF(evGetNext)7.511 E F0 1.679 1.666(\(\) a)D(nd)-1.666 E F1(evDispatch)102 108 Q F0 -3.332 1.666(\(\) f)D 2.5(unctions. \(Note) -1.666 F(that)2.5 E F1(evGetNext)2.5 E F0 -3.332 1.666(\(\) h)D (as both polling and blocking modes.\))-1.666 E .846(The function)102 126 R F1(evOpen)3.346 E F0 -2.486 1.666(\(\) c)D .846(reates an e)-1.666 F -.15(ve)-.25 G .846(nt conte).15 F .846 (xt which is needed by all the other functions in this library)-.15 F(.) -.65 E 1.233 (All information used internally by this library is bound to this conte) 102 138 R 1.232(xt, rather than to static storage.)-.15 F(This)6.232 E (mak)102 150 Q .481(es the library `)-.1 F .481(`thread safe,)-.74 F 1.961 -.74('' a)-.7 H .481(nd permits other library functions to use e) X.74 F -.15(ve)-.25 G .482(nts without disrupting the ap-).15 F (plication')102 162 Q 2.5(su)-.55 G(se of e)-2.5 E -.15(ve)-.25 G(nts.) X.15 E 1.611(The function)102 180 R F1(evClose)4.111 E F0 -1.721 1.666 (\(\) d)D(estro)-1.666 E 1.611(ys a conte)-.1 F 1.61 (xt that has been created by)-.15 F F1(evOpen)4.11 E F0 4.11(\(\). All)B 1.61(dynamic memory)4.11 F 1.083(bound to this conte)102 192 R 1.083 (xt will be freed.)-.15 F 1.083(An implicit)6.083 F F1(evTimerClear) 3.583 E F0 -2.249 1.666(\(\) w)D 1.083 (ill be done on all timers set in this)-1.666 F -2.15 -.25(ev e)102 204 T .264(nt conte).25 F 2.764(xt. An)-.15 F(implicit)2.764 E F1 (evDeselectFD)2.764 E F0 -3.068 1.666(\(\) w)D .263 (ill be done on all \214le descriptors selected in this e)-1.666 F -.15 (ve)-.25 G .263(nt con-).15 F(te)102 216 Q(xt.)-.15 E .543(The function) 102 234 R F1(evGetNext)3.043 E F0 -2.788 1.666(\(\) p)D .544 (otentially w)-1.666 F .544(aits for and then retrie)-.1 F -.15(ve)-.25 G 3.044(st).15 G .544(he ne)-3.044 F .544(xt asynchronous e)-.15 F -.15 (ve)-.25 G .544(nt, placing it).15 F .017(in the object of the)102 246 R /F2 10/Courier-Oblique@0 SF(ev)2.517 E F0 .017(pointer ar)2.517 F 2.517 (gument. T)-.18 F .217 -.1(wo m)-.8 H .017(utually e).1 F(xclusi)-.15 E -.15(ve)-.25 G F2(options)2.666 E F0 .016(are a)2.516 F -.25(va)-.2 G (ilable:).25 E F2(EV_POLL)2.516 E F0 2.516(,m)C(ean-)-2.516 E .707 (ing that)102 258 R F1(evGetNext)3.207 E F0 -2.625 1.666(\(\) s)D .708 (hould not block, b)-1.666 F .708(ut rather return `)-.2 F(`)-.74 E F2 (-1)A F0 2.188 -.74('' w)D(ith).74 E F2(errno)3.208 E F0 .708(set to) 3.208 F F2(EWOULDBLOCK)3.208 E F0 .708(if no)3.208 F -2.15 -.25(ev e)102 270 T .157(nts ha).25 F .457 -.15(ve o)-.2 H .157(ccurred; and).15 F F2 (EV_WAIT)2.657 E F0 2.657(,w)C .157(hich tells)-2.657 F F1(evGetNext) 2.657 E F0 -3.175 1.666(\(\) t)D 2.657(ob)-1.666 G .157(lock in)-2.657 F /F3 10/Courier@0 SF(select)2.657 E F0 .157(\(2\) until the ne)B .156 (xt e)-.15 F -.15(ve)-.25 G(nt).15 E(occurs.)102 282 Q .05(The function) 102 300 R F1(evDispatch)2.55 E F0 -3.282 1.666(\(\) d)D .05 (ispatches an e)-1.666 F -.15(ve)-.25 G .05(nt retrie).15 F -.15(ve)-.25 G 2.55(db).15 G(y)-2.55 E F1(evGetNext)2.55 E F0 2.551(\(\). This)B .051 (usually in)2.551 F -.2(vo)-.4 G(lv).2 E .051(es calling)-.15 F .084 (the function that w)102 312 R .084(as associated with the e)-.1 F -.15 (ve)-.25 G .083(nt when the e).15 F -.15(ve)-.25 G .083(nt w).15 F .083 (as re)-.1 F .083(gistered with)-.15 F F1(evSetTimer)2.583 E F0 -3.249 1.666(\(\) o)D(r)-1.666 E F1(evS-)2.583 E(electFD)102 324 Q F0 3.09 (\(\). All)B -2.15 -.25(ev e)3.09 H .59(nts retrie).25 F -.15(ve)-.25 G 3.09(db).15 G(y)-3.09 E F1(evGetNext)3.09 E F0 -2.742 1.666(\(\) m)D X.591(ust be gi)-1.666 F -.15(ve)-.25 G 3.091(no).15 G -.15(ve)-3.241 G 3.091(rt).15 G(o)-3.091 E F1(evDispatch)3.091 E F0 -2.741 1.666(\(\) a)D 3.091(ts)-1.666 G .591(ome point,)-3.091 F (since there is some dynamic memory associated with each e)102 336 Q -.15(ve)-.25 G(nt.).15 E(The function)102 354 Q F1(evMainLoop)2.5 E F0 -3.332 1.666(\(\) i)D 2.5(sj)-1.666 G(ust:)-2.5 E F3 (while \(\(x = evGetNext\(opaqueCtx, &event, EV_WAIT\)\) == 0\))132 372 Q(if \(\(x = evDispatch\(opaqueCtx, event\)\) < 0\))177 384 Q(break;)222 396 Q(return \(x\);)132 408 Q F0 1.335(In other w)102 426 R 1.335 (ords, get e)-.1 F -.15(ve)-.25 G 1.334 (nts and dispatch them until an error occurs.).15 F 1.334 (One such error w)6.334 F 1.334(ould be that all the)-.1 F -2.15 -.25 (ev e)102 438 T 3.13(nts under this conte).25 F 3.13(xt become unre)-.15 F 3.131(gistered; in that e)-.15 F -.15(ve)-.25 G 3.131 (nt, there will be nothing to w).15 F 3.131(ait for and)-.1 F F1 (evGetNext)102 450 Q F0 -3.332 1.666(\(\) b)D (ecomes an unde\214ned operation.)-1.666 E .284(The function)102 468 R F1(evConsTimeV)2.784 E F0 -3.048 1.666(\(\) i)D 2.784(sac)-1.666 G .283 (onstructor for `)-2.784 F(`)-.74 E F2 .283(struct timeval)B F0 1.763 -.74('' w)D .283(hich allo).74 F .283(ws these structures to)-.25 F .195 (be created and then passed as ar)102 480 R .196 (guments to other functions without the use of temporary v)-.18 F 2.696 (ariables. \(If)-.25 F 2.696(Ch)2.696 G(ad)-2.696 E (inline constructors, there w)102 492 Q (ould be no need for this function.\))-.1 E .185(The function)102 510 R F1(evAddTimeV)2.685 E F0 -3.147 1.666(\(\) a)D .185(dds tw)-1.666 F 2.685(o`)-.1 G(`)-3.425 E F2 .185(struct timeval)B F0 1.665 -.74('' v)D X.184(alues and returns the result as a `).49 F(`)-.74 E F2(struct)A (timeval)102 522 Q F0 -.74('')C(.).74 E .06(The function)102 540 R F1 (evSubTimeV)2.56 E F0 -3.272 1.666(\(\) s)D .06(ubtracts its second `) -1.666 F(`)-.74 E F2 .06(struct timeval)B F0 1.54 -.74('' a)D -.18(rg) X.74 G .061(ument from its \214rst `).18 F(`)-.74 E F2(struct)A(timeval) 102 552 Q F0 1.48 -.74('' a)D -.18(rg).74 G (ument and returns the result as a `).18 E(`)-.74 E F2(struct timeval)A F0 -.74('')C(.).74 E .985(The function)102 570 R F1(evCmpTimeV)3.485 E F0 -2.347 1.666(\(\) c)D .985(ompares its tw)-1.666 F 3.485(o`)-.1 G(`) -4.225 E F2 .984(struct timeval)B F0 2.464 -.74('' a)D -.18(rg).74 G X.984(uments and returns an `).18 F(`)-.74 E F2(int)A F0 -.74('')C .684 (that is less than zero if the \214rst ar)102 582 R .684(gument speci\ \214es an earlier time than the second, or more than zero if the)-.18 F X.049(\214rst ar)102 594 R .049(gument speci\214es a later time than the\ X second, or equal to zero if both ar)-.18 F .049 (guments specify the same time.)-.18 F .433(The function)102 612 R F1 (evSetTimer)2.933 E F0 -2.899 1.666(\(\) r)D -.15(eg)-1.666 G .433 (isters a timer e).15 F -.15(ve)-.25 G .433(nt, which will be deli).15 F -.15(ve)-.25 G .433(red as a function call to the func-).15 F .75 (tion speci\214ed by the)102 624 R F2(func)3.25 E F0(ar)3.25 E 3.25 (gument. The)-.18 F -2.15 -.25(ev e)3.25 H .75(nt will be deli).25 F -.15(ve)-.25 G .749(red at time).15 F F2(due)3.249 E F0 3.249(,a)C .749 (nd then if time)-3.249 F F2(inter)3.249 E F0(is)3.249 E 1.004 (not equal to `)102 636 R(`)-.74 E F2(evConsTimeV\(0,0\))A F0 -.74('')C 3.504(,s).74 G 1.004(ubsequently at interv)-3.504 F 1.004 (als equal to time)-.25 F F2(inter)3.504 E F0 3.505(.A)C 3.505(sas) -3.505 G 1.005(pecial case,)-3.505 F 1.257(specifying a)102 648 R F2 (due)3.757 E F0(ar)3.757 E 1.257(gument equal to `)-.18 F(`)-.74 E F2 (evConsTimeV\(0,0\))A F0 2.737 -.74('' m)D 1.257(eans `).74 F 1.256 (`due immediately)-.74 F -.7(.')-.65 G 6.256('T)-.04 G(he)-6.256 E F2 (id)3.756 E F0(ar)3.756 E(gu-)-.18 E .369(ment, if speci\214ed as a v) 102 660 R .37(alue other than)-.25 F F2(NULL)2.87 E F0 2.87(,w)C .37 (ill be used to store the resulting `)-2.87 F(`timer)-.74 E/F4 9 /Times-Roman@0 SF(ID)2.87 E F0 -.7(,')C 2.87('u)-.04 G .37 (seful as an ar)-2.87 F(-)-.2 E 1.142(gument to)102 672 R F1 (evClearTimer)3.642 E F0 3.642(\(\). Note)B 1.142(that in a `)3.642 F 1.142(`one shot')-.74 F 3.642('t)-.74 G 1.142(imer \(which has an)-3.642 F F2(inter)3.642 E F0(ar)3.642 E 1.141(gument equal to)-.18 F -.74(``) 102 684 S F2(evConsTimeV\(0,0\)).74 E F0 1.647 -.74('' \) t)D .167 (he user function).74 F F2(func)2.668 E F0 .168(should deallocate an) 2.668 F 2.668(yd)-.15 G .168(ynamic memory that is uniquely)-2.668 F X.543(bound to the)102 696 R F2(uap)3.043 E F0 3.043(,s)C .543 (ince no handles to this memory will e)-3.043 F .543(xist within the e) -.15 F -.15(ve)-.25 G .543(nt library after a one shot timer).15 F (has been deli)102 708 Q -.15(ve)-.25 G(red.).15 E(4th Berk)72 756 Q (ele)-.1 E 2.5(yD)-.15 G(istrib)-2.5 E 89.595(ution September)-.2 F (14, 1995)2.5 E(2)188.865 E EP %%Page: 3 3 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF -.834(EVENTLIB \( 3 \))72 48 R(BSD Programmer') 112.632 E 2.5(sM)-.55 G 110.132(anual EVENTLIB)-2.5 F 1.666(\(3\))1.666 G .256(The function)102 96 R/F1 10/Courier-Bold@0 SF(evClearTimer)2.756 E F0 -3.076 1.666(\(\) w)D .256(ill unre)-1.666 F .256 (gister the timer e)-.15 F -.15(ve)-.25 G .256(nt speci\214ed by).15 F /F2 10/Courier-Oblique@0 SF(id)2.757 E F0 2.757(.N)C .257 (ote that if the)-2.757 F F2(uap)2.757 E F0(speci-)2.757 E .034 (\214ed in the corresponding)102 108 R F1(evSetTimer)2.534 E F0 -3.298 1.666(\(\) c)D .034(all is uniquely bound to an)-1.666 F 2.533(yd)-.15 G X.033(ynamic memory)-2.533 F 2.533(,t)-.65 G .033(hen that dynamic)-2.533 F .631(memory should be freed by the caller before the handle is lost.) 102 120 R .631(After a call to)5.631 F F1(evClearTimer)3.131 E F0 .632 (\(\), no han-)B(dles to this)102 132 Q F2(uap)2.5 E F0(will e)2.5 E (xist within the e)-.15 E -.15(ve)-.25 G(nt library).15 E(.)-.65 E 1.173 (The function)102 150 R F1(evSelectFD)3.673 E F0 -2.159 1.666(\(\) r)D -.15(eg)-1.666 G 1.173(isters a \214le I/O e).15 F -.15(ve)-.25 G 1.173 (nt for the \214le descriptor speci\214ed by).15 F F2(fd)3.672 E F0 3.672(.B)C 1.172(its in the)-3.672 F F2(eventmask)102 162 Q F0(ar)3.372 E .872(gument are named)-.18 F F2(EV_READ)3.373 E F0(,)A F2(EV_WRITE) 3.373 E F0 3.373(,a)C(nd)-3.373 E F2(EV_EXCEPT)3.373 E F0 .873 (\(corresponding to the `)3.373 F(`read-)-.74 E(able,)102 174 Q 1.626 -.74('' ``)-.7 H(writable,).74 E 1.626 -.74('' a)-.7 H .146(nd `).74 F (`e)-.74 E(xceptional')-.15 E 2.646('m)-.74 G .146(asks of the system') -2.646 F(s)-.55 E/F3 10/Courier@0 SF(select)2.646 E F0 .146(\(2\) call.) B .145(At least one of these bits must)5.146 F .652(be speci\214ed.)102 186 R .652(If the)5.652 F F2(id)3.152 E F0(ar)3.152 E .652 (gument is not equal to)-.18 F F2(NULL)3.152 E F0 3.152(,i)C 3.152(tw) -3.152 G .652(ill be used to store a unique `)-3.152 F .652(`\214le e) -.74 F -.15(ve)-.25 G(nt).15 E/F4 9/Times-Roman@0 SF(ID)3.152 E F0 2.133 -.74('' f)D(or).74 E(this e)102 198 Q -.15(ve)-.25 G (nt, which is useful in subsequent calls to).15 E F1(evDelectFD)2.5 E F0 (\(\).)A 1.204(The function)102 216 R F1(evDeselectFD)3.704 E F0 -2.128 1.666(\(\) u)D(nre)-1.666 E 1.204(gisters the `)-.15 F 1.204(`\214le e) -.74 F -.15(ve)-.25 G(nt').15 E 3.704('s)-.74 G 1.204(peci\214ed by the) -3.704 F F2(id)3.704 E F0(ar)3.704 E 3.704(gument. If)-.18 F 1.203 (the corre-)3.703 F(sponding)102 228 Q F2(uap)3.514 E F0 1.014 (uniquely points to dynamic memory)3.514 F 3.514(,t)-.65 G 1.015 (hat memory should be freed before its handle is lost,)-3.514 F (since after a call to)102 240 Q F1(evDeselectFD)2.5 E F0 (\(\), no handles to this e)A -.15(ve)-.25 G(nt').15 E(s)-.55 E F2(uap) 2.5 E F0(will remain within the e)2.5 E -.15(ve)-.25 G(nt library).15 E (.)-.65 E F1(evSetSignal)102 258 Q F0 -2.835 1.666(\(\) b)D .497 (locks a signal from deli)-1.666 F -.15(ve)-.25 G .496(ry and re).15 F X.496(gisters the)-.15 F F2(func)2.996 E F0 .496(to be called when)2.996 F F1(evDispatch)2.996 E F0 1.666(\(\))C(disco)102 270 Q -.15(ve)-.15 G X.565(rs that this signal is pending.).15 F(The)5.566 E F2(id)3.066 E F0 (ar)3.066 E .566(gument, if not)-.18 F F2(NULL)3.066 E F0 3.066(,w)C X.566(ill be used to store a unique `)-3.066 F(`signal)-.74 E F4(ID)102 282 Q F0 1.48 -.74('' f)D(or this e).74 E -.15(ve)-.25 G (nt, which is useful in subsequent calls to).15 E F1(evClearSignal)2.5 E F0 1.666(\(\))C .461(The function)102 300 R F1(evClearSignal)2.961 E F0 -2.871 1.666(\(\) d)D(ere)-1.666 E .461(gisters the speci\214ed signal) -.15 F F2(id)2.961 E F0 2.961(,u)C .461(nblocking it if it w)-2.961 F X.461(as unblock)-.1 F .461(ed be-)-.1 F .162(fore the corresponding)102 312 R F1(evSetSignal)2.662 E F0 -3.17 1.666(\(\) c)D 2.662(all. If) -1.666 F .163(the corresponding)2.663 F F2(uap)2.663 E F0 .163 (uniquely points to dynamic memo-)2.663 F(ry)102 324 Q 3.173(,t)-.65 G X.673(hat memory should be freed before its handle is lost, since after \ a call to)-3.173 F F1(evClearSignal)3.172 E F0 .672(\(\), no han-)B (dles on this e)102 336 Q -.15(ve)-.25 G(nt').15 E(s)-.55 E F2(uap)2.5 E F0(will e)2.5 E(xist within the e)-.15 E -.15(ve)-.25 G(nt library).15 E (.)-.65 E/F5 10/Times-Bold@0 SF 1.666(RETURN V)72 360 R(ALUES)-1.35 E F0 X.794(All the functions whose return type is `)102 372 R(`)-.74 E F2(int) A F0 2.274 -.74('' u)D .794(se the standard con).74 F -.15(ve)-.4 G .794 (ntion of returning zero \(0\) to indicate).15 F .014 (success, or returning `)102 384 R(`)-.74 E F2(-1)A F0 1.493 -.74('' a)D X.013(nd setting).74 F F2(errno)2.513 E F0 .013(to indicate f)2.513 F 2.513(ailure. Other)-.1 F .013(functions ha)2.513 F .313 -.15(ve r)-.2 H X.013(eturn v).15 F .013(alues as indi-)-.25 F(cated abo)102 396 Q -.15 (ve)-.15 G(.).15 E F5(ERR)72 420 Q(ORS)-.3 E F0 .32(The possible v)102 432 R .32(alues for)-.25 F F2(errno)2.82 E F0 .32(when one of the `)2.82 F(`)-.74 E F2(int)A F0 1.801 -.74('' f)D .321 (unctions in this library returns `).74 F(`)-.74 E F2(-1)A F0 1.801 -.74 ('' i)D .321(nclude those).74 F(of the Standard C Library and also:)102 444 Q([)102.833 462 Q F3(EINVAL).833 E F0 37.841(]S).833 G (ome function ar)-37.841 E(gument has an unreasonable v)-.18 E(alue.) -.25 E([)102.833 480 Q F3(EINVAL).833 E F0 37.841(]T).833 G .164 (he speci\214ed \214le descriptor has an inte)-37.841 F .163(ger v)-.15 F .163(alue greater than the def)-.25 F(ault)-.1 E F2(FD_SETSIZE)2.663 E F0(,)A(meaning that the application')185 492 Q 2.5(sl)-.55 G (imit is higher than the library')-2.5 E(s.)-.55 E([)102.833 510 Q F3 (ENOENT).833 E F0 37.841(]T).833 G(he speci\214ed e)-37.841 E -.15(ve) -.25 G(nt).15 E F4(ID)2.5 E F0(does not e)2.5 E(xist.)-.15 E([)102.833 528 Q F3(EWOULDBLOCK).833 E F0 7.841(]N).833 G 2.5(oe)-7.841 G -.15(ve) -2.75 G(nts ha).15 E .3 -.15(ve o)-.2 H(ccurred and the).15 E F2 (EV_POLL)2.5 E F0(option w)2.5 E(as speci\214ed.)-.1 E([)102.833 546 Q F3(EBADF).833 E F0 43.841(]T).833 G(he speci\214ed signal w)-43.841 E (as unblock)-.1 E(ed outside the library)-.1 E(.)-.65 E F5 1.666 (SEE ALSO)72 570 R F3(select)102 582 Q F0(\(2\),)A F3(malloc)5 E F0 (\(3\),)A F3(XtMainLoop)5 E F0(\(3\))A F5(HIST)72 606 Q(OR)-.18 E(Y)-.35 E F0(The)102 618 Q F1(eventlib)2.96 E F0 .46(library w)2.96 F .46 (as designed by P)-.1 F .46(aul V)-.15 F .46(ixie with e)-.6 F .46 (xcellent advice from his friends and with a tip 'o)-.15 F (the cap to the X Consortium.)102 630 Q(4th Berk)72 750 Q(ele)-.1 E 2.5 (yD)-.15 G(istrib)-2.5 E 89.595(ution September)-.2 F(14, 1995)2.5 E(3) 188.865 E EP %%Trailer end %%EOF SHAR_EOF $shar_touch -am 0917161295 'eventlib.pscat' && chmod 0664 'eventlib.pscat' || echo 'restore of eventlib.pscat failed' shar_count="`wc -c < 'eventlib.pscat'`" test 25096 -eq "$shar_count" || echo "eventlib.pscat: original size 25096, current size $shar_count" fi # ============= eventlib.h ============== if test -f 'eventlib.h' && test X"$1" != X"-c"; then echo 'x - skipping eventlib.h (file already exists)' else echo 'x - extracting eventlib.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'eventlib.h' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* eventlib.h - exported interfaces for eventlib X * vix 09sep95 [initial] X * X * $Id: eventlib.h,v 1.2 1995/09/17 23:12:25 vixie Exp $ X */ X #ifndef _EVENTLIB_H #define _EVENTLIB_H X #include <sys/time.h> X #ifndef __P # ifdef __STDC__ # define __P(x) x # else # define __P(x) # endif #endif X /* In the absence of branded types... */ typedef struct { void *opaque; } evTimerID; typedef struct { void *opaque; } evFileID; typedef struct { void *opaque; } evSignalID; typedef struct { void *opaque; } evContext; typedef struct { void *opaque; } evEvent; X typedef void (*evTimerFunc)__P((evContext ctx, void *uap, X struct timeval due, struct timeval inter)); typedef void (*evFileFunc)__P((evContext ctx, void *uap, int fd, int evmask)); typedef void (*evSignalFunc)__P((evContext ctx, void *uap, int sig)); X #define EV_POLL 1 #define EV_WAIT 2 X #define EV_READ 1 #define EV_WRITE 2 #define EV_EXCEPT 4 X /* eventlib.c */ #define evOpen __evOpen #define evClose __evClose #define evGetNext __evGetNext #define evDispatch __evDispatch #define evMainLoop __evMainLoop X int evOpen __P((evContext *ctx)); int evClose __P((evContext ctx)); int evGetNext __P((evContext ctx, evEvent *ev, int options)); int evDispatch __P((evContext ctx, evEvent ev)); int evMainLoop __P((evContext ctx)); X /* timers.c */ #define evConsTimeV __evConsTimeV #define evAddTimeV __evAddTimeV #define evSubTimeV __evSubTimeV #define evCmpTimeV __evCmpTimeV #define evSetTimer __evSetTimer #define evClearTimer __evClearTimer X struct timeval evConsTimeV __P((int sec, int usec)); struct timeval evAddTimeV __P((struct timeval add1, struct timeval add2)); struct timeval evSubTimeV __P((struct timeval minu, struct timeval subtra)); int evCmpTimeV __P((struct timeval a, struct timeval b)); int evSetTimer __P((evContext ctx, evTimerFunc func, void *uap, X struct timeval due, struct timeval inter, X evTimerID *id)); int evClearTimer __P((evContext ctx, evTimerID id)); X /* files.c */ #define evSelectFD __evSelectFD #define evDeselectFD __evDeselectFD X int evSelectFD __P((evContext ctx, int fd, int eventmask, X evFileFunc func, void *uap, evFileID *id)); int evDeselectFD __P((evContext ctx, evFileID id)); X /* signals.c */ #define evSetSignal __evSetSignal #define evClearSignal __evClearSignal X int evSetSignal __P((evContext ctx, int sig, evSignalFunc func, void *uap, X evSignalID *ID)); int evClearSignal __P((evContext ctx, evSignalID ID)); X #endif /*_EVENTLIB_H*/ SHAR_EOF $shar_touch -am 0917161295 'eventlib.h' && chmod 0444 'eventlib.h' || echo 'restore of eventlib.h failed' shar_count="`wc -c < 'eventlib.h'`" test 3291 -eq "$shar_count" || echo "eventlib.h: original size 3291, current size $shar_count" fi # ============= eventlib_p.h ============== if test -f 'eventlib_p.h' && test X"$1" != X"-c"; then echo 'x - skipping eventlib_p.h (file already exists)' else echo 'x - extracting eventlib_p.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'eventlib_p.h' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* eventlib_p.h - private interfaces for eventlib X * vix 09sep95 [initial] X * X * $Id: eventlib_p.h,v 1.1 1995/09/17 05:30:26 vixie Exp $ X */ X #ifndef _EVENTLIB_P_H #define _EVENTLIB_P_H X #include <sys/param.h> #include <sys/types.h> X #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> X #include "eventlib_p.h" X #ifdef DEBUG extern int evDebugLev; #define DPRINTF(l,a) if (l <= evDebugLev) printf a #else #define DPRINTF(l,a) #endif X #define ERR(e) for (;;) { errno = (e); return (-1); } #define OK(x) if ((x) < 0) ERR(errno) else NULL; #define NEW(p) if (((p) = malloc(sizeof *(p))) != NULL) \ X memset((p), 0xF5, sizeof *(p)); #define OKNEW(p) if (!((p) = malloc(sizeof *(p)))) { \ X errno = ENOMEM; \ X return (-1); \ X } else \ X memset((p), 0xF5, sizeof *(p)); X typedef struct evTimer { X evTimerFunc func; X void *uap; X struct timeval due, inter; X struct evTimer *next; } evTimer; X typedef struct evFile { X evFileFunc func; X void *uap; X int fd; X int eventmask; X struct evFile *next; } evFile; X typedef struct evSignal { X evSignalFunc func; X void *uap; X int sig; X struct sigaction oact; X struct evSignal *next; } evSignal; X typedef struct { X /* Timers. */ X evTimer *timers; X /* Files. */ X evFile *files, *fdNext; X fd_set rdLast, rdNext; X fd_set wrLast, wrNext; X fd_set exLast, exNext; X fd_set nonblockBefore; X int fdMax, fdCount; X /* Signals. */ X evSignal *signals; X sigset_t blockedBefore; } evContext_p; X typedef struct { X enum {Timer, File, Signal} type; X union { X struct { X evTimer *this; X } timer; X struct { X evFile *this; X int eventmask; X } file; X struct { X evSignal *this; X } signal; X } u; } evEvent_p; X /* timers.c */ #define evRelinkTimers __evRelinkTimers int evRelinkTimers(evContext_p *ctx, evTimer *del, evTimer *add); X #endif /*_EVENTLIB_P_H*/ SHAR_EOF $shar_touch -am 0916223095 'eventlib_p.h' && chmod 0444 'eventlib_p.h' || echo 'restore of eventlib_p.h failed' shar_count="`wc -c < 'eventlib_p.h'`" test 2694 -eq "$shar_count" || echo "eventlib_p.h: original size 2694, current size $shar_count" fi # ============= eventlib.c ============== if test -f 'eventlib.c' && test X"$1" != X"-c"; then echo 'x - skipping eventlib.c (file already exists)' else echo 'x - extracting eventlib.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'eventlib.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* eventlib.c - implement clue for the eventlib X * vix 09sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: eventlib.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include <assert.h> X #include "eventlib.h" #include "eventlib_p.h" X static evEvent_p *GetSignal(evContext_p *ctx); static const struct timeval NoTime = {0, 0}; static const struct timeval ShortTime = {1, 500000}; X int evOpen(evContext *opaqueCtx) { X evContext_p *ctx; X X OKNEW(ctx); X X /* Timers. */ X ctx->timers = NULL; X X /* Files. */ X ctx->files = NULL; X FD_ZERO(&ctx->rdNext); X FD_ZERO(&ctx->wrNext); X FD_ZERO(&ctx->exNext); X FD_ZERO(&ctx->nonblockBefore); X ctx->fdMax = -1; X ctx->fdNext = NULL; X ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */ X X /* Signals. */ X ctx->signals = NULL; X sigemptyset(&ctx->blockedBefore); X X opaqueCtx->opaque = ctx; X return (0); } X int evClose(evContext opaqueCtx) { X evContext_p *ctx = opaqueCtx.opaque; X int revs = 424242; /* Doug Adams. */ X X /* Timers. */ X while (revs-- > 0 && ctx->timers != NULL) { X evTimerID timer; X X timer.opaque = ctx->timers; X (void) evClearTimer(opaqueCtx, timer); X } X X /* Files. */ X while (revs-- > 0 && ctx->files != NULL) { X evFileID file; X X file.opaque = ctx->files; X (void) evDeselectFD(opaqueCtx, file); X } X X /* Signals. */ X while (revs-- > 0 && ctx->signals != NULL) { X evSignalID sig; X X sig.opaque = ctx->signals; X (void) evClearSignal(opaqueCtx, sig); X } X X free(ctx); X return(0); } X int evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { X evContext_p *ctx = opaqueCtx.opaque; X struct timeval now, nextTime; X evTimer *nextTimer; X evEvent_p *new; X int x, timerPast; X X /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ X x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); X if (x != 1) X ERR(EINVAL); X X /* Give signals top priority. */ X if ((new = GetSignal(ctx)) != NULL) { X opaqueEv->opaque = new; X return (0); X } X X /* Get the time of day. We'll do this again after select() blocks. */ X OK(gettimeofday(&now, NULL)); X X /* Get the status and content of the next timer. */ X if ((nextTimer = ctx->timers) != NULL) { X nextTime = nextTimer->due; X timerPast = (evCmpTimeV(nextTime, now) <= 0); X } X X again: X DPRINTF(9, ("evGetNext: again: fdCount %d\n", ctx->fdCount)); X if (!ctx->fdCount) { X enum { JustPoll, ShortPoll, Block, Timer } m; X struct timeval t, *tp; X X /* Are there any events at all? */ X if ((options & EV_WAIT) && !nextTimer && ctx->fdMax == -1 && X !ctx->signals) X ERR(ENOENT); X X /* Figure out what select()'s timeout parameter should be. */ X if (options & EV_POLL) { X m = JustPoll; X t = NoTime; X tp = &t; X } else if (! nextTimer) { X if (ctx->signals) { X m = ShortPoll; X t = ShortTime; X tp = &t; X } else { X m = Block; X /* ``t'' unused. */ X tp = NULL; X } X } else if (timerPast) { X m = JustPoll; X t = NoTime; X tp = &t; X } else { X m = Timer; X /* ``t'' filled in later. */ X tp = &t; X } X X do { X /* We do these here due to possible EINTR. */ X ctx->rdLast = ctx->rdNext; X ctx->wrLast = ctx->wrNext; X ctx->exLast = ctx->exNext; X X /* We do this here due to possible EINTR. */ X if (m == Timer) { X assert(tp == &t); X t = evSubTimeV(nextTime, now); X /* Do we need to ensure periodic sig polls? */ X if (ctx->signals != NULL && X evCmpTimeV(t, ShortTime) > 0) X t = ShortTime; X } X X DPRINTF(4, ("select(%d, %#x, %#x, %#x, %d.%06d)\n", X ctx->fdMax+1, X &ctx->rdLast, &ctx->wrLast, &ctx->exLast, X tp ? tp->tv_sec : -1, X tp ? tp->tv_usec : -1)); X X x = select(ctx->fdMax+1, X &ctx->rdLast, &ctx->wrLast, &ctx->exLast, X tp); X X /* Did any signals come in during select()? */ X if ((new = GetSignal(ctx)) != NULL) { X opaqueEv->opaque = new; X return (0); X } X X /* Anything but a poll can change the time. */ X if (m != JustPoll) X OK(gettimeofday(&now, NULL)); X X /* Select() likes to finish about 10ms early. */ X if (x == 0 && m == Timer && X evCmpTimeV(now, nextTime) < 0) { X /* Simulate EINTR, go back, select() again. */ X x = -1; X errno = EINTR; X } X X /* Are we polling for a signal? */ X if (x == 0 && m == ShortPoll && ctx->signals) { X /* Simulate EINTR, go back, select() again. */ X x = -1; X errno = EINTR; X } X } while (x < 0 && errno == EINTR); X if (x < 0) X ERR(errno); X if (x == 0 && !timerPast && (options & EV_POLL)) X ERR(EWOULDBLOCK); X ctx->fdCount = x; X } X assert(nextTimer || ctx->fdCount); X X /* Timers go first since we'd like them to be accurate. */ X if (nextTimer && !timerPast) { X /* Has anything happened since we blocked? */ X timerPast = (evCmpTimeV(nextTime, now) <= 0); X } X if (nextTimer && timerPast) { X OKNEW(new); X new->type = Timer; X new->u.timer.this = nextTimer; X opaqueEv->opaque = new; X return (0); X } X X /* No timers, so there must be a ready file descriptor. */ X while (ctx->fdCount) { X register evFile *fid; X register int fd, eventmask; X X if (!ctx->fdNext) X ctx->fdNext = ctx->files; X fid = ctx->fdNext; X ctx->fdNext = fid->next; X X fd = fid->fd; X eventmask = 0; X if (FD_ISSET(fd, &ctx->rdLast)) X eventmask |= EV_READ; X if (FD_ISSET(fd, &ctx->wrLast)) X eventmask |= EV_WRITE; X if (FD_ISSET(fd, &ctx->exLast)) X eventmask |= EV_EXCEPT; X if (eventmask != 0) { X ctx->fdCount--; X OKNEW(new); X new->type = File; X new->u.file.this = fid; X new->u.file.eventmask = eventmask; X opaqueEv->opaque = new; X return (0); X } X } X X /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ X goto again; } X static evEvent_p * GetSignal(evContext_p *ctx) { X evEvent_p *new; X evSignal *cur; X sigset_t set; X X if (sigpending(&set) < 0) X return (NULL); X for (cur = ctx->signals; cur; cur = cur->next) X if (sigismember(&set, cur->sig)) X break; X if (!cur) X return (NULL); X X /* X * Briefly unblock and then reblock the signal. According to X * IEEE Std1003.1-1988 ("POSIX") 3.3.5.1, at least one signal X * will be delivered before a return from an unblocking call X * to setprocmask(). Since we're only unblocking one signal, X * and it's one that sigpending() says is pending (see above), X * this ought to clear the signal (and the sigpending().) We X * immediately turn around and reblock this signal afterward. X */ X sigemptyset(&set); X sigaddset(&set, cur->sig); X (void) sigprocmask(SIG_UNBLOCK, &set, NULL); X (void) sigpending(&set); X assert(sigismember(&set, cur->sig) <= 0); X sigemptyset(&set); X sigaddset(&set, cur->sig); X (void) sigprocmask(SIG_BLOCK, &set, NULL); X X NEW(new); X if (!new) { X /* Note: we're silently losing a signal in this case. */ X errno = ENOMEM; X return (NULL); X } X new->type = Signal; X new->u.signal.this = cur; X return (new); } X int evDispatch(evContext opaqueCtx, evEvent opaqueEv) { X evContext_p *ctx = opaqueCtx.opaque; X evEvent_p *ev = opaqueEv.opaque; X X switch (ev->type) { X case Timer: { X evTimer *this = ev->u.timer.this; X X (this->func)(opaqueCtx, this->uap, this->due, this->inter); X if (this->inter.tv_sec == 0 && this->inter.tv_usec == 0) { X evTimerID opaque; X X opaque.opaque = this; X (void) evClearTimer(opaqueCtx, opaque); X } else { X this->due = evAddTimeV(this->due, this->inter); X /* XXX a signal that called evSetTimer() would hurt. */ X evRelinkTimers(ctx, this, this); X } X break; X } X case File: { X evFile *this = ev->u.file.this; X int eventmask = ev->u.file.eventmask; X X (this->func)(opaqueCtx, this->uap, this->fd, eventmask); X break; X } X case Signal: { X evSignal *this = ev->u.signal.this; X X (this->func)(opaqueCtx, this->uap, this->sig); X break; X } X default: { X abort(); X } X } X return (0); } X int evMainLoop(evContext opaqueCtx) { X evContext_p *ctx = opaqueCtx.opaque; X evEvent event; X int x; X X while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) X if ((x = evDispatch(opaqueCtx, event)) < 0) X break; X return (x); } X SHAR_EOF $shar_touch -am 0917161295 'eventlib.c' && chmod 0444 'eventlib.c' || echo 'restore of eventlib.c failed' shar_count="`wc -c < 'eventlib.c'`" test 8744 -eq "$shar_count" || echo "eventlib.c: original size 8744, current size $shar_count" fi # ============= timers.c ============== if test -f 'timers.c' && test X"$1" != X"-c"; then echo 'x - skipping timers.c (file already exists)' else echo 'x - extracting timers.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'timers.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* timers.c - implement timers for the eventlib X * vix 09sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: timers.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include "eventlib.h" #include "eventlib_p.h" X static void LinkTimer(evContext_p *ctx, evTimer *old, evTimer *add); static void UnlinkTimer(evContext_p *ctx, evTimer *old, evTimer *cur); X #ifdef DEBUG static void PrintTimers(const evContext_p *ctx, char *label); #else #define PrintTimers(ctx,label) #endif X struct timeval evConsTimeV(int sec, int usec) { X struct timeval x; X X x.tv_sec = sec; X x.tv_usec = usec; X return (x); } X struct timeval evAddTimeV(struct timeval addend1, struct timeval addend2) { X struct timeval x; X X x.tv_sec = addend1.tv_sec + addend2.tv_sec; X x.tv_usec = addend1.tv_usec + addend2.tv_usec; X if (x.tv_usec >= 1000000) { X x.tv_sec++; X x.tv_usec -= 1000000; X } X return (x); } X struct timeval evSubTimeV(struct timeval minuend, struct timeval subtrahend) { X struct timeval x; X X x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; X if (minuend.tv_usec >= subtrahend.tv_usec) { X x.tv_usec = minuend.tv_usec - subtrahend.tv_usec; X } else { X x.tv_usec = 1000000 - subtrahend.tv_usec + minuend.tv_usec; X x.tv_sec--; X } X return (x); } X int evCmpTimeV(struct timeval a, struct timeval b) { X int x = a.tv_sec - b.tv_sec; X X if (! x) X x = a.tv_usec - b.tv_usec; X DPRINTF(99, ("evCmpTimeV(%d.%06d, %d.%06d) -> %d\n", X a.tv_sec, a.tv_usec, b.tv_sec, b.tv_usec, x)); X return (x); } X int evSetTimer(evContext opaqueCtx, X evTimerFunc func, X void *uap, X struct timeval due, X struct timeval inter, X evTimerID *opaqueID ) { X evContext_p *ctx = opaqueCtx.opaque; X evTimer *id; X X DPRINTF(1, ( "evSetTimer(ctx %#x, func %#x, uap %#x, due %d.%06d, inter %d.%06d)\n", X ctx, func, uap, X due.tv_sec, due.tv_usec, X inter.tv_sec, inter.tv_usec)); X X /* due={0,0} is a magic cookie meaning "now." */ X if (due.tv_sec == 0 && due.tv_usec == 0) X OK(gettimeofday(&due, NULL)); X X /* Allocate and fill. */ X OKNEW(id); X id->func = func; X id->uap = uap; X id->due = due; X id->inter = inter; X X /* Insert in ``due'' order. */ X (void) evRelinkTimers(ctx, /*harmless*/id, id); X X /* Remember the ID if the caller provided us a place for it. */ X if (opaqueID) X opaqueID->opaque = id; X X return (0); } X int evClearTimer(evContext opaqueCtx, evTimerID id) { X evContext_p *ctx = opaqueCtx.opaque; X evTimer *del = id.opaque, *old, *cur; X X /* Find element whose ID matches caller's. */ X for (old = NULL, cur = ctx->timers; X cur != NULL && cur != del; X old = cur, cur = cur->next) X NULL; X if (! cur) X ERR(ENOENT); X X UnlinkTimer(ctx, old, cur); X (void) free(cur); X return (0); } X int evRelinkTimers(evContext_p *ctx, evTimer *del, evTimer *add) { X evTimer *old, *cur; X X /* In one pass, delete ``del'' and insert ``add'' in time-due order. */ X for (old = NULL, cur = ctx->timers; X cur != NULL && (del != NULL || add != NULL); X cur = cur->next) { X if (cur == del) { X UnlinkTimer(ctx, old, cur); X del = NULL; X continue; X } X if (add && evCmpTimeV(cur->due, add->due) > 0) { X LinkTimer(ctx, old, add); X cur = add; X add = NULL; X } X old = cur; X } X if (add) X LinkTimer(ctx, old, add); X if (del) X ERR(ENOENT); X PrintTimers(ctx, "after relink"); X return (0); } X static void LinkTimer(evContext_p *ctx, evTimer *old, evTimer *add) { X if (! old) { X add->next = ctx->timers; X ctx->timers = add; X } else { X add->next = old->next; X old->next = add; X } X PrintTimers(ctx, "after link"); } X static void UnlinkTimer(evContext_p *ctx, evTimer *old, evTimer *cur) { X if (! old) X ctx->timers = cur->next; X else X old->next = cur->next; X PrintTimers(ctx, "after unlink"); } X #ifdef DEBUG static void PrintTimers(const evContext_p *ctx, char *label) { X const evTimer *cur; X X DPRINTF(2, ("PrintTimers [%s]:\n", label)); X for (cur = ctx->timers; cur; cur = cur->next) X DPRINTF(2, ( "\tfunc %#x, uap %#x, due %d.%06d, inter %d.%06d, next %#x\n", X cur->func, cur->uap, X cur->due.tv_sec, cur->due.tv_usec, X cur->inter.tv_sec, cur->inter.tv_usec, X cur->next)); } #endif SHAR_EOF $shar_touch -am 0917161295 'timers.c' && chmod 0444 'timers.c' || echo 'restore of timers.c failed' shar_count="`wc -c < 'timers.c'`" test 4959 -eq "$shar_count" || echo "timers.c: original size 4959, current size $shar_count" fi # ============= files.c ============== if test -f 'files.c' && test X"$1" != X"-c"; then echo 'x - skipping files.c (file already exists)' else echo 'x - extracting files.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'files.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* files.c - implement asynch file IO for the eventlib X * vix 11sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: files.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include "eventlib.h" #include "eventlib_p.h" X static evFile *FindFD(const evContext_p *ctx, int fd); X int evSelectFD(evContext opaqueCtx, X int fd, X int eventmask, X evFileFunc func, X void *uap, X evFileID *opaqueID ) { X evContext_p *ctx = opaqueCtx.opaque; X evFile *id; X int mode; X X DPRINTF(1,("evSelectFD(ctx %#x, fd %d, mask 0x%x, func %#x, uap %#x)\n", X ctx, fd, eventmask, func, uap)); X if (!eventmask || (eventmask & ~(EV_READ|EV_WRITE|EV_EXCEPT))) X ERR(EINVAL); X if (fd >= FD_SETSIZE) X ERR(EINVAL); X OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ X X /* X * The first time we touch a file descriptor, we need to check to see X * if the application already had it in O_NONBLOCK mode and if so, all X * of our deselect()'s have to leave it in O_NONBLOCK. If not, then X * all but our last deselect() has to leave it in O_NONBLOCK. X */ X if (! (id = FindFD(ctx, fd))) { X if (mode & O_NONBLOCK) X FD_SET(fd, &ctx->nonblockBefore); X else { X OK(fcntl(fd, F_SETFL, mode | O_NONBLOCK)); X FD_CLR(fd, &ctx->nonblockBefore); X } X } X X /* Allocate and fill. */ X OKNEW(id); X id->func = func; X id->uap = uap; X id->fd = fd; X id->eventmask = eventmask; X X /* X * Insert at head. Order could be important for performance if we X * believe that evGetNext()'s accesses to the fd_sets will be more X * serial and therefore more cache-lucky if the list is ordered by X * ``fd.'' We do not believe these things, so we don't do it. X * X * The interesting sequence is where GetNext() has cached a select() X * result and the caller decides to evSelectFD() on some descriptor. X * Since GetNext() starts at the head, it can miss new entries we add X * at the head. This is not a serious problem since the event being X * evSelectFD()'d for has to occur before evSelectFD() is called for X * the file event to be considered "missed" -- a real corner case. X * Maintaining a "tail" pointer for ctx->files would fix this, but I'm X * not sure it would be ``more correct.'' X */ X id->next = ctx->files; X ctx->files = id; X X /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ X if (eventmask & EV_READ) X FD_SET(fd, &ctx->rdNext); X if (eventmask & EV_WRITE) X FD_SET(fd, &ctx->wrNext); X if (eventmask & EV_EXCEPT) X FD_SET(fd, &ctx->exNext); X X /* Update fdMax. */ X if (fd > ctx->fdMax) X ctx->fdMax = fd; X X /* Remember the ID if the caller provided us a place for it. */ X if (opaqueID) X opaqueID->opaque = id; X X return (0); } X int evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { X evContext_p *ctx = opaqueCtx.opaque; X evFile *del = opaqueID.opaque; X evFile *old, *cur; X int mode, eventmask; X X /* Get the mode. Unless the file has been closed, errors are bad. */ X mode = fcntl(del->fd, F_GETFL, NULL); X if (mode == -1 && errno != EBADF) X ERR(errno); X X /* Remove this ID. Its absense is an ENOENT error. */ X for (old = NULL, cur = ctx->files; X cur != NULL && cur != del; X old = cur, cur = cur->next) X NULL; X if (! cur) X ERR(ENOENT); X if (! old) X ctx->files = del->next; X else X old->next = del->next; X X /* X * If the file descriptor does not appear in any other select() entry, X * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode X * earlier, then: restore the fd to blocking status. X */ X if (!(cur = FindFD(ctx, del->fd)) && X FD_ISSET(del->fd, &ctx->nonblockBefore) && X mode != -1) { X /* X * Note that we won't return an error status to the caller if X * this fcntl() fails since (a) we've already done the work X * and (b) the caller didn't ask us anything about O_NONBLOCK. X */ X (void) fcntl(del->fd, F_SETFL, mode & ~O_NONBLOCK); X } X X /* X * We saved the position of the next use of this FD in the select list, X * and if there is any such, we need to search the remainder of the X * list OR'ing all the eventmasks for this fd together so that we don't X * turn off {rd,wr,ex}Next bits that some other select is using. X */ X eventmask = 0; X for (; cur; cur = cur->next) X if (cur->fd == del->fd) X eventmask |= cur->eventmask; X X /* OK, now we know which bits we can clear out. */ X if (eventmask & EV_READ) X FD_CLR(del->fd, &ctx->rdNext); X if (eventmask & EV_WRITE) X FD_CLR(del->fd, &ctx->wrNext); X if (eventmask & EV_EXCEPT) X FD_CLR(del->fd, &ctx->exNext); X X /* If this was the maxFD, find the new one. */ X if (del->fd == ctx->fdMax) { X ctx->fdMax = -1; X for (cur = ctx->files; cur; cur = cur->next) X if (cur->fd > ctx->fdMax) X ctx->fdMax = cur->fd; X } X X /* If this was the fdNext, cycle that to the next entry. */ X if (del == ctx->fdNext) X ctx->fdNext = del->next; X X /* Couldn't free it before now since we were using fields out of it. */ X (void) free(del); X X return (0); } X static evFile * FindFD(const evContext_p *ctx, int fd) { X evFile *id; X X for (id = ctx->files; id != NULL && id->fd != fd; id = id->next) X NULL; X return (id); } SHAR_EOF $shar_touch -am 0917161295 'files.c' && chmod 0444 'files.c' || echo 'restore of files.c failed' shar_count="`wc -c < 'files.c'`" test 5896 -eq "$shar_count" || echo "files.c: original size 5896, current size $shar_count" fi # ============= signals.c ============== if test -f 'signals.c' && test X"$1" != X"-c"; then echo 'x - skipping signals.c (file already exists)' else echo 'x - extracting signals.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'signals.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* signals.c - implement asynch signals for the eventlib X * vix 16sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: signals.c,v 1.1 1995/09/17 05:30:26 vixie Exp $"; #endif X #include "eventlib.h" #include "eventlib_p.h" X static evSignal *FindSig(const evContext_p *ctx, int sig); static void EatMe(int mystery); X int evSetSignal(evContext opaqueCtx, int sig, X evSignalFunc func, void *uap, X evSignalID *opaqueID ) { X evContext_p *ctx = opaqueCtx.opaque; X evSignal *old, *new; X struct sigaction act, oact; X sigset_t set, oset; X int save; X X /* X * POSIX gives us no way to validate the signal number, since there's X * no requirement that sigaddset() return (-1) if given a bad signal X * (and BSD's sigaddset() macro doesn't do so in any case.) So we'll X * try a sigaddset(), check it for errors, and then check its results. X */ X OK(sigemptyset(&set)); X OK(sigaddset(&set, sig)); X if (sigismember(&set, sig) <= 0) X ERR(EINVAL); X X /* X * If we already have something in the signal list for this signal, X * then we want its ``oact,'' elsewise we need to get the ``oact'' X * from the system. X */ X old = FindSig(ctx, sig); X X /* X * Block the signal. If it wasn't previously blocked and we had the X * signal on the list, exit now. If it was previously blocked and we X * didn't have it on the list, remember the blockedness so that we X * leave it blocked after evClearSignal(). Note that we block the X * signal even if it's already on our signal list, since this gives X * us a chance to blue chunks if it's not in fact blocked any more. X * X * Note that blocking the signal has the effect that our select() in X * evGetNext() will not return with -1 and errno==EINTR when a signal X * occurs. We would rather not have that happen, but to fix it we X * would have to let the signal call a handler, and that handler would X * either have to have static global storage (to remember that the X * signal had occured -- had for thread safety!). We prefer polling, X * while noting that POSIX should have defined a signal "uap" argument. X */ X OK(sigprocmask(SIG_BLOCK, &set, &oset)); X if (!old) { X /* First catch of this signal. Make blockedBefore right. */ X X if (sigismember(&oset, sig) > 0) { X /* Note that an error below doesn't need any fixups. */ X OK(sigaddset(&ctx->blockedBefore, sig)); X } else { X if (sigismember(&ctx->blockedBefore, sig) > 0) X OK(sigdelset(&ctx->blockedBefore, sig)); X } X X /* X * Install a signal handler. We don't do anything in the X * handler, but the POSIX docs are unclear as to whether X * SIG_IGN will preclude the sigpending() mask from ever X * showing that the signal happened. Since we rely on the X * (obscure) POSIX semantics of sigprocmask() (see the X * comments in evGetNext for more details), we want to make X * sure that the kernel has no excuse not to set our X * sigpending() mask bit. X */ X sigemptyset(&set); X act.sa_handler = EatMe; X act.sa_mask = set; X act.sa_flags = 0; X if (sigaction(sig, &act, &oact) < 0) { X save = errno; X (void) sigprocmask(SIG_SETMASK, &oset, NULL);/*Fixup.*/ X ERR(errno); X } X } else { X /* This signal is already being caught. Make sure, though. */ X X if (sigismember(&oset, sig) <= 0) { X (void) sigprocmask(SIG_SETMASK, &oset, NULL);/*Fixup.*/ X ERR(EBADF); X } X oact = old->oact; X } X X /* Allocate, fill, link. */ X NEW(new); X if (!new) { X (void) sigprocmask(SIG_SETMASK, &oset, NULL); /* Fixup. */ X if (!old) X (void) sigaction(sig, &oact, NULL); X ERR(ENOMEM); X } X new->func = func; X new->uap = uap; X new->sig = sig; X new->oact = oact; X new->next = ctx->signals; X ctx->signals = new; X X /* Save handle if we've been given one. */ X if (opaqueID) X opaqueID->opaque = new; X X return (0); } X int evClearSignal(evContext opaqueCtx, evSignalID opaqueID) { X evContext_p *ctx = opaqueCtx.opaque; X evSignal *del = opaqueID.opaque; X evSignal *old, *cur; X X /* Unlink. */ X for (old = NULL, cur = ctx->signals; X cur != NULL && cur != del; X old = cur, cur = cur->next) X NULL; X if (! cur) X ERR(ENOENT); X if (! old) X ctx->signals = del->next; X else X old->next = del->next; X X /* X * Was the signal caught elsewise? If not, we should restore the X * signal handler and blocking status to whatever it used to be. X */ X if (!(cur = FindSig(ctx, del->sig))) { X if (sigismember(&ctx->blockedBefore, del->sig) <= 0) { X sigset_t set; X X (void) sigemptyset(&set); X (void) sigaddset(&set, del->sig); X (void) sigprocmask(SIG_UNBLOCK, &set, NULL); X } X (void) sigaction(del->sig, &del->oact, NULL); X } X X /* Deallocate and get out. */ X free(del); X return (0); } X static evSignal * FindSig(const evContext_p *ctx, int sig) { X register evSignal *cur; X X for (cur = ctx->signals; cur && cur->sig != sig; cur = cur->next) X NULL; X return (cur); } X static void EatMe(int mystery) { X NULL; } SHAR_EOF $shar_touch -am 0916223095 'signals.c' && chmod 0444 'signals.c' || echo 'restore of signals.c failed' shar_count="`wc -c < 'signals.c'`" test 5692 -eq "$shar_count" || echo "signals.c: original size 5692, current size $shar_count" fi # ============= testfiles.c ============== if test -f 'testfiles.c' && test X"$1" != X"-c"; then echo 'x - skipping testfiles.c (file already exists)' else echo 'x - extracting testfiles.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'testfiles.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* testfiles - a really slow version of "cat" that tests file I/O events X * vix 13sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: testfiles.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include <assert.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> X #include "eventlib.h" X #ifdef DEBUG int evDebugLev = 10; #endif X struct closure { X int otherFD; X evFileID id; }; X void myCopyFunc(evContext ctx, void *uap, int fd, int eventmask) { X struct closure *c = uap; X char buf[BUFSIZ]; X int len; X X len = read(fd, buf, sizeof buf); X if (len <= 0) { X evDeselectFD(ctx, c->id); X free(uap); X } else X write(c->otherFD, buf, len); } X int main(int argc, char *argv[]) { X evContext ev; X struct closure *c; X X puts("This is a really slow version of ``cat''. Type something."); X evOpen(&ev); X if (!(c = malloc(sizeof *c))) { X printf("out of memory?\n"); X exit(1); X } X c->otherFD = STDOUT_FILENO; X if (evSelectFD(ev, STDIN_FILENO, EV_READ, myCopyFunc, c, &c->id) < 0) { X perror("evSelectFD"); X exit(1); X } X X assert(evMainLoop(ev) == -1); X if (errno != ENOENT) X perror("evMainLoop"); X evClose(ev); X exit(0); X /*NOTREACHED*/ } SHAR_EOF $shar_touch -am 0917161295 'testfiles.c' && chmod 0444 'testfiles.c' || echo 'restore of testfiles.c failed' shar_count="`wc -c < 'testfiles.c'`" test 2048 -eq "$shar_count" || echo "testfiles.c: original size 2048, current size $shar_count" fi # ============= testtimers.c ============== if test -f 'testtimers.c' && test X"$1" != X"-c"; then echo 'x - skipping testtimers.c (file already exists)' else echo 'x - extracting testtimers.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'testtimers.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* testtimers - a test jig to let programmers test the timer events X * vix 13sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: testtimers.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include <stdlib.h> #include <stdio.h> #include <string.h> X #ifdef NEED_STRDUP static char *strdup(char *str); #endif X #include "eventlib.h" X #ifdef DEBUG int evDebugLev = 10; #endif X struct closure { X char *name; X evTimerID id; }; X void myTimerFunc(evContext ctx, void *uap, X struct timeval due, X struct timeval inter ) { X struct timeval now; X struct closure *c = uap; X int reissue = inter.tv_sec || inter.tv_sec; X X printf("myTimerFunc: due %d.%06d [ctx %#x, uap %#x(%s)]\n", X due.tv_sec, due.tv_usec, ctx, c, c->name); X (void) gettimeofday(&now, NULL); X printf("myTimerFunc: now %d.%06d [inter %d.%06d, reissue: %d]\n", X now.tv_sec, now.tv_usec, inter.tv_sec, inter.tv_usec, reissue); X if (!reissue) X free(uap); } X int main(int argc, char *argv[]) { X char buf[1000]; X evContext ev; X struct timeval now; X X puts("Read the source to figure out what this does."); X evOpen(&ev); X gettimeofday(&now, NULL); X while (gets(buf)) { X char name[100]; X struct timeval due, inter; X struct closure *c; X int x; X X x = sscanf(buf, "%d.%d %d.%d %s\n", X &due.tv_sec, &due.tv_usec, X &inter.tv_sec, &inter.tv_usec, X name); X if (x != 5 && x != 4 && x != 2) { X printf("bong! usage: due inter name\n"); X continue; X } X if (x < 5) X strcpy(name, "default"); X if (x < 4) X inter = evConsTimeV(0,0); X if (!(c = malloc(sizeof *c))) { X printf("out of memory?\n"); X exit(1); X } X c->name = strdup(name); X x = evSetTimer(ev, myTimerFunc, c, X evAddTimeV(due, now), inter, X &c->id); X printf("---> %d\n", x); X } X evMainLoop(ev); X perror("evMainLoop"); X evClose(ev); X exit(0); X /*NOTREACHED*/ } X #ifdef NEED_STRDUP static char * strdup(char *str) { X char *x = malloc(strlen(str) + 1); X X return (strcpy(x, str)); } #endif SHAR_EOF $shar_touch -am 0917161295 'testtimers.c' && chmod 0444 'testtimers.c' || echo 'restore of testtimers.c failed' shar_count="`wc -c < 'testtimers.c'`" test 2830 -eq "$shar_count" || echo "testtimers.c: original size 2830, current size $shar_count" fi # ============= testsignals.c ============== if test -f 'testsignals.c' && test X"$1" != X"-c"; then echo 'x - skipping testsignals.c (file already exists)' else echo 'x - extracting testsignals.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'testsignals.c' && /* Copyright (c) 1995 by Internet Software Consortium X * X * Permission to use, copy, modify, and distribute this software for any X * purpose with or without fee is hereby granted, provided that the above X * copyright notice and this permission notice appear in all copies. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X /* testsignals - test jig allowing programmers to test the eventlib signals X * vix 16sep95 [initial] X */ X #if !defined(LINT) && !defined(CODECENTER) static const char rcsid[] = "$Id: testsignals.c,v 1.2 1995/09/17 23:12:25 vixie Exp $"; #endif X #include <assert.h> #include <errno.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> X #include "eventlib.h" X #ifdef DEBUG int evDebugLev = 10; #endif X void mySignalFunc(evContext ctx, void *uap, int sig) { X char *name = uap; X X printf("mySignalFunc(ctx %#x, uap %#x(%s), sig %d)\n", X ctx, uap, name, sig); X if (sig == SIGINT) { X evClose(ctx); X exit(0); X } X if (sig == SIGALRM) { X time_t now = time(NULL); X X printf(" ...time now %s", ctime(&now)); X alarm(5); X } } X int main(int argc, char *argv[]) { X evContext ev; X struct closure *c; X X puts("You should get some output every six seconds, and you should"); X puts("get a slightly delayed exit from a SIGINT (^C)."); X evOpen(&ev); X if (evSetSignal(ev, SIGINT, mySignalFunc, "interrupt", NULL) < 0) { X perror("evSetSignal"); X exit(1); X } X if (evSetSignal(ev, SIGALRM, mySignalFunc, "alarm", NULL) < 0) { X perror("evSetSignal"); X exit(1); X } X alarm(5); X X assert(evMainLoop(ev) == -1); X if (errno != ENOENT) X perror("evMainLoop"); X evClose(ev); X exit(0); X /*NOTREACHED*/ } SHAR_EOF $shar_touch -am 0917161295 'testsignals.c' && chmod 0444 'testsignals.c' || echo 'restore of testsignals.c failed' shar_count="`wc -c < 'testsignals.c'`" test 2176 -eq "$shar_count" || echo "testsignals.c: original size 2176, current size $shar_count" fi # ============= testtimers.data ============== if test -f 'testtimers.data' && test X"$1" != X"-c"; then echo 'x - skipping testtimers.data (file already exists)' else echo 'x - extracting testtimers.data (text)' sed 's/^X//' << 'SHAR_EOF' > 'testtimers.data' && 10.500000 ten 9.000000 nine 8.100000 eight 7.250000 seven 6.666666 six 5.050505 five 4.110000 four 3.314159 three 2.718281 two 1.414213 one SHAR_EOF $shar_touch -am 0911170595 'testtimers.data' && chmod 0444 'testtimers.data' || echo 'restore of testtimers.data failed' shar_count="`wc -c < 'testtimers.data'`" test 140 -eq "$shar_count" || echo "testtimers.data: original size 140, current size $shar_count" fi # ============= testtimers2.data ============== if test -f 'testtimers2.data' && test X"$1" != X"-c"; then echo 'x - skipping testtimers2.data (file already exists)' else echo 'x - extracting testtimers2.data (text)' sed 's/^X//' << 'SHAR_EOF' > 'testtimers2.data' && 10.0 ten 9.0 nine 8.0 eight 7.0 seven 6.0 six 5.0 five 4.0 four 3.0 three 2.0 two 1.0 one SHAR_EOF $shar_touch -am 0911171095 'testtimers2.data' && chmod 0444 'testtimers2.data' || echo 'restore of testtimers2.data failed' shar_count="`wc -c < 'testtimers2.data'`" test 90 -eq "$shar_count" || echo "testtimers2.data: original size 90, current size $shar_count" fi exit 0 -- Paul Vixie La Honda, CA "Illegitimibus non carborundum." <paul@vix.com> pacbell!vixie!paul