diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-04 17:21:04 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-04 17:21:04 -0800 |
commit | e0b431a48cc3ac5d3ec32f06eddd9708ad655fa2 (patch) | |
tree | ce4c73521220fbb751c2be6a42e85ff6a6cbff97 | |
download | expect-e0b431a48cc3ac5d3ec32f06eddd9708ad655fa2.tar.gz expect-e0b431a48cc3ac5d3ec32f06eddd9708ad655fa2.tar.bz2 expect-e0b431a48cc3ac5d3ec32f06eddd9708ad655fa2.zip |
Imported Upstream version 5.45upstream/5.45
145 files changed, 82653 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..64c40a4 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1514 @@ +2010-10-26 Andreas Kupries <andreask@activestate.com> + + * expect.c: [Bug 3095935]: Convert #bytes information to #chars to + prevent later code to fail when copying strings around and + miscalculating how much to copy, for strings containing + non-ASCII utf chars. + +2010-09-30 Andreas Kupries <andreask@activestate.com> + + * example/autopasswd: Updated to use tclsh in PATH, and 'package + * example/chess.exp: require Expect'. Obsoletes fixline1. + * example/cryptdir: + * example/decryptdir: + * example/dislocate: + * example/dvorak: + * example/ftp-inband: + * example/ftp-rfc: + * example/gethostbyaddr: + * example/kibitz: + * example/lpunlock: + * example/mkpasswd: + * example/multixterm: + * example/passmass: + * example/read1char: + * example/rftp: + * example/rlogin-cwd: + * example/robohunt: + * example/rogue.exp: + * example/telnet-cwd: + * example/timed-read: + * example/timed-run: + * example/unbuffer: + * example/virterm: + * example/weather: + * example/xkibitz: + * example/xpstat: + + * Makefile.in: Continued work on the 'make dist' target (config.{sub,guess}) + * install.sh: Removed unused file. + * mkinstalldirs: Removed unused file. + * tclconfig/README.txt: Removed unused file. + * testsuite/config/: Removed contents of unused directory. + * test/.Sanitize: Removed unused file. + +2010-09-17 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: improved make dist target to include the necessary + files, and remove old dist_orig. + Enable Makefile regen target + +2010-09-16 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: regen with ac-2.59 + * tclconfig/tcl.m4: update for correct LDFLAGS on HP-UX + * Makefile.in (expect): use TEA LDFLAGS instead of tclConfig.sh to + build expect executable + +2010-09-01 Andreas Kupries <andreask@activestate.com> + + * Makefile.in: [Bug 865278] Semi-applied Don Porter's patch adding + code which prevents the package from registering with Tcl + interpreters which cannot load it, i.e. below the version it was + compiled against. Semi because the pkgIndex.in in his patch is + not used, the pkgIndex.tcl is generated by the Makefile(.in). + * pkgIndex.in: Removed. File not used. + +2010-08-31 Andreas Kupries <andreask@activestate.com> + + * Various cleanups, local patches of ActiveState. + * exp_clib.c: Remove local copy of Tcl_ErrnoMsg(). + * exp_inter.c: Hack access to TCL_REG_BOSONLY when not present, + became private with Tcl 8.5 and higher. + * expect.h: Remove the local fiddling with the memory allocation + and panic macros. + + * Dbg.c: [Bug 2972727]: Applied the parts of Larry Virden's patch + which were still current. Most of it applied to the partially + ansified sources we had in trunk for a time and where errors in + that set of changes, thus out of date now. + + * example/unbuffer: [Bug 2949748]: Applied patch by Vitezslav + Crhonek <vcrhonek@users.sourceforge.net> to prevent unbuffer + from eating the exit code of the command it ran (regular mode + only, not -p). Slightly modified, I removed the superfluous + 'eval' used to invoke 'wait', invoking it directly. + +2010-08-27 Jeff Hobbs <jeffh@ActiveState.com> + + * retoglob.c: Fail if the generated glob contains more than + two asterisks. Fixes [Expect SF Bug 3010684] (cederqvist) + + * exp_main_sub.c: add return to silence compiler warning. + Updated EXP_VERSION to 5.45.0 + + * config.guess, config.sub, expect.m4 (removed): + * configure, configure.in, tclconfig/tcl.m4: Update to TEA 3.9 + * Makefile.in, aclocal.m4: Partial cleanup of the build system. + * testsuite/Makefile.in: Remove unused EXP_ from configure.in + * testsuite/aclocal.m4: and no longer use Tk. + * testsuite/configure: Update testsuite bits to use TEA info. + * testsuite/configure.in: + Update expect to version 5.45 + + * Dbg.c: account for removal of tcldbgcf.h + * DbgMkfl.in, Dbgconfig.in, Dbgconfigure, DbgpkgInd.in (removed): + * tcldbgcf.h.in (removed): removed Dbg debugger subcomponent as it + no longer built and debugger functionality is included in expect + library and binary + + * pty_termios.c: add HAVE_STRING_H include string.h + * exp_trap.c: add HAVE_STRING_H include string.h + + * expectk.man, exp_main_tk.c (removed): expectk no longer + built. Use tclsh with package require Tk and Expect instead. + + * tests/all.tcl: add package require Expect + + * example/archie, example/autoexpect: minor code cleanup + * example/tkpasswd, example/tknewsbiff, example/tkterm: use + package require statements in lieu of expectk + +2009-11-03 Andreas Kupries <andreask@activestate.com> + + * exp_command.c (Exp_SpawnObjCmd): [Expect SF Bug 2891422]. Fixed + error message when the command to spawn could not be executed. + Tried to use a Tcl_Obj* as argument for a %s. Replaced with the + correct char* variable. Thanks to Elchonon Edelson + <eee@users.sourceforge.net> for the report. + [Expect SF Bug 2891563] Ditto for the same type of bug when + emitting error 'usage: -ignore unknown signal name'. The + remainder of the exp_error calls are ok however. + + * configure.in: Bumped version to 5.44.1.15. + * configure: Regen'd, autoconf 2.59. + +2009-07-14 Andreas Kupries <andreask@activestate.com> + + * exp_clib.c (TclRegComp): Fixed memory leak reported by + <ettlmartin@users.sourceforge.net> in [Expect SF Bug 2814263]. + +2009-06-22 Andreas Kupries <andreask@activestate.com> + + * pty_unicos.c (pty_stty): Fixed missing double-quotes for sprint + formatting strings. Thanks to <ettlmartin@users.sourceforge.net> + for the report, i.e. [Expect SF Bug 2809496]. + +2009-06-18 Andreas Kupries <andreask@activestate.com> + + * exp_command.c (Exp_LogFileObjCmd): Fix argument parsing logic + error in the log_file command breaking the use of options -open + and -leaveopen. Applied patch supplied by Andy Belsey + <Andrew.Belsey@Sun.COM>. With thanks for both the analysis of + the problem and the patch. + + * configure.in: Bumped version to 5.44.1.14. + * configure: Regen'd, autoconf 2.59. + +2009-05-27 Andreas Kupries <andreask@activestate.com> + + * exp_tty.c (Exp_SttyCmd, Exp_SystemCmd): Applied patch by + Reinhard Max (max@suse.de) fixing buffer-overflows in the 'stty' + command due to an off-by-one error in the buffer size. See the + bugs https://bugzilla.novell.com/show_bug.cgi?id=506873 + and https://bugzilla.novell.com/show_bug.cgi?id=501291 + + * configure.in: Bumped version to 5.44.1.13. + * configure: Regen'd, autoconf 2.59. + +2009-05-06 Andreas Kupries <andreask@activestate.com> + + * retoglob.c: Accepted the patch by Mike Cumings + <mcumings@users.sourceforge.net> fixing [Expect SF Bug 13179]. + The updated code checks a (?...) sequence that it contains only + ARE options before processing it as such. This prevents the + misinterpretation of non-capturing paren groups as ARe options + with subsequent segmentation fault. + + * configure.in: Bumped version to 5.44.1.12. + * configure: Regen'd, autoconf 2.59. + +2008-09-30 Andreas Kupries <andreask@activestate.com> + + * configure.in: Bumped version to 5.44.1.11. + * configure: Regen'd, autoconf 2.59. + + * exp_command.c (Exp_OverlayObjCmd): Fixed [Expect SF Bug 2127456] + reported by <eee@users.sourceforge.net>, with thanks. Changed + retrieval of command from objv[0] (== 'overlay' itself), to + objv[i] containing the actual user command. + + * expect.c (string_case_first, string_first, eval_case_string): + Applied patch supplied by Andy Belsey <Andrew.Belsey@Sun.COM> + fixing the seg.fault in 'expect -exact'. With thanks for both + the analysis of the problem and the patch. See also [Expect SF + Bug 2114547]. + +2008-08-28 Andreas Kupries <andreask@activestate.com> + + * exp_trap.c (tophalf): Fixed inverted condition setting the + interpreter used for trap handling to NULL, causing a crash when + trying to handle ^C. This fixes [SF Bug 1757471] reported by + Matthias Kraft <matzek@users.sourceforge.net>. + * configure.in: Bumped version to 5.44.1.10. + * configure: Regen'd, autoconf 2.59. + +2008-08-18 Jeff Hobbs <jeffh@ActiveState.com> + + * exp_main_sub.c (exp_interpreter): cleaner handling of commandPtr + to prevent crash. (das) + +2008-06-03 Andreas Kupries <andreask@activestate.com> + + * exp_glob.c (Exp_StringCaseMatch2): Fixed bug in the handling of + glob classes, see [SF Bug 1873404]. The code tried to match the + closing bracket of a class in the input because it was not + properly skipped after the class was matched successfully. + Additional trace output added. + * configure.in: Bumped version to 5.44.1.9. + * configure: Regen'd, autoconf 2.59. + +2008-05-05 Andreas Kupries <andreask@activestate.com> + + * exp_pty.c: Minimal ansification of function definitions to match + them to their prototypes where promoted types are otherwise + causing a mismatch for some compilers, like AIX in 64bit mode. + * configure.in: Bumped version to 5.44.1.8. + * configure: Regen'd, autoconf 2.59. + +2008-04-03 Andreas Kupries <andreask@activestate.com> + + * configure.in: Bumped version to 5.44.1.7. + * configure: Regen'd, autoconf 2.59. + + * The following set of changes was sent our way by Reinhard Max + <max@tclers.tk>. + + * exp_command.c: Fixed more compiler warnings, and started + * exp_command.h: to ansify the code base, beginning with + * exp_inter.c: the introduction of proper function prototypes. + * exp_main_exp.c: + * exp_pty.h: + * exp_tty.c: + * exp_tty.h: + * exp_win.c: + * expect.c: + * pty_termios.c: + * retoglob.c: + +2008-04-03 Andreas Kupries <andreask@activestate.com> + + * configure.in: Bumped version to 5.44.1.6. + * configure: Regen'd, autoconf 2.59. + + * The following set of changes was sent our way by Reinhard Max + <max@tclers.tk>. + + * configure.in: Fixed checking of stty on linux, do not restrict + to specific cpu's. Further try with stdin, and stdin redirected + to /dev/tty when determining if stdout is read. + + * testsuite/configure.in: Brought up to TEA 3.5. + * testsuite/aclocal.m4: New file, to import the TEA definitions. + + * Dbg.c: Added missed CONST in declaration and definition of + 'debugger_trap'. + + * exp_command.c: Fixed pointer aliasing trouble with + 'Tcl_DetachPids', and added the missing initialization of the + command string in the 'overlay' command. + + * expect.c: Fixed missing initialization of 'simple_start' element + of 'ecase'. + + * exp_inter.c: Fixed bogus use of 'slen' in 'intMatch'. The + relevant string is Tcl_Unichar, not Utf. + + * Makefile.in: Replaced bogus INSTALL_ROOT with DESTDIR, and added + missing DESTDIR references to the target for the installation of + the manpages. + +2008-02-27 Andreas Kupries <andreask@activestate.com> + + * expect.c: Fixed refcounting error when parsing a single expect + * configure.in: argument into a list of patterns and + * configure: actions. Updated the version number to 5.44.1.5. + * Dbg.c: Added missing 'return TCL_OK' to debugger_trap. + +2007-12-13 Jeff Hobbs <jeffh@ActiveState.com> + + * exp_log.c (expStdoutLogU): correct which buf is output. + + * exp_command.c (Exp_SendLogObjCmd): fix '--' handling + (Exp_SendObjCmd): fix '--' handling to expect last argument + +2007-09-24 Andreas Kupries <andreask@activestate.com> + + * exp_inter.c: Changed inclusion of tcl.h to tclInt.h to get the + * expect.c: definition of TCL_REG_BOSONLY, which was moved to that + header in Tcl 8.5. Ditto for expect.c, for the macro + TclUtfToUniChar (was a function in 8.4). Expect now compiles + again for both Tcl 8.4 and 8.5. + + * configure.in: Bumped version to 5.44.1.4. + * configure: Regenerated. + +2007-09-19 Andreas Kupries <andreask@activestate.com> + + * retoglob.c (EMITC): Keep the characters '^' and '$' quoted as + well, we do not wish to invoke their special interpretation by + the Expect glob matcher. + * configure.in: Bumped version to 5.44.1.3. + * configure: Regenerated. + +2007-08-09 Andreas Kupries <andreask@activestate.com> + + * retoglob.c: We had ExpChopNested and ExpBackslash locally + ansified (prototypes) to avoid a compiler error on AIX (type + promotion trouble). This now integrated into the mainline + sources, conditional to AIX. + + * expect.c (Exp_TimestampObjCmd): Fixed argument processing broken + by objc,objv conversion. Tried to use command name as the + argument for -seconds. Also did not detect when one argument to + many was specified. + + * configure.in: Bumped version to 5.44.1.2. + * configure: Regenerated. + +2007-07-17 Andreas Kupries <andreask@activestate.com> + + * expect.c: Circumvented problems with the C compiler by use of a + temporary variable to hold the unicode pointer of a glob + pattern. The computed pattern length given to + Exp_StringCaseMatch was bogus. + + * exp_glob.c: Added tracing of the glob matcher internals (Can be + enabled by define EXP_INTERNAL_TRACE_GLOB). Fixed bug in a guard + condition in the optimized handling of '*'. The bad condition + caused the code to miss possible matches at the beginning of the + input (first char). + + * tests/expect.test: Added tests which check the glob matcher and + RE gate keeping. + + * configure.in: Bumped to 5.44.1.1 to separate this from the + regular 5.44.1 sources. + * configure: Regenerated. + +2007-07-12 Andreas Kupries <andreask@activestate.com> + + * expect.c: Found bugs mismanaging input and pattern in the + * exp_glob.c: updated glob matcher. We cannot check for '\0' + anymore to find the end of the string, these are counted + arrays now. Rewritten to use sentinel pointers. + +2007-07-11 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c: Converted the buffering system from UTF-8 in Tcl_Obj + * exp_command.h: to UTF-16 C-array, to avoid the repeated conversion + * expect.c: of the input from utf-8 to utf-16. Updated the glob + * exp_glob.c: matching code to use the same tricks for speed which + * exp_inter.c: are used by the Tcl core. Extended the regexp + * exp_log.c: matching path with a glob matcher which uses a gate + * exp_log.h: keeper glob pattern to weed out most non-candidates + * retoglob.c (New file): in a speedy manner. Regexp matching now + has to be done only for the small number of candidates + identified by the gate keeper. Overall speed improvement as glob + matching is faster than regexp matching. Added code translating + regular expressions into their gate keeper glob pattern. + + * Dbg.c: Converted the lot of argc,argv based command + * exp_command.c: implementations over to objc,objv. + * expect.c: + * exp_main_sub.c: + + * Dbg.c: Cleaned up the direct access to interp->result, + * exp_command.c: replaced with the proper functions and + * expect.c: Tcl_Obj's. + * exp_main_exp.c: + * exp_main_sub.c: + * exp_main_tk.c: + * exp_prog.h: + * exp_trap.c: + * exp_tty.c: + * exp_win.c: + * exp_win.h: + + * tests/cat.test: Added proper 'package require Expect' + * tests/expect.test: to the test setup code (JeffH). + * tests/logfile.test: + * tests/pid.test: + * tests/send.test: + * tests/spawn.test: + * tests/stty.test: + + * exp_command.c: Reformatted overlong lines, whitespace, + * expect.c: comments. Added braces to some if-constructs. + * exp_inter.c: Reworked if-constructs interleaved with + * exp_tty.c: #if for better formatting in emacs. + + * Dbg.c: Added note about unhandled cases in a switch. + * exp_chan.c: Added code to suppress unhandled warning for + unreachable code. + * exp_command.c: Removed unused variable. + * expect.c: Removed unused static function, added code to suppress + unhandled warning for unreachable code. + + * exp_command.c: Fixed typo in comment. + +2007-06-28 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official version 5.44.1 of expect into + the SF sources. See the details below. + + -------------------- + Marius Schamsula <marius173@mchsi.xcom> reported tclconfig + missing, evidentally for new TEA. + + Lots of massaging to fix TEAification of Makefile and configure + including that version numbers will now be full three part. + + Daniel Wong <danielwong@berkeley.xedu> noted the home page + should note that Wikipedia has a very readable entry for Expect. + + Andre Alves <aalves@escloyalty.xcom> noted passmass needed some + fixes to handle Solaris 9 passwd prompt changes. + + Andreas fixed several things: changes to better support TEA, fix + debugger interaction with nonblocking mode, and probably other + things I'm overlooking. + + Martin Dietze <di@fh-wedel.xde> noted that autoconf 2.59 is + confused by C comment after undefs in expect_cf.h.in. + + Added additional code to unbuffer -p so that if a process + earlier in the pipeline exits, unbuffer attempts to recover any + remaining output from the spawned proc before unbuffer itself + exits. + + Jeffrey Hobbs noted that once stty was called, a bg'd script + would be suspended at exit. Turned out to be overaggressive + code in stty that recorded what 'damage' the user might have + caused when calling stty in the first place. + + Jens Petersen provided patch to make setpgrp configure better on + some Linux systems. + + Added example/getpassck script to test for getpass bug. + + multixterm had debugging stuff leftover ("hello"). + -------------------- + +2006-02-27 Andreas Kupries <andreask@activestate.com> + + * exp_main_sub.c: Added command 'exp_configure' for magic configuration. + * exp_command.c: Accepts option -strictwrite. Default is 0, ignoring + * exp_chan.c: write errors (compatible to 5.41). Setting to 1 re- + * expect_tcl.h: activates 5.42 behaviour. + +2006-01-25 Jeff Hobbs <jeffh@ActiveState.com> + + * tclconfig/tcl.m4, configure: Fix LD_SEARCH_FLAGS setting in tcl.m4 + + * example/unbuffer: whitespace police + + * example/beer.exp: brace exprs + + * expect.man: use clock instead of exec date, minor nroff fixes. + +2006-01-24 Andreas Kupries <andreask@activestate.com> + + * tclconfig/tcl.m4: Updated to TEA 3.5 + * configure.in: Ditto. + * configure: Regenerated. + +2006-01-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tests/expect.test: ensure iso8859-1 for /tmp/null (steffen). + +2005-09-19 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c (ExpOutputProc): Added guard to intercept and ignore + empty write operations, i.e. operations trying to write zero + bytes. + +2005-09-09 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c (ExpBlockModeProc): No, stdin is not ok (See last + entry). Fixed. + +2005-07-07 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c (ExpBlockModeProc): [Expect SF Bug 1108551]. Excluded + manipulation of the blocking status for stdin/stderr. This is + handled by the Tcl core itself and we must absolutely not pull + the rug out from under it. The standard setting to non-blocking + will mess with the core which had them set to blocking, and + makes all its decisions based on that assumption. Setting to + non-blocking can cause hangs and crashes. Stdin is ok however, + apparently. + + This problem was introduced at '2004-06-14'. + +2005-06-22 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c: Fixed bug causing crash of expect on exit when a + * exp_command.c: Tcl channel is used with -(leave)open more than + * exp_command.h: once. It tried to close such channels multiple + times, going through already freed memory. Added data structures + to track and refcount all such channels, to close them only when + the last user goes away. + +2005-06-09 Andreas Kupries <andreask@activestate.com> + + * Makefile.in: Upgraded build system to TEA 3.2. + * configure.in: + * config.guess: + * config.sub + * exp_main_sub.c: + * aclocal.m4: + +2005-03-29 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c: Fixed problem with debugger introduced at '2004-06-14'. + * tcldbg.h: For a nonblocking stdin the debugger blowed up on the + * Dbg.c: empty reads it could get, exiting the application. I + guess that this was an implicit 'panic'. Fix: + + - Split ExpBlockmodeProc into high- and lowlevel + code, the latter for use by the debugger. The + high-level code tells the debugger which state + stdin is in (doing this explicitly because if + FIONBIO is used it is not possible to query the fd + directly, and I saw no reason to #ifdef for fcntl + which can). + + - Debugger now exports a function for use by the + blockmode proc, and in each interaction it checks + for nonblocking input, forces blocking if + necessary. At the end of each interaction the true + mode is restored. Both operations use the + low-level blockmode code. + +2005-03-07 Jeff Hobbs <jeffh@ActiveState.com> + + * exp_tty.c (Exp_SttyCmd): fix from Libes that controlling + terminal check example (book p372) by restricting set of + exp_ioctled_devtty variable. + +2005-02-15 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official versions 5.42.1 and 5.43.0 of + expect into the SF sources. See the details below. + + -------------------- + Martin Forssen <maf@tkrat.xorg> fixed bug in ExpOutputProc + that caused misbehavior during partial writes. + + Someone noted that gets stdin behaves differently (returns -1 + immediately) from tclsh because with 5.42, stdin is unblocked by + defaults. + + Robroy Gregg <robroy@armory.xcom> noted that expect_background + ignores timeouts. Added to documentation. + + Jens Peterson <peterson@redhat.xcom> provided patch for + "mkpasswd -vo". + + Gary Bliesener <gary.bliesener@nextel.xcom> noted that + multixterm failed on his system which had an old Tk that didn't + support the Tk package. + + Removed beta designation. + + Daniel A. Steffen <steffen@ics.mq.edu.xau> provided patch for + MacOS to avoid panic-redefinition. + -------------------- + +2005-01-21 Andreas Kupries <andreask@activestate.com> + + * exp_inter.c: Changed all uses of 'time(3)' to Tcl_GetTime. IOW + * expect.c: go through the abstract core API instead of + directly acessing OS time. This makes the code + dependent on Tcl 8.4, as Tcl_GetTime was not public + before. See TIP #73 for its introduction into the + public API. As for the reason behind _this_ change + see TIP #233. Our change here now causes Expect to + be automatically in sync with any virtualization + set up in the core. + +2004-08-19 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c (ExpOutputProc): Added code posted by Don on + c.l.t. to handle interrupted system calls (EAGAIN). + +2004-07-15 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official version 5.42b0 of expect into + the SF sources. See details below. + + -------------------- + Alexander Doktorovich <alexander.doktorovich@ericsson.xcom> + wanted to use Expect as a filter. This is possible but 'too + hard'. To make it easier, added close_on_eof command to control + whether expect/interact automatically close the channel on eof. + This should simplify/enable other scripts. + + Kurt Heberlein <kurth@3pardata.xcom> noted that Expect would + hang. Andreas tracked it down to a change in Tcl such that when + Tcl had data left in its buffers, it would check for more data + rather than returning what it had to Expect first. If no data + was forthcoming then Tcl would hang because the pty driver runs + in blocked mode. Recoded to use nonblocking mode. + + Yi Luo <yluo@brocade.xcom> noted that multixterm xterms were + reporting the parent's X window ids (via the WINDOWID env + variable) instead of the new ones. + + Dick Van Deun <dirk@dinf.vub.ac.xbe> noted that kibitz expects + to find write in /bin but it is in /usr/bin on Slackware. Seems + safe to drop the prefix. + + Steve Lee <steve@tuxsoft.xcom> noted that building Expect failed + on Linux when built from scratch because stty ends up in + /usr/local/bin rather than the assumed /bin. Added code to + support this. + -------------------- + +2004-06-14 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c: Integrated the block mode proc I got by mail from + Don Libes into the channel driver. This fixes an error with + expect hanging on some input if the situation is just + right^Hwrong. Basically if the buffers in driver, Tcl IO core + and Expect itself are aligned just so it can cause Expect to + block in all call to the OS for more data even if all the data + it needs is in ts buffers. Because the driver is blocking and + the Tcl core was told that it can run in non-blocking mode. with + the block mode proc in place the driver knows that it should be + non-blocking and is able to tell this to the OS as well. The + call to the OS still happens, but is not blocking anymore, and + so the problem is gone. + + A number of incompat changes in the Tcl IO core to work around + this problem in Expect will be removed now. + +2004-06-03 Andreas Kupries <andreask@activestate.com> + + * aclocal.m4 (TCLHDIRDASHI): Extended with path to unix headers as + well. + * expect_tcl.h: Added inclusion of <stdio.h>. + Both changes required for Expect to compile against Tcl 8.5 + after the header reform. + * configure: Regenerated. + +2004-05-19 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official version 5.41 of expect into the + SF sources. See details below. + + -------------------- + Simon Taylor <simon@unisolve.com.xau> provided fix for interact + -o which was completely broken by 5.40.1. + + Added scroll support to official tkterm. Copied all fixes + from/to term_expect to/from tkterm. + + Kiran Madabhushi <maskiran@hotmail.xcom> encountered interact + diagnostics incorrectly pointing to expect_background. Also, + found multiple -o flags behaving unexpectedly. Added diag. + + Kristoffer Eriksson <ske@pkmab.xse> noted typo in SIMPLE code in + exp_inter.c. However, this is extremely unlikely to affect any + machines. + + Reinhard Max <max@suse.xcom> noted that "make test" failed when + run in the background. The log testcase was testing the + send_tty command. Added code in both Expect and in the test to + handle this. + -------------------- + +2004-02-25 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official version 5.40 of expect into the + SF sources. See details below. Partially already done (Rich + Kennedy's patch). + + -------------------- + Eric Raymond <esr@snark.thyrsus.xcom> provided troff-related + fixes for the expect, lib, and dislocate man pages. + + Rich Kennedy <rickenne@cisco.xcom> noted a bug having to do + with our caching of whether we have registered a filehandler. + This broke when Tcl was setting a handler on the same file. + + Ken Pizzini <ken.pizzini@explicate.xorg> provided patch for + leak in spawn error handling. + + Pete Lancashire <plancashire@columbia.xcom> noted autopasswd + example broke on Solaris which capitalized prompts. + -------------------- + +2003-10-20 Andreas Kupries <andreask@activestate.com> + + * exp_event.c (exp_get_next_event): Applied a patch made by Don + Libes in response to a bug report posted to news:comp.lang.tcl + by Rich Kennedy <rickenne@cisco.com>. Patch was posted to c.l.t + too. + + > Subject: Re: 2nd interact does not grab stdin + > Date: 17 Oct 2003 15:33:38 -0400 + > From: Don Libes <libes@nist.gov> + > Organization: National Institute of Standards and Technology + > Newsgroups: comp.lang.tcl + > References: <3F86D6F8.E535CBDE@cisco.com> + + > It's a bug - some overaggressive caching regarding stdin. A fix + > appears below. (You should also be able to avoid the problem by + > replacing the gets with expect_user.) + + > Don + + > Rich Kennedy <rickenne@cisco.com> writes: + + > > Hi, + > > + > > The following little expect script gets in trouble with second + > > 'interact' statement. The 'less' program does not get stdin + > > so it doesn't respond to typed characters... + > > + > > Is there something that must be done after the 1st interact to + > > allow the second to work correctly? (Note, you have to run + > > as a script because it works correctly if you type the commands + > > interactively to expect) + > > + > > #!/usr/local/bin/expect + > > + > > gets stdin a + > > spawn less file1 + > > interact + > > wait + > > gets stdin junk + > > spawn less file2 + > > interact + > > wait + > > + > > Thanks + > > + > > Rich Kennedy + +2003-09-05 Andreas Kupries <andreask@activestate.com> + + * Merged changes from the official version 5.39 of expect into the + SF sources. See details below. Partially already done. + + -------------------- + Poorva Gupta <poorva@cup.hp.xcom> noted that grantpt/unlockpt + order was backward. Strange that this was never a prob before! + + Eric Raymond <esr@snark.thyrsus.xcom> provided a troff-related + fix for the multixterm man page. + + Nicolas Roeser <n-roeser@gmx.xnet> noted confusion with md5 so I + made the Expect page more explicit about which file that hash + was based on. + + Josh Purinton noted that earlier fix wasn't quite right. Exit + on INT/TERM should cause Expect to exit with signal embedded in + status. He also requested I obfuscate email addresses in this + file. + + Guido Ostkamp <Guido.Ostkamp@t-online.xde> and Igor Sobrado + <sobrado@string1.ciencias.uniovi.xes> noted that fixline1 + rewrote scripts to be expect scripts even if they were expectk + scripts. + + Dirk Petera <dirkpetera@yahoo.xcom> noted that any_spawn_id used + to work but did no longer. Looks like a bug left over from the + the I18L conversion. Fixed. + + Steve Szabo noted exp_log_file -open channel failed. Fixed. + + Fixed bug from 5.31 that prevent stty from returning messages + from underlying program. + + Thomas Dickey <dickey@herndon4.his.xcom> noted that ncurses + ignores 2-char term names because of, well, poor assumptions and + coding. Changed tkterm to use longer names. + + Heath Moore <hmoore@systran.xcom> noted that exp_clib could lock + up if remtime happened to be precisely 0. Recoded to avoid. + + At request of Per Otterholm <otterholm@telia.xcom>, wrote script + to read from stdin and echo passwords (exercise 9 in Tk chapter + of Expect book). Added to example directory as passwdprompt. + + Josh Purinton <josh@purinton.xorg> pointed out that by default, + SIGINT/TERM should cause expect's return status to be 1, not 0. + + Paul Reithmuller <paul.reithmuller@eng.sun.xcom> noted that + unbuffer shouldn't postprocess its output. Added stty_init. + + Mordechai T. Abzug <morty@sanctuary.arbutus.md.xus> noted that + log_file wasn't recording -append status. + + James Kelly <macubergeek@comcast.xnet> noted weather example + needed new source. + + Dimitar Haralanov <mitko@tahoenetworks.xcom> noted that interact + dumped core with interact { timeout 1 } + -------------------- + +2003-06-16 Andreas Kupries <andreask@activestate.com> + + * exp_command.c: Applied patch provided on c.l.t., by Don Libes + <libes@nist.gov> in response to a bug report by Dirk Petera + <dirkpetera@yahoo.com> in same place. See thread reference + below: + + http://groups.google.ca/groups?threadm=4791f5a6.0305250619.1a660299%40posting.google.com + +2003-05-08 Andreas Kupries <andreask@activestate.com> + + * exp_clib.c (expectv): Applied patch provided on c.l.t., by Don + Libes <libes@nist.gov> in response to a bug report by "Heath + Moore" <hmoore@systran.com> in same place: + + > Regarding expect 5.38... + > + > I'm using libexpect on RedHat 8.0 to communicate via telnet, + > and am having problems with it locking up instead of timing + > out. Causing traffic during the lockup breaks the lockup. I + > looked at the sources, and think I may have found the reason. + > + > It appears as though i_read can be called with remtime== 0, + > which means do > one read() and return without using alarm(), + > even when exp_timeout is non-zero. This would happen if + > i_read were to return after receiving non-matching data when + > end_time == current_time. The subsequent i_read would then + > wait until it received data. + +2003-02-17 Andreas Kupries <andreask@activestate.com> + + * Makefile.in: + * configure.in: Removed the check of configure against + configure.in and Makefile.in. It is a hassle to deal with when + trying to build straight from CVS, making unsupervised automatic + builds difficult + +2003-02-14 Andreas Kupries <andreask@activestate.com> + + * configure.in: Made expect aware of tcl stubs. Derived from the + * exp_command.h: patches to expect done by Steve Landers + * exp_command.c: <stevel@digital-smarties.com>. Modifications: + * exp_main_sub.c No global cmdinfo structures for 'close' and + * exp_main_exp.c: 'return'. Made this per-interpreter information + * exp_main_tk.c: as it should be. Using interp assoc data for this. + + NOTE: stubs is not default, but has to be activated via '--enable-stubs'. + + * configure: Regenerated. + +2003-02-14 Andreas Kupries <andreask@activestate.com> + + * exp_chan.c (exp_close_all): Save the nextPtr in a local variable + before calling 'exp_close' as 'expStateFree' can be called from + it under some circumstances, possibly causing the memory + allocator to smash the value in 'esPtr'. + +2003-02-03 Andreas Kupries <andreask@activestate.com> + + * exp_log.c (expLogChannelOpen): Fixed the bug reported on + comp.lang.tcl by Mordechai T. Abzug + <morty@sanctuary.arbutus.md.us>. The bugfix itself was provided + by Don Libes. + +2002-10-09 Andreas Kupries <andreask@activestate.com> + + * exp_command.c (Exp_SpawnCmd): Tcl_GetChannelHandle expected a + ClientData*, but got an int*. sizeof(int) != sizeof(ClientData) + on 64bit platforms. Crashed the command on a PA-RISC 2.0 machine + with --enable-64bit set. Fix: Use temp. variables of type + ClientData to retrieve the fd's, and copy this into the actual + variables, with a cast to int. + +2002-09-25 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: regen'ed + * configure.in: use tcl_libdir in EXP_LIB_SPEC instead of + ${INSTALL_ROOT}${exec_prefix}/lib (steffen) + + * exp_main_tk.c (Tk_Init2): don't call XSynchronize on OS X. + +2002-08-08 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * Merged changes from the official version 5.38 of expect into the + SF sources. See details below. + + * Makefile.in: Added generation of MD5 checksum for distributed + archive. + * rftp: Bugfix by Curt Schroeder, see HISTORY + * HISTORY: Updated with new info. + * configure: Updated version info. + * configure.in: Updated version info. + +2002-06-26 David Gravereaux <davygrvy@pobox.com> + + * example/weather: Updated script to use rainmaker.wunderground.com + instead of cirrus.sprl.umich.edu. The old service is closed. + Added Larry Virden's notes about how rainmaker needs reverse DNS + from the peer making the connection or no data can retrieved. + This appears to be a blind error condition. + +2002-06-17 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * exp_main_tk.c: #ifdef'd definition of "matherr". This hack is + not required for 8.4 anymore. But still for 8.3. + +2002-03-25 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * exp_main_sub.c: Fixed typo in merge of #459646. Thanks to Hemang Lavana. + + * exp_log.c (expStdoutLogU): Merged fix for SF Bug #513382 into + the HEAD (The source of the patch is "expect-sf418892-sf439042-branch"). + + Use Tcl_WriteChars/Tcl_Flush instead of 'fwrite' for tcl 8.1 and + beyond to enforce correct conversion of the internal UTF/8 into + the external representation. + + * Merged fix for SF Bug #459646 into the HEAD (The source of the + patch is "expect-sf418892-sf439042-branch"). + + * Merged fix for SF Bug #439042 into the HEAD (The source of the + patch is "expect-sf418892-sf439042-branch"). + + * Merged fix for SF Bug #418892 into the HEAD (The source of the + patch is "expect-sf418892-sf439042-branch"). + +2002-03-23 Don Libes <libes@users.sourceforge.net> + + * Andreas Kupries mods to provide CONST support per TIP 27 (Fixed + SF Patch #525074). + +2002-02-25 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * expect.c: Applied patch by Don Libes fixing improper + internationalization. + +2002-02-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * expect.man: Changed the paragraph about [exp_continue] to + contain information about the flag "-continue_timer". This fixes + the bug SF #520630. + +2002-02-08 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * expect.man: Changed abbreviation of "-notransfer" from "-n" to + "-not". "-n" is no longer unique due to the addition of + "-nocase". This fixes the bug SF #514994. + +2002-02-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * Applied patch for SF #514590 to correct behaviour of expect when + expecting and send from and to bogus spawn id's. + +2002-01-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * Resynchronization of SourceForge with Don's sources to Expect + version 5.34. The changes are + + Don Porter <don.porter@nist.gov> provided package-related fixes + for test suite. + + Brian Theado <brian.theado@usa.net> noted that interact's -re + support broke when offsets kicked in. Turned out that the + regexp engine supports them during execution but the results are + delivered RELATIVE to the offset. (I suspect this was done + due to expediency.) + +2001-12-05 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * exp_inter.c: Applied patch posted by Don libes to c.l.t. on his + behalf to keep the SF repository in sync with his changes. Don's + notes: I obviously missed the fact that although + "Tcl_RegExpExecObj" supports offsets, they aren't delivered to + "Tcl_RegExpGetInfo". + +2001-09-12 David Gravereaux <davygrvy@pobox.com> + + * 'telco-tec-win32-branch' branch created. + +2001-08-01 Jeff Hobbs <jeffh@ActiveState.com> + + * Dbg.c (Dbg_On): fixed handling of stepping. [Bug: #446412] + +2000-04-26 Rob Savoye <rob@welcomehome.org> + + * pty_termios.h: Only include stropts.h if it exists, rather than + deciding it exists based on HAVE_PTMX. + * configure.in: Make sure libpt exists, rather than blindly using + it for all our configure tests, which then all fail. Also assume + our svr4 style ptys are broken, if /dev/ptmx exists, but stropts.h + doesn't exist. + +1999-08-31 Jennifer Hom <jenn@scriptics.com> + + * Makefile.in: Changed test target to source tests/all.tcl instead + of tests/all + + * tests/README: Modified documentation to reflect the change from + usage of a defs file to the use of package tcltest to run the tests + + * tests/all: + * tests/defs: + * tests/all.tcl: + * tests/cat.test: + * tests/expect.test: + * tests/logfile.test: + * tests/pid.test: + * tests/send.test: + * tests/spawn.test + * tests/stty.test: Modified test files to use package tcltest, + removed tests/all and tests/defs, and added tests/all.tcl + +1999-06-22 <stanton@scriptics.com> + + * expect.c: Fixed bug in token parsing where index was not being + incremented properly. + + * configure.in: Changed version number to 5.31. + + * aclocal.m4: Fixed CY_AC_LOAD_TKCONFIG so it tests for Tk_Init + instead of Tk_Main (which is only a macro in 8.1 and later). Also + added TCL_BUILD_LIB_SPEC to the set of flags used in this test to + avoid linker errors. + + * Dbgconfig.in: move CY_*_TCLCONFIG tests below AC_PROG_CC so it + will work with gcc + +Thu Mar 20 14:27:45 1997 Geoffrey Noer <noer@cygnus.com> + + * configure.in: don't check if stty reads stdout for + i[[3456]]86-*-sysv4.2MP during config; hard code instead + +Tue Nov 19 09:22:08 1996 Tom Tromey <tromey@cygnus.com> + + * Makefile.in (install_shared_lib): Put else clause onto each if. + +Fri Nov 15 11:23:43 1996 Tom Tromey <tromey@cygnus.com> + + * Makefile.in (XCFLAGS): Use EXP_SHLIB_CFLAGS, not + TCL_SHLIB_CFLAGS. + (TCL_SHLIB_CFLAGS): Define. + + * configure.in: Allow arguments to --enable-blah to work. + Compute and AC_SUBST EXP_SHLIB_CFLAGS. + Added missing AC_MSG_CHECKING. + +Wed Oct 2 10:13:37 1996 Tom Tromey <tromey@cygnus.com> + + * configure: Regenerated. + * configure.in (stty_reads_stdout): /bin/stty on DG/UX fails. + +Fri Sep 27 10:15:48 1996 Tom Tromey <tromey@creche.cygnus.com> + + * expect.c (exp_i_read): Pass interp as first arg to exp_error. + * configure.in (stty_reads_stdout): /bin/stty on OSF2.0, OSF3.2, + HPUX 9.X, HPUX 10.X guesses wrong, so set value explicitly. + +Mon Sep 9 10:29:32 1996 Tom Tromey <tromey@creche.cygnus.com> + + * configure: Regenerated. + * configure.in: Added code to actually handle --with-x. + + * configure: Regenerated. + * configure.in: Don't bother looking for Tk if --with-x=no + specified. + +Thu Sep 5 11:01:09 1996 Tom Tromey <tromey@creche.cygnus.com> + + * configure: Regenerated. + * configure.in (stty_reads_stdout): AIX fails "stty" test in + background, so set explicitly. Ditto HPUX 9 and 10. + +Thu Aug 29 17:04:55 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * configure.in (i[345]86-*-*): Recognize i686 for pentium pro. + * configure: Regenerate. + +Mon Aug 5 12:55:06 1996 Tom Tromey <tromey@creche.cygnus.com> + + * Makefile.in (XCFLAGS): New macro. + (CFLAGS): Define to just @CFLAGS@. + (CFLAGS_INT): Use $(XCFLAGS). + (expect, expect_installed, expect.tc, expectk, expectk_installed, + expectk.tc): Use $(XCFLAGS). + +Mon Feb 12 23:11:38 1996 Rob Savoye <rob@chinadoll> + + * aclocal.m4: Fix typo of ac_cv_tkh to be ac_cv_tclh so it works + on all systems. + * configure, DBGconfigure, testsuite/configure: Regenerated with + autoconf 2.7. + +Tue Feb 6 11:48:05 1996 Tom Tromey <tromey@creche.cygnus.com> + + * exp_clib.c, exp_printify.c, expect_comm.h: For Tcl 7.5 and + greater, use ../compat/stdlib.h, not compat/stdlib.h. + +Tue Jan 30 12:21:37 1996 Fred Fish <fnf@kalessin.cygnus.com> + + * exp_regexp.c (regmatch, regrepeat): Only declare strchr if it is not + a macro. + +Mon Jan 22 11:17:06 1996 Tom Tromey <tromey@creche.cygnus.com> + + * configure.in: Check for -lieee, -ldl, and -ldld. + + * Makefile.in (OFILES): Include @LIBOBJS@. + (strerror.o): New target. + + * strerror.c: New file. + + * configure.in: Test for strerror. + +Fri Jan 19 11:08:11 1996 Tom Tromey <tromey@creche.cygnus.com> + + * Makefile.in (install, ${SCRIPT_LIST}, test): Find new Tcl libraries. + +Thu Jan 18 13:43:13 1996 Tom Tromey <tromey@creche.cygnus.com> + + * Most files: Update to expect 5.19. + +Fri Jan 12 16:22:12 1996 Tom Tromey <tromey@creche.cygnus.com> + + * exp_closetcl.c (exp_close_tcl_files): Skip stdin, stdout, + stderr. + * expect_comm.h: Declare exp_close_files_interp. + * exp_command.c (exp_init_most_cmds): Set exp_close_files_interp. + +Thu Jan 11 09:43:14 1996 Tom Tromey <tromey@creche.cygnus.com> + + * exp_closetcl.c (exp_close_files_interp): New variable for Tcl + 7.5. + (exp_close_tcl_files): Updated for Tcl 7.5. + + Prototype and varargs changes: + * expect.c: Don't include <varargs.h>. + * Dbg.c: Copied in many defines from expect_comm.h. + (print): Use new varargs defines. + * exp_clib.c (exp_fexpectl): Use EXP_VARARGS_START. + * expect_comm.h: Include "tclInt.h". + * exp_console.c (exp_console_manipulation_failed): First arg to + errorlog is char*, not FILE*. + * exp_log.c (debuglog): Pass name of last argument to + EXP_VARARGS_START. + * expect_cf.h.in (tcl_AsyncReady): Removed define. + * expect.c (Exp_ExpectGlobalCmd): Added cast. + * exp_command.c (exp_i_update): First arg to exp_debuglog is + * exp_poll.c (exp_get_next_event): Likewise. + char*, not Tcl_Interp*. + * exp_log.h: Use prototypes everywhere. Include "expect_comm.h". + * expect_tcl.h: Use EXP_VARARGS, not VARARGS. + (tcl_AsyncReady): New define for Tcl 7.5. + + * aclocal.m4 (CY_AC_PATH_TCLH): Handle Tcl 7.5 and greater. + (CY_AC_PATH_TCLLIB): Handle Tcl 7.5 and greater. + (CY_AC_PATH_TKH): Handle Tk 4.1 and greater. + (CY_AC_PATH_TKLIB): Handle Tk 4.1 and greater. Properly quote + argument to AC_REQUIRE. + * configure: Regenerated. + +Tue Jan 9 16:26:47 1996 Rob Savoye <rob@chinadoll.cygnus.com> + + * Makefile.in: Change SHORT_BINDIR to $prefix, rather than + exec_prefix. This is only used to store the platform independant + expect scripts. + +Dec 18 17:22:05 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * configure.in, configure: For a solaris2 machine doing a static + build, add `-ldl -lw' to avoid unresolved refs using the + OpenWindows libraries. + +Wed Nov 22 08:49:01 1995 Rob Savoye <rob@chinadollchinadoll.cygnus.com> + + * Most files: Update to expect 5.18.1. + +Fri Nov 17 17:31:55 1995 Rob Savoye <rob@chinadoll.cygnus.com> + + * configure.in: Add support for SCO OpenServer. It doesn't like + the trap either. + +Thu Nov 16 09:28:53 1995 Rob Savoye <rob@chinadoll.cygnus.com> + + * configure.in: Use $host to get the OS type rather than trying to + get the host name ourselves. Use the $host to set the + STTY_READS_STDOUT for hosts were the test is known to fail. It + also now configures in the background. + * configure.in, Dbgconfig.in, testsuite/configure.in: Use + AC_PROG_CC again since Cygnus configure now does the sames thing. + +Mon Oct 30 18:16:48 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * configure.in (no_tk): zero out X_PROGS if we can't find tk + libraries. + +Tue Oct 24 18:25:09 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * Makefile.in (X11HDIR): Changed to X11_CFLAGS. + (X11_LIB_FLAGS): Changed to X11_LDFLAGS. + (X11_LIB): Changed to X11_LIBS. + (CPPFLAGS_SIMPLE): Use X11_CFLAGS. + (expectk, expectk.tc, tk): use X11_LDFLAGS & X11_LIBS. + + * configure.in (X11HDIR, X11_LIB_FLAGS, X11_LIB): Use X11_CFLAGS, + X11_LDFLAGS, X11_LIBS. Link X11 statically on Solaris, SunOS and + HPUX. + +Thu Oct 19 20:55:54 1995 Fred Fish <fnf@cygnus.com> + + * Makefile.in: Remove extraneous tabs and blanks in otherwise + empty lines. That confuses older non-GNU versions of "make". + +Mon Oct 9 20:58:50 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * testsuite/aclocal.m4: New file. Include ../aclocal.m4. + +Thu Aug 31 00:16:26 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * HISTORY, Makefile.in, aclocal.m4, exp_command.h, exp_inter.c, + exp_main_tk.c, exp_pty.c, expect.c, tests/all, + testsuite/Makefile.in. Update to the 5.18.0 release. Minor + changes. + +Thu Aug 17 18:47:21 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * Most files: Update to the 5.17.7 release. + +Thu Aug 3 22:47:36 1995 Jeff Law (law@snake.cs.utah.edu) + + * pty_termios.c (HAVE_PTMX): Undefine if both HAVE_PTYM and + HAVE_PTMX are defined (as happens for hpux10). + +Thu Jul 27 16:31:23 1995 J.T. Conklin <jtc@cygnus.com> + + * Makefile.in (configure): Removed rule that automatically + rebuilds configure script. Users might not have autoconf. + +Tue Jul 18 23:15:03 1995 Fred Fish <fnf@fishbowl> + + * expect.c (Exp_ExpectGlobalCmd): Cast ckrealloc first arg to char*. + +Sun Jun 18 13:02:41 1995 Fred Fish <fnf@amigalib.com> + + * configure, configure.in (XLIBS): When adding -lX11, also preserve + the previous libraries that we went to the trouble of finding. + +Sun Jun 18 12:15:44 1995 Fred Fish <fnf@amigalib.com> + + * Makefile.in (exp_clib.o): Add dependencies. + +Mon May 1 16:50:22 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * configure.in: Also set XINCLUDES in the Makefile. + +Fri Apr 28 18:56:02 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * aclocal.m4: Create a clone of AC_C_CROSS called CY_C_CROSS that + has better error handling in case the native compiler is hosed. + * aclocal.m4: Look for tcl and tk directories as just tcl (and tk) + or tcl[0-9] (and tk[0-9)] so it doesn't match the tclX + release. Print an error and exit if any of the --with-{tcl,tk}* + options are used and point to bogus paths. Based Tcl header search + on tclInt./h rather than tcl.h. + * Makefile.in: Add dependancies for back in for configure and + Dbgconfigure targets. + +Mon Apr 24 16:46:01 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * exp_command.c, exp_event.h, exp_inter.c, exp_main_tk.c, + exp_poll.c, exp_select.c, exp_simple.c, exp_tk.c, exp_trap.c, + exp_tty.c, FAQ, README, HISTORY: Update to expect 5.16.3. + +Fri Apr 14 12:00:39 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * configure.in: Copy Dbg_cf.h to objdir, not srcdir. + +Tue Apr 11 18:52:24 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * aclocal.m4: Split the macros so header and library searches are + seperate macros. AC_PATH_{TCL,TK} nows only calls the macros. Lots + of optimization to the AC_PATH_T* macros. Supports the use of + --with-tclinclude, --with-tcllib, --with-tkinclude, --with-tklib + to specify alternative search dirs for tcl and tk stuff. + * Makefile.in, testsuite/Makefile.in: Re-write targets for + configure, Dbgconfigure so they work in an unconfigured srcdir. + * configure.in: Put AC_PATH_X before AC_PATH_TK and make the TK + test conditional. Fix how Dbgconfigure gets passed the Tcl header + dir to use --with-PACKAGE which is much simpler. Removed the test + for user override of X search paths since AC_PATH_X uses. + --x-includes and --x-libraries instead. + * Dbgconfig.in: Use AC_PATH_TCLH to find just the headers, and + test for LynxOS. + * debugger/: Remove directory. Recursive configuring is so much + easier... + * DbgMkfl.in, Dbg_cf.h.in, Dbg.c, Dbg.h, Dbgconfigure, + Dbgconfig.in: Sigh, moved back to the top-level expect directory. + +Wed Apr 5 17:25:45 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * configure.in: Add a trap so the configure runs in the + background. + +Thu Mar 16 16:56:08 1995 Rob Savoye <rob@darkstar.cygnus.com> + + * debugger: New directory for the Tcl debugger. + * debugger/Dbg.c, debugger/Dbg.h, debugger/Dbg_cf.h.in: Moved from + the top level expect directory so it builds standalone. + * DbgMkfl.in, debugger/Makefile.in: Moved to debugger dir and + renamed. + * install-sh, mkinstalldirs: New files borrowed from the autoconf + distribution. + * aclocal.m4: New autoconf macros. + * Makefile.in: Tweaked so it's recursive. + * configure.in: Use new macros in aclocal.m4 rather than hunting + for the Tcl and Tk stuff ourseleves. + * debugger/Makefile.in: Build debugger standalone. + * testsuite/Makefile.in, testsuite/configure.in: New files for + autoconf support. + * exp_test.c, testsuite/exp_test.c: Move test file. + +Fri Jan 13 15:30:30 1995 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * Makefile.in (check): Pass EXPECT correctly to runtest. + +Thu Oct 20 18:04:06 1994 Rob Savoye <rob@darkstar.cygnus.com> + + * Makefile.in: Add X11_INCLUDE_FLAGS so top level flags get used + too. + +Tue Jun 14 12:32:07 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * aclocal.m4: Copy from TCL directory. + * configure.in: Improve checks for installed Tcl and Tk. + * configure: Rebuilt. + +Tue Jun 7 13:52:34 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (mostlyclean, realclean): New targets. + +Wed May 18 12:21:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (install): Add another ``else true''. + +Fri Apr 29 16:49:36 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (install): Always use else in if conditional to + avoid Ultrix sh bug. + +Mon Apr 11 15:22:12 1994 Rob Savoye (rob@cirdan.cygnus.com) + + * Upgrade to the new "official" beta release of expect 5.7. + +Wed Mar 30 17:15:28 1994 Rob Savoye (rob@cirdan.cygnus.com) + + * testsuite/expect.tests/expect-test.exp: Just run the new expect + tests and format the outout under DejaGnu. + +Mon Mar 28 14:33:55 1994 Rob Savoye (rob@cirdan.cygnus.com) + + * Upgrade to expect 5.6.3. + +Thu Dec 2 16:26:54 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * configure.in: Add tests to find Tcl and Tk headers and + libraries. + +Thu Aug 19 18:26:49 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * upgraded to version 4.7.6, add OSF/1 patches in again. + +Wed Aug 18 20:10:16 1993 Rob Savoye (rob@rtl.cygnus.com) + + * upgraded to version 4.7.4, add OSF/1 patches in again. + +Tue Aug 17 20:17:40 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * pty_termios.c, exp_command.c, configure.in: Add support for + using ptmx_bsd's if they exist. Only found on OSF/1. (patch + applied from Gregory Depp <depp@osf.org> + +Thu Jun 10 11:36:09 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * exp_main.h: fix prototype for exp_cook + +Fri Jun 4 08:55:22 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (TCLLIB): If ../tcl/libtcl.a does not exist, use + -ltcl. + +Tue May 25 14:45:12 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * Makefile.in, configure.in: Add some support for autoconfiguring + for X. + +Sun May 23 22:32:09 1993 Rob Savoye (rob at darkstar.cygnus.com) + + * exp_command.c: Fix so send_log still works when master is out of + bounds. (ok since it doesn't get used). + +Mon May 17 19:51:52 1993 Rob Savoye (rob@cygnus.com) + + * configure.in: Change test for ranlib so it kicks out "true" + rather than "@:" if it can't be found. + +Thu Apr 15 14:11:50 1993 Rob Savoye (rob@cygnus.com) + + * configure.in, Makefile.in: If using ptmx's (SVR4 style pty's) + then check for libpt.a too. + +Thu Apr 8 17:13:39 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: all doesn't depend on $(SCRIPTS). When building + $(SCRIPTS) using fixline & sources in $(srcdir), not the current + directory. When installing manpages, install from $(srcdir). + Don't install like "install foo $(bindir)" but rather "install foo + $(bindir)/foo". + +Mon Mar 22 23:56:29 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: add check & installcheck targets + +Tue Mar 2 20:28:30 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in, configure: declare SETUID to be @: instead of echo + + * pty_termios.c: declare ptynum + + * Makefile.in: a number of changes, including use of the AR and + ARFLAGS variables, the appropriate variables for X11 (as passed + down from the top level Makefile), clean up some doc lines + +Mon Mar 1 15:05:40 1993 Rob Savoye (rob at darkstar.cygnus.com) + + * configure.in, defs.h.in: Fixed problem for systems that think + getpty() should be _getpty(). + +Thu Feb 25 15:34:34 1993 Rob Savoye (rob at darkstar.cygnus.com) + + * exp_tty.h: Defines portable tty macros. + * pty_termios.c: New file, slightly based on pty_usg.c. Uses + portable macros and also supports termio. + * pty_sgttyb.c: Was pty_bsd.c. + * configure.in, Makefile.in, configure: autoconf support for + expect. + +Sun Feb 21 17:42:28 1993 Rob Savoye (rob at darkstar.cygnus.com) + + * exp_tty.h: Removed and renamed the macros to use configure's. + +Wed Feb 17 18:56:36 1993 Rob Savoye (rob at darkstar.cygnus.com) + + * expect.c, Makefile.in: Changed SIG_FN_RETURN to RETSIGTYPE + since that's what autoconf kicks out. + +Thu Dec 24 15:07:32 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: added dummy dvi target + +Wed Dec 16 11:26:16 1992 Ian Lance Taylor (ian@cygnus.com) + + * inter_select.c (init_interact): if SCO is defined, use sysconf + to get maxfds, rather than getdtablesize. + * configure.in (*-*-sco*): Use mh-sco. + * mh-sco: New file; like mh-sysv, but pass -DSCO in HDEFS. + +Tue Nov 17 14:28:20 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * config/mh-{hpux,aix,irix4,sysv*}: updated with appropriate + values for the host machine (HDEFS, RANLIB, etc) + + * configure.in: use that + + * Makefile.in: use $(HDEFS) in compiling C files + +Sun Nov 15 21:46:16 1992 Fred Fish (fnf@cygnus.com) + + * Update to base 3.24.0 release, merging back in changes made + by cygnus to 3.22.12 release. + +Sat Nov 14 20:16:26 1992 Fred Fish (fnf@cygnus.com) + + * Makefile.in (CFLAGS): Rework use of CFLAGS to fit in better with + cygnus configuration standard. + * config/mh-svr4: Removed. + * config/mh-sysv4: New file, renamed from mh-svr4. + * configure.in (*-sysv4): New configuration. + * configure.in (*-sun-solaris2, *-sysv4): Use mh-sysv4. + * expect.c (sigwinch_handler): Fix #if without any condition. + * command.c, expect.c, global.h, lib_exp.c, main.c, term.h: + Test for SYSV4 as well as SYSV3. + * inter_select.c (sys/sysconfig.h): Include when SYSV4 defined. + * inter_select.c (init_interact): Add sysconf call for SYSV4. + * pty_svr4.c (ptsname): Declare for SYSV4. + +Thu Oct 22 17:35:07 1992 Rob Savoye (rob@cygnus.com) + + * command.c: Added a "send_log" command. It only writes to a log + file if one was opened by the "log_file" command. + + * main.c: Added setbuf commands for stdin, stdout, stderr to turn + off buffering. + @@ -0,0 +1,1470 @@ +/* Dbg.c - Tcl Debugger - See cmdHelp() for commands + +Written by: Don Libes, NIST, 3/23/93 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include <stdio.h> + +#ifndef HAVE_STRCHR +#define strchr(s,c) index(s,c) +#endif /* HAVE_STRCHR */ + +#if 0 +/* tclInt.h drags in stdlib. By claiming no-stdlib, force it to drag in */ +/* Tcl's compat version. This avoids having to test for its presence */ +/* which is too tricky - configure can't generate two cf files, so when */ +/* Expect (or any app) uses the debugger, there's no way to get the info */ +/* about whether stdlib exists or not, except pointing the debugger at */ +/* an app-dependent .h file and I don't want to do that. */ +#define NO_STDLIB_H +#endif + + +#include "tclInt.h" +/*#include <varargs.h> tclInt.h drags in varargs.h. Since Pyramid */ +/* objects to including varargs.h twice, just */ +/* omit this one. */ +/*#include "string.h" tclInt.h drags this in, too! */ +#include "tcldbg.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +static int simple_interactor (Tcl_Interp *interp, ClientData data); +static int zero (Tcl_Interp *interp, char *string); + +/* most of the static variables in this file may be */ +/* moved into Tcl_Interp */ + +static Dbg_InterProc *interactor = &simple_interactor; +static ClientData interdata = 0; +static Dbg_IgnoreFuncsProc *ignoreproc = &zero; +static Dbg_OutputProc *printproc = 0; +static ClientData printdata = 0; +static int stdinmode; + +static void print _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); + +static int debugger_active = FALSE; + +/* this is not externally documented anywhere as of yet */ +char *Dbg_VarName = "dbg"; + +#define DEFAULT_COMPRESS 0 +static int compress = DEFAULT_COMPRESS; +#define DEFAULT_WIDTH 75 /* leave a little space for printing */ + /* stack level */ +static int buf_width = DEFAULT_WIDTH; + +static int main_argc = 1; +static char *default_argv = "application"; +static char **main_argv = &default_argv; + +static Tcl_Trace debug_handle; +static int step_count = 1; /* count next/step */ + +#define FRAMENAMELEN 10 /* enough to hold strings like "#4" */ +static char viewFrameName[FRAMENAMELEN];/* destination frame name for up/down */ + +static CallFrame *goalFramePtr; /* destination for next/return */ +static int goalNumLevel; /* destination for Next */ + +static enum debug_cmd { + none, step, next, ret, cont, up, down, where, Next +} debug_cmd = step; + +/* info about last action to use as a default */ +static enum debug_cmd last_action_cmd = next; +static int last_step_count = 1; + +/* this acts as a strobe (while testing breakpoints). It is set to true */ +/* every time a new debugger command is issued that is an action */ +static int debug_new_action; + +#define NO_LINE -1 /* if break point is not set by line number */ + +struct breakpoint { + int id; + Tcl_Obj *file; /* file where breakpoint is */ + int line; /* line where breakpoint is */ + int re; /* 1 if this is regexp pattern */ + Tcl_Obj *pat; /* pattern defining where breakpoint can be */ + Tcl_Obj *expr; /* expr to trigger breakpoint */ + Tcl_Obj *cmd; /* cmd to eval at breakpoint */ + struct breakpoint *next, *previous; +}; + +static struct breakpoint *break_base = 0; +static int breakpoint_max_id = 0; + +static struct breakpoint * +breakpoint_new() +{ + struct breakpoint *b = (struct breakpoint *)ckalloc(sizeof(struct breakpoint)); + if (break_base) break_base->previous = b; + b->next = break_base; + b->previous = 0; + b->id = breakpoint_max_id++; + b->file = 0; + b->line = NO_LINE; + b->pat = 0; + b->re = 0; + b->expr = 0; + b->cmd = 0; + break_base = b; + return(b); +} + +static +void +breakpoint_print(interp,b) +Tcl_Interp *interp; +struct breakpoint *b; +{ + print(interp,"breakpoint %d: ",b->id); + + if (b->re) { + print(interp,"-re \"%s\" ",Tcl_GetString(b->pat)); + } else if (b->pat) { + print(interp,"-glob \"%s\" ",Tcl_GetString(b->pat)); + } else if (b->line != NO_LINE) { + if (b->file) { + print(interp,"%s:",Tcl_GetString(b->file)); + } + print(interp,"%d ",b->line); + } + + if (b->expr) + print(interp,"if {%s} ",Tcl_GetString(b->expr)); + + if (b->cmd) + print(interp,"then {%s}",Tcl_GetString(b->cmd)); + + print(interp,"\n"); +} + +static void +save_re_matches(interp, re, objPtr) +Tcl_Interp *interp; +Tcl_RegExp re; +Tcl_Obj *objPtr; +{ + Tcl_RegExpInfo info; + int i, start; + char name[20]; + + Tcl_RegExpGetInfo(re, &info); + for (i=0;i<=info.nsubs;i++) { + start = info.matches[i].start; + /* end = info.matches[i].end-1;*/ + + if (start == -1) continue; + + sprintf(name,"%d",i); + Tcl_SetVar2Ex(interp, Dbg_VarName, name, Tcl_GetRange(objPtr, + info.matches[i].start, info.matches[i].end-1), 0); + } +} + +/* return 1 to break, 0 to continue */ +static int +breakpoint_test(interp,cmd,bp) +Tcl_Interp *interp; +char *cmd; /* command about to be executed */ +struct breakpoint *bp; /* breakpoint to test */ +{ + if (bp->re) { + int found = 0; + Tcl_Obj *cmdObj; + Tcl_RegExp re = Tcl_GetRegExpFromObj(NULL, bp->pat, + TCL_REG_ADVANCED); + cmdObj = Tcl_NewStringObj(cmd,-1); + Tcl_IncrRefCount(cmdObj); + if (Tcl_RegExpExecObj(NULL, re, cmdObj, 0 /* offset */, + -1 /* nmatches */, 0 /* eflags */) > 0) { + save_re_matches(interp, re, cmdObj); + found = 1; + } + Tcl_DecrRefCount(cmdObj); + if (!found) return 0; + } else if (bp->pat) { + if (0 == Tcl_StringMatch(cmd, + Tcl_GetString(bp->pat))) return 0; + } else if (bp->line != NO_LINE) { + /* not yet implemented - awaiting support from Tcl */ + return 0; + } + + if (bp->expr) { + int value; + + /* ignore errors, since they are likely due to */ + /* simply being out of scope a lot */ + if (TCL_OK != Tcl_ExprBooleanObj(interp,bp->expr,&value) + || (value == 0)) return 0; + } + + if (bp->cmd) { + Tcl_EvalObjEx(interp, bp->cmd, 0); + } else { + breakpoint_print(interp,bp); + } + + return 1; +} + +static char *already_at_top_level = "already at top level"; + +/* similar to TclGetFrame but takes two frame ptrs and a direction. +If direction is up, search up stack from curFrame +If direction is down, simulate searching down stack by + seaching up stack from origFrame +*/ +static +int +TclGetFrame2(interp, origFramePtr, string, framePtrPtr, dir) + Tcl_Interp *interp; + CallFrame *origFramePtr; /* frame that is true top-of-stack */ + char *string; /* String describing frame. */ + CallFrame **framePtrPtr; /* Store pointer to frame here (or NULL + * if global frame indicated). */ + enum debug_cmd dir; /* look up or down the stack */ +{ + Interp *iPtr = (Interp *) interp; + int level, result; + CallFrame *framePtr; /* frame currently being searched */ + + CallFrame *curFramePtr = iPtr->varFramePtr; + + /* + * Parse string to figure out which level number to go to. + */ + + result = 1; + if (*string == '#') { + if (Tcl_GetInt(interp, string+1, &level) != TCL_OK) { + return TCL_ERROR; + } + if (level < 0) { + levelError: + Tcl_AppendResult(interp, "bad level \"", string, "\"", + (char *) NULL); + return TCL_ERROR; + } + framePtr = origFramePtr; /* start search here */ + + } else if (isdigit(*string)) { + if (Tcl_GetInt(interp, string, &level) != TCL_OK) { + return TCL_ERROR; + } + if (dir == up) { + if (curFramePtr == 0) { + Tcl_SetResult(interp,already_at_top_level,TCL_STATIC); + return TCL_ERROR; + } + level = curFramePtr->level - level; + framePtr = curFramePtr; /* start search here */ + } else { + if (curFramePtr != 0) { + level = curFramePtr->level + level; + } + framePtr = origFramePtr; /* start search here */ + } + } else { + level = curFramePtr->level - 1; + result = 0; + } + + /* + * Figure out which frame to use. + */ + + if (level == 0) { + framePtr = NULL; + } else { + for (;framePtr != NULL; framePtr = framePtr->callerVarPtr) { + if (framePtr->level == level) { + break; + } + } + if (framePtr == NULL) { + goto levelError; + } + } + *framePtrPtr = framePtr; + return result; +} + + +static char *printify(s) +char *s; +{ + static int destlen = 0; + char *d; /* ptr into dest */ + unsigned int need; + static char buf_basic[DEFAULT_WIDTH+1]; + static char *dest = buf_basic; + Tcl_UniChar ch; + + if (s == 0) return("<null>"); + + /* worst case is every character takes 4 to printify */ + need = strlen(s)*6; + if (need > destlen) { + if (dest && (dest != buf_basic)) ckfree(dest); + dest = (char *)ckalloc(need+1); + destlen = need; + } + + for (d = dest;*s;) { + s += Tcl_UtfToUniChar(s, &ch); + if (ch == '\b') { + strcpy(d,"\\b"); d += 2; + } else if (ch == '\f') { + strcpy(d,"\\f"); d += 2; + } else if (ch == '\v') { + strcpy(d,"\\v"); d += 2; + } else if (ch == '\r') { + strcpy(d,"\\r"); d += 2; + } else if (ch == '\n') { + strcpy(d,"\\n"); d += 2; + } else if (ch == '\t') { + strcpy(d,"\\t"); d += 2; + } else if ((unsigned)ch < 0x20) { /* unsigned strips parity */ + sprintf(d,"\\%03o",ch); d += 4; + } else if (ch == 0177) { + strcpy(d,"\\177"); d += 4; + } else if ((ch < 0x80) && isprint(UCHAR(ch))) { + *d = (char)ch; d += 1; + } else { + sprintf(d,"\\u%04x",ch); d += 6; + } + } + *d = '\0'; + return(dest); +} + +static +char * +print_argv(interp,argc,argv) +Tcl_Interp *interp; +int argc; +char *argv[]; +{ + static int buf_width_max = DEFAULT_WIDTH; + static char buf_basic[DEFAULT_WIDTH+1]; /* basic buffer */ + static char *buf = buf_basic; + int space; /* space remaining in buf */ + int len; + char *bufp; + int proc; /* if current command is "proc" */ + int arg_index; + + if (buf_width > buf_width_max) { + if (buf && (buf != buf_basic)) ckfree(buf); + buf = (char *)ckalloc(buf_width + 1); + buf_width_max = buf_width; + } + + proc = (0 == strcmp("proc",argv[0])); + sprintf(buf,"%.*s",buf_width,argv[0]); + len = strlen(buf); + space = buf_width - len; + bufp = buf + len; + argc--; argv++; + arg_index = 1; + + while (argc && (space > 0)) { + CONST char *elementPtr; + CONST char *nextPtr; + int wrap; + + /* braces/quotes have been stripped off arguments */ + /* so put them back. We wrap everything except lists */ + /* with one argument. One exception is to always wrap */ + /* proc's 2nd arg (the arg list), since people are */ + /* used to always seeing it this way. */ + + if (proc && (arg_index > 1)) wrap = TRUE; + else { + (void) TclFindElement(interp,*argv, +#if TCL_MAJOR_VERSION >= 8 + -1, +#endif + &elementPtr,&nextPtr,(int *)0,(int *)0); + if (*elementPtr == '\0') wrap = TRUE; + else if (*nextPtr == '\0') wrap = FALSE; + else wrap = TRUE; + } + + /* wrap lists (or null) in braces */ + if (wrap) { + sprintf(bufp," {%.*s}",space-3,*argv); + } else { + sprintf(bufp," %.*s",space-1,*argv); + } + len = strlen(buf); + space = buf_width - len; + bufp = buf + len; + argc--; argv++; + arg_index++; + } + + if (compress) { + /* this copies from our static buf to printify's static buf */ + /* and back to our static buf */ + strncpy(buf,printify(buf),buf_width); + } + + /* usually but not always right, but assume truncation if buffer is */ + /* full. this avoids tiny but odd-looking problem of appending "}" */ + /* to truncated lists during {}-wrapping earlier */ + if (strlen(buf) == buf_width) { + buf[buf_width-1] = buf[buf_width-2] = buf[buf_width-3] = '.'; + } + + return(buf); +} + +#if TCL_MAJOR_VERSION >= 8 +static +char * +print_objv(interp,objc,objv) +Tcl_Interp *interp; +int objc; +Tcl_Obj *objv[]; +{ + char **argv; + int argc; + int len; + argv = (char **)ckalloc(objc+1 * sizeof(char *)); + for (argc=0 ; argc<objc ; argc++) { + argv[argc] = Tcl_GetStringFromObj(objv[argc],&len); + } + argv[argc] = NULL; + return(print_argv(interp,argc,argv)); +} +#endif + +static +void +PrintStackBelow(interp,curf,viewf) +Tcl_Interp *interp; +CallFrame *curf; /* current FramePtr */ +CallFrame *viewf; /* view FramePtr */ +{ + char ptr; /* graphically indicate where we are in the stack */ + + /* indicate where we are in the stack */ + ptr = ((curf == viewf)?'*':' '); + + if (curf == 0) { + print(interp,"%c0: %s\n", + ptr,print_argv(interp,main_argc,main_argv)); + } else { + PrintStackBelow(interp,curf->callerVarPtr,viewf); + print(interp,"%c%d: %s\n",ptr,curf->level, +#if TCL_MAJOR_VERSION >= 8 + print_objv(interp,curf->objc,curf->objv) +#else + print_argv(interp,curf->argc,curf->argv) +#endif + ); + } +} + +static +void +PrintStack(interp,curf,viewf,objc,objv,level) +Tcl_Interp *interp; +CallFrame *curf; /* current FramePtr */ +CallFrame *viewf; /* view FramePtr */ + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +char *level; +{ + PrintStackBelow(interp,curf,viewf); + print(interp," %s: %s\n",level,print_objv(interp,objc,objv)); +} + +/* return 0 if goal matches current frame or goal can't be found */ +/* anywere in frame stack */ +/* else return 1 */ +/* This catches things like a proc called from a Tcl_Eval which in */ +/* turn was not called from a proc but some builtin such as source */ +/* or Tcl_Eval. These builtin calls to Tcl_Eval lose any knowledge */ +/* the FramePtr from the proc, so we have to search the entire */ +/* stack frame to see if it's still there. */ +static int +GoalFrame(goal,iptr) +CallFrame *goal; +Interp *iptr; +{ + CallFrame *cf = iptr->varFramePtr; + + /* if at current level, return success immediately */ + if (goal == cf) return 0; + + while (cf) { + cf = cf->callerVarPtr; + if (goal == cf) { + /* found, but since it's above us, fail */ + return 1; + } + } + return 0; +} + +#if 0 +static char *cmd_print(cmdtype) +enum debug_cmd cmdtype; +{ + switch (cmdtype) { + case none: return "cmd: none"; + case step: return "cmd: step"; + case next: return "cmd: next"; + case ret: return "cmd: ret"; + case cont: return "cmd: cont"; + case up: return "cmd: up"; + case down: return "cmd: down"; + case where: return "cmd: where"; + case Next: return "cmd: Next"; + } + return "cmd: Unknown"; +} +#endif + +/* debugger's trace handler */ + +static int +debugger_trap _ANSI_ARGS_ (( + ClientData clientData, + Tcl_Interp *interp, + int level, + CONST char *command, + Tcl_Command commandInfo, + int objc, + struct Tcl_Obj * CONST * objv)); + + +/*ARGSUSED*/ +static int +debugger_trap(clientData,interp,level,command,commandInfo,objc,objv) + ClientData clientData; /* not used */ + Tcl_Interp *interp; + int level; /* positive number if called by Tcl, -1 if */ + /* called by Dbg_On in which case we don't */ + /* know the level */ + CONST char *command; + Tcl_Command commandInfo; /* Unused */ + int objc; + struct Tcl_Obj * CONST * objv; +{ + char level_text[6]; /* textual representation of level */ + + int break_status; + Interp *iPtr = (Interp *)interp; + + CallFrame *trueFramePtr; /* where the pc is */ + CallFrame *viewFramePtr; /* where up/down are */ + + int print_command_first_time = TRUE; + static int debug_suspended = FALSE; + + struct breakpoint *b; + + char* thecmd; + + /* skip commands that are invoked interactively */ + if (debug_suspended) return TCL_OK; + + thecmd = Tcl_GetString (objv[0]); + /* skip debugger commands */ + if (thecmd[1] == '\0') { + switch (thecmd[0]) { + case 'n': + case 's': + case 'c': + case 'r': + case 'w': + case 'b': + case 'u': + case 'd': return TCL_OK; + } + } + + if ((*ignoreproc)(interp,thecmd)) return TCL_OK; + + /* if level is unknown, use "?" */ + sprintf(level_text,(level == -1)?"?":"%d",level); + + /* save so we can restore later */ + trueFramePtr = iPtr->varFramePtr; + + /* do not allow breaking while testing breakpoints */ + debug_suspended = TRUE; + + /* test all breakpoints to see if we should break */ + /* if any successful breakpoints, start interactor */ + debug_new_action = FALSE; /* reset strobe */ + break_status = FALSE; /* no successful breakpoints yet */ + for (b = break_base;b;b=b->next) { + break_status |= breakpoint_test(interp,command,b); + } + if (break_status) { + if (!debug_new_action) { + goto start_interact; + } + + /* if s or n triggered by breakpoint, make "s 1" */ + /* (and so on) refer to next command, not this one */ + /* step_count++;*/ + goto end_interact; + } + + switch (debug_cmd) { + case cont: + goto finish; + case step: + step_count--; + if (step_count > 0) goto finish; + goto start_interact; + case next: + /* check if we are back at the same level where the next */ + /* command was issued. Also test */ + /* against all FramePtrs and if no match, assume that */ + /* we've missed a return, and so we should break */ +/* if (goalFramePtr != iPtr->varFramePtr) goto finish;*/ + if (GoalFrame(goalFramePtr,iPtr)) goto finish; + step_count--; + if (step_count > 0) goto finish; + goto start_interact; + case Next: + /* check if we are back at the same level where the next */ + /* command was issued. */ + if (goalNumLevel < iPtr->numLevels) goto finish; + step_count--; + if (step_count > 0) goto finish; + goto start_interact; + case ret: + /* same comment as in "case next" */ + if (goalFramePtr != iPtr->varFramePtr) goto finish; + goto start_interact; + /* DANGER: unhandled cases! none, up, down, where */ + } + +start_interact: + if (print_command_first_time) { + print(interp,"%s: %s\n", + level_text,print_argv(interp,1,&command)); + print_command_first_time = FALSE; + } + /* since user is typing a command, don't interrupt it immediately */ + debug_cmd = cont; + debug_suspended = TRUE; + + /* interactor won't return until user gives a debugger cmd */ + (*interactor)(interp,interdata); +end_interact: + + /* save this so it can be restored after "w" command */ + viewFramePtr = iPtr->varFramePtr; + + if (debug_cmd == up || debug_cmd == down) { + /* calculate new frame */ + if (-1 == TclGetFrame2(interp,trueFramePtr,viewFrameName, + &iPtr->varFramePtr,debug_cmd)) { + print(interp,"%s\n",Tcl_GetStringResult (interp)); + Tcl_ResetResult(interp); + } + goto start_interact; + } + + /* reset view back to normal */ + iPtr->varFramePtr = trueFramePtr; + +#if 0 + /* allow trapping */ + debug_suspended = FALSE; +#endif + + switch (debug_cmd) { + case cont: + case step: + goto finish; + case next: + goalFramePtr = iPtr->varFramePtr; + goto finish; + case Next: + goalNumLevel = iPtr->numLevels; + goto finish; + case ret: + goalFramePtr = iPtr->varFramePtr; + if (goalFramePtr == 0) { + print(interp,"nowhere to return to\n"); + break; + } + goalFramePtr = goalFramePtr->callerVarPtr; + goto finish; + case where: + PrintStack(interp,iPtr->varFramePtr,viewFramePtr,objc,objv,level_text); + break; + } + + /* restore view and restart interactor */ + iPtr->varFramePtr = viewFramePtr; + goto start_interact; + + finish: + debug_suspended = FALSE; + return TCL_OK; +} + +/*ARGSUSED*/ +static +int +cmdNext(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + debug_new_action = TRUE; + debug_cmd = *(enum debug_cmd *)clientData; + + last_action_cmd = debug_cmd; + + if (objc == 1) { + step_count = 1; + } else if (TCL_OK != Tcl_GetIntFromObj (interp, objv[1], &step_count)) { + return TCL_ERROR; + } + + last_step_count = step_count; + return(TCL_RETURN); +} + +/*ARGSUSED*/ +static +int +cmdDir(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + char* frame; + debug_cmd = *(enum debug_cmd *)clientData; + + if (objc == 1) { + frame = "1"; + } else { + frame = Tcl_GetString (objv[1]); + } + + strncpy(viewFrameName,frame,FRAMENAMELEN); + return TCL_RETURN; +} + +/*ARGSUSED*/ +static +int +cmdSimple(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + debug_new_action = TRUE; + debug_cmd = *(enum debug_cmd *)clientData; + last_action_cmd = debug_cmd; + + return TCL_RETURN; +} + +static +void +breakpoint_destroy(b) +struct breakpoint *b; +{ + if (b->file) Tcl_DecrRefCount(b->file); + if (b->pat) Tcl_DecrRefCount(b->pat); + if (b->cmd) Tcl_DecrRefCount(b->cmd); + if (b->expr) Tcl_DecrRefCount(b->expr); + + /* unlink from chain */ + if ((b->previous == 0) && (b->next == 0)) { + break_base = 0; + } else if (b->previous == 0) { + break_base = b->next; + b->next->previous = 0; + } else if (b->next == 0) { + b->previous->next = 0; + } else { + b->previous->next = b->next; + b->next->previous = b->previous; + } + + ckfree((char *)b); +} + +static void +savestr(objPtr,str) +Tcl_Obj **objPtr; +char *str; +{ + *objPtr = Tcl_NewStringObj(str, -1); + Tcl_IncrRefCount(*objPtr); +} + +/*ARGSUSED*/ +static +int +cmdWhere(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + static char* options [] = { + "-compress", + "-width", + NULL + }; + enum options { + WHERE_COMPRESS, + WHERE_WIDTH + }; + int i; + + if (objc == 1) { + debug_cmd = where; + return TCL_RETURN; + } + + /* Check and process switches */ + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case WHERE_COMPRESS: + i++; + if (i >= objc) { + print(interp,"%d\n",compress); + break; + } + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[i], &buf_width)) + goto usage; + break; + case WHERE_WIDTH: + i++; + if (i >= objc) { + print(interp,"%d\n",buf_width); + break; + } + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &buf_width)) + goto usage; + break; + } + } + + if (i < objc) goto usage; + + return TCL_OK; + + usage: + print(interp,"usage: w [-width #] [-compress 0|1]\n"); + return TCL_ERROR; +} + +#define breakpoint_fail(msg) {error_msg = msg; goto break_fail;} + +/*ARGSUSED*/ +static +int +cmdBreak(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + struct breakpoint *b; + char *error_msg; + + static char* options [] = { + "-glob", + "-regexp", + "if", + "then", + NULL + }; + enum options { + BREAK_GLOB, + BREAK_RE, + BREAK_IF, + BREAK_THEN + }; + int i; + int index; + + + /* No arguments, list breakpoints */ + if (objc == 1) { + for (b = break_base;b;b=b->next) breakpoint_print(interp,b); + return(TCL_OK); + } + + /* Process breakpoint deletion (-, -x) */ + + /* Copied from exp_prog.h */ +#define streq(x,y) (0 == strcmp((x),(y))) + + if (objc == 2) { + int id; + + if (streq (Tcl_GetString (objv[1]),"-")) { + while (break_base) { + breakpoint_destroy(break_base); + } + breakpoint_max_id = 0; + return(TCL_OK); + } + + if ((Tcl_GetString (objv[1])[0] == '-') && + (TCL_OK == Tcl_GetIntFromObj (interp, objv[1], &id))) { + id = -id; + + for (b = break_base;b;b=b->next) { + if (b->id == id) { + breakpoint_destroy(b); + if (!break_base) breakpoint_max_id = 0; + return(TCL_OK); + } + } + Tcl_SetResult(interp,"no such breakpoint",TCL_STATIC); + return(TCL_ERROR); + } + } + + b = breakpoint_new(); + + /* Process switches */ + + i = 1; + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) == TCL_OK) { + switch ((enum options) index) { + case BREAK_GLOB: + i++; + if (i == objc) breakpoint_fail("no pattern?"); + savestr(&b->pat,Tcl_GetString (objv[i])); + i++; + break; + case BREAK_RE: + i++; + if (i == objc) breakpoint_fail("bad regular expression"); + b->re = 1; + savestr(&b->pat,Tcl_GetString (objv[i])); + if (Tcl_GetRegExpFromObj(interp, b->pat, TCL_REG_ADVANCED) == NULL) { + breakpoint_destroy(b); + return TCL_ERROR; + } + i++; + break; + case BREAK_IF: break; + case BREAK_THEN: break; + } + } else { + /* look for [file:]line */ + char *colon; + char *linep; /* pointer to beginning of line number */ + char* ref = Tcl_GetString (objv[i]); + colon = strchr(ref,':'); + if (colon) { + *colon = '\0'; + savestr(&b->file,ref); + *colon = ':'; + linep = colon + 1; + } else { + linep = ref; + /* get file from current scope */ + /* savestr(&b->file, ?); */ + } + + if (TCL_OK == Tcl_GetInt(interp,linep,&b->line)) { + i++; + print(interp,"setting breakpoints by line number is currently unimplemented - use patterns or expressions\n"); + } else { + /* not an int? - unwind & assume it is an expression */ + + if (b->file) Tcl_DecrRefCount(b->file); + } + + } + + if (i < objc) { + int do_if = FALSE; + + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) == TCL_OK) { + switch ((enum options) index) { + case BREAK_IF: + i++; + do_if = TRUE; + /* Consider next word as expression */ + break; + case BREAK_THEN: + /* No 'if expression' guard here, do nothing */ + break; + case BREAK_GLOB: + case BREAK_RE: + do_if = TRUE; + /* Consider current word as expression, without a preceding 'if' */ + break; + } + } else { + /* Consider current word as expression, without a preceding 'if' */ + do_if = TRUE; + } + + if (do_if) { + if (i == objc) breakpoint_fail("if what"); + savestr(&b->expr,Tcl_GetString (objv[i])); + i++; + } + } + + if (i < objc) { + /* Remainder is a command */ + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) == TCL_OK) { + switch ((enum options) index) { + case BREAK_THEN: + i++; + break; + case BREAK_IF: + case BREAK_GLOB: + case BREAK_RE: + break; + } + } + + if (i == objc) breakpoint_fail("then what?"); + + savestr(&b->cmd,Tcl_GetString (objv[i])); + } + + Tcl_SetObjResult (interp, Tcl_NewIntObj (b->id)); + return(TCL_OK); + + break_fail: + breakpoint_destroy(b); + Tcl_SetResult(interp,error_msg,TCL_STATIC); + return(TCL_ERROR); +} + +static char *help[] = { +"s [#] step into procedure", +"n [#] step over procedure", +"N [#] step over procedures, commands, and arguments", +"c continue", +"r continue until return to caller", +"u [#] move scope up level", +"d [#] move scope down level", +" go to absolute frame if # is prefaced by \"#\"", +"w show stack (\"where\")", +"w -w [#] show/set width", +"w -c [0|1] show/set compress", +"b show breakpoints", +"b [-r regexp-pattern] [if expr] [then command]", +"b [-g glob-pattern] [if expr] [then command]", +"b [[file:]#] [if expr] [then command]", +" if pattern given, break if command resembles pattern", +" if # given, break on line #", +" if expr given, break if expr true", +" if command given, execute command at breakpoint", +"b -# delete breakpoint", +"b - delete all breakpoints", +0}; + +/*ARGSUSED*/ +static +int +cmdHelp(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + char **hp; + + for (hp=help;*hp;hp++) { + print(interp,"%s\n",*hp); + } + + return(TCL_OK); +} + +/* occasionally, we print things larger buf_max but not by much */ +/* see print statements in PrintStack routines for examples */ +#define PAD 80 + +/*VARARGS*/ +static void +print TCL_VARARGS_DEF(Tcl_Interp *,arg1) +{ + Tcl_Interp *interp; + char *fmt; + va_list args; + + interp = TCL_VARARGS_START(Tcl_Interp *,arg1,args); + fmt = va_arg(args,char *); + if (!printproc) vprintf(fmt,args); + else { + static int buf_width_max = DEFAULT_WIDTH+PAD; + static char buf_basic[DEFAULT_WIDTH+PAD+1]; + static char *buf = buf_basic; + + if (buf_width+PAD > buf_width_max) { + if (buf && (buf != buf_basic)) ckfree(buf); + buf = (char *)ckalloc(buf_width+PAD+1); + buf_width_max = buf_width+PAD; + } + + vsprintf(buf,fmt,args); + (*printproc)(interp,buf,printdata); + } + va_end(args); +} + +/*ARGSUSED*/ +Dbg_InterStruct +Dbg_Interactor(interp,inter_proc,data) +Tcl_Interp *interp; +Dbg_InterProc *inter_proc; +ClientData data; +{ + Dbg_InterStruct tmp; + + tmp.func = interactor; + tmp.data = interdata; + interactor = (inter_proc?inter_proc:simple_interactor); + interdata = data; + return tmp; +} + +/*ARGSUSED*/ +Dbg_IgnoreFuncsProc * +Dbg_IgnoreFuncs(interp,proc) +Tcl_Interp *interp; +Dbg_IgnoreFuncsProc *proc; +{ + Dbg_IgnoreFuncsProc *tmp = ignoreproc; + ignoreproc = (proc?proc:zero); + return tmp; +} + +/*ARGSUSED*/ +Dbg_OutputStruct +Dbg_Output(interp,proc,data) +Tcl_Interp *interp; +Dbg_OutputProc *proc; +ClientData data; +{ + Dbg_OutputStruct tmp; + + tmp.func = printproc; + tmp.data = printdata; + printproc = proc; + printdata = data; + return tmp; +} + +/*ARGSUSED*/ +int +Dbg_Active(interp) +Tcl_Interp *interp; +{ + return debugger_active; +} + +char ** +Dbg_ArgcArgv(argc,argv,copy) +int argc; +char *argv[]; +int copy; +{ + char **alloc; + + main_argc = argc; + + if (!copy) { + main_argv = argv; + alloc = 0; + } else { + main_argv = alloc = (char **)ckalloc((argc+1)*sizeof(char *)); + while (argc-- >= 0) { + *main_argv++ = *argv++; + } + main_argv = alloc; + } + return alloc; +} + +static struct cmd_list { + char *cmdname; + Tcl_ObjCmdProc *cmdproc; + enum debug_cmd cmdtype; +} cmd_list[] = { + {"n", cmdNext, next}, + {"s", cmdNext, step}, + {"N", cmdNext, Next}, + {"c", cmdSimple, cont}, + {"r", cmdSimple, ret}, + {"w", cmdWhere, none}, + {"b", cmdBreak, none}, + {"u", cmdDir, up}, + {"d", cmdDir, down}, + {"h", cmdHelp, none}, + {0} +}; + +/* this may seem excessive, but this avoids the explicit test for non-zero */ +/* in the caller, and chances are that that test will always be pointless */ +/*ARGSUSED*/ +static int +zero (Tcl_Interp *interp, char *string) +{ + return 0; +} + +extern int expSetBlockModeProc _ANSI_ARGS_((int fd, int mode)); + +static int +simple_interactor(Tcl_Interp *interp, ClientData data) +{ + int rc; + char *ccmd; /* pointer to complete command */ + char line[BUFSIZ+1]; /* space for partial command */ + int newcmd = TRUE; + Interp *iPtr = (Interp *)interp; + + Tcl_DString dstring; + Tcl_DStringInit(&dstring); + + /* Force blocking if necessary */ + + if (stdinmode == TCL_MODE_NONBLOCKING) { + expSetBlockModeProc(0, TCL_MODE_BLOCKING); + } + + newcmd = TRUE; + while (TRUE) { + struct cmd_list *c; + + if (newcmd) { +#if TCL_MAJOR_VERSION < 8 + print(interp,"dbg%d.%d> ",iPtr->numLevels,iPtr->curEventNum+1); +#else + /* unncessarily tricky coding - if nextid + isn't defined, maintain our own static + version */ + + static int nextid = 0; + CONST char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0); + if (nextidstr) { + sscanf(nextidstr,"%d",&nextid); + } + print(interp,"dbg%d.%d> ",iPtr->numLevels,nextid++); +#endif + } else { + print(interp,"dbg+> "); + } + fflush(stdout); + + rc = read(0,line,BUFSIZ); + if (0 >= rc) { + if (!newcmd) line[0] = 0; + else exit(0); + } else line[rc] = '\0'; + + ccmd = Tcl_DStringAppend(&dstring,line,rc); + if (!Tcl_CommandComplete(ccmd)) { + newcmd = FALSE; + continue; /* continue collecting command */ + } + newcmd = TRUE; + + /* if user pressed return with no cmd, use previous one */ + if ((ccmd[0] == '\n' || ccmd[0] == '\r') && ccmd[1] == '\0') { + + /* this loop is guaranteed to exit through break */ + for (c = cmd_list;c->cmdname;c++) { + if (c->cmdtype == last_action_cmd) break; + } + + /* recreate textual version of command */ + Tcl_DStringAppend(&dstring,c->cmdname,-1); + + if (c->cmdtype == step || + c->cmdtype == next || + c->cmdtype == Next) { + char num[10]; + + sprintf(num," %d",last_step_count); + Tcl_DStringAppend(&dstring,num,-1); + } + } + +#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION < 4 + rc = Tcl_RecordAndEval(interp,ccmd,0); +#else + rc = Tcl_RecordAndEval(interp,ccmd,TCL_NO_EVAL); + rc = Tcl_Eval(interp,ccmd); +#endif + Tcl_DStringFree(&dstring); + + switch (rc) { + case TCL_OK: + { + char* res = Tcl_GetStringResult (interp); + if (*res != 0) + print(interp,"%s\n",res); + } + continue; + case TCL_ERROR: + print(interp,"%s\n",Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY)); + /* since user is typing by hand, we expect lots + of errors, and want to give another chance */ + continue; + case TCL_BREAK: + case TCL_CONTINUE: +#define finish(x) {rc = x; goto done;} + finish(rc); + case TCL_RETURN: + finish(TCL_OK); + default: + /* note that ccmd has trailing newline */ + print(interp,"error %d: %s\n",rc,ccmd); + continue; + } + } + /* cannot fall thru here, must jump to label */ + done: + Tcl_DStringFree(&dstring); + + /* Restore old blocking mode */ + if (stdinmode == TCL_MODE_NONBLOCKING) { + expSetBlockModeProc(0, TCL_MODE_NONBLOCKING); + } + return(rc); +} + +static char init_auto_path[] = "lappend auto_path $dbg_library"; + +static void +init_debugger(interp) +Tcl_Interp *interp; +{ + struct cmd_list *c; + + for (c = cmd_list;c->cmdname;c++) { + Tcl_CreateObjCommand(interp,c->cmdname,c->cmdproc, + (ClientData)&c->cmdtype,(Tcl_CmdDeleteProc *)0); + } + + debug_handle = Tcl_CreateObjTrace(interp,10000,0, + debugger_trap,(ClientData)0, NULL); + + debugger_active = TRUE; + Tcl_SetVar2(interp,Dbg_VarName,"active","1",0); +#ifdef DBG_SCRIPTDIR + Tcl_SetVar(interp,"dbg_library",DBG_SCRIPTDIR,0); +#endif + Tcl_Eval(interp,init_auto_path); + +} + +/* allows any other part of the application to jump to the debugger */ +/*ARGSUSED*/ +void +Dbg_On(interp,immediate) +Tcl_Interp *interp; +int immediate; /* if true, stop immediately */ + /* should only be used in safe places */ + /* i.e., when Tcl_Eval can be called */ +{ + if (!debugger_active) init_debugger(interp); + + /* Initialize debugger in single-step mode. Note: if the + command reader is already active, it's too late which is why + we also statically initialize debug_cmd to step. */ + debug_cmd = step; + step_count = 1; + +#define LITERAL(s) Tcl_NewStringObj ((s), sizeof(s)-1) + + if (immediate) { + Tcl_Obj* fake_cmd = LITERAL ( "--interrupted-- (command_unknown)"); + + Tcl_IncrRefCount (fake_cmd); + debugger_trap((ClientData)0,interp,-1,Tcl_GetString (fake_cmd),0,1,&fake_cmd); +/* (*interactor)(interp);*/ + Tcl_DecrRefCount (fake_cmd); + } +} + +void +Dbg_Off(interp) +Tcl_Interp *interp; +{ + struct cmd_list *c; + + if (!debugger_active) return; + + for (c = cmd_list;c->cmdname;c++) { + Tcl_DeleteCommand(interp,c->cmdname); + } + + Tcl_DeleteTrace(interp,debug_handle); + debugger_active = FALSE; + Tcl_UnsetVar(interp,Dbg_VarName,TCL_GLOBAL_ONLY); + + /* initialize for next use */ + debug_cmd = step; + step_count = 1; +} + +/* allows any other part of the application to tell the debugger where the Tcl channel for stdin is. */ +/*ARGSUSED*/ +void +Dbg_StdinMode(mode) + int mode; +{ + stdinmode = mode; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ @@ -0,0 +1,1989 @@ +Expect FAQ (Frequently Asked Questions) + +An HTML version of this FAQ can be found in http://expect.nist.gov/FAQ.html + +This FAQ lists common questions, usually about subjects that didn't +fit well in the book for one reason or another (or weren't +indexed sufficiently well so that people can't find the answers easily +enough). In some cases, I've left the original questions. I suppose +I could've stripped off the headers, but it seems more realistic to +see actual people who've asked the questions. Thanks to everyone who +asked. + +The man page and the papers listed in the README file should +also be consulted for highly technical or philosophical discussion of +the implementation, design, and practical application of Expect. + +Don + +====================================================================== + + Here is the list of questions. You can search for the corresponding + answer by searching for the question number. For example searching + for "#3." will get you that answer. + + +**** General **** + +#1. I keep hearing about Expect. So what is it? +#2. How do you pronounce "Ousterhout" anyway? (Or "Libes" for that matter?) + +#3. Why should I learn yet another language (Tcl) instead of +writing my interaction in <a language I already know>? +#4. What about Perl? +#5. Do we need to pay or ask for permission to distribute Expect? +#6. Since Expect is free, can we give you a gift? +#7. Are there any hidden dangers in using Expect? + +**** Book, newsgroup, FAQ, README, ... **** + +#8. Why is this FAQ so short? +#9. How was this FAQ created? +#10. The background makes the FAQ hard to read. +#11. Why isn't there an Expect mailing list? +#12. Why isn't overlay covered in Exploring Expect? +#13. Is the front cover of your book a self portrait (ha ha)? +#14. Why don't the examples in your USENIX papers work? +#15. Can you put the examples in your book into an anonymous ftp site? +#16. Do you have ideas for more articles on Expect? + +**** Can Expect do this? **** + +#17. Can Expect automatically generate a script from watching a session? +#18. Can Expect understand screen-oriented (Curses) programs? +#19. Can Expect be run as a CGI script? +#20. Can Expect act like a browser and retrieve pages or talk to a CGI script? +#21. Can Expect be run from cron? +#22. Why does my Expect script not work under inetd? + +**** Compilation or porting questions **** + +#23. Why can't I compile Expect with Tcl 8.0? +#24. Does Expect 5.26 work with Tcl/Tk 8.0.3? +#25. Why can't I compile Expect with Tcl/Tk 8.1aX? +#26. Why can't I compile Expect with Tcl/Tk 8.0b1? +#27. Why does Expect need to be setuid root on Cray? +#28. Does Expect run on VMS? +#29. Is it possible to use Expect and TclX together? +#30. Is it possible to use Expect and <lots of random extensions> together? +#31. Why does configure complain about "cross-compiling"? +#32. Why are make/configure looping endlessly? +#33. Why does compile fail with: Don't know how to make pty_.c? +#34. Does Expect run on MSDOS, Win95, WinNT, MacOS, etc...? +#35. Why does Expect dump core? Why can I run Expect as root but not as myself? + +**** Other... **** + +#36. Is it possible to prevent Expect from printing out its interactions? +#37. Why does it send back the same string twice? +#38. Why can't I send the line "user@hostname\r"? +#39. How do I hide the output of the send command? +#40. Why don't I see pauses between characters sent with send -s? +#41. Why does "talk" fail with "Who are you? You have no entry utmp" or + "You don't exist. Go away"? +#42. Why does . match a newline? +#43. Why doesn't Expect kill telnet (or other programs) sometimes? +#44. How come I get "ioctl(set): Inappropriate ..., bye recursed"? +#45. How come there's no interact function in the Expect library? +#46. Can't you make tkterm understand any terminal type? +#47. Trapping SIGCHLD causes looping sometimes +#48. Why do I get "invalid spawn id"? +#49. Could you put a version number in the filename of the Expect archive? +#50. Why does Expect work as root, but say "out of ptys" when run as myself? +#51. Why does spawn fail with "sync byte ...."? +#52. Why does Expect fail on RedHat 5.0? +#53. Why does Expect fail on RedHat 5.1? +#54. Is Expect Y2K compliant? + + +* +* Questions and Answers +* + + + +**** General **** + + +#1. I keep hearing about Expect. So what is it? + +From: libes (Don Libes) +To: Charles Hymes <chymes@crew.umich.edu> +Subject: I keep hearing about Expect. So what is it? + +Charles Hymes writes: +> +>So, what is Expect? + +Expect is a tool primarily for automating interactive applications +such as telnet, ftp, passwd, fsck, rlogin, tip, etc. Expect really +makes this stuff trivial. Expect is also useful for testing these +same applications. Expect is described in many books, articles, +papers, and FAQs. There is an entire book on it available from +O'Reilly. + +Expect is free and in the public domain. Download instructions can +be found in the Expect homepage. + +Don + +====================================================================== + +#2. How do you pronounce "Ousterhout" anyway? (Or "Libes" for that matter?) + + +From: ouster@sprite.Berkeley.EDU (John Ousterhout) +To: libes@cme.nist.gov +Subject: Re: pronunciation? +Date: Tue, 29 May 90 21:26:10 PDT + +Those of us in the family pronounce it "OH-stir-howt", where the +first syllable rhymes with "low", the second with "purr", and the +third with "doubt". Unfortunately this isn't the correct Dutch +pronounciation for a name spelled this way (someplace along +the line it got misspelled: it was originally "Oosterhout"), nor +is it what you'd guess if you use common sense. So, we've gotten +used to responding to almost anything. + + -John- + +I suppose I should say something in kind. "Libes" is pronounced +"Lee-bis" with stress on the first syllable. Like John though, I've +gotten used to responding to anything close. + +By the way, notice the date on this message. I had only written +the first cut of Expect four months earlier. I asked John how to +pronounce his name because I had already got a paper accepted into +USENIX and needed to be able to say his name correctly while giving +the talk! + +Don + +====================================================================== + +#3. Why should I learn yet another language (Tcl) instead of +writing my interaction in <a language I already know>? + +From: libes (Don Libes) +Subject: Re: Expect, Tcl, programmed dialogue etc. +Date: Mon, 2 Sep 91 15:47:14 EDT + +>>>A friend told me about "Expect". But then, I have to know the +>>>idiocies of "tcl". I would like to know if there is an alternative +>>>to Expect that is also useful in other places, so that I do not +>>>have to spend time getting used to tcl for just this one tool. +> +>>Your reasoning is shortsighted. Tcl is a language that can be used in +>>other applications. It won't be a waste of your time to learn it. +> +>I have nothing against tcl as such. +>The reluctance to learn it comes mainly from the feeling that half my +>life seems to be spent learning new languages that differ very little +>from existing ones, and differ in annoying little details at that. +>To add to the misery, every implementation has its own +>idiosyncracies...:-( + +Ironically, Tcl was written specifically to halt this very problem. + +The author recognized that every utility seems to have its own +idiosyncratic .rc file or programming language. Tcl was designed as a +general-purpose language that could be included with any utility, to +avoid having everyone hack up their own new language. + + In this context, your statements do Tcl a great disservice. + +Don + +====================================================================== + +#4. What about Perl? + +From: libes (Don Libes) +To: Joe McGuckin <joe@ns.via.net> +Subject: Re: Need Perl examples +Date: Sun, 22 Jan 95 20:17:39 EST + +Joe McGuckin writes: +> +>Yeah, I've scanned through your book a couple of times in the last +>week, trying to make up my mind if I should buy it. + +I spent three years writing it - so I'm glad to hear you're spending a +little time considering its merit! + +>Pro: +> Looks like implementing some sort of telnet daemon would be trivial. + +Once you see it as an Expect script, you'll realize how trivial +these things can really be. + +>Con: +> Yet another language to learn. I know perl reasonably well & would +> like to stick with it. + +Good point. While I'm not a Perl guru, I've used it quite a bit +and it's nice for many things. But I wouldn't have bothered writing +Expect in the first place if I thought Perl was ideal. And many Perl +experts agree - I know a lot of them who call out to Expect scripts +rather than do this stuff in Perl - it's that much easier with Expect. +Expect is also much more mature. It's portable, stable, robust, and +it's fully documented - with lots of examples and a complete tutorial, +too. + +In response to someone complaining about how difficult it was to do +something in Perl, Larry Wall once remarked: "The key to using +Perl is to focus on its strengths and avoid its weaknesses." That +definitely applies here. + +Even if you do proceed with Perl, you will find the book +helpful. Automating interactive applications has unique pitfalls to +it and many of the descriptions and solutions in the book transcend +the choice of language that you use to implement them. + +Don + +====================================================================== + +#5. Do we need to pay or ask for permission to distribute Expect? + +From: libes (Don Libes) +To: Mohammad Reza Jahanbin <mrj@CIS.Prime.COM> +Subject: Copyright Question. +Date: Tue, 26 Jan 93 23:46:24 EST + +Mohammad Reza Jahanbin writes: +>Before anything let me thank you on behalf of ComputeVision R&D for +>putting so much effort into Expect. Part of CV has been using Expect +>for the past two years or so to build variety of tools including an +>automated testbed for a product. +> +>CV is currently considering shipping the automated testbed to some of its +>retailers, to enable them to perform their own tests before distributing +>the product. +> +>The Question is, are we allowed to ship Expect? Do we need to ask +>anyone for permission? Do we need to say or write anything in the +>documentation? Do we need to pay for it? +> +>I have not been able to find any copyright (or indeed copyleft) notices +>in the usual Expect distribution. Would you be able to clarify our position. + +It is my understanding that you are allowed to do just about anything +with Expect. You can even sell it. You need not ask our permission. +You need not pay for it. (Your tax dollars, in effect, already have +paid for it.) + +You should not claim that you wrote it (since this would be a lie), nor +should you attempt to copyright it (this would be fruitless as it is a +work of the US government and therefore not subject to copyright). + +NIST would appreciate any credit you can give for this work. One line +may suffice (as far as I'm concerned) although there should be +something to the effect that this software was produced for research +purposes. No warantee, guarantee, or liability is implied. + +My management is always interested in feedback on our work. If you +would like to send letters of praise describing how Expect has helped +your business, we would be delighted. Letters (on letterhead please) +are strong evidence used by policy makers when deciding where every +dollar goes. If you want to send these letters to NIST directly, you +may send them to the following individuals: + +Robert Hebner, Director +NIST +Admin Bldg, Rm A-1134 +Gaithersburg, MD 20899 + +Ric Jackson, Manufacturing Engineering Laboratory +NIST +Bldg 220, Rm B-322 +Gaithersburg, MD 20899 + +Steve Ray, Manufacturing Systems Integration Division +NIST +Bldg 220, Rm A-127 +Gaithersburg, MD 20899 + +Amy Knutilla, Manufacturing Collaboration Technologies Group +NIST +Bldg 220, Rm A-127 +Gaithersburg, MD 20899 + +In case you're wondering about the uninformative titles, Robert Hebner +is the director of all of NIST (about 3000 people) and +Amy Knutilla (way down there at the bottom) is my immediate supervisor. + +I hope this has answered your questions. Let me know if you have +further questions. + +Don + +====================================================================== + +#6. Since Expect is free, can we give you a gift? + +This is not an actual letter but represents the gist of several +that I've received. + +>>>Expect has saved us many thousands of dollars. We'd like to send +>>>you a free copy of our product. +>> +>>Thanks, but please don't. As a federal employee, I'm not +>>allowed to accept gifts of any significant value. +> +>But, what if it is for personal use (like at home)? I assume +>that would be okay. + +It doesn't matter (much). What the rules address is whether a gift +might cause me to make an official decision differently. This is +especially a concern because I may very well have to decide whether or +not to buy products from your company in the future. + +There is a clause that says "you may accept gifts from friends, +regardless of value ... but you should be careful to avoid accepting +gifts which may create an appearance of impropriety, even if permitted +as an exception to the gift rules." + +I'm still permitted to accept small token gifts, such as a t-shirt +or reasonably-priced dinner (under $20 per gift to a maximum of $50 +per year from any person or company) - so things are not totally +ridiculous. Although the precise values in the gift rules seem rather +arbitrary, I actually like the gift rules. They stop a lot of the +nonsense that used to go on involving gifts. + +Don + +====================================================================== + +#7. Are there any hidden dangers in using Expect? + +From: Charlton Henry Harrison <charlton@cs.utexas.edu> +To: libes@NIST.GOV +Date: Fri, 27 Jan 1995 23:30:56 -0600 + +>>>Dear Don: +>>> +>>> I've been a fan of Expect ever since I first learned of UNIX back +>>>in late '93. I'm young and don't have my CS degree just yet, but I worked +>>>a while back at Texas Instruments in their Telecom Customer Support dept. +>>>I started in late '93 (and hence, that's where I first started exploring +>>>the UNIX environment) and immediately forsaw the need of automating a lot +>>>of my redundant and mindless duties, but I didn't know how since we were +>>>working over a heterogeneous LAN with multiple OSs. +>>> Then I found out about Expect. I automated everything! My boss didn't +>>>like hearing that I was working on something else in order to get out of +>>>work, and I got tired of explaining it to him. +>>> Although I accomplished all the aspects of my duties, I was infamous +>>>for being the laziest person at work, and it showed (I made my job SO easy). +>>>I got a new boss after a while, and he hated me from the start and fired +>>>me soon after. Oh well, I guess my mentality didn't click with theirs. +>>> There are a lot of people like that: they believe life is putting +>>>in a hard day's work to get by. I hate that. +>>> So the point is, thank you for the wonderful 'Expect'. I bought +>>>your book and now I have the most recent version of it on my Linux system +>>>at home. Needless to say I'm looking for another job, though. +>>> +>>> Charlton +>>> +>> Thanks very much for your nice letter. Sorry to hear about your +>> automating yourself out of a job. Actually, I think most computer +>> scientists have to face this dilemma. In some ways, it's a +>> self-defeating occupation. +>> +>> Don +> +>Yeah, I'd be interested in hearing if you have a personal philosophy on +>how to handle this kind of thing. I plan on pursuing a career in Artificial +>Intelligence for similar reason of making life easier for everyone (me +>in particular!) What the future holds in this category is a great +>mystery. + +I'm glad you asked. My personal philosophy on this kind of thing is: +Find someone really rich and marry them. + +Don + +====================================================================== + +**** Book, newsgroup, FAQ, README, ... **** + + +#8. Why is this FAQ so short? + +From: libes (Don Libes) +To: Wade Holst <wade@cs.ualberta.ca> +Subject: Expect question + +Wade Holst writes: +> +> 1) Is there a more up-to-date version of the FAQ than what +> comes with expect-5.5? (For such a useful application, I +> would expect more than 12 questions). + +I know that a lot of other packages have *huge* FAQs but I +have always believed that this is an indication that their regular +documentation sucks. As questions arise that are not addressed well +by the original docs, the docs themselves should be fixed rather than +new ones created. + +In contrast, I believe that an FAQ should literally be a list of +frequently asked questions and little else. An FAQ should not be a +replacement for good documentation. + +In that sense, I have tried to use this FAQ as a second place to +look rather than a first place. The place you should always look +first is Exploring Expect. At over 600 pages, the book is very +comprehensive, well-organized, and includes three indices and two +tables-of-contents to make it very easy to find what you want to know. + +The book was not a rush job. During the three years I spent +writing it, virtually every question I was asked became incorporated +as subject material for the book. I wanted to make sure that the book +wouldn't need much of an FAQ! + +It would not make sense to try and distill the entire book into an +FAQ (that is actually comprehensive rather that truly frequently asked +questions). There's simply too much material there. + +So this FAQ is short. It really tries to stick just to *truly* +frequently asked questions. + +Don + +====================================================================== + +#9. How was this FAQ created? + +The Expect FAQ is regularly recreated by a Tcl script which +produces either text or HTML depending on how it is called. Using Tcl +has two nice results: + + I didn't have to choose one format and worry about +converting it to the other. (Remember that the FAQ appears in HTML on +the web and it appears in text in the Expect distribution.) The more +common approach - doing conversions in either direction - is really +painful - plus, it's now easy to generate other formats, too. + + It's much, much easier to keep track of questions and +answers. For example, when I add a new question, I don't have to add +it twice (once at the top and again later with the answer), nor do I +have to worry about making the links between them. All this and a lot +of other stuff is handled automatically - and the source is much more +readable than the actual HTML. +(see "FAQbuilder") + +You can read about these ideas in a paper that appeared at Tcl '96 +called Writing CGI Scripts in Tcl. (CGI scripts are the primary focus of the +paper, but it also spends time on HTML generation for other purposes - +including the example of highly stylized documents like FAQs.) + +I encourage you to examine the source to this FAQ - it +comes in two parts: + + Expect-specific FAQ source + + Generic FAQ Builder source + +The generic FAQ builder has also been used to build several other +FAQs (unrelated to Expect). + +Don + +====================================================================== + +#10. The background makes the FAQ hard to read. + +To: bonneau@mudd.csap.af.mil (Allen Bonneau) +Subject: FAQ background colors +Date: Wed, 10 Apr 96 10:24:52 EDT + +Allen Bonneau writes: +>... the white and gray background makes the FAQ difficult to read. + +It's not white and gray. It's several very close shades of gray. +It's supposed to be very subtle. Sounds like you have your browser in +a mode where it is mishandling colors. Turn on dithering and +restart your browser. + +Don + +====================================================================== + +#11. Why isn't there an Expect mailing list? + +From: libes (Don Libes) +To: dclark@nas.nasa.gov (David R. Clark) +Subject: Mailing list for Expect +Date: Mon, 23 Sep 91 18:21:28 EDT + +>Would be nice if their were an Expect mailing list. I would use it more +>often, and be made aware of other users. + +Perhaps I'm too myopic, but I don't see the need for it. Most of +the questions about Expect posted to Usenet every day can be found in +the various FAQs or in the book, so it's pretty easy getting +answers to them. + +For one reason or another (occasionally a bug fix, but often, just +adding a neat example), I update Expect every couple of weeks. +Personally, I'd hate being on the other end of something like this. +Who needs patches every two weeks for problems that are likely not +even relevant to you? (Most patches these days are either extremely +esoteric or are related to porting Expect to some unusual machine.) + +>It would be helpful, too, if this served as an area for swapping programs. +>Many of the things that I want to do are done by others already. + +NIST doesn't distribute software written by other people but if +you've got relatively small scripts that show off unique ideas and +techniques that would be educational for the Expect community, I can +include your script with Expect or put it in a publicly accessible +directory so other people can get it. I'm also willing to list links +in Expect's home page to other web pages about projects that use +Expect. + +There is a Tcl newsgroup, comp.lang.tcl, which many Expect users +read. It's pretty good for asking questions about Tcl, and many of +the readers use Expect so Expect questions are encouraged. The +newsgroup is gatewayed to a mailing list (tcl@sprite.berkeley.edu) +which is further described in the Tcl documentation. + +Don + +====================================================================== + +#12. Why isn't overlay covered in Exploring Expect? + +To: spaf@cs.purdue.edu + +Gene Spafford writes: +>I'm curious as to why the "overlay" command is not mentioned anywhere +>in the book. Is that a recent addition? A deprecated feature? I +>ended up using it in one of my scripts.... + +The overlay command has been in Expect for a long time. In all that +time no one has ever asked me about it and I have never used it. +Well, I used it once but I really didn't like the result, and so I +rewrote the script to not use it. I left the overlay command in +Expect because it seemed like an interesting idea, but I never really +finished it - in the sense that I believe it needs some more options +and controls. In comparison, the interact command is very flexible +and makes the need for overlay pretty moot. + +Don + +====================================================================== + +#13. Is the front cover of your book a self portrait (ha ha)? + +From: libes (Don Libes) +To: pkinz@cougar.tandem.com (kinzelman_paul) +Subject: the cover? + +kinzelman paul writes: +>The book finally came in. I tried to buy 4 copies but they had only 2 +>left and they came in last Saturday. Move over Stephen King! :-) + +4 copies!? Wow. That's more than my mother bought! + +>I was discussing your book with somebody who stopped in and we began +>to speculate about the monkey on the cover. I don't suppose it's a +>self portrait? :-) + +There is some real humor here. There seems to be considerable +debate over what the creature is! The colophon at the end of the book +says that it is a chimpanzee. I like that idea much more than a +monkey which is what it looks like to me. My wife, who has a degree +in zoology, explained to me that chimps are actually the second +smartest of primates (humans are the smartest). Chimps are very +intelligent and can do many things (but not everything) that humans +do. Perfect for describing Expect. Anyway, she says I should be +honored to have it grace the cover - even in theory. + +I remarked to Edie (the cover designer at O'Reilly) that even though +the cover was nice looking, everyone was going to stare at it and say, +"Gee, but it looks like a monkey." She replied "The purpose of the +cover is just to get people to pick the book up. This cover will do +that. Don't worry. If you get any rude comments from anyone, at least +you know they are paying attention." + +[After being inundated by people pointing out that the animal +really is a monkey, O'Reilly subsequently decided to acquiesce and has +changed the colophon to admit that yes it is a rhesus monkey. +Evidentally, the book from which O'Reilly has been taking those +pictures from was wrong on this one.] + +Don + +====================================================================== + +#14. Why don't the examples in your USENIX papers work? + +From: libes (Don Libes) +To: Will Smith (AC) <william@ritchie.acomp.usf.edu> +Subject: Expect + +Will Smith (AC) writes: +>I just entered some scripts from a USENIX paper that my boss had. I get +>errors about my quotes in the script. Also, it doesn't seem to know +>about expect_match. Thanks in advance for any insight you could offer. + +The USENIX papers are old and out-of-date as far as quoting goes. A +couple years ago, I cleaned up and simplified this aspect of Expect. +Similarly, expect_out is now where the results of expect's pattern +matching are saved. + +The man page is always the best reference on what Expect currently +supports. Alternatively, you can read the CHANGES files. These files +document the changes from one major version to another. + +Don + +====================================================================== + +#15. Can you put the examples in your book into an anonymous ftp site? + +From: libes (Don Libes) +To: pren@cs.umass.edu +Subject: Examples in your book "Exploring Expect" + +Peifong Ren writes: +> +>Hi, +> +>I bought your book "Exploring Expect" from O'Reilly. +>I wonder can you put the eamples in your book into an anonymous ftp +>site? + +All of the substantive examples come with recent versions of Expect. +Just look in the example directory. + +The remaining 50 or so examples are short enough that typing them +in only takes a minute or two. If I put them online, you'd spend more +time looking for them (reading my online catalog, figuring out what +the online descriptions meant, mapping them back to the file, etc.) +then it would take to type them in. And since you're likely to want +to change the examples anyway, there's nothing to be gained for short +ones. + +Don + +====================================================================== + +#16. Do you have ideas for more articles on Expect? + +From: libes (Don Libes) +To: faught@zeppelin.convex.com (Danny R. Faught) +Cc: libes +Subject: Re: SQA Quarterly articles +Date: Thu, 21 Dec 95 13:31:01 EST + +Danny R. Faught writes: +>I just arranged to write an article on automating interactive +>processes for an issue early next year. You have so many good pieces +>on expect out there, it's going to be hard to add anything original. + +One thing I've never written is a good mini-tutorial. Magazine +editors love these types of pieces and there's certainly a need for +it. So I'd encourage that type of article. + +Another possibility is an article on how you or your colleagues +personally applied Expect to solve your particular problem. Application- +oriented papers are the kind that necessarily have to be written by +people in the field who are applying the technology. People love this +kind of practical paper. For example, a good paper might be "Writing +a pager". This is a nice topic because you can start with a simple +5-line script that solves the problem and then show progressive +refinements that handle different twists on the same problem. (And +"how to write a pager" is a very frequently asked question on Usenet.) + +Don + +====================================================================== + +**** Can Expect do this? **** + + +#17. Can Expect automatically generate a script from watching a session? + +From: libes (Don Libes) +To: pete@willow24.cray.com +Subject: Expect +Date: Fri, 12 Oct 90 17:16:47 EDT + +>I like "Expect" and am thinking of using it to help automate the +>testing of interactive programs. It would be useful if Expect had a +>"watch me" mode, where it "looks over the shoulder" of the user and +>records his keystrokes for later use in an Expect script. +> +>(Red Ryder and other Macintosh telecommunications packages offer this +>sort of thing. You log onto Compuserve once in "watch me" mode, and +>RR keeps track of the keystrokes/prompts. When you're done you have a +>script that can be used to log onto Compuserve automatically.) +> +>Before I look into adding a "watch me" feature, I thought I should +>ask: has this been done already? +> +>I'll say again that I like the tool a lot--nice work! There are other +>people here using it for things like the testing of ksh, which +>responds differently to signals when not used interactively. +> +>-- Pete + +The autoexpect script in Expect's example directory does what you +want. + +Don + +====================================================================== + +#18. Can Expect understand screen-oriented (Curses) programs? + +Yes, it can - with a little clever scripting. Look at the +term_expect script for an example. It uses a Tk text widget to +support screen-oriented Expect commands. This technique is described +very thoroughly in Chapter 19 of Exploring Expect. + +Adrian Mariano (adrian@cam.cornell.edu) converted the term_expect +code (see above) so that it runs without Tk (exercise 4 in Chapter +19!) Both term_expect and virterm can be found in the example +directory that comes with Expect. + +An alternative approach to screen-handling was demonstrated by Mark +Weissman (weissman@gte.com) and Christopher Matheus who modified a +version of Expect to include a built-in Curses emulator. It can be +ftp'd from the Tcl archive as expecTerm1.0beta.tar.Z. (Note that +Expecterm does not run with the current version of Expect.) + +I like the idea of keeping the curses emulator outside of Expect +itself. It leaves the interface entirely defineable by the user. And +you can do things such as define your own terminal types if you want. +For these reasons and several others, I'm not likely to return to +Expecterm. + +Don + +====================================================================== + +#19. Can Expect be run as a CGI script? + +Expect scripts work fine as CGI scripts. A couple pointers might +help to get you going: + +Many Expect scripts can be run directly with one change - the +following line should be inserted before any other output: + +puts "Content-type: text/html\n" + +Be sure not to forget that extra newline at the end of the puts. + +Next, make sure you invoke external programs using full paths. For +example, instead of "spawn telnet", use "spawn /usr/ucb/telnet" (or +whatever). Remember that the PATH and other environment variables are +going to be different than what you are used to. This is very similar +to dealing with cron and you can get other good tips and advice from +reading the Background chapter in the book. + + Another tip: If a script runs fine by hand but not from CGI, just +log in as "nobody" to the host on which your CGI script runs. Then +try running it by hand. This generally makes it very obvious what's +going on. (If you can't log in to the server or can't log in as +"nobody", use the kibitz trick described in the Background chapter.) + +You may find it helpful to use cgi.tcl, a nice collection of +CGI support utilities for Tcl scripts. It includes an Expect example +among many others. The package includes just about everything: +tables, frames, cookies, file upload, etc...., with some nice +debugging support. It's pure Tcl, no C code - so it's very easy to +try out and use. + +Don + +====================================================================== + +#20. Can Expect act like a browser and retrieve pages or talk to a CGI script? + +From: jasont@netscape.com (Jason Tu) +Date: Sat, 02 Nov 1996 09:51:03 -0800 + +I read your book "Exploring Expect" and find Expect is just the tool +to test Netscape's enterprise server product, since it is very easy to +use and quick to develop. I figured I would use telnet to send HTTP +protocol dialog to a HTTP server and simulate how it behaves. But I +couldn't get it to work at all. I am wondering that there might be a +quick example that you can share with me. + +Yes, this is a useful way of testing HTTP servers and running CGI +scripts (and winning Web contests :-). You can add error checking and +other stuff, but here's the minimum your script should have to read a +web page: + +match_max 100000 +set timeout -1 +spawn telnet $host 80 +expect "Escape character is *\n" +send "GET $page\r\n" +expect +puts "$expect_out(buffer)" + +If you want to communicate information to a CGI script, you'll want +more. One way to see what needs to be sent is to load a real browser +with the form and then send it to a fake daemon such as this one: + +#!/bin/sh +/bin/cat -u > /tmp/catlog + +Enable this by adding this service to inetd. Then save the form in +a temporary file, modify the form's host and port to correspond to +your own host and whatever port you've chosen to associate with your +fake daemon. Now fill out the form and you'll find the form data in +/tmp/catlog. Using this, you can determine exactly how to amend your +Expect script to behave like your browser. + +Don + +====================================================================== + +#21. Can Expect be run from cron? + +Expect itself works fine from cron - however, you can cause +problems if you do things that don't make sense in cron - such as +assume that there is a terminal type predefined. There are a number +of other pitfalls to watch out for. The list and explanations aren't +short - which is why there's a whole chapter ("Background") on the +subject in the book. + +Here's one that someone tried to stump me with recently: They told +me that their program started up and then Expect immediately exited. +We spent a lot of time tracking this down (Was the spawned program +really starting up but then hanging - which would indicate a bug in +the program; or was the program NOT starting up - which would indicate +a bug in the environment; etc.) Turned out that Expect wasn't even +running their program. They had assumed cron honored the #! line +(which it doesn't) and so the first line in their script (exec date) +was being interpreted by the shell and of course, the script did +nothing after that - because that's what the shell's exec is supposed +to do!) + +Don + +====================================================================== + +#22. Why does my Expect script not work under inetd? + +From: dpm@bga.com (David P. Maynard) +Subject: Re: Tcl/Expect, inetd service, and no echo password +Date: 24 Oct 1996 13:34:57 -0500 + +In article <54ocsh$9i1@urchin.bga.com> dpm@bga.com (David P. Maynard) writes: + I am fairly new to expect, so hopefully this isn't too obvious. I also + confess to not having looked in "Exploring Expect" becuase I haven't + found it in stock at a local bookstore yet. + + I want to write an expect script that runs as a service from inetd. + (Actually, I plan to use the tcpd 'twist' command to launch the + binary, but that doesn't seem to affect the problem.) The script will + prompt the user for a password. The supplied password is used as a + key to decrypt some passwords stored online. The script then fires + off a telnet session to a remote box and does some fairly simple + things that require the decrypted passwords. + + I have all of this working when I run the script from a UNIX prompt. + However, when I run it out of inetd, the 'stty -echo' commands that + turn off character echo when the user types the password fail with the + following error: + + stty: impossible in this context + are you disconnected or in a batch, at or cron script? + stty: ioctl(user): Bad file descriptor + + I can understand the cause of the message (no associated tty), but I + can't think of an easy solution. If I use 'gets' or 'expect_user,' + the user's input is always echoed. I tried a few variations on the + stty command, but didn't have any luck. + + Any suggestions? + +Yes, read Exploring Expect, Chapter 17 (Background Processing). In +the section "Expect as a Daemon", there's a very thorough discussion +of this problem and how to solve it. + + +In short, there's no tty when you run a process from inetd. Echoing +is controlled by the telnet protocol, so you must send and expect +telnet protocol packets to solve the problem. Even knowing this, the +actual implementation is very non-obvious which is why the book goes +into it in such detail. + +Don + +====================================================================== + +**** Compilation or porting questions **** + + +#23. Why can't I compile Expect with Tcl 8.0? + +Sounds like you have an old version of Expect. Get a a new version of Expect. + +Don + +====================================================================== + +#24. Does Expect 5.26 work with Tcl/Tk 8.0.3? + +To: aspi@cisco.com +Subject: Re: Expect 5.26 and TCL 8.0 +Aspi Siganporia writes: +> +>Hi Don, +> +>We are looking at upgrading Expect. Our last version was Expect5.22 +> +>I see that Expect5.26 supports TCL 8.0. +> +>The question is, +> +>Will it work with TCL8.0.3? +> +>Thanks +>Aspi + +It might. 8.0.3 broke a couple of the more esoteric configurations. +If you find that you can't compile using 5.26, get 5.27. + +Don + +====================================================================== + +#25. Why can't I compile Expect with Tcl/Tk 8.1aX? + +Historically, I've rarely found the time to port Expect to alphas +and betas. I recommend you stick with 8.0 unless you're willing to do +a little work. + +Don + +====================================================================== + +#26. Why can't I compile Expect with Tcl/Tk 8.0b1? + +I don't see the point in supporting an old beta. Upgrade to the +production release of Tcl/Tk 8.0. + +Don + +====================================================================== + +#27. Why does Expect need to be setuid root on Cray? + +From: libes (Don Libes) +To: u70217@f.nersc.gov (Lori Wong) +Subject: setuid in Expect +Date: Thu, 24 Oct 91 16:15:20 EDT + +> I have been running Expect now under UNICOS 6.1 and CSOS 1.0 (Cray +>Computer Corporation's OS). The two machines that I am running Expect +>on have stringent security features, one of which is to limit setuid +>privileges to specific individuals. I was wondering if you would be +>kind enough to explain the purpose of the setuid that is needed by Expect +>and whether it could be compiled to run without having to have setuid +>privilege? I know it has to do with spawning and communicating with +>the various spawned tasks, but don't know enough of the details to be +>able to explain why Expect specifically needs setuid and whether or not +>it could cause a security problem (could someone use it to enter into +>the system and wreak havoc, for example?). Right now, I've limited +>the access of Expect to my group, but need to know what the security +>implications are if I open it to all users. I'd appreciate any light +>you can shed on this subject... + +Root-access is needed to open a pty under Unicos. Thus, all programs +accessing ptys must be setuid root. If you do an "ls -l" of programs +like "script", "xterm", etc, you'll see this. + +I have no idea why this is. The requirement was probably for security +reasons to begin with, but it has the ironic effect of making more +programs require setuid and therefore greater possibility of errant +setuid programs. + +In fact, there is one known Unicos bug relating to the way uids are +switched at exec time which requires further special coding. If you +search for "Cray" in the Expect source you will see significant chunks +of code to get around the problem. + +I don't know if this reassures you any. All I can tell you is that a +number of Cray experts have looked into the situation and are happy +with the current implementation of Expect. + +Don + +====================================================================== + +#28. Does Expect run on VMS? + +From: libes (Don Libes) +To: Cameron Laird <claird@Starbase.NeoSoft.COM> +Subject: VMS question. + +Cameron Laird writes: +>Do you know of anyone working with Expect and VMS? +>I'd like not to re-invent wheels, but, if I'm to be +>the first one, I want others to benefit. + +No, I'm not aware of anyone doing it. Since VMS claims POSIX +conformance, it shouldn't be that hard - Expect uses the POSIX calls +if it can. Probably the hardest part will just be modifying the Makefile +and the configure script! + +However, that there might be a simpler solution. The neat thing +about Expect is that you can control other computers easily. Run +Expect on your UNIX box and have it log in to the VMS box and do its +thing. (You can bypass the login garbage by using an inet daemon.) +We've done exactly this to a number of weird pieces of hardware we +have around the lab (robots, Lisp machines, embedded controllers, and, +of course, a VAX running VMS). It saves time porting! + +Don + +====================================================================== + +#29. Is it possible to use Expect and TclX together? + +Is it possible to use Expect and TclX together? +From: bfriesen@iphase.com (Bob Friesenhahn) +Date: 20 Jul 1994 04:09:43 GMT +Organization: Interphase Corporation, Dallas TX - USA + +Jeffery A. Echtenkamp (echtenka@michigan.nb.rockwell.com) wrote: +: Do Expect and tclX work together? If so, must anything special be done to +: get them to work together? + +This answer courtesy of Bob Friesenhahn, Interphase (bfriesen@iphase.com): + +They work fine together. However, you should prepend "exp_" to your Expect +command names. This will ensure that there are no conflicts between Expect +commands and tclX commands of the same name (like wait). + +Just pick up the "make-a-wish" package, follow the instructions, and you will +be all set. I have built a wish based on tcl, tk, Expect, tclX, and dp using +this technique with no observed problems. + +Bob + +[If you need additional information, please read Chapter 22 +("Expect as Just Another Tcl Extension") of Exploring Expect. Its +sole focus is how to make Expect work with other extensions. - Don] +====================================================================== + +#30. Is it possible to use Expect and <lots of random extensions> together? + +From: libes (Don Libes) +To: Frank Winkler <winkler@eas.iis.fhg.de> +Subject: Q Expect + TkSteal + +Frank Winkler writes: +>Hi don, +> +>a short question considering installation of Expectk. +> +>Is it possible to build an Expectk-binary, which uses +>the features of BLT, TkSteal and Expect ? + +I've never done it, but I know it must be possible because the tgdb +package in the Tcl archive uses all of those extensions with Expect. + +Expect is a "well-behaved extension" in the sense that it requires no +changes to the Tcl core. So Expect should work with any other Tcl +extensions. You just need to add the usual Exp_Init call to main() or +the other _Init calls to Expect's main. + +>If yes, which of them should be build first, second ... ? + +Order doesn't matter. + +I've done this kind of thing by hand. It's pretty simple. But people +tell me the make-a-wish package in the Tcl archive automates the +creation of multi-extension Tcl applications. + +[Also see the answer to the previous FAQ answer.] + +Don + +====================================================================== + +#31. Why does configure complain about "cross-compiling"? + +From: libes (Don Libes) +To: morton@hendrix.jci.tju.edu (Dan Morton) +Subject: Re: Sorry to bother you, but... + +Dan Morton writes: +>Don, +> +>I've posted an inquiry to comp.lang.tcl about my configure problems with +>expect, but I've not yet gotten a reply. Perhaps you can nudge me in the +>right direction? +> +>I'm running HP-UX 9.0 on a 735, and I've snagged the latest versions of Tcl +>and expect from NIST (7.4 and 5.18 respectively). My gcc is v2.6. Tcl +>configured and built out of the box, but I can't get expect to configure +>properly. No matter what I do, it thinks it wants to cross-compile. I +>think it's failing that little snippet of eval code. It gets further if I +>specify --host=HP, but still complains about cross compiling. Here's the +>result without options: +> +>{hendrix:~/expect-5.18:8} ./configure +>checking for gcc... gcc +>checking whether we are using GNU C... yes +>checking whether gcc accepts -g... no +>checking how to run the C preprocessor... gcc -E +>checking whether cross-compiling... yes +>checking whether cross-compiling... (cached) configure: error: You need to +>specify --target to cross compile, +> or the native compiler is broken + +I guess the error message has to be clearer. The message: + + "or the native compiler is broken" + +means that configure tried to compile a simple program and it failed. +Here's the program it tries to compile: + + main() { + return(0); + } + +The configure output that you showed me says that it found gcc. +Perhaps it was misinstalled or is just a placeholder and doesn't +actually do anything? Try compiling a tiny C program yourself from +the command line. + +Don + +====================================================================== + +#32. Why are make/configure looping endlessly? + +To: Xiaorong Qu <aqu@cisco.com> +Subject: Make message for Expect +--text follows this line-- +Xiaorong Qu writes: +>Don, +> +>The following is the output of make, you can find +>that the process repeated three times. + +I bet what's going on is that your system clock is set to some +ridiculous time such as last year. "Make" is sensitive to your clock. +Please fix your clock. Then check that all the files are "older" +than the current time. (If not, "touch" them all.) + +Don + +====================================================================== + +#33. Why does compile fail with: Don't know how to make pty_.c? + +From: libes (Don Libes) +To: wren@io.nosc.mil +Subject: Compile fails with: Don't know how to make pty_.c + +> I'm trying to compile Expect on hpux 9.01, +> downloaded from ftp.cme.nist.gov expect.tar + +> after running config +> the make fails with "Don't know how to make pty_.c. (compile fails) +> I see three versions pty_sgttyb.c, pty_termios.c and pty_unicos.c in +> the load, but the configure picked none of them. +> I tried forcing to pty_termios.c but that failed with other compile errors. + +I've seen this happen because gcc was partially installed. configure +finds the gcc stub and uses gcc for all the tests. But because the +compiler doesn't work, every test fails so configure doesn't select +any of the choices. + +So either finish installing gcc or delete the stub. + +(And if it's not that, then something similar is wrong with whatever +compiler you've got. Look closely at the output from configure, it +will tell you what compiler it is trying to use.) + +By the way, Expect compiles fine on my HP (A.09.05 E 9000/735). + +Don + +====================================================================== + +#34. Does Expect run on MSDOS, Win95, WinNT, MacOS, etc...? + +Gordon Chaffee has ported Expect to NT. I would like to unify the +UNIX and NT code but I probably won't have the time to do this +personally. Volunteers are welcome. + +I have no plans to do other ports. Feel free to volunteer. + +Don + +====================================================================== + +#35. Why does Expect dump core? Why can I run Expect as root but not as myself? + +From: Wayne Tcheng <wmt@visi.net> +Subject: Expect on Solaris +Date: Wed, 2 Apr 97 21:34:50 EST + +I've compiled Expect 5.21 with Tcl 7.6 and Tk 4.2. Whenever I run Expect +as a non-root user, it core dumps. When I am root, I can run it +successfully. However, if I "su - wmt" to my own id, I can also run it +without a problem. I've tried making the expect binary suid root, but +that does not help either. I'm on Solaris 2.5. Any ideas? + +Sounds like something on your system is misconfigured. Everytime +I've had reports like this (works as root, not as user), it's turned +out to be /tmp was unwriteable or something equally improbable. + +The easiest way to find out is to use the debugger and tell me where +Expect is dumping core. (If you don't understand this statement, ask +a local C or C++ programmer.) + +As an aside, you should be using the most recent version of Expect +(currently 5.22.1). But I don't know of any problems in 5.21 that +caused core dumps, so it's certainly worth trying the debugger +approach before retrieving the latest version. But if you do find a +bug in Expect, before reporting it, please verify that it still exists +in the current version. + +Don + +====================================================================== + +**** Other... **** + + +#36. Is it possible to prevent Expect from printing out its interactions? + +From: libes (Don Libes) +To: Sunanda Iyengar <sunanda@simvax.labmed.umn.edu> +Subject: Disabling display from Expect + +Sunanda Iyengar writes: +>Is it possible to have Expect interact with a process and not print-out +>the results of interaction? In my application, I need it to go into a +>silent mode, communicate with a process without reporting to the user, and +>then come back to normal mode and put the process into interactive mode. + +Use the following command: + + log_user 0 + +To restore output: + + log_user 1 + +See the Expect man page for more details or page 175 of Exploring +Expect for details and examples. + +Don + +====================================================================== + +#37. Why does it send back the same string twice? + +From: Don Libes +To: yusufg@himalaya.cc.gatech.edu (Yusuf Goolamabbas) +Subject: Duplicate pattern matches in Expectk +--text follows this line-- + Hi, I am trying to do a very simple thing in expectk + + spawn cat + expect_background -re ".+" { + send $expect_out(0,string) + } + exp_send "Hello World\n" + + Now the display in the text widget looks like this + Hello World\r + Hello World\r + + whereas I was expecting only one line + Hello World\r + + Thanks in advance, Yusuf + -- + Yusuf Goolamabbas yusufg@cc.gatech.edu + Graphics, Visualization, & Usability Center (O) 404.894.8791 + College of Computing Georgia Tech + http://www.cc.gatech.edu/grads/g/Yusuf.Goolamabbas/home.html + +This is correct behavior. The first "Hello World" is echoed by the +terminal driver. The second is echoed by cat. This behavior has +nothing to do with Expectk (or Expect for that matter). You can see +this same thing if you type to cat interactively. + +% cat +Hello World +Hello World + +In the example above, I typed "cat" at the shell prompt and pressed +return. Then I entered "Hello World" and pressed return. Looking at +the output I *see* "Hello World" twice even though I only entered it +once. + +You can account for this behavior in your patterns. Alternatively, +just turn off the echo. In your particular case though, it's doing +the right thing, showing you the result of an interactive cat just as +if you had typed it yourself. + +In practice, this kind of problem doesn't arise - because programs +like cat aren't spawned (except in very special situations). I assume +that cat was just something you chose to experiment with. + +Don + +====================================================================== + +#38. Why can't I send the line "user@hostname\r"? + +From: libes (Don Libes) +To: bt@nadine.hpl.hp.com +Subject: Re: [Q] Expect, ftp and '@' + +> I am attempting to use Expect to perform anonymous ftp gets without +>my having to type all the stuff --- I mean, waaaiiiting for the +>prompt, entering a-n-o-n-y-m-o-u-s with my fat fingers, and the rest. +> +> But I have a probleme: as I set the password to be my e-mail address: +> set password "bt@hplb.hpl.hp.com" + +> the ftp servers seem not to receive neither my login name nor the +>at-sign. Some of them do not care, some others say "ok, but don't do +>that again", and the last ones throw me off. + +The short answer is to upgrade to Expect 5.20 or later. If you +don't feel like doing this, here's the explanation for older versions +of Expect: + +spawn initializes the terminal by using your current parameters and +then forces them to be "sane". Unfortunately, on your system, "sane" +says to interpret the "@" as the line-kill character. + +The most sensible thing to do is change "sane" in your Makefile to +something that makes sense. (Since you work at HP, you might also +suggest that they modernize stty!) + +Here's an example of a replacement line for the Makefile: + + STTY = -DDFLT_STTY=\""sane kill ^U"\" + +Other alternatives are: quote the @, or use the -nottyinit flag, or +set the stty_init variable. + +Don + +====================================================================== + +#39. How do I hide the output of the send command? + +From: tim@mks.com (Timothy D. Prime) +Subject: Re: hide the text of expect's send command? +Date: 29 Mar 1996 15:41:02 GMT + +In article <khughesDoy1yH.5zo@netcom.com>, Kirby Hughes <khughes@netcom.com> wrote: +> I don't want to see (on the screen) the text sent by a "send" command. Is +> there a way to hide it? "log_user 0" works for text coming back to me, but +> doesn't (seem to) work for sending... +> +> #!/usr/local/bin/expect -- +> log_user 0 +> spawn telnet proxy +> expect Command +> send "c [lrange $argv 0 1]\n" +> log_user 1 +> interact + +This answer courtesy of Timothy Prime, Mortice Kern Systems (tim@mks.com): + +The output you are seeing wasn't printed by the send command. +(I.e., the log_user command is working just fine.) The output you see +is from the interact command. The interact command found program +output and thus wrote it to the terminal so that you could see it. +That's what the interact command is supposed to do! + +Although the expanation might take a little thought, the solution is +easy. Simply put an expect command in before the command "log_user 1". +Match against the last characters that you wish to suppress. +====================================================================== + +#40. Why don't I see pauses between characters sent with send -s? + +From: jcarney@mtl.mit.edu (John C. Carney) +Newsgroups: comp.lang.tcl +Date: 12 Aug 1996 17:32:54 GMT +Organization: Massachvsetts Institvte of Technology + +I am trying to use expect to spawn the kermit program. It then +is supposed to dial the modem and procede. + +When I run kermit from the shell, it has no problem dialing the +modem. However, when kermit is spawned by expect, it will not dial. + +I thought perhaps the input stream was too fast for kermit and tried +send -s. I do see a long delay before the dial message is sent, but it +still won't dial. Also, I would expect (no pun) that I would see the +characters sent as follows: + +a<pause>t<pause>d<pause>t<pause> ... + +But instead I see: + +<long_pause>atdt ... + +What am I doing wrong? + +Thanks for you help. + +John Carney +jcarney@garcon.mit.edu + +The send command doesn't wait for responses. The echoing you see +is from an expect command running after send has run. At that point, +all the characters have been echoed already - thus, you see the long +pause (while send is running) and the rush of characters (while expect +is running). + +Before you ask, no, it doesn't make sense to have send pause +briefly and wait for echoing. Sometimes there is no echoing. And +sometimes things aren't echoed in an intuitive way. So how could send +possibly know what to wait for and how long? + +The solution is to use the expect background command: + expect_background -re .+ + +Just put this after your spawn command and before you start sending +things. + +Don + +====================================================================== + +#41. Why does "talk" fail with "Who are you? You have no entry utmp" or + "You don't exist. Go away"? + +From: libes (Don Libes) +To: Will Smith (AC) <william@ritchie.acomp.usf.edu> +Subject: Expect + +Will Smith (AC) writes: +>Hi there. I was wondering if you had any ideas to why i am getting +>this problem running an Expect script which tries to spawn a talk +>process to myself on another machine. Would it have anything to do +>with the fact that the executables are NOT installed in /usr/local/bin +>or because it wasnt installed by ROOT or what. This is what my Expect +>script looks like. +> +>#! /home/ritchie/ops/william/test/expect -f +> +>spawn talk william@curiac.acomp +>set timeout 200 +>expect {*established*} +>set send_human {.1 .3 1 .05 2} +>send -h "This is only a test.. I swear \ Please don't bust me with expect \n >expect "{*\r*}" +>expect "{*\r*}" +>exec sleep 5 +>send -h "Ok, well see ya tomorrow you idiot \n" +>exec sleep 3 +> +>The error i get is that it returns this when i run the script. +> +> Who are you? You have no entry in /etc/utmp! Aborting... + +On most systems, Expect does not automatically make a utmp entry. (A +utmp entry normally indicates login information which seems kind of +pointless for Expect scripts.) This allows Expect to run non-setuid. + +Normally, this lack of utmp entries doesn't mean much. However, a few +programs actually refuse to run without a utmp entry. Fortunately, +there are workarounds: + +Program-dependent solutions: + +"talk" is the only program I'm aware of that falls into this category. +One solution is to get ytalk. ytalk doesn't have this problem plus it +fixes many other bugs in talk, such as being able to communicate with +both old and new talk. + +Program-independent solutions: + +Use a program specifically intended to create utmp entries. Such +programs are easy to write or get if you don't have them already. For +instance, sessreg is one which comes with the xdm distribution. And +Solaris uses utmp_update. I like this approach because it isolates +the setuid code in a small single system utility rather than in every +program on the system that needs this ability. + +Tod Olson <tao@stone.lib.uchicago.edu> sent in the following +example of how to use sessreg. He says: sessreg works nicely. Here +is a fragment showing how we invoke sessreg on our Linux machines. +Note: sessreg must be able to write utmp. We decided to make utmp +work writable, since it's a kinda bogus creature anyhow, rather than +make sessreg suid root (or whatever). + +... +spawn $shell +expect $prompt +send "sessreg -w /var/run/utmp -a $user\r" +expect $prompt +====================================================================== + +#42. Why does . match a newline? + +From: libes (Don Libes) +To: xipr@alv.teli.se (Ivan Prochazka) +Subject: Why does . match a newline? +Ivan Prochazka writes: +> +>Hello Don. +> +>In my opinion(and emacs) the regexp-symbol "." stands for all +>characters except newline(\n). +>This is not the case in Expect 5.2. + +Yes, there are some packages that follow this convention, but I don't +think it is appropriate for Expect. Unlike emacs, most Expect +patterns don't look for full lines - more often they look for prompts +which *don't* end with newlines. + +I find that I actually write the [^\n] pattern very rarely. And +if I write it frequently in a script, then the expect itself probably +ought to be in a subroutine. + +In fact, the more common line-terminating sequence in Expect is \r\n, +so that might make a more likely argument. In any case, Expect +defines . the way POSIX does. So I feel pretty good about the +definition of . being what it is. + +Don + +====================================================================== + +#43. Why doesn't Expect kill telnet (or other programs) sometimes? + +From: libes (Don Libes) +To: Karl.Sierka@Labyrinth.COM +Subject: Re: need help running telnet Expect script from cron on sunos 4.1.3 + +karl.sierka@labyrinth.com writes: +> The only problem I am still having with the script I wrote is that +> the telnet does not seem to die on it's own, unless I turn on debugging. + +Actually, Expect doesn't explicitly kill processes at all. Generally, +processes kill themselves after reading EOF on input. So it just seems +like Expect kills all of its children. + +> I was forced to save the pid of the spawned telnet, and kill it with an +> 'exec kill $pid' in a proc that is hopefully called before the script +> exits. This seems to work fine, but it makes me nervous since omnet +> charges for connect time, and leaving a hung telnet lying around could +> get expensive. I warned the rest of the staff so that they will also be +> on the lookout for any possible hung telnets to omnet. + +The problem is that telnet is not recognizing EOF. (This is quite +understandable since real users can't actually generate one from the +telnet user interface.) The solution is to either 1) explicitly drive +telnet to kill itself (i.e., a graceful logout) followed by "expect +eof" or 2) "exec kill" as you are doing. + +This is described further in Exploring Expect beginning on page 103. + +Don + +====================================================================== + +#44. How come I get "ioctl(set): Inappropriate ..., bye recursed"? + +From: libes (Don Libes) +To: james@Solbourne.COM (James B. Davis) +Subject: How come I get "ioctl(set): Inappropriate ..., bye recursed" ... +Date: Tue, 10 Dec 91 10:47:21 MST + +>Every time I ^C out of a Expect script run I get: +> +>ioctl(set): Inappropriate ioctl for device +>bye recursed +> +>james@solbourne.com + +This answer courtesy of Michael Grant (mgrant@xdr.ncsl.nist.gov): + +You (or whoever installed gcc) forgot to run the fixincludes shell +script while installing gcc. Recompiled gcc with itself, then run the +fixincludes script - and the messages will go away. + +Michael Grant +====================================================================== + +#45. How come there's no interact function in the Expect library? + +From: libes (Don Libes) +To: Djamal SIMOHAND <djamal@lyohp5.in2p3.fr> +Subject: Re: exp_expectl +Date: Wed, 3 Jan 96 12:17:01 EST + +Djamal SIMOHAND writes: +>I have already used the Expect program to write a script to connect by +>telnet on my machine. Now I made a graphic interface in C and I need +>the expect in C in order to have a coherent executable. +> +>I've already written most of the C already, but the connection is +>closed just after my program is finished. Then I have no opportunity +>to work on my machine. It seems I need of the equivalent of +>"interact" in C. Is there such a function in the C library? +> +>Thanks for your help, +> Djamal + +No, there is no interact-like function in the C library. The reason +is three-fold: + +1) It is simple enough to write your own. It's just a loop after +all: + + while 1 { + select/poll() + read() + write() + } + +2) There's no way I could possibly provide all the options you might +need. In Expect, it's not a problem because the environment is very +controlled, but in C, it's impossible to control what you might want +to do. For example, you mention that you're embedding your code in a +graphics application. Graphics packages typically have their own +event manager, so you wouldn't want a monolithic interact function. + +3) The library is intended for embedding in other applications, where +it rarely makes sense to give the user direct control of a spawned +process. That kind of thing makes so much more sense to handle with +an Expect script than a C program. The C library was not intended as +a replacement for Expect. Expect is really the tool of choice for +interaction problems, not C. + +In summary, there's very little payoff for the library to supply an +interact function. A simple one would only satisfy people who should +be using Expect anyway - and it's impossible to create one that would +do everything that everyone wants. It's easier just to let people +create their own. + +Don + +====================================================================== + +#46. Can't you make tkterm understand any terminal type? + +From: swig@teleport.com (Scott Swigart) +Newsgroups: comp.lang.tcl +Date: Tue, 13 Aug 1996 18:50:22 GMT + +I looked at tkterm, and it is promising, but it's missing some +critical features. For one, I need something that understands various +terminal types, and can get it's escape sequences from something like +termcap or terminfo, instead of having them hard coded. Also, I +question the ability of an Expect script to keep up if it had 50 or so +types of escape sequences to parse. Actual C code would probably have +to be created to do the parsing, and if you're going to go that far, +why not just create a terminal widget so you could do something like: + +terminal .myterm -type vt220 + +which is more along the lines of what I was originally looking for. + +Yes, that would be divine. But terminal emulators are horribly +complex and very little of that complexity can be discerned from the +termcap file. For example, compare xterm's human-readable docs (63k +man page + 18k appendix) to its termcap entry (654 bytes). Now +consider the other hundreds of terminals in termcap each with their +own weird extensions. I can't imagine what kind of ".myterm configure" +interface you'd present to the user. What would you allow the user to +change? The nice thing about tkterm is that everything is accessible +to the user, but I can't imagine doing that through a widget +interface. + +Unfortunately, like everyone else, I don't have the time... + +Me neither. Call me lazy. + +As an aside, I wonder why you want the ability for a terminal emulator +to read termcap/info. Turns out that it's useless (unless what you +are doing is testing termcap itself). Because if your app is using +termcap in the first place, then it doesn't care what terminal type +you choose - so why not choose the one that tkterm does? (And if your +app isn't using termcap, then you have the converse problem.) + +Actually, I and several other people did a fair amount of +experimentation (i.e., wrote a lot of C code) to do a universal +terminal emulator - turns out that it's not possible in a general +sense. To support any terminal type, you are going to be forced to go +beyond what termcap/info offers. I.e., you'll have to handedit the +definition or add new ones and/or accept certain limitations. + +After many revisions, Software - Practice & Experience is +publishing a paper on tkterm. The paper includes more insights on the +difficulties I've mentioned here. You can get a draft of the paper +at: http://www.cme.nist.gov/msid/pubs/libes96d.ps + +Don + +====================================================================== + +#47. Trapping SIGCHLD causes looping sometimes + +From: Bryan Kramer <bryan.kramer@hydro.on.ca> +Sender: kramer@hydro.on.ca +Cc: libes@NIST.GOV +Subject: Problem with trap in expect on Solaris +Date: Tue, 17 Sep 1996 11:09:50 -0400 + +I'm getting an infinite loop running the attached script foo.tcl on my +solaris machine (Ultra Sparc, SunOS 5.5). This does not happen when I +run the version of the same expect that I compiled on a Sparc 20 with +SunOS 4.1.3UI (even though I am running it on the Solaris 5.5. ultra). + +trap { + if {[catch { + puts stderr "CALL TRAP [trap -number] [trap -name]" + wait -i 1 + } output]} { + puts stderr "TRAP $output" + return + } + puts "TRAP DONE" +} SIGCHLD + + +if {[catch {exec trivial} msg]} { + puts stderr "Error $msg" +} + + +Please let me know if there is an immediate work around. + +Thanks +-- +|Bryan M. Kramer, Ph.D. 416-592-8865, fax 416-592-8802| +|Ontario Hydro, 700 University Avenue, H12-C1 | +|Toronto, Ontario, Canada M5G 1X6 | +<A href="http://www.cs.toronto.edu/~kramer">B. Kramer Home Page</A> + +I haven't analyzed your script in depth, but this sounds like a +problem I've seen before - it's due to an implementation deficiency in +Tcl. The problem is that when an exec'd process finishes, it raises +SIGCHLD. Expect's "wait" sees that it is Tcl's process. +Unfortunately, there is no way to wait for one of Tcl's processes and +tell Tcl that you've done so, nor is there any way to have Tcl wait +itself. So Expect's wait just returns. On some systems alas, this +just causes SIGCHLD to be reraised. + +The solution is multipart: + 1 Tell John he needs to fix this problem. (I've told him this but he +didn't agree with me that it's a problem.) Tcl needs to provide a new +interface - either to clean up its process or to allow extensions to +do the wait and pass the status back to Tcl so that it can have it +later when needed. + 2 Don't call exec while you are trapping SIGCHLD. Since this is a +severe limitation, I recommend you avoid the problem by using +"expect_before eof" to effectively trap the same event. If you're not +already using expect, well, call it every so often anyway. + +Don + +====================================================================== + +#48. Why do I get "invalid spawn id"? + +Subject: Why do I get "invalid spawn id" +In article <53ggqe$hag@hole.sdsu.edu> khumbert@mail.sdsu.edu writes: + I am trying to write a general looping procedure that will handle + many cases that have similar prompt sequences. The function and one + call are below. + The problem is that when the "looping" function is called I get an + "invalid spawn id(5) while executing "expect $exp1 {send -s "$send1} + timeout {continue}". I only have one spawn in the entire program + (a telnet session). I've tried setting a spawn_id variable for the + telnet spawn and then setting spawn_id to that variable in "looping", + but no dice, same error. + + Any ideas? Thanks in advance for any suggestions!!! + + Kelly Humbert + + proc looping {exp1 exp2 send1 send2} { + global max_tries ### 5 ### + set tries 0 + set connected 0 + set timeout 60 + + while {$tries <= $max_tries && $connected == 0} { + incr tries + expect { + $exp1 {send -s $send1} + timeout {continue} + } + expect { + ">? " {send -s "\n"} + timeout {continue} + } + expect { + $exp2 {incr connected;send -s $send2} + timeout {continue} + } + } + return $tries + }; + +What's going on is that the spawned process has closed the +connection. When Expect detects this, it matches the "eof" pattern, +and the spawn id is marked "invalid". However, you aren't testing for +"eof", so the next command in your script finds the invalid spawn id, +hence the complaint. + +If you want to find out where the eof is occurring, enable Expect's +diagnostic mode - Expect will get very chatty about what it is doing +internally. + +You can handle eof in all your expect statements by add a single +expect_before/after command to your script. + +Don + +====================================================================== + +#49. Could you put a version number in the filename of the Expect archive? + +From: "Nelson H. F. Beebe" <beebe@math.utah.edu> +Date: Mon, 23 Dec 1996 08:46:57 -0700 (MST) + +It would be helpful for the expect distribution to contain its version +number, e.g. expect-5.21.6.tar.gz; I had an earlier version called +5.21, and it took some diffing to verify that the expect.tar.gz I +fetched from ftp://ftp.cme.nist.gov/pub/subject/expect/expect.tar.gz +really was newer. + +I don't name the file with a version number because I make new +distributions so frequently. I realize that many other distributions +include version numbers in them, but constantly changing filenames +really annoys the heck out of people. I've been packaging Expect this +way for five years and I've only gotten this question twice before. +In contrast, I'm responsible for a number of other files on our ftp +server that do occasionally change names, and I get no end of +questions from people about where such and such a file has gone or why +their ftp request fails. + +So that people don't have to download the distribution only to find +it hasn't changed, there is a HISTORY file in the distribution +directory. It's relatively short and has the latest version number at +the top (with any changes listed immediately after). + +Don + +====================================================================== + +#50. Why does Expect work as root, but say "out of ptys" when run as myself? + +Expect works fine as root, but when I run it as myself it says "out of +ptys" (which I know isn't true). Any ideas? + +Sounds like a misconfiguration problem on your system. For +example, once I saw this on a Digital system where the system +administrator had decided to remove setuid from all programs ("I heard +that setuid is a security risk, right?"). On that particular system, +Expect uses a system library function that internally calls an +external program chgpt which exists solely for the purpose of managing +ptys. Needless to say, it must be setuid. Unfortunately, the library +function doesn't do enough error checking, and there's no way for Expect +to know that, so there's nothing I can do to give a better diagnostic +explaining how your system is misconfigured. + +Don + +====================================================================== + +#51. Why does spawn fail with "sync byte ...."? + +When I spawned a process using Expect, I got the following +message: + +parent: sync byte read: bad file number +child: sync byte write: bad file number + +This is one of these "should not happen" errors. For example, the +following question in this FAQ mentions that it could be the fault of +the C library. Another possibility is that you've run out of some +system resource (file descriptors). The most likely reason is that +you're calling spawn in a loop and have neglected to call close and +wait. + +Don + +====================================================================== + +#52. Why does Expect fail on RedHat 5.0? + +Lots of people have reported the following error from Expect on +RedHat 5.0: + +failed to get controlling terminal using TIOCSCTTY +parent sync byte write: broken pipe + +Martin Bly <ussc@star.rl.ac.uk> reports that: + +The fault is/was in the GNU libc (aka glibc) provided by Red Hat +Software. Our sysadmin updated the version of the C libraries we have +installed and both problems have vanished - in the case of the expect +test, without a rebuild. +====================================================================== + +#53. Why does Expect fail on RedHat 5.1? + +People have reported the following error from Expect on RedHat +5.1: + +failed to get controlling terminal using TIOCSCTTY +parent sync byte write: broken pipe + +If there are any people +who have some debugging experience and can reproduce that error on +RedHat 5.1, read on: + +First look in the man page (or perhaps diff the 5.1 and pre-5.1 man +pages) governing TIOCSTTY and let me know what you find. +Alternatively look at the source to xterm (or some other program that +must allocate a pty) and see how it is allocating a pty. + +If anyone else is wondering if the problem has been fixed by the time +you read this, just check the FAQ again. I'll update it as soon as +the problem has been successfully diagnosed. + +Don + +====================================================================== + +#54. Is Expect Y2K compliant? + +The short answer is: Yes, if you're using a modern version of Tcl +(7.6p2 or later). + +Longer answer: Tcl 7.5 and 7.6p0/1 had bugs that caused them to be +noncompliant with regard to how POSIX defines 2-character years. If +your scripts use 2-character years, you should upgrade to a modern +version of Tcl. If your scripts use 4-character years, than you have +nothing to worry about. + +Don + +====================================================================== + + +Names of companies and products, and links to commercial pages are +provided in order to adequately specify procedures and equipment used. +In no case does such identification imply recommendation or +endorsement by the National Institute of Standards and Technology, nor +does it imply that the products are necessarily the best available for +the purpose. + +Last edited: Tue Sep 22 17:52:23 EDT 1998 by Don Libes @@ -0,0 +1,3552 @@ +This is the HISTORY file for Expect. Modifications made by Cygnus +support are in ChangeLog. - Don + +Date Version Description +------- ------- ------------------------------------------------------ +1/31/06 5.44.1 Marius Schamsula <marius173@mchsi.xcom> reported tclconfig + missing, evidentally for new TEA. + +1/20/06 5.44.0 Lots of massaging to fix TEAification of Makefile and configure + including that version numbers will now be full three part. + + Daniel Wong <danielwong@berkeley.xedu> noted the home page + should note that Wikipedia has a very readable entry for + Expect. + + Andre Alves <aalves@escloyalty.xcom> noted passmass needed some + fixes to handle Solaris 9 passwd prompt changes. + + Andreas fixed several things: changes to better support TEA, + fix debugger interaction with nonblocking mode, and probably + other things I'm overlooking. + + Martin Dietze <di@fh-wedel.xde> noted that autoconf 2.59 is + confused by C comment after undefs in expect_cf.h.in. + + Added additional code to unbuffer -p so that if a process + earlier in the pipeline exits, unbuffer attempts to + recover any remaining output from the spawned proc before + unbuffer itself exits. + + Jeffrey Hobbs noted that once stty was called, a bg'd script + would be suspended at exit. Turned out to be overaggressive + code in stty that recorded what 'damage' the user might have + caused when calling stty in the first place. + + Jens Petersen provided patch to make setpgrp configure better + on some Linux systems. + + Added example/getpassck script to test for getpass bug. + + multixterm had debugging stuff leftover ("hello"). + +2/7/05 5.43.0 Martin Forssen <maf@tkrat.xorg> fixed bug in ExpOutputProc + that caused misbehavior during partial writes. + + Someone noted that gets stdin behaves differently (returns -1 + immediately) from tclsh because with 5.42, stdin is unblocked + by defaults. + + Robroy Gregg <robroy@armory.xcom> noted that expect_background + ignores timeouts. Added to documentation. + + Jens Petersen <peterson@redhat.xcom> provided patch for + "mkpasswd -vo". + + Gary Bliesener <gary.bliesener@nextel.xcom> noted that + multixterm failed on his system which had an old Tk that didn't + support the Tk package. + +8/3/04 5.42.1 Removed beta designation. + + Daniel A. Steffen <steffen@ics.mq.edu.xau> provided patch for + MacOS to avoid panic-redefinition. + +7/6/04 5.42b0 Releasing as beta because nonblocking mode is a big change in + the code. http://expect.nist.gov/beta.tar.gz + + Alexander Doktorovich <alexander.doktorovich@ericsson.xcom> + wanted to use Expect as a filter. This is possible but 'too + hard'. To make it easier, added close_on_eof command to + control whether expect/interact automatically close the + channel on eof. This should simplify/enable other scripts. + + Kurt Heberlein <kurth@3pardata.xcom> noted that Expect would + hang. Andreas tracked it down to a change in Tcl such that + when Tcl had data left in its buffers, it would check for more + data rather than returning what it had to Expect first. If + no data was forthcoming then Tcl would hang because the pty + driver runs in blocked mode. Recoded to use nonblocking mode. + + Yi Luo <yluo@brocade.xcom> noted that multixterm xterms were + reporting the parent's X window ids (via the WINDOWID env + variable) instead of the new ones. + + Dick Van Deun <dirk@dinf.vub.ac.xbe> noted that kibitz expects + to find write in /bin but it is in /usr/bin on Slackware. + Seems safe to drop the prefix. + + Steve Lee <steve@tuxsoft.xcom> noted that building Expect + failed on Linux when built from scratch because stty ends up + in /usr/local/bin rather than the assumed /bin. Added code to + support this. + +4/20/04 5.41.0 Simon Taylor <simon@unisolve.com.xau> provided fix for + interact -o which was completely broken by 5.40.1. + +4/6/04 5.40.1 Added scroll support to official tkterm. Copied all fixes + from/to term_expect to/from tkterm. + + Kiran Madabhushi <maskiran@hotmail.xcom> encountered interact + diagnostics incorrectly pointing to expect_background. Also, + found multiple -o flags behaving unexpectedly. Added diag. + + Kristoffer Eriksson <ske@pkmab.xse> noted typo in SIMPLE code + in exp_inter.c. However, this is extremely unlikely to affect + any machines. + + Reinhard Max <max@suse.xcom> noted that "make test" failed when + run in the background. The log testcase was testing the + send_tty command. Added code in both Expect and in the test + to handle this. + +1/30/04 5.40.0 Eric Raymond <esr@snark.thyrsus.xcom> provided troff-related + fixes for the expect, lib, and dislocate man pages. + + Rich Kennedy <rickenne@cisco.xcom> noted a bug having to do + with our caching of whether we have registered a filehandler. + This broke when Tcl was setting a handler on the same file. + + Ken Pizzini <ken.pizzini@explicate.xorg> provided patch for + leak in spawn error handling. + + Pete Lancashire <plancashire@columbia.xcom> noted autopasswd + example broke on Solaris which capitalized prompts. + +7/31/03 5.39.0 Poorva Gupta <poorva@cup.hp.xcom> noted that grantpt/unlockpt + order was backward. Strange that this was never a prob before! + + Andreas Kupries <andreask@pliers.activestate.xcom> noted that + in exp_command.c, Tcl_GetChannelHandle expected a ClientData*, + but got an int*. sizeof(int) != sizeof(ClientData) on 64bit + platforms. Crashed the command on a PA-RISC 2.0 machine with + --enable-64bit set. Fix: Use temp. variables of type ClientData + to retrieve the fd's, and copy this into the actual variables, + with a cast to int. + + More fixes from Andreas to sync this version with SF. + Fixed: exp_chan, weather, exp_main_tk. + + Eric Raymond <esr@snark.thyrsus.xcom> provided a troff-related + fix for the multixterm man page. + +7/29/03 5.38.4 Nicolas Roeser <n-roeser@gmx.xnet> noted confusion with md5 so + I made the Expect page more explicit about which file that hash + was based on. + +7/11/03 5.38.3 Josh Purinton noted that earlier fix wasn't quite right. Exit + on INT/TERM should cause Expect to exit with signal embedded in + status. He also requested I obfuscate email addresses in this + file. + +7/7/03 5.38.2 Guido Ostkamp <Guido.Ostkamp@t-online.xde> and Igor Sobrado + <sobrado@string1.ciencias.uniovi.xes> noted that fixline1 + rewrote scripts to be expect scripts even if they were expectk + scripts. + +5/27/03 5.38.1 Dirk Petera <dirkpetera@yahoo.xcom> noted that any_spawn_id + used to work but did no longer. Looks like a bug left over + from the the I18L conversion. Fixed. + + Steve Szabo noted exp_log_file -open channel failed. Fixed. + + Fixed bug from 5.31 that prevent stty from returning messages + from underlying program. + + Thomas Dickey <dickey@herndon4.his.xcom> noted that ncurses + ignores 2-char term names because of, well, poor assumptions + and coding. Changed tkterm to use longer names. + + Heath Moore <hmoore@systran.xcom> noted that exp_clib could + lock up if remtime happened to be precisely 0. Recoded to + avoid. + + At request of Per Otterholm <otterholm@telia.xcom>, wrote + script to read from stdin and echo passwords (exercise 9 in Tk + chapter of Expect book). Added to example directory as + passwdprompt. + + Josh Purinton <josh@purinton.xorg> pointed out that + by default, SIGINT/TERM should cause expect's return status to + be 1, not 0. + + Paul Reithmuller <paul.reithmuller@eng.sun.xcom> noted that + unbuffer shouldn't postprocess its output. Added stty_init. + + Mordechai T. Abzug <morty@sanctuary.arbutus.md.xus> noted that + log_file wasn't recording -append status. + + James Kelly <macubergeek@comcast.xnet> noted weather example + needed new source. + + Dimitar Haralanov <mitko@tahoenetworks.xcom> noted that + interact dumped core with interact { timeout 1 } + +7/18/02 5.38.0 At request of Hugh Sasse <hgs@dmu.ac.xuk> added md5 hash of gz + to homepage. + + Dave Schooler <dave@stashtea.xcom> reported that send -s wasn't + handling certains chars correctly. Turned out to be those + that had multibyte UTF8 reps. send -s was just pumping out + hunks of bytes without regard to UTF boundaries and evidentally + Tcl's I/O engine thought that it should translate a partial + UTF8 character into, uh, something else. + + Curt Shroeder <c.schroeder@computer.xorg> fixed bug in rftp - a + a filename looked enough like a 3-digit diagnostic that the + script got confused. + +4/16/02 5.37.2 Multixterm couldn't find man page all the time. + +4/16/02 5.37.1 Made multixterm handle user-supplied args. + +4/15/02 5.37.0 Added multixterm to example directory. + +4/8/02 5.36.1 Backed out CONST qualifiers. Too much trouble with older + versions of Tcl. I'll let someone else worry about them. + +4/8/02 5.36.0 Made first cut at multixterm, a replacement for crlogin. + + Fixed bug in background handler. If an action waited on the + same spawn id, esPtr would become invalidated. + + Ryan Schmidt <rschmidt@mac.xcom> noted configure didn't + recognize MacOS X. Downloaded new config.guess. + + Andreas Kupries <andreask@activestate.xcom> provided CONST + patches to accomodate Tcl changes per TIP 27. + +2/25/02 5.35.0 Joe Eggleston <joe@arbor.xnet> noted bug in full_buffer test. + The test hadn't been I18'd properly and was testing chars + instead of bytes. Also fixed diagnostics so it printed when + it was testing full buffer even if there wasn't one. + +2/7/02 5.34.1 Bruce Hartweg <brhartweg@bigfoot.xcom> noted that direct spawn + ids were not being tested so something like "expect -i exp9999" + would dump core. Evidentally a bug from the 5.31 transition. + +12/20/01 5.34.0 Don Porter <don.porter@nist.xgov> provided package-related + fixes for test suite. + + Brian Theado <brian.theado@usa.xnet> noted that interact's -re + support broke when offsets kicked in. Turned out that the + regexp engine supports them during execution but the results + are delivered RELATIVE to the offset. (I suspect this was done + due to expediency.) + +10/1/01 5.33.0 <mark@doradosoftware.xcom> found that expect's diagnostics + didn't include the "no" after testing for a full buffer. + + Hemang Lavana <hlavana@cisco.xcom> noted that "debug" (Dbg_On) + calls didn't always force the debugger into step mode. + + Martin Kammerhofer <dada@sbox.tugraz.xat> noted that the man + page neglected to document interpreter -eof. + + Chris Clare <clarec@nortelnetworks.xcom> provided fix for + multiple decl in C lib. + + Sheng Wang <wangs@sh.bel.alcatel.xbe> found interact's + can-match code had broken. It was missing the special hook + that Henry had added just for this purpose. How strange. + + Dieter Fiebelkorn <dieter@fiebelkorn.xnet> requested addition + to config.guess for Power*Macintosh:Darwin for MacOSX. + Aside - to download latest config.guess: + cvs -d :pserver:anoncvs@subversions.gnu.org:/cvs co \ + autoconf/config + + Added pipeline example to unbuffer man page. + +8/4/00 5.32.2 Allen J. Newton <anewton@alturia.fleet.xorg> provided code for + generating passwords with special characters in mkpasswd. + + Brent Welch <welch@ajubasolutions.xcom> changed the fix1line + install script so that "autoexpect" and other scripts that + get installed into the platform-independent bin directory + generically invoke "expect" from the users PATH instead + of hardwiring the platform-specific expect pathname. + + TclPro 1.4 released with 5.32.2 bundled. + +7/13/00 5.32.1 Uwe Klein <uwe-klein@foni.xnet> reported segfaults from reading + nulls. Due to code rewrite in 5.30->5.31 transition. + +5/14/00 5.32.0 New version for timing with Ajuba TclPro 1.4. This version + of Expect has no new features or behaviors but a lot has been + fixed since 5.31.0. + + Martin Buchholz <martin@xemacs.xorg> noted that his + alphaev56-dec-osf4.0e has ptmx and ptmx_bsd (and ptm, pts, + pty, ptym). He suggested that BSD things are now usually + deprecated so to skip ptmx_bsd if ptmx avail. + + Chang Li <changl@neatware.xcom> noted that debugger's bp cmd + broke on every command. Was a bug in breakpoint_trace from + when we installed the new regexp engine. + + Jonathan Kamens fixed printf formats in several pty diags. + + rm_nulls -d was set to wrong value. + +5/12/00 5.31.8 After receiving yet another request for fully versioned + archives, gave in. + + Signal handler sometimes sent error to stderr inappropriately. + +4/27/00 5.31.7 Rob Savoye fixed Debian ptys and properly checking of libpt. + +3/8/00 5.31.6 Petrus Vloet <petrus.vloet@siemens.xat> noted that Expect + installed tclRegexp.h which included regex.h which of course + misbehaves when it reads the system's version. This is new + since 8.0. Since I need to revise the Clib anyway (which + is what this install was for), I'll back this out for now. + +3/6/00 5.31.5 Larry Virden noted that configure checked for threads twice. + +2/19/00 5.31.4 Omer Azmon <oazmon@telsoft-solutions.xcom> note errors in + pty_termios.c in exp_pty_test that caused problems during + pty testing. + + Jeffrey Hobbs recommended having configure accept and warn + about --enable-threads. + + John Ellson <ellson@lucent.xcom> noted configure's autoconf + testing had leftover debugging code. Also provided a fix for + building w/shared libs on HP - appeared to be leftover from + earlier Tcl-required configuration that has now disappeared. + + Susan Muston <smuston@crosskeys.xcom> noted that exp_wait with + no spawned processes exited immediately which is different + than 5.29 behavior which reported "no children". This new + behavior was evidentally a gratuitous change during the + channel driver addition. Backed out. At the same time, + neither behavior matches documentation - doc should be fixed + and improved except I'm not sure if the behavior should yet + be something else (depending if stdin closed or not). + + istvan.nadas@epfl.ch reported "spawn cat;exp_open" failed. + Uninited variable. + + Scriptics reported memory leak. Was bug in parse_expect_args. + + "Michael P. Reilly" <arcege@shore.xnet> noted clib was hanging + in spawn code. status_pipe wasn't being closed. + + Egil Kvaleberg <egil@kvaleberg.xno> provided fix due to new gcc + which defines strchr as a macro. + + Dave Morrison <drmorris@corp.phone.xcom> noted some printfs + in exp_log.c that misinterpreted embedded %'s with resulting + core dumps. + + Dick Goodwin <goodwin@qosnetics.xcom> noted that "system echo + foo" returned with no apparent effect. Due to closeonexec + in expect's channel driver. Added skip if std channel. + Fixed similar bug in stty command. Minor bug left in stty + which isn't passing output back from underlying exec. + + Stacy W. Smith <stacy@ixc-comm.xcom> provided patch that uses + sigsetjmp instead of setjmp that he says fixes a problem he + encountered with C lib where it stopped timing out in expect() + as if the signals were corrupted. The man page doesn't + explain the difference between these calls in a way that makes + sense as to why they should make a difference, but I'll the + names are certainly suggestive so I'll try it. He says "it + appears that the linux setjmp behaves a little differently + compared to setjmp on some other OSs. Specifically, setjmp + on linux does not save the signal context. It seems most + BSDish OSs do save the signal context with setjmp. On those + machines, it appears setjmp(env) is equivalent to + sigsetjmp(env,1) whereas on linux, setjmp(env) is equivalent + to sigsetjmp(env,0). My patch made a (probably bad) + assumption that if siglongjmp() exists that we should use + the sigXXX versions. I specifically tested for siglongjmp + rather than sigsetjmp because on linux, sigsetjmp is just a + #define for __sigsetjmp. It appears that linux will give + the BSD behaviour if __FAVOR_BSD is defined, but I didn't + know what other implications that might have. + + Michael Schumacher provided fix so that test for whether + configure was out-of-date worked when not using the default + build dir. + +11/1/99 5.31.3 Shlomi Mahlab <shlomi@seagull.co.xil> noted all.tcl in CVS + but not distribution. + + More notes from Keith Brown on HP cc complaints in exp_pty.c. + +10/28/99 5.31.2 "Keith Brown" <surely@nortelnetworks.xcom> noted that HP cc + objected to auto aggregate initialization in + expLogChannelOpen. + +10/22/99 5.31.1 Official release! + + P Darcy Barnett <pdb@cam.nist.xgov> noted Makefile could + produce "autoconf not found" for non-developers using CVS. + Made configure detect and provide advice on workaround. + + Fixed bug in interact -echo exhibited in rftp example. + + Ryan Murray <rmurray@cyberhqz.xcom> noted Expect wasn't + handling handling 8-bit bytes correctly. I had accidentally + used Tcl_Write instead of Tcl_WriteChar. + + Ashley Pittman <ashley@ilo.dec.xcom> noted that digital unix + V5.0 prefers openpty (4000 ptys) over ptmx (60 ptys), so I'm + reversing the login in pty_termios.c. This also controls + linux, but no linux hackers have weighed in on this subject + yet. + + Andrew Tannenbaum <trb@world.std.xcom> noted exp_internal + command and "expect -exact" were broken. + +6/29/99 5.31.0 See the NEWS file for this date for an overview. (I'm + too tired to add all the details. Maybe later.) + + Fixed exp_clib so that it immediately reported failure of + exec (in spawn) rather than passing it back through pipe. + + Removed error checking from ioctl(TIOCSCTTY) to pacify the + variety of (but not all) Linux systems and a few others which + define TIOCSCTTY but return an error although seem to work + anyway. + + Added configure test for 0 vs 2-arg setpgrp. + + Kenji Kamizono <kenji@math.columbia.xedu> noted it was possible + to compile Linux (2.2.5) so that it recognized both openpty + and ptmx leading to conflicts. I arbitrarily chose ptmx. + +10/15/99 5.30.2 Herve Tireford <tdes46@email.sps.mot.xcom> noted extraneous + sleep(20) in clib. Apparently left over from debugging, oops. + +8/18/99 5.30.1 Added test for newer versions of Tcl that are incompatible. + + Kenji Kamizono <kenji@math.columbia.xedu> noted it was possible + to compile Linux (2.2.5) so that it recognized both openpty + and ptmx leading to conflicts. I arbitrarily chose ptmx. + +4/1/99 5.30.0 Martin Forssen <maf@crt.xse> provided fix to allow configure + to start with LDFLAGS from environment. + + Paul Tazzyman <Paul.Tazzyman@one.xat> noted that log_file + didn't check for logging twice without turning off logging + first. + + Ben <spy@calvin.iconoclasm.xorg> provided updated host for + weather example. + + Jonathon Kamens noted that Expect didn't build properly if + Tcl and/or Tk used build/install directories out of the usual + hierarchy. At the same time, I fixed a number of other related + problems in Makefile/configure. + + Pierre Pomes <ppomes@it.marseille-innov.assoc.xfr> provided fix + to ftp-inband. It blew up from an unprotected send that + was handed a uuencoded line that started with a -. + + Autoexpect was thrown off by simple-minded [file executable] + test picking up expect directory while searching for + executable. + +1/21/99 5.29.0 Martin Forssen provides mods to support INSTALL_ROOT. + + Bryan Surles <surles@scriptics.xcom> modified configure.in to + map DBGX to the same value as TCL_DBGX so the .so is named + correctly. + + Suresh Sastry <suresh@scriptics.xcom> forced $LIBS to be + added to EXP_SHLIB_LD_LIBS. It's not clear to me why this is + necessary (since Tk doesn't) but he was having a problem + with openpty not being found during runtime on Linux. + + Martin Forssen noted expectk was crashing if a Tcl error was + encountered. He found that exp_exit_handlers() was trying + to write into interp->result after interp had been deleted. + + Added another copy to distribution site - with version number. + + Stanislav Shalunov <shalunov@mccme.xru> closed race in pty + code. + + Fixed man page: -brace should be -nobrace. + + Dan O'Brien <dmobrien@lucent.xcom> noted that Expect needed to + call Tcl_FindExecutable at startup for info nameofexecutable. + + Robbie Gilbert <rwg@nc.fnc.fujitsu.xcom> noted indirect spawn + ids occasionally failed. Fixed. + +9/30/98 5.28.1 Brian France <franceb@fsj.co.xjp> noted that his compiler + rejected label with no statement. + +9/28/98 5.28.0 Fixed two bugs in tcl-debugger (see that HISTORY file). + + Submitted Expect documentation for official NIST review. At + their request, modified a couple things. + +9/21/98 5.27.0 Added support for Tcl 8.0.3. Simple compiles already work + fine but exotic things break. In particular, Expect needed to + understand new TCL_DBGX feature. Massaged debugger interface + which was recently revised. + + Karun Krishnaswamy <karun@transarc.xcom> noted that pine didn't + run in term_expect. The problem was that pine uses curses + (or terminfo) directly (!!) and insists on clear-to-eol (a + really dumb thing to insist on since it's so easily emulated). + + bert@xpilot.org (Bert Gijsbers) (of xpilot fame) provided patch + to passmass to handle ssh protocol and explanation of how to + create new password entries. + +6/15/98 5.26.1 Dean Sauder <dsauder@dcn.att.xcom> noted C-preprocessor lines in + configure must start in column 0. + +5/18/98 5.26.0 Kevin Schleicher <kms@lucent.xcom> noted xkibitz leaves xterms + if first xterm is HUP'd. Kevin also noticed a resource leak + in dislocate. Both problems fixed. + + Robbie Gilbert <rwg@fns.xcom> noted expect_devtty was logging + devtty (twice) to stdout. Fixed. + + Added support inttypes.h, required on Solaris 5.6 for termios.h + + Kristina <kristina@greatbasin.xnet> noted that tip failed when + spawned from a cgi script (BSDI BSD/OS 3.1 i386) because tip + didn't see a definition for SHELL and HOME. They need to be + set. (Doesn't have to be anything useful; the empty string is + fine!) Solution: documented this in Expect man page. + + Zachariah Baum <zack@studioarchetype.xcom> noted that + config.sub didn't recognize Intel 686. Found a newer version + that did in autoconf-2.11. + + POTENTIAL INCOMPATIBILITY: Changed interact so that it observes + parity while matching. It used to ignore parity. This impacts + people who use interact to connect through to a real serial + device that generates parity. If matches don't work, use the + exp_parity command. (This fix should have been made years ago, + when the exp_parity command was added. It is now absolutely + necessary now that people are doing matching with 8 bits.) + + After the second occurrence of a system admin who broke grantpt + by removing setuid from the relevant system util, I added an + explicit test and explanation. + + Disabled history in xkibitz. There seems to be some new + incestuous relationship between history and unknown now so that + redefining unknown leaves Tcl calling history but without + knowing what it is because it's never been defined (as it would + be by the traditional unknown). + + Fixed quoting bug in passwd.cgi example. + +9/28/97 5.25.0 Switched back to hand-generating pkgIndex.tcl file after too + many complaints about problems running pkg_mkIndex. + +8/12/97 5.24.1 Chris Schanzle <chris@goof2.ncsl.nist.xgov> pointed out that + install fails on a virgin file system because install_shared_ + lib depends on a directory that hasn't yet been created. + + Larry Virden gave corrections to URLs in README. + +8/21/97 5.24.0 Bo Johansson <bo.johansson@mbox2.swipnet.xse> noted TclWordEnd + had changed and provided fix. This caused crash in expect. + +8/18/97 5.23.0 This version supports Tcl 8.0 and continues support for 7.6. + Refs to Tcl_Files dropped. inter_return and close became + obj cmds. Rewrote notifier (again) to accomodate new notifier + model. Lots of other miscellaneous tweaks. Also see debugger + HISTORY file. + + Finally removed long-deprecated commands "continue -expect", + "send_spawn", and "getpid" and their exp_ versions. + + Harold Brauer <harold.brauer@canada.cdev.xcom> reported problem + with an old SCO system (i386-unknown-sco3.2v5.0) that turned + out to be due to a typo in the configure script. + + Jimmy Aitken supplied mods to config.guess for brand new and + very old Pyramid systems. + + Buz Owen noted memory leak in use of expect_background (with + no args). + + Jonathon Kamens noted provided patch for pty_termios.c for + modern Sequent (which ptmx). + + Jonathon Kamens noted that TCL defined RANLIB for shared lib + (if --enabled-shared) which isn't appropriate when Expect tries + to build both shared and unshared libs. + + Jonathon Kamens noted that shared lib config didn't work on + SunOS. I had used Tcl's SHLIB_SUFFIX instead of its + SHARED_LIB_SUFFIX. + + Qingyi Liao <liao@casabyte.xcom> encountered core dump when + exp_bg -i $exp_spawn_any was retracted. Bug in ecmd_remove_fd. + + Fixed a bunch of bugs in example/gethostbyaddr. + + Josef Sachs noted that stty cannot be caught when no /dev/tty. + It calls exit instead of returning an error. + + Gordon Chaffee <chaffee@plateau.CS.Berkeley.XEDU> patched + Exp_WaitCmd - it was zeroing pid element instead of wait. + + Bob Manson <manson@cygnus.xcom> provided fix for HP on which it + was possible for timer to be mistakenly deleted in + exp_get_next_event while processing a pty open event. + + Jeff Slonaker <JSlonaker@osc.uscg.xmil> noted that exp_poll.c + had wrong signature and poll had arguments out of order! That + would suggest that no one has ever used exp_poll.c before... + + 5.22.1 Larry Virden noted that TCL_BUILD_LIB_SPEC can't be used if + build directory has been removed. Added check to configure. + + Worked more on package command. Buz Owen pointed out that my + code wouldn't support redefinition of TCL_LIBRARY. Bumped up + minor version to avoid package loading mishaps. + + Nigel Standing <nigel@idiom.xcom> noted lack of C-u binding in + tkpasswd - must be due to change in tk4.2. + + Forced env(SHELL) to be defined inside kibitz for when using + with CGI. + + Charles Packer <packer@fermi.gsfc.nasa.xgov> noted that + CRAY-YMP needed sys/types.h in exp_console.c + + Extra / when developing defn of TCL_LIBRARY. Shouldn't + actually cause any problems though. + +2/3/97 5.22.0 Fixed package support - again. Sigh. + + David Pasirstein <dpasirst@sun.cs.wcupa.xedu> noted that RedHat + Linux 2nd passwd prompt requires slightly different pattern - + modified mkpasswd and tkpasswd. + + Toshiaki Nomura <nom@yk.fujitsu.co.xjp> provided patch to + config.guess for Fujitsu DS/90. + + Roger Brooks <R.S.Brooks@liverpool.ac.xuk> noted C lib passed + argv[0] instead of file to first arg of execvp. + + Cary D. Renzema <caryr@mxim.xcom> noted that a simple puts -nnl + might never appear - Expect closes all of its fds before Tcl + gets a chance to flush. Stdout is the obvious problem since + Expect thinks it can cavalierly close that too. Hmm. + + At request of Tom Tromey, solved possible missing tclRegexp.h + problem by having Expect install it. Cleaned up TCLHDIR and + TCL_LIBRARY hackery in Makefile. + +12/27/96 5.21.7 Nelson Beebe noted unset is not portable in /bin/sh. Removed + and converted everything to understand CONFIG_SHELL. + + Modified cryptdir to strip out shell metachars from filenames. + +12/10/96 5.21.6 Michael Schumacher noted that some systems cannot build + unshared libs from shared objects. Chose to go with BLT's + approach of building shared objs in separate shared directory. + + Buz Owen <ado@bbn.xcom> noted that "package require Expect" + didn't work because it looked for Expect lib in the wrong + place (well, the "documented" place). The problem is that Tcl + insists libraries should be in the same directory as the + pkgIndex.tcl file while the natural thing to do would be to + split them up and put the .tcl file in the arch-indepent + app-specific scripts dir and the lib in the arch-dependent + common dir. Sigh. If this is ever fixed/changed, the + instructions in the Makefile should be fixed. + + <Van.Trinh@siemenscom.xcom> noted that expect library name + exceed filename max on some systems - like his old SCO. + +12/4/96 5.21.5 Michael Schumacher noted new configure wasn't passing on Tcl's + shared lib cflags. + +10/26/96 5.21.4 Achyutram Bhamidipaty <ram@epic.xcom> ran into bugs in Expect's + file event handler which prevented expectk from entering + implied event loop. Also found one memory problem - thanks + to CenterLine. + + Tom Tromey fixed handling of --enable-shared when overriding + Tcl's value et al. Tom also added missing "else true" to + Makefile: "In a Makefile, you have to always supply an "else" + clause for an "if", to work around a bug in certain versions of + sh. In some versions of sh, an "if" whose test fails will + return the status of the test if there is no "else" clause -- + causing spurious make failures." See ChangeLog. + +10/18/96 5.21.3 Example directory was missing several examples. + +10/17/96 5.21.2 Debugger section of configure file corrupted. + +10/10/96 5.21.1 Oops, distribution unpacked into wrong version. + + Tom Tromey provided patch for stty to understand OSF 4.0. + +9/28/96 5.21.0 Official Expect release for Tcl 7.5. + + Junio Hamano <junio@twinsun.xcom> provided fixes for aclocal + for with_tcl/tkconfig. + + Roger Billau <rfbilla@amtnet.sandia.xgov> noted that C library + didn't work on Solaris 2.5. Turns out Solaris requires fflush + be called between input and output operations on FILE pointers. + + Lots of Cygnus mods - see ChangeLog. + + Sid Cowles <scowles@incyte.xcom> and Hans Riethmann + <hans@F1.telekurs.xch> noted relative path specs of + tcl-includes (and others) caused debugger config to fail since + it is at a different directory level. + + Al Snow <asnow@fuwutai.att.xcom> noted -C failed due to typo. + +8/17/96 5.20b18 Andrew Rakowski <andrew.rakowski@nr.usu.xedu> noted no defn of + LIB_RUNTIME_DIR, a creation of Tcl7.5p1. + + Tom Tromey added -v to Expect and -version to Expectk. + + Ben Boule <bboule@xylogics.xcom> noted that Interactive (IUNIX) + requires 9 char max length after -l. Looks like squeezing out + the "." is sufficient. He also noted that IUNIX needs -Xp in + LIBS to find strftime. This test should really be done by Tcl. + +8/12/96 5.20b17 Glen Biagioni <glen@prosoft.xcom> noted interact -re "A(xx)" + failed to match. Problem turned out to be that Tcl 7.5 changed + a constant which in the regexp code, which Expect didn't see + because it provides its own defn for interact. Alas, the one + thing Expect reuses from Tcl was where the change was. This + should really be fixed so Expect doesn't rely on Tcl in this + way, but there's no point in putting in a lot of work on regexp + when we're anticipating a new one soon anyway. + + Bjorn S. Nilsson <nilsson@nbivms.nbi.xdk> noted fixcat hangs. + Turned out that new Tcl (7.5p1) now waits for all children to + disappear. But Expect still had a handle to a child. I added + an exit handler to close the connections before Tcl's exit + handler. + + Tom Tromey provided patch to support augmenting CFLAGS on + Makefile invocation. + + Gary Merinstein <gmerin@panix.xcom> noted that configure failed + on his linux unless it had --enabled-shared. Not quite sure + about how this can be, but the flag wasn't being passed to the + debugger's configure, so I've fixed that and hopefully this + will cure the original prob. + + Added initial announcement of full version at beginning of + configure. This should ease my pain in responding to people + sending me config output without including version numbers. + + Tom Tromey noted expect_cf.h was machine dependent. Fixed + expect_comm.h so that it no longer required expect_cf.h (which + should be renamed to indicate it is no longer public). + + Bart Robinson <lomew@cs.utah.xedu> provides mods to support + openpty() in FreeBSD/NetBSD. Without openpty, Expect doesn't + see the full pty namespace (ptyX[0-v]). + +7/15/96 5.20b16 Nathan Estey <nfe@the-hermes.xnet> noted that Makefile failed + on SunOS when shared libs were enabled due to incomplete dot + stripping in lib prefix. + +7/6/96 5.20b15 Malcolm Tredinnick <malcolmt@geko.net.xau> noted that shared + lib has to be installed before building expect. Also noted + that ldconfig should be run on Linux 2.0 systems and maybe + others. + +6/25/96 5.20b14 Tim Mooney provided fixes to obey --includedir and similar + configure conventions. + +6/25/96 5.20b13 A bug when installing Expect using new _installed targets. + +6/24/96 5.20b12 Numerous complaints from Solaris users about shared libraries. + Unfortunately, no one is giving me configure-ready fixes so + (and Tk's configure seems to have bugs as well) so fixing + these is like throwing darts. + + Stan Brown <stanb@netcom.xcom> noted noidle example broke when + fed "-". + + Gordon Irlam <gordoni@cygnus.xcom> noted typo in install-sh. + + David Sheinberg <sheinb@bcmvision.neusc.bcm.tmc.xedu> noted no + args test for spawn -open/leaveopen. + + Misc patches from Tim Mooney to pacify much of gcc -wall. + + Kayvan Sylvan insists Linux stty reads from stdin so added + hardcoding to configure.in for that. In xkibitz, Linux stty + -raw didn't disable all post-processing. How odd that it is + not a problem in interact. In the meantime, added extra stty + to xkibitz to do what was missed. + +5/30/96 5.20b11 Kayvan Sylvan <kayvan@sylvan.xcom> noted quoting bug in + autoexpect. + +5/22/96 5.20.b10 Patches from Larry Virden in Makefile.in and exp_int.h + +5/20/96 5.20.b9 Too many substitutions in configure caused sed failures on + DEC (limit 99) and HP (100). Commented out definitions + that weren't absolutely critical. Hopefully, this gets us + under the limit but can't be sure since there's no easy way + of knowing. + + Numerous mods from Mark Diekhans to support clist-style ptys + on SCO OpenServer. (He says SVR4 ptys are broken on that + platform.) + + Simon J. Gerraty <sjg@zen.void.oz.xau> says that write() + returns 0 inside of exact_write on SunOS. This is outside the + SunOS spec so of course we have no idea what's going on. So I + added code to try and recover from (or at least warn of) this. + + Tom Tromey unified decls of errno to #includes. + +5/13/96 5.20b8 Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.xedu> pointed out + backwards stty test - this would have corrupted every platform! + He also pointed out that alpha-dec-osf3.2 (3.2c) complained + too many args to sed. Someone earlier said similarly about + HPUX 10, but I assumed it was the quotes in the weird stty + flag I was passing, so that "fix" wasn't. GNU sed has no + problem, but obviously this is not sufficient for many people. + +5/10/96 5.20b7 Renamed/numbered versions so that it's easier for others to + track. + + Upgraded to autoconf 2.10. + + Matthias Kurz <mk@baerlap.north.xde> noted Makefile problems + with final Tcl7.5. + + Blair Zajac <blair@gps.caltech.xedu> noted configure mishandled + stty defaults on HP and shared lib must be installed executable + on HP. + + autoconf insists on adding -O to CFLAGS when using gcc. Ack! + +3/23/96 5.20b1 Beta release 1 of Expect for Tcl 7.5. + + Michael Hunter <mphunter@qnx.xcom> provided misc mods for QNX. + + Various people reported problems with IRIX. Removing from the + stty list fixed the problem. Similar problem with Solaris. + + Added explicit close to autoexpect. Added a mechanism for + enabling conservative mode after script is generated. + + Hal Schechner <hal-j@netusa.xnet> pointed out passwd.cgi must + meet passwd's requirement that it not be run by an unrelated + user. Easy enough - just do an su first. + +3/26/96 5.20a5 Alpha release 5 of Expect for Tcl 7.5b3. + + Added example passwd.{html,cgi} to change a password. + + Many fixes from Stephen Williams <steve@icarus.xcom> + and Jonathon Kamens for Makefile and configure. + +3/22/96 5.20a4 Alpha release 4 of Expect for Tcl 7.5b3. + + Added version number to lib directories (POTENTIAL + INCOMPATIBILITY). + + Revised gethostbyaddr example - evidentally hadn't worked for + some time! + + Jan Nijtmans <nijtmans@nici.kun.xnl> provided pkgIndex.tcl.in. + Renamed Exp_Init to Expect_Init to support package cmd. + Provided #define so that Exp_Init will continue to work. + + Revised exit handling so that it works if Expect is dynamically + loaded. + + aclocal.m4 Patches from Tom Tromey. + +3/15/96 5.20a3 Alpha release 3 of Expect for Tcl 7.5b3. + + Edward Haletky <elh@astroarch.xcom> noted that Machten required + inclusion of types.h in exp_tty_in.h. + + Added various patches from Rob Savoye. One incompatibility + is that the static lib now ends with the version number. + + Added support for TCL_SHLIB_{LD_LIBS,VERSION} in Tcl b3. + + Jonathan Karges <J.Karges@dkfz-heidelberg.xde> found that clib + was timing out immediately on -1. + +3/6/96 5.20a2 Alpha release 2 of Expect for Tcl 7.5b2. + + Leland Joseph <leland@tec.tetd.bellcore.xcom> noted + expect-tests.exp exceeds the 14 character filename length. + + Added config.{sub,guess} to support AC_CANONICAL_.... + + Rewrote much of aclocal, configure.in, and Makefile.in + to handle Tcl/Tk config.sh files and shared/dl support. + + Simplified varargs/stdarg mess for Expect's C library. + + Threw away closetcl junk. No longer required because + Tcl finally started doing close-on-exec. + + Incorporated various fixes from Tom Tromey at Cygnus. + See ChangeLog for details. + + Added require/provide support. + + Rejiggered event handling to support new Tcl_File interface. + + Removed libexpectk. Because event loop was moved into Tcl, it + is no longer necessary for it to be different than libexpect. + + Removed all support for earlier versions of Tcl and Tk. + + Numerous misc patches from Paul Eggert <eggert@twinsun.xcom> + most to support Tcl 7.5. + + Arnold Robbins supplied yet another patch to fix earlier + problem noted by Hume Smith. + + David Engel <david@ods.xcom> reported problem with Linux + dumping core. CenterLine, of course, immediately found the + problem - uninit'd lowercase buffer. + + Peter Haggerty <haggerty@borg.lib.vt.xedu> noted that his Next + died in cron. It seems that Next doesn't support O_NOCTTY + (even though the man pages says it does) and so during pty + testing, control terminal would get allocated and then kill + the process (by generating a HUP) when deallocated. Avoid + by ignoring HUP when doing pty testing on such machines. + +1/3/96 5.19.0 Fixed bug that made expect report wrong string when using + a terminating anchor in a positive-length glob match, + reported by Graham L. Randall <grandall@nit.airtouch.xcom>. + + Added rlogin-display to included examples. rlogin-display + automatically propagates your $DISPLAY when you rlogin. + + Hume Smith <hclsmith@localhost.isisnet.xcom> noted problem + with day of the week calc at year end/start. Arnold Robbins + supplied fixes. + + Jonathan Kamens provided fix to make sync byte reads + recover from EINTR. + + Henry Spencer noted errant line of spaces in Makefile. + +10/21/95 5.18.1 Began adding support for tcl7.5a1/tk4.1a1. (not finished!!) + - Make aclocal understand new Tcl/Tk directory layout + for finding tclInt.h and private libraries. + - Added support for Tcl_AsyncReady. + + Paul Townsend <aab@aab.cc.purdue.xedu> noted that distclean did + not remove some config cruft. Also recommended unsetting + M*FLAGS that cause make called from configure to fail. + + Various fixes from Cygnus. See Changelog. + + Deleted "-" before rm in loop in deinstall in Makefile as per + Doug Claar <dclaar@hprtnyc.ptp.hp.xcom>. Doug also found prob + involving recent STTY fix. Symptom was that pty wasn't + correctly inited in cgi scripts on HPs - and Cray pty support + blew up entirely. + + Added exp_ prefix to tests so that they can be run with other + extensions. + + Seth Ornstein <pp001465@pop3.interramp.xcom> noted bug in the + way rftp detected symlinks. + + Upgraded to autoconf 2.4. This fixes a bug in AC_PROC_CPP + which blew up when CPP was defined in the environment. Noted + by John Pfuntner. + + Jonathan Kamens noted that library didn't check return pipe() + return value. + + Added vrfy example. + + Przemek Klosowski <przemek@rrdjazz.nist.xgov> Irix 6.0 fails + to use ptys that have been used by someone else. SGI admitted + this is a bug and the solution is to upgrade to 6.1. + + Yoad Grinberg noted "expect -timeout" mistakenly ate next arg + as pattern. + +8/24/95 5.18.0 Wayne Christopher noted that the way exp_eval_with_one_arg + modifies the original argv makes the ICEM Tcl compiler unhappy + so I rewrote it to avoid that. + + Ian Zimmerman <itz@rahul.xnet> found that a braced arg list of + a single pattern beginning with a \n caused expect to reeval + for multiple args twice. I added a -nobrace flag that expect + and/interact can use internally to prevent this. + + Florian La Roche <florian@jurix.jura.uni-sb.xde> noted a few + glitches in the way -ltcl was searched for in aclocal. + + Joachim Posegga <posegga@ira.uka.xde> noted lack of Tcl + internal includes should be an error during configure. + +8/10/95 5.17.8 Martin Wunderli <wunderli@baloo.limmat.net.xch> found missing + quote in config. + + Danny Faught noted problems in Makefile when passing STTY defn + with quotes. Created another a STTY-less CPPFLAGS for cases + where additional reexpansion occurs. + + Danny Faught noted bug in error handling for checking + permission problem with /tmp. + +8/1/95 5.17.7 Todd Rimmer <trimmer@mantis.ssw.xcom> noted that HP 10 with + optional streams package has both PTYM and PTMX which conflict + in pty_termios. + + Rainer Wilcke provides fixes: scripts not listed as dependency. + distclean target used Makefile after deleting, and many fixes + to man pages. + + Saad Mufti <mufti@hobbit.pls.xcom> noted bug in how C library + handled polling (when handling multiple fds). + + Jeff Bowyer noted more autoexpect bugs. + +7/22/95 5.17.6 More features added to autoexpect (now version 1.3). + + Sanjay <sanjay@clef.lcs.mit.xedu> noted bug in TCLH config + macro which caused it to use 7.3 instead of 7.4. + + Rodney Barnett <rlb@us.teltech.xcom> noted expectd.proto had a + few refs to interact_out where it should've had expect_out. + + Terry Rhodes <tbr@88open.xorg> noted that Expect returned a 0 + exit status upon syntax error unlike tclsh and wish. + + Fred Obermann <fredo@conan.ids.xnet> noted that Unixware 2.01 + native development tools don't permit configure to find memcpy + because memcpy is handled specially by the compiler and it + complains when it finds configure's default test with no args. + Changed to a hand-crafted test with args. + +7/12/95 5.17.5 Jeff Bowyer <jbowyer@muni.xcz> noted minor bugs in autoexpect. + + Rob Saul <robs@sco.xcom> noted that configure failed on SCO + OSR5 because trap requested by Cygnus (to allow config in bg) + used higher traps than SCO sh knows about. + + Changed "can't happen" to "xmkmf is broken" when configure + fails to compile simple C-Tk program. + + John H. Chauvin <jchauvin@netcom.xcom> noted exp_tty_current + and cooked raised multiple def errors on SGI 5.3 with native + cc. + +7/9/95 5.17.4 Wolfhardt Lotz <s11@blue.lrw.uni-bremen.xde> noted Solaris + doesn't do case-insensitive man page lookups so I lowerized + the beginning of the .SH lines. + + Henry Spencer noted unbackslashed quotes in the autoexpect + boilerplate. + +7/3/95 5.17.3 Modified VARARGS decls to support new Tcl 7.4 definitions. + + Fine-tuned aclocal so that it would prefer later versions. + + Added autoexpect example and man page. + +6/30/95 5.17.2 select-based dsleep() was returning an internal expect-style + return code instead of a Tcl-style. + +6/30/95 5.17.1 Kannan Varadhan <kannan@isi.xedu> noted aclocal didn't + look in right directories to find Tk. + +6/30/95 5.17.0 Modified regexp interfaces to support Tcl 7.4b4. + + Mods from Tony Isles <ittony@traf.xcom> for Sequent Dynix/ptx + V2.1.5 (which is really old). + + Michael Schumacher <hightec@rz.uni-sb.xde> noted that Solaris + 2.4 header files require __EXTENSIONS__ for all sorts of + traditional but non-standard definitions. + + Modified aclocal to support new Tcl/Tk library names. + + George Forman <forman@cs.washington.xedu> requested support in + C lib for fds that already exist. I added exp_spawnfd. + + Fixed bug preventing signal rearming on Linux (using SV-style + signal handling). + + Wayne Christopher <wayne@pmac.icemcfd.xcom> noted missing + interp in call to exp_error. + + Added null support to interact's exact matching. + + Bruce Jerrick noted INSTALL was being used rather than + INSTALL_PROGRAM/DATA. + + Dennis Ferguson <dennis@mci.xnet> noted that on Solaris 2.4 + close(pty) occasionally returns EINVAL. + + Added tests so that if we can't get a pty, we can give the user + much more help with what to do about it. + + Steven Byrnes noted that Solaris has replaced TIOCCONS with + SRIOCISREDIR interface. + + Technically speaking, interact shouldn't do buffer-shuffling + but I've added as a fail-safe mechanism to catch people who + use preposterous patterns. + + Alan Heckert <heckert@tiber.nist.xgov> noted missing decl in + Convex pty support. + + Fixed all expectk examples for Tk4. + + Bryan S. So <so@cs.wisc.xedu> noted that interact -o eof failed + if an unbuffered pattern was partially in progress. + + Added -timeout flag to expect command to override timeout var. + + John Pfuntner <pfuntner@VNET.IBM.XCOM> noted that OpenMVS did + not notice @ inside of Makefile SETUID macro as suppression + but instead treated it as part of the program name. + + Jim Porter <James.W.Porter@att.xcom> noted that exp_free_i + freed the variable name even if not allocated. + + Yet more mods to aclocal and various .in files from Rob Savoye. + +4/21/95 5.16.3 Matija Grabnar <Matija.Grabnar@ijs.xsi> noted that sleep maxed + out after about 36 minutes. Turned out to be a poor assumption + in some interfacing code. + +4/19/95 5.16.2 rbd <uport@netcom.xcom> noted tcl_RcFileName multiply defined + when compiling with Tk4. + +4/16/95 5.16.1 Robert Nicholson <robert@steffi.dircon.co.xuk> noted NextStep's + sys/wait.h is not POSIX-like so WNOHANG fails to get a defn. + + Alexandre Rafalovitch <arafalov@socs.uts.edu.xau> discovered + example on dislocate man page didn't work. I fixed it. + +4/8/95 5.16.0 gcc 2.3.3 complains about internal errors so I figure: time to + upgrade. Switched to Cygnus 2.6-95q1. Works now but now + complains about wait status. I trashed all the gory wait + status configure code and adopted autoconf's suggestion about + refusing to use sys/wait.h if not POSIX.1 compatible. Nice! + + Jeffrey C Honig <jch@nr-tech.cit.cornell.xedu> requested a -gmt + flag for timestamp command. + + Chuck Ocheret <chuck@gigadactyl.xcom> noted that expect -pty + fails. Problem is that Tcl's exec blindly closes all the fds + between 3 and its own highest fd. See comments in code. + + Loris Caren <loris@caren.demon.co.xuk> noted eof in fg bombs on + Linux. Turns out to be analogous to eof in bg problem fixed + in 5.14.0. + + Upgraded to autoconf 2.3. Continued making changed to config + script to take advantage of autoconf 2 capabilities. + +4/1/95 5.15.4 Steve Simmons noted .x remnant from earlier dir install proc. + +3/31/95 5.15.3 Forgot to export TCLHDIR defn when configuring debugger. + +3/29/95 5.15.2 Steve Simmons <scs@aisinc.xcom> noted Makefile multiple defined + distclean and it might be nice to provide aclocal.m4 even + though it isn't normally used. + + cevans@resdev1.ppco.com added prompts to passmass for AIX. + +3/27/95 5.15.1 Fixed tkterm script - inadvertently left tic debugging on. + Also add support for Ctrl-space and Ctrl-@ as requested by + Zbigniew Wieckowski <wieckows@cs.umn.xedu>. + + Larry Virden asked that configure also check for .so libs. + +3/23/95 5.15.0 Everitt Beers <ebeers@scf.usc.xedu> noted that Linux doesn't + support kill -STOP 0. Changed 0 to [pid]. + + zhengping (z.) you <you@bnr.xca> found bug where a bg expect + did not rearm a spawn id after a first bg expect (and another + one) to clear it. + + Elliott Wolin <wolin@physics.wm.xedu> noted that tkterm + complained if tic wasn't found. I'll have it override the + user misconfig in that case. Also noted that interact failed + on AIX. Evidentally, my new config tests for ISC found that + AIX looked just like it. Added additional test for tcsetattr + to distinguish them. + + Rob Savoye asked for Dbg config.in to be distributed. Rob + supplied numerous other mods: install-sh replaced install.sh, + mkinstalldirs, testsuite mods, new aclocal.m4, support for + recursive make. + + Fixed bugs in configuration of debugger. + + Disabled configure's file-caching. + + Kannan Varadhan <kannan@isi.xedu> noted incorrect diag + reporting TCLHDIR in configure. + + Marty Olevitch <marty@howdy.wustl.xedu> noted that DEC Alpha + did not sleep correctly because configure didn't find sleep + and found poll (which is broken). Problem turned out to be a + bug in autoconf's AC_CHECK_FUNC. Got patch from Jim Meyering + <meyering@comco.xcom> + + Fixed config probs for Edward Huie <huie@net.xcom> on Mac + SE/30, System 7.1, Tenon Intersystems' MachTen 2.1.1-G (BSD 4.3 + on Mach kernel) and MachTen X11R4 3.1. + + Moved libraries forward in configure to allow for AC_CHECK_FUNC + to succeed when funcs are in other libraries. + + Made configure test for Linux and unset CFLAGS=-g if so. + +2/25/95 5.14.3 Larry Virden noted configure was missing brackets in raw shell + cmds evidentally due to m4 interpretation. + +2/24/95 5.14.2 Larry Virden noted configure was not correctly rewriting from + --(exec-)prefix. Due to new autoconf. Also noted glob was + finding tclX directory. + + Hal Peterson noted that because configure now actually attempts + a link before using a library, the code to check for -ltk would + have to worry about all the other utility libraries first. + +2/23/95 5.14.1 Hal Peterson noted that configure.in checked incorrectly for + tcllib. + +2/22/95 5.14.0 Jamal <root@lonestar.tlug.xorg> noted Linux has tic in a + different place than on my system - affected tkterm script. + + Xiaokun Zhu <xiaokun@stats.gla.ac.xuk> noted problem on DEC + Alpha OSF/1.3 evidentally due to backwards decl of index macro. + + Greg McFarlane <gregm@nms.otc.com.xau> noted that large args in + send cmd cannot be passed blindly to exp_error. + + david d `zoo' zuhn <zoo@armadillo.xcom> requested modifying + configure so that it did not require Tcl/Tk to be built - only + configured. This means that it may not find installed + libraries. Hopefully, this won't cause anyone problems but its + not my preference. + + Fixed error which caused spurious eof when changing patterns + in expect_bg. + + Moved to autoconf-2.1 and m4-1.4. Rewrote a LOT of the config + file. Finally got my hands on an ISC box and fixed configure + for that. + + Tony Booker <tb@sequent.xcom> provides mods for Sequent ptx 2 + and 4. + + Jeffrey Friedl <jfriedl@nff.ncl.omron.co.xjp> provided fixes + for timezone handling in config and exp_strf.c. + + David Schmitt <dschmitt@netcom.xcom> noted that library did + not detect eof on HP. I didn't think this was necessary for + read() but it evidentally is. I added the support for raw fds + although it is not obvious to me how to do it for FILEs. + + James Carter <jimc@math.ucla.xedu> noted expect_after couldn't + worked in the exp_bg because I had accidentally written BEFORE + instead of AFTER when checking the cases. He also found that + the eof body could be trashed in an exp_bg. + + Ousterhout apologized for the Tcl7.4 change I noted in 5.13.1 + and said he will undo it. + + Eric Frias <efrias@vt.xedu> found library bombed after + timeouts. exp_match_end was not updated - which makes sense + since there was no match - however the following expect call + assumed that exp_match_end was meaningful in order to do its + buffer shuffling. + + Jonathan Kamens supplied new configure test for REARM_SIG after + noting old could fail if limit prevented creation of core file. + He also noted REARM_SIG had accidentally been commented out + of cf file. + + Vincent D. Skahan <vds7789@aw101.iasl.ca.boeing.xcom> noted + that Apollo's stty reads stdout and doesn't complain if its + bogus. + + Yoad Grinberg <grinberg@vnet.ibm.xcom> noted that SIGCHLD does + not work for forked processes, only spawned processes. Fixed + this and added counting to make sure none get lost. + + Hal Peterson contributed mods for Unicos. He noted that + configure should be more careful adding libs to the link line. + On the Cray, non-existent libs generate warnings which are not + detected by configure but which annoy make. + + Bela Gazdy <bela@euch3e.chem.emory.xedu> noted /etc/resolv.conf + misspelled in kibitz. + + Rainer Wilcke noted that "send -null/break" mishandled return + code, and these and send/expect_tty were not in man page. + + Dvorak example was missing -- in send -. + +1/12/95 5.13.2 Peter Wassenaar <peterw@stack.urc.tue.xnl> noted that kibitz + didn't work on AIX. My fixcat script assumed that AIX's cat + was like HP's cat - buffered by default. + +1/7/95 5.13.1 Marc Bouron <mbouron@lhr-sys.bru-ro.DHL.XCOM> noted I forgot to + add virterm to distribution. + + Marc W. Mengel <mengel@dcdmwm.fnal.xgov> noted that configure + must be run in the foreground due to the stty tests. Added + this to documentation. + + Modified interpreter to account for the change in Tcl7.4 which + forces Tcl_RecordAndEval to call Tcl_GlobalEval instead of + Tcl_Eval. + + Changed ptys to be initialized based on current tty setting + rather than original tty setting. + + Stephen Melvin <melvin@zytek.xfr> noted that set -e is the real + problem with ash (see 5.13). I bet "[" is returning a value + and triggering it. It appears that the script can live without + the set, so out it goes. + + Braun Brelin <bbrelin@netcom.xcom> noted pipe allocs in spawn + could fail with meaningless error message. + +12/15/94 5.13.0 Synchronize with appearance of "Exploring Expect". This + distribution corresponds to the book both in description of + Expect and in containing all the substantive examples. + + Graham Mark <gam@lanl.xgov> noted that his Cray (Unicos + 7.0.6.1) didn't recognize TCSETCTTY. Since this was in some + Cray-specific code, I guess Unicos must have changed some .h + files. I made it include either termios or termio. It, at + least, works on our Cray (Unicos 8.0.2.4). + + Robert Withrow <witr@rwwa.xcom> noted that FreeBSD 1.1.5.1 + supplied union wait but waitpid doesn't use it! So I modified + configure to be smarter. He also noted that its /bin/sh is + really ash which blows up on install.sh. It appears that it + doesn't handle uninitialized parameters correctly. I'm not + going to fix this because having a broken /bin/sh is so awful + probably other things are breaking too. He did note that it + worked if he switched to bash or the native install, but that + blows the whole point of install.sh - that we have found too + much variation in native installs. Rather than try and figure + out everyone's variation, we'd like to simplify our life and + use this common, simple-to-understand sh script. + + Added more example scripts: Adrian Mariano's virterm (like + expect_term but without relying on Tk), gethostbyaddr, and + expectd.proto for telnet daemon. + + Matt DiMeo <mdimeo@brooktree.xcom> noted that expect_background + failed to detect eof on HP. I had forgotten to pass the mask. + + Josef Sachs noted that expect_background put Tk's event handler + in an infinite loop if it was listening to a pipeline that was + killed. I had aborted the cleanup procedure if Tcl's close + reported an error. That was a mistake. + + Rick Lyons <rick@razorback.brisnet.org.xau> noted a bug. C lib + expect would turn a normal read into a poll if remtime reached + zero on the nose. + + Added ResetResult to Exp_Init to clean up diags in Expectk. + Made GENFUNCs return -1 on error as per ParseArgv's convention. + +11/13/94 5.12.0 Alon Albert noted that in clib, exp_match_end should be init'd + to exp_buffer before trying to match the pattern - if the + expect doesn't produce a match, exp_match_end is incorrect and + will be wrong for subsequent expects. + + Steven Diamond noted that fg expect did not react to a change + in an indirect spawn id list if it was just waiting for I/O + (rather than looping in exp_continue). + + Wait fix in previous version broke system() whose return value + is horribly overloaded. + +11/10/94 5.11.0 Stephen Fitzpatrick <sfitzp@cs.qub.ac.xuk> noted that NeXT wait + macros do not accept int wait status. Switched to using Tcl's + detection of wait status type. + + Made log_file -leaveopen leave file id open until close like + spawn -leaveopen did. + + Bruce Jerrick <bruce@cse.ogi.xedu> noted public include dir + wasn't getting created. + + Karl Vogel noted 1) Pyramid has index instead of strchr, strf.c + needs sys/time.h instead of time.h in strf.c, needs to call + timezone(), and stty reads stdout but usual stty test fails. + + Made expect_out(spawn_id) always be written to assist people + who want to log different procs to different files. This is + no longer an efficiency problem because interact can do so + much more then it used to. Made full_buffer condition write + forgotten chars even when full_buffer isn't explicitly + specified. + + Bert Robben <Bert.Robben@CS.kuleuven.ac.xbe> noted that the + debugger needs to know about the presence of stdlib.h. I was + hoping to avoid this because it's a pain getting configure to + call another configure. + + Rainer Wilcke provide several improvements for xkibitz and man + page. + +10/6/94 5.10.0 Moved example files around. Added password generation to + tkpasswd. Created standalone script to generate and set + passwords - good for all those adduser shell scripts. + + Rick Cady <rickc@NSD.3Com.XCOM> found a bug when switching log + files. + + Rainer Wilcke <wilcke@esrf.xfr> noted that xkibitz died when + closing a connection. stdin was mistakenly being closed. He + also noted that killing xterms under HPUX 9 requires kill -9. + + Enzo Michelangeli <enzo@airhk.air.xorg> noted that SCO 3.2.1 + defined window size structure in ptem.h. + + Josef Sachs <sachs@panix.xcom> found a bug when calling fg + expects repeatedly between bg expects. On the first fg expect, + it cached the fact that the filehandler was armed. The next + background expect disarmed it but failed to update the cache. + + John P. Rouillard" <rouilj@dstar.iddis.xcom> provided configure + support for --with-{tcl,tk}{lib,include}. + + Mike Figg <figg@pencom.xcom> noted that man page used old style + of continue command. + +8/23/94 5.9.1 Adrian Mariano noted it would be useful to have exp_continue + not reset the timer. Added flag to support this. + + Morris Gasser <gasser@ksr.xcom> noted that lowering match_max + didn't work (lib was broken too). + + Keith Hanlan provided a fix for exp_exact. + + Added more examples: mkpasswd, tkterm, term_expect. + + Put close_tcl_files in sep file for easier non-Tcl use of clib. + +8/21/94 5.9.0 Fixed window handling code - on AIX, termios does not define + TIOCGWINSZ. Instead, you have to include ioctl.h. Of course, + you have to avoid the trap of including both on OTHER systems + such as SunOS 4.1 where the include files conflict! + + Dan MacDonald found that close in async routine caused sync + expect to blow up. + + Missed deletion of last line of out macro in exp_inter.c + + Simon Warfield <simonw@bwh.harvard.xedu> noted bug in xkibitz + help message. + + Fixed exp_background to use global scope instead of current. + + Steve Diamond <sdd@aplcomm.jhuapl.xedu> noted that -i "4 5" + only used spawn id 5. + + Rob Nagler found yet another bug in log_file when called + incorrectly. + + Expectk wasn't creating a window by default. + +7/25/94 5.8.1 Made exp_interp external. Users should be able to set this + explicitly. + + David Barnett <davidb@cats.ucsc.xedu> found that Linux was not + getting a controlling terminal. The original test for doing + that was based on Stevens and tested in a very nonspecific way + for the presence of a Sun via CIBAUD. Replaced this with a + more specific test. + + It seems Tcl 7.3 broke my -nostack hack. The top-level interp + translates unknown return codes to TCL_ERROR. Sigh. I wish + Ousterhout would stop all of those translations. If the user + wants them, they can do so themselves, but now they're forced. + + Martin Buchhoz <buchhlz@vnet.ibm.xcom> suggested adding + XKIBITZ_XTERM_ARGS environment variable to xkibitz. He also + noted that stty rows/columns support doesn't seem to work on + AIX. I haven't yet looked into this. + + Copied 2nd sync mechanism from Expect to C library. + Added exp_child_exec_prelude hook. + + Jonathan Kamens noted that "spawn cat;close;wait" returned + -1 on AIX and 0 on Sun. This is "correct", however to + address this, I added -ignore to spawn and otherwise made + signals default. Also added extra information to return value + of wait if caused by signal. + + Dan MacDonald <hfvstud@bcarh80a.bnr.xca> noted that + exp_continue didn't cause timeout to get reread. + + Ting Tan <utan@cisco.xcom> noted that when using -b, expect + hangs if open brace and doesn't stop in case of error. + + Oops, broke "log_file" with no args. + + Removed -timestamp from documentation. Use "timestamp" command + instead. + + Keith Hanlan noted C library didn't test already arrived data + before attempting to read more. He also suggested I avoid + forcing the user to do save/restores of per-fd globals. + +6/24/94 5.8.0 Hubert Halkin <hhalkin@ucsd.xedu> pointed out that interleaved + expect_bgs and spawns dump core. I had used the exp_f ptrs + as handles to TkCreateFileHandler but realloc shuffled them + around. + + Rick Lyons <pclink@qus102.qld.tne.oz.xau> provided misc. mods + for Pyramid. + + Keith Hanlan <keithh@bnr.xca> noted that HP-UX C compiler + causes odd behavior in Expect when it is compiled with "-O. + -g" works fine. + + Peter Gasche <zrspg01@compserv.zdv.uni-tuebingen.xde> pointed + out that Convex 10.2 fails to build. New version of Convex OS + added getpty(). Naturally, it differs from old one. Testing + is tricky because there is no header file for it. Even worse, + the algorithm in the Convex man page is incorrect - it allows + you to allocate ptys already in use! Unfortunately, the man + page is too vague to allow the reader to see that immediately. + + In contrast to BSD stty, Convex, Mach, and NeXT stty don't + complain if redirected to null. I'll just have to hardwire the + test in configure. + + Added -nowait flag to wait command. + + Upon suggestions from David Vezie <dv@xnet.ssl.berkeley.xedu>: + Added -noappend, -open, and -leaveopen to log_file command. + Added -leaveopen flag to spawn and exp_open. + Modified spawn to close -open immediately. + Modified exp_open to close spawn_id immediately. + + Between Jeff Wright <wright@spock.cen.encompass.xcom>, Brad + Skrbec, Arup Mukherjee <arup+@cmu.xedu>, and the anonymous + Mach support group at CMU, finally got hard answers about Mach. + It is no longer supported and there is no intention to provide + full POSIX support. Now, at least, I can fix the configure + script to understand this. + + Added "unbuffer" example. + + Dana Chee <dana@dino.bellcore.xcom> provided configure hooks + for finding -lnsl and -lsocket. + + Henry Spencer <henry@zoo.toronto.xedu> noted timestamp doc did + not jive with C defn. Fixed doc and added timezone support. + + Steve Pynes <fb@steve@ucsd.xedu> noted that exp_win.c needs + _IBCS2 (Intel Binary Compat Standard #2!?!) before it will + recognize winsize. He also noted #out was redefined in inter + code if using simple_event. + + Fixed defn of "stty cooked" to retain echo setting. + + Bennett Todd noted dislocate's pidfile_read was missing close. + He also noted useless bind in tkpasswd. + + Marty Leisner noted that ^C causes xkibitz to exit ungracefully + when in interpreter. + + Added yet another sync mechanism (see 5.6) to spawn so that + child cannot eof before parent has prepped the pty (only a + probably on HPs, of course). I had actually written most of + the code, but left it disabled because I hoped that the + problem simply wouldn't happen in practice. Alas, Jonathon + Kamens found a case where it does. + + Jimmy Aitken <jimmy@pyra.co.xuk> noted problem on Pyramid. My + original code only looked for /dev/tty##. On pyramid, ptys + look like /dev/pts/4. term wants the last two characters, but + on the Pyramid, the first of the last two characters can be a + / in which case xterm wants a 0. I.e., suffix of /dev/pts/4 + is "04". xterm fails completely with 3-digit ptys! I sent + a suggestion and patch to X Consortium for this and the pid + problem - xterm has no way of telling it to which pid to send + the SIGWINCH. + + Poul-Henning Kamp <phk@TFS.XCOM> noted that -lm would make + autoconf forget about other libs. + + Ram Bhamidipaty noted I forgot to document sleep. + + Removed disasterous performance with * at beginning of glob. + + Mods from Rob Savoye. See ChangeLog. + + Earnest Hua <eh@c-cube.xcom> noted expectk.man need wasn't + installed. + + Bogus arguments to expectk were not reported correctly. + + Modified clib to catch when user changes match_max between + expects on two different fds and then switches back. + + Rewrote timestamp to get rid of 200 char limit. + + Ram Bhamidipaty <ram@xor.epi.wisc.xedu> noted NetBSD .9 stty + complained "stdout appears redirected, but stdin is the + control descriptor". It compares dev(stdout) to dev(stderr) + and assumes if they are different then user thinks stty + ioctls stdout. This is one case when that assumption is wrong. + Fixed fd 2 so it points new 2 and is reset to old 2 if an + error occurs. This forced me to remove any diagnostic output + from child (in getptyslave) since this now went back to the + proc as child output rather than original stderr, sigh. + + Stephan Winokur <swinokur@pinky.trevose.sgi.xcom> noted that + IRIX 4.2 had problems with gcc. While diagnosing, I found + PTY_TYPE was used before set. Make doesn't mind (how odd) + but I changed it anyway. + + Made send understand "-null". Deprecated "-0". + + Made Expect read .expect.rc from DOTDIR if present. + +3/30/94 5.7.0 Removed alpha status. + + Added $(EVENT).o to library. + + Finally deleted old shar file. Revised README. + +3/22/94 5.6.3 Phil Moore <phil@signals.geol.scarolina.xedu> noted termios.h + should not come from sys even if it exists. (SGI doesn't have + sys/termios.h.) + +3/21/94 5.6.2 Paul Kinzelman <pkinz@cougar.tandem.xcom> noted that I forgot + to remove -update from documentation. + + Fixed interact's -i so it understands indirect spawn ids. + +3/21/94 5.6.1 expect_background randomly failed. I forgot to save Tk's + event mask so occasionally events were incorrectly classified + as eof. + + Added -buffer to expectk and made "nobuffer" the default so + scripts are read in much faster. + +3/15/94 5.6.0 Added cat_buffers marker to avoid "catu" option to scripts. + + Got temporary use of an evaluation copy of TestCenter. + Promptly found several memory leaks. Oops. + + Added a synchronization mechanism to spawn so that user cannot + send to pty before it is init'd. This also deals with the HP + trap more simply. Removed extra open added in 5.5.1. While + working on this, it occurred to me stty needs to temporarily + disable trap. Added exp_slave_control so that C programmers + can get to it portably. + + Added "expect -ex" to documentation. + + Fixed winsize bug on Solaris. + + Added functions to allow user flexibility closing fds in child. + +3/8/93 5.5.1 Integrated bug fixes from Arnold Robbins <arnold@skeeve.atl. + ga.xus> for his own strftime code. + + Rob Savoye passed back a patch from OSF to cast ptsname. + + Added a test for cat. R.K.Lloyd noted HP failed pid test. + Turned out to be another bug related to pty-trapping. The test + of course, was doing something that a user would never do. + Hope this doesn't break other HPs. Pty trapping is becoming + less and less clear to me. Ioctls generated by slave look like + modem ioctls. Added an artificial open because different + versions of HP's stty execute differing numbers of ioctls. + In test script, changed each cat to cat -u. + +2/17/93 5.5.0 Began a test suite based on Ousterhout's model: make test + + Added passmass man page. + Added decl of exp_tty_original to pty_sgtty.c. + Added error_spawn_id + + Alon Albert <al@mercury.co.xil> provided a bug fix for new + buffer handling code in C library. + + Fix fd leak related to spawn -open. + +2/7/94 5.4.0 Some installation improvements from Rob Savoye and Owen Rees. + + Bug in handling empty string match - crept in recently. + + Finally fixed longstanding oddness: stty -raw reset echo. + + Made spawn close all file descriptors. Added exp_open command + to get old effect. + +1/26/94 5.3.5 Made rftp use /bin/ls to avoid -F from people's aliases. + + Initialized auto_path. + + Fixed exp_version so it fails if the major #s are not equal + (which is what the man page said). + +1/18/94 5.3.4 Jim Meyering <meyering@idefix.comco.xcom> gave config fixes + of X handling on Irix-4.0.5 and suggested that tknewsbiff + observe DOTDIR. + +1/18/94 5.3.3 Kevin Short <short@gdc.xcom> noted some remaining use of malloc + and free instead of ck versions. + + Initialize tcl_interactive to 0 while processing -c flag to + avoid unreliable handling of unknown proc. + +1/17/94 5.3.2 Jeffry Abramson <jra@hrcms.att.xcom> noted that "spawn -pty" + hung on an HP. Problem was trapping was enabled so as soon + as I tried to open the slave, Expect blocked waiting for ack! + +1/14/94 5.3.1 Forgot to delete a bad call to strcat in exp_internal. + +1/13/94 5.3.0 Added -info flag to log_file, log_user, exp_internal, and + strace, so you could get original args back out. + + Wrote tknewsbiff script (and was extremely pleased). + + Fixed rftp. I must have broke it when I changed to using Tcl's + new switch cmd. Also sped it up by replacing split/join + nonsense with a single regexp. + + Danny Faught <faught@convex.xcom> noted that glob patterns + returned shortest matches. While fixing this, found that glob + patterns ending in $ were broken, too. + + Massaged libraries and include files. The include file for + using Expect with Tcl or Tk is now expectcl.h. libexpect.a + now suffices for using Expect's funcs with C or Tcl. + + Add all the features from Expect into C library including + null and full buffer matching. Added exp_buffer (_end) and + some other variables to support fd multiplexing better. + Made unmatched chars from previous expects remain for future + matches. + + Chen <johnny@e0sun3.ccl.itri.org.xtw> found bug in exp_pid when + -i had no arg. + + Rewrote expect_bg, after, and before so they all handle args + the same. Interact and all the expect variables now handle + indirects. exp_bg now handles -brace flag. + + Geoff Bullen <geoff@itx.nsg.com.xau> noted that interact put + terminal into raw mode even if stdin was redirected. + + Rob Savoye provided more configure mods to better find Tcl/Tk. + + Fixed bug in wait that didn't close down "busied" fds. + + Kazuro Furukawa <furukawa@apricot.kek.xjp> provided a better + default for SHORT_BINDIR in the Makefile and noted that DEC + doesn't understand "test -x". + +12/3/93 5.2.0 Recent fix was buggy and blew up when eof case still had data + in buffer. + +11/23/93 5.1.4 At request of Rod Beckwith <rodb@slugo.corp.sgi.xcom> fix some + minor things to which SGI cc was sensitive. + + Fixed bug in dvorak script where eof could occur in nested + interact, upsetting original interact. + + Forgot to change -flush to -nobuffer in man page. + + Added some more places to search for X11 for Jeff Moore + <jbm@internet.sbi.xcom> note. + + Added yet more fixes and notes for NeXT for Brad Skrbec + <skrbec@motcid.rtsg.mot.xcom> who found that NeXT has POSIX + include files but NOT the functions that go with them. Sigh. + Needless to say, configure is thrown off by this. + +11/14/93 5.1.3 John Pierce <jpierce@chem.UCSD.XEDU> noted several declarations + that AIX's cc couldn't handle include a struct with same elt + name at two different levels. Also _IO is declared twice + in AIX include files but only checked once. + + Fixed bad args in exp_spawnl call in chesslib examples. Can't + imagine how it ever worked before. + + Richard Weidner <richard@cicero.jpl.nasa.xgov> found a bug in + configure (test always treats a bare string as true!) that + caused NeXT to be declared as POSIX. + + Fixed two bugs in Tcl_StringMatch2. One caused glob ranges to + succeed when they shouldn't. Another was how malformed ranges + are handled, and came right from Tcl. Reported to John. + Switched Expect library to use T_SM2 from Expect itself. + + Blair Zajac <blair@olympia.gps.caltech.xedu> noted expectk used + CLFLAGS instead of CFLAGS. + + Forgot to fix mishandling of parens inside of alternation in + interact. + +11/9/93 5.1.2 Added "null" keyword and remove_nulls command to allow matching + ASCII 0 in expect/interact. + + Rob Nagler <nagler@olsen.xch> noted that expect_background + failed if pattern didn't consume all data. event handler + knows nothing about data already arrived but not processed. + + Made Expectk understand -- + +11/8/93 5.1.1 Fixed yet another bug in setting expectk's argv0. + +11/6/93 5.1.0 Provided support to work with Tcl 7.[0-1] and Tk 3.[3-4]. + + Pasi Kaara <ppk@atk.tpo.xfi> found an off-by-one in the buffer + shuffling when buffers fill up during an expect. + + Changed \\\$ to \\$ in patterns that search for literal $. + + Added "spawn -pty" support for xterm -S. + + Fixed yet another argv problem in Expectk. When run using + expectk explicitly, script name was left in argv. + + Fixed system command's return value to match exec new style. + +11/1/93 5.0.4 Mark Davies <mark@comp.vuw.ac.nz> noted that BSD4.4 sysconf + returns -1 (a bug). Rewrote to avoid requiring this info. + Switched from from explicit refs of sys_errlist to Tcl's + strerror. + + As per Adrian Mariano <adrian@cam.cornell.xedu>, added + exp_sleep command primarily to allow sleeping by sub-second + intervals. Also avoids exec overhead. Not yet documented. + + Kartik Subbarao <subbarao@concorde.fc.hp.xcom> noted that on + HPUX 9, SC_OPEN_MAX should be ifdef'd on itself rather than + HAVE_SYSCONF. + + Karl Vogel <vogelke@c-17igp.wpafb.af.xmil> noted Pyramid + didn't like varargs included twice in exp_command.c. + + Deleted expect_version variable (was never documented) and + deprecated expect_library to be exp_library for consistency. + +10/16/93 5.0.3 Lou-Salkind@deshaw.com found interpreter() could stomp past end + of input array. Same problem in debugger. + + Bud Bach noted init.tcl wasn't being sourced, and Makefile + broke if all scripts were commented out. + + Added interesting highlights and bindings to tkpasswd. + + Made Makefile look for -ltk if libtk.a doesn't exist. + + Rick Sladkey pointed out that -re patterns to look for $ should + "\\\$". + + R.K.Lloyd noted config doesn't see prototypes with K&R cpp. + +10/8/93 5.0.2 Bud Bach noted tcl_interactive was not set. + +10/8/93 5.0.1 R.K.Lloyd noted various problems, some related to being on an + HP when a lot of #ifdefs kicked in. + +10/7/93 5.0.0 Added expect_background. In the Tk environment, this registers + actions to be called upon receipt of a pattern from a process. + + Renamed "debug" as exp_internal" and made debugger available + as "debug" and "exp_debug". + + Milan Gupta <mbg0@bunny.gte.xcom> noted that system() (at least + on his HP) hangs when SIGCLD is ignored. + + <jason@vicor.xcom> noted that Tcl's exec command doesn't bother + to close fds, so force them with close on exec. + + Renamed "continue -expect" as "exp_continue". "continue + -expect" will continue to work, just won't be documented. It's + just too dangerous when you start mixing extensions. + Renamed "return -tcl" as "inter_return". Had to do something + to avoid random return values from matching "-tcl". This + design was just wrong. Surprising that it never bit anyone. + Renamed "expect_version" as "exp_version" just to continue + this regularity. + + Protected initial fd_new's with isatty so disconnect doesn't + lose redirected fds. + + Allowed DFLT_STTY to be omitted entirely. Apollo doesn't need + it. + + Modified fork to fail on failure instead of returning -1. This + made spawn failure match disconnect failure. + + Dan Hyde <drh@citi.umich.xedu> noted missing arg in exp_error. + + Jerry Whelan <guru@stasi.bradley.xedu> noted -buffer was + botched in man page. Hal Peterson noted that bug in man page + caused groff to choke. + + wait now returns {pid, spawn_id, 0|-1, status (or error msg). + errorCode is now set if appropriate. wait -i -1 waits for any. + + Propagated winsize to pty. + + Documented "-open". + + Quentin Stafford-Fraser <Fraser@europarc.xerox.xcom> noted that + interact -u was broken. + + Fixed interact's default actions "return"/"interpreter" to be + writable. Removed ability to set default eof/timeout. Removed + dash from same. + + Rewrote trap to use Tcl's async support. + Added -code switch and made interpreter understand "-nostack" + coming from error to use ^C to easily return to interpreter. + Introduced following incompatibilities: + - ONEXIT interface disappeared. Use "exit -onexit". (Thinking + of this as a signal bought nothing but complexity.) + Added "exit -noexit" to run all expect-related exit + handlers without exiting or destroying interp or ".". + Useful for when other apps have exit handlers. + - trap command takes missing action as a query. Use "" or + SIG_DFL to delete or reset a trap. + - SIGCLD gone. Now always called CHLD even if underlying + system only knows about CLD. + All sig handlers and exit handlers run at global level. + + Removed setjmp/longjmp crap. Not needed since systems which + wait in read don't restart system calls. + + Added support in expect for "-gl" and allowed longer forms to + match Tcl's switch command. Similarly for "-ex" in interact. + Rewrote arg parsing for send. + + Added "stty" command to support stty of ttys other than + /dev/tty. Better for /dev/tty, too. This should fix + security complaint from BSD's Net2 stty. + + <R.K.Lloyd@csc.liv.ac.xuk> gave fixes for configure and noted + exp_main_tk was missing exp_conf.h. + + Added "exp_timestamp" command. Fixed bug in interpreter cmd. + It wouldn't return anything with TCL_OK. + + Renamed -flush to -nobuffer. + + Make interact default to executing actions in raw mode. + Accept -reset to execute in cooked mode. Ignore -f. + Fixed examples. Fixed bug in "-o -timeout". + + Deprecated getpid (due to Tcl's pid), added exp_pid. + + Put "rm -f" inside catch. SunOS 4.1.3 and some version of AIX + complain despite the -f! + + Added "send -break" for Dave Mielke. + + Fixed argv handling of expectk to match expect for Steve Clark. + + Switching to Tcl 7.0 + +8/21/93 4.7.7 Cygnus added support for OSF/1 style ptys. + + Brian Bebeau <brian@cblph.att.xcom> found bug in PTC support, + HAVE__GETPTY, timestamp doc, and provides some mods for config + AT&T StarServer. + + Detection of direct spawn ids failed on -1. + +8/18/93 4.7.6 Removed zone and gmtoff from timestamp. Not ANSI. + Removed getpid confusion. + Once again, added "cat -u" into kibitz (this time for AIX 3.2). + +8/18/93 4.7.5 De Clarke <de@lick.UCSC.XEDU> hit error in exp_global.h because + tcl.h had not been included. + +8/16/93 4.7.4 Richard Kasperowski <richk@icad.XCOM> found that Ultrix 4.1-2 + failed to allocate controlling terminal. Ultrix's setsid is + evidentally buggy. Switched back to setpgrp - which fixed it. + + Fixed type defn of exp_tty_original. + + Dave Mielke found two bugs in interact: re-failure prevented + other patterns from matching a particular point in the stream, + and two or more -inputs didn't actually work. Also found bug + in HP trap handling - despite what docs say, other things + besides open/close have to be handled. Specifically, slave was + generating an ARGGET. Backed off on trying to wait immediately + for two OPENs to just waiting for one OPEN. Perhaps zero? + Also found deficiency in return -tcl - failed to return arg. + + At Dave's request, made cmdfile by read in a single gulp rather + than line by line. Added -b (buffer) flag for old behavior. + Old behavior performs badly on very long procedures but is use- + ful for reading commands from pipes. Made "system stty" return + status of raw/echo. + + Made log_user return previous value irrespective of args. + + Fixed mishandling of parens inside of alternation noted by + Bud Bach <bachww@rtsg.mot.xcom>. + + Added -timestamp, -iread, and -iwrite to interact and + expect. + + Added -onexec flag to close to solve problem posed by + Bellave Jayaram <bjayaram@slee01.srl.ford.xcom>. + + Added -0 to send. Removed capability of send to send multiple + strings. + + Chip Rosenthal noted bug in releasing trap 0's action. Also + modified exit handler to allow recursive invocation. Instead + of complaining, it skips handlers that have already been + invoked and forces the process to exit. + + Added new names for most command prefaced by "exp_". + Deprecated send_spawn. + + Switched to Ousterhout's ckalloc and attitudes towards failure. + + Started adding Tcl 7.0 support. getpid renamed to pid. Added + exp_pid to support things that Tcl 7 does with its pid. + +6/12/93 4.7.3 fnf@fishpond.cygnus.com noted minor type problems. Rob Savoye + noted trap SIGINT overrode debugger handler. Default should + be reverse. + +6/8/93 4.7.2 Added debugger to public release. + +6/7/93 4.7.1 Ed Oskiewicz <eo@ansa.co.xuk> noted prototype botch - exp_cook. + Owen Rees <rtor@ansa.co.xuk> noted missing decl for + tclRegexpError. + +6/6/93 4.7.0 Gert Bultman <bultman@dgw.rws.xnl> exposed a bug in interact's + -update. + +5/27/93 4.6.0 Rick Sladkey <jrs@world.std.xcom> fixed a bug in send_log - + checking a master needlessly and indexing off the end of an + array. + + Rob Savoye made change for detecting libpt.a, modified + autoconf for better handling of X, exec_prefix, and ranlib. + + Kris Woeppel <krisw@cs.athabascau.xca> said SVR3 doesn't have + wait.h. + + Made libexpect.a understand regexp. Reorganized code. It + now requires Tcl to be installed first, although it uses only + a few utility routines. Hopefully this isn't a problem for + anyone. + + Zack Xu <zack@cs.wisc.xedu> noted exp_main.h needed C++ + support. + + Pascal Meheut <pascal@cnam.cnam.xfr> gave fix for skipping over + null bytes while interact is pattern matching. + + Added "--" to expect, interact, and send. + + Added support for associating multiple -i's with a single + pattern, and -i's with no pattern for use with spawn_id_any. + + Made interact work with systems that lack select/poll. + + Added code and #defines for debugger. Debugger itself is not + yet available. + +4/19/93 4.5.2 Achim Flammenkamp <achim@HRZ.Uni-Bielefeld.XDE> noted that I + documented full_buffer as buffer_full. + + Ted Stockwell <ted@sirius.aggregate.xcom> noted that wait arg + was missing an & in configure test. + + Scott Hess noted that systems can have wait4 without waitpid. + + Jonathan Kamens <jik@gza.xcom> noted/fixed some things that + weren't autoconf'd correctly: pid_t, RETSIGTYPE, malloc. + + Gary Shea noted that a recent change to expectk made it not + default to interactive. + +4/12/93 4.5.1 At request of Rusty Wilson <zrlw05@hou.amoco.xcom>, added + "-console" to spawn. + + Pang Wai Man Raymond <wmpang@cuse1.se.cuhk.hk> reported that + passmass didn't recognize DEC's passwd prompts for root. + +4/7/93 4.5.0 Fixed bug in interact regexp preventing match of multichar + literals. + +4/6/93 4.4.3 Bennett Todd <bet@sbi.xcom> noted missing example scripts + timed-read and time-run. + +3/29/93 4.4.2 Bill Houle <Bill.House@SanDiego.NCR.COM reported fixes + for SVR4 pty support to compile. + + Made string matcher understand *$. Documented tty_spawn_id. + Made command line -i override -f. + + For Tuan Doan <tdoan@bnr.xca> on HP, make kibitz use domainname + as fallback and used whoami instead of env(USER). + + Fixed bug in the generic pty code that could report out of ptys + because an earlier slave slowly deleted the lock file. + +3/25/93 4.4.1 Stephen House <sdhouse@bnr.xca> reported exp_tk.c wouldn't + compile on HP. Fixed. + +3/24/93 4.4.0 Added back SVR4-style pty allocation which got omitted in the + autoconfig process. Fixed bug in interact's -update handling. + Fixed bug in weather script that cut off long reports. + +3/15/93 4.3.0 Cleaned up /tmp files used during pty locking. + + Added command "parity" to enable parity stripping. Fixed + match_max to do -i correctly. + +3/15/93 4.2.4 Fixed to work on new SGI which returns slave-close via excep + (select) or POLLERR (poll) rather than thru read(). + +3/12/93 4.2.3 Fixed to work on AIX (using /dev/ptc) and UTS (using getpty). + +3/11/93 4.2.1-2 Fixed numerous bugs relating to HP ptys. It's amazing that for + their bewildering complexity, they couldn't support generation + of EOF to the master (or at least enable trapping of just + close), rather than forcing the code to know about opens, too. + +3/8/93 4.2.0 Integrated Rob Savoye's autoconfig code. + + Interact mishandled new -eof flag. Added -update. + + Gary Shea <shea@cs.ukans.xedu> noted that tkwait hung if + expect had been called. Rewrote most of tk_event.c and fixed + some other problems related to efficiency & multiple timeouts. + + E Beck <beck@qtp.ufl.xedu> suggested mods to more easily + support Extended Tcl. + + Bill Mitchell <mitchell@mdd.comm.mot.xcom> reported problems on + 4.3+BSD. Added support for TIOCSCTTY. + + Dana Burd <dana@wrs.xcom> noted that "exit" caused by ^C during + expect didn't work - just returning to expect. Fixed, and then + removed "feature" of ^C to abort a timeout. This feature + proved a lot less useful than I thought it would. + +2/21/93 4.1.0 Bill Tierney <wtierney@leland.stanford.xedu> noted that double + close dumped core. Rewrote fd_to_f and close/adjust functions. + + Interactive interpreter() didn't properly wait in + get_next_event, so Tk stopped responding to events. + Wrote version of interpreter that shares expect's input buffers + but can't think of a use. Left as an ifdef SHARE_CMD_BUFFER. + +1/26/93 4.0.1 Added eof check to xpstat. Removed incorrect and unnec. + #includes from exp_main_exp.c + + Chip Rosenthal <chip@chinacat.unicom.xcom> found my refs to + tclRegexpError need externs on systems that don't use Tcl's + string.h. string.h should probably be changed not to refer to + tclInt.h. + + Added FAQ about Expect's copyright status. + + Mark Christopher <christo@bnr.xca> pointed out some really + stupid errors in the HP support for select. + +12/16/92 4.0.0 Rewrote interact. Made re-entrant thru event-handler for Tk. + (Same for Expect.) Abstracted out common code so that + remainder is specific to select vs poll vs tk (although + "simple" was impossible to handle). Added timeouts, regexps + (at request of numerous people), ability to set up arbitrary + graphs of process flows, and some miscellaneous but useful + functionality. New flags are: -input, -output, -re, -echo, + -flush, -eof. + + Added "-noecho" to spawn command. + + Added getpid command. Something with this functionality should + be added to the Tcl core. When it is, this function will go + away. + + Removed assumption of global "interp" handle. Rewrote init + and other routines for use as libraries. Added appropriate + glue to Makefile. + + At request of Rob Savoye <rob@cygnus.xcom> added "send_log" and + disabled buffering on all output. The only affect unbuffered + output will cause users is if they pass large strings in + multiple args to send. + + Ray Davis <rdavis@masschaos.de.convex.xcom> reported Convex + could not do job control from spawned procs. I added a symbol + DO_SETSID to force this. + + Martin Leisner modified rftp to understand iftp. I added it + to the publicly donated scripts directory. + +11/17/92 3.24.1 Martin Leisner suggested Makefile use $(MAKE) and support Tcl + as a Sun shared library. + + Seth Perlman <seth@welchgate.welch.jhu.xedu> suggested interact + support timeout. I've added this as "-timeout" in inter_select + but left undocumented while we experiment with interface. + + Joe VanAndel <vanandel@ncar.ucar.xedu> pointed out that su2 + script still used old syntax. Fixed. + + Konrad Haedener <haedener@iacrs1.unibe.xch> fixed a bug in + POSIX tty handling on AIX. Surprisingly, we discovered AIX + worked just fine when pty_bsd is used and without -DPOSIX! + + Doug (George Jetson) <pynq@midway.uchicago.xedu> pointed out + that a spawn_id for /dev/tty would be really handy. I added + tty_spawn_id for this purpose. + +11/4/92 3.24.0 After problem reported by James Ward <jew@sunquest.xcom> added + to man page describing delays required by hardware such as for + UART switching. + + Recoded all \C sequences as \### in examples and man page in + anticipation of them going away in next version of Tcl. + + Switched to printing errorInfo during errors instead of the + command and only the top-level error message. Since this + includes entire stack, this should be very helpful. + + J. Cazander <cazander:pasichva via serigate@phcoms.seri. + philips.xnl> reported that purify found a write beyond the end + of an input buffer. Lucked, it was just before a double-word + boundary, so it probably isn't a problem. I fixed it anyway. + +10/9/92 3.23.1 Tor Lillqvist supplied support for HP 8.0.7 in POSIX-mode, and + a bugfix for POSIX tty mode switching + +10/8/92 3.23.0 Larry Rogers <lrr@Princeton.XEDU> reported that "weather" blew + up in spawn. I'll add a catch-all to the script to report + similar problems (out of ptys, processes, etc.) + + Ting Leung <tleung@bnr.xca> notes that log() in human_write can + receive a 0 (domain error). Fixed unit_random to avoid that. + + Tony Primavera <aprima@xox.ssc.af.xmil> notes that the sample + archie script needs to understand mcgill's limit of 10 users. + Tor Lillqvist <tml@tik.vtt.xfi> noted that a lesser-used + pattern ("unknown...") is incorrect. + + Grant Taylor <gat@pecan.cray.xcom> found a problem when forking + (using Expect's fork) multiple processes, each of which spawned + something. In the BSD pty support, I had used the pid to build + a temporary file for testing the pty before actual use. When + multiple processes tried to use the same tempfile, it blew up. + +8/12/92 3.22.13 Corey Satten pointed out that -u on cat caused kibitz to slow + down on Ultrix. I see the same behavior on SunOS. I added an + option to fix it for systems that need it. Corey also noted + arg miscounting in kibitz, and pointed out that world-readable + fifos could be a security problem. He gave a fix for this and + also a fix to force ptys to be put into raw mode. + + Terrence Brannon <tb06@pl122e.eecs.lehigh.xedu> reported rftp + referenced the undefined variable 'transfer'. Turned out to be + a bug in the code to handle symbolic links. + +7/20/92 3.22.12 Added O_NOCTTY (if defined) in pty_bsd.c to avoid gaining + control terminal while testing pty when running as daemon. + + At request of Michael D. Riley <riley@mbeya.research.att.xcom> + added explanation to man page - how expect_after/before deal + with spawn_id. + + Charles Hannum discovered the problem with AIX (see earlier) + was a missing "extern" in the errno declaration. Also, the + compiler was sensitive to a lack of access to the defn of + struct expect_special. + + Dave Coombs gave me yet another fix for the weather server to + accomodate its ever continual change. + +7/2/92 3.22.11 Yet more work. Discovered that SunOS and Ultrix really like + setpgrp(0,0) much better than setpgrp(0,getpid()) but the + manual doesn't describe well why this seems to work better. + (The old call worked inconsistently.) + +6/30/92 3.22.10 Did more work on modifications to dissolve connection between + stdio and devtty. Eventually, I'd like to add a separate + spawn_id for devtty (expect_devtty?). + +6/5/92 3.22.9 Hansel Wan <hhw0@gte.xcom> noted that $errorInfo was clobbered + by prompt1. To prevent this, I added a default definition + for prompt1 (and prompt2 while I was at it). + + Unnati Amin <uxa@po.cwru.xedu> noted that the example scripts + checked for $ in prompts which didn't work. This bug was + created when $ was turned into a "match end-of-input" char + in the transition from v2 to v3. Solution: backslash the $. + + A few parts of code assumed spawn_id was always stdin, which + caused "send" to send to stdout, which meant succeeding + expect's hung, waiting forever. Fixed is_user macro. + This was a problem with scripts that redirected stdin or + somehow reused fd 0. Surprising that no one ever did that + before - also surprising that it didn't bother cron jobs. + +6/2/92 3.22.8 Man pages fixes from Matt Crawford crawdad@fncent.fnal.gov. + +5/12/92 3.22.7 Missing ; in Makefile, screwed up chmod. + + Fixed bug that caused interact to think the modes had changed + when they hadn't. + +5/11/92 3.22.6 Added regression paper to ftp archive - published in the 1992 + USENIX San Antonio Proceedings. + + Swapped setpgrp and fork in disconnect command for sysV88. + According to Dave Schmitt <daves@techmpc.csg.gss.mot.xcom>, + original code (right out of Stevens) starts the child with + closed stdio fds. + + Fixed bug in interact that changed /dev/tty modes even if + interact was used to connect two completely different ttys. + Had never been a problem before, but today I wrote some code + that actually calls interact from cron! Also, copied the + experimental fix from 3.22.5 to inter_poll. + + Jeremy Nussbaum <jeremy@world.std.xcom> says cat needs "-u" in + kibitz for his HP 8.0 system to work. I wonder why this has + never been a problem on earlier HP and other systems? + + Forced Makefile to mark scripts executable. + +4/12/92 3.22.5 Fixed bugs reported by Matt Ranney <mjr@uther.Calvin.XEDU> + including a syntax error (!) in expect.c on ecases_inuse. + I didn't even compile this before pushing out? He also noted + some # were not in column 1. + + I put in an experimental fix to interact (only in select + version currently) to fix when pattern matching from master + and user needs to continue typing in order to complete match. + +4/3/92 3.22.4 Charles Hannum (mycroft@gnu.ai.mit.edu) pointed out that I + screwed up a comment in the brand new pty_aix3.c. He also gave + me a fix for an arg-less expect, which did a malloc(0). And + he said that AIX ptys return EOF in yet a new way - read() + returns -1 with errno == 0. Yuck. + +3/29/92 3.22.3 Jay Schmidgall gave me yet another pty_aix3.c. He also gave + ifdefs for POSIX terminal support. + +3/18/92 3.22.2 Jay Schmidgall <shmdgljd+@rchland.ibm.xcom> modified pty_sgi3.c + to make a pty interface for recent versions of AIX. + + Steve Summit <scs@adam.mit.xedu> noted that "trap 0" could + actually call signal(0...) + + Martin Leisner <Martin_A._Leisner.Henr801C@xerox.xcom> noted + that rftp was broken. It seems I never handled symlinks. They + are interesting. You can't tell from the listing whether they + are files or directories, so you just have to blindly go ahead + and assume it's one or the other and see what happens! + +3/11/92 3.22.1 In talking to Dave Schmitt ,daves@techmpc.csg.gss.mot.xcom>, + realized the documentation for wait had never been updated + from the way it used to work in v2 (returning any pid). + +3/11/92 3.22.0 Another question from Ron, prompted me to find another bug. + interact -o wrongly manipulated the user buffer at one point. + +3/10/92 3.21.0 Ron Young <ron@nevada.xedu> found that spawn failed on a + DECstation 3100 running Ultrix 4.2. I had forgotten to test + that cmdfile was valid before comparing against stdin in fix + related to fflush in 3.20.0. + + While I was on a DECstation, I noticed that it does not accept + setpgrp(...,0). Changed 2nd arg to getpid(). + +3/6/92 3.20.2 Stefan Farestam <farestam@orion.cerfacs.xfr> provided a new + version of pty_sgi.c which uses _getpty. I renamed the old + one pty_sgi3.c + +3/3/92 3.20.1 Brian Woodson requested I update the dates and version numbers. + +3/1/92 3.20.0 Prompted by a question from Ken Mandelberg, added -raw to + noidle and kibitz script. + + Fixed fflush(cmdfile) again, having been authoritatively told + by net wisdom that there is no way to portably fflush a shared + read-stream. (I take back my claim about a bug in HP's fclose!) + + John Sellens gave me some more fixes for non-DEC MIPS OS. + +2/22/92 3.19.1 John Sellens <jmsellen@watmath.waterloo.xedu> gave me a bug + fix for NOWAITPID. + +2/21/92 3.19.0 Found a bug in HPUX fclose!! It moves the I/O pointer in the + shared file table entry! This explains the symptoms I reported + earlier. Fortunately, it's easy to code around (by me - it is + no longer necessary to fudge the scripts). + + Added some stuff to the man page to explain why expect behaves + the way it does in an emacs shell window and how to live with + it. + +2/21/92 3.18.0 Worked on the HP port some more. The HP causes a real problem + by insisting SIGCLD be delivered in order for wait to return + a status. This royally complicated the code, partly because + of the special casing all over the place in the trap command, + the asynchronous delivery of SIGCLD and also because Tcl itself + is not prepared to have system calls be interrupted. The HP + also defines both CLD and CHLD which threw my macros off. + + Anyway, the end result is that on the HP, SIGCLD is ignored. + The manual claims wait status will not be delivered but it + seems to be anyway. Good grief! (Even if it were ignored, + it would not be such a calamity, since wait is used mainly + to discard zombies on other systems.) + + A remaining problem is that there appears to be some odd + interaction, perhaps with fork, such that the script is rolled + back at eof if a spawned process happens to exit at the same + time. The solution for now is to exit all scripts via exit + rather than letting exit be called implicitly. There must be + some real bug, but I'm unable to find anything after lots of + testing, line and Saber. At the moment, I'm highly suspicious + of the HP itself rather than expect. + + Bob Proulx and Jeff Okamoto supplied me with patches for + inter_select.c. HP transmits some pty interactions via the + exception field in select. + + Michael Grant gave me a mod to recognize ~ in the logfile and + debug commands. + +2/17/92 3.17.1 Brian Keves <keves@meaddata.xcom> pointed out that the man page + still referred to "expect_match" instead of "expect_out". + +2/12/92 3.17.0 Eric Arnold <Eric.Arnold@corp.sun.xcom> ran into a problem + when running in the background. interact did ioctl(0...)s to + change the terminal mode, ignoring the -u flag. + + Fixed a bug in kibitz which blew up when asking for a password + due to a spelling error. The drawbacks of interpreters... + +2/4/92 3.16.3 Dongchul Lim <lim@doctor.chem.yale.xedu> noted that scripts can + hang in the background. I had assumed isatty(0) was enough to + contrast bg/fg but it returns 1 if the script was started with + a & from the terminal. I added code to watch if any ioctl(0)s + were done. If so, than it is safe to do more, in particular + in the exit handler to reset the terminal modes. + +1/28/92 3.16.2 Fixed a bug on SV systems causing errors when trying to do + further reads after a SIGCLD had already arrived on a spawn_id. + + Peter Funk <pf@artcom0.north.xde> gave mods for SCO XENIX 386. + +1/24/92 3.16.1 Oops. Forgot to add pty_svr4.c to shar. + +1/13/92 3.16.0 Karl Lehenbauer <karl@sugar.NeoSoft.xcom> a tiny change for + getting a clean compile on SCO 3.2.2. + + My getimeofday-avoidance code wasn't right, sigh. Kibitz + noticed. Fixed two other bugs in kibitz - password request + was for wrong user and it timed out but shouldn't have. + + Note: seems to work fine with new version of Tcl: 6.2 + +1/13/92 3.15.1 Added a bit of code to avoid gettimeofday system calls when + timeout == -1. Fixed minor bugs in kibitz relating to cleaning + up and returning error messages. + + Redid support for stdlib.h including making it default to fix + problem in Ultrix 4.2 reported by Oliver Kretzschmar <viskretz + @ikesg1.energietechnik.uni-stuttgart.xde>. + + Ian Johnstone <ianj@sequent.xcom> said his system (DYNIX 3.2) + needed an additional include <ctype.h> in inter_select. + + Dave Coombs <cme.nist.xgov> added logic to test/weather to + accomodate a new feature in the weather server. + + Hal Peterson fixed some SV code that I just added for handling + SIGCLD properly. He made the Cray-extra-child timeout in half + the normal timeout to allow distinguishing between eof and real + timeout. Finished rest of Jeff Okamoto's fixes for HPUX. + + Wally Strzelec <packman@tamuts.tamu.xedu> provided mods for + Amdahl which has its own pty-handling functions. Ifdef'd into + pty_usg. + +12/30/91 3.15.0 Fixed a bug that struck when eof occurred when reading from + multiple processes simultaneously and no user-supplied eof + handler. + +12/26/91 3.14.1 Ted Gibson <tgibson@logdis11.hq.aflc.af.xmil> gave me some mods + for a 3B2 having to do with termio vs termios, etc. + +12/24/91 3.14.0 Deprecated expect 2. Expect 3 is now the official version. + + Parag Patel <parag@netcom.netcom.xcom> gave me some #includes + necessary for A/UX 2. + + Brian Woodson noticed "send a b" generates incorrect debug + output. + + Working with Jeff Okamoto to run expect on HP/UX 8.0, we fixed + SIGCLD catching (he says HPUX doesn't ignore them by default?), + obviating longjmp from stomping locals, fixed a bug in cmdWait + that would prevent the wait status from being collected in + rare situations. + +12/17/91 3.13.1 James Davis suggested fixing Makefile to handle case where no + example scripts should be installed. I added similar logic + for script man pages. + + Pete Siemsen fixed a bunch of things in the Makefile including + where to get expect when invoking fixline1. He suggested defs + for supporting install and multiple MAN targets. + +12/12/91 3.13.0 Matthew Freedman <mattf@cac.washington.xedu> noted mismatch + between lib man page (said "stty_init") and lib code (said + "exp_stty"). He also found a screwup in the library such that + the pty slave wasn't being set up correctly. + + Added note to kibitz man page on how to kibitz with 3 or more. + +12/12/91 3.12.0 "expect *" worked incorrectly if it was first expect after + spawn, due to buffer not being initialized. + + Added a good example for "expect -continue" to man page. + Added an FAQ about a gcc problem that seems to be common. + +12/11/91 3.11.2 James Davis noted I forgot to put kibitz.man in distribution. + I changed kibitz to read domain from resolv.conf instead of + calling domainname(1) for systems upon which NIS domainname + differs from Internet. + + Pete Siemsen <siemsen@barnard.usc.xedu> noted slight error in + libexpect man page. + +12/10/91 3.11.1 A couple tiny mods to the Makefile courtesy of James B. Davis + and Michael Grant (guest worker from Sun, temporarily at + <mgrant@xdr.ncsl.nist.xgov>. Both of them also noted a problem + caused by incorrect installation of gcc that caused expect to + say "ioctl(set): Invalid something or other" upon exit. + + Fixed complaint about exit() while compiling without STDC. + +12/9/91 3.11.0 beta! + + Hal Peterson provided fixes for UNICOS 6.1 and 7.0 on both + CRAY-2 and CRAY Y-MP. He also fixed a problem in interact + where malloc(0) could've occurred. + + Added support for allowing user to set interpreter prompt. + + Added forgotten -d flag to match_max in rftp script. + Made kibitz understand user@host. + + Expect's internal buffer-full-handling incorrectly copied + the latter buffer half beginning from the end of the buffer. + +12/5/91 3.10.1 Massaged Makefile to allow for more flexibility in + installation, especially with regards to scripts. #! is now + reset. + + Added "kibitz", a really cute script to let two people control + one program. Example users are for one person to help another + remotely, logging a conversation (run emacs or whatever inside + kibitz and your conversation can be logged, scrolled backwards, + etc., or of course, playing games together. + +12/4/91 3.10.0 Tightened up arg checking for "wait" - it core dumped when it + should've said "syntax error". + + Rick Cady <rickc@nsd.3com.xcom> noted minor inconsistency in + man page describing strace. + + I fixed a bug that prevented "system stty -echo raw" from + working. The raw data was clobbering the -echo data. + +12/3/91 3.9.0 Brian Woodson noted that "close -i ..." evoked a syntax error. + I had parsed the arguments incorrectly. + + After the nth request, I finally set up pub/expect/scripts as + a directory for scripts. + +12/2/91 3.8.0 Phil Sheperd <pshepher@loki.uni.edu.xau> fixed a major bug in + exp_spawnv() preventing one side of the pty from being set up + correctly. Thus nothing worked! He also reported that his + system didn't have strdup, so I added an explicit defn of it. + + James B. Davis fixed a couple nroff-bugs on the man page, and + said someone already gave him a dump script (see below). + + Richard (R.C.) Vieregge <richv@bnr.xca> found a $ was missing + from test/ftp.exp. + +11/22/91 3.7.2 James B. Davis <james@solbourne.xcom> straightened out a couple + things in the Makefile and asked if anyone had written a script + for dump. + + Jeff Okamoto <okamoto@hpcc25.corp.hp.xcom> had a couple changes + for HPUX 7 and 8 compat, involving termio stuff. + + Prompted by Andy Norman, added note to man page describing how + to disable all argv processing while using #!. + + Converted passmass and rftp over to new version. + +11/15/91 3.7.1 Brian Woodson asked me about the Tcl_WaitPids "got unknown + process" panic. This is a Tcl bug that John has promised + to fix. I'll document how to avoid it in the man page. + + Incidentally, I'm going under the knife tomorrow for three + torn cartilage in my wrist. The doctors say it may be a couple + days to couple months. Until I get back, hang in there. + +11/13/91 3.7.0 Yet another bug discovered (and fixed). "expect eof" was + failing to remember the buffer, and expect_out(buffer) was + empty upon return. + + Brian Woodson noted I forgot to document the -i flag of close. + +11/12/91 3.6.0 Sean Cunningham <sean@moorenet.xcom> reported that he couldn't + open /dev/tty from 'at'. 'spawn' was incorrectly not executing + code to claim it was a controlling tty. BSD only. + +11/11/91 3.5.1 Brian Woodson notes that version 2 and 3 treat the following + differently. + + proc p {} {spawn s}; expect + + In v3, spawn_id is locallized by the proc, and thrown away when + p returns. Unfortunately, in v2 due to some sloppy coding on + my part, spawn always affected the global value of spawn_id. + This differed from the handling of other variables, and in v3, + this unusual behavior had to go, because the multiprocess + handling and the large number of variables implicitly set + (especially by the expect command) demanded that I be more + systematic about how this was done. + + Since I never depended on this behavior, I never documented it + as being something you should rely upon. Alas. To fix it, add + the line + + global spawn_id + + to the beginning of any proc that calls spawn and needs the + value of spawn_id implicitly defined outside of the proc. + +11/6/91 3.5.0 Drew Whitehouse <Drew.Whitehouse@anu.edu.xau> hit a bad pointer. + I forgot an initialization in expect.c which caused problems + when an EOF occurred which had no eof pattern. + +11/2/91 3.4.0 Added FAQ from various questions people have sent me and my + replies. Made CONVERTING file on converting from 2 to 3. + + Nelson H. F. Beebe <beebe@math.utah.xedu> found a missing + declaration for exp_tty_original in bye() of main.c. How come + the Sun C compiler doesn't complain about this!?!!? + + Nelson also reported that SunOS 4.0.3 had a problem including + varargs. It turned out that old varargs had check for + reinclusion, and tclInt.h also includes it. So I added an + #ifdef va_dcl and put my inclusion after tclInt.h. + +10/31/91 3.3.0 Converted most of the examples. Three more to go. + Worked on man page some more. + + Modified expect so that if timeout > 0, and nothing in the + buffer matched, it will force a read, no matter how long the + preceding code took. This may be hard to understand, but is + the intuitive behavior that I always desired. + +10/30/91 3.2.0 Fixed bug in eof handling. Converted some more of the + examples, and added to Makefile. + +10/29/91 3.1.0 Fixed slight bugs in tty mode switching, pty initialization + (via stty). + + Fixed expect library. Fixed compatibility code for non-BSD + systems. As usual, I could only test it so far, not having + all these systems at my disposal. I don't expect major + problems though, since the basic functions I depend on haven't + changed. + + Completely rewrote handling of continue, return, etc in + expect, interact, interpreter. It's actually systematic now. + + Checked with John O. about some code to bounce wild return + codes, which he said was a mistake and would remove, so now I + can pass my own return codes different from Tcl's. + +To get | to return -> TCL_RETURN TCL_OK (no return) + V + expect return default continue -expect + interact return -tcl return default + interpreter return -tcl return default + + What this table says is, to get "interpreter" (for example) to + return TCL_RETURN to its caller, you must say "return -tcl", + because "return" makes it return TCL_OK. + + The "argumented" versions are considered to be the uncommon + form. In particular, I'd be surprised if anyone ever uses + the -tcl argument, but it's there for completeness and + consistency now. + + Put together a FAQ. Needs more work, but hopefully worthwhile + as is. + + Computing Systems with Expect article appeared a couple days + ago. How ironic that it describes the old version of Expect. + Nonetheless, it looks ok. + +10/25/91 3.0.0 alpha! + First release of Tcl-6.0-ready code. + It might fly for a couple seconds. + + Here is a quick list of changes. Besides Tcl incompatibilities, Expect + incompatibilities are flagged below as: + + ** major - scripts definitely won't run if they depend on this + * minor - scripts probably will run but there is some subtle + change that should be examined). + + ** Select renamed 'ready' and undocumented. Seems pointless now. + + Added support to expect command for waiting on patterns from + different processes. The old version implemented this via + 'select' but but it is much simpler via expect. Added -i to + a number of commands to signify a spawn_id which overrides + the variable. + + Added any_spawn_id to match any spawn_id. + An explicit null pattern, forces a spawn_id to be considered + when all it can possibly match are any_spawn_id patterns. + + * output is no longer flushed to expect_match upon timeout. + May be multiple buffers now, so it doesn't make sense to + flush just one.) -n was added to disable transfers from input + buffer to expect_match var. I suspect it will only be used + for experimentation. + + Added expect -re for regular expressions. Added expect_out + array to retain indices and strings of partial matches for + ** for both glob and re. expect_match has been renamed + expect_out(buffer). + + A la Tcl, added -nocase for both types of patterns. (Oddly, + Tcl's case only does it for regexps.) + + By popular demand, unanchored glob patterns. Old patterns + will continue to work, since earlier interpretation was much + stricter. Unfortunately, unanchored matches make certain user + errors easier. For instance, people will send answers before + seeing all of the question. Typically, output can 'look' + ugly, as answers land in the middle of other things. + + To anchor patterns, use ^ in beginning and/or $ at end. + + Added expect_out(spawn_id) to report which spawn_id was read. + + Made expect and variants understand all args as one arg. + + Added 'default' pattern. + + Added continue_expect command. + + Added expect_before, expect_after commands which take same + args as expect, but continue to stay in effect for all expects. + + ** Added match_max command, deleted it as a variable. The old + way was too coarse for use over multiple spawn_ids. With no + arg, returns current max. Takes -i flag and -d for default. + + Added globbing to spawn command. + + Added optional -i spawn_id to wait. + + Added optional -i to send (and all its variants). + + Renamed trace to 'strace' since it conflicts with Tcl's new + trace command. Since 'trace' traces variables, I figured + 'strace' wasn't too bad (for "statement trace"). I felt + obliged to make it short and not as obliged to make it as + meaningful since it will probably invariably be typed by hand. + + Made timeout == -1 mean infinity. + + Made interact do pattern matching in both directions via + use of -o flag. + + Added -F flag for convenience. If -f or -F used, interact + can no longer be overrun. In particular, if more characters + arrive then match a pattern, remaining characters will be + buffered rather than thrown away (old behavior). + + Patterns may now be substrings of one another. + + Made interact optionally take all args as one. + + Default action is now 'interpreter' (see below). + interpreter now forces cooked mode, and echos results + so you don't have to constantly say "send_user [...]\n" + + * Interact reads characters that have been buffered but not + matched by expect. And vice versa. Does anyone care? + (My rogue script did.) + + From discussion with John Conti, I decided to make + 'interpreter' a separate command to start up interactive + command processor. Changed default action in interact to this. + Added eval depth and event id to prompt to interpreter. + + Added expect_library which contains path for commonly + sourced expect scripts. Automatically source expect.rc + out of expect_library unless -N given. Automatically source + ~/.expect.rc unless -n given. + + Added expect_version command to print and/or verify script + is compatible with running expect. Tcl version is also tested. + Felt it was worth making this a command because it's such a + pain to tear apart version strings. + + Tcl's close and exit are both subsumed by expect's commands + of the same name. + + Rewrote mode switching code so that "system stty" is handled + specially. This allows interact and interpret to get the modes + they want, without burning the user. It is now much easier + to leave expect in raw mode all the time, but the choice is + up to the user. + + Added vgrindefs, courtesy of Brian Fitzgerald. + +9/23/91 Tcl 6.0 released. This new Tcl has some incompatibilities + with the old Tcl, so as long as everyone is changing their + scripts already, I'm taking the opportunity to make some + incompatible changes to Expect that I've wanted to do for a + long time. + +9/11/91 2.67 Ed Klein <eklein@syrinx.umd.xedu> added support for SVR4 in the + form of pty_svr4.c and mods to command.c. + + Added explanation to man page of how to create unreadable but + executable scripts. (No, chmod 111 doesn't work.) + + Mark Diekhans <markd@grizzly.XCOM> pointed out to me that there + is a potential problem with the trap command: + + "There is no control over when the signal will cause Tcl_Eval + to be executed. There is a chance that code in the Tcl library + will be executing when the signal comes in and the interpreter + data structure will be in an inconsistent state. This could + cause all sorts of nasty things to happen. In our Extended Tcl + (4.0) we added signal handling. but the way we implemented it + was to have the signal handler set a global flag. We modified + Tcl_Eval to check the flag after it finishs executing each + command. If the signal came in, Tcl_Eval then returns an error + such as: "SIGINT signal received". Signals may then be caught + with the catch command and processed." + +9/10/91 2.66 Don Jackson <Don.Jackson@Eng.Sun.XCOM> found a syntax error in + the usage error message of the example ftp-rfc script. + + Marty Olevitch <marty%cosray@wuphys.wustl.xedu> provided mods + to support MORE/bsd. Namely, added #include types.h to + expect.c and extern int errno to a number of files. + + Scott Hess <scott@nic.gac.xedu> noted a potential problem in + interact. Since interact only checks patterns at beginning + of reads, user can conceivably type fast enough so that + patterns are typed in the middle of a read. In reality this + doesn't happen, but Scott was driving one expect with another + expect and in this way provoked the behavior. + + The solution is to read chars one at a time, either by + read(,,1) or buffering in a stdio-like way, but I'm not going + to do that because the code should really be rewritten entirely + and it just isn't worth it, since it is so easy to get around + at the user level. + + Steve Legowik found that spawn-disconnect sequences fail. The + pty testing I added in version 2.55 causes expect to regain the + slave as a controlling tty, which generated SIGHUPs. If anyone + knows a clean way to avoid regain controlling ttys, let me + know. For now, I just set SIGHUP to SIG_IGN in the disconnect + command. + +8/14/91 2.65 Old passmass script changed root password. I renamed it to + passmass.old, and made a new one which works for any account. + It also supports yppasswd, telnet/rlogin, different names for + accounts on different machines. Handles VMS machines, too. + + Added Computing Systems paper to expect distribution and moved + all expect-related things to separate expect directory in our + ftp directory. + +8/5/91 2.64 Achille Petrilli <achille@miss.cern.xch> found that on an SGI, + the expect command ocassionally returned "no more processes". + He traced the problem back to O_NDELAY in the open, which was + taken as-is from the man page, by someone else who's code I + didn't look at too closely at the time. The result works now. + Oddly I thought I fixed this error myself when the SGI support + was first installed, but I cannot find it. I evidentally + screwed up. + +7/31/91 2.63 Steve Legowik <legowik@cme.nist.xgov> wanted to implement + callback by having a modem dial out and NOT go away, but + interact in the reverse direction. I added "interact -u" to + support the idea of changing the user from the default stdio + to a second spawned process. The result is that we can now + write a modem callback program that doesn't depend on the cute + trick of having getty recognize DTR which only worked when the + modem was directly connected to the computer. In Steve's case, + there were several network switches in the way. + + Added "overlay" function which is similar to plain "exec" in + shell. (Too bad Tcl took the name already.) + + Added robohunt scripts to the test directory. I wrote these + back in January, '91 and forgot about them til now. But I + suppose they are illustrative (at the very least of how to + generate truly random numbers). Ha. + +7/20/91 2.62 Carl Witty <cwitty@jessica.stanford.xedu> pointed out my fdset + implementation (for systems that don't have it) wasted some + space. I had commented it correctly, however, making the + incorrect code obvious (except to me). + + Robert Howland <howland@rahjr.ame.nd.xedu> pointed out that + expect complained about not running from a real terminal under + cron. Oops! So I added a test to skip saving/restoring + terminal modes when fd 0 is not a tty, since this is obviously + pointless. + +7/19/91 2.61 Oops. Forgot to include getline and getline.exp examples even + though they have been documented! + +7/17/91 2.60 UMich changed interface to weather system necessitating change + to weather script. + +7/9/91 2.59 Didn't correctly comment things right in Makefile. Fixed. + + Changed 'close' in gethostbyaddr example to 'catch close'. + +6/22/91 2.58 Made new file (pty_sgi.c) for supporting Silicon Graphics ptys. + Silicon Graphics select fails to see eof immediately but poll + works ok. Unfortunately, there was an error in inter_poll + (bad_io was uninitialized). Silicon Graphics works now. + + Andy Norman <ange@hplb.hpl.hp.xcom> notes that linking expect + with the BSD compatibility library under HP-UX, libc.a must + be loaded before libBSD.a. Modified Makefile to reflect this. + He notes that there is a problem with expect not reading an EOF + from the current process. This should go away with HP-UX 8.0 + when select has been enhanced to flag exceptions in the readfds + argument. Probably inter_poll would work. + + Edward Haines <haines@bbn.xcom> notes that close returns EPERM + ("Not owner") on his Sun 4.0.3. This is rather startling! + (That's what I get for checking the return value of close!) + He said it is possible that they have modified things (viz. + DDN X.25 is loaded), but it still sounds incredible. For now, + I told him to either "catch" all closes or to remove the check + in the source code. + + Added example scripts: ftp-rfc retrieves an RFC from uunet + via ftp. archie mails back a listing from the archie server. + + Add the rest of Hal Peterson's changes for Cray support, 1) + fixing a problem where spawned processes flushed unread I/O + upon process exit, and 2) creating processes with the correct + uid. See his comments in command.c for more info. + +6/6/91 2.57 (On Cray) made signal handler declarations right. Added + missing #endif. Added includes to pty_unicos.c. Fixed bug + in two bugs in CmdSend, one involving send_stderr, the other + send_user. All of these are from Hal Peterson. + + Added gethostbyaddr as example script. Given an internet + address, it returns the domain name. By querying neighboring + hosts if the name server fails, a much higher probability of + returning the name is obtained. + +5/30/91 2.56 Mispelled "match_max" as "max_match" in rftp script. This + caused files after the 2000 byte mark (per directory) to be + skipped. + +5/21/91 2.55 Revisited BSD pty code to reject ptys that have either slave or + master side already open. This fixes problems rare problems + such as expect not being able to see EOFs from the child proc. + (because another process still has the pty slave side open). + USG and Cray pty code could probably use this code, too. + + Fixed bug in expect library (lib_exp.c) which caused output to + be copied to stderr instead of logfile when logfile_all was + set. Per Sreedhar Muppala <muppalla@nssdca.gsfc.nasa.xgov>. + +5/16/91 2.54 Fixed weather script to accomodate occasional Weather Watch + that would cause an unexpected initial question to pop up. + +5/15/91 2.53 Added comment to BUG section of man page describing pty + misbehavior with non-interactive programs (search for "553061" + below), as per Hal Peterson <hrp@cray.xcom>. + + Removed note from README about asking Ousterhout for SV TCL + at his request. + +5/11/91 2.52 Fixed a syntax error that Bruce Larson <ires@kaspar.ires.xcom> + found in inter_poll.c + +4/23/91 Computing Systems accepted paper on Expect for issue 4.2. + +4/18/91 2.51 Added some example scripts: + weather - retrieves weather forecasts from National Weather + Service via University of Michigan server. + rftp - ftp a directory hierarchy (i.e., recursively). + +4/18/91 2.50 Changed timeout to apply to total time in expect rather than + per read(). Original behavior hung forever when my modem test + script started listening to a modem than spit out 1 spurious + character every 10 seconds (very consistently). + + Hal Peterson <hrp@pecan.cray.xcom> noted that exp_spawnv's args + didn't match documentation. Fixed in favor of documentation. + Several other funcs don't match header file (but typechecking + is avoided during compilation), because it was too hard for me + to make the header file ANSI compliant and support varargs + (which is undeniably more portable than stdargs at this point). + Fixed prototype declarations (again) in expect.h for C++ and + Standard C. Verified with GNU, G++ and Sun C (proto-less). + + Added exp_disconnect to library. Moved alarm calls closer + to read() to tighten windows. + +4/11/91 2.49 Changed passmass script to use timeout of 1000000 instead of + 10000000000 after discovering that Ultrix sleep(3) doesn't + sleep at all for large values! + + Added support for systems without dup2 (SVR2) per + <elston@edwards-tems.af.xmil>. + + Added test/Makefile to shar as per Chris Pribe + <cpribe@park.bu.xedu>. + +4/4/91 2.48 Fixed possible problem with poll in inter_poll.c for systems + that check for a valid address even though no members are used. + +3/27/91 2.47 Added support for Cray Unicos 6.0, which of course is different + from Unicos 5.1 (which was different from everything else)! + This and other minor bugs fixed courtesy of Pete Termaat. + +3/19/91 2.46 Removed a "feature" which caused patterns with no whitespace + not to be run through SplitList. While not documented not to + do so, this was mystifying even to me when I saw it. For + William Waite. The result actually simplified the internal + handling of multiple patterns, removing some excessively + complex logic that I thought would be helpful for speed, but + that in retrospect, was not that important. + +3/16/91 2.45 Added my own definition of FD_SET, fd_set, etc, test for + SIGABRT, and support different types of signal arg func + definitions to support SunOS 3.5 as requested by William Waite + <waite@scotty.colorado.xedu>. + +3/14/91 2.44 Removed redundant def'n of pty_stty in pty_usg.c, redef of + sprintf and added signal.h to command.c to make compiles + cleaner on SV3 and HPUX machines. All compliments of Mike + Gourlay. + +3/10/91 2.43 Added -s (for slow) and -h (for human) flags to send. This + had been requested by several people including Frank Terhaar- + Yonkers (who actually wrote and tested a "send_slow" command), + and Steve Simmons who suggested the "human" option (over a year + ago), and Brian Woodson (brianw@swqa-sun.ESD.3com.com), who + requested both! Thanks to NIST statistician, Keith Eberhardt, + who taught me about the Weibull Distribution. + + According to Jim Thomas <jthomas@nmsu.xedu>, 3b2 requires + defines for R_OK and W_OK. Added to pty_usg.c. + + Added support for "-" as file name on command line to mean + stdin as requested by Steve Clark <clark@cme.nist.xgov>. + + Wrote passmass (change root password on a set of machines) as + requested by Ken Manheimer <klm@cme.nist.xgov>. Added to test + directory. + +2/21/91 2.42 Removed reinstallation of signal 0 in signal handler. + + Added hook for setting initial pty parameters when started in + the background. Should've done this a long time ago, but I + was never really happy with my solution and had hoped I would + think of a nicer method. I only hope this is clean enough. + +2/10/91 2.41 Added buffer_full keyword to solve Brian Fitzgerald's problem. + It disables "forgetfullness" so that when expect's internal + buffer hits match_max, whatever it has returns at that point. + Didn't add this to the library version, because I want to think + for awhile about the cleanest way to do it. + +2/4/91 2.40 Per Brian Fitzgerald (fitz@mml0.meche.rpi.edu), fixed error in + interact example on man page which incorrectly implied that + "kill" was built-in. + + Added fork/disconnect functions. This solved the problem of + Jerry Friesen (jafries@snll-arpagw.llnl.gov) who wanted to run + an expect script that asks for a password and then goes to + sleep for awhile before waking up to run in the background (to + run a program using Kerberos). + +1/30/91 2.39 Per Jim Johnson (jaj@mlb.semi.harris.com), added declaration + and documentation for exp_pid in libexpect. + +1/10/91 2.38 More mods from Frank Terhaar-Yonkers. Also, some requests + from Pete TerMaat (pete@willow.cray.com) for features: + + 1) a single-step facility. Yeah, that would be nice. No + ideas on how to do this easily. + + 2) Generate scripts automatically after watching a session. + This is hard. Read more about this in the FAQ. + +1/10/91 2.37 Added support for Cray Unicos 5.1, all courtesy of Frank + Terhaar-Yonkers (fty@sunvis.rtpnc.epa.gov). Most of it had to + do with pty support. + +1/8/91 2.36 Modified expect.h to support C++ and ANSI prototypes. Added + appropriate example in test directory based on chesslib.c. + +1/7/91 2.35 At the request of Jan Norden (jano@imdpy1.im.se) added + NO_MEMCPY and NO_STRING_H defines for Pyramid. + +1/3/91 2.34 Added a check to protect against a longjmp occurring between + i_read and alarm(0). Didn't think this would be a problem but + evidentally a function return modifies the stack, so it cannot + be returned to again. Drat! This appeared in the robohunt + script I wrote which plays hunt automatically and uses 1 + second timeouts. + +12/19/90 2.33 Add signal to sighandler, to reinstall signal for those systems + that need it. + +12/12/90 2.32 Removed test for args to expect. I only recently realized that + no args still allows a valid way to check for timeout and eof! + +12/6/90 2.30-1 Mike Gourlay (mike@penguin.gatech.edu) found and fixed quite a + few SV-related problems that I had introduced since Clem's + fixes. We eventually got it to run on his HPUX machine, a + mixed breed of BSD/USG stuff. But spawning a shell worked but + always produced a complaint about "no access to tty" which we + were never able to get rid of, and he had a problem with + exp_fexpect (but not exp_expect), although it still isn't clear + if that was expect's fault. He said he would speak to some HP + engineers about what he found. + +12/5/90 2.29 Fixed a malloc off-by-one bug in new C library. After + contemplation, revised interfaces. Decided that rather than + following the original 'expect' style, it should be more like + what a C programmer is used to, so I made the file descriptors + be parameters to exp_expect rather than globals, added an + exp_popen which is a popen equivalent, and added exp_fexpect + versions which are stream equivalents. + + Am not happy with exp_fexpect. It is much less efficient than + exp_expect, because there is no way to (portably) get fread() + to return the way read() does, with less then the number of + characters you supplied a buffer for. Instead, I have to call + fgetc for every char. Ugh. + + Add a couple new examples, including lpunlock, time.exp, + chesslib.c (using file descriptors) and chesslib2.c (which uses + stream pointers). + +12/3/90 2.28 Created C library version of expect. + +11/29/90 2.27 Fixed bug in interact - when no string actions were defined, + the mapping table length wasn't set at all. + + Made interact call printify when debugging so that crlf and + other nonprintables are visible. Fixed bug in printify which + interpreted some characters wrong due to parity. + + Added some more examples to the distribution (lpunlock, dvorak, + timed_read) and put in another tip in the TCL HINTS section of + the man page. + +11/18/90 2.26 Fixed mismatched comment per Craig Warren (ccw@deakin.oz.xau). + Also improved man page entry for "interact". + +11/17/90 2.25 Added -f (fast) on interact options, and made default case a + little more efficient. Added explicit support for SIG_IGN and + SIG_DFL in trap command. Added ability to specify signals + symbolically for portability. + +11/15/90 2.24 Craig Warren (ccw@deakin.oz.xau) wanted to exit expect while in + interact with a single character. Dan Bernstein + (brnstnd@kramden.acf.nyu.edu) wanted to suspend with a single + character. So I generalized interact's escape character to + string-action pairs. + +11/7/90 2.23 Tired of getting reports that various (Ultrix 3.1, BSD4.3) C + compilers can't handle ternary conditionals returning ptr to + func returning void. Made all (2) such statements into + if-then-elses. Per Steve Simmons (scs@iti.org). + +10/8/90 2.22 Allow "log_file" even when no log is open. This makes user + programming a little simpler - they don't have to remember + whether they opened the log or not. + +9/27/90 2.21 Fixed bug, v2.19 introduced. debuglog(unknown string) requires + a "%s" as formatting for protection against %'s in the unknown + string. + +9/17/90 2.20 4 syntax errors in interact_poll.c, vik@sequent.com. Added + quotes to all the sends (now that this is more efficient) in + the examples and man pages. Also removed a misstatement in the + man page about the behavior of double quotes. + +9/15/90 2.19 Removed buffering from send command. Originally, I buffered + the args, so I could do it all in one write. But to send + variables bigger than the buffer didn't work. I didn't think + about this before. But Joe Gorman + (Joe.Gorman@elab-runit.sintef.xno) asked me if you could "send" + a file in one command, and of course you can using [exec cat] + as the argument to send, but the buffering prevented big + files from being sent. Anyway, now it works. + +9/14/90 Fixed the declarations of nflog and nferrlog. Added a #define + so lack of pid_t could be controlled from the Makefile. Per + Andy Holyer (and@ux.rfhsm.lon.ac.uk) + +9/4/90 2.18 Added trap command to catch signals. This is nice as (among + other things) it allows you to turn off the conversion of ^C to + timeout which was requested by John Conti <jconti@cisco.xcom>. + +8/21/90 2.17 Fixed bug in printify. Forgot to reset ptr to beginning of + print buffer. Made debugging info wrong. Possibly screwing up + other things on overflow. + + Paper accepted into USENIX LISA! + +8/15/90 Cleaned up man page. Made tabs line things up correctly, + finally. + + Found another problem with ptys (at least under SunOS 4.1 and + earlier). When last pty-slave fd closed, any unread output is + lost after a short window of time (around 10 seconds on a + Sun 3/60). Sent example ptybug.c to Sun demonstrating this and + EIO problem found earlier. (Service Order #553061) + +8/6/90 2.16 Added -f to debug command, -a to log_file command. This + required significant changes, including revisiting all the + logging routines, plus miscellaneous output done in special + places. Noted that it cannot be done with getopt, since it + could be called during main's getopt, and getopt is not + reentrant! (Guess how I discovered this!!) + + I'm not particularly happy with the design, but maybe others + won't be. In any case, I like the benefit of it and am now + glad that -a was asked for. Per Harry Bochner and Ira Fuchs + (fuchs@pucc.bitnet). + + Changed behavior of argv, so that 0 == [length $argv] when no + script/args supplied. + +8/4/90 2.15 Added debug command, so -d-ness could be changed while expect + is running. + +7/20/90 2.14 Fixed small bug in -d output from expect, which printed ^Z as + ^: + +7/18/90 2.13 Added wait command. A waitpid/waitspawnid would be nice and + cleaner, too, but since csh doesn't need it, it is probably not + worth much. + + Consequently, removed SIGCHLD handling from command.c. It + worked under SV but not BSD. By forcing users to explicitly + code waits, resulting scripts are more portable. + + Rewrote rogue example. rogue sometimes misses EOF (generated + by close on our side) and continues reading. + +7/16/90 2.12 Removed buffering from variadic log routines. This was + faulting when the buffers overflowed. + + Cleaned up the -d output from expect, so it is much more + readable. For example, control characters are now visible. + +7/14/90 2.11 Added declaration for errno, to support 4.3BSD. Per Alan + Crosswell. Added -i flag and related behavior. + +7/12/90 2.10 Fixed bug where timeout = 0 waited forever rather than not + waiting at all. + +7/11/90 Fixed man page example which didn't include the blank on the + end of an ftp prompt. + +7/9/90 2.9 Fixed bug in send when spawn_id = $user_spawn_id. + +6/27/90 2.8 Integrated some mods from clem cole (clemc@ccc.com) to support + System V.3 (386/ix Version 2.02). Unfortunately, he didn't do + "select". + +6/25/90 2.7 Test that cmdfile and logfile are open before fclosing in child + while spawning. Per Corey Satten <corey@cac.washington.xedu> + +6/24/90 2.6 Pty master returns EIO instead of EOF when pty slave closes. + Bug in pty driver? Until I figure this out, I have put in code + to interpret EIO to EOF. + +6/21/90 Added new section to expect man page - Tcl hints. + +6/14/90 Spoke at USENIX. Went well. Added USENIX paper as separate + ftp archive. + +6/4/90 2.5 Fixed bug in ^C catching during expect. Changed man page to + accurately describe what ^C does. Fixed bug that caused "send" + to screw up when handed 0 arguments. All per Harry Bochner. + +6/1/90 2.4 Made trailing empty action in expect optional, primarily to + make straightline code easier to read. + +5/15/90 2.3 Changed expect to strip nulls from program output since there + is no way for Tcl to handle them, per Harry Bochner. + +5/5/90 Added "send_error" command. + +4/26/90 Got USENIX paper back from Kolstad to proof. Am depressed at + how awfully they formatted it. + +4/25/90 2.2 Eric Newton found that expect's special variables weren't being + found inside of user subroutines. Had to do with new Tcl, + which now differentiates between variables that are undefined + vs. empty. + +4/24/90 Upgraded Tcl from 2.1 to 3.3. + +4/22/90 Added special behaviors of ^C in expect, and when profiling. + Profiled rogue (at urging of Ousterhout). + +4/10/90 2.1 Added select command. Added support for user_spawn_id so that + you could treat user just like another process (i.e. with send + and expect). Decided to leave send_user/expect, since scripts + are more readable with them. + +4/2/90 2.0 Changed syntax of expect to provide alternatives (a la Tcl + case), per suggestion of John Ousterhout. Note that this + breaks pre-2.0 scripts. + +3/31/90 Got great comments from Ousterhout. (This time he said that he + really liked the idea. Maybe he realizes how much it will + promote Tcl!) + +3/30/90 Got comments from dpk. Made me think more about Perl. + +3/28/90 Evi said I should turn the paper in unformatted and they will + format it. (She's kidding, I hope.) + +3/27/90 1.8 Rewrote interface so that raw arguments can be passed in like a + shell. I'd been thinking about this for some time, but Eric + Newton finally prodded me into action. + +3/25/90 Got first corrections for paper - from Sue Mulroney! + +3/24/90 Observed that it is possible to use the #! syntax with expect. + I asked John O. about this (his choice of # as a comment + character), and he said it was pure coincidence. Deprecated + request to end scripts in ".exp". + + Ted Hopp volunteered to be my Center WERB reader. + +3/23/90 Finished 1st draft of USENIX paper and sent copies to John + Ousterhout and panel chair, dpk@morgan.com. + +3/20/90 1.7 Deprecated "stty", and added more general "system" command. + + Sent Evi some complaints about the business of not allowing + camera-ready at USENIX. + +3/17/90 Sent copies of man page to Doug Gwyn and Larry Wall for + comments. Note that gwyn downloaded it. + +3/16/90 Am really irritated by USENIX. My paper has been put in a + session against another session, the BSD people. Furthermore, + they called my paper an application, when it is no more so than + any other shell or language. Better I should be in "lessons + learned". But it was too late to change the schedule. On top + of that, our session has four people in it, so I'll have very + little time to speak. Grrrr. + +3/13/90 1.6 Added "stty", because without it you can't do things like + turning off echo to accept a password. + +3/8/90 1.5 Abstract was accepted into USENIX!!!! Time to start writing + it! Sent man page to Ousterhout. He didn't seem too + impressed. + + Added "send_user/expect_user" after listening to Ken complain + about how shell could not do timed reads. Actually it can, but + expect does it much more naturally. Deprecated echo. Now, I + realize that expect can be viewed as a shell! + + Changed logfile/loguser to log_file/log_user to match all the + variables with underscores in them. + + Barry Warsaw asked if there was any way one could execute any + command from interact (apparently without any reason in mind). + Nonetheless, it is a wonderful idea, and I changed the "abort + character" in interact to an "escape mechanism". After + escaping, you may execute any command. return duplicates the + old action of the abort character. Now you can do interactive + job control, recursive interacts, etc. You can bet I didn't + get this right the first time! + + At Scott's request, fixed bug related to pty initializing. + Scott was putting expect in the background which disassociated + it from a tty, and I was blindly copying the tty parameters + without checking to see if they were meaningful or not. + + Tightened up exit code. Fixed bug in spawn so it would print + error messages when it failed. Spawn sends back the error + message in the pty, if the fork succeeds but exec fails. Cute! + + Added "close" command. Makes scripts much shorter and cleaner. + + Return string matched by expect directly, rather than setting a + special variable. + + Added "match_max" feature. Probably no one will ever use it. + + Added trace command. + +3/6/90 1.4 Rob Densock was the second user, and suggested (demanded?) the + idea of the loguser command. I added it and changed "log" to + "logfile" making the first incompatibility with existing + scripts (sorry, Steve). + +3/1/90 1.3 Trying to make pty code more robust. Many questions unanswered + by manuals. Did a lot of guessing. While debugging, looked + through pty code in gnuemacs to see if I might increase + portability somehow. Found lots of funky ifdefs on weird + ioctls. Found lots of comments like "this might work". + +2/28/90 Sent a short Tcl bug list to John Ousterhout. He thanked me! + +2/22-3/90 1.2 Hooked my first user, Steve Ray. Surprisingly, he only found + one bug in the code (exit didn't handle args correctly), but it + was obvious that I need to put more explanation in the man + page. Many of the examples in the man page are based upon his + probl.. questions. Thanks, Steve! + +2/20/90 Posted news about expect to "general" newsgroup locally. + +2/15-20/90 Talked to local POSIX reps and then to Steve Albert (AT&T) + about portability of select, wait and other system calls. I'm + not impressed by 1003.1. + +2/9/90 John Ousterhout answered some questions I had about Tcl syntax. + I like this language! + +2/8/90 1.1 Sandy Ressler suggested the idea of being able to spawn + multiple programs at the same time although he didn't say how. + + It took about a day to design and code the spawn_id hook. + Extremely difficult to support this with uucp-style kludge. + Switched to using select. So much for portability. + + I investigated how to do this portably, and spent some time + talking to NIST & AT&T POSIX representatives. Unfortunately, + portability (especially when it comes to select()) remains a + dream. Provided multiple versions of "interact" depending upon + what OS you are running. + +2/7/90 1.0 Completed first cut of "sex" (for "Smart EXec" or + "Send/EXpect"). Supports send, expect, echo, log, spawn, + interact. + + Spent a lot of time making "log" write to log in just the right + order (across fork and while debug flag enabled). Ended up + writing a bunch of variadic log routines. + + Fooled around with uucp-style multiple processes versus one + process doing select() to read asynchronously. Using + uucp-style for now, since it is more portable. + + Gave up on pipes, and switched to ptys. Pipes seem to be + messed up by ftp, perhaps because it goes into raw mode? Ptys + are more efficient and cleaner to program albeit less + well-documented and portable from system to system. + + Ken Manheimer helped me explain what the program does. I kept + saying it does "send/expect" processing, and he kept insisting + that was meaningless to everyone. (In fact, it comes from + uucp, and I guess uucp hackers are indeed a dying breed.) Ken + gave me an elegant enough sentence that I expanded it into an + abstract and sent it in to the USENIX conference the following + day (two days after the deadline). + + I noted that the uucp documentation I referenced in the + submission is dated October 31, 1978! + +1/30/90 0.0 Got a copy of Tcl and went to work. Tcl was exactly what I + need. Plus, it is easy to use, AND it is documented. + +1/25/90 Attended Winter 1990 USENIX in DC, with the goal of banging + heads with some other gurus in hopes of finding a good + send/expect language for a generalized stelnet. Had looked at + uucp and kermit but found nothing general enough. + + Listened to John Ousterhout's presentation on Tcl. By the + middle of the talk, I had found religion. At the end when he + said it was public-domain, I was ready to swoon. + +*/*/88-89 Spent a lot of time telling Scott how useful his program could + be if he made it more general. I thought it wouldn't be that + difficult to make more generic. Scott was interested but not + enough to do it. + +9/25/87 Helped Scott Paisley write a program called stelnet, that + forked a telnet and did very simple send/expect processing. + It used pipes, not ptys. It had no pattern matching, and only + straight-line control without error handling. Nonetheless, + this got me to thinking about making stelnet more generic. + @@ -0,0 +1,282 @@ +This file is INSTALL. It contains installation instructions for Expect. + +If you do not have Tcl, get it (Expect's README explains how) and +install it. The rest of these instructions assume that you have Tcl +installed. + +If you are installing Expect on a single architecture, or are just +trying it out to see whether it is worth installing, follow the +"Simple Installation" below. If you are installing Expect on multiple +architectures or the "Simple Installation" instructions are not +sufficient, see "Sophisticated Installations" below. + +-------------------- +Permissions +-------------------- + +On a Cray, you must be root to compile Expect. See the FAQ for why +this is. + +If you want shared libs on Linux, you must be root in order to run +ldconfig. See the ldconfig man page for more info. + +-------------------- +Simple Installation +-------------------- + +By default, the Tcl source directory is assumed to be in the same +directory as the Expect source directory. For example, in this +listing, Expect and Tcl are both stored in /usr/local/src: + + /usr/local/src/tcl8.0 (actual version may be different) + /usr/local/src/expect-5.24 (actual version may be different) + +If Tcl is stored elsewhere, the easiest way to deal with this is to +create a symbolic link to its real directory. For example, from the +Expect directory, type: + + ln -s /some/where/else/src/tcl8.0 .. + +The same applies for Tk, if you have it. (Tk is optional.) + +Run "./configure". This will generate a Makefile (from a prototype +called "Makefile.in") appropriate to your system. (This step must be +done in the foreground because configure performs various tests on +your controlling tty. If you want to do this step in the background +in the future, automate it using Expect!) + +Most people will not need to make any changes to the generated +Makefile and can go on to the next step. If you want though, you can +edit the Makefile and change any definitions as appropriate for your +site. All the definitions you are likely to want to change are +clearly identified and described at the beginning of the file. + +To build only the stand-alone Expect program, run "make expect". This +is appropriate even if you still haven't decided whether to install +Expect, are still curious about it, and want to do the minimum +possible in order to experiment with it. + +To build everything, run "make". If "configure" found Tk and X on +your system, this will build "expectk" (Expect with Tk). + +Once expect is built, you can cd to the example directory and try out +some of the examples (see the README file in the example directory). +Note that if Tcl has not yet been installed, this won't work. In this +case, see the instructions "Trying Expect Without Installing Tcl" +below. + +"make install" will install Expect. If you built Expectk, that will +be installed as well. So will the documentation and some of the most +useful examples. + +If you want shared libs on Linux, you must now su to root and run +ldconfig on the shared library. See the ldconfig man page for more +info. + +A handful of people running "pure" 4.2BSD systems have noted that +expect fails to link due to lack of getopt and vprintf. You can get +these from uunet or any good archive site. + +-------------------- +Trying Expect Without Installing Tcl +-------------------- + +Once expect is built, you can try it out. If Tcl has not been +installed (but it has been compiled), you will need to define the +environment variable TCL_LIBRARY. It should name the directory +contain the Tcl libraries. For example, if you are using csh with Tcl +8.0.3: + + $ setenv TCL_LIBRARY ../tcl8.0.3/library + +Now you can run expect. + +The same advice applies to Tk. If it is available but has not been +installed, you can try out expectk but only after defining TK_LIBRARY. +For example, if you are using csh with Tk 8.0.3: + + $ setenv TK_LIBRARY ../tk8.0.3/library + +Now you can run expectk. + +-------------------- +Sophisticated Installations +-------------------- + +The following instructions provide some suggestions for handling +complex installations. + +-------------------- +Changing Defaults +-------------------- + +The configure script allows you to customize the Expect configuration +for your site; for details on how you can do this, type "./configure +-help" or refer to the autoconf documentation (not included here). +Expect's configure supports the following flags in addition to the +standard ones: + + --verbose Cause configure to describe + what it is checking and what it decides. + + --enable-shared Compile Expect as a shared library if it + can figure out how to do that on this + platform. (You must have already + compiled Tcl with this flag.) + + --disable-load This switch is ignored so that you can + configure Expect with the same configure + command as Tcl. If you want to disable + dynamic loading, configure Tcl with this + flag and then reconfigure Expect. + + --enable-gcc This switch is ignored so that you can + configure Expect with the same configure + command as Tcl. If you want to enable gcc, + configure Tcl with it and then reconfigure + Expect. Expect will inherit the definition + that way. It is not safe to modify the + Makefile to use gcc by hand. If you do + this, then information related to dynamic + linking will be incorrect. + + --enable-threads This switch is ignored so that you can + configure Expect with the same configure + command as Tcl. + + --with-tcl=... Specifies the directory containing Tcl's + configure file (tclConfig.sh). + + --with-tclinclude=... Specifies the directory containing Tcl's + private include files (such as tclInt.h) + + --with-tk=... Specifies the directory containing Tk's + configure file (tkConfig.sh). + + --with-tkinclude=... Specifies the directory containing Tk's + private include files (such as tkInt.h) + +Some of the defaults in "configure" can be overridden by environment +variables. This is a convenience intended for environments that are +likely to affect any program that you configure and install. + +The following environment variables are supported. If you use these, +consider adding them to your .login file so that other installation +scripts can make use of them. + +CC C compiler +CFLAGS Flags to C compiler +CPPFLAGS Flags to C preprocessor +LDFLAGS Flags to linker +LIBS Libraries +CONFIG_SHELL Shell for configure and Make + +Settings can also be given on the command line. For example, you +could tell configure about flags from a Bourne-compatible shell as +follows: + + CFLAGS=-O2 LIBS=-lposix ./configure + +Although configure will do some searching for Tcl (and all of this +discussion holds true for Tk as well), configure likes to find the Tcl +source directory in the parent directory of Expect and will use that +Tcl if it exists. To make sure Tcl can be found this way (if it is +located somewhere else), create a symbolic link in Expect's parent +directory to where the Tcl directory is. + +By default, configure uses the latest Tcl it can find. You can +override this by creating a symbolic link of "tcl" which points to the +release you want. + +If you can't or don't want to create symbolic links, you can instead +indicate where Tcl and Tk are by using the following environment variables: + +with_tcl Directory containing Tcl configure file (tclConfig.h) +with_tclinclude Directory containing Tcl include files +with_tkinclude Directory containing Tk include files +with_tk Directory containing Tk binary library (tkConfig.h) + +-------------------- +Multiple-Architecture Installation +-------------------- + +You might want to compile a software package in a different directory +from the one that contains the source code. Doing this allows you to +compile the package for several architectures simultaneously from the +same copy of the source code and keep multiple sets of object files on +disk. + +To compile the package in a different directory from the one +containing the source code, you must use a version of make that +supports the VPATH variable. GNU make and most other recent make +programs can do this. + +cd to the directory where you want the object files and executables to +go and run configure. configure automatically checks for the source +code in the directory that configure is in and in .. If configure +reports that it cannot find the source code, run configure with the +option --srcdir=dir, where dir is the directory that contains the +source code. + +You can save some disk space by installing architecture-independent +files (e.g., scripts, include files) in a different place than +architecture-dependent files (e.g., binaries, libraries). To do this, +edit the Makefile after configure builds it, or have configure create +the Makefile with the right definitions in the first place. To have +configure do it, use the following options to configure: + + --prefix=indep + --exec-prefix=dep + +where dep is the root of the tree in which to store +architecture-dependent files and indep is the root in which to +store -dependent files. For example, you might invoke configure this +way: + + configure --prefix=/usr/local/bin --exec-prefix=/usr/local/bin/arch + +-------------------- +Test Suite +-------------------- + +Patterned after the Tcl test suite, I have begun building a test suite +in the subdirectory "test". It is still incomplete however you may +use by typing "make test" in this directory. You should then see a +printout of the test files processed. If any errors occur, you'll see +a much more substantial printout for each error. See the README file +in the "tests" directory for more information on the test suite. + +Note that the test suite assumes the existence of certain programs to +use as interactive programs. If you are missing these or they behave +differently, errors may be reported. Similarly, the test suite +assumes certain other things about your system, such as the sane stty +parameters. + +You may also try some of the programs distribute in the example +directory (see the README file in the example directory). They are a +strong indication of whether Expect works or not. If you have any +problems with them, let me know. + +-------------------- +Uninstalling +-------------------- + +"make uninstall" removes all the files that "make install" creates +(excluding those in the current directory). + +-------------------- +Cleaning Up +-------------------- + +Several "clean" targets are available to reduce space consumption of +the Expect source. The two most useful are as follows: + +"make clean" deletes all files from the current directory that were +created by "make" + +"make distclean" is like "make clean", but it also deletes files +created by "configure" + +Other targets can be found in the Makefile. They follow the GNU +Makefile conventions. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..c05c880 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,636 @@ +# Makefile.in -- +# +# This file is a Makefile for Expect TEA Extension. If it has the name +# "Makefile.in" then it is a template for a Makefile; to generate the +# actual Makefile, run "./configure", which is a configuration script +# generated by the "autoconf" program (constructs like "@foo@" will get +# replaced in the actual Makefile. +# +# Copyright (c) 1999 Scriptics Corporation. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: Makefile.in,v 5.51 2010/09/30 17:14:07 andreas_kupries Exp $ + +#======================================================================== +#======================================================================== + +# expect must be setuid on crays in order to open ptys (and accordingly, +# you must run this Makefile as root). +# See the FAQ for more info on why this is necessary on Crays. +SETUID = @SETUID@ +# SETUID = chmod u+s + +LIB_RUNTIME_DIR = $(DESTDIR)@libdir@ + +# The following Expect scripts are not necessary to have installed as +# commands, but are very useful. Edit out what you don't want +# installed. The INSTALL file describes these and others in more +# detail. Some Make's screw up if you delete all of them because +# SCRIPTS is a target. If this is a problem, just comment out the +# SCRIPTS target itself. + +SCRIPTS = timed-run timed-read ftp-rfc autopasswd lpunlock weather \ + passmass rftp kibitz rlogin-cwd xpstat tkpasswd dislocate xkibitz \ + tknewsbiff unbuffer mkpasswd cryptdir decryptdir autoexpect \ + multixterm + +# A couple of the scripts have man pages of their own. +# You can delete these too if you don't want'em. + +SCRIPTS_MANPAGES = kibitz dislocate xkibitz tknewsbiff unbuffer mkpasswd \ + passmass cryptdir decryptdir autoexpect multixterm + + +# allow us to handle null list gracefully, "end_of_list" should not exist + +SCRIPT_LIST = $(SCRIPTS) end_of_list +SCRIPT_MANPAGE_LIST = $(SCRIPTS_MANPAGES) end_of_list + +# Short directory path where binaries can be found to support #! hack. +# This directory path can be the same as the directory in which the +# binary actually sits except when the path is so long that the #! +# mechanism breaks (usually at 32 characters). The solution is to +# create a directory with a very short name, which consists only of +# symbolic links back to the true binaries. Subtracting two for "#!" +# and a couple more for arguments (typically " -f" or " --") gives you +# 27 characters. Pathnames over this length won't be able to use the +# #! magic. For more info on this, see the execve(2) man page. + +SHORT_BINDIR = $(exec_prefix)/bin + +#======================================================================== +# Nothing of the variables below this line should need to be changed. +# Please check the TARGETS section below to make sure the make targets +# are correct. +#======================================================================== + +#======================================================================== +# The names of the source files is defined in the configure script. +# The object files are used for linking into the final library. +# This will be used when a dist target is added to the Makefile. +# It is not important to specify the directory, as long as it is the +# $(srcdir) or in the generic, win or unix subdirectory. +#======================================================================== + +PKG_SOURCES = @PKG_SOURCES@ +PKG_OBJECTS = @PKG_OBJECTS@ + +PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ +PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ + +#======================================================================== +# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with +# this package that need to be installed, if any. +#======================================================================== + +PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ + +#======================================================================== +# This is a list of public header files to be installed, if any. +#======================================================================== + +PKG_HEADERS = @PKG_HEADERS@ + +#======================================================================== +# "PKG_LIB_FILE" refers to the library (dynamic or static as per +# configuration options) composed of the named objects. +#======================================================================== + +PKG_LIB_FILE = @PKG_LIB_FILE@ +PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ + +lib_BINARIES = $(PKG_LIB_FILE) +bin_BINARIES = expect +BINARIES = $(lib_BINARIES) $(bin_BINARIES) + +SHELL = @SHELL@ + +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +libdir = @libdir@ +datadir = @datadir@ +mandir = @mandir@ +includedir = @includedir@ + +DESTDIR = + +PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) +pkgdatadir = $(datadir)/$(PKG_DIR) +pkglibdir = $(libdir)/$(PKG_DIR) +pkgincludedir = $(includedir)/$(PKG_DIR) + +top_builddir = . + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +CC = @CC@ +CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ +CFLAGS_WARNING = @CFLAGS_WARNING@ +CLEANFILES = @CLEANFILES@ +EXEEXT = @EXEEXT@ +LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ +MAKE_LIB = @MAKE_LIB@ +MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ +MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ +MAKE_STUB_LIB = @MAKE_STUB_LIB@ +OBJEXT = @OBJEXT@ +RANLIB = @RANLIB@ +RANLIB_STUB = @RANLIB_STUB@ +SHLIB_CFLAGS = @SHLIB_CFLAGS@ +SHLIB_LD = @SHLIB_LD@ +SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ +STLIB_LD = @STLIB_LD@ +TCL_DEFS = @TCL_DEFS@ +TCL_BIN_DIR = @TCL_BIN_DIR@ +TCL_SRC_DIR = @TCL_SRC_DIR@ +# Not used, but retained for reference of what libs Tcl required +TCL_LIBS = @TCL_LIBS@ + +#======================================================================== +# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our +# package without installing. The other environment variables allow us +# to test against an uninstalled Tcl. Add special env vars that you +# require for testing here (like TCLX_LIBRARY). +#======================================================================== + +EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) +TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ + @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ + PATH="$(EXTRA_PATH):$(PATH)" \ + TCLLIBPATH="$(top_builddir)" +TCLSH_PROG = @TCLSH_PROG@ +TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) +SHARED_BUILD = @SHARED_BUILD@ + +INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ + +PKG_CFLAGS = @PKG_CFLAGS@ + +# TCL_DEFS is not strictly need here, but if you remove it, then you +# must make sure that configure.in checks for the necessary components +# that your library may use. TCL_DEFS can actually be a problem if +# you do not compile with a similar machine setup as the Tcl core was +# compiled with. +#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) +DEFS = @DEFS@ $(PKG_CFLAGS) + +CONFIG_CLEAN_FILES = Makefile + +CPPFLAGS = @CPPFLAGS@ +LIBS = @PKG_LIBS@ @LIBS@ +AR = @AR@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +#======================================================================== +# Start of user-definable TARGETS section +#======================================================================== + +#======================================================================== +# TEA TARGETS. Please note that the "libraries:" target refers to platform +# independent files, and the "binaries:" target inclues executable programs and +# platform-dependent libraries. Modify these targets so that they install +# the various pieces of your package. The make and install rules +# for the BINARIES that you specified above have already been done. +#======================================================================== + +all: binaries libraries doc + +#======================================================================== +# The binaries target builds executable programs, Windows .dll's, unix +# shared/static libraries, and any other platform-dependent files. +# The list of targets to build for "binaries:" is specified at the top +# of the Makefile, in the "BINARIES" variable. +#======================================================================== + +binaries: $(BINARIES) pkgIndex.tcl-hand + +libraries: + +doc: + +install: all install-binaries install-libraries install-doc + +install-binaries: binaries install-lib-binaries install-bin-binaries + +#======================================================================== +# This rule installs platform-independent files, such as header files. +#======================================================================== + +install-libraries: libraries $(SCRIPTS) + @mkdir -p $(DESTDIR)$(includedir) + @echo "Installing header files in $(DESTDIR)$(includedir)" + @list='$(PKG_HEADERS)'; for i in $$list; do \ + echo "Installing $(srcdir)/$$i" ; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ + done; +# install standalone scripts and their man pages, if requested + @mkdir -p $(DESTDIR)$(prefix)/bin + -for i in $(SCRIPT_LIST) ; do \ + if [ -f $$i ] ; then \ + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(prefix)/bin/$$i ; \ + rm -f $$i ; \ + else true; fi ; \ + done + +#======================================================================== +# Install documentation. Unix manpages should go in the $(mandir) +# directory. +#======================================================================== + +install-doc: doc + @mkdir -p $(DESTDIR)$(mandir)/man1 + @mkdir -p $(DESTDIR)$(mandir)/man3 + @echo "Installing documentation in $(DESTDIR)$(mandir)" +# install Expect man page + $(INSTALL_DATA) $(srcdir)/expect.man $(DESTDIR)$(mandir)/man1/expect.1 +# install man page for Expect library + $(INSTALL_DATA) $(srcdir)/libexpect.man $(DESTDIR)$(mandir)/man3/libexpect.3 + -for i in $(SCRIPT_MANPAGE_LIST) ; do \ + if [ -f $(srcdir)/example/$$i.man ] ; then \ + $(INSTALL_DATA) $(srcdir)/example/$$i.man $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + else true; fi ; \ + done + +test: binaries libraries + $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) + +shell: binaries libraries + @$(TCLSH) $(SCRIPT) + +expectshell: binaries libraries + @$(TCLSH_ENV) expect $(SCRIPT) + +gdb: + $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) + +depend: + +#======================================================================== +# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable +# mentioned above. That will ensure that this target is built when you +# run "make binaries". +# +# The $(PKG_OBJECTS) objects are created and linked into the final +# library. In most cases these object files will correspond to the +# source files above. +#======================================================================== + +$(PKG_LIB_FILE): $(PKG_OBJECTS) + -rm -f $(PKG_LIB_FILE) + ${MAKE_LIB} + $(RANLIB) $(PKG_LIB_FILE) + +$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) + -rm -f $(PKG_STUB_LIB_FILE) + ${MAKE_STUB_LIB} + $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) + +#======================================================================== +# We need to enumerate the list of .c to .o lines here. +# +# In the following lines, $(srcdir) refers to the toplevel directory +# containing your extension. If your sources are in a subdirectory, +# you will have to modify the paths to reflect this: +# +# Expect.$(OBJEXT): $(srcdir)/generic/Expect.c +# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/Expect.c` -o $@ +# +# Setting the VPATH variable to a list of paths will cause the makefile +# to look into these paths when resolving .c to .obj dependencies. +# As necessary, add $(srcdir):$(srcdir)/compat:.... +#======================================================================== + +VPATH = $(srcdir) + +.c.@OBJEXT@: + $(COMPILE) -c `@CYGPATH@ $<` -o $@ + +#======================================================================== +# Create the pkgIndex.tcl file. +# It is usually easiest to let Tcl do this for you with pkg_mkIndex, but +# you may find that you need to customize the package. If so, either +# modify the -hand version, or create a pkgIndex.tcl.in file and have +# the configure script output the pkgIndex.tcl by editing configure.in. +#======================================================================== + +pkgIndex.tcl: + ( echo pkg_mkIndex . $(PKG_LIB_FILE) \; exit; ) | $(TCLSH) + +pkgIndex.tcl-hand: + (echo 'if {![package vsatisfies [package provide Tcl] @TCL_VERSION@]} {return}' ; \ + echo 'package ifneeded Expect $(PACKAGE_VERSION) \ + [list load [file join $$dir $(PKG_LIB_FILE)]]'\ + ) > pkgIndex.tcl + +#======================================================================== +# Distribution creation +# You may need to tweak this target to make it work correctly. +#======================================================================== + +TAR = tar +#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar +COMPRESS = $(TAR) zcvf $(PKG_DIR).tar.gz $(PKG_DIR) +DIST_ROOT = /tmp/dist +DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) + +dist-clean: + rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* + +dist: dist-clean doc + mkdir -p $(DIST_DIR) + cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \ + $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ + $(srcdir)/fixline1 \ + $(DIST_DIR)/ + chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 + chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in + + mkdir $(DIST_DIR)/tclconfig + cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ + $(srcdir)/tclconfig/config.guess $(srcdir)/tclconfig/config.sub \ + $(DIST_DIR)/tclconfig/ + chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 + chmod +x $(DIST_DIR)/tclconfig/install-sh + + cp -p $(srcdir)/*.{c,h,man} $(srcdir)/vgrindefs $(srcdir)/NEWS \ + $(srcdir)/INSTALL $(srcdir)/FAQ $(srcdir)/HISTORY \ + $(DIST_DIR)/ + chmod 664 $(DIST_DIR)/*.{c,h,man} + + -list='demos example generic library tests unix win tests testsuite'; \ + for p in $$list; do \ + if test -d $(srcdir)/$$p ; then \ + mkdir -p $(DIST_DIR)/$$p; \ + cp -p $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \ + fi; \ + done + (cd $(DIST_ROOT); $(COMPRESS);) + cp $(DIST_ROOT)/$(PKG_DIR).tar.gz $(top_builddir) + +$(SCRIPTS): + $(TCLSH) $(srcdir)/fixline1 $(SHORT_BINDIR) < $(srcdir)/example/$@ > $@ + +## We cannot use TCL_LIBS below (after TCL_LIB_SPEC) because its +## expansion references the contents of LIBS, which contains linker +## options we cannot use here (and which is what we are replacing in +## the first place). + +expect: exp_main_exp.o $(PKG_LIB_FILE) + $(CC) \ + @CFLAGS@ \ + @LDFLAGS_DEFAULT@ \ + -o expect exp_main_exp.o \ + @EXP_BUILD_LIB_SPEC@ \ + @TCL_LIB_SPEC@ \ + @TCL_DL_LIBS@ @PKG_LIBS@ @MATH_LIBS@ \ + @TCL_CC_SEARCH_FLAGS@ \ + @EXP_CC_SEARCH_FLAGS@ + $(SETUID) expect + +expectk: + @echo "expectk remove from distribution" + @echo "use tclsh with package require Tk and Expect" + +#======================================================================== +# Produce FAQ and homepage +#======================================================================== + +WEBDIR = /proj/itl/www/div826/subject/expect +VERSION = $(PACKAGE_VERSION) + +# create the FAQ in html form +FAQ.html: FAQ.src FAQ.tcl + FAQ.src html > FAQ.html + +# create the FAQ in text form +FAQ: FAQ.src FAQ.tcl + FAQ.src text > FAQ + +# generate Expect home page +homepage.html: homepage.src homepage.tcl expect.tar.gz.md5 + homepage.src > homepage.html + +expect.tar.gz.md5: expect-$(VERSION).tar.gz + md5 expect-$(VERSION).tar.gz > expect.tar.gz.md5 + +# install various html docs on our web server +install-html: FAQ.html homepage.html + cp homepage.html $(WEBDIR)/index.html + cp FAQ.html $(WEBDIR) + +# HTMLize man pages for examples and push them out to the web server +example-man-pages: + -for i in $(SCRIPT_MANPAGE_LIST) ; do \ + if [ -f $(srcdir)/example/$$i.man ] ; then \ + rman -f HTML $(srcdir)/example/$$i.man > $(srcdir)/example/$$i.man.html ; \ + cp $(srcdir)/example/$$i.man.html $(FTPDIR)/example ; \ + else true; fi ; \ + done + +#======================================================================== +# Push out releases +#======================================================================== + +FTPDIR = /proj/itl/www/div826/subject/expect + +# make a private tar file for myself +tar: expect-$(VERSION).tar + mv expect-$(VERSION).tar expect.tar + +# make a release and install it on ftp server +# update web page to reflect new version +ftp: expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz install-html homepage.html + cp expect-$(VERSION).tar.Z $(FTPDIR)/expect.tar.Z + cp expect-$(VERSION).tar.gz $(FTPDIR)/expect.tar.gz + cp expect-$(VERSION).tar.gz $(FTPDIR)/old/expect-$(VERSION).tar.gz + md5 $(FTPDIR)/expect.tar.gz > expect.tar.gz.md5 + cp HISTORY $(FTPDIR) + cp README $(FTPDIR)/README.distribution + cp example/README $(FTPDIR)/example + cp `pubfile example` $(FTPDIR)/example + ls -l $(FTPDIR)/expect.tar* +# delete .Z temp file, still need .gz though for md5 later + rm expect-$(VERSION).tar* + +# make an alpha release and install it on ftp server +alpha: expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz + cp expect-$(VERSION).tar.Z $(FTPDIR)/alpha.tar.Z + cp expect-$(VERSION).tar.gz $(FTPDIR)/alpha.tar.gz + cp HISTORY $(FTPDIR) + rm expect-$(VERSION).tar* + ls -l $(FTPDIR)/alpha.tar* + +# make a beta release and install it on ftp server +beta: expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz + rm -rf $(FTPDIR)/alpha.tar* + cp expect-$(VERSION).tar.Z $(FTPDIR)/beta.tar.Z + cp expect-$(VERSION).tar.gz $(FTPDIR)/beta.tar.gz + cp HISTORY $(FTPDIR) + rm expect-$(VERSION).tar* + ls -l $(FTPDIR)/beta.tar* + +expect-$(VERSION).tar: configure + rm -f ../expect-$(VERSION) + ln -s `pwd` ../expect-$(VERSION) + cd ..;tar cvfh $@ `pubfile expect-$(VERSION)` + mv ../$@ . + +expect-$(VERSION).tar.Z: expect-$(VERSION).tar + compress -fc expect-$(VERSION).tar > $@ + +expect-$(VERSION).tar.gz: expect-$(VERSION).tar + gzip -fc expect-$(VERSION).tar > $@ + +#======================================================================== +# End of user-definable section +#======================================================================== + +#======================================================================== +# Don't modify the file to clean here. Instead, set the "CLEANFILES" +# variable in configure.in +#======================================================================== + +clean: + -test -z "$(BINARIES)" || rm -f $(BINARIES) + -rm -f *.$(OBJEXT) core *.core + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean: clean + -rm -f *.tab.c + -rm -f $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log config.status + +#======================================================================== +# Install binary object libraries. On Windows this includes both .dll and +# .lib files. Because the .lib files are not explicitly listed anywhere, +# we need to deduce their existence from the .dll file of the same name. +# Library files go into the lib directory. +# In addition, this will generate the pkgIndex.tcl +# file in the install location (assuming it can find a usable tclsh shell) +# +# You should not have to modify this target. +#======================================================================== + +install-lib-binaries: + @mkdir -p $(DESTDIR)$(pkglibdir) + @list='$(lib_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ + stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ + if test "x$$stub" = "xstub"; then \ + echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ + $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ + else \ + echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ + $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ + fi; \ + ext=`echo $$p|sed -e "s/.*\.//"`; \ + if test "x$$ext" = "xdll"; then \ + lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ + if test -f $$lib; then \ + echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ + $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ + fi; \ + fi; \ + fi; \ + done + @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + destp=`basename $$p`; \ + echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ + fi; \ + done + @if test "x$(SHARED_BUILD)" = "x1"; then \ + echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ + $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ + fi + +#======================================================================== +# Install binary executables (e.g. .exe files and dependent .dll files) +# This is for files that must go in the bin directory (located next to +# wish and tclsh), like dependent .dll files on Windows. +# +# You should not have to modify this target, except to define bin_BINARIES +# above if necessary. +#======================================================================== + +install-bin-binaries: + @mkdir -p $(DESTDIR)$(bindir) + @list='$(bin_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ + fi; \ + done + +.SUFFIXES: .c .$(OBJEXT) .man .n .html + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +uninstall-binaries: + list='$(lib_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + p=`basename $$p`; \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(bin_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/$$p; \ + done + +#======================================================================== +# +# Target to regenerate header files and stub files from the *.decls tables. +# +#======================================================================== + +genstubs: + $(TCLSH_PROG) \ + $(srcdir)/tools/genStubs.tcl $(srcdir)/generic \ + $(srcdir)/Expect.decls + +#======================================================================== +# +# Target to check that all exported functions have an entry in the stubs +# tables. +# +#======================================================================== + +Expect_DECLS = \ + $(srcdir)/expect.decls + +checkstubs: + -@for i in `nm -p $(Expect_LIB_FILE) | awk '$$2 ~ /T/ { print $$3 }' \ + | sort -n`; do \ + match=0; \ + for j in $(Expect_DECLS); do \ + if [ `grep -c $$i $$j` -gt 0 ]; then \ + match=1; \ + fi; \ + done; \ + if [ $$match -eq 0 ]; then echo $$i; fi \ + done + + +.PHONY: all binaries clean depend distclean doc install libraries test chantest + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: @@ -0,0 +1,715 @@ +This file is the NEWS file from the Expect distribution. + +====================================================================== +====================================================================== + +Date: 08/01/00 + +** SUMMARY + +Expect 5.32 is being released in conjuction with Tcl 8.3.2. +This is a fairly minor update with no feature changes but with +a number of useful bug fixes in the way expects uses the new +regular expression engine and the UTF-8 features of Tcl. +Details are in the HISTORY and ChangeLog files. + +====================================================================== +====================================================================== + +Date: 10/22/99 + +** SUMMARY + +Expect 5.31 now works with Tcl 8.2. Expect 5.31 does NOT work with +prior releases of Tcl. Thanks to an incredible amount of work by +Scott Stanton, Henry Spencer, Melissa Hirschl, and funding from +Scriptics for making this possible. + +** NEW FEATURES + +What? You mean that working with Tcl 8.2 isn't enough????? + +Expect supports Tcl's new regexp engine. + +Expect supports null bytes in strings directly. (You no longer have +to use the "null" keyword to send or match nulls. Of course, the +"null" keyword will continue to be supported.) Null removal (on +input) is still enabled by default since nulls are almost never +intended for end-user consumption in interactive dialogues. + +** CHANGES IN BEHAVIOR (POTENTIAL INCOMPATIBILITIES) + +The interpreter command used to exit upon eof. Now it uses "-eof +script" to control this behavior. The default behavior is to return. +(This change was required because Expect now gives control to Tcl upon +exit and Tcl waits (potentially forever) for all processes to die on +exit.) Explicit calls to interpreter are almost non-existent. +However, you should look for *implicit* calls via interact commands +with a pattern but no action. This required changes in the examples: +dislocate, dvorak, kibitz, and xkibitz. + +Indirect variables can no longer start with "exp". Such variables +will be interpreted as channel names. + +Old-style regexps may need conversion. If you have been protecting +regexps containing backslashes with {}, then you need to examine all +your backslashes since the new regexp engine interprets backslash +sequences (such as \n) itself. For example: + + expect "\n" (works the same in Tcl 8.0 and 8.1) + expect {\n} (works differently in Tcl 8.0 and 8.1) + +Scriptics has also created a new-regexp-features page which you should +read: http://www.scriptics.com/support/howto/regexp81.html. Some of +the new features allow much more efficient regexps than before. For +example, non-greedy quantifiers can replace [split] looping +constructions with a single regexp, enabling Tcl to parse very +efficiently. For the whole story, read the re_syntax man page. + +The interact command's regexp matching no longer skips nulls. (I'd be +surprised if anyone misses this. At least I hope ....) + +Expect's C library now reports failures in spawn's underlying exec +directly (by returning -1) rather than the way it used to (as data in +the pty). This makes user code more robust. However, it requires you +to simplify your code, alas. See the chesslib.c example. + +Linking with Expect's C library no longer requires the Tcl library +(unless, of course, you make Tcl calls yourself). Tcl is still +required to build the library in the first place, however. + +** CHANGES IN BEHAVIOR (SHOULD NOT CAUSE INCOMPATIBILITIES) + +The match_max command now controls by bytes, not chars. This won't +cause problems unless your existing scripts are interacting using +sizeable chunks of multibyte characters. (If you don't know what I'm +talking about, ignore this.) + +The Make/configure suite now corresponds to the TEA conventions (at +least in theory; the conventions are changing regularly so it's hard +to be less vague on this point). Significantly, this means that you +should be able to use the same configure flags as when compiling Tcl +or any other TEA-compatible extension. (See the INSTALL file.) + +The values of special variables such as exp_spawn_id_any have changed. +(The values were never documented so you shouldn't have been using +them anyway.) + +Spawn ids now appear as "exp...". (They used to be small integers.) +Do not assume that spawn ids will continue to be represented in any +particular way (other than unique strings). + +** OTHER NOTES + +Expect uses channels. There is an Expect channel type. It is +possible to use Tcl's channel commands, such as fconfigure, to change +the encoding. However, Expect layers its own buffering system on top +of Tcl's channel handler so don't expect intuitive behavior when using +commands such as gets and puts. Unless you know what you're doing, I +recommend manipulating the Expect channels only with the expect +commands. + +Some effort was made to make Expect support threads, however it is not +complete. You can compile Expect with threads enabled but don't run +Expect in multiple threads just yet. + +So much code has changed, there are bound to be bugs in dark corners. +Please let me know of such cases. The best response will come by +supplying a simple test case that can be added to Expect's test suite. + +In places where the behavior of Expect was not precisely documented, +full advantage was taken to do something different :-) + +Several esoteric bugs were fixed. + +Although Expect itself uses Henry Spencer's new regexp engine, +Expect's C library still uses his original regexp engine. + +No testing has been done of the poll and non-event subsystems. (These +are used on systems which don't support select on ptys or ttys. Some +minor work needs to be done on them (because the event subsystem was +rewritten) which I'll probably do only if anyone requests it. + +Many deprecated features (deprecated for many years!) have been +removed. All such features were deprecated prior to Exploring Expect +so if that's how you learned Expect, you have nothing to worry about. +For example, Expect's getpid command predates Tcl's pid command and +it's been deprecated for, oh.... 6 years - wow! Other deprecated features +include: + expect -timestamp (flag only; behavior itself was removed years ago) + expect -iwrite (flag only; behavior occurs all the time) + expect_version (use "exp_version" command) + expect_library (use "exp_library" global variable) + interact -eof (use "eof" keyword) + interact -timeout (use "timeout" keyword) + interact -timestamp (use "clock" command) + getpid (use "pid" command) + system stty (use "stty" command) + +With this release, the following are deprecated: + timestamp (use "clock" command) + debugger (use a different one; there are very nice replacements + around. Fortunately the Expect debugger is not something anyone + is wiring into their scripts, so for now, consider it on the + endangered species list. Anyone still want this debugger?) + +From now on, the most current snapshots of Expect will be found in the +Scriptics CVS repository. Not all snapshots are official releases. + +====================================================================== +====================================================================== + +Date: 8/18/96 + +Expect now works with Tcl 8.0. + +No changes were made to take advantage of 8.0 features such as +namespaces. (If you want to put the Expect commands in a namespace, +declare a namespace before loading them in.) + +Even though Tcl allows embedded nulls in commands, Expect still does +not. Tcl still doesn't support embedded in patterns and regexps. +I'll wait til Tcl supports that before rewriting Expect's null +support. + + +====================================================================== +====================================================================== + +Date: 9/28/96 + +There is now an Expect FAQ and home page. Feedback is encouraged. +You can get to the FAQ from the home page and vice versa, so you only +need to remember one of the links, but here are both for completeness: + +home page: http://expect.nist.gov +FAQ: http://expect.nist.gov/FAQ.html + + + +====================================================================== +====================================================================== +This section describes the changes to Expect 5, many due to changes +from Tcl 7.4 to 7.5. + +Improvements +============================== + +You can now use expect_background from Tcl along with all the +Tcl-based event stuff such as "after". You can also do fun things +such as have "after" actions run while expect is waiting for input. +It's worth comparing the difference between commands such as expect +(which waits in the event loop) and gets (which doesn't). + +Incompatibilities +============================== + +libexpectk is gone. Because of the event loop was moved into Tcl, +this is no longer necessary. Just use the regular Expect library. +This only affects you if are hand-linking. + +The name of the static C library now has the extension on the end - +just like Tcl. This only affects you if are hand-linking. + + +============================== +Some obvious questions and answers + +Nothing in the user interface has changed. All your old scripts +should run. Tcl now has commands that replace Expect functionality in +the area of version control and date handling. I encourage you to use +Tcl's support rather than Expect's for any new scripts that you write. +However, I won't be removing Expect's commands, so don't worry about +having to convert old scripts. + +It is my understand that shared/dl libs work. (I say "it is my +understanding", because my own environment doesn't handle it, sigh. +My system admins tell me that they're working on it.) So I've had to +guess on some things - in fact, I've talked to a number of people and +I get the feeling that a lot of people are guessing on shared/dl libs. +I have yet to talk to anyone that REALLY understands this stuff (by +"understand", I mean "can write the configure/Makefile portably and +correctly". So much for my griping. In theory, the shared/dl support +is pretty much a freebie because Tcl itself provides all the support +for this. (There is some reorganization that could be done to improve +shared library memory use - I'll get to it eventually - it shouldn't +affect most people.) Don't send me complaints about shared/dl libs +unless you are *positive* it is something that I am responsible for. +Even if Tcl works and Expect fails, it is likely to be a Tcl error (or +more precisely, a configuration problem that is more appropriately +fixed from the Tcl distribution). + +For Tcl-package purposes, Expect is called "Expect". (Duh...) + +Expect's multiple interpreter support is minimal. It should work for +most things, serendipitously. I haven't spent any time making this +perfect. + +No, this release isn't portable to Windows or Mac. Let me know if +you're seriously interested in a lot of work. I'm not saying it's not +possible. It's definitely possible and the porting working at Sun has +made it easier than before. But it's still not a weekend hack. + +============================== +Building the code +============================== + +Expect builds as usual. (See the INSTALL file for details.) + +The only significant change is that Expect now has to find the +tclConfig.sh file (and tkConfig.sh if you want). So if you like to +store Tcl where Expect can't find it, you'll need to use even more +configure flags than you used to. + +Shared/dl Expect libraries are built if you configured Tcl for +shared/dl libraries. + +All support for earlier versions of Tcl and Tk have been removed from +Expect. For example, if you're still using Tcl 7.4 (or earlier), +don't bother to install this release. + +====================================================================== +====================================================================== +This section describes the changes from Expect 4 to Expect 5. + +The changes that people will find most interesting or annoying are as +follows. Some of them may seem rather arbitrary but fix inconsistencies +leading to much cleaner coding both internally and externally. + + +-- Expect version 5.20 and above is designed to work with Tcl 7.5 and +Tk 4.1. Expect 5.20 and above will not work with earlier versions. + +-- Glob-style patterns do longest-possible matches (from the earliest +possible position) just like regexps. Previously, they matched the +shortest-possible strings. However, the documentation didn't actually +say this (it didn't say anything) + +-- Exact patterns are now supported from expect. Use the "-ex" flag. +Exact patterns work just like those in interact. No special handling +is made of *, ^, etc. + +-- The new command "expect_background" registers patterns that are to +be tested against spawned process output whenever it appears (i.e., +asynchronously). This only works in the Tk environment. The +arguments are the same as the expect command. + +-- expect_before and expect_after now handle their arguments like +expect_background. Previously, a command such as "expect_before" +with no arguments deleted patterns for all spawn ids. Now, it only +deletes patterns for the current spawn id. Similarly with the "-i" +form. + +-- expect_background/before/after support an -info flag to query what +the current patterns are. The results are returned in such a way that +they can be re-used by a new expect command. + +The -info flag must be the first flag in the command. With no other +arguments, it returns the setting for the current spawn id. With a -i +descriptor, information is returned for that spawn id. The argument +-noindirect may be used to suppress indirects which also match a +direct spawn id. Only a single -i specification may be given with +-info. With the argument "-all", all spawn id specifications are +reported. + +-- There is now a sleep command. It understands decimal values such as + + sleep .5 + +Interrupts and other asynchronous events are processed while Expect sleeps. + +-- Traps now use Tcl's "Async" support. This has advantages and +disadvantages. One advantage is that traps have no chance of screwing +up the Tcl internals. One disadvantage is that trap handlers are +delayed at certain specific times and places. For example, a handler +cannot occur inside another handler. While one handler is running, +all other handlers are blocked. This is probably the most noticable +place where handlers are blocked. Others are generally small windows, +so you shouldn't notice the delay in executing the handlers. + +Several traps are initially defined: + + trap exit {SIGINT SIGTERM} + +If you use the -D flag to start the debugger, the following trap is +defined: + + trap {exp_debug 1} SIGINT + +You can, of course, override these. In particular, if you have your +own "trap exit SIGINT", this will override the debugger trap. Because +SIGINT is tied to exit (see above) by default anyway, you should +remove your own "trap exit SIGINT" unless you specifically do not want +to be able to get to the debugger by ^C. + +If you want to define your own trap on SIGINT but still trap to the +debugger when it is running, use: + + if ![exp_debug] {trap mystuff SIGINT} + +Alternatively, you can trap to the debugger using some other signal. + +The ONEXIT trap is no longer available. Instead, say "exit -onexit ..." + +Traps are now deleted by using the empty ({}) handler. The current +handler is returned if no action is supplied. With no arguments, trap +returns the signal number of the trap command currently being executed. + +-- The wait command now returns a four element list if a valid child +was waited on. +Element 1: pid +Element 2: spawn id +Element 3: 0 (or -1 if there was an OS error) +Element 4: status (or errno if element 3 == -1) + +-- expect and interact notes: + +The timeout and eof patterns were initially named "-timeout" and +"-eof" but have been renamed "timeout" and "eof" to match those of +expect. The ability to define default timeout/eof actions has been +removed. (You can do this more easily by grouping spawn ids.) + +expect and interact now support a "null" keyword to match an ASCII 0. +send supports -null and -break keywords. + +Since a large number of special keywords have been added to interact, +a new keyword "-ex" for "exact" was added descriptive of its default +treatment of patterns. This protects the next token from being +misinterpreted as a keyword. The expect command provides "-gl" for +"glob" for analogous reasons. + +Any string starting with "-" should be protected by the "-ex" or "-gl" +flag, even those that are not keywords currently. (All strings +starting with "-" are reserved for future options.) + +String start/end indices are no longer written to expect_out and +interact_out unless the -indices flag is given. + +expect_out(spawn_id) is set to the spawn id associated with the spawn +id that produced the last output in an expect command. For example, +you can use this to delete files that have closed, by removing this +element from an indirect spawn ids spec. The same effect is +reproducable with interact (and interact_out(spawn_id)) but for +efficiency reasons, it requires the -iwrite flag before each pattern. + +Expect's -i and interact's -i, -u, -input, and -output flags can now +describe a list of spawn ids. So you can say things like: + + interact -input "$id1 $id2 $id3" .... -output "$id1 $id2" ... + +In this case, id1, 2, 3 would be sent to id1, and 2. + +The spawn id may be given as a global variable name (called an +"indirect spawn id specification"), in which case, the variable +contains the list of spawn ids. Whenever the variable is changed, the +new list of spawn ids is automatically used. This is particularly +useful with any long running expect command such as expect_before, +expect_after, expect_background, and interact. + +The -update flag was removed. Use indirect spawn ids (see previous +paragraph). + +-- interact notes: + +Interact now support -input and -output flags that provide very +flexible means of moving data from/to multiple spawn ids in complex +ways (but very quickly). It is possible to write most expect loops +using a simple interact statement. For instance, the three way +interaction inside kibitz (between two users and a process) is written +this way: + + interact { + -output $shell + -input $userin eof { . . . } -output $shell + -input $shell -output "$user_spawn_id $userout" + } + +-- send command notes: + +It is possible to send a break by using the "-break" flag. + +Any string starting with "-" should be protected by preceding it with +the "--" flag, even those that are not keywords currently. (All +strings starting "-" are reserved for future options.) + +-- The spawn command now takes an "-open" flag which in turns takes a +Tcl file as an argument. This lets you treat raw devices, files, and +pipelines as spawned processes without using a pty. + +This was actually in Expect 4, but I forgot to document it. Oops! + +-- The old "debug" command (which describes what Expect is doing +internally) was renamed "exp_internal". "debug" (and "exp_debug") now +invoke the interactive debugger. + +-- The new command "stty" now takes over the job of "system stty". It +works much better, allowing POSIX-style redirection to affect other +ttys. It otherwise takes arguments as "system stty" did. + +-- The "-tcl" option to "return" has gone away. (This was dangerous +to anyone that actually happened to return the value "-tcl".) +Instead, use inter_return. + +-- Added exp_timestamp command to produce very fast timestamps. + +-- Added exp_pid command to return pid of given spawn id. + +-- The close command now takes an argument of "-onexec" with a following +0 or non-zero value. For example, the follow command stops the +current spawn id from being closed when another process is exec'd or +spawn'd. + + close -onexec 0 + +While "-onexec 1" returns it to the default condition where it will be +closed upon exec or spawn. + +-- log_user now returns previous value. It is acceptable to call now, +without arguments just to get the value. + +-- The following forms are deprecated. They will be allowed +indefinitely but not advertised or supported if they break. + + -eof, -timeout in interact (reason: didn't match expect. + Instead, use eof or timeout.) + + -- in expect or interact (reason: no easier to read. + Instead, use -gl in expect or -ex in interact.) + + continue -expect (reason: when mixing in extensions, you have + to use exp_continue, so -expect becomes irrelevant. + Instead, use exp_continue.) + + getpid (reason: Tcl now supplies same functionality as "pid". + Instead, use pid.) + + expect_version and expect_library (reason: the name implies + they have something to do with the expect command, + which they doesn't. + Instead, use exp_version and exp_library.) + + -timestamp for obtaining tm and ctime in expect and interact + (reason: separate command now exists for this purpose. + Instead, use exp_timestamp.) + + system stty (reason: bad interaction with redirection. + Instead, use stty.) + +-- New examples have been added: + +"dislocate" lets you disconnect and reconnect to processes. + +"tkpasswd" illustrates passwd embedded in a GUI. + +They may not be overwhelmingly useful, but run them once to see what +they do. If you ever need to do anything similar, you can look back +at them. + +"tknewsbiff" pops up a window or plays a audio clip when you have +unread news. + +-- Changes to the Expect libraries: + +The expect-tcl library (libexpectcl.a) has been integrated with the +expect library (libexpect.a). So references to libexpectcl.a should +be removed. + +The Expect C library now supports buffering, multiplexing, null +matching, full buffer matching. Basically, all of the features in +Expect are now in the library. + +Buffering and multiplexing has caused the biggest change to the +library. Previously, exp_match contained the entire buffer that +matched. Now exp_match just points to where in the buffer the match +started. exp_buffer points to the beginning of the buffer. +Previously, the previous buffer was thrown away at the beginning of +each expect function call. Now, previously unmatched characters are +eligible for matching. + +To match on different file descriptors, exp_match, exp_match_end, +exp_buffer_end must be restored to their previous values. Initially, +they should be zero. + +The meaning of timeout == 0 in the Expect library has been changed. +See the man page for more info. + +====================================================================== +====================================================================== +This file describes the changes from Expect 3 to Expect 4. + +The improvements that people will find most interesting are: + +1) Expect version 4 is designed to work with Tcl 6.7 and Tk 3.2. + (Earlier versions of Expect will not work with Tcl 6.7) + Expect can now be layered in with any Tcl program. + Note that in Tk, Expect's send command is called "exp_send". + (It used to be called "send_spawn" but this bit the dust.) +2) A debugger is provided. +3) The interact command has been totally rewritten and supports regular + expressions, timeout/eof patterns, and a number of other new things. +4) The default behavior of ^C (SIGINT) is exit whether or not you are in + a read. +5) Expect uses "sane" terminal parameters by default, allowing scripts + to work the same whether inside emacs shell mode or not. (See man + page on "spawn" for more info.) +6) All the hard parts of the installation process are automated. This + was done primarily by Rob Savoye at Cygnus. Thank you, Rob! +7) It is now possible to buy a support contract for Expect from Cygnus. + +The changes that people will find most annoying are: + +1) send now only sends a single string. (It used to send any number of + strings with spaces jammed in between.) +2) getpid was renamed pid. +3) interact's -flush was renamed -nobuffer (much more descriptive). +4) interact now runs all actions in raw mode unless the flag -reset + is used. -f and -F are ignored. send automatically understands + how to do the right thing. The most likely thing to watch out for + are actions like "exec kill -STOP 0" which almost certainly need + the -reset flag. +5) argv0 is initialized to script name. argv no longer contains it. + argc is initialized [llength $argv]. This follows new Tcl style. + +All differences are described in the man page. Some of the less +significant differences are described in the HISTORY file. The +debugger is described in a separate document (see the README). + +This version also introduces one incompatibility that may require +changes to scripts. While this may initially annoy you, the final +result will simplify the process of writing scripts. Namely: + +In version 3, the expect command accepted lists of glob-style patterns +such as: + + expect "a\ b c" action + +where "a b" or "c" would cause action to be executed. The problem +with this is that the pattern list is hard to write and hard to read. +Patterns with control-characters, backslashes and dollar signs were +very difficult to deal with. + +Regular-expression patterns provide a much simpler solution. Via the +alternation feature (using a "|") the above pattern can be written as: + + expect -re "a b|c" action + +I was concerned about people having a significant investment in code +that depended on the old syntax but responders to a comp.lang.tcl poll +about such a change in pattern handling were 100% in favor of it. (I +even proposed hooks for backward compatibility, but there was no +interest in it.) + +Fortunately, most simple things will work as before including: + + expect foobar + expect {foobar} + expect "foobar" + expect "foo\ bar" + +However, some things won't work as before. For example, the following +will behave differently - now the braces will be considered as part of +the pattern. + + expect "{foo bar}" + +Here are examples of patterns in my own code that I had to change: + + was changed to + Version 3 pattern list Version 4 pattern + + {Whois:\ } "Whois: " + {No\ match} "No match" + {250*ftp>* 200*ftp>*} -re "2(5|0)0.*ftp>.*" + {{Press Return to continue*}} "Press Return to continue*" + {*\r\n*\\\\\r\n} "\r\n*\\\r\n" + + + +Future Change Alert + +John Ousterhout has pre-announced a future change in Tcl that may +affect you. In particular, backslash sequences other than those +explicitly listed in the Tcl documentation will be handled as if the +backslash was not present. + +The likely place this arises is when quoting characters that are +special to the pattern matcher but not to Tcl. + +For example in Tcl 6.7, the following command matches a period. + + expect -re "\." + +In Tcl 7.0, it will match any character, because Tcl will throw away +the backslash. If you want to match a period, you will have to say: + + expect -re "\\." +or + expect -re {\.} + +The following command will find occurrences of this. (It may find +other things, but it will at least find the problem cases.) + + egrep '(\\$)|(\\[^][bfnrtv\0-9{}$ ;"])' *.exp + +====================================================================== +====================================================================== +This section describes the changes from Expect 2 to Expect 3. + +If you used to use Expect version 2 (any version written before +September '91) you will find that the current version of Expect (3) +introduced minor but significant incompatibilities. + +The HISTORY file describes these briefly. They are described at +length in the man page. + +I'm sorry if you feel annoyed at the incompatibilities, but Expect has +been out for a year and a half, Tcl even longer. Both Tcl and Expect +are using this as a last chance to make significant changes, so that +we will not disturb even more users in the future. + +There is no automated conversion procedure (although see note below) +for Expect or even raw Tcl. For now, I suggest that you not bother +fixing things that already work - just keep the old Expect around. +The binary isn't very big after all. If you do write a translation +script, let me know. Thanks. + +Of course, I felt obligated to convert the examples distributed with +expect. I did this by hand while writing the new version itself, +partly as an aid but mostly to test lots of variations. In 90% of the +scripts, all I had to do was change: + +(changes due to Tcl) + 'index' to 'lindex' + 'range' to 'lrange' + 'length' to 'llength' + 'print' to 'send_user' or 'puts' depending on how you use it + 'function .... c' with '[join [function [split string ""]] ""]' +(changes due to Expect) + 'expect_match' to 'expect_out(buffer)' + 'set match_max' to 'match_max' (perhaps with -d flag) + '*' to '-re .+' + +If anyone wants to write a script to do this, note the pitfalls: + +1) functions and variables do not share the same namespace, so it is a +inappropriate to just globally rename things. + +A number of optimizations can be made: + +1) If you are doing multiple split/joins, you should probably cache the +split string. + +2) Virtually all uses of scan are unnecessary now, due to exec's automatic +stripping of terminating newlines, and expect's support of regexps. + +3) String manipulation can be reduced or avoided entirely if you use +expect -re. + +4) exec is no longer necessary to retrieve environment variables, since +they can now be retrieved from $env. + +5) If you have been really careful about testing for timeout and eof, +you can dramatically reduce the size of your scripts by using +expect_before and expect_after. This is more efficient, as well, +since those actions are only parsed once. + @@ -0,0 +1,350 @@ +NOTE: ALPHA AND BETA RELEASES OF TCL/TK ARE NOT SUPPORTED! + +-------------------- +Introduction +-------------------- + +This is the README file for Expect, a program that performs programmed +dialogue with other interactive programs. It is briefly described by +its man page, expect(1). This directory contains the source and man +page for Expect. + +This README file covers Expect 5.38 and up. These versions of Expect +work with Tcl 8.2 and up and Tk 8.2 and up. Significant changes and +other news can be found in the NEWS file. + +The Expect home page is: http://expect.nist.gov +The Expect FAQ is: http://expect.nist.gov/FAQ.html + +-------------------- +Getting Started - The Preferable Way +-------------------- + +A book on Expect is available from O'Reilly with the title "Exploring +Expect: A Tcl-Based Toolkit for Automating Interactive Applications", +ISBN 1-56592-090-2. + +The book is filled with detailed examples and explanations, and is a +comprehensive tutorial to Expect. The book also includes a tutorial +on Tcl written specifically for Expect users (so you don't have to +read the Expect papers or the man pages). Exploring Expect is 602 +pages. + +-------------------- +Getting Started - The Hacker Way +-------------------- + +While the book is the best way to learn about Expect, it is not +absolutely necessary. There are man pages after all and there are +numerous articles and papers on Expect. All of my own papers are in +the public domain and can be received free. If you are a hacker on a +tight budget, this may appeal to you. Nonetheless, I think you will +find the book pays for itself very quickly. It is much more readable +than the man pages, it includes well-written and explained examples, +and it describes everything in the papers as a coherent whole. The +concepts in the papers actually only make up a small fraction of the +book. + +The 1990 USENIX paper (see "Readings" below) is probably the best one +for understanding Expect conceptually. The 1991 Computing Systems and +the LISA IV papers provide a nice mix of examples. The only downside +is, the examples in these papers don't actually work anymore - some +aspects (e.g., syntax) of both Expect and Tcl have changed. The +papers still make interesting reading - just don't study the examples +too closely! Fortunately, most of the examples from the papers also +accompany this distribution - and all of these are up to date. + +For all the details, read the man page. It is long but you can get +started just by skimming the sections on the following commands: + + spawn (starts a process) + send (sends to a process) + expect (waits for output from a process) + interact (lets you interact with a process) + +To print out the Expect man page, invoke your local troff using the +-man macros, such as either of: + + ptroff -man expect.man + ditroff -man expect.man + +If Expect is installed, you can read the man pages using the "usual" +man commands, such as "man expect". If not installed, view the man +page on your screen by saying something like: + + nroff -man expect.man | more + +Expect uses Tcl as the underlying language for expressing things such +as procedures, loops, file I/O, and arithmetic expressions. For many +simple scripts, it is not necessary to learn about Tcl. Just by +studying the examples, you will learn enough Tcl to get by. But if +you would like to learn more about Tcl or use it in your own +applications, read the Tcl README file which provides pointers to the +extensive Tcl documentation. Or read Exploring Expect. Chapter 2 of +Exploring Expect is a Tcl tutorial specifically designed for Expect +users. + +An interactive debugger is bundled with Expect. The debugger has its +own documentation that comes separately. It is listed in the Readings +below. Again, it is slightly out of date. An up-to-date description +of the debugger appears in Chapter 18 of Exploring Expect. This +chapter also contains additional advice and tips for debugging. + +You may get the feeling that the Expect documentation is somewhat +scattered and disorganized. This was true prior to publication of +Exploring Expect. The book contains everything you need to know, all +up-to-date, and with examples of every concept. (The book contains no +references to any of the Expect papers because none are necessary.) + +---------------------- +Examples +---------------------- + +This distribution contains many example scripts. (All of the +substantive examples in the book are included.) They can be found in +the example directory of this distribution. The README file in that +directory briefly describes all of the example scripts. Many of the +more sophisticated examples have man pages of their own. + +Other interesting scripts are available separately in the directory +http://expect.nist.gov/scripts/ (ftpable as +ftp://ftp.nist.gov/mel/div826/subject/expect/scripts). (See below for +how to retrieve these.) You are welcome to send me scripts to add to +this directory. A number of Expect scripts are also available in the +Tcl archive, available at ftp://ftp.neosoft.com/pub/tcl. + +-------------------- +Readings on Expect +-------------------- + +The implementation, philosophy, and design are discussed in "expect: +Curing Those Uncontrollable Fits of Interaction", Proceedings of the +Summer 1990 USENIX Conference, Anaheim, CA, June 11-15, 1990. + +Examples and discussion, specifically aimed at system administrators, +are in "Using expect to Automate System Administration Tasks", +Proceedings of the 1990 USENIX Large Systems Administration Conference +(LISA) IV, Colorado Springs, CO, October 17-19, 1990. + +A comprehensive paper of example scripts is "expect: Scripts for +Controlling Interactive Programs", Computing Systems, Vol. 4, No. 2, +University of California Press Journals, 1991. + +Regression and conformance testing is discussed in "Regression Testing +and Conformance Testing Interactive Programs", Proceedings of the +Summer 1992 USENIX Conference, San Antonio, TX, June 8-12, 1992. + +An explanation of some of the more interesting source code to an early +version of Expect is in Chapter 36 ("Expect") of "Obfuscated C and +Other Mysteries", John Wiley & Sons, ISBN 0-471-57805-3, January 1993. + +A paper on connecting multiple interactive programs together using +Expect is "Kibitz - Connecting Multiple Interactive Programs +Together", Software - Practice & Experience, Vol. 23, No. 5, May 1993. + +The debugger is discussed in "A Debugger for Tcl Applications", +Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA, June 10-11, +1993. + +Using Expect with Tk is described in the paper "X Wrappers for +Non-Graphic Interactive Programs", Proceedings of Xhibition '94, San +Jose, CA, June 20-24, 1994. + +Simple techniques to allow secure handling of passwords in background +processes are covered in "Handling Passwords with Security and +Reliability in Background Processes", Proceedings of the 1994 USENIX +LISA VIII Conference, San Diego, CA, September 19-23, 1994. + +More publications can be found in the Expect home page (see elsewhere). + +-------------------- +How to Get the Latest Version of Expect or the Readings +-------------------- + +Expect may be ftp'd as mel/div826/subject/expect/expect.tar.gz from +expect.nist.gov. (Yes, the URL is much shorter: +http://expect.nist.gov/expect.tar.Z) Request email delivery by mailing +to "library@cme.nist.gov". The contents of the message should be (no +subject line) "send pub/expect/expect.tar.Z". + +Once you have retrieved the system, read the INSTALL file. The papers +mentioned above can be retrieved separately (from the same directories +listed above) as: + + doc/seminal.ps.Z (USENIX '90 - Intro and Implementation) + doc/sysadm.ps.Z (LISA '90 - System Administration) + doc/scripts.ps.Z (Comp. Systems '91 - Overview of Scripts) + doc/regress.ps.Z (USENIX '92 - Testing) + doc/kibitz.ps.Z (SP&E '93 - Automating Multiple + Interactive Programs Simultaneously) + doc/tcl-debug.ps.Z (Tcl/Tk '93 - Tcl/Tk Debugger) + doc/expectk.ps.Z (Xhibition '94 - Using Expect with Tk) + doc/bgpasswd.ps.Z (LISA '94 - Passwds in Background Procs) + doc/chargraph.ps.Z (SP&E '96 - Testing and Automation + of Character Graphic Applications) + +The book "Exploring Expect" is described in more detail earlier in +this file. + +The book "Obfuscated C and Other Mysteries" is not on-line but is +available in bookstores or directly from the publisher (Wiley). + +Overhead transparencies I've used at conferences are also available in +the same way as the papers themselves. The transparencies are sketchy +and not meant for personal education - however if you are familiar +with Expect and just want to give a short talk on it to your +colleagues, you may find the transparencies useful. They vary in +length from 15 to 20 minutes in length. These are: + + doc/seminal-talk.ps.Z (USENIX '90 - Intro and Implementation) + doc/sysadm-talk.ps.Z (LISA '90 - System Administration) + doc/regress-talk.ps.Z (USENIX '92 - Testing) + doc/tcl-debug-talk.ps.Z (Tcl/Tk '93 - Tcl/Tk Debugger) + doc/expectk-talk.ps.Z (Xhibition '94 - Expect + Tk = Expectk) + doc/bgpasswd-talk.ps.Z (LISA '94 - Passwords in the Background) + +All of the documents are compressed PostScript files and should be +uncompressed and sent to a PostScript printer. The documents are +intended for printing at 8.5"x11" and may fail on some ISO A4 +printers. According to Hans Mayer <Hans.Mayer@gmd.de>, you can make +them A4-able by searching for "FMVERSION" and changing the next line +from: + + 1 1 0 0 612 792 0 1 13 FMDOCUMENT +to: + 1 1 0 0 594 841 0 1 13 FMDOCUMENT + + +-------------------- +Using Expect with and without Tcl and/or Tk. +-------------------- + +The usual way of using Expect is as a standalone program with Tcl as +the control language. Since you may already have Tcl, it is available +separately. Tcl may be retrieved as tcl.tar.Z in the same way as +described above for Expect. When new releases of Tcl appear, I will +try to check them out for Expect as soon as possible. If you would +like to get the newest Tcl release without waiting, ftp it from +ftp.scriptics.com (directory pub/tcl). + +Expect may also be built using the Tk library, a Tcl interface to the +X Window System. Tk is available in the same way as Tcl. + +It is possible to embed the Expect/Tcl core and optionally Tk in your +own C programs. This is described in libexpect(3). + +Expect can also be used from a C or C++ program without Tcl. This is +described in libexpect(3). While I consider this library to be easy +to use, the standalone Expect program is much, much easier to use than +working with the C compiler and its usual edit, compile, debug cycle. +Unlike typical programming, most of the debugging isn't getting the C +compiler to accept your programs - rather, it is getting the dialogue +correct. Also, translating scripts from Expect to C is usually not +necessary. For example, the speed of interactive dialogues is +virtually never an issue. So please try 'expect' first. It is a more +appropriate tool than the library for most people. + +-------------------- +Systems Supported +-------------------- + +I do not know of any UNIX systems on which Expect will not run. +Systems which do not support select or poll can use Expect, but +without the ability to run multiple processes simultaneously. I am +willing to work with you to complete a port. + +Before sending me changes, please download or verify that you have the +latest version of Expect (see above). Then send me a "diff -c" along +with a suitable English explanation. If your diff involves something +specific to a machine, give me diffs for configure.in as well or give +me a hint about when the diffs should be done so I can write the +configure support myself. Also please include the version of the OS +and whether it is beta, current, recent, or totally out-of-date and +unsupported. + +-------------------- +Installing Expect +-------------------- + +Expect comes with a configure script that provides for an automated +installation. I believe you will find that Expect is very easy to +install. (Tcl and Tk, too.) + +For more information, read the INSTALL file. + +-------------------- +Support from Don Libes or NIST +-------------------- + +Although I can't promise anything in the way of support, I'd be +interested to hear about your experiences using it (good or bad). I'm +also interested in hearing bug reports and suggestions for improvement +even though I can't promise to implement them. + +If you send me a bug, fix, or question, include the version of Expect +(as reported by expect -d), version of Tcl, and name and version of +the OS that you are using. Before sending mail, it may be helpful to +verify that your problem still exists in the latest version. You can +check on the current release and whether it addresses your problems by +retrieving the latest HISTORY file (see "History" above). + + +Awards, love letters, and bug reports may be sent to: + +Don Libes +National Institute of Standards and Technology +Bldg 220, Rm A-127 +Gaithersburg, MD 20899 +(301) 975-3535 +libes@nist.gov + +I hereby place this software in the public domain. NIST and I would +appreciate credit if this program or parts of it are used. + +Design and implementation of this program was funded primarily by +myself. Funding contributors include the NIST Automated Manufacturing +Research Facility (funded by the Navy Manufacturing Technology +Program), the NIST Scientific and Technical Research Services, the +ARPA Persistent Object Bases project and the Computer-aided +Acquisition and the Logistic Support (CALS) program of the Office of +the Secretary of Defense. + +Especially signicant contributions were made by John Ousterhout, Henry +Spencer, and Rob Savoye. See the HISTORY file for others. + +-------------------- +Commercial Support, Classes +-------------------- + +Several companies provide commercial support for Expect. If your +company has a financial investment in Expect or you wish to be assured +of continuing support for Expect, you can buy a support contract this +way. These companies currently include: + +ActiveState +#200 - 580 Granville St +Vancouver, BC +V6C 1W6 Canada ++1 (604) 484-6800 +http://www.activestate.com/Company/contact.plex + +Cygnus Support +1937 Landings Drive +Mountain View, CA 94043 ++1 (415) 903-1400 +info@cygnus.com +http://www.cygnus.com + +Computerized Processes Unlimited (CPU) +4200 S. I-10 Service Rd., Suite 205 +Metairie, LA 70006 ++1 (504) 889-2784 +info@cpu.com +http://www.cpu.com +http://www.cpu.com/cpu/expect.htm (Expect class page) + +CPU provides Expect support and also Expect classes. Contact them for +more information. + +Neither NIST nor I have any financial relationship with these +companies. Please contact me to be added to this list. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..0b05739 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,9 @@ +# +# Include the TEA standard macro set +# + +builtin(include,tclconfig/tcl.m4) + +# +# Add here whatever m4 macros you want to define for your package +# diff --git a/configure b/configure new file mode 100755 index 0000000..5aabafb --- /dev/null +++ b/configure @@ -0,0 +1,17741 @@ +#! /bin/sh +# From configure.in Id: configure.in. +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for expect 5.45. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='expect' +PACKAGE_TARNAME='expect' +PACKAGE_VERSION='5.45' +PACKAGE_STRING='expect 5.45' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subdirs_all="$ac_subdirs_all testsuite" +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CYGPATH EXEEXT PKG_LIB_FILE PKG_STUB_LIB_FILE PKG_STUB_SOURCES PKG_STUB_OBJECTS PKG_TCL_SOURCES PKG_HEADERS PKG_INCLUDES PKG_LIBS PKG_CFLAGS TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC CLEANFILES TCL_LIBS TCL_DEFS TCL_EXTRA_CFLAGS TCL_LD_FLAGS TCL_SHLIB_LD_LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE RANLIB ac_ct_RANLIB EGREP MATH_LIBS TCL_INCLUDES TCL_TOP_DIR_NATIVE TCL_THREADS SHARED_BUILD AR CELIB_DIR CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS LD_LIBRARY_PATH_VAR CFLAGS_DEFAULT LDFLAGS_DEFAULT TCL_DBGX build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os subdirs EXP_BUILD_LIB_SPEC EXP_CC_SEARCH_FLAGS SETUID SETPGRP_VOID DEFAULT_STTY_ARGS TCL_DL_LIBS TCL_CC_SEARCH_FLAGS PKG_SOURCES PKG_OBJECTS MAKE_LIB MAKE_SHARED_LIB MAKE_STATIC_LIB MAKE_STUB_LIB RANLIB_STUB VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE TCLSH_PROG LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures expect 5.45 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of expect 5.45:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-threads build with threads + --enable-shared build and link with shared libraries (default: on) + --enable-64bit enable 64bit support (default: off) + --enable-64bit-vis enable 64bit Sparc VIS support (default: off) + --disable-rpath disable rpath support (default: on) + --enable-wince enable Win/CE support (where applicable) + --enable-symbols build with debugging symbols (default: off) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-tcl directory containing tcl configuration + (tclConfig.sh) + --with-tclinclude directory containing the public Tcl header files + --with-celib=DIR use Windows/CE support library from DIR + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +expect configure 5.45 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by expect $as_me 5.45, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # TEA extensions pass this us the version of TEA they think they + # are compatible with. + TEA_VERSION="3.9" + + echo "$as_me:$LINENO: checking for correct TEA configuration" >&5 +echo $ECHO_N "checking for correct TEA configuration... $ECHO_C" >&6 + if test x"${PACKAGE_NAME}" = x ; then + { { echo "$as_me:$LINENO: error: +The PACKAGE_NAME variable must be defined by your TEA configure.in" >&5 +echo "$as_me: error: +The PACKAGE_NAME variable must be defined by your TEA configure.in" >&2;} + { (exit 1); exit 1; }; } + fi + if test x"3.9" = x ; then + { { echo "$as_me:$LINENO: error: +TEA version not specified." >&5 +echo "$as_me: error: +TEA version not specified." >&2;} + { (exit 1); exit 1; }; } + elif test "3.9" != "${TEA_VERSION}" ; then + echo "$as_me:$LINENO: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5 +echo "${ECHO_T}warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6 + else + echo "$as_me:$LINENO: result: ok (TEA ${TEA_VERSION})" >&5 +echo "${ECHO_T}ok (TEA ${TEA_VERSION})" >&6 + fi + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*) + # Extract the first word of "cygpath", so it can be a program name with args. +set dummy cygpath; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CYGPATH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CYGPATH"; then + ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYGPATH="cygpath -w" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" +fi +fi +CYGPATH=$ac_cv_prog_CYGPATH +if test -n "$CYGPATH"; then + echo "$as_me:$LINENO: result: $CYGPATH" >&5 +echo "${ECHO_T}$CYGPATH" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + CYGPATH=echo + EXEEXT=".exe" + # TEA_PLATFORM is determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + { echo "$as_me:$LINENO: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 +echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} + + + + + # This package name must be replaced statically for AC_SUBST to work + + # Substitute STUB_LIB_FILE in case package creates a stub library too. + + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + + + + + + + + + +ac_aux_dir= +for ac_dir in tclconfig $srcdir/tclconfig; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in tclconfig $srcdir/tclconfig" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in tclconfig $srcdir/tclconfig" >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + + +#-------------------------------------------------------------------- +# Configure script for package 'Expect'. +# TEA compliant. +#-------------------------------------------------------------------- + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + + + + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + with_tclconfig="${withval}" +fi; + echo "$as_me:$LINENO: checking for Tcl configuration" >&5 +echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6 + if test "${ac_cv_c_tclconfig+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 +echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 +echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} + { (exit 1); exit 1; }; } + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + { { echo "$as_me:$LINENO: error: Can't find Tcl configuration definitions" >&5 +echo "$as_me: error: Can't find Tcl configuration definitions" >&2;} + { (exit 1); exit 1; }; } + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + fi + + + echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6 + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + echo "$as_me:$LINENO: result: loading" >&5 +echo "${ECHO_T}loading" >&6 + . "${TCL_BIN_DIR}/tclConfig.sh" + else + echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + case "`uname -s`" in + *CYGWIN_*) + echo "$as_me:$LINENO: checking for cygwin variant" >&5 +echo $ECHO_N "checking for cygwin variant... $ECHO_C" >&6 + case ${TCL_EXTRA_CFLAGS} in + *-mwin32*|*-mno-cygwin*) + TEA_PLATFORM="windows" + CFLAGS="$CFLAGS -mwin32" + echo "$as_me:$LINENO: result: win32" >&5 +echo "${ECHO_T}win32" >&6 + ;; + *) + TEA_PLATFORM="unix" + echo "$as_me:$LINENO: result: unix" >&5 +echo "${ECHO_T}unix" >&6 + ;; + esac + EXEEXT=".exe" + ;; + *) + ;; + esac + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + +cat >>confdefs.h <<_ACEOF +#define BUILD_${PACKAGE_NAME} +_ACEOF + + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + + + + + + + + +# expectk has been removed from the distribution as Tcl has supported +# dynamic extensions everywhere for a while. We still allow 'expect' +# to be built for the die-hard users, but expectk is just wish with +# package require Expect +if test "${with_tk+set}" = set ; then + { echo "$as_me:$LINENO: WARNING: With Tk request ignored - use package require Tk & Expect" >&5 +echo "$as_me: WARNING: With Tk request ignored - use package require Tk & Expect" >&2;} +fi + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + + + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + { echo "$as_me:$LINENO: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 +echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} + prefix=${TCL_PREFIX} + else + { echo "$as_me:$LINENO: --prefix defaulting to /usr/local" >&5 +echo "$as_me: --prefix defaulting to /usr/local" >&6;} + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + { echo "$as_me:$LINENO: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 +echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} + exec_prefix=${TCL_EXEC_PREFIX} + else + { echo "$as_me:$LINENO: --exec-prefix defaulting to ${prefix}" >&5 +echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} + exec_prefix=$prefix + fi + fi + + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create +# the basic setup necessary to compile executables. +#----------------------------------------------------------------------- + + + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + # If the user did not set CFLAGS, set it now to keep + # the AC_PROG_CC macro from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + + + + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5 +echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6 +if test "${tcl_cv_cc_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_pipe=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_pipe=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_pipe" >&5 +echo "${ECHO_T}$tcl_cv_cc_pipe" >&6 + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + if test "${TEA_PLATFORM}" = "unix" ; then + + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking for sin" >&5 +echo $ECHO_N "checking for sin... $ECHO_C" >&6 +if test "${ac_cv_func_sin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define sin to an innocuous variant, in case <limits.h> declares sin. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define sin innocuous_sin + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char sin (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef sin + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sin (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sin) || defined (__stub___sin) +choke me +#else +char (*f) () = sin; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != sin; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_sin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_sin=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5 +echo "${ECHO_T}$ac_cv_func_sin" >&6 +if test $ac_cv_func_sin = yes; then + MATH_LIBS="" +else + MATH_LIBS="-lm" +fi + + echo "$as_me:$LINENO: checking for main in -lieee" >&5 +echo $ECHO_N "checking for main in -lieee... $ECHO_C" >&6 +if test "${ac_cv_lib_ieee_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lieee $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ieee_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ieee_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ieee_main" >&5 +echo "${ECHO_T}$ac_cv_lib_ieee_main" >&6 +if test $ac_cv_lib_ieee_main = yes; then + MATH_LIBS="-lieee $MATH_LIBS" +fi + + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking for main in -linet" >&5 +echo $ECHO_N "checking for main in -linet... $ECHO_C" >&6 +if test "${ac_cv_lib_inet_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_inet_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_inet_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_inet_main" >&5 +echo "${ECHO_T}$ac_cv_lib_inet_main" >&6 +if test $ac_cv_lib_inet_main = yes; then + LIBS="$LIBS -linet" +fi + + if test "${ac_cv_header_net_errno_h+set}" = set; then + echo "$as_me:$LINENO: checking for net/errno.h" >&5 +echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_net_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking net/errno.h usability" >&5 +echo $ECHO_N "checking net/errno.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <net/errno.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking net/errno.h presence" >&5 +echo $ECHO_N "checking net/errno.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <net/errno.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: net/errno.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: net/errno.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: net/errno.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: net/errno.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: net/errno.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: net/errno.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: net/errno.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for net/errno.h" >&5 +echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_net_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_net_errno_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6 + +fi +if test $ac_cv_header_net_errno_h = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NET_ERRNO_H 1 +_ACEOF + +fi + + + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case <limits.h> declares connect. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 +if test $ac_cv_func_connect = yes; then + tcl_checkSocket=0 +else + tcl_checkSocket=1 +fi + + if test "$tcl_checkSocket" = 1; then + echo "$as_me:$LINENO: checking for setsockopt" >&5 +echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6 +if test "${ac_cv_func_setsockopt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define setsockopt to an innocuous variant, in case <limits.h> declares setsockopt. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define setsockopt innocuous_setsockopt + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char setsockopt (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef setsockopt + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setsockopt (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setsockopt) || defined (__stub___setsockopt) +choke me +#else +char (*f) () = setsockopt; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != setsockopt; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_setsockopt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_setsockopt=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5 +echo "${ECHO_T}$ac_cv_func_setsockopt" >&6 +if test $ac_cv_func_setsockopt = yes; then + : +else + echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5 +echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_setsockopt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setsockopt (); +int +main () +{ +setsockopt (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_setsockopt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_setsockopt=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6 +if test $ac_cv_lib_socket_setsockopt = yes; then + LIBS="$LIBS -lsocket" +else + tcl_checkBoth=1 +fi + +fi + + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + echo "$as_me:$LINENO: checking for accept" >&5 +echo $ECHO_N "checking for accept... $ECHO_C" >&6 +if test "${ac_cv_func_accept+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define accept to an innocuous variant, in case <limits.h> declares accept. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define accept innocuous_accept + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char accept (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef accept + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char accept (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_accept) || defined (__stub___accept) +choke me +#else +char (*f) () = accept; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != accept; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_accept=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_accept=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_accept" >&5 +echo "${ECHO_T}$ac_cv_func_accept" >&6 +if test $ac_cv_func_accept = yes; then + tcl_checkNsl=0 +else + LIBS=$tk_oldLibs +fi + + fi + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 +if test $ac_cv_func_gethostbyname = yes; then + : +else + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + LIBS="$LIBS -lnsl" +fi + +fi + + + # TEA specific: Don't perform the eval of the libraries here because + # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + + + + + echo "$as_me:$LINENO: checking dirent.h" >&5 +echo $ECHO_N "checking dirent.h... $ECHO_C" >&6 +if test "${tcl_cv_dirent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ + +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_dirent_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_dirent_h=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_dirent_h" >&5 +echo "${ECHO_T}$tcl_cv_dirent_h" >&6 + + if test $tcl_cv_dirent_h = no; then + +cat >>confdefs.h <<\_ACEOF +#define NO_DIRENT_H 1 +_ACEOF + + fi + + # TEA specific: + if test "${ac_cv_header_errno_h+set}" = set; then + echo "$as_me:$LINENO: checking for errno.h" >&5 +echo $ECHO_N "checking for errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_errno_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking errno.h usability" >&5 +echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <errno.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking errno.h presence" >&5 +echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <errno.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for errno.h" >&5 +echo $ECHO_N "checking for errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_errno_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_errno_h" >&6 + +fi +if test $ac_cv_header_errno_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_ERRNO_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_float_h+set}" = set; then + echo "$as_me:$LINENO: checking for float.h" >&5 +echo $ECHO_N "checking for float.h... $ECHO_C" >&6 +if test "${ac_cv_header_float_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 +echo "${ECHO_T}$ac_cv_header_float_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking float.h usability" >&5 +echo $ECHO_N "checking float.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <float.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking float.h presence" >&5 +echo $ECHO_N "checking float.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <float.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: float.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for float.h" >&5 +echo $ECHO_N "checking for float.h... $ECHO_C" >&6 +if test "${ac_cv_header_float_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_float_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 +echo "${ECHO_T}$ac_cv_header_float_h" >&6 + +fi +if test $ac_cv_header_float_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_FLOAT_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_values_h+set}" = set; then + echo "$as_me:$LINENO: checking for values.h" >&5 +echo $ECHO_N "checking for values.h... $ECHO_C" >&6 +if test "${ac_cv_header_values_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 +echo "${ECHO_T}$ac_cv_header_values_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking values.h usability" >&5 +echo $ECHO_N "checking values.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <values.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking values.h presence" >&5 +echo $ECHO_N "checking values.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <values.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: values.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: values.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: values.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: values.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: values.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: values.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: values.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for values.h" >&5 +echo $ECHO_N "checking for values.h... $ECHO_C" >&6 +if test "${ac_cv_header_values_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_values_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 +echo "${ECHO_T}$ac_cv_header_values_h" >&6 + +fi +if test $ac_cv_header_values_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_VALUES_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_limits_h+set}" = set; then + echo "$as_me:$LINENO: checking for limits.h" >&5 +echo $ECHO_N "checking for limits.h... $ECHO_C" >&6 +if test "${ac_cv_header_limits_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 +echo "${ECHO_T}$ac_cv_header_limits_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking limits.h usability" >&5 +echo $ECHO_N "checking limits.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <limits.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking limits.h presence" >&5 +echo $ECHO_N "checking limits.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <limits.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for limits.h" >&5 +echo $ECHO_N "checking for limits.h... $ECHO_C" >&6 +if test "${ac_cv_header_limits_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_limits_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 +echo "${ECHO_T}$ac_cv_header_limits_h" >&6 + +fi +if test $ac_cv_header_limits_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIMITS_H 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define NO_LIMITS_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_stdlib_h+set}" = set; then + echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking stdlib.h usability" >&5 +echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <stdlib.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking stdlib.h presence" >&5 +echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_stdlib_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 + +fi +if test $ac_cv_header_stdlib_h = yes; then + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtol" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtoul" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtod" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + if test $tcl_ok = 0; then + +cat >>confdefs.h <<\_ACEOF +#define NO_STDLIB_H 1 +_ACEOF + + fi + if test "${ac_cv_header_string_h+set}" = set; then + echo "$as_me:$LINENO: checking for string.h" >&5 +echo $ECHO_N "checking for string.h... $ECHO_C" >&6 +if test "${ac_cv_header_string_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 +echo "${ECHO_T}$ac_cv_header_string_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking string.h usability" >&5 +echo $ECHO_N "checking string.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <string.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking string.h presence" >&5 +echo $ECHO_N "checking string.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for string.h" >&5 +echo $ECHO_N "checking for string.h... $ECHO_C" >&6 +if test "${ac_cv_header_string_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_string_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 +echo "${ECHO_T}$ac_cv_header_string_h" >&6 + +fi +if test $ac_cv_header_string_h = yes; then + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strstr" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strerror" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + +cat >>confdefs.h <<\_ACEOF +#define NO_STRING_H 1 +_ACEOF + + fi + + if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/wait.h" >&5 +echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/wait.h usability" >&5 +echo $ECHO_N "checking sys/wait.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/wait.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/wait.h presence" >&5 +echo $ECHO_N "checking sys/wait.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/wait.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/wait.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/wait.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/wait.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/wait.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/wait.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/wait.h" >&5 +echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_wait_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 + +fi +if test $ac_cv_header_sys_wait_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_SYS_WAIT_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo "$as_me:$LINENO: checking for dlfcn.h" >&5 +echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 +if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 +echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking dlfcn.h usability" >&5 +echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <dlfcn.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking dlfcn.h presence" >&5 +echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <dlfcn.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for dlfcn.h" >&5 +echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 +if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_dlfcn_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 +echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 + +fi +if test $ac_cv_header_dlfcn_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_DLFCN_H 1 +_ACEOF + +fi + + + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + +for ac_header in sys/param.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + # Let the user call this, because if it triggers, they will + # need a compat/strtod.c that is correct. Users can also + # use Tcl_GetDouble(FromObj) instead. + #TEA_BUGGY_STRTOD + fi + + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + +#TEA_PUBLIC_TCL_HEADERS + + echo "$as_me:$LINENO: checking for Tcl public headers" >&5 +echo $ECHO_N "checking for Tcl public headers... $ECHO_C" >&6 + + +# Check whether --with-tclinclude or --without-tclinclude was given. +if test "${with_tclinclude+set}" = set; then + withval="$with_tclinclude" + with_tclinclude=${withval} +fi; + + if test "${ac_cv_c_tclh+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + { { echo "$as_me:$LINENO: error: ${with_tclinclude} directory does not contain tcl.h" >&5 +echo "$as_me: error: ${with_tclinclude} directory does not contain tcl.h" >&2;} + { (exit 1); exit 1; }; } + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + +fi + + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + { { echo "$as_me:$LINENO: error: tcl.h not found. Please specify its location with --with-tclinclude" >&5 +echo "$as_me: error: tcl.h not found. Please specify its location with --with-tclinclude" >&2;} + { (exit 1); exit 1; }; } + else + echo "$as_me:$LINENO: result: ${ac_cv_c_tclh}" >&5 +echo "${ECHO_T}${ac_cv_c_tclh}" >&6 + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + + + + # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} + + echo "$as_me:$LINENO: checking for Tcl private include files" >&5 +echo $ECHO_N "checking for Tcl private include files... $ECHO_C" >&6 + + TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` + TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" + + # Check to see if tcl<Plat>Port.h isn't already with the public headers + # Don't look for tclInt.h because that resides with tcl.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tclh}/tclWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tclh}/tclUnixPort.h"; then + result="private headers found with public headers" + else + TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" + if test "${TEA_PLATFORM}" = "windows"; then + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" + else + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TCL_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -d "${TCL_BIN_DIR}/Headers" -a \ + -d "${TCL_BIN_DIR}/PrivateHeaders"; then + TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" + else + TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TCL_INCLUDES}" + else + if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then + { { echo "$as_me:$LINENO: error: Cannot find private header tclInt.h in ${TCL_SRC_DIR}" >&5 +echo "$as_me: error: Cannot find private header tclInt.h in ${TCL_SRC_DIR}" >&2;} + { (exit 1); exit 1; }; } + fi + result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" + fi + fi + + + + + echo "$as_me:$LINENO: result: ${result}" >&5 +echo "${ECHO_T}${result}" >&6 + + +#-------------------------------------------------------------------- +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + + + CLEANFILES="$CLEANFILES pkgIndex.tcl" + + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# So far only Tcl responds to this one. +# +# Hook for when threading is supported in Expect. The --enable-threads +# flag currently has no effect. +#------------------------------------------------------------------------ + + + # Check whether --enable-threads or --disable-threads was given. +if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval +else + tcl_ok=yes +fi; + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + +cat >>confdefs.h <<\_ACEOF +#define USE_THREAD_ALLOC 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + if test "`uname -s`" = "SunOS" ; then + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + fi + +cat >>confdefs.h <<\_ACEOF +#define _THREAD_SAFE 1 +_ACEOF + + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6 +if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + echo "$as_me:$LINENO: checking for __pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for __pthread_mutex_init in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread___pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char __pthread_mutex_init (); +int +main () +{ +__pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread___pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread___pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread___pthread_mutex_init" >&6 +if test $ac_cv_lib_pthread___pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6 +if test "${ac_cv_lib_pthreads_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthreads $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthreads_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthreads_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_mutex_init" >&6 +if test $ac_cv_lib_pthreads_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lc... $ECHO_C" >&6 +if test "${ac_cv_lib_c_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_c_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_c_pthread_mutex_init" >&6 +if test $ac_cv_lib_c_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc_r" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lc_r... $ECHO_C" >&6 +if test "${ac_cv_lib_c_r_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_r_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_c_r_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_c_r_pthread_mutex_init" >&6 +if test $ac_cv_lib_c_r_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + { echo "$as_me:$LINENO: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 +echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + echo "$as_me:$LINENO: checking for building with threads" >&5 +echo $ECHO_N "checking for building with threads... $ECHO_C" >&6 + if test "${TCL_THREADS}" = 1; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_THREADS 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes (default)" >&5 +echo "${ECHO_T}yes (default)" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + { echo "$as_me:$LINENO: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&5 +echo "$as_me: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&2;} + fi + ;; + *) + if test "${TCL_THREADS}" = "1"; then + { echo "$as_me:$LINENO: WARNING: + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core." >&5 +echo "$as_me: WARNING: + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core." >&2;} + fi + ;; + esac + + + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + + + echo "$as_me:$LINENO: checking how to build libraries" >&5 +echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6 + # Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval +else + tcl_ok=yes +fi; + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + echo "$as_me:$LINENO: result: shared" >&5 +echo "${ECHO_T}shared" >&6 + SHARED_BUILD=1 + else + echo "$as_me:$LINENO: result: static" >&5 +echo "${ECHO_T}static" >&6 + SHARED_BUILD=0 + +cat >>confdefs.h <<\_ACEOF +#define STATIC_BUILD 1 +_ACEOF + + fi + + + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + + + + + # Step 0.a: Enable 64 bit support? + + echo "$as_me:$LINENO: checking if 64bit support is requested" >&5 +echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6 + # Check whether --enable-64bit or --disable-64bit was given. +if test "${enable_64bit+set}" = set; then + enableval="$enable_64bit" + do64bit=$enableval +else + do64bit=no +fi; + echo "$as_me:$LINENO: result: $do64bit" >&5 +echo "${ECHO_T}$do64bit" >&6 + + # Step 0.b: Enable Solaris 64 bit VIS support? + + echo "$as_me:$LINENO: checking if 64bit Sparc VIS support is requested" >&5 +echo $ECHO_N "checking if 64bit Sparc VIS support is requested... $ECHO_C" >&6 + # Check whether --enable-64bit-vis or --disable-64bit-vis was given. +if test "${enable_64bit_vis+set}" = set; then + enableval="$enable_64bit_vis" + do64bitVIS=$enableval +else + do64bitVIS=no +fi; + echo "$as_me:$LINENO: result: $do64bitVIS" >&5 +echo "${ECHO_T}$do64bitVIS" >&6 + # Force 64bit on with VIS + if test "$do64bitVIS" = "yes"; then + do64bit=yes +fi + + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + echo "$as_me:$LINENO: checking if compiler supports visibility \"hidden\"" >&5 +echo $ECHO_N "checking if compiler supports visibility \"hidden\"... $ECHO_C" >&6 +if test "${tcl_cv_cc_visibility_hidden+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {} +int +main () +{ +f(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_visibility_hidden=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_visibility_hidden=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_visibility_hidden" >&5 +echo "${ECHO_T}$tcl_cv_cc_visibility_hidden" >&6 + if test $tcl_cv_cc_visibility_hidden = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE extern __attribute__((__visibility__("hidden"))) +_ACEOF + + +fi + + + # Step 0.d: Disable -rpath support? + + echo "$as_me:$LINENO: checking if rpath support is requested" >&5 +echo $ECHO_N "checking if rpath support is requested... $ECHO_C" >&6 + # Check whether --enable-rpath or --disable-rpath was given. +if test "${enable_rpath+set}" = set; then + enableval="$enable_rpath" + doRpath=$enableval +else + doRpath=yes +fi; + echo "$as_me:$LINENO: result: $doRpath" >&5 +echo "${ECHO_T}$doRpath" >&6 + + # TEA specific: Cross-compiling options for Windows/CE builds? + + if test "${TEA_PLATFORM}" = windows; then + + echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5 +echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6 + # Check whether --enable-wince or --disable-wince was given. +if test "${enable_wince+set}" = set; then + enableval="$enable_wince" + doWince=$enableval +else + doWince=no +fi; + echo "$as_me:$LINENO: result: $doWince" >&5 +echo "${ECHO_T}$doWince" >&6 + +fi + + + # Set the variable "system" to hold the name and version number + # for the system. + + + echo "$as_me:$LINENO: checking system version" >&5 +echo $ECHO_N "checking system version... $ECHO_C" >&6 +if test "${tcl_cv_sys_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5 +echo "$as_me: WARNING: can't find uname command" >&2;} + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + +fi +echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5 +echo "${ECHO_T}$tcl_cv_sys_version" >&6 + system=$tcl_cv_sys_version + + + # Require ranlib early so we can override it in special cases below. + + + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + CFLAGS_OPTIMIZE=-O + if test "$GCC" = yes; then + + # TEA specific: + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + +else + CFLAGS_WARNING="" +fi + + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + if test "x$SHLIB_VERSION" = x; then + SHLIB_VERSION="1.0" +fi + + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test ! -d "${PATH64}" ; then + { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 +echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} + { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5 +echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} + do64bit="no" + else + echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 +echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + { { echo "$as_me:$LINENO: error: Windows/CE and 64-bit builds incompatible" >&5 +echo "$as_me: error: Windows/CE and 64-bit builds incompatible" >&2;} + { (exit 1); exit 1; }; } + fi + if test "$GCC" = "yes" ; then + { { echo "$as_me:$LINENO: error: Windows/CE and GCC builds incompatible" >&5 +echo "$as_me: error: Windows/CE and GCC builds incompatible" >&2;} + { (exit 1); exit 1; }; } + fi + + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + +# Check whether --with-celib or --without-celib was given. +if test "${with_celib+set}" = set; then + withval="$with_celib" + with_celibconfig=${withval} +fi; + echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5 +echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6 + if test "${ac_cv_c_celibconfig+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + { { echo "$as_me:$LINENO: error: ${with_celibconfig} directory doesn't contain inc directory" >&5 +echo "$as_me: error: ${with_celibconfig} directory doesn't contain inc directory" >&2;} + { (exit 1); exit 1; }; } + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[0-9]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + +fi + + if test x"${ac_cv_c_celibconfig}" = x ; then + { { echo "$as_me:$LINENO: error: Cannot find celib support library directory" >&5 +echo "$as_me: error: Cannot find celib support library directory" >&2;} + { (exit 1); exit 1; }; } + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + echo "$as_me:$LINENO: result: found $CELIB_DIR" >&5 +echo "${ECHO_T}found $CELIB_DIR" >&6 + fi + fi + + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ + if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ + if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ + if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + { { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5 +echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;} + { (exit 1); exit 1; }; } + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + + vars="bufferoverflowU.lib" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower($0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + +cat >>confdefs.h <<_ACEOF +#define $i 1 +_ACEOF + + done + +cat >>confdefs.h <<_ACEOF +#define _WIN32_WCE $CEVERSION +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define UNDER_CE $CEVERSION +_ACEOF + + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + + else + RC="rc" + lflags="-nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + RC="windres" + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD="$CC -shared" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then + + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` + ;; + esac + echo "$as_me:$LINENO: result: Using $CC for compiling with threads" >&5 +echo "${ECHO_T}Using $CC for compiling with threads" >&6 + +fi + + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then + + if test "$GCC" = yes; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + +fi + + +fi + + + if test "`uname -m`" = ia64; then + + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + if test "$GCC" = yes; then + + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + +else + + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + +fi + + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +else + + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared -Wl,-bexpall' + +else + + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + +fi + + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + echo "$as_me:$LINENO: checking for inet_ntoa in -lbind" >&5 +echo $ECHO_N "checking for inet_ntoa in -lbind... $ECHO_C" >&6 +if test "${ac_cv_lib_bind_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbind $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char inet_ntoa (); +int +main () +{ +inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bind_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bind_inet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bind_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_bind_inet_ntoa" >&6 +if test $ac_cv_lib_bind_inet_ntoa = yes; then + LIBS="$LIBS -lbind -lsocket" +fi + + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + EXE_SUFFIX=".exe" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' + echo "$as_me:$LINENO: checking for inet_ntoa in -lnetwork" >&5 +echo $ECHO_N "checking for inet_ntoa in -lnetwork... $ECHO_C" >&6 +if test "${ac_cv_lib_network_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetwork $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char inet_ntoa (); +int +main () +{ +inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_network_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_network_inet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_network_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_network_inet_ntoa" >&6 +if test $ac_cv_lib_network_inet_ntoa = yes; then + LIBS="$LIBS -lnetwork" +fi + + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + +cat >>confdefs.h <<\_ACEOF +#define _XOPEN_SOURCE_EXTENDED 1 +_ACEOF + + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + if test "`uname -m`" = ia64; then + + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + +else + + SHLIB_SUFFIX=".sl" + +fi + + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = yes; then + + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + +fi + + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + +fi + + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = "yes"; then + + if test "$GCC" = yes; then + + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + ;; + esac + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + +fi + + +fi + ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + if test "$GCC" = yes; then + + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + +else + + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + +fi + + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + + # Check to enable 64-bit flags for compiler/linker + + if test "$do64bit" = yes; then + + if test "$GCC" = yes; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported by gcc" >&5 +echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} + +else + + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + +fi + + +fi + + ;; + Linux*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "`uname -m`" = "alpha"; then + CFLAGS="$CFLAGS -mieee" +fi + + if test $do64bit = yes; then + + echo "$as_me:$LINENO: checking if compiler accepts -m64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -m64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_m64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_m64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_m64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_m64" >&5 +echo "${ECHO_T}$tcl_cv_cc_m64" >&6 + if test $tcl_cv_cc_m64 = yes; then + + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + +fi + + +fi + + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + if test x"${USE_COMPAT}" != x; then + CFLAGS="$CFLAGS -fno-inline" +fi + + + ;; + GNU*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + SHLIB_LD='${CC} -shared' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + if test "`uname -m`" = "alpha"; then + CFLAGS="$CFLAGS -mieee" +fi + + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + ;; + OpenBSD-*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' + echo "$as_me:$LINENO: checking for ELF" >&5 +echo $ECHO_N "checking for ELF... $ECHO_C" >&6 +if test "${tcl_cv_ld_elf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#ifdef __ELF__ + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then + tcl_cv_ld_elf=yes +else + tcl_cv_ld_elf=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5 +echo "${ECHO_T}$tcl_cv_ld_elf" >&6 + if test $tcl_cv_ld_elf = yes; then + + LDFLAGS=-Wl,-export-dynamic + +else + LDFLAGS="" +fi + + if test "${TCL_THREADS}" = "1"; then + + # OpenBSD builds and links with -pthread, never -lpthread. + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + SHLIB_CFLAGS="$SHLIB_CFLAGS -pthread" + +fi + + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*|FreeBSD-[3-4].*) + # FreeBSD 3.* and greater have ELF. + # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "${TCL_THREADS}" = "1"; then + + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + + case $system in + FreeBSD-3.*) + # FreeBSD-3 doesn't handle version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + TCL_SHLIB_LD_EXTRAS="-soname \$@" + SHLIB_SUFFIX=".so" + LDFLAGS="" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + if test "${TCL_THREADS}" = "1"; then + + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" +fi + + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" + if test $do64bit = yes; then + + case `arch` in + ppc) + echo "$as_me:$LINENO: checking if compiler accepts -arch ppc64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -arch ppc64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_arch_ppc64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_arch_ppc64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_arch_ppc64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_ppc64" >&5 +echo "${ECHO_T}$tcl_cv_cc_arch_ppc64" >&6 + if test $tcl_cv_cc_arch_ppc64 = yes; then + + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + +fi +;; + i386) + echo "$as_me:$LINENO: checking if compiler accepts -arch x86_64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -arch x86_64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_arch_x86_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_arch_x86_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_arch_x86_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_x86_64" >&5 +echo "${ECHO_T}$tcl_cv_cc_arch_x86_64" >&6 + if test $tcl_cv_cc_arch_x86_64 = yes; then + + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + +fi +;; + *) + { echo "$as_me:$LINENO: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 +echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; + esac + +else + + # Check for combined 32-bit and 64-bit fat build + if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then + + fat_32_64=yes +fi + + +fi + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5 +echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_single_module+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_single_module=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_single_module=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5 +echo "${ECHO_T}$tcl_cv_ld_single_module" >&6 + if test $tcl_cv_ld_single_module = yes; then + + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + +fi + + # TEA specific: link shlib with current and compatiblity version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then + + LDFLAGS="$LDFLAGS -prebind" +fi + + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5 +echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_search_paths_first+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_search_paths_first=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_search_paths_first=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5 +echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6 + if test $tcl_cv_ld_search_paths_first = yes; then + + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + +fi + + if test "$tcl_cv_cc_visibility_hidden" != yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE __private_extern__ +_ACEOF + + tcl_cv_cc_visibility_hidden=yes + +fi + + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then + + if test "${TEA_WINDOWINGSYSTEM}" = x11; then + + echo "$as_me:$LINENO: checking for 64-bit X11" >&5 +echo $ECHO_N "checking for 64-bit X11... $ECHO_C" >&6 +if test "${tcl_cv_lib_x11_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_lib_x11_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_lib_x11_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_lib_x11_64" >&5 +echo "${ECHO_T}$tcl_cv_lib_x11_64" >&6 + +fi + + if test "${TEA_WINDOWINGSYSTEM}" = aqua; then + + echo "$as_me:$LINENO: checking for 64-bit Tk" >&5 +echo $ECHO_N "checking for 64-bit Tk... $ECHO_C" >&6 +if test "${tcl_cv_lib_tk_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <tk.h> +int +main () +{ +Tk_InitStubs(NULL, "", 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_lib_tk_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_lib_tk_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_lib_tk_64" >&5 +echo "${ECHO_T}$tcl_cv_lib_tk_64" >&6 + +fi + + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then + + { echo "$as_me:$LINENO: Removing 64-bit architectures from compiler & linker flags" >&5 +echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done +fi + + +fi + + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + +cat >>confdefs.h <<\_ACEOF +#define _OE_SOCKETS 1 +_ACEOF + + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + if test "$SHARED_BUILD" = 1; then + + SHLIB_LD='ld -shared -expect_unresolved "*"' + +else + + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + +fi + + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + if test "$GCC" = yes; then + CFLAGS="$CFLAGS -mieee" +else + + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" +fi + + # see pthread_intro(3) for pthread support on osf1, k.furukawa + if test "${TCL_THREADS}" = 1; then + + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + if test "$GCC" = yes; then + + LIBS="$LIBS -lpthread -lmach -lexc" + +else + + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + + +fi + + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + if test "$GCC" = yes; then + + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + +else + + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + +fi + + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[0-6]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then + + arch=`isainfo` + if test "$arch" = "sparcv9 sparc"; then + + if test "$GCC" = yes; then + + if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + +fi + + +else + + do64bit_ok=yes + if test "$do64bitVIS" = yes; then + + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + +else + + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + +fi + + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + +fi + + +else + if test "$arch" = "amd64 i386"; then + + if test "$GCC" = yes; then + + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; + esac + +else + + do64bit_ok=yes + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + +fi + + +else + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5 +echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} +fi + +fi + + +fi + + + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "$do64bit_ok" = yes; then + + if test "$arch" = "sparcv9 sparc"; then + + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + +else + if test "$arch" = "amd64 i386"; then + + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + +fi + +fi + + +fi + + +else + + case $system in + SunOS-5.[1-9][0-9]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +fi + + ;; + esac + + if test "$do64bit" = yes -a "$do64bit_ok" = no; then + + { echo "$as_me:$LINENO: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 +echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} + +fi + + + + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + if test "$GCC" = yes; then + + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*) ;; + IRIX*) ;; + NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac +fi + + + if test "$tcl_cv_cc_visibility_hidden" != yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE extern +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define NO_VIZ +_ACEOF + + +fi + + + if test "$SHARED_LIB_SUFFIX" = ""; then + + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' +fi + + if test "$UNSHARED_LIB_SUFFIX" = ""; then + + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' +fi + + + + + + + + + + + + + + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + + echo "$as_me:$LINENO: checking for required early compiler flags" >&5 +echo $ECHO_N "checking for required early compiler flags... $ECHO_C" >&6 + tcl_flags="" + + if test "${tcl_cv_flag__isoc99_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__isoc99_source=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _ISOC99_SOURCE 1 +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__isoc99_source=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__isoc99_source=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _ISOC99_SOURCE 1 +_ACEOF + + tcl_flags="$tcl_flags _ISOC99_SOURCE" + fi + + + if test "${tcl_cv_flag__largefile64_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile64_source=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGEFILE64_SOURCE 1 +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile64_source=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__largefile64_source=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _LARGEFILE64_SOURCE 1 +_ACEOF + + tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" + fi + + + if test "${tcl_cv_flag__largefile_source64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile_source64=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE64 1 +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile_source64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__largefile_source64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _LARGEFILE_SOURCE64 1 +_ACEOF + + tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" + fi + + if test "x${tcl_flags}" = "x" ; then + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + else + echo "$as_me:$LINENO: result: ${tcl_flags}" >&5 +echo "${ECHO_T}${tcl_flags}" >&6 + fi + + + echo "$as_me:$LINENO: checking for 64-bit integer type" >&5 +echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6 + if test "${tcl_cv_type_64bit+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +__int64 value = (__int64) 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_type_64bit=__int64 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_type_64bit="long long" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +switch (0) { + case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; + } + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_type_64bit=${tcl_type_64bit} +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "${tcl_cv_type_64bit}" = none ; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_WIDE_INT_IS_LONG 1 +_ACEOF + + echo "$as_me:$LINENO: result: using long" >&5 +echo "${ECHO_T}using long" >&6 + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + echo "$as_me:$LINENO: result: using Tcl header defaults" >&5 +echo "${ECHO_T}using Tcl header defaults" >&6 + else + +cat >>confdefs.h <<_ACEOF +#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} +_ACEOF + + echo "$as_me:$LINENO: result: ${tcl_cv_type_64bit}" >&5 +echo "${ECHO_T}${tcl_cv_type_64bit}" >&6 + + # Now check for auxiliary declarations + echo "$as_me:$LINENO: checking for struct dirent64" >&5 +echo $ECHO_N "checking for struct dirent64... $ECHO_C" >&6 +if test "${tcl_cv_struct_dirent64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/dirent.h> +int +main () +{ +struct dirent64 p; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_struct_dirent64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_struct_dirent64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_struct_dirent64" >&5 +echo "${ECHO_T}$tcl_cv_struct_dirent64" >&6 + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRUCT_DIRENT64 1 +_ACEOF + + fi + + echo "$as_me:$LINENO: checking for struct stat64" >&5 +echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6 +if test "${tcl_cv_struct_stat64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 p; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_struct_stat64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_struct_stat64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_struct_stat64" >&5 +echo "${ECHO_T}$tcl_cv_struct_stat64" >&6 + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRUCT_STAT64 1 +_ACEOF + + fi + + + +for ac_func in open64 lseek64 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + echo "$as_me:$LINENO: checking for off64_t" >&5 +echo $ECHO_N "checking for off64_t... $ECHO_C" >&6 + if test "${tcl_cv_type_off64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ +off64_t offset; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_type_off64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_type_off64_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TYPE_OFF64_T 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi + fi + + + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + + + + echo "$as_me:$LINENO: checking for build with symbols" >&5 +echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6 + # Check whether --enable-symbols or --disable-symbols was given. +if test "${enable_symbols+set}" = set; then + enableval="$enable_symbols" + tcl_ok=$enableval +else + tcl_ok=no +fi; + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE}" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + echo "$as_me:$LINENO: result: yes (standard debugging)" >&5 +echo "${ECHO_T}yes (standard debugging)" >&6 + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + + + + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_MEM_DEBUG 1 +_ACEOF + + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + echo "$as_me:$LINENO: result: enabled symbols mem debugging" >&5 +echo "${ECHO_T}enabled symbols mem debugging" >&6 + else + echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5 +echo "${ECHO_T}enabled $tcl_ok debugging" >&6 + fi + fi + + +#-------------------------------------------------------------------- +# Everyone should be linking against the Tcl stub library. If you +# can't for some reason, remove this definition. If you aren't using +# stubs, you also need to modify the SHLIB_LD_LIBS setting below to +# link against the non-stubbed Tcl library. +#-------------------------------------------------------------------- + +cat >>confdefs.h <<\_ACEOF +#define USE_TCL_STUBS 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define USE_TCL_STUBS 1 +_ACEOF + + +#------------------------------------------------------------------------- +# Check for system header files. +#------------------------------------------------------------------------- + +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/select.h" >&5 +echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/select.h usability" >&5 +echo $ECHO_N "checking sys/select.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/select.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/select.h presence" >&5 +echo $ECHO_N "checking sys/select.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/select.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/select.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/select.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/select.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/select.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/select.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/select.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/select.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/select.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/select.h" >&5 +echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_select_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 + +fi +if test $ac_cv_header_sys_select_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_sysmacros_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/sysmacros.h" >&5 +echo $ECHO_N "checking for sys/sysmacros.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_sysmacros_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_sysmacros_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_sysmacros_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/sysmacros.h usability" >&5 +echo $ECHO_N "checking sys/sysmacros.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/sysmacros.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/sysmacros.h presence" >&5 +echo $ECHO_N "checking sys/sysmacros.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/sysmacros.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysmacros.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/sysmacros.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/sysmacros.h" >&5 +echo $ECHO_N "checking for sys/sysmacros.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_sysmacros_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_sysmacros_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_sysmacros_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_sysmacros_h" >&6 + +fi +if test $ac_cv_header_sys_sysmacros_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYSMACROS_H 1 +_ACEOF + +fi + + + +# Oddly, some systems have stdarg but don't support prototypes +# Tcl avoids the whole issue by not using stdarg on UNIX at all! + + +if test "${ac_cv_header_varargs_h+set}" = set; then + echo "$as_me:$LINENO: checking for varargs.h" >&5 +echo $ECHO_N "checking for varargs.h... $ECHO_C" >&6 +if test "${ac_cv_header_varargs_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_varargs_h" >&5 +echo "${ECHO_T}$ac_cv_header_varargs_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking varargs.h usability" >&5 +echo $ECHO_N "checking varargs.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <varargs.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking varargs.h presence" >&5 +echo $ECHO_N "checking varargs.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <varargs.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: varargs.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: varargs.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: varargs.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: varargs.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: varargs.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: varargs.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: varargs.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: varargs.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: varargs.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: varargs.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: varargs.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for varargs.h" >&5 +echo $ECHO_N "checking for varargs.h... $ECHO_C" >&6 +if test "${ac_cv_header_varargs_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_varargs_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_varargs_h" >&5 +echo "${ECHO_T}$ac_cv_header_varargs_h" >&6 + +fi +if test $ac_cv_header_varargs_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_VARARGS_H 1 +_ACEOF + +fi + + + +# If no stropts.h, then the svr4 implementation is broken. +# At least it is on my Debian "potato" system. - Rob Savoye + +if test "${ac_cv_header_sys_stropts_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/stropts.h" >&5 +echo $ECHO_N "checking for sys/stropts.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_stropts_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_stropts_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_stropts_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/stropts.h usability" >&5 +echo $ECHO_N "checking sys/stropts.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/stropts.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/stropts.h presence" >&5 +echo $ECHO_N "checking sys/stropts.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stropts.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/stropts.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/stropts.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/stropts.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/stropts.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/stropts.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/stropts.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/stropts.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stropts.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/stropts.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/stropts.h" >&5 +echo $ECHO_N "checking for sys/stropts.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_stropts_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_stropts_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_stropts_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_stropts_h" >&6 + +fi +if test $ac_cv_header_sys_stropts_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STROPTS_H 1 +_ACEOF + +else + svr4_ptys_broken=1 +fi + + +if test "${ac_cv_header_sys_sysconfig_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/sysconfig.h" >&5 +echo $ECHO_N "checking for sys/sysconfig.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_sysconfig_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_sysconfig_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_sysconfig_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/sysconfig.h usability" >&5 +echo $ECHO_N "checking sys/sysconfig.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/sysconfig.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/sysconfig.h presence" >&5 +echo $ECHO_N "checking sys/sysconfig.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/sysconfig.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/sysconfig.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/sysconfig.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/sysconfig.h" >&5 +echo $ECHO_N "checking for sys/sysconfig.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_sysconfig_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_sysconfig_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_sysconfig_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_sysconfig_h" >&6 + +fi +if test $ac_cv_header_sys_sysconfig_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYSCONF_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_fcntl_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/fcntl.h" >&5 +echo $ECHO_N "checking for sys/fcntl.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_fcntl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_fcntl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_fcntl_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/fcntl.h usability" >&5 +echo $ECHO_N "checking sys/fcntl.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/fcntl.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/fcntl.h presence" >&5 +echo $ECHO_N "checking sys/fcntl.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/fcntl.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/fcntl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/fcntl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/fcntl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/fcntl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/fcntl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/fcntl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/fcntl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/fcntl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/fcntl.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/fcntl.h" >&5 +echo $ECHO_N "checking for sys/fcntl.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_fcntl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_fcntl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_fcntl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_fcntl_h" >&6 + +fi +if test $ac_cv_header_sys_fcntl_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_FCNTL_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_ptem_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/ptem.h" >&5 +echo $ECHO_N "checking for sys/ptem.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_ptem_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_ptem_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_ptem_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/ptem.h usability" >&5 +echo $ECHO_N "checking sys/ptem.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/ptem.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/ptem.h presence" >&5 +echo $ECHO_N "checking sys/ptem.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/ptem.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/ptem.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/ptem.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/ptem.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/ptem.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/ptem.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/ptem.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/ptem.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ptem.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/ptem.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/ptem.h" >&5 +echo $ECHO_N "checking for sys/ptem.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_ptem_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_ptem_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_ptem_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_ptem_h" >&6 + +fi +if test $ac_cv_header_sys_ptem_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_PTEM_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_strredir_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/strredir.h" >&5 +echo $ECHO_N "checking for sys/strredir.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_strredir_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_strredir_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_strredir_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/strredir.h usability" >&5 +echo $ECHO_N "checking sys/strredir.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/strredir.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/strredir.h presence" >&5 +echo $ECHO_N "checking sys/strredir.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/strredir.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/strredir.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/strredir.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/strredir.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/strredir.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/strredir.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/strredir.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/strredir.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strredir.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/strredir.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/strredir.h" >&5 +echo $ECHO_N "checking for sys/strredir.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_strredir_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_strredir_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_strredir_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_strredir_h" >&6 + +fi +if test $ac_cv_header_sys_strredir_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRREDIR_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_strpty_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/strpty.h" >&5 +echo $ECHO_N "checking for sys/strpty.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_strpty_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_strpty_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_strpty_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/strpty.h usability" >&5 +echo $ECHO_N "checking sys/strpty.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/strpty.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/strpty.h presence" >&5 +echo $ECHO_N "checking sys/strpty.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/strpty.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/strpty.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/strpty.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/strpty.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/strpty.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/strpty.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/strpty.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/strpty.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/strpty.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/strpty.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/strpty.h" >&5 +echo $ECHO_N "checking for sys/strpty.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_strpty_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_strpty_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_strpty_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_strpty_h" >&6 + +fi +if test $ac_cv_header_sys_strpty_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRPTY_H 1 +_ACEOF + +fi + + + +echo "$as_me:$LINENO: checking for sys/bsdtypes.h" >&5 +echo $ECHO_N "checking for sys/bsdtypes.h... $ECHO_C" >&6 +if test "ISC_${ISC}" = "ISC_1" ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + # if on ISC 1, we need <sys/bsdtypes.h> to get FD_SET macros + +for ac_header in sys/bsdtypes.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +#------------------------------------------------------------------------- +# What type do signals return? +#------------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 +if test "${ac_cv_type_signal+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <signal.h> +#ifdef signal +# undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_signal=void +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_signal=int +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +echo "${ECHO_T}$ac_cv_type_signal" >&6 + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + + +#------------------------------------------------------------------------- +# Find out all about time handling differences. +#------------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 +echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6 +if test "${ac_cv_struct_tm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <time.h> + +int +main () +{ +struct tm *tp; tp->tm_sec; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_struct_tm=time.h +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_struct_tm=sys/time.h +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +echo "${ECHO_T}$ac_cv_struct_tm" >&6 +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + + + +for ac_header in sys/time.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the expect lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_time=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6 +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + + echo "$as_me:$LINENO: checking for struct tm.tm_zone" >&5 +echo $ECHO_N "checking for struct tm.tm_zone... $ECHO_C" >&6 +if test "${ac_cv_member_struct_tm_tm_zone+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <$ac_cv_struct_tm> + + +int +main () +{ +static struct tm ac_aggr; +if (ac_aggr.tm_zone) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_tm_tm_zone=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <$ac_cv_struct_tm> + + +int +main () +{ +static struct tm ac_aggr; +if (sizeof ac_aggr.tm_zone) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_tm_tm_zone=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_tm_tm_zone=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_tm_tm_zone" >&5 +echo "${ECHO_T}$ac_cv_member_struct_tm_tm_zone" >&6 +if test $ac_cv_member_struct_tm_tm_zone = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TM_TM_ZONE 1 +_ACEOF + + +fi + +if test "$ac_cv_member_struct_tm_tm_zone" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TM_ZONE 1 +_ACEOF + +else + echo "$as_me:$LINENO: checking for tzname" >&5 +echo $ECHO_N "checking for tzname... $ECHO_C" >&6 +if test "${ac_cv_var_tzname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <time.h> +#ifndef tzname /* For SGI. */ +extern char *tzname[]; /* RS6000 and others reject char **tzname. */ +#endif + +int +main () +{ +atoi(*tzname); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_var_tzname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_var_tzname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_var_tzname" >&5 +echo "${ECHO_T}$ac_cv_var_tzname" >&6 + if test $ac_cv_var_tzname = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TZNAME 1 +_ACEOF + + fi +fi + + + + +for ac_func in gmtime_r localtime_r +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + echo "$as_me:$LINENO: checking tm_tzadj in struct tm" >&5 +echo $ECHO_N "checking tm_tzadj in struct tm... $ECHO_C" >&6 +if test "${tcl_cv_member_tm_tzadj+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <time.h> +int +main () +{ +struct tm tm; tm.tm_tzadj; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_member_tm_tzadj=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_member_tm_tzadj=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_member_tm_tzadj" >&5 +echo "${ECHO_T}$tcl_cv_member_tm_tzadj" >&6 + if test $tcl_cv_member_tm_tzadj = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TM_TZADJ 1 +_ACEOF + + fi + + echo "$as_me:$LINENO: checking tm_gmtoff in struct tm" >&5 +echo $ECHO_N "checking tm_gmtoff in struct tm... $ECHO_C" >&6 +if test "${tcl_cv_member_tm_gmtoff+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <time.h> +int +main () +{ +struct tm tm; tm.tm_gmtoff; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_member_tm_gmtoff=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_member_tm_gmtoff=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_member_tm_gmtoff" >&5 +echo "${ECHO_T}$tcl_cv_member_tm_gmtoff" >&6 + if test $tcl_cv_member_tm_gmtoff = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TM_GMTOFF 1 +_ACEOF + + fi + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + echo "$as_me:$LINENO: checking long timezone variable" >&5 +echo $ECHO_N "checking long timezone variable... $ECHO_C" >&6 +if test "${tcl_cv_timezone_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <time.h> +int +main () +{ +extern long timezone; + timezone += 1; + exit (0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_timezone_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_timezone_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_timezone_long" >&5 +echo "${ECHO_T}$tcl_cv_timezone_long" >&6 + if test $tcl_cv_timezone_long = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TIMEZONE_VAR 1 +_ACEOF + + else + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + echo "$as_me:$LINENO: checking time_t timezone variable" >&5 +echo $ECHO_N "checking time_t timezone variable... $ECHO_C" >&6 +if test "${tcl_cv_timezone_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <time.h> +int +main () +{ +extern time_t timezone; + timezone += 1; + exit (0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_timezone_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_timezone_time=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_timezone_time" >&5 +echo "${ECHO_T}$tcl_cv_timezone_time" >&6 + if test $tcl_cv_timezone_time = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TIMEZONE_VAR 1 +_ACEOF + + fi + fi + + +#-------------------------------------------------------------------- +# The check below checks whether <sys/wait.h> defines the type +# "union wait" correctly. It's needed because of weirdness in +# HP-UX where "union wait" is defined in both the BSD and SYS-V +# environments. Checking the usability of WIFEXITED seems to do +# the trick. +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking union wait" >&5 +echo $ECHO_N "checking union wait... $ECHO_C" >&6 +if test "${tcl_cv_union_wait+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/wait.h> +int +main () +{ + +union wait x; +WIFEXITED(x); /* Generates compiler error if WIFEXITED uses an int. */ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_union_wait=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_union_wait=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +echo "$as_me:$LINENO: result: $tcl_cv_union_wait" >&5 +echo "${ECHO_T}$tcl_cv_union_wait" >&6 +if test $tcl_cv_union_wait = no; then + cat >>confdefs.h <<\_ACEOF +#define NO_UNION_WAIT 1 +_ACEOF + +fi + +###################################################################### +# required by Sequent ptx2 + +echo "$as_me:$LINENO: checking for gethostname" >&5 +echo $ECHO_N "checking for gethostname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostname to an innocuous variant, in case <limits.h> declares gethostname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define gethostname innocuous_gethostname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef gethostname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostname) || defined (__stub___gethostname) +choke me +#else +char (*f) () = gethostname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostname" >&6 +if test $ac_cv_func_gethostname = yes; then + gethostname=1 +else + gethostname=0 +fi + +if test $gethostname -eq 0 ; then + echo "$as_me:$LINENO: checking for gethostname in -linet" >&5 +echo $ECHO_N "checking for gethostname in -linet... $ECHO_C" >&6 +if test "${ac_cv_lib_inet_gethostname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostname (); +int +main () +{ +gethostname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_inet_gethostname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_inet_gethostname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_inet_gethostname" >&5 +echo "${ECHO_T}$ac_cv_lib_inet_gethostname" >&6 +if test $ac_cv_lib_inet_gethostname = yes; then + LIBS="$LIBS -linet" +fi + +fi + +###################################################################### +# required by Fischman's ISC 4.0 + +echo "$as_me:$LINENO: checking for socket" >&5 +echo $ECHO_N "checking for socket... $ECHO_C" >&6 +if test "${ac_cv_func_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define socket to an innocuous variant, in case <limits.h> declares socket. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define socket innocuous_socket + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char socket (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef socket + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_socket) || defined (__stub___socket) +choke me +#else +char (*f) () = socket; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != socket; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_socket=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_socket=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_socket" >&5 +echo "${ECHO_T}$ac_cv_func_socket" >&6 +if test $ac_cv_func_socket = yes; then + socket=1 +else + socket=0 +fi + +if test $socket -eq 0 ; then + echo "$as_me:$LINENO: checking for socket in -linet" >&5 +echo $ECHO_N "checking for socket in -linet... $ECHO_C" >&6 +if test "${ac_cv_lib_inet_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket (); +int +main () +{ +socket (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_inet_socket=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_inet_socket=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_inet_socket" >&5 +echo "${ECHO_T}$ac_cv_lib_inet_socket" >&6 +if test $ac_cv_lib_inet_socket = yes; then + LIBS="$LIBS -linet" +fi + +fi + +###################################################################### + +echo "$as_me:$LINENO: checking for select" >&5 +echo $ECHO_N "checking for select... $ECHO_C" >&6 +if test "${ac_cv_func_select+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define select to an innocuous variant, in case <limits.h> declares select. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define select innocuous_select + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char select (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef select + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char select (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_select) || defined (__stub___select) +choke me +#else +char (*f) () = select; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != select; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_select=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_select=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_select" >&5 +echo "${ECHO_T}$ac_cv_func_select" >&6 +if test $ac_cv_func_select = yes; then + select=1 +else + select=0 +fi + +if test $select -eq 0 ; then + echo "$as_me:$LINENO: checking for select in -linet" >&5 +echo $ECHO_N "checking for select in -linet... $ECHO_C" >&6 +if test "${ac_cv_lib_inet_select+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char select (); +int +main () +{ +select (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_inet_select=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_inet_select=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_inet_select" >&5 +echo "${ECHO_T}$ac_cv_lib_inet_select" >&6 +if test $ac_cv_lib_inet_select = yes; then + LIBS="$LIBS -linet" +fi + +fi + +###################################################################### + +echo "$as_me:$LINENO: checking for getpseudotty" >&5 +echo $ECHO_N "checking for getpseudotty... $ECHO_C" >&6 +if test "${ac_cv_func_getpseudotty+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define getpseudotty to an innocuous variant, in case <limits.h> declares getpseudotty. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define getpseudotty innocuous_getpseudotty + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getpseudotty (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef getpseudotty + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getpseudotty (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getpseudotty) || defined (__stub___getpseudotty) +choke me +#else +char (*f) () = getpseudotty; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != getpseudotty; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_getpseudotty=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_getpseudotty=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_getpseudotty" >&5 +echo "${ECHO_T}$ac_cv_func_getpseudotty" >&6 +if test $ac_cv_func_getpseudotty = yes; then + getpseudotty=1 +else + getpseudotty=0 +fi + +if test $getpseudotty -eq 0 ; then + +echo "$as_me:$LINENO: checking for getpseudotty in -lseq" >&5 +echo $ECHO_N "checking for getpseudotty in -lseq... $ECHO_C" >&6 +if test "${ac_cv_lib_seq_getpseudotty+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lseq $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getpseudotty (); +int +main () +{ +getpseudotty (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_seq_getpseudotty=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_seq_getpseudotty=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_seq_getpseudotty" >&5 +echo "${ECHO_T}$ac_cv_lib_seq_getpseudotty" >&6 +if test $ac_cv_lib_seq_getpseudotty = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSEQ 1 +_ACEOF + + LIBS="-lseq $LIBS" + +fi + +fi + +###################################################################### +# Check for FreeBSD/NetBSD openpty() +unset ac_cv_func_openpty + +echo "$as_me:$LINENO: checking for openpty" >&5 +echo $ECHO_N "checking for openpty... $ECHO_C" >&6 +if test "${ac_cv_func_openpty+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define openpty to an innocuous variant, in case <limits.h> declares openpty. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define openpty innocuous_openpty + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char openpty (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef openpty + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char openpty (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_openpty) || defined (__stub___openpty) +choke me +#else +char (*f) () = openpty; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != openpty; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_openpty=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_openpty=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_openpty" >&5 +echo "${ECHO_T}$ac_cv_func_openpty" >&6 +if test $ac_cv_func_openpty = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_OPENPTY 1 +_ACEOF + openpty=1 +else + openpty=0 +fi + +if test $openpty -eq 0 ; then + echo "$as_me:$LINENO: checking for openpty in -lutil" >&5 +echo $ECHO_N "checking for openpty in -lutil... $ECHO_C" >&6 +if test "${ac_cv_lib_util_openpty+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lutil $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char openpty (); +int +main () +{ +openpty (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_util_openpty=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_util_openpty=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_util_openpty" >&5 +echo "${ECHO_T}$ac_cv_lib_util_openpty" >&6 +if test $ac_cv_lib_util_openpty = yes; then + + # we only need to define OPENPTY once, but since we are overriding + # the default behavior, we must also handle augment LIBS too. + # This needn't be done in the 2nd and 3rd tests. + cat >>confdefs.h <<\_ACEOF +#define HAVE_OPENPTY 1 +_ACEOF + + LIBS="$LIBS -lutil" + +fi + +fi + +###################################################################### +# End of library/func checking +###################################################################### + +# Hand patches to library/func checking. + +echo "$as_me:$LINENO: checking if running Sequent running SVR4" >&5 +echo $ECHO_N "checking if running Sequent running SVR4... $ECHO_C" >&6 +if test "$host_alias" = "i386-sequent-sysv4" ; then + LIBS="-lnsl -lsocket -lm" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +# From here on comes original expect configure code. +# At the end we will have another section of TEA 3.2 code. +# +# Note specialities +# +# - Runs a sub configure (Dbgconfigure) for the expect tcl debugger +# +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6 +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_target_alias=$target_alias +test "x$ac_cv_target_alias" = "x" && + ac_cv_target_alias=$ac_cv_host_alias +ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6 +target=$ac_cv_target +target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +# If `configure' is invoked (in)directly via `make', ensure that it +# encounters no `make' conflicts. +# + +MFLAGS= +MAKEFLAGS= + +# An explanation is in order for the strange things going on with the +# various LIBS. There are three separate definitions for LIBS. The +# reason is that some systems require shared libraries include +# references to their dependent libraries, i.e., any additional +# libraries that must be linked to. And some systems get upset if the +# references are repeated on the link line. So therefore, we create +# one for Expect, one for Expect and Tcl, and one for building Expect's own +# shared library. Tcl's tclConfig.sh insists that any shared libs +# that it "helps" build must pass the libraries as LIBS (see comment +# near end of this configure file). I would do but since we're close +# to hitting config's max symbols, we take one short cut and pack the +# LIBS into EXP_SHLIB_LD_LIBS (which is basically what Tcl wants to do +# for us). The point, however, is that there's no separate LIBS or +# EXP_LIBS symbol passed out of configure. One additional point for +# confusion is that LIBS is what configure uses to do all library +# tests, so we have to swap definitions of LIBS periodically. When we +# are swapping out the one for Expect's shared library, we save it in +# EXP_LIBS. Sigh. + +eval "LIBS=\"$TCL_LIBS\"" + +if test "${with_tcl+set}" = set ; then + case "${with_tcl}" in + ..*) + { echo "$as_me:$LINENO: WARNING: Specify absolute path to --with-tcl for subdir configuration" >&5 +echo "$as_me: WARNING: Specify absolute path to --with-tcl for subdir configuration" >&2;} + ;; + esac +fi + +# these are the other subdirectories we need to configure + + +subdirs="$subdirs testsuite" + + +echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6 +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((pid_t *) 0) + return 0; +if (sizeof (pid_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_pid_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6 +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + + +echo "$as_me:$LINENO: checking if running Mach" >&5 +echo $ECHO_N "checking if running Mach... $ECHO_C" >&6 +mach=0 +case "${host}" in + # Both Next and pure Mach behave identically with respect + # to a few things, so just lump them together as "mach" + *-*-mach*) mach=1 ;; + *-*-next*) mach=1 ; next=1 ;; +esac + +if test $mach -eq 1 ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:$LINENO: checking if running MachTen" >&5 +echo $ECHO_N "checking if running MachTen... $ECHO_C" >&6 +# yet another Mach clone +if test -r /MachTen ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + mach=1 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:$LINENO: checking if on Pyramid" >&5 +echo $ECHO_N "checking if on Pyramid... $ECHO_C" >&6 +if test -r /bin/pyr ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + pyr=1 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + pyr=0 +fi + +echo "$as_me:$LINENO: checking if on Apollo" >&5 +echo $ECHO_N "checking if on Apollo... $ECHO_C" >&6 +if test -r /usr/apollo/bin ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + apollo=1 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + apollo=0 +fi + +echo "$as_me:$LINENO: checking if on Interactive" >&5 +echo $ECHO_N "checking if on Interactive... $ECHO_C" >&6 +if test "x`(uname -s) 2>/dev/null`" = xIUNIX; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + iunix=1 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + iunix=0 +fi + +echo "$as_me:$LINENO: checking stty to use" >&5 +echo $ECHO_N "checking stty to use... $ECHO_C" >&6 +if test -r /usr/local/bin/stty ; then + STTY_BIN=/usr/local/bin/stty +else + STTY_BIN=/bin/stty +fi +echo "$as_me:$LINENO: result: $STTY_BIN" >&5 +echo "${ECHO_T}$STTY_BIN" >&6 + +echo "$as_me:$LINENO: checking if stty reads stdout" >&5 +echo $ECHO_N "checking if stty reads stdout... $ECHO_C" >&6 + +# On some systems stty can't be run in the background (svr4) or get it +# wrong because they fail to complain (next, mach), so don't attempt +# the test on some systems. + +stty_reads_stdout="" +case "${host}" in + *-*-solaris*) stty_reads_stdout=0 ;; + *-*-irix*) stty_reads_stdout=0 ;; + *-*-sco3.2v[45]*) stty_reads_stdout=1 ;; + i[3456]86-*-sysv4.2MP) stty_reads_stdout=0 ;; + *-*-linux*) stty_reads_stdout=0 ;; + # Not sure about old convex but 5.2 definitely reads from stdout + c[12]-*-*) stty_reads_stdout=1 ;; + *-*-aix[34]*) stty_reads_stdout=0 ;; + *-*-hpux9*) stty_reads_stdout=0 ;; + *-*-hpux10*) stty_reads_stdout=0 ;; + *-*-osf[234]*) stty_reads_stdout=0 ;; + *-*-ultrix4.4) stty_reads_stdout=0 ;; + *-*-dgux*) stty_reads_stdout=0 ;; +esac + +if test $mach -eq 1 ; then + stty_reads_stdout=1 +fi +if test $apollo -eq 1 ; then + stty_reads_stdout=1 +fi +if test $pyr -eq 1 ; then + stty_reads_stdout=1 +fi + +# if we still don't know, test +if test x"${stty_reads_stdout}" = x"" ; then + $STTY_BIN > /dev/null 2> /dev/null ; a=$? + $STTY_BIN < /dev/tty > /dev/null 2> /dev/null ; b=$? + if test $a -ne 0 -a $b -ne 0; then + stty_reads_stdout=1 + else + stty_reads_stdout=0 + fi +fi + +if test ${stty_reads_stdout} -eq 1 ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define STTY_READS_STDOUT 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# Solaris 2.4 and later requires __EXTENSIONS__ in order to see all sorts +# of traditional but nonstandard stuff in header files. +echo "$as_me:$LINENO: checking if running Solaris" >&5 +echo $ECHO_N "checking if running Solaris... $ECHO_C" >&6 +solaris=0 +case "${host}" in + *-*-solaris*) solaris=1;; +esac + +if test $solaris -eq 1 ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define SOLARIS 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# On Interactive UNIX, -Xp must be added to LIBS in order to find strftime. +# This test should really be done by Tcl. So just check Tcl's definition. +# If defective, add to all three LIBS. (It's not actually necessary for +# EXP_LIBS since -Xp will just be ignored the way that EXP_LIBS is used in +# the Makefile, but we include it for consistency.) + +if test $iunix -eq 1 ; then + echo "$as_me:$LINENO: checking for strftime" >&5 +echo $ECHO_N "checking for strftime... $ECHO_C" >&6 +if test "${ac_cv_func_strftime+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strftime to an innocuous variant, in case <limits.h> declares strftime. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define strftime innocuous_strftime + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strftime (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef strftime + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strftime (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strftime) || defined (__stub___strftime) +choke me +#else +char (*f) () = strftime; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strftime; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strftime=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strftime=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strftime" >&5 +echo "${ECHO_T}$ac_cv_func_strftime" >&6 +if test $ac_cv_func_strftime = yes; then + : +else + + LIBS="${LIBS} -Xp" + +fi + +fi + +###################################################################### +# +# Look for various header files +# + +# +# Look for functions that may be missing +# +echo "$as_me:$LINENO: checking for memmove" >&5 +echo $ECHO_N "checking for memmove... $ECHO_C" >&6 +if test "${ac_cv_func_memmove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define memmove to an innocuous variant, in case <limits.h> declares memmove. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define memmove innocuous_memmove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char memmove (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef memmove + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char memmove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_memmove) || defined (__stub___memmove) +choke me +#else +char (*f) () = memmove; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != memmove; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_memmove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_memmove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_memmove" >&5 +echo "${ECHO_T}$ac_cv_func_memmove" >&6 +if test $ac_cv_func_memmove = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MEMMOVE 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for sysconf" >&5 +echo $ECHO_N "checking for sysconf... $ECHO_C" >&6 +if test "${ac_cv_func_sysconf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define sysconf to an innocuous variant, in case <limits.h> declares sysconf. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define sysconf innocuous_sysconf + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char sysconf (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef sysconf + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sysconf (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sysconf) || defined (__stub___sysconf) +choke me +#else +char (*f) () = sysconf; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != sysconf; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_sysconf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_sysconf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_sysconf" >&5 +echo "${ECHO_T}$ac_cv_func_sysconf" >&6 +if test $ac_cv_func_sysconf = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYSCONF 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for strftime" >&5 +echo $ECHO_N "checking for strftime... $ECHO_C" >&6 +if test "${ac_cv_func_strftime+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strftime to an innocuous variant, in case <limits.h> declares strftime. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define strftime innocuous_strftime + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strftime (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef strftime + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strftime (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strftime) || defined (__stub___strftime) +choke me +#else +char (*f) () = strftime; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strftime; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strftime=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strftime=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strftime" >&5 +echo "${ECHO_T}$ac_cv_func_strftime" >&6 +if test $ac_cv_func_strftime = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for strchr" >&5 +echo $ECHO_N "checking for strchr... $ECHO_C" >&6 +if test "${ac_cv_func_strchr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strchr to an innocuous variant, in case <limits.h> declares strchr. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define strchr innocuous_strchr + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strchr (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef strchr + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strchr (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strchr) || defined (__stub___strchr) +choke me +#else +char (*f) () = strchr; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strchr; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strchr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strchr=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strchr" >&5 +echo "${ECHO_T}$ac_cv_func_strchr" >&6 +if test $ac_cv_func_strchr = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRCHR 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for timezone" >&5 +echo $ECHO_N "checking for timezone... $ECHO_C" >&6 +if test "${ac_cv_func_timezone+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define timezone to an innocuous variant, in case <limits.h> declares timezone. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define timezone innocuous_timezone + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char timezone (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef timezone + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char timezone (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_timezone) || defined (__stub___timezone) +choke me +#else +char (*f) () = timezone; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != timezone; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_timezone=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_timezone=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_timezone" >&5 +echo "${ECHO_T}$ac_cv_func_timezone" >&6 +if test $ac_cv_func_timezone = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TIMEZONE 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for siglongjmp" >&5 +echo $ECHO_N "checking for siglongjmp... $ECHO_C" >&6 +if test "${ac_cv_func_siglongjmp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define siglongjmp to an innocuous variant, in case <limits.h> declares siglongjmp. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define siglongjmp innocuous_siglongjmp + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char siglongjmp (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef siglongjmp + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char siglongjmp (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_siglongjmp) || defined (__stub___siglongjmp) +choke me +#else +char (*f) () = siglongjmp; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != siglongjmp; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_siglongjmp=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_siglongjmp=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_siglongjmp" >&5 +echo "${ECHO_T}$ac_cv_func_siglongjmp" >&6 +if test $ac_cv_func_siglongjmp = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SIGLONGJMP 1 +_ACEOF + +fi + + +# dnl check for memcpy by hand +# because Unixware 2.0 handles it specially and refuses to compile +# autoconf's automatic test that is a call with no arguments +echo "$as_me:$LINENO: checking for memcpy" >&5 +echo $ECHO_N "checking for memcpy... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + +char *s1, *s2; +memcpy(s1,s2,0); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_MEMCPY 1 +_ACEOF + + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +# Some systems only define WNOHANG if _POSIX_SOURCE is defined +# The following merely tests that sys/wait.h can be included +# and if so that WNOHANG is not defined. The only place I've +# seen this is ISC. +echo "$as_me:$LINENO: checking if WNOHANG requires _POSIX_SOURCE" >&5 +echo $ECHO_N "checking if WNOHANG requires _POSIX_SOURCE... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <sys/wait.h> +main() { +#ifndef WNOHANG + return 0; +#else + return 1; +#endif +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define WNOHANG_REQUIRES_POSIX_SOURCE 1 +_ACEOF + + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +echo "$as_me:$LINENO: checking if any value exists for WNOHANG" >&5 +echo $ECHO_N "checking if any value exists for WNOHANG... $ECHO_C" >&6 +rm -rf wnohang +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <stdio.h> +#include <sys/wait.h> +main() { +#ifdef WNOHANG + FILE *fp = fopen("wnohang","w"); + fprintf(fp,"%d",WNOHANG); + fclose(fp); + return 0; +#else + return 1; +#endif +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<_ACEOF +#define WNOHANG_BACKUP_VALUE `cat wnohang` +_ACEOF + + rm -f wnohang + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + cat >>confdefs.h <<\_ACEOF +#define WNOHANG_BACKUP_VALUE 1 +_ACEOF + + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# +# check how signals work +# + +# Check for the data type of the mask used in select(). +# This picks up HP braindamage which defines fd_set and then +# proceeds to ignore it and use int. +# Pattern matching on int could be loosened. +# Can't use ac_header_egrep since that doesn't see prototypes with K&R cpp. +echo "$as_me:$LINENO: checking mask type of select" >&5 +echo $ECHO_N "checking mask type of select... $ECHO_C" >&6 +if egrep "select\(size_t, int" /usr/include/sys/time.h >/dev/null 2>&1; then + echo "$as_me:$LINENO: result: int" >&5 +echo "${ECHO_T}int" >&6 + cat >>confdefs.h <<\_ACEOF +#define SELECT_MASK_TYPE int +_ACEOF + +else + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + cat >>confdefs.h <<\_ACEOF +#define SELECT_MASK_TYPE fd_set +_ACEOF + +fi + + +# FIXME: check if alarm exists +echo "$as_me:$LINENO: checking if signals need to be re-armed" >&5 +echo $ECHO_N "checking if signals need to be re-armed... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { echo "$as_me:$LINENO: WARNING: Expect can't be cross compiled" >&5 +echo "$as_me: WARNING: Expect can't be cross compiled" >&2;} + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <signal.h> +#define RETSIGTYPE $retsigtype + +int signal_rearms = 0; + +RETSIGTYPE +child_sigint_handler(n) +int n; +{ +} + +RETSIGTYPE +parent_sigint_handler(n) +int n; +{ +signal_rearms++; +} + +main() +{ + signal(SIGINT,parent_sigint_handler); + + if (0 == fork()) { + signal(SIGINT,child_sigint_handler); + kill(getpid(),SIGINT); + kill(getpid(),SIGINT); + kill(getppid(),SIGINT); + } else { + int status; + + wait(&status); + unlink("core"); + exit(signal_rearms); + } +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define REARM_SIG 1 +_ACEOF + + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# HPUX7 has trouble with the big cat so split it +# Owen Rees <rtor@ansa.co.uk> 29Mar93 +SEDDEFS="${SEDDEFS}CONFEOF +cat >> conftest.sed <<CONFEOF +" +# + +# There are multiple versions of getpty, alas. +# I don't remember who has the first one, but Convex just added one +# so check for it. Unfortunately, there is no header so the only +# reasonable way to make sure is to look it we are on a Convex. +echo "$as_me:$LINENO: checking if on Convex" >&5 +echo $ECHO_N "checking if on Convex... $ECHO_C" >&6 +convex=0 +case "${host}" in + c[12]-*-*) convex=1;; +esac + +if test $convex -eq 1 ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define CONVEX 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +echo "$as_me:$LINENO: checking if on HP" >&5 +echo $ECHO_N "checking if on HP... $ECHO_C" >&6 +if test "x`(uname) 2>/dev/null`" = xHP-UX; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + hp=1 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + hp=0 +fi + +echo "$as_me:$LINENO: checking sane default stty arguments" >&5 +echo $ECHO_N "checking sane default stty arguments... $ECHO_C" >&6 +DEFAULT_STTY_ARGS="sane" + +if test $mach -eq 1 ; then + DEFAULT_STTY_ARGS="cooked" +fi + +if test $hp -eq 1 ; then + DEFAULT_STTY_ARGS="sane kill " +fi + +echo "$as_me:$LINENO: result: $DEFAULT_STTY_ARG" >&5 +echo "${ECHO_T}$DEFAULT_STTY_ARG" >&6 + +# Look for various features to determine what kind of pty +# we have. For some weird reason, ac_compile_check would not +# work, but ac_test_program does. +# +echo "$as_me:$LINENO: checking for HP style pty allocation" >&5 +echo $ECHO_N "checking for HP style pty allocation... $ECHO_C" >&6 +# following test fails on DECstations and other things that don't grok -c +# but that's ok, since they don't have PTYMs anyway +if test -r /dev/ptym/ptyp0 2>/dev/null ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTYM 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:$LINENO: checking for HP style pty trapping" >&5 +echo $ECHO_N "checking for HP style pty trapping... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/ptyio.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "struct.*request_info" >/dev/null 2>&1; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTYTRAP 1 +_ACEOF + + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest* + + +echo "$as_me:$LINENO: checking for AIX new-style pty allocation" >&5 +echo $ECHO_N "checking for AIX new-style pty allocation... $ECHO_C" >&6 +if test -r /dev/ptc -a -r /dev/pts ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTC_PTS 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:$LINENO: checking for SGI old-style pty allocation" >&5 +echo $ECHO_N "checking for SGI old-style pty allocation... $ECHO_C" >&6 +if test -r /dev/ptc -a ! -r /dev/pts ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTC 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# On SCO OpenServer, two types of ptys are available: SVR4 streams and c-list. +# The library routines to open the SVR4 ptys are broken on certain systems and +# the SCO command to increase the number of ptys only configure c-list ones +# anyway. So we chose these, which have a special numbering scheme. +# +echo "$as_me:$LINENO: checking for SCO style pty allocation" >&5 +echo $ECHO_N "checking for SCO style pty allocation... $ECHO_C" >&6 +sco_ptys="" +case "${host}" in + *-sco3.2v[45]*) sco_clist_ptys=1 svr4_ptys_broken=1;; +esac + +if test x"${sco_clist_ptys}" != x"" ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_SCO_CLIST_PTYS 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:$LINENO: checking for SVR4 style pty allocation" >&5 +echo $ECHO_N "checking for SVR4 style pty allocation... $ECHO_C" >&6 +if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTMX 1 +_ACEOF + + # aargg. Some systems need libpt.a to use /dev/ptmx + echo "$as_me:$LINENO: checking for libpts=\"-lpt\" in -lpt" >&5 +echo $ECHO_N "checking for libpts=\"-lpt\" in -lpt... $ECHO_C" >&6 +if test "${ac_cv_lib_pt_libpts___lpt_+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char libpts="-lpt" (); +int +main () +{ +libpts="-lpt" (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pt_libpts___lpt_=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pt_libpts___lpt_=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pt_libpts___lpt_" >&5 +echo "${ECHO_T}$ac_cv_lib_pt_libpts___lpt_" >&6 +if test $ac_cv_lib_pt_libpts___lpt_ = yes; then + libpts="" +fi + + echo "$as_me:$LINENO: checking for ptsname" >&5 +echo $ECHO_N "checking for ptsname... $ECHO_C" >&6 +if test "${ac_cv_func_ptsname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define ptsname to an innocuous variant, in case <limits.h> declares ptsname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define ptsname innocuous_ptsname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char ptsname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef ptsname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char ptsname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_ptsname) || defined (__stub___ptsname) +choke me +#else +char (*f) () = ptsname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != ptsname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_ptsname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_ptsname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_ptsname" >&5 +echo "${ECHO_T}$ac_cv_func_ptsname" >&6 +if test $ac_cv_func_ptsname = yes; then + : +else + LIBS="${LIBS} $libpts" +fi + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# In OSF/1 case, SVR4 are somewhat different. +# Gregory Depp <depp@osf.org> 17Aug93 +echo "$as_me:$LINENO: checking for OSF/1 style pty allocation" >&5 +echo $ECHO_N "checking for OSF/1 style pty allocation... $ECHO_C" >&6 +if test -r /dev/ptmx_bsd ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTMX_BSD 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +tcgetattr=0 +tcsetattr=0 +echo "$as_me:$LINENO: checking for tcgetattr" >&5 +echo $ECHO_N "checking for tcgetattr... $ECHO_C" >&6 +if test "${ac_cv_func_tcgetattr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define tcgetattr to an innocuous variant, in case <limits.h> declares tcgetattr. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define tcgetattr innocuous_tcgetattr + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char tcgetattr (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef tcgetattr + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tcgetattr (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_tcgetattr) || defined (__stub___tcgetattr) +choke me +#else +char (*f) () = tcgetattr; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != tcgetattr; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_tcgetattr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_tcgetattr=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_tcgetattr" >&5 +echo "${ECHO_T}$ac_cv_func_tcgetattr" >&6 +if test $ac_cv_func_tcgetattr = yes; then + tcgetattr=1 +fi + +echo "$as_me:$LINENO: checking for tcsetattr" >&5 +echo $ECHO_N "checking for tcsetattr... $ECHO_C" >&6 +if test "${ac_cv_func_tcsetattr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define tcsetattr to an innocuous variant, in case <limits.h> declares tcsetattr. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define tcsetattr innocuous_tcsetattr + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char tcsetattr (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef tcsetattr + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tcsetattr (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_tcsetattr) || defined (__stub___tcsetattr) +choke me +#else +char (*f) () = tcsetattr; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != tcsetattr; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_tcsetattr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_tcsetattr=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_tcsetattr" >&5 +echo "${ECHO_T}$ac_cv_func_tcsetattr" >&6 +if test $ac_cv_func_tcsetattr = yes; then + tcsetattr=1 +fi + +if test $tcgetattr -eq 1 -a $tcsetattr -eq 1 ; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TCSETATTR 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define POSIX 1 +_ACEOF + +fi + +# first check for the pure bsd +echo "$as_me:$LINENO: checking for struct sgttyb" >&5 +echo $ECHO_N "checking for struct sgttyb... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <sgtty.h> +main() +{ + struct sgttyb tmp; + exit(0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_SGTTYB 1 +_ACEOF + + PTY_TYPE=sgttyb + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# mach systems have include files for unimplemented features +# so avoid doing following test on those systems +if test $mach -eq 0 ; then + + # next check for the older style ttys + # note that if we detect termio.h (only), we still set PTY_TYPE=termios + # since that just controls which of pty_XXXX.c file is use and + # pty_termios.c is set up to handle pty_termio. + echo "$as_me:$LINENO: checking for struct termio" >&5 +echo $ECHO_N "checking for struct termio... $ECHO_C" >&6 + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <termio.h> + main() + { + struct termio tmp; + exit(0); + } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TERMIO 1 +_ACEOF + + PTY_TYPE=termios + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + # now check for the new style ttys (not yet posix) + echo "$as_me:$LINENO: checking for struct termios" >&5 +echo $ECHO_N "checking for struct termios... $ECHO_C" >&6 + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + /* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +# ifdef HAVE_INTTYPES_H +# include <inttypes.h> +# endif +# include <termios.h> + main() + { + struct termios tmp; + exit(0); + } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TERMIOS 1 +_ACEOF + + PTY_TYPE=termios + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi + +echo "$as_me:$LINENO: checking if TCGETS or TCGETA in termios.h" >&5 +echo $ECHO_N "checking if TCGETS or TCGETA in termios.h... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#include <termios.h> +main() { +#if defined(TCGETS) || defined(TCGETA) + return 0; +#else + return 1; +#endif +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +echo "$as_me:$LINENO: checking if TIOCGWINSZ in termios.h" >&5 +echo $ECHO_N "checking if TIOCGWINSZ in termios.h... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#include <termios.h> +main() { +#ifdef TIOCGWINSZ + return 0; +#else + return 1; +#endif +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TIOCGWINSZ_IN_TERMIOS_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# finally check for Cray style ttys +echo "$as_me:$LINENO: checking for Cray-style ptys" >&5 +echo $ECHO_N "checking for Cray-style ptys... $ECHO_C" >&6 +SETUID=":" +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +main(){ +#ifdef CRAY + return 0; +#else + return 1; +#endif +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + PTY_TYPE=unicos + SETUID="chmod u+s" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +# +# Check for select and/or poll. If both exist, we prefer select. +# if neither exists, define SIMPLE_EVENT. +# +select=0 +poll=0 +unset ac_cv_func_select +echo "$as_me:$LINENO: checking for select" >&5 +echo $ECHO_N "checking for select... $ECHO_C" >&6 +if test "${ac_cv_func_select+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define select to an innocuous variant, in case <limits.h> declares select. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define select innocuous_select + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char select (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef select + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char select (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_select) || defined (__stub___select) +choke me +#else +char (*f) () = select; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != select; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_select=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_select=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_select" >&5 +echo "${ECHO_T}$ac_cv_func_select" >&6 +if test $ac_cv_func_select = yes; then + select=1 +fi + +echo "$as_me:$LINENO: checking for poll" >&5 +echo $ECHO_N "checking for poll... $ECHO_C" >&6 +if test "${ac_cv_func_poll+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define poll to an innocuous variant, in case <limits.h> declares poll. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define poll innocuous_poll + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char poll (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef poll + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char poll (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_poll) || defined (__stub___poll) +choke me +#else +char (*f) () = poll; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != poll; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_poll=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_poll=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_poll" >&5 +echo "${ECHO_T}$ac_cv_func_poll" >&6 +if test $ac_cv_func_poll = yes; then + poll=1 +fi + +echo "$as_me:$LINENO: checking event handling" >&5 +echo $ECHO_N "checking event handling... $ECHO_C" >&6 +if test $select -eq 1 ; then + EVENT_TYPE=select + EVENT_ABLE=event + echo "$as_me:$LINENO: result: via select" >&5 +echo "${ECHO_T}via select" >&6 +elif test $poll -eq 1 ; then + EVENT_TYPE=poll + EVENT_ABLE=event + echo "$as_me:$LINENO: result: via poll" >&5 +echo "${ECHO_T}via poll" >&6 +else + EVENT_TYPE=simple + EVENT_ABLE=noevent + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + cat >>confdefs.h <<\_ACEOF +#define SIMPLE_EVENT 1 +_ACEOF + +fi + + +for ac_func in _getpty +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +for ac_func in getpty +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# following test sets SETPGRP_VOID if setpgrp takes 0 args, else takes 2 +echo "$as_me:$LINENO: checking whether setpgrp takes no argument" >&5 +echo $ECHO_N "checking whether setpgrp takes no argument... $ECHO_C" >&6 +if test "${ac_cv_func_setpgrp_void+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot check setpgrp when cross compiling" >&5 +echo "$as_me: error: cannot check setpgrp when cross compiling" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_UNISTD_H +# include <unistd.h> +#endif + +int +main () +{ +/* If this system has a BSD-style setpgrp which takes arguments, + setpgrp(1, 1) will fail with ESRCH and return -1, in that case + exit successfully. */ + exit (setpgrp (1,1) == -1 ? 0 : 1); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_setpgrp_void=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_setpgrp_void=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_func_setpgrp_void" >&5 +echo "${ECHO_T}$ac_cv_func_setpgrp_void" >&6 +if test $ac_cv_func_setpgrp_void = yes; then + +cat >>confdefs.h <<\_ACEOF +#define SETPGRP_VOID 1 +_ACEOF + +fi + + +# +# check for timezones +# +echo "$as_me:$LINENO: checking for SV-style timezone" >&5 +echo $ECHO_N "checking for SV-style timezone... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: Expect can't be cross compiled" >&5 +echo "$as_me: error: Expect can't be cross compiled" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +extern char *tzname[2]; +extern int daylight; +main() +{ + int *x = &daylight; + char **y = tzname; + + exit(0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SV_TIMEZONE 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +# Following comment stolen from Tcl's configure.in: +# Note: in the following variable, it's important to use the absolute +# path name of the Tcl directory rather than "..": this is because +# AIX remembers this path and will attempt to use it at run-time to look +# up the Tcl library. + +PACKAGE_VERSION_NODOTS="`echo $PACKAGE_VERSION | sed -e 's/\.//g'`" + +if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + EXP_LIB_VERSION=$PACKAGE_VERSION +else + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi +if test $iunix -eq 1 ; then + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi + +# also remove dots on systems that don't support filenames > 14 +# (are there systems which support shared libs and restrict filename lengths!?) +echo "$as_me:$LINENO: checking for long file names" >&5 +echo $ECHO_N "checking for long file names... $ECHO_C" >&6 +if test "${ac_cv_sys_long_file_names+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_long_file_names=yes +# Test for long file names in all the places we know might matter: +# . the current directory, where building will happen +# $prefix/lib where we will be installing things +# $exec_prefix/lib likewise +# eval it to expand exec_prefix. +# $TMPDIR if set, where it might want to write temporary files +# if $TMPDIR is not set: +# /tmp where it might want to write temporary files +# /var/tmp likewise +# /usr/tmp likewise +if test -n "$TMPDIR" && test -d "$TMPDIR" && test -w "$TMPDIR"; then + ac_tmpdirs=$TMPDIR +else + ac_tmpdirs='/tmp /var/tmp /usr/tmp' +fi +for ac_dir in . $ac_tmpdirs `eval echo $prefix/lib $exec_prefix/lib` ; do + test -d $ac_dir || continue + test -w $ac_dir || continue # It is less confusing to not echo anything here. + ac_xdir=$ac_dir/cf$$ + (umask 077 && mkdir $ac_xdir 2>/dev/null) || continue + ac_tf1=$ac_xdir/conftest9012345 + ac_tf2=$ac_xdir/conftest9012346 + (echo 1 >$ac_tf1) 2>/dev/null + (echo 2 >$ac_tf2) 2>/dev/null + ac_val=`cat $ac_tf1 2>/dev/null` + if test ! -f $ac_tf1 || test "$ac_val" != 1; then + ac_cv_sys_long_file_names=no + rm -rf $ac_xdir 2>/dev/null + break + fi + rm -rf $ac_xdir 2>/dev/null +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_long_file_names" >&5 +echo "${ECHO_T}$ac_cv_sys_long_file_names" >&6 +if test $ac_cv_sys_long_file_names = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LONG_FILE_NAMES 1 +_ACEOF + +fi + +if test $ac_cv_sys_long_file_names = no; then + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi + +if test "$FRAMEWORK_BUILD" = "1" ; then + EXP_BUILD_LIB_SPEC="-F`pwd` -framework Expect" + EXP_LIB_SPEC="-framework Expect" + EXP_LIB_FILE="Expect" + cat >>confdefs.h <<\_ACEOF +#define EXP_FRAMEWORK 1 +_ACEOF + +else + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + EXP_LIB_FLAG="-lexpect${EXP_LIB_VERSION}" + else + EXP_LIB_FLAG="-lexpect`echo ${EXP_LIB_VERSION} | tr -d .`" + fi + EXP_BUILD_LIB_SPEC="-L`pwd` ${EXP_LIB_FLAG}" + EXP_LIB_SPEC="-L${libdir} ${EXP_LIB_FLAG}" +fi + +#-------------------------------------------------------------------- +# This section is based on analogous thing in Tk installation. - DEL +# Various manipulations on the search path used at runtime to +# find shared libraries: +# 2. On systems such as AIX and Ultrix that use "-L" as the +# search path option, colons cannot be used to separate +# directories from each other. Change colons to " -L". +# 3. Create two sets of search flags, one for use in cc lines +# and the other for when the linker is invoked directly. In +# the second case, '-Wl,' must be stripped off and commas must +# be replaced by spaces. +#-------------------------------------------------------------------- + +LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}/${PACKAGE_NAME}${PACKAGE_VERSION}' + +# If Tcl and Expect are installed in different places, adjust the library +# search path to reflect this. + +if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib" +fi + +if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then + LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'` +fi + +# The eval below is tricky! It *evaluates* the string in +# ..._CC_SEARCH_FLAGS, which causes a substitution of the +# variable LIB_RUNTIME_DIR. + +eval "EXP_CC_SEARCH_FLAGS=\"$TCL_CC_SEARCH_FLAGS\"" + +# now broken out into EXP_AND_TCL_LIBS. Had to do this +# in order to avoid repeating lib specs to which some systems object. + +LIBS="$LIBS $LD_SEARCH_FLAGS" + +# +# Set up makefile substitutions +# + + + + + +# Expect uses these from tclConfig.sh to make the main executable + + + +#-------------------------------------------------------------------- +# More TEA code based on data we got from the original expect +# configure code. +#-------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + + + vars=" + exp_command.c expect.c exp_inter.c exp_regexp.c exp_tty.c + exp_log.c exp_main_sub.c exp_pty.c exp_trap.c exp_strf.c + exp_console.c exp_glob.c exp_win.c exp_clib.c exp_closetcl.c + exp_memmove.c exp_tty_comm.c exp_chan.c Dbg.c +" + for i in $vars; do + case $i in + \$*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + { { echo "$as_me:$LINENO: error: could not find source file '$i'" >&5 +echo "$as_me: error: could not find source file '$i'" >&2;} + { (exit 1); exit 1; }; } + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + + + + +# Variant sources. Comments in the Makefile indicate that the +# event_type/able stuff can be overidden in the Makefile, and should +# be for particular systems. IMHO this requires a configure option. +# +# See at the end, where we select the sources based on the collect +# information. + + + vars=" + pty_${PTY_TYPE}.c + exp_${EVENT_TYPE}.c + exp_${EVENT_ABLE}.c +" + for i in $vars; do + case $i in + \$*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + { { echo "$as_me:$LINENO: error: could not find source file '$i'" >&5 +echo "$as_me: error: could not find source file '$i'" >&2;} + { (exit 1); exit 1; }; } + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + + + + + + vars="expect.h expect_tcl.h expect_comm.h tcldbg.h" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + { { echo "$as_me:$LINENO: error: could not find header file '${srcdir}/$i'" >&5 +echo "$as_me: error: could not find header file '${srcdir}/$i'" >&2;} + { (exit 1); exit 1; }; } + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + + + + + vars="-I." + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + + + + vars="-I\"`\${CYGPATH} \${srcdir}`\"" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + + + + + vars="" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + + PKG_CFLAGS="$PKG_CFLAGS -DTCL_DEBUGGER -DUSE_NON_CONST" + + + + PKG_CFLAGS="$PKG_CFLAGS -DSCRIPTDIR=\\\"\${DESTDIR}\${prefix}/lib/\${PKG_DIR}\\\"" + + + + PKG_CFLAGS="$PKG_CFLAGS -DEXECSCRIPTDIR=\\\"\${DESTDIR}\${pkglibdir}\\\"" + + + + PKG_CFLAGS="$PKG_CFLAGS -DSTTY_BIN=\\\"${STTY_BIN}\\\"" + + + + PKG_CFLAGS="$PKG_CFLAGS -DDFLT_STTY=\"\\\"$DEFAULT_STTY_ARGS\\\"\"" + + + + + vars="" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + { { echo "$as_me:$LINENO: error: could not find stub source file '$i'" >&5 +echo "$as_me: error: could not find stub source file '$i'" >&2;} + { (exit 1); exit 1; }; } + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + + + + + vars="" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + { { echo "$as_me:$LINENO: error: could not find tcl source file '${srcdir}/$i'" >&5 +echo "$as_me: error: could not find tcl source file '${srcdir}/$i'" >&2;} + { (exit 1); exit 1; }; } + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + + + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + + + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS)" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "manifest needed" >/dev/null 2>&1; then + + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + + CLEANFILES="$CLEANFILES *.manifest" + + +fi +rm -f conftest* + + MAKE_STUB_LIB="\${STLIB_LD} -out:\$@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + + + + + + + + + +#-------------------------------------------------------------------- +# Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl +# file during the install process. Don't run the TCLSH_PROG through +# ${CYGPATH} because it's being used directly by make. +# Require that we use a tclsh shell version 8.2 or later since earlier +# versions have bugs in the pkg_mkIndex routine. +# Add WISH as well if this is a Tk extension. +#-------------------------------------------------------------------- + + + echo "$as_me:$LINENO: checking for tclsh" >&5 +echo $ECHO_N "checking for tclsh... $ECHO_C" >&6 + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + echo "$as_me:$LINENO: result: ${TCLSH_PROG}" >&5 +echo "${ECHO_T}${TCLSH_PROG}" >&6 + + + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the Makefile. +# You may alternatively have a special pkgIndex.tcl.in or other files +# which require substituting th AC variables in. Include these here. +#-------------------------------------------------------------------- + +touch expect_cf.h + ac_config_files="$ac_config_files Makefile" + ac_config_commands="$ac_config_commands default" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by expect $as_me 5.45, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +expect config.status 5.45 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CYGPATH@,$CYGPATH,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@PKG_LIB_FILE@,$PKG_LIB_FILE,;t t +s,@PKG_STUB_LIB_FILE@,$PKG_STUB_LIB_FILE,;t t +s,@PKG_STUB_SOURCES@,$PKG_STUB_SOURCES,;t t +s,@PKG_STUB_OBJECTS@,$PKG_STUB_OBJECTS,;t t +s,@PKG_TCL_SOURCES@,$PKG_TCL_SOURCES,;t t +s,@PKG_HEADERS@,$PKG_HEADERS,;t t +s,@PKG_INCLUDES@,$PKG_INCLUDES,;t t +s,@PKG_LIBS@,$PKG_LIBS,;t t +s,@PKG_CFLAGS@,$PKG_CFLAGS,;t t +s,@TCL_VERSION@,$TCL_VERSION,;t t +s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t +s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t +s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t +s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t +s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t +s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t +s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t +s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t +s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t +s,@CLEANFILES@,$CLEANFILES,;t t +s,@TCL_LIBS@,$TCL_LIBS,;t t +s,@TCL_DEFS@,$TCL_DEFS,;t t +s,@TCL_EXTRA_CFLAGS@,$TCL_EXTRA_CFLAGS,;t t +s,@TCL_LD_FLAGS@,$TCL_LD_FLAGS,;t t +s,@TCL_SHLIB_LD_LIBS@,$TCL_SHLIB_LD_LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@EGREP@,$EGREP,;t t +s,@MATH_LIBS@,$MATH_LIBS,;t t +s,@TCL_INCLUDES@,$TCL_INCLUDES,;t t +s,@TCL_TOP_DIR_NATIVE@,$TCL_TOP_DIR_NATIVE,;t t +s,@TCL_THREADS@,$TCL_THREADS,;t t +s,@SHARED_BUILD@,$SHARED_BUILD,;t t +s,@AR@,$AR,;t t +s,@CELIB_DIR@,$CELIB_DIR,;t t +s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t +s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t +s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t +s,@STLIB_LD@,$STLIB_LD,;t t +s,@SHLIB_LD@,$SHLIB_LD,;t t +s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t +s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t +s,@LD_LIBRARY_PATH_VAR@,$LD_LIBRARY_PATH_VAR,;t t +s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t +s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t +s,@TCL_DBGX@,$TCL_DBGX,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@target@,$target,;t t +s,@target_cpu@,$target_cpu,;t t +s,@target_vendor@,$target_vendor,;t t +s,@target_os@,$target_os,;t t +s,@subdirs@,$subdirs,;t t +s,@EXP_BUILD_LIB_SPEC@,$EXP_BUILD_LIB_SPEC,;t t +s,@EXP_CC_SEARCH_FLAGS@,$EXP_CC_SEARCH_FLAGS,;t t +s,@SETUID@,$SETUID,;t t +s,@SETPGRP_VOID@,$SETPGRP_VOID,;t t +s,@DEFAULT_STTY_ARGS@,$DEFAULT_STTY_ARGS,;t t +s,@TCL_DL_LIBS@,$TCL_DL_LIBS,;t t +s,@TCL_CC_SEARCH_FLAGS@,$TCL_CC_SEARCH_FLAGS,;t t +s,@PKG_SOURCES@,$PKG_SOURCES,;t t +s,@PKG_OBJECTS@,$PKG_OBJECTS,;t t +s,@MAKE_LIB@,$MAKE_LIB,;t t +s,@MAKE_SHARED_LIB@,$MAKE_SHARED_LIB,;t t +s,@MAKE_STATIC_LIB@,$MAKE_STATIC_LIB,;t t +s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t +s,@RANLIB_STUB@,$RANLIB_STUB,;t t +s,@VC_MANIFEST_EMBED_DLL@,$VC_MANIFEST_EMBED_DLL,;t t +s,@VC_MANIFEST_EMBED_EXE@,$VC_MANIFEST_EMBED_EXE,;t t +s,@TCLSH_PROG@,$TCLSH_PROG,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + default ) chmod +x ${srcdir}/install-sh ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d $srcdir/$ac_dir || continue + + { echo "$as_me:$LINENO: configuring in $ac_dir" >&5 +echo "$as_me: configuring in $ac_dir" >&6;} + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + cd $ac_dir + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'" + elif test -f $ac_srcdir/configure; then + ac_sub_configure="$SHELL '$ac_srcdir/configure'" + elif test -f $ac_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 +echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file=$ac_top_builddir$cache_file ;; + esac + + { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval $ac_sub_configure $ac_sub_configure_args \ + --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir || + { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 +echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} + { (exit 1); exit 1; }; } + fi + + cd $ac_popdir + done +fi + diff --git a/configure.in b/configure.in new file mode 100755 index 0000000..fcb6c06 --- /dev/null +++ b/configure.in @@ -0,0 +1,1059 @@ +dnl +dnl Process this file with autoconf to produce a configure script. +dnl +AC_REVISION($Id: configure.in,v 5.80 2010/08/27 21:51:53 hobbs Exp $) + +AC_INIT([expect],[5.45]) + +TEA_INIT([3.9]) + +AC_CONFIG_AUX_DIR(tclconfig) + +#-------------------------------------------------------------------- +# Configure script for package 'Expect'. +# TEA compliant. +#-------------------------------------------------------------------- + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + +TEA_PATH_TCLCONFIG +TEA_LOAD_TCLCONFIG + +# expectk has been removed from the distribution as Tcl has supported +# dynamic extensions everywhere for a while. We still allow 'expect' +# to be built for the die-hard users, but expectk is just wish with +# package require Expect +if test "${with_tk+set}" = set ; then + AC_MSG_WARN([With Tk request ignored - use package require Tk & Expect]) +fi + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + +TEA_PREFIX + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create +# the basic setup necessary to compile executables. +#----------------------------------------------------------------------- + +TEA_SETUP_COMPILER + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + +#TEA_PUBLIC_TCL_HEADERS +TEA_PRIVATE_TCL_HEADERS + +#-------------------------------------------------------------------- +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + +TEA_ADD_CLEANFILES([pkgIndex.tcl]) + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# So far only Tcl responds to this one. +# +# Hook for when threading is supported in Expect. The --enable-threads +# flag currently has no effect. +#------------------------------------------------------------------------ + +TEA_ENABLE_THREADS + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + +TEA_ENABLE_SHARED + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + +TEA_CONFIG_CFLAGS + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + +TEA_ENABLE_SYMBOLS + +#-------------------------------------------------------------------- +# Everyone should be linking against the Tcl stub library. If you +# can't for some reason, remove this definition. If you aren't using +# stubs, you also need to modify the SHLIB_LD_LIBS setting below to +# link against the non-stubbed Tcl library. +#-------------------------------------------------------------------- + +AC_DEFINE(USE_TCL_STUBS) +AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) + +#------------------------------------------------------------------------- +# Check for system header files. +#------------------------------------------------------------------------- + +AC_CHECK_HEADER(sys/select.h, AC_DEFINE(HAVE_SYS_SELECT_H)) +AC_CHECK_HEADER(sys/sysmacros.h, AC_DEFINE(HAVE_SYSMACROS_H)) + +# Oddly, some systems have stdarg but don't support prototypes +# Tcl avoids the whole issue by not using stdarg on UNIX at all! + +dnl AC_CHECK_HEADER(stdarg.h, AC_DEFINE(HAVE_STDARG_H)) + +AC_CHECK_HEADER(varargs.h, AC_DEFINE(HAVE_VARARGS_H)) + +# If no stropts.h, then the svr4 implementation is broken. +# At least it is on my Debian "potato" system. - Rob Savoye + +AC_CHECK_HEADER(sys/stropts.h, AC_DEFINE(HAVE_STROPTS_H), svr4_ptys_broken=1) +AC_CHECK_HEADER(sys/sysconfig.h, AC_DEFINE(HAVE_SYSCONF_H)) +AC_CHECK_HEADER(sys/fcntl.h, AC_DEFINE(HAVE_SYS_FCNTL_H)) +AC_CHECK_HEADER(sys/ptem.h, AC_DEFINE(HAVE_SYS_PTEM_H)) +AC_CHECK_HEADER(sys/strredir.h, AC_DEFINE(HAVE_STRREDIR_H)) +AC_CHECK_HEADER(sys/strpty.h, AC_DEFINE(HAVE_STRPTY_H)) + +AC_MSG_CHECKING([for sys/bsdtypes.h]) +if test "ISC_${ISC}" = "ISC_1" ; then + AC_MSG_RESULT(yes) + # if on ISC 1, we need <sys/bsdtypes.h> to get FD_SET macros + AC_HAVE_HEADERS(sys/bsdtypes.h) +else + AC_MSG_RESULT(no) +fi + +#------------------------------------------------------------------------- +# What type do signals return? +#------------------------------------------------------------------------- + +AC_TYPE_SIGNAL + +#------------------------------------------------------------------------- +# Find out all about time handling differences. +#------------------------------------------------------------------------- + +TEA_TIME_HANDLER + +#-------------------------------------------------------------------- +# The check below checks whether <sys/wait.h> defines the type +# "union wait" correctly. It's needed because of weirdness in +# HP-UX where "union wait" is defined in both the BSD and SYS-V +# environments. Checking the usability of WIFEXITED seems to do +# the trick. +#-------------------------------------------------------------------- + +AC_MSG_CHECKING([union wait]) +AC_CACHE_VAL(tcl_cv_union_wait, + AC_TRY_LINK([#include <sys/types.h> +#include <sys/wait.h>], [ +union wait x; +WIFEXITED(x); /* Generates compiler error if WIFEXITED uses an int. */ + ], tcl_cv_union_wait=yes, tcl_cv_union_wait=no)) +AC_MSG_RESULT($tcl_cv_union_wait) +if test $tcl_cv_union_wait = no; then + AC_DEFINE(NO_UNION_WAIT) +fi + +###################################################################### +# required by Sequent ptx2 + +AC_CHECK_FUNC(gethostname, gethostname=1 , gethostname=0) +if test $gethostname -eq 0 ; then + AC_CHECK_LIB(inet, gethostname, LIBS="$LIBS -linet") +fi + +###################################################################### +# required by Fischman's ISC 4.0 + +AC_CHECK_FUNC(socket, socket=1 , socket=0) +if test $socket -eq 0 ; then + AC_CHECK_LIB(inet, socket, LIBS="$LIBS -linet") +fi + +###################################################################### + +AC_CHECK_FUNC(select, select=1 , select=0) +if test $select -eq 0 ; then + AC_CHECK_LIB(inet, select, LIBS="$LIBS -linet") +fi + +###################################################################### + +AC_CHECK_FUNC(getpseudotty, getpseudotty=1 , getpseudotty=0) +if test $getpseudotty -eq 0 ; then + AC_CHECK_LIB(seq, getpseudotty) +fi + +###################################################################### +# Check for FreeBSD/NetBSD openpty() +unset ac_cv_func_openpty + +AC_CHECK_FUNC(openpty, AC_DEFINE(HAVE_OPENPTY) openpty=1 , openpty=0) +if test $openpty -eq 0 ; then + AC_CHECK_LIB(util, openpty, [ + # we only need to define OPENPTY once, but since we are overriding + # the default behavior, we must also handle augment LIBS too. + # This needn't be done in the 2nd and 3rd tests. + AC_DEFINE(HAVE_OPENPTY) + LIBS="$LIBS -lutil" + ]) +fi + +###################################################################### +# End of library/func checking +###################################################################### + +# Hand patches to library/func checking. +dnl From: Michael Kuhl <mkuhl@legato.com> +dnl To get expect to compile on a Sequent NUMA-Q running DYNIX/ptx v4.4.2. + +AC_MSG_CHECKING([if running Sequent running SVR4]) +if test "$host_alias" = "i386-sequent-sysv4" ; then + LIBS="-lnsl -lsocket -lm" + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- +# From here on comes original expect configure code. +# At the end we will have another section of TEA 3.2 code. +# +# Note specialities +# +# - Runs a sub configure (Dbgconfigure) for the expect tcl debugger +# +#-------------------------------------------------------------------- +#-------------------------------------------------------------------- + +dnl AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..) +AC_CANONICAL_SYSTEM + +# If `configure' is invoked (in)directly via `make', ensure that it +# encounters no `make' conflicts. +# + +dnl unset MFLAGS MAKEFLAGS +MFLAGS= +MAKEFLAGS= + +# An explanation is in order for the strange things going on with the +# various LIBS. There are three separate definitions for LIBS. The +# reason is that some systems require shared libraries include +# references to their dependent libraries, i.e., any additional +# libraries that must be linked to. And some systems get upset if the +# references are repeated on the link line. So therefore, we create +# one for Expect, one for Expect and Tcl, and one for building Expect's own +# shared library. Tcl's tclConfig.sh insists that any shared libs +# that it "helps" build must pass the libraries as LIBS (see comment +# near end of this configure file). I would do but since we're close +# to hitting config's max symbols, we take one short cut and pack the +# LIBS into EXP_SHLIB_LD_LIBS (which is basically what Tcl wants to do +# for us). The point, however, is that there's no separate LIBS or +# EXP_LIBS symbol passed out of configure. One additional point for +# confusion is that LIBS is what configure uses to do all library +# tests, so we have to swap definitions of LIBS periodically. When we +# are swapping out the one for Expect's shared library, we save it in +# EXP_LIBS. Sigh. + +eval "LIBS=\"$TCL_LIBS\"" + +if test "${with_tcl+set}" = set ; then + case "${with_tcl}" in + ..*) + AC_MSG_WARN([Specify absolute path to --with-tcl for subdir configuration]) + ;; + esac +fi + +# these are the other subdirectories we need to configure +AC_CONFIG_SUBDIRS(testsuite) + +AC_TYPE_PID_T + +AC_MSG_CHECKING([if running Mach]) +mach=0 +case "${host}" in + # Both Next and pure Mach behave identically with respect + # to a few things, so just lump them together as "mach" + *-*-mach*) mach=1 ;; + *-*-next*) mach=1 ; next=1 ;; +esac + +if test $mach -eq 1 ; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([if running MachTen]) +# yet another Mach clone +if test -r /MachTen ; then + AC_MSG_RESULT(yes) + mach=1 +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([if on Pyramid]) +if test -r /bin/pyr ; then + AC_MSG_RESULT(yes) + pyr=1 +else + AC_MSG_RESULT(no) + pyr=0 +fi + +AC_MSG_CHECKING([if on Apollo]) +if test -r /usr/apollo/bin ; then + AC_MSG_RESULT(yes) + apollo=1 +else + AC_MSG_RESULT(no) + apollo=0 +fi + +AC_MSG_CHECKING([if on Interactive]) +if test "x`(uname -s) 2>/dev/null`" = xIUNIX; then + AC_MSG_RESULT(yes) + iunix=1 +else + AC_MSG_RESULT(no) + iunix=0 +fi + +AC_MSG_CHECKING([stty to use]) +if test -r /usr/local/bin/stty ; then + STTY_BIN=/usr/local/bin/stty +else + STTY_BIN=/bin/stty +fi +AC_MSG_RESULT($STTY_BIN) + +AC_MSG_CHECKING([if stty reads stdout]) + +# On some systems stty can't be run in the background (svr4) or get it +# wrong because they fail to complain (next, mach), so don't attempt +# the test on some systems. + +stty_reads_stdout="" +case "${host}" in + *-*-solaris*) stty_reads_stdout=0 ;; + *-*-irix*) stty_reads_stdout=0 ;; + *-*-sco3.2v[[45]]*) stty_reads_stdout=1 ;; + i[[3456]]86-*-sysv4.2MP) stty_reads_stdout=0 ;; + *-*-linux*) stty_reads_stdout=0 ;; + # Not sure about old convex but 5.2 definitely reads from stdout + c[[12]]-*-*) stty_reads_stdout=1 ;; + *-*-aix[[34]]*) stty_reads_stdout=0 ;; + *-*-hpux9*) stty_reads_stdout=0 ;; + *-*-hpux10*) stty_reads_stdout=0 ;; + *-*-osf[[234]]*) stty_reads_stdout=0 ;; + *-*-ultrix4.4) stty_reads_stdout=0 ;; + *-*-dgux*) stty_reads_stdout=0 ;; +esac + +if test $mach -eq 1 ; then + stty_reads_stdout=1 +fi +if test $apollo -eq 1 ; then + stty_reads_stdout=1 +fi +if test $pyr -eq 1 ; then + stty_reads_stdout=1 +fi + +# if we still don't know, test +if test x"${stty_reads_stdout}" = x"" ; then + $STTY_BIN > /dev/null 2> /dev/null ; a=$? + $STTY_BIN < /dev/tty > /dev/null 2> /dev/null ; b=$? + if test $a -ne 0 -a $b -ne 0; then + stty_reads_stdout=1 + else + stty_reads_stdout=0 + fi +fi + +if test ${stty_reads_stdout} -eq 1 ; then + AC_MSG_RESULT(yes) + AC_DEFINE(STTY_READS_STDOUT) +else + AC_MSG_RESULT(no) +fi + +# Solaris 2.4 and later requires __EXTENSIONS__ in order to see all sorts +# of traditional but nonstandard stuff in header files. +AC_MSG_CHECKING([if running Solaris]) +solaris=0 +case "${host}" in + *-*-solaris*) solaris=1;; +esac + +if test $solaris -eq 1 ; then + AC_MSG_RESULT(yes) + AC_DEFINE(SOLARIS) +else + AC_MSG_RESULT(no) +fi + +# On Interactive UNIX, -Xp must be added to LIBS in order to find strftime. +# This test should really be done by Tcl. So just check Tcl's definition. +# If defective, add to all three LIBS. (It's not actually necessary for +# EXP_LIBS since -Xp will just be ignored the way that EXP_LIBS is used in +# the Makefile, but we include it for consistency.) + +if test $iunix -eq 1 ; then + AC_CHECK_FUNC(strftime, , [ + LIBS="${LIBS} -Xp" + ]) +fi + +###################################################################### +# +# Look for various header files +# + +# +# Look for functions that may be missing +# +dnl AC_CHECK_FUNC(memcpy, AC_DEFINE(HAVE_MEMCPY)) +AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE)) +AC_CHECK_FUNC(sysconf, AC_DEFINE(HAVE_SYSCONF)) +AC_CHECK_FUNC(strftime, AC_DEFINE(HAVE_STRFTIME)) +AC_CHECK_FUNC(strchr, AC_DEFINE(HAVE_STRCHR)) +AC_CHECK_FUNC(timezone, AC_DEFINE(HAVE_TIMEZONE)) +AC_CHECK_FUNC(siglongjmp, AC_DEFINE(HAVE_SIGLONGJMP)) + +# dnl check for memcpy by hand +# because Unixware 2.0 handles it specially and refuses to compile +# autoconf's automatic test that is a call with no arguments +AC_MSG_CHECKING([for memcpy]) +AC_TRY_LINK(,[ +char *s1, *s2; +memcpy(s1,s2,0); +], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MEMCPY) + , + AC_MSG_RESULT(no) +) + +# Some systems only define WNOHANG if _POSIX_SOURCE is defined +# The following merely tests that sys/wait.h can be included +# and if so that WNOHANG is not defined. The only place I've +# seen this is ISC. +AC_MSG_CHECKING([if WNOHANG requires _POSIX_SOURCE]) +AC_TRY_RUN([ +#include <sys/wait.h> +main() { +#ifndef WNOHANG + return 0; +#else + return 1; +#endif +}], + AC_MSG_RESULT(yes) + AC_DEFINE(WNOHANG_REQUIRES_POSIX_SOURCE) +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +AC_MSG_CHECKING([if any value exists for WNOHANG]) +rm -rf wnohang +AC_TRY_RUN([ +#include <stdio.h> +#include <sys/wait.h> +main() { +#ifdef WNOHANG + FILE *fp = fopen("wnohang","w"); + fprintf(fp,"%d",WNOHANG); + fclose(fp); + return 0; +#else + return 1; +#endif +}], + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(WNOHANG_BACKUP_VALUE, `cat wnohang`) + rm -f wnohang +, + AC_MSG_RESULT(no) + AC_DEFINE(WNOHANG_BACKUP_VALUE, 1) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +# +# check how signals work +# + +# Check for the data type of the mask used in select(). +# This picks up HP braindamage which defines fd_set and then +# proceeds to ignore it and use int. +# Pattern matching on int could be loosened. +# Can't use ac_header_egrep since that doesn't see prototypes with K&R cpp. +AC_MSG_CHECKING([mask type of select]) +if egrep "select\(size_t, int" /usr/include/sys/time.h >/dev/null 2>&1; then + AC_MSG_RESULT(int) + AC_DEFINE(SELECT_MASK_TYPE, int) +else + AC_MSG_RESULT(none) + AC_DEFINE(SELECT_MASK_TYPE, fd_set) +fi + +dnl # Check for the data type of the function used in signal(). This +dnl # must be before the test for rearming. +dnl # echo checking return type of signal handlers +dnl AC_HEADER_EGREP([(void|sighandler_t).*signal], signal.h, retsigtype=void,AC_DEFINE(RETSIGTYPE, int) retsigtype=int) + +# FIXME: check if alarm exists +AC_MSG_CHECKING([if signals need to be re-armed]) +AC_TRY_RUN([ +#include <signal.h> +#define RETSIGTYPE $retsigtype + +int signal_rearms = 0; + +RETSIGTYPE +child_sigint_handler(n) +int n; +{ +} + +RETSIGTYPE +parent_sigint_handler(n) +int n; +{ +signal_rearms++; +} + +main() +{ + signal(SIGINT,parent_sigint_handler); + + if (0 == fork()) { + signal(SIGINT,child_sigint_handler); + kill(getpid(),SIGINT); + kill(getpid(),SIGINT); + kill(getppid(),SIGINT); + } else { + int status; + + wait(&status); + unlink("core"); + exit(signal_rearms); + } +}], + AC_MSG_RESULT(yes) + AC_DEFINE(REARM_SIG) +, + AC_MSG_RESULT(no) +, AC_MSG_WARN([Expect can't be cross compiled]) +) + +# HPUX7 has trouble with the big cat so split it +# Owen Rees <rtor@ansa.co.uk> 29Mar93 +SEDDEFS="${SEDDEFS}CONFEOF +cat >> conftest.sed <<CONFEOF +" +# + +# There are multiple versions of getpty, alas. +# I don't remember who has the first one, but Convex just added one +# so check for it. Unfortunately, there is no header so the only +# reasonable way to make sure is to look it we are on a Convex. +AC_MSG_CHECKING([if on Convex]) +convex=0 +case "${host}" in + c[[12]]-*-*) convex=1;; +esac + +if test $convex -eq 1 ; then + AC_MSG_RESULT(yes) + AC_DEFINE(CONVEX) +else + AC_MSG_RESULT(no) +fi + + +AC_MSG_CHECKING([if on HP]) +if test "x`(uname) 2>/dev/null`" = xHP-UX; then + AC_MSG_RESULT(yes) + hp=1 +else + AC_MSG_RESULT(no) + hp=0 +fi + +AC_MSG_CHECKING([sane default stty arguments]) +DEFAULT_STTY_ARGS="sane" + +if test $mach -eq 1 ; then + DEFAULT_STTY_ARGS="cooked" +fi + +if test $hp -eq 1 ; then + DEFAULT_STTY_ARGS="sane kill " +fi + +AC_MSG_RESULT($DEFAULT_STTY_ARG) + +# Look for various features to determine what kind of pty +# we have. For some weird reason, ac_compile_check would not +# work, but ac_test_program does. +# +AC_MSG_CHECKING([for HP style pty allocation]) +# following test fails on DECstations and other things that don't grok -c +# but that's ok, since they don't have PTYMs anyway +if test -r /dev/ptym/ptyp0 2>/dev/null ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTYM) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([for HP style pty trapping]) +AC_HEADER_EGREP([struct.*request_info], sys/ptyio.h, + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTYTRAP) +, + AC_MSG_RESULT(no) +) + +AC_MSG_CHECKING([for AIX new-style pty allocation]) +if test -r /dev/ptc -a -r /dev/pts ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTC_PTS) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([for SGI old-style pty allocation]) +if test -r /dev/ptc -a ! -r /dev/pts ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTC) +else + AC_MSG_RESULT(no) +fi + +# On SCO OpenServer, two types of ptys are available: SVR4 streams and c-list. +# The library routines to open the SVR4 ptys are broken on certain systems and +# the SCO command to increase the number of ptys only configure c-list ones +# anyway. So we chose these, which have a special numbering scheme. +# +AC_MSG_CHECKING([for SCO style pty allocation]) +sco_ptys="" +case "${host}" in + *-sco3.2v[[45]]*) sco_clist_ptys=1 svr4_ptys_broken=1;; +esac + +if test x"${sco_clist_ptys}" != x"" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SCO_CLIST_PTYS) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([for SVR4 style pty allocation]) +if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTMX) + # aargg. Some systems need libpt.a to use /dev/ptmx + AC_CHECK_LIB(pt, libpts="-lpt", libpts="") + AC_CHECK_FUNC(ptsname, , LIBS="${LIBS} $libpts") +else + AC_MSG_RESULT(no) +fi + +# In OSF/1 case, SVR4 are somewhat different. +# Gregory Depp <depp@osf.org> 17Aug93 +AC_MSG_CHECKING([for OSF/1 style pty allocation]) +if test -r /dev/ptmx_bsd ; then + AC_DEFINE(HAVE_PTMX_BSD) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +tcgetattr=0 +tcsetattr=0 +AC_CHECK_FUNC(tcgetattr, tcgetattr=1) +AC_CHECK_FUNC(tcsetattr, tcsetattr=1) +if test $tcgetattr -eq 1 -a $tcsetattr -eq 1 ; then + AC_DEFINE(HAVE_TCSETATTR) + AC_DEFINE(POSIX) +fi + +# first check for the pure bsd +AC_MSG_CHECKING([for struct sgttyb]) +AC_TRY_RUN([ +#include <sgtty.h> +main() +{ + struct sgttyb tmp; + exit(0); +}], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SGTTYB) + PTY_TYPE=sgttyb +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +# mach systems have include files for unimplemented features +# so avoid doing following test on those systems +if test $mach -eq 0 ; then + + # next check for the older style ttys + # note that if we detect termio.h (only), we still set PTY_TYPE=termios + # since that just controls which of pty_XXXX.c file is use and + # pty_termios.c is set up to handle pty_termio. + AC_MSG_CHECKING([for struct termio]) + AC_TRY_RUN([#include <termio.h> + main() + { + struct termio tmp; + exit(0); + }], + AC_DEFINE(HAVE_TERMIO) + PTY_TYPE=termios + AC_MSG_RESULT(yes) +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + + # now check for the new style ttys (not yet posix) + AC_MSG_CHECKING([for struct termios]) + AC_TRY_RUN([ + /* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +# ifdef HAVE_INTTYPES_H +# include <inttypes.h> +# endif +# include <termios.h> + main() + { + struct termios tmp; + exit(0); + }], + AC_DEFINE(HAVE_TERMIOS) + PTY_TYPE=termios + AC_MSG_RESULT(yes) + , + AC_MSG_RESULT(no) + , + AC_MSG_ERROR([Expect can't be cross compiled]) + ) +fi + +AC_MSG_CHECKING([if TCGETS or TCGETA in termios.h]) +AC_TRY_RUN([ +/* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#include <termios.h> +main() { +#if defined(TCGETS) || defined(TCGETA) + return 0; +#else + return 1; +#endif +}], + AC_DEFINE(HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H) + AC_MSG_RESULT(yes) +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +AC_MSG_CHECKING([if TIOCGWINSZ in termios.h]) +AC_TRY_RUN([ +/* including termios.h on Solaris 5.6 fails unless inttypes.h included */ +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#include <termios.h> +main() { +#ifdef TIOCGWINSZ + return 0; +#else + return 1; +#endif +}], + AC_DEFINE(HAVE_TIOCGWINSZ_IN_TERMIOS_H) + AC_MSG_RESULT(yes) +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +# finally check for Cray style ttys +AC_MSG_CHECKING([for Cray-style ptys]) +SETUID=":" +AC_TRY_RUN([ +main(){ +#ifdef CRAY + return 0; +#else + return 1; +#endif +} +], + PTY_TYPE=unicos + SETUID="chmod u+s" + AC_MSG_RESULT(yes) +, + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + +# +# Check for select and/or poll. If both exist, we prefer select. +# if neither exists, define SIMPLE_EVENT. +# +select=0 +poll=0 +unset ac_cv_func_select +AC_CHECK_FUNC(select, select=1) +AC_CHECK_FUNC(poll, poll=1) +AC_MSG_CHECKING([event handling]) +if test $select -eq 1 ; then + EVENT_TYPE=select + EVENT_ABLE=event + AC_MSG_RESULT(via select) +elif test $poll -eq 1 ; then + EVENT_TYPE=poll + EVENT_ABLE=event + AC_MSG_RESULT(via poll) +else + EVENT_TYPE=simple + EVENT_ABLE=noevent + AC_MSG_RESULT(none) + AC_DEFINE(SIMPLE_EVENT) +fi + +AC_HAVE_FUNCS(_getpty) +AC_HAVE_FUNCS(getpty) + +# following test sets SETPGRP_VOID if setpgrp takes 0 args, else takes 2 +AC_FUNC_SETPGRP + +# +# check for timezones +# +AC_MSG_CHECKING([for SV-style timezone]) +AC_TRY_RUN([ +extern char *tzname[2]; +extern int daylight; +main() +{ + int *x = &daylight; + char **y = tzname; + + exit(0); +}], + AC_DEFINE(HAVE_SV_TIMEZONE) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no) +, + AC_MSG_ERROR([Expect can't be cross compiled]) +) + + +# Following comment stolen from Tcl's configure.in: +# Note: in the following variable, it's important to use the absolute +# path name of the Tcl directory rather than "..": this is because +# AIX remembers this path and will attempt to use it at run-time to look +# up the Tcl library. + +PACKAGE_VERSION_NODOTS="`echo $PACKAGE_VERSION | sed -e 's/\.//g'`" + +if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + EXP_LIB_VERSION=$PACKAGE_VERSION +else + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi +if test $iunix -eq 1 ; then + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi + +# also remove dots on systems that don't support filenames > 14 +# (are there systems which support shared libs and restrict filename lengths!?) +AC_SYS_LONG_FILE_NAMES +if test $ac_cv_sys_long_file_names = no; then + EXP_LIB_VERSION=$PACKAGE_VERSION_NODOTS +fi + +if test "$FRAMEWORK_BUILD" = "1" ; then + EXP_BUILD_LIB_SPEC="-F`pwd` -framework Expect" + EXP_LIB_SPEC="-framework Expect" + EXP_LIB_FILE="Expect" + AC_DEFINE(EXP_FRAMEWORK) +else + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + EXP_LIB_FLAG="-lexpect${EXP_LIB_VERSION}" + else + EXP_LIB_FLAG="-lexpect`echo ${EXP_LIB_VERSION} | tr -d .`" + fi + EXP_BUILD_LIB_SPEC="-L`pwd` ${EXP_LIB_FLAG}" + EXP_LIB_SPEC="-L${libdir} ${EXP_LIB_FLAG}" +fi + +#-------------------------------------------------------------------- +# This section is based on analogous thing in Tk installation. - DEL +# Various manipulations on the search path used at runtime to +# find shared libraries: +# 2. On systems such as AIX and Ultrix that use "-L" as the +# search path option, colons cannot be used to separate +# directories from each other. Change colons to " -L". +# 3. Create two sets of search flags, one for use in cc lines +# and the other for when the linker is invoked directly. In +# the second case, '-Wl,' must be stripped off and commas must +# be replaced by spaces. +#-------------------------------------------------------------------- + +LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}/${PACKAGE_NAME}${PACKAGE_VERSION}' + +# If Tcl and Expect are installed in different places, adjust the library +# search path to reflect this. + +if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib" +fi + +if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then + LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'` +fi + +# The eval below is tricky! It *evaluates* the string in +# ..._CC_SEARCH_FLAGS, which causes a substitution of the +# variable LIB_RUNTIME_DIR. + +eval "EXP_CC_SEARCH_FLAGS=\"$TCL_CC_SEARCH_FLAGS\"" + +# now broken out into EXP_AND_TCL_LIBS. Had to do this +# in order to avoid repeating lib specs to which some systems object. + +LIBS="$LIBS $LD_SEARCH_FLAGS" + +# +# Set up makefile substitutions +# +AC_SUBST(EXP_BUILD_LIB_SPEC) +AC_SUBST(EXP_CC_SEARCH_FLAGS) +AC_SUBST(SETUID) +AC_SUBST(SETPGRP_VOID) +AC_SUBST(DEFAULT_STTY_ARGS) +# Expect uses these from tclConfig.sh to make the main executable +AC_SUBST(TCL_DL_LIBS) +AC_SUBST(TCL_CC_SEARCH_FLAGS) + +#-------------------------------------------------------------------- +# More TEA code based on data we got from the original expect +# configure code. +#-------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + +TEA_ADD_SOURCES([ + exp_command.c expect.c exp_inter.c exp_regexp.c exp_tty.c + exp_log.c exp_main_sub.c exp_pty.c exp_trap.c exp_strf.c + exp_console.c exp_glob.c exp_win.c exp_clib.c exp_closetcl.c + exp_memmove.c exp_tty_comm.c exp_chan.c Dbg.c +]) + +# Variant sources. Comments in the Makefile indicate that the +# event_type/able stuff can be overidden in the Makefile, and should +# be for particular systems. IMHO this requires a configure option. +# +# See at the end, where we select the sources based on the collect +# information. + +TEA_ADD_SOURCES([ + pty_${PTY_TYPE}.c + exp_${EVENT_TYPE}.c + exp_${EVENT_ABLE}.c +]) + +TEA_ADD_HEADERS([expect.h expect_tcl.h expect_comm.h tcldbg.h]) + +TEA_ADD_INCLUDES([-I.]) +TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}`\"]) + +TEA_ADD_LIBS([]) +TEA_ADD_CFLAGS([-DTCL_DEBUGGER -DUSE_NON_CONST]) +TEA_ADD_CFLAGS([-DSCRIPTDIR=\\\"\${DESTDIR}\${prefix}/lib/\${PKG_DIR}\\\"]) +TEA_ADD_CFLAGS([-DEXECSCRIPTDIR=\\\"\${DESTDIR}\${pkglibdir}\\\"]) +TEA_ADD_CFLAGS([-DSTTY_BIN=\\\"${STTY_BIN}\\\"]) +TEA_ADD_CFLAGS([-DDFLT_STTY=\"\\\"$DEFAULT_STTY_ARGS\\\"\"]) + +TEA_ADD_STUB_SOURCES([]) +TEA_ADD_TCL_SOURCES([]) + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + +TEA_MAKE_LIB + +#-------------------------------------------------------------------- +# Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl +# file during the install process. Don't run the TCLSH_PROG through +# ${CYGPATH} because it's being used directly by make. +# Require that we use a tclsh shell version 8.2 or later since earlier +# versions have bugs in the pkg_mkIndex routine. +# Add WISH as well if this is a Tk extension. +#-------------------------------------------------------------------- + +TEA_PROG_TCLSH + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the Makefile. +# You may alternatively have a special pkgIndex.tcl.in or other files +# which require substituting th AC variables in. Include these here. +#-------------------------------------------------------------------- + +touch expect_cf.h +AC_OUTPUT([Makefile], chmod +x ${srcdir}/install-sh) diff --git a/example/Makefile b/example/Makefile new file mode 100644 index 0000000..be32170 --- /dev/null +++ b/example/Makefile @@ -0,0 +1,63 @@ +EXPVERSION = 5.31 + +CC = gcc +CPLUSPLUS = g++ +CPLUSPLUSLIBDIR = -L/depot/gnu/arch/lib +CPLUSPLUSLIB = -lg++ + +CFLAGS = -g -I.. +LIBEXPECT = -L.. -lexpect$(EXPVERSION) + +LIBS = $(LIBEXPECT) -lm + +SCRIPTS = su2 noidle script.exp bonfield.exp + +all: chesslib chesslib2 chesslib++ + +# this can be compiled with either cc or gcc +chesslib: chesslib.o + $(CC) -g -o chesslib chesslib.o $(LIBS) + +# this can be compiled with either cc or gcc +chesslib2: chesslib2.o + $(CC) -g -o chesslib2 chesslib2.o $(LIBS) + +# this is compiled with c++ +chesslib++: chesslib++.o + $(CPLUSPLUS) -g -o chesslib++ chesslib++.o $(LIBS) \ + $(CPLUSPLUSLIBDIR) $(CPLUSPLUSLIB) + +chesslib++.o: chesslib++.c + $(CPLUSPLUS) -c $(CFLAGS) chesslib++.c + +unbuffer-standalone: unbuffer.o + $(CC) -g -o unbuffer-standalone unbuffer.o $(LIBS) + +printvars: printvars.o + $(CC) -o printvars printvars.o $(LIBS) + +ftplib: ftplib.o + $(CC) -g -o ftplib ftplib.o $(LIBS) + +match_max: match_max.o + $(CC) -g -o match_max match_max.o $(LIBS) + +jaj1: jaj1.o + $(CC) -g -o jaj1 jaj1.o $(LIBS) + +jaj2: jaj2.o + $(CC) -g -o jaj2 jaj2.o $(LIBS) + +# wrap up password-generation examples +passgen: + shar passgen.README tkpasswd mkpasswd mkpasswd.man > /tmp/passgen + +cleanup: + rm -f expect devtty exho dumb test.raw test.results test.tmp + +# copy some contributed scripts over to public-accessible directory +SCRIPTDIR = ~ftp/pub/expect/scripts +ftp: + rcp README.scripts durer:$(SCRIPTDIR)/README + rcp $(SCRIPTS) durer:$(SCRIPTDIR) + rsh durer ls -l $(SCRIPTDIR) diff --git a/example/README b/example/README new file mode 100644 index 0000000..77081be --- /dev/null +++ b/example/README @@ -0,0 +1,144 @@ +This file is example/README. It contains brief descriptions of the +examples in this directory. Also listed are scripts from the Expect +archive at ftp.cme.nist.gov (See Expect's README for how to retrieve +these from). You are welcome to send me additional scripts. A number +of Expect scripts are also available in the Tcl archive, available via +anonymous ftp at harbor.ecn.purdue.edu + +Note that on some systems, some of the scripts (notably kibitz and +dislocate) require that Expect be installed. (Merely compiling the +expect binary is not enough.) + +-------------------- +Expect scripts (See next section for example Tk scripts) +-------------------- +Entries marked with "m" have their own man page. +Entries marked with "a" live in the Expect archive (see above). + + archie - mails back response after talking to archie ftp-catalog. + m autoexpect - generate an Expect script from watching a session + autopasswd - runs passwd non-interactively for superuser. + a bc - Uses bc to do arbitrary precision math. + beer.exp - 99 Bottles of Beer On The Wall, Expect-style. + beer.exp.out - sample output from beer.exp (but you really have to + run it to see the timing aspect). + a bonfield.exp - solve Jim Bonfield's puzzle that won the 1991 Obfuscated + C Code contest. + carpal - warn about typing for too long without a break. + chess.exp - has two chess games play each other. + m cryptdir - encrypt all files in a directory. + m decryptdir - decrypt all files in a directory. + m dislocate - allow disconnection/reconnection to background processes. + dvorak - dvorak keyboard. + a eftp - ftp client with miscellaneous frills (also see rftp below). + expectd.proto - telnet daemon. + ftp-inband - does file transfer over telnet, rlogin, etc. + ftp-rfc - retrieve a DoD RFC from uunet via anonymous ftp. + ftp-talk-radio - gets "Internet Talk Radio" files from a host. + gethostbyaddr - translates internet address to name (with a higher + success rate than nslookup). Easier to use, too. + getpassck - test for presence of bug in getpass. + irsh - run interactive commands via rsh + m kibitz - lets two people control a program at the same time. + Lots of uses. I.e., You can help another person remotely. + Can run an editor and log a transcript of a conversation. + a libro-II - connect to Libro-II, the NIST library catalog. + lpunlock - unhangs a printer which says it is "waiting for lock". + a mirror_file - mirror a file from another ftp site, copying file only + if changed. + a mirror_dir - mirror a directory from another ftp site, copying only + files which have changed. + m multixterm - drive several xterms simultaneously. + m mkpasswd - generates good passwords, optionally runs passwd with them. + a mx - return any MX records for the given host. + a noidle - run a shell which avoids being 'autologged out'. + a pager.alpha - sends a message to a (Alpha brand) pager. + a pager.mercury - sends a message to a (Mercury brand) pager. + m passmass - sets passwd on many machines simultaneously. + passwd.html - form to change a login passwd + passwd.cgi - CGI script to respond to passwd.html form + passwdprompt - Prompt from stdin and echo *'s. + a ping-and-page - Ping list of hosts. If any down, page system admin. + read1char - read a single character for the shell, Perl, etc. + reprompt - like timed-read but reprompt after given amount of time. + rlogin-cwd - rlogin giving you same current working directory. + (Compare to telnet-cwd and xrlogin.) + robohunt - plays the game of hunt (from Berkeley). + It's more of a wild player than good, but amusing to watch. + Fun to throw against people who don't know about it. + rogue.exp - finds a good game of rogue. + rftp - recursive ftp (assumes UNIX-style ftpd at other end). + a s-key-rlogin - Automate rlogin (or telnet) using s/key + a scripttoggle - Like UNIX script command, but allow enabling/disabling + of recording. + a slip.shar - scripts to keep your SLIP link alive. + su.exp - start up an 'su' and run the argument. + telnet-cwd - telnet giving you same current working directory. + telnet-in-bg - put telnet (or any program) in bg, saving all remaining + output to a logfile. + a term-rlogin - run Term over rlogin. Good for traversing PPP/SLIP or + firewall rlogin connections. + a term-start - start up Term (a sophisticated UNIX-to-UNIX serial line + handler). + a timed-choice - offer user a timed choice of responses. + timed-read - a timed read for the shell, Perl, etc. Compare with + reprompt example. + m timed-run - run a program for only a given amount of time. + a try-phone-list - automate logging in to remote system, trying numbers + from a list until finding one that works. + m unbuffer - disables output buffering that normally occurs when + programs are redirected. + virterm - example of terminal emulation and expect operations on + character graphics using arrays (compare to term_expect + (below) which uses Tk widget). + vrfy - verifies an email address using SMTP/VRFY to remote site. + a waste-collection - Contact NIST service for hazardous waste pickup. + weather - retrieves weather forecasts. + m xkibitz - similar to kibitz but uses X Window System for handling + communication. Also, allows users to be added dynamically. + xrlogin - rlogin giving you same DISPLAY. (Compare to rlogin-cwd.) + +To run, for example, chess.exp, type: + + expect chess.exp + +If expect is installed and your system supports the #! magic you can +invoke it as: + + chess.exp + +Each of these examples necessarily depends upon other binaries in the +system. For example, chess.exp depends upon the "usual" UNIX chess +program being present. If any of these programs are different, +it may cause the associated script to misbehave. + +Please use the ".exp" extension on scripts that might otherwise have +names that could be confused with the real program, such as "rogue.exp". +Scripts that have unique names do not need the extension, such as "rftp". + +-------------------- +Sample Expectk scripts +-------------------- +Entries marked with "m" have their own man page. + + term_expect - template for doing expect operations on character + graphics. + m tknewsbiff - pops up a window (or plays sounds, etc) when news + arrives in selected newsgroups. + tkpasswd - Tk GUI for changing passwords. + tkterm - Tk terminal emulator in a Tk text widget. + xpstat - provide an X window front end to the xpilot game. + +-------------------- +Sample C and C++ programs that use the Expect library +-------------------- + + chesslib.c - same thing as chess.exp, but in C. + chesslib2.c - ditto, but uses popen and stream-style I/O. + chesslib++.c - ditto, but for C++. + m unbuffer.c - same as unbuffer example but standalone + +You may change the value of CC or CPLUSPLUS in the Makefile, to +compile under gcc or other compilers. However, you may have to edit +the lines defining where the libraries are. + diff --git a/example/archie b/example/archie new file mode 100755 index 0000000..0d5f43f --- /dev/null +++ b/example/archie @@ -0,0 +1,41 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# archie + +# Log in to the archie ftp-catalog at McGill University, and mail back results +# Brian P. Fitzgerald +# Department of Mechanical Engineering +# Rensselaer Polytechnic Institute + +set CINTR \003 ;# ^C +set CSUSP \032 ;# ^Z + +set timeout -1 +spawn telnet quiche.cs.mcgill.ca + +expect_after eof exit ;# archie logs us out if too many people are logged in + +expect { + login: {send archie\r} + "unknown" {exit 1} + "unreachable" {exit 1} +} + +expect "archie>" {send "set pager\r"} +expect "archie>" {send "set maxhits 20\r"} +expect "archie>" {send "set term vt100\r"} +expect "archie>" {send "set sortby time\r"} +expect "archie>" { + send "set mailto [exec whoami]@[exec hostname].[exec domainname]\r" +} + +send_user "type ^C to exit, ^Z to suspend\n" +interact { + -reset $CSUSP {exec kill -STOP [pid]} + $CINTR {exit 0} +} diff --git a/example/autoexpect b/example/autoexpect new file mode 100755 index 0000000..35e57ce --- /dev/null +++ b/example/autoexpect @@ -0,0 +1,348 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# Name: autoexpect - generate an Expect script from watching a session +# +# Description: +# +# Given a program name, autoexpect will run that program. Otherwise +# autoexpect will start a shell. Interact as desired. When done, exit +# the program or shell. Autoexpect will create a script that reproduces +# your interactions. By default, the script is named script.exp. +# See the man page for more info. +# +# Author: Don Libes, NIST +# Date: June 30 1995 +# Version: 1.4b + +set filename "script.exp" +set verbose 1 +set conservative 0 +set promptmode 0 +set option_keys "" + +proc check_for_following {type} { + if {![llength [uplevel set argv]]} { + puts "autoexpect: [uplevel set flag] requires following $type" + exit 1 + } +} + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + if {0==[regexp "^-" $flag]} break + set argv [lrange $argv 1 end] + switch -- $flag \ + "-c" { + set conservative 1 + } "-C" { + check_for_following character + lappend option_keys [lindex $argv 0] ctoggle + set argv [lrange $argv 1 end] + } "-p" { + set promptmode 1 + } "-P" { + check_for_following character + lappend option_keys [lindex $argv 0] ptoggle + set argv [lrange $argv 1 end] + } "-Q" { + check_for_following character + lappend option_keys [lindex $argv 0] quote + set argv [lrange $argv 1 end] + } "-f" { + check_for_following filename + set filename [lindex $argv 0] + set argv [lrange $argv 1 end] + } "-quiet" { + set verbose 0 + } default { + break + } +} + +############################################################# +# Variables Descriptions +############################################################# +# userbuf buffered characters from user +# procbuf buffered characters from process +# lastkey last key pressed by user +# if undefined, last key came from process +# echoing if the process is echoing +############################################################# + +# Handle a character that came from user input (i.e., the keyboard) +proc input {c} { + global userbuf lastkey + + send -- $c + append userbuf $lastkey + set lastkey $c +} + +# Handle a null character from the keyboard +proc input_null {} { + global lastkey userbuf procbuf echoing + + send -null + + if {$lastkey == ""} { + if {$echoing} { + sendcmd "$userbuf" + } + if {$procbuf != ""} { + expcmd "$procbuf" + } + } else { + sendcmd "$userbuf" + if {$echoing} { + expcmd "$procbuf" + sendcmd "$lastkey" + } + } + cmd "send -null" + set userbuf "" + set procbuf "" + set lastkey "" + set echoing 0 +} + +# Handle a character that came from the process +proc output {s} { + global lastkey procbuf userbuf echoing + + send_user -raw -- $s + + if {$lastkey == ""} { + if {!$echoing} { + append procbuf $s + } else { + sendcmd "$userbuf" + expcmd "$procbuf" + set echoing 0 + set userbuf "" + set procbuf $s + } + return + } + + regexp (.)(.*) $s dummy c tail + if {$c == $lastkey} { + if {$echoing} { + append userbuf $lastkey + set lastkey "" + } else { + if {$procbuf != ""} { + expcmd "$procbuf" + set procbuf "" + } + set echoing 1 + } + append procbuf $s + + if {[string length $tail]} { + sendcmd "$userbuf$lastkey" + set userbuf "" + set lastkey "" + set echoing 0 + } + } else { + if {!$echoing} { + expcmd "$procbuf" + } + sendcmd "$userbuf$lastkey" + set procbuf $s + set userbuf "" + set lastkey "" + set echoing 0 + } +} + +# rewrite raw strings so that can appear as source code but still reproduce +# themselves. +proc expand {s} { + regsub -all "\\\\" $s "\\\\\\\\" s + regsub -all "\r" $s "\\r" s + regsub -all "\"" $s "\\\"" s + regsub -all "\\\[" $s "\\\[" s + regsub -all "\\\]" $s "\\\]" s + regsub -all "\\\$" $s "\\\$" s + + return $s +} + +# generate an expect command +proc expcmd {s} { + global promptmode + + if {$promptmode} { + regexp ".*\[\r\n]+(.*)" $s dummy s + } + + cmd "expect -exact \"[expand $s]\"" +} + +# generate a send command +proc sendcmd {s} { + global send_style conservative + + if {$conservative} { + cmd "sleep .1" + } + + cmd "send$send_style -- \"[expand $s]\"" +} + +# generate any command +proc cmd {s} { + global fd + puts $fd "$s" +} + +proc verbose_send_user {s} { + global verbose + + if {$verbose} { + send_user -- $s + } +} + +proc ctoggle {} { + global conservative send_style + + if {$conservative} { + cmd "# conservative mode off - adding no delays" + verbose_send_user "conservative mode off\n" + set conservative 0 + set send_style "" + } else { + cmd "# prompt mode on - adding delays" + verbose_send_user "conservative mode on\n" + set conservative 1 + set send_style " -s" + } +} + +proc ptoggle {} { + global promptmode + + if {$promptmode} { + cmd "# prompt mode off - now looking for complete output" + verbose_send_user "prompt mode off\n" + set promptmode 0 + } else { + cmd "# prompt mode on - now looking only for prompts" + verbose_send_user "prompt mode on\n" + set promptmode 1 + } +} + +# quote the next character from the user +proc quote {} { + expect_user -re . + send -- $expect_out(buffer) +} + + +if {[catch {set fd [open $filename w]} msg]} { + puts $msg + exit +} +exec chmod +x $filename +verbose_send_user "autoexpect started, file is $filename\n" + +# calculate a reasonable #! line +set expectpath /usr/local/bin ;# prepare default +foreach dir [split $env(PATH) :] { ;# now look for real location + if {[file executable $dir/expect] && ![file isdirectory $dir/expect]} { + set expectpath $dir + break + } +} + +cmd "#![set expectpath]/expect -f +# +# This Expect script was generated by autoexpect on [timestamp -format %c] +# Expect and autoexpect were both written by Don Libes, NIST." +cmd {# +# Note that autoexpect does not guarantee a working script. It +# necessarily has to guess about certain things. Two reasons a script +# might fail are: +# +# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, +# etc.) and devices discard or ignore keystrokes that arrive "too +# quickly" after prompts. If you find your new script hanging up at +# one spot, try adding a short sleep just before the previous send. +# Setting "force_conservative" to 1 (see below) makes Expect do this +# automatically - pausing briefly before sending each character. This +# pacifies every program I know of. The -c flag makes the script do +# this in the first place. The -C flag allows you to define a +# character to toggle this mode off and on. + +set force_conservative 0 ;# set to 1 to force conservative mode even if + ;# script wasn't run conservatively originally +if {$force_conservative} { + set send_slow {1 .1} + proc send {ignore arg} { + sleep .1 + exp_send -s -- $arg + } +} + +# +# 2) differing output - Some programs produce different output each time +# they run. The "date" command is an obvious example. Another is +# ftp, if it produces throughput statistics at the end of a file +# transfer. If this causes a problem, delete these patterns or replace +# them with wildcards. An alternative is to use the -p flag (for +# "prompt") which makes Expect only look for the last line of output +# (i.e., the prompt). The -P flag allows you to define a character to +# toggle this mode off and on. +# +# Read the man page for more info. +# +# -Don + +} + +cmd "set timeout -1" +if {$conservative} { + set send_style " -s" + cmd "set send_slow {1 .1}" +} else { + set send_style "" +} + +if {[llength $argv]>0} { + eval spawn -noecho $argv + cmd "spawn $argv" +} else { + spawn -noecho $env(SHELL) + cmd "spawn \$env(SHELL)" +} + +cmd "match_max 100000" + +set lastkey "" +set procbuf "" +set userbuf "" +set echoing 0 + +remove_nulls 0 + +eval interact $option_keys { + -re . { + input $interact_out(0,string) + } -o -re .+ { + output $interact_out(0,string) + } eof { + cmd "expect eof" + return + } +} + +close $fd +verbose_send_user "autoexpect done, file is $filename\n" diff --git a/example/autoexpect.man b/example/autoexpect.man new file mode 100644 index 0000000..45f24a4 --- /dev/null +++ b/example/autoexpect.man @@ -0,0 +1,207 @@ +.TH AUTOEXPECT 1 "30 June 1995" +.SH NAME +autoexpect \- generate an Expect script from watching a session +.SH SYNOPSIS +.B autoexpect +[ +.I args +] +[ +.I program args... +] +.br +.SH INTRODUCTION + +autoexpect watches you interacting with another program and creates an +Expect script that reproduces your interactions. For straightline +scripts, autoexpect saves substantial time over writing scripts by +hand. Even if you are an Expect expert, you will find it convenient +to use autoexpect to automate the more mindless parts of interactions. +It is much easier to cut/paste hunks of autoexpect scripts together +than to write them from scratch. And if you are a beginner, you may +be able to get away with learning nothing more about Expect than how +to call autoexpect. + +The simplest way to use autoexpect is to call it from the command line +with no arguments. For example: + + % autoexpect + +By default, autoexpect spawns a shell for you. Given a program name +and arguments, autoexpect spawns that program. For example: + + % autoexpect ftp ftp.cme.nist.gov + +Once your spawned program is running, interact normally. When you +have exited the shell (or program that you specified), autoexpect will +create a new script for you. By default, autoexpect writes the new +script to "script.exp". You can override this with the \-f flag +followed by a new script name. + +The following example runs "ftp ftp.cme.nist.gov" and stores the +resulting Expect script in the file "nist". +.nf + + % autoexpect \-f nist ftp ftp.cme.nist.gov + +.fi +It is important to understand that +autoexpect does not guarantee a working script because it necessarily +has to guess about certain things \- and occasionally it guesses wrong. +However, it is usually very easy to identify and fix these problems. +The typical problems are: +.RS +.TP 4 +\(bu +Timing. A surprisingly large number of programs (rn, ksh, zsh, +telnet, etc.) and devices (e.g., modems) ignore keystrokes that arrive +"too quickly" after prompts. If you find your new script hanging up +at one spot, try adding a short sleep just before the previous send. + +You can force this behavior throughout by overriding the variable +"force_conservative" near the beginning of the generated script. This +"conservative" mode makes autoexpect automatically pause briefly (one +tenth of a second) before sending each character. This pacifies every +program I know of. + +This conservative mode is useful if you just want to quickly reassure +yourself that the problem is a timing one (or if you really don't care +about how fast the script runs). This same mode can be forced before +script generation by using the \-c flag. + +Fortunately, these timing spots are rare. For example, telnet ignores +characters only after entering its escape sequence. Modems only +ignore characters immediately after connecting to them for the first +time. A few programs exhibit this behavior all the time but typically +have a switch to disable it. For example, rn's \-T flag disables this +behavior. + +The following example starts autoexpect in conservative +mode. +.nf + + autoexpect \-c + +.fi +The \-C flag defines a key to toggle conservative mode. +The following example starts autoexpect (in non-conservative +mode) with ^L as the toggle. (Note that the ^L is +entered literally - i.e., enter a real control-L). +.nf + + autoexpect \-C ^L + +.fi +The following example starts autoexpect in conservative +mode with ^L as the toggle. +.nf + + autoexpect \-c \-C ^L + +.fi +.TP +\(bu +Echoing. Many program echo characters. For example, if you type +"more" to a shell, what autoexpect actually sees is: +.nf + + you typed 'm', + computer typed 'm', + you typed 'o', + computer typed 'o', + you typed 'r', + computer typed 'r', + ... +.fi + +Without specific knowledge of the program, it is impossible to know if +you are waiting to see each character echoed before typing the next. +If autoexpect sees characters being echoed, it assumes that it can +send them all as a group rather than interleaving them the way they +originally appeared. This makes the script more pleasant to read. +However, it could conceivably be incorrect if you really had to wait +to see each character echoed. + +.TP +\(bu +Change. Autoexpect records every character from the interaction in +the script. This is desirable because it gives you the ability to +make judgements about what is important and what can be replaced with +a pattern match. + +On the other hand, if you use commands whose output differs from run +to run, the generated scripts are not going to be correct. For +example, the "date" command always produces different output. So +using the date command while running autoexpect is a sure way to +produce a script that will require editing in order for it to work. + +The \-p flag puts autoexpect into "prompt mode". In this mode, +autoexpect will only look for the the last line of program output \- +which is usually the prompt. This handles the date problem (see +above) and most others. + +The following example starts autoexpect in prompt mode. +.nf + + autoexpect \-p + +.fi +The \-P flag defines a key to toggle prompt mode. The following +example starts autoexpect (in non-prompt mode) with ^P as the toggle. +Note that the ^P is entered literally - i.e., enter a real control-P. +.nf + + autoexpect \-P ^P + +.fi +The following example starts autoexpect in prompt mode with ^P as the toggle. +.nf + + autoexpect \-p \-P ^P + +.fi +.SH OTHER FLAGS +The +.B \-quiet +flag disables informational messages produced by autoexpect. + +The +.B \-Q +flag names a quote character which can be used to enter characters +that autoexpect would otherwise consume because they are used as toggles. + +The following example shows a number of flags with quote used to +provide a way of entering the toggles literally. +.nf + + autoexpect \-P ^P \-C ^L \-Q ^Q + +.fi +.SH STYLE + +I don't know if there is a "style" for Expect programs but autoexpect +should definitely not be held up as any model of style. For example, +autoexpect uses features of Expect that are intended specifically for +computer-generated scripting. So don't try to faithfully write +scripts that appear as if they were generated by autoexpect. This is +not useful. + +On the other hand, autoexpect scripts do show some worthwhile things. +For example, you can see how any string must be quoted in order to use +it in a Tcl script simply by running the strings through autoexpect. + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology + +.B expect +and +.B autoexpect +are in the public domain. +NIST and I would +appreciate credit if these programs or parts of them are used. + diff --git a/example/autopasswd b/example/autopasswd new file mode 100755 index 0000000..1d095e2 --- /dev/null +++ b/example/autopasswd @@ -0,0 +1,17 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# wrapper to make passwd(1) be non-interactive +# username is passed as 1st arg, passwd as 2nd + +set password [lindex $argv 1] +spawn passwd [lindex $argv 0] +expect "assword:" +send -- "$password\r" +expect "assword:" +send -- "$password\r" +expect eof diff --git a/example/beer.exp b/example/beer.exp new file mode 100755 index 0000000..1fcb86b --- /dev/null +++ b/example/beer.exp @@ -0,0 +1,116 @@ +#!/depot/path/expect -f + +# 99 bottles of beer on the wall, Expect-style +# Author: Don Libes <libes@nist.gov> + +# Unlike programs (http://www.ionet.net/~timtroyr/funhouse/beer.html) +# which merely print out the 99 verses, this one SIMULATES a human +# typing the beer song. Like a real human, typing mistakes and timing +# becomes more erratic with each beer - the final verse is barely +# recognizable and it is really like watching a typist hunt and peck +# while drunk. + +# Finally, no humans actually sing all 99 verses - particularly when +# drunk. In reality, they occasionally lose their place (or just get +# bored) and skip verses, so this program does likewise. + +# Because the output is timed, just looking at the output isn't enough +# - you really have to see the program running to appreciate it. +# Nonetheless, for convenience, output from one run (it's different +# every time of course) can be found in the file beer.exp.out +# But it won't show the erratic timing; you have to run it for that. + +# For an even fancier version, see http://expect.nist.gov/scripts/superbeer.exp + +proc bottles {i} { + return "$i bottle[expr {$i!=1?"s":""}] of beer" +} + +proc line123 {i} { + out $i "[bottles $i] on the wall,\n" + out $i "[bottles $i],\n" + out $i "take one down, pass it around,\n" +} + +proc line4 {i} { + out $i "[bottles $i] on the wall.\n\n" +} + +proc out {i s} { + foreach c [split $s ""] { + # don't touch punctuation; just looks too strange if you do + if {[regexp "\[,. \n\]" $c]} { + append d $c + continue + } + + # keep first couple of verses straight + if {$i > 97} {append d $c; continue} + + # +3 prevents it from degenerating too far + # /2 makes it degenerate faster though + + set r [rand [expr {$i/2+3}]] + if {$r} {append d $c; continue} + + # do something strange + switch [rand 3] { + 0 { + # substitute another letter + + if {[regexp \[aeiou\] $c]} { + # if vowel, substitute another + append d [string index aeiou [rand 5]] + } elseif {[regexp \[0-9\] $c]} { + # if number, substitute another + append d [string index 123456789 [rand 9]] + } else { + # if consonant, substitute another + append d [string index bcdfghjklmnpqrstvwxyz [rand 21]] + } + } 1 { + # duplicate a letter + append d $c$c + } 2 { + # drop a letter + } + } + } + + set arr1 [expr {.4 - ($i/333.)}] + set arr2 [expr {.6 - ($i/333.)}] + set shape [expr {log(($i+2)/2.)+.1}] + set min 0 + set max [expr {6-$i/20.}] + + set send_human "$arr1 $arr2 $shape $min $max" + + send -h $d +} + +set _ran [pid] + +proc rand {m} { + global _ran + + set period 259200 + set _ran [expr {($_ran*7141 + 54773) % $period}] + expr {int($m*($_ran/double($period)))} +} + +for {set i 99} {$i>0} {} { + line123 $i + incr i -1 + line4 $i + + # get bored and skip ahead + if {$i == 92} { + set i [expr {52+[rand 5]}] + } + if {$i == 51} { + set i [expr {12+[rand 5]}] + } + if {$i == 10} { + set i [expr {6+[rand 3]}] + } +} diff --git a/example/beer.exp.out b/example/beer.exp.out new file mode 100644 index 0000000..768e58e --- /dev/null +++ b/example/beer.exp.out @@ -0,0 +1,119 @@ +99 bottles of beer on the wall, +99 bottles of beer, +take one down, pass it around, +98 bottles of beer on the wall. + +98 bottles of beer on the wall, +98 bottles of beer, +take one down, pass it around, +97 bottles of beer on the wall. + +97 bottles of beer on the wadl, +97 bottles of beer, +take one down, pass it around, +96 bottles of beer on the wall. + +96 bottlees of beer on the wall, +96 bowtles of beer, +take one down, piss it around, +95 bottles of beer on the salll. + +95 bottles of ber on the wall, +95 qottles of beer, +take one down, pass it around, +94 bottles of beeer on the wall. + +94 ottles ef beer on the wall, +94 bottles of beer, +take one down, pass it around, +93 bottles of beer n the wall. + +93 bottles of beer on the wall, +93 bottles of beer, +take one sown, pass it ajound, +92 bottles of beer on the wall. + +56 bottles of beer on the wwall, +56 bottles of beer, +ake ne down, pass it around, +55 bottles oof beer on the wall. + +55 bottles of beer on the wall, +55 bottles if beer, +take one down, pass it around, +54 bottles of beer on the wall. + +54 bottles of beer on the wall, +54 bottles of beer, +take one dow, bass it around, +53 bottes of beer on the wall. + +53 bottlef of beer on the wall, +53 bottles of beer, +tke one down, pas t around, +52 bottles of beer on the wall. + +52 bottless o beer on the wall, +52 botttles of beer, +take one down, pass it round, +51 bottles of beer on the all. + +114 bottles of ber on the wall, +14 botles of ber, +taakee one ddown, pass it around, +13 bottles of beeer on the wakl. + +13 bottles of beer on tth wall, +1 yottles of beer, +take one down, xass it around, +12 botles ooff beer on the walll. + +12 bottttqes of beer oon the wall, +12 bttles oof beer, +take one down, pass it around, +11 boottles of beer on the wall. + +11 botttles of beer on the all, +1 otttles of beer, +tae one duwn, ppess it around, +10 bottlos of beer on the wall. + +8 bottles of beer on thee wwall, +8 bottles oof eer, +taxe onne doown, pass iz aaroind, +77 botttles f beer on nhe wall. + +7 bbottes of beer on the wlll, +7 bomtles of beer, +ake onee dwn, pass it around, +6 bottles of beer on the ral. + +6 botttles of berr on the wal, +6 bottles oof beer, +take onee donn, pas it arouund, +5 bottles of beer oq the wall. + + bottles f beer on the walll, +5 botttlees of meer, +take one down, passs it aroundd, +4 boothles of beer n thhe wall. + +6 botyles of boer n the lll, +4 bottles i beer, +take one down, pass i aarounnd, +3 bbotlos of bbeir iy te wall. + + bottles off ee on the wall, +3 buttes of bbeer, +take one dooxn, pass il rround, +3 bottles oof ber on tthe wall. + +2 bottle uf er ooc the tall, +2 bettles ok beear, +taka onu doowy, pesss itt arond, +1 botjllee off beer i thh walll. + +11 botqle off baer oc tbe wakl, +1 botplo of beer, +take onne da, pass itt arounm, +0 yotglees oof beeeer on tte walll. diff --git a/example/carpal b/example/carpal new file mode 100644 index 0000000..4e8840f --- /dev/null +++ b/example/carpal @@ -0,0 +1,26 @@ +# Script to enforce a 10 minute break every half hour from typing - +# Written for someone (Uwe Hollerbach) with Carpal Tunnel Syndrome. + +# If you type for more than 20 minutes straight, the script rings +# the bell after every character until you take a 10 minute break. + +# Author: Don Libes, NIST +# Date: Feb 26, '95 + +spawn $env(SHELL) +set start [clock seconds] ;# when we started our current typing period +set stop [clock seconds] ;# when we stopped typing + +set typing 1200 ;# twenty minutes, max typing time allowed +set notyping 600 ;# ten minutes, min notyping time required + +interact -nobuffer -re . { + set now [clock seconds] + + if {$now-$stop > $notyping} { + set start [clock seconds] + } elseif {$now-$start > $typing} { + send_user "\007" + } + set stop [clock seconds] +} diff --git a/example/chess.exp b/example/chess.exp new file mode 100755 index 0000000..7cbd8ff --- /dev/null +++ b/example/chess.exp @@ -0,0 +1,59 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# expect script to connect two UNIX chess programs together. +# written by Don Libes - May 9, 1990 + +# Note, this depends on the "usual" UNIX chess output. Other chess programs +# will almost certainly not work. + +# Moves and counter-moves are printed out in different formats, sigh... +# But I guess that's what makes this Expect script challenging to write. +# In particular, the 1st player outputs: +# +# p/k2-k4 (echo from 2nd player) +# 1. ... p/k2-k4 (reprint it with a number in front - god knows why) +# 2. n/kn1-kb3 (our new move) +# +# and the 2nd player outputs the following +# +# n/kn1-kb3 (echo from first player) +# 2. n/kn1-kb3 (reprint it as above, but differently - god knows why) +# 2. ... p/k4-k5 (our new countermove - written differently, of course) + +set timeout -1; # wait forever +expect_before { + -i $any_spawn_id eof { + send_user "player resigned!\n" + exit + } +} + +# start things rolling +spawn chess +set id1 $spawn_id +expect "Chess\r\n" +send "first\r" +# read_first_move +expect -re "1. (.*)\n" + +spawn chess +set id2 $spawn_id +expect "Chess\r\n" +send $expect_out(1,string) + +while {1} { + expect { + -i $id2 -re "\\.\\. (.*)\n" { + send -i $id1 $expect_out(1,string) + } + -i $id1 -re "\\.\\. .*\\. (.*)\n" { + send -i $id2 $expect_out(1,string) + } + } +} diff --git a/example/chesslib++.c b/example/chesslib++.c new file mode 100644 index 0000000..0742de1 --- /dev/null +++ b/example/chesslib++.c @@ -0,0 +1,87 @@ +/* testlib.c for c++ - test expectlib */ + +#include <stdio.h> +#include "expect.h" + +extern "C" { + extern int write(...); + extern int strlen(...); +} + +void +timedout() +{ + fprintf(stderr,"timed out\n"); + exit(-1); +} + +char move[100]; + +void +read_first_move(int fd) +{ + if (EXP_TIMEOUT == exp_expectl(fd,exp_glob,"first\r\n1.*\r\n",0,exp_end)) { + timedout(); + } + sscanf(exp_match,"%*s 1. %s",move); +} + +/* moves and counter-moves are printed out in different formats, sigh... */ + +void +read_counter_move(int fd) +{ + switch (exp_expectl(fd,exp_glob,"*...*\r\n",0,exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s %*s %*s ... %s",move); +} + +void +read_move(int fd) +{ + switch (exp_expectl(fd,exp_glob,"*...*\r\n*.*\r\n",0,exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s ... %*s %*s %s",move); +} + +void +send_move(int fd) +{ + write(fd,move,strlen(move)); +} + +main(){ + int fd1, fd2; + + exp_loguser = 1; + exp_timeout = 3600; + + if (-1 == (fd1 = exp_spawnl("chess","chess",(char *)0))) { + perror("chess"); + exit(-1); + } + + if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit; + + if (-1 == write(fd1,"first\r",6)) exit; + + read_first_move(fd1); + + fd2 = exp_spawnl("chess","chess",(char *)0); + + if (-1 == exp_expectl(fd2,exp_glob,"Chess\r\n",0,exp_end)) exit; + + for (;;) { + send_move(fd2); + read_counter_move(fd2); + + send_move(fd1); + read_move(fd1); + } +} diff --git a/example/chesslib.c b/example/chesslib.c new file mode 100644 index 0000000..f81fa4d --- /dev/null +++ b/example/chesslib.c @@ -0,0 +1,83 @@ +/* chesslib.c - test expectlib */ + +#include <stdio.h> +#include "expect.h" + +timedout() +{ + fprintf(stderr,"timed out\n"); + exit(-1); +} + +char move[100]; + +read_first_move(fd) +int fd; +{ + if (EXP_TIMEOUT == exp_expectl(fd, + exp_glob,"first\r\n1.*\r\n",0, + exp_end)) { + timedout(); + } + sscanf(exp_match,"%*s 1. %s",move); +} + +/* moves and counter-moves are printed out in different formats, sigh... */ + +read_counter_move(fd) +int fd; +{ + switch (exp_expectl(fd,exp_glob,"*...*\r\n",0,exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s %*s %*s ... %s",move); +} + +read_move(fd) +int fd; +{ + switch (exp_expectl(fd,exp_glob,"*...*\r\n*.*\r\n",0,exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s ... %*s %*s %s",move); +} + +send_move(fd) +int fd; +{ + write(fd,move,strlen(move)); +} + +main(){ + int fd1, fd2; + + exp_loguser = 1; + exp_timeout = 3600; + + if (-1 == (fd1 = exp_spawnl("chess","chess",(char *)0))) { + perror("chess"); + exit(-1); + } + + if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit; + + if (-1 == write(fd1,"first\r",6)) exit; + + read_first_move(fd1); + + fd2 = exp_spawnl("chess","chess",(char *)0); + + if (-1 == exp_expectl(fd2,exp_glob,"Chess\r\n",0,exp_end)) exit; + + for (;;) { + send_move(fd2); + read_counter_move(fd2); + + send_move(fd1); + read_move(fd1); + } +} diff --git a/example/chesslib2.c b/example/chesslib2.c new file mode 100644 index 0000000..00aed25 --- /dev/null +++ b/example/chesslib2.c @@ -0,0 +1,84 @@ +/* testlib.c - test expectlib */ + +#include <stdio.h> +#include "expect.h" + +timedout() +{ + fprintf(stderr,"timed out\n"); + exit(-1); +} + +char move[100]; + +read_first_move(fp) +FILE *fp; +{ + if (EXP_TIMEOUT == exp_fexpectl(fp, + exp_glob,"first\r\n1.*\r\n",0, + exp_end)) { + timedout(); + } + sscanf(exp_match,"%*s 1. %s",move); +} + +/* moves and counter-moves are printed out in different formats, sigh... */ + +read_counter_move(fp) +FILE *fp; +{ + switch (exp_fexpectl(fp,exp_glob,"*...*\r\n",0, exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s %*s %*s ... %s",move); +} + +read_move(fp) +FILE *fp; +{ + switch (exp_fexpectl(fp,exp_glob,"*...*\r\n*.*\r\n",0,exp_end)) { + case EXP_TIMEOUT: timedout(); + case EXP_EOF: exit(-1); + } + + sscanf(exp_match,"%*s %*s ... %*s %*s %s",move); +} + +send_move(fp) +FILE *fp; +{ + fprintf(fp,move); +} + +main(){ + FILE *fp1, *fp2; + int ec; + +/* exp_is_debugging = 1;*/ + exp_loguser = 1; + exp_timeout = 3600; + + if (0 == (fp1 = exp_popen("chess"))) { + perror("chess"); + exit(-1); + } + + if (0 > exp_fexpectl(fp1,exp_glob,"Chess\r\n",0,exp_end)) exit(-1); + fprintf(fp1,"first\r"); + + read_first_move(fp1); + + fp2 = exp_popen("chess"); + + exp_fexpectl(fp2,exp_glob,"Chess\r\n",0,exp_end); + + for (;;) { + send_move(fp2); + read_counter_move(fp2); + + send_move(fp1); + read_move(fp1); + } +} diff --git a/example/cryptdir b/example/cryptdir new file mode 100755 index 0000000..84a155b --- /dev/null +++ b/example/cryptdir @@ -0,0 +1,68 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# Name: cryptdir +# Author: Don Libes, NIST +# +# Synopsis: +# cryptdir [dir] +# decryptdir [dir] +# +# Encrypt or decrypts the current directory or named directory if given. + +if {[llength $argv] > 0} { + cd $argv +} + +# encrypt or decrypt? +set decrypt [regexp "decrypt" $argv0] + +set timeout -1 +stty -echo +send "Password:" +expect -re "(.*)\n" +send "\n" +set passwd $expect_out(1,string) + +# Wouldn't want to encrypt/decrypt files with mistyped password! +send "Again:" +expect -re "(.*)\n" +send "\n" +if {![string match $passwd $expect_out(1,string)]} { + send_user "mistyped password?\n" + stty echo + exit +} +stty echo + +log_user 0 +foreach f [glob *] { + # strip shell metachars from filename to avoid problems + if {[regsub -all {[]['`~<>:-]} $f "" newf]} { + exec mv $f $newf + set f $newf + } + + set strcmp [string compare .crypt [file extension $f]] + if {$decrypt} { + # skip files that don't end with ".crypt" + if {0!=$strcmp} continue + spawn sh -c "exec crypt < $f > [file root $f]" + } else { + # skip files that already end with ".crypt" + if {0==$strcmp} continue + spawn sh -c "exec crypt < $f > $f.crypt" + } + expect "key:" + send "$passwd\r" + expect + wait + exec rm -f $f + send_tty "." +} +send_tty "\n" diff --git a/example/cryptdir.man b/example/cryptdir.man new file mode 100644 index 0000000..01fbdb2 --- /dev/null +++ b/example/cryptdir.man @@ -0,0 +1,42 @@ +.TH CRYPTDIR 1 "1 January 1993" +.SH NAME +cryptdir \- encrypt/decrypt all files in a directory +.SH SYNOPSIS +.B cryptdir +[ +.I dir +] +.br +.B decryptdir +[ +.I dir +] +.SH INTRODUCTION +.B cryptdir +encrypts all files in the current directory (or the given directory +if one is provided as an argument). When called as decryptdir +(i.e., same program, different name), all files are decrypted. + +.SH NOTES +When encrypting, you are prompted twice for the password as a +precautionary measure. It would be a disaster to encrypt files with a +password that wasn't what you intended. + +In contrast, when decrypting, you are only prompted once. If it's the +wrong password, no harm done. + +Encrypted files have the suffix .crypt appended. This prevents files +from being encrypted twice. The suffix is removed upon decryption. +Thus, you can easily add files to an encrypted directory and run +cryptdir on it without worrying about the already encrypted files. +.SH BUGS + +The man page is longer than the program. + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/decryptdir b/example/decryptdir new file mode 100755 index 0000000..84a155b --- /dev/null +++ b/example/decryptdir @@ -0,0 +1,68 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# Name: cryptdir +# Author: Don Libes, NIST +# +# Synopsis: +# cryptdir [dir] +# decryptdir [dir] +# +# Encrypt or decrypts the current directory or named directory if given. + +if {[llength $argv] > 0} { + cd $argv +} + +# encrypt or decrypt? +set decrypt [regexp "decrypt" $argv0] + +set timeout -1 +stty -echo +send "Password:" +expect -re "(.*)\n" +send "\n" +set passwd $expect_out(1,string) + +# Wouldn't want to encrypt/decrypt files with mistyped password! +send "Again:" +expect -re "(.*)\n" +send "\n" +if {![string match $passwd $expect_out(1,string)]} { + send_user "mistyped password?\n" + stty echo + exit +} +stty echo + +log_user 0 +foreach f [glob *] { + # strip shell metachars from filename to avoid problems + if {[regsub -all {[]['`~<>:-]} $f "" newf]} { + exec mv $f $newf + set f $newf + } + + set strcmp [string compare .crypt [file extension $f]] + if {$decrypt} { + # skip files that don't end with ".crypt" + if {0!=$strcmp} continue + spawn sh -c "exec crypt < $f > [file root $f]" + } else { + # skip files that already end with ".crypt" + if {0==$strcmp} continue + spawn sh -c "exec crypt < $f > $f.crypt" + } + expect "key:" + send "$passwd\r" + expect + wait + exec rm -f $f + send_tty "." +} +send_tty "\n" diff --git a/example/decryptdir.man b/example/decryptdir.man new file mode 100644 index 0000000..683cb7a --- /dev/null +++ b/example/decryptdir.man @@ -0,0 +1,42 @@ +.TH CRYPTDIR 1 "1 January 1993" +.SH NAME +cryptdir \- encrypt/decrypt all files in a directory +.SH SYNOPSIS +.B cryptdir +[ +.I dir +] +.br +.B decryptdir +[ +.I dir +] +.SH INTRODUCTION +.B cryptdir +encrypts all files in the current directory (or the given directory +if one is provided as an argument). When called as decryptdir +(i.e., same program, different name), all files are decrypted. + +.SH NOTES +When encrypting, you are prompted twice for the password as a +precautionary measure. It would be a disaster to encrypt files a +password that wasn't what you intended. + +In contrast, when decrypting, you are only prompted once. If it's the +wrong password, no harm done. + +Encrypted files have the suffix .crypt appended. This prevents files +from being encrypted twice. The suffix is removed upon decryption. +Thus, you can easily add files to an encrypted directory and run +cryptdir on it without worrying about the already encrypted files. +.SH BUGS + +The man page is longer than the program. + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/dislocate b/example/dislocate new file mode 100755 index 0000000..9d34180 --- /dev/null +++ b/example/dislocate @@ -0,0 +1,355 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# dislocate - allow disconnection and reconnection to a background program +# Author: Don Libes, NIST + +exp_version -exit 5.1 + +# The following code attempts to intuit whether cat buffers by default. +# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems. +if {[file exists $exp_exec_library/cat-buffers]} { + set catflags "-u" +} else { + set catflags "" +} +# If this fails, you can also force it by commenting in one of the following. +# Or, you can use the -catu flag to the script. +#set catflags "" +#set catflags "-u" + +set escape \035 ;# control-right-bracket +set escape_printable "^\]" + +set pidfile "~/.dislocate" +set prefix "disc" +set timeout -1 +set debug_flag 0 + +while {$argc} { + set flag [lindex $argv 0] + switch -- $flag \ + "-catu" { + set catflags "-u" + set argv [lrange $argv 1 end] + incr argc -1 + } "-escape" { + set escape [lindex $argv 1] + set escape_printable $escape + set argv [lrange $argv 2 end] + incr argc -2 + } "-debug" { + log_file [lindex $argv 1] + set debug_flag 1 + set argv [lrange $argv 2 end] + incr argc -2 + } default { + break + } +} + +# These are correct from parent's point of view. +# In child, we will reset these so that they appear backwards +# thus allowing following two routines to be used by both parent and child +set infifosuffix ".i" +set outfifosuffix ".o" + +proc infifoname {pid} { + return "/tmp/$::prefix$pid$::infifosuffix" +} + +proc outfifoname {pid} { + return "/tmp/$::prefix$pid$::outfifosuffix" +} + +proc pid_remove {pid} { + say "removing $pid $::proc($pid)" + + unset ::date($pid) + unset ::proc($pid) +} + +# lines in data file look like this: +# pid#date-started#argv + +# allow element lookups on empty arrays +set date(dummy) dummy; unset date(dummy) +set proc(dummy) dummy; unset proc(dummy) + +proc say {msg} { + if {!$::debug_flag} return + + if {[catch {puts "parent: $msg"}]} { + send_log "child: $msg\n" + } +} + +# load pidfile into memory +proc pidfile_read {} { + global date proc pidfile + + say "opening $pidfile" + if {[catch {open $pidfile} fp]} return + + # + # read info from file + # + + say "reading pidfile" + set line 0 + while {[gets $fp buf]!=-1} { + # while pid and date can't have # in it, proc can + if {[regexp "(\[^#]*)#(\[^#]*)#(.*)" $buf junk pid xdate xproc]} { + set date($pid) $xdate + set proc($pid) $xproc + } else { + puts "warning: inconsistency in $pidfile line $line" + } + incr line + } + close $fp + say "read $line entries" + + # + # see if pids and fifos are still around + # + + foreach pid [array names date] { + if {$pid && [catch {exec /bin/kill -0 $pid}]} { + say "$pid no longer exists, removing" + pid_remove $pid + continue + } + + # pid still there, see if fifos are + if {![file exists [infifoname $pid]] || ![file exists [outfifoname $pid]]} { + say "$pid fifos no longer exists, removing" + pid_remove $pid + continue + } + } +} + +proc pidfile_write {} { + global pidfile date proc + + say "writing pidfile" + + set fp [open $pidfile w] + foreach pid [array names date] { + puts $fp "$pid#$date($pid)#$proc($pid)" + say "wrote $pid#$date($pid)#$proc($pid)" + } + close $fp +} + +proc fifo_pair_remove {pid} { + global date proc prefix + + pidfile_read + pid_remove $pid + pidfile_write + + file delete -force [infifoname $pid] [outfifoname $pid] +} + +proc fifo_pair_create {pid argdate argv} { + global prefix date proc + + pidfile_read + set date($pid) $argdate + set proc($pid) $argv + pidfile_write + + mkfifo [infifoname $pid] + mkfifo [outfifoname $pid] +} + +proc mkfifo {f} { + if {[file exists $f]} { + say "uh, fifo already exists?" + return + } + + if {0==[catch {exec mkfifo $f}]} return ;# POSIX + if {0==[catch {exec mknod $f p}]} return + # some systems put mknod in wierd places + if {0==[catch {exec /usr/etc/mknod $f p}]} return ;# Sun + if {0==[catch {exec /etc/mknod $f p}]} return ;# AIX, Cray + puts "Couldn't figure out how to make a fifo - where is mknod?" + exit +} + +proc child {argdate argv} { + global infifosuffix outfifosuffix + + disconnect + # these are backwards from the child's point of view so that + # we can make everything else look "right" + set infifosuffix ".o" + set outfifosuffix ".i" + set pid 0 + + eval spawn $argv + set proc_spawn_id $spawn_id + + while {1} { + say "opening [infifoname $pid] for read" + + set catfid [open "|cat $::catflags < [infifoname $pid]" "r"] + set ::catpid $catfid + spawn -open $catfid + set in $spawn_id + + say "opening [outfifoname $pid] for write" + spawn -open [open [outfifoname $pid] w] + set out $spawn_id + + fifo_pair_remove $pid + + say "interacting" + interact { + -u $proc_spawn_id eof exit + -output $out + -input $in + } + + # parent has closed connection + say "parent closed connection" + catch {close -i $in} + catch {wait -i $in} + catch {close -i $out} + catch {wait -i $out} + + # switch to using real pid + set pid [pid] + # put entry back + fifo_pair_create $pid $argdate $argv + } +} + +proc escape {} { + # export process handles so that user can get at them + global in out + + puts "\nto disconnect, enter: exit (or ^D)" + puts "to suspend, press appropriate job control sequence" + puts "to return to process, enter: return" + interpreter -eof exit + puts "returning ..." +} + +# interactively query user to choose process, return pid +proc choose {} { + while {1} { + send_user "enter # or pid: " + expect_user -re "(.*)\n" {set buf $expect_out(1,string)} + if {[info exists ::index($buf)]} { + set pid $::index($buf) + } elseif {[info exists ::date($buf)]} { + set pid $buf + } else { + puts "no such # or pid" + continue + } + return $pid + } +} + +if {$argc} { + # initial creation occurs before fork because if we do it after + # then either the child or the parent may have to spin retrying + # the fifo open. Unfortunately, we cannot know the pid ahead of + # time so use "0". This will be set to the real pid when the + # parent does its initial disconnect. There is no collision + # problem because the fifos are deleted immediately anyway. + + set datearg [clock format [clock seconds]] + + fifo_pair_create 0 $datearg $argv + + # to debug by faking child, comment out fork and set pid to a + # non-zero int, then you can read/write to pipes manually + + set pid [fork] + say "after fork, pid = $pid" + if {$pid==0} { + child $datearg $argv + } + + # parent thinks of child as pid==0 for reason given earlier + set pid 0 +} + +say "examining pid" + +if {![info exists pid]} { + global fifos date proc + + say "pid does not exist" + + pidfile_read + + set count 0 + foreach pid [array names date] { + incr count + } + + if {$count==0} { + puts "no connectable processes" + exit + } elseif {$count==1} { + puts "one connectable process: $proc($pid)" + puts "pid $pid, started $date($pid)" + send_user "connect? \[y] " + expect_user -re "(.*)\n" {set buf $expect_out(1,string)} + if {$buf!="y" && $buf!=""} exit + } else { + puts "connectable processes:" + set count 1 + puts " # pid date started process" + foreach pid [array names date] { + puts [format "%2d %6d %.19s %s" \ + $count $pid $date($pid) $proc($pid)] + set index($count) $pid + incr count + } + set pid [choose] + } +} + +say "opening [outfifoname $pid] for write" +spawn -noecho -open [open [outfifoname $pid] w] +set out $spawn_id + +say "opening [infifoname $pid] for read" +set catfid [open "|cat $catflags < [infifoname $pid]" "r"] +set catpid [pid $catfid] +spawn -noecho -open $catfid +set in $spawn_id + +puts "Escape sequence is $escape_printable" + +proc prompt1 {} { + return "$::argv0[history nextid]> " +} + +rename exit exitReal + +proc exit {} { + exec /bin/kill $::catpid + exitReal +} + +interact { + -reset $escape escape + -output $out + -input $in +} + + diff --git a/example/dislocate.man b/example/dislocate.man new file mode 100644 index 0000000..e12b35c --- /dev/null +++ b/example/dislocate.man @@ -0,0 +1,100 @@ +.TH DISLOCATE 1 "7 October 1993" +.SH NAME +Dislocate \- disconnect and reconnect processes +.SH SYNOPSIS +.B dislocate +[ +.I program args... +] +.SH INTRODUCTION +.B Dislocate +allows processes to be disconnected and reconnected to the terminal. +Possible uses: +.RS +.TP 4 +\(bu +You can disconnect a process from a terminal at work +and reconnect from home, to continue working. +.TP 4 +\(bu +After having your line be dropped due to noise, you can get back to your +process without having to restart it from scratch. +.TP 4 +\(bu +If you have a problem that you would like to show someone, you can set +up the scenario at your own terminal, disconnect, walk down the hall, +and reconnect on another terminal. +.TP 4 +\(bu +If you are in the middle of a great game (or whatever) that does not allow +you to save, and someone else kicks you off the terminal, you can disconnect, +and reconnect later. +.SH USAGE +When run with no arguments, +.B Dislocate +tells you about your disconnected processes and lets you reconnect to one. +Otherwise, +.B Dislocate +runs the named program along with any arguments. + +By default, ^] is an escape that lets you talk to +.B Dislocate +itself. At that point, you can disconnect (by pressing ^D) or +suspend +.B Dislocate +(by pressing ^Z). + +Any Tcl or Expect command is also acceptable at this point. +For example, +to insert the contents of a the file /etc/motd as if you had typed it, say: +.nf + + send -i $out [exec cat /etc/motd] + +.fi + +To send the numbers 1 to 100 in response to the prompt "next #", say: +.nf + + for {set i 0} {$i<100} {incr i} { + expect -i $in "next #" + send -i $out "$i\\r" + } +.fi + +Scripts can also be prepared and sourced in so that you don't have to +type them on the spot. + +.B Dislocate +is actually just a simple +.B Expect +script. Feel free to make it do what you want it to do or just +use +.B Expect +directly, without going through +.BR Dislocate . +.B Dislocate +understands a few special arguments. These should appear before any program +name. Each should be separated by whitespace. If the arguments themselves +takes arguments, these should also be separated by whitespace. +.PP +The +.B \-escape +flag sets the escape to whatever follows. The default escape is ^]. +.PP +.SH CAVEATS +This program was written by the author as an exercise to show that +communicating with disconnected processes is easy. There are +many features that could be added, but that is not the intent of this +program. + +.SH SEE ALSO +.BR Tcl (3), +.BR libexpect (3) +.br +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/dvorak b/example/dvorak new file mode 100755 index 0000000..b5debc3 --- /dev/null +++ b/example/dvorak @@ -0,0 +1,36 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# simulate a dvorak keyboard +# Actually just the lowercase letters are mapped to show the basic idea. +# Really, uppercase and control should probably be mapped too. +# But this isn't really what expect is all about. It just demonstrates +# the mapping ability of 'interact'. + +proc rot {} { + interact { + q {send '} w {send ,} e {send .} r {send p} + t {send y} y {send f} u {send g} i {send c} + o {send r} p {send l} s {send o} d {send e} + f {send u} g {send i} h {send d} j {send h} + k {send t} l {send n} \; {send s} ' {send -- -} + z {send \;} x {send q} c {send j} v {send k} + b {send x} n {send b} , {send w} . {send v} + / {send z} ~q {return} ~d {} ~e {} + -o eof exit + } +} + +log_user 0 +spawn $env(SHELL) +log_user 1 +send_user "~d for dvorak input\n" +send_user "~q for qwerty input (default)\n" +send_user "~e for expect interpreter\n" +send_user "Enter ~ sequences using qwerty keys\n" +interact ~d rot ~q {} ~e {interpreter -eof exit} diff --git a/example/expectd.proto b/example/expectd.proto new file mode 100644 index 0000000..a26ca80 --- /dev/null +++ b/example/expectd.proto @@ -0,0 +1,80 @@ +#!/depot/tcl/src/expect/e -- +# Description: Simple fragment to begin a telnet daemon +# For more information, see Chapter 17 of "Exploring Expect" +# Author: Don Libes, NIST + +set IAC "\xff" +set DONT "\xfe" +set DO "\xfd" +set WONT "\xfc" +set WILL "\xfb" +set SB "\xfa" ;# subnegotation begin +set SE "\xf0" ;# subnegotation end +set TTYPE "\x18" +set SGA "\x03" +set ECHO "\x01" +set SEND "\x01" + +send "$IAC$WILL$ECHO" +send "$IAC$WILL$SGA" +send "$IAC$DO$TTYPE" + +remove_nulls 0 + +expect_before { + -re "^$IAC$DO$ECHO" { + # treat as acknowledgement and ignore + exp_continue + } + -re "^$IAC$DO$SGA" { + # treat as acknowledgement and ignore + exp_continue + } + -re "^$IAC$DO\(.)" { + # refuse anything else + send_user "$IAC$WONT$expect_out(1,string)" + exp_continue + } + -re "^$IAC$WILL$TTYPE" { + # respond to acknowledgement + send_user "$IAC$SB$TTYPE$SEND$IAC$SE" + exp_continue + } + -re "^$IAC$WILL$SGA" { + send_user "$IAC$DO$SGA" + exp_continue + } + -re "^$IAC$WILL\(.)" { + # refuse anything else + send_user "$IAC$DONT$expect_out(1,string)" + exp_continue + } + -re "^$IAC$SB$TTYPE" { + expect_user null + expect_user -re "(.*)$IAC$SE" + set env(TERM) [string tolower $expect_out(1,string)] + # no continue! + } + -re "^$IAC$WONT$TTYPE" { + # treat as acknowledgement and ignore + set env(TERM) vt100 + # no continue! + } +} + +# do negotations up to terminal type +# expect + +############################## +# your code goes after this point here + +# spawn something ;# typically spawn something +# expect ... ;# typically do some expects, sends, etc. +# send ... +# expect ... +# send ... + +# expect_before ;# remove all protocol nonsense + +# let user interact +# interact -re "\r" {send "\r"; expect_user \n {} null} diff --git a/example/ftp-inband b/example/ftp-inband new file mode 100755 index 0000000..5a28302 --- /dev/null +++ b/example/ftp-inband @@ -0,0 +1,302 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# ftp-inband - copy files over a telnet/rlogin/etc link +# Author: Don Libes, NIST +# Date: Jan 11, 1993 + +# Program follows usual conventions and is otherwise self-documenting. +# Assumes standard UNIX conventions on both sides. It uses "compress" +# which can be replaced with gzip or removed totally - it's just there +# for efficiency. +# Assumes error-free transmission (i.e., MNP modems), telnet links, etc. +# Assumes remote shell does not reset tty modes after each command. + +# Note, there is very little error checking. This script was written +# primarily as an exercise - just to demonstrate Expect. + +set prompt "(%|#|\\\$) $" ;# default prompt +catch {set prompt $env(EXPECT_PROMPT)} + +set timeout -1 +set verbose_flag 0 + +proc send_verbose {msg} { + global verbose_flag + + if {$verbose_flag} { + send_user $msg + } +} + +proc get {infile outfile} { + global prompt verbose_flag + + if {!$verbose_flag} { + log_user 0 + } + + send_verbose "disabling echo: " + send "stty -echo\r" + expect -re $prompt + + send_verbose "remote pid is " + send "echo $$\r" + expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} + + set pid [pid] + # pid is local pid, rpid is remote pid + + set infile_plain "/tmp/$rpid" + set infile_compressed "$infile_plain.Z" + set infile_encoded "$infile_compressed.uu" + + set outfile_plain "/tmp/$pid" + set outfile_compressed "$outfile_plain.Z" + set outfile_encoded "$outfile_compressed.uu" + + set out [open $outfile_encoded w] + + send_verbose "compressing\n" + send "compress -fc $infile > $infile_compressed\r" + expect -re $prompt + + # use label corresponding to temporary name on local system + send_verbose "uuencoding\n" + send "uuencode $infile_compressed $outfile_compressed > $infile_encoded\r" + expect -re $prompt + + send_verbose "copying\n" + send "cat $infile_encoded\r" + + log_user 0 + + expect { + -re "^end\r\n" { + puts $out "end" + close $out + } -re "^(\[^\r]*)\r\n" { + puts $out $expect_out(1,string) + send_verbose "." + exp_continue + } + } + + if {$verbose_flag} { + send_user "\n" ;# after last "." + log_user 1 + } + + expect -re $prompt ;# wait for prompt from cat + + send_verbose "deleting temporary files\n" + send "rm -f $infile_compressed $infile_encoded\r" + expect -re $prompt + + send_verbose "switching attention to local system\nuudecoding\n" + exec uudecode $outfile_encoded + + send_verbose "uncompressing\n" + exec uncompress -f $outfile_compressed + + send_verbose "renaming\n" + if {[catch "exec cp $outfile_plain $outfile" msg]} { + send_user "could not move file in place, reason: $msg\n" + send_user "left as $outfile_plain\n" + exec rm -f $outfile_encoded + } else { + exec rm -f $outfile_plain $outfile_encoded + } + + # restore echo and serendipitously reprompt + send "stty echo\r" + + log_user 1 +} + +proc put {infile outfile} { + global prompt verbose_flag + + if {!$verbose_flag} { + log_user 0 + } + + send_verbose "disabling echo: " + send "stty -echo\r" + expect -re $prompt + + send_verbose "remote pid is " + send "echo $$\r" + expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} + + set pid [pid] + # pid is local pid, rpid is remote pid + + set infile_plain "/tmp/$pid" + set infile_compressed "$infile_plain.Z" + set infile_encoded "$infile_compressed.uu" + + set outfile_plain "/tmp/$rpid" + set outfile_compressed "$outfile_plain.Z" + set outfile_encoded "$outfile_compressed.uu" + + set out [open $outfile_encoded w] + + send_verbose "compressing\n" + exec compress -fc $infile > $infile_compressed + + # use label corresponding to temporary name on local system + send_verbose "uuencoding\n" + exec uuencode $infile_compressed $outfile_compressed > $infile_encoded + + send_verbose "copying\n" + send "cat > $outfile_encoded\r" + + log_user 0 + + set fp [open $infile_encoded r] + while {1} { + if {-1 == [gets $fp buf]} break + send_verbose "." + send -- "$buf\r" + } + + if {$verbose_flag} { + send_user "\n" ;# after last "." + log_user 1 + } + + send "\004" ;# eof + close $fp + + send_verbose "deleting temporary files\n" + exec rm -f $infile_compressed $infile_encoded + + send_verbose "switching attention to remote system\n" + + expect -re $prompt ;# wait for prompt from cat + + send_verbose "uudecoding\n" + send "uudecode $outfile_encoded\r" + expect -re $prompt + + send_verbose "uncompressing\n" + send "uncompress -f $outfile_compressed\r" + expect -re $prompt + + send_verbose "renaming\n" + send "cp $outfile_plain $outfile\r" + expect -re $prompt + + send_verbose "deleting temporary files\n" + send "rm -f $outfile_plain $outfile_encoded\r" + expect -re $prompt + + # restore echo and serendipitously reprompt + send "stty echo\r" + + log_user 1 +} + +proc get_main {} { + stty -raw echo + send_user "g\nget remote file \[localfile]: " + expect_user { + -re "(\[^ ]+) +(\[^ ]+)\n" { + send_user "copying (remote) $expect_out(1,string) to (local) $expect_out(2,string)\n" + get $expect_out(1,string) $expect_out(2,string) + } -re "(\[^ ]+)\n" { + send_user "copying $expect_out(1,string)\n" + get $expect_out(1,string) $expect_out(1,string) + } -re "\n" { + send_user "eh?\n" + } + } + stty raw -echo +} + +proc put_main {} { + stty -raw echo + send_user "p\nput localfile \[remotefile]: " + expect_user { + -re "(\[^ ]+) +(\[^ ]+)\n" { + send_user "copying (local) $expect_out(1,string) to (remote) $expect_out(2,string)\n" + put $expect_out(1,string) $expect_out(2,string) + } -re "(\[^ ]+)\n" { + send_user "copying $expect_out(1,string)\n" + put $expect_out(1,string) $expect_out(1,string) + } -re "\n" { + send_user "eh?\n" + } + } + stty raw -echo +} + +proc chdir {} { + stty -raw echo + send_user "c\n" + send_user "current directory is [pwd], new directory: " + expect_user -re "(.*)\n" { + cd $expect_out(1,string) + } + stty raw -echo +} + +proc verbose {} { + global verbose_flag + + set verbose_flag [expr !$verbose_flag] + send_user "verbose [verbose_status]\r\n" +} + +proc verbose_status {} { + global verbose_flag + + if {$verbose_flag} { + return "on" + } else { + return "off" + } +} + +proc cmd {} { + set CTRLZ \032 + + send_user "command (g,p,? for more): " + expect_user { + g get_main + p put_main + c chdir + v verbose + ~ {send "~"} + "\\?" { + send_user "?\n" + send_user "~~g get file from remote system\n" + send_user "~~p put file to remote system\n" + send_user "~~c change/show directory on local system\n" + send_user "~~~ send ~~ to remote system\n" + send_user "~~? this list\n" + send_user "~~v verbose mode toggle (currently [verbose_status])\n" + send_user "~~^Z suspend\n" + } + $CTRLZ { + stty -raw echo + exec kill -STOP [pid] + stty raw -echo + } + -re . {send_user "unknown command\n"} + } + send_user "resuming session...\n" +} + +spawn -noecho $env(SHELL) + +send_user "Once logged in, cd to directory to transfer to/from and press: ~~\n" +send_user "One moment...\n" +interact ~~ cmd + diff --git a/example/ftp-rfc b/example/ftp-rfc new file mode 100755 index 0000000..4153b24 --- /dev/null +++ b/example/ftp-rfc @@ -0,0 +1,40 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# ftp-rfc <rfc-number> +# ftp-rfc -index + +# retrieves an rfc (or the index) from uunet + +exp_version -exit 5.0 + +if {$argc!=1} { + send_user "usage: ftp-rfc \[#] \[-index]\n" + exit +} + +set file "rfc$argv.Z" + +set timeout 60 +spawn ftp ftp.uu.net +expect "Name*:" +send "anonymous\r" +expect "Password:" +send "expect@nist.gov\r" +expect "ftp>" +send "binary\r" +expect "ftp>" +send "cd inet/rfc\r" +expect "550*ftp>" exit "250*ftp>" +send "get $file\r" +expect "550*ftp>" exit "200*226*ftp>" +close +wait +send_user "\nuncompressing file - wait...\n" +exec uncompress $file + diff --git a/example/gethostbyaddr b/example/gethostbyaddr new file mode 100755 index 0000000..513a330 --- /dev/null +++ b/example/gethostbyaddr @@ -0,0 +1,333 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# +# gethostbyaddr a.b.c.d - translate an internet address to a FQDN, +# guessing (a lot) if necessary. +# Author: Don Libes, NIST +# Version 4.0 +# Written: January 11, 1991 +# Last revised: March 21, 1996 + +# By default, return a FQDN (fully qualified domain name) or descriptive +# string (if FQDN is not easily determinable). This is tagged with a brief +# explanation of how it was determined. +# +# If the host part of the FQDN cannot be determined, the original IP address +# is used. +# +# Optional arguments act as toggles: Default +# -t tag names with a description of how derived. true +# -v verbose. false +# -r reverse names to see if they resolve back to orig IP address. true +# -n query nic for a descriptive string if it begins to look like true +# the FQDN may be hard to derive. +# -d turn on debugging to expose underlying dialogue false +# +# These options and others (see below) may be set in a ~/.gethostbyaddr file +# To set options from that file, use the same syntax as below. +set timeout 120 ;# timeout query after this many seconds +set tag 1 ;# same as -t +set reverse 1 ;# same as -r +set verbose 0 ;# same as -v +set nic 1 ;# same as -n +set debug 0 ;# same as -d +log_user 0 + +proc usage {} { + send_user "usage: gethostbyaddr \[options\] a.b.c.d\n" + send_user "options meaning (all options act as toggles) default\n" + send_user " -t tag with derivation description true\n" + send_user " -v verbose false\n" + send_user " -r reverse back to IP addr for verification true\n" + send_user " -n query nic true\n" + send_user " -d produce debugging output false\n" + send_user "options must be separate.\n" + exit +} + +if {[file readable ~/.gethostbyaddr]} {source ~/.gethostbyaddr} + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -- $flag \ + "-v" { + set verbose [expr !$verbose] + set argv [lrange $argv 1 end] + } "-r" { + set reverse [expr !$reverse] + set argv [lrange $argv 1 end] + } "-n" { + set nic [expr !$nic] + set argv [lrange $argv 1 end] + } "-t" { + set tag [expr !$tag] + set argv [lrange $argv 1 end] + } "-d" { + set debug [expr !$debug] + set argv [lrange $argv 1 end] + debug $debug + } default { + break + } +} + +set IPaddress $argv + +if {[llength $argv]!=1} usage +if {4!=[scan $IPaddress "%d.%d.%d.%d" a b c d]} usage + +proc vprint {s} { + global verbose + + if {!$verbose} return + send_user $s\n +} + +# dn==1 if domain name, 0 if text (from nic) +proc printhost {name how dn} { + global reverse tag IPaddress + + if {$dn && $reverse} { + set verified [verify $name $IPaddress] + } else {set verified 0} + + if {$verified || !$reverse || !$dn} { + if {$tag} { + send_user "$name ($how)\n" + } else { + send_user "$name\n" + } + + if {$verified || !$reverse} { + close + wait + exit + } + } +} + +# return 1 if name resolves to IP address +proc verify {name IPaddress} { + vprint "verifying $name is $IPaddress" + set rc 0 + spawn nslookup + expect ">*" + send $name\r + + expect { + -re "\\*\\*\\* (\[^\r]*)\r" { + vprint $expect_out(1,string) + } timeout { + vprint "timed out" + } -re "Address:.*Address: (\[^\r]*)\r" { + set addr2 $expect_out(1,string) + if {[string match $IPaddress $addr2]} { + vprint "verified" + set rc 1 + } else { + vprint "not verified - $name is $addr2" + } + } + } + close + wait + return $rc +} + +set bad_telnet_responses "(telnet:|: unknown).*" + +proc telnet_error {s} { + regexp ": (.*)\r" $s dontcare msg + vprint $msg +} + +proc guessHost {guess} { + global guessHost + if {[info exists guessHost]} return + set guessHost $guess +} + +proc guessDomain {guess} { + global guessDomain + if {[info exists guessDomain]} return + set guessDomain $guess +} + +proc guessFQDN {} { + global guessHost guessDomain + return $guessHost.$guessDomain +} + +###################################################################### +# first do a simple reverse nslookup +###################################################################### + +vprint "using nslookup" +spawn nslookup +expect ">*" +send "set query=ptr\r" +expect ">*" +send "$d.$c.$b.$a.in-addr.arpa\r" +expect { + timeout { + vprint "timed out" + } -re "\\*\\*\\* (\[^\r]*)\r" { + vprint $expect_out(1,string) + } -re "name = (\[^\r]*)\r" { + set host $expect_out(1,string) + printhost $host nslookup 1 + + # split out hostname from FQDN as guess for later + guessHost [lindex [split $host "."] 0] + } +} + +close +wait + +###################################################################### +# next telnet to host and ask it what its name is +###################################################################### + +vprint "talking smtp to $IPaddress" +spawn telnet $IPaddress smtp +expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $host.$domain smtp 1 + + # if not valid FQDN, it's likely either host or domain + if {[string length $domain]} { + guessDomain $host.$domain + } else { + guessHost $host + } + } +} +catch close +wait + +###################################################################### +# ask NIC for any info about this host +###################################################################### + +if {$nic || ($d == 0)} { + vprint "talking to nic" + spawn telnet internic.net + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } "InterNIC >" { + send "whois\r" + expect "Whois: " + vprint "getting info on network $a.$b.$c" + send "net $a.$b.$c\r" + expect { + "No match*" { + vprint "no info" + expect "Whois: " + vprint "getting info on network $a.$b" + send "net $a.$b\r" + expect { + "No match*" { + vprint "no info" + } -re "net\r\n(\[^\r]*)\r" { + printhost $expect_out(1,string) nic 0 + } timeout { + vprint "timed out" + } + } + } -re "net\r\n(\[^\r]*)\r" { + printhost $expect_out(1,string) nic 0 + } timeout { + vprint "timed out" + } + } + } + } + catch close + wait + if {$d == 0} exit +} + +###################################################################### +# ask other hosts in the same class C what their name is +# so that we can at least get the likely domain +# +# do this in two loops - first from current IP address down to 0 +# and then next from current IP address up to 255 +###################################################################### + +# give up guessing host name +guessHost "unknown" + +for {set i [expr $d-1]} {$i>0} {incr i -1} { + vprint "talking smtp to $a.$b.$c.$i" + spawn telnet $a.$b.$c.$i smtp + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 + + # if not valid FQDN, it's likely either host or domain + # don't bother recording host since it can't be for + # original addr. + if {[string length $domain]} { + guessDomain $host.$domain + } + } + } + catch close + wait +} + +for {set i [expr $d+1]} {$i<255} {incr i} { + vprint "talking smtp to $a.$b.$c.$i" + spawn telnet $a.$b.$c.$i smtp + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^ ]*.(\[^ ])) " { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 + + # if not valid FQDN, it's likely either host or domain + # don't bother recording host since it can't be for + # original addr. + if {[string length $domain]} { + guessDomain $host.$domain + } + } + } + catch close + wait +} + +###################################################################### +# print our best guess as to the name +###################################################################### + + +# How pathetic. Print something, anything! +if {!$verbose && !$tag} {send_user [guessFQDN]} diff --git a/example/getpassck b/example/getpassck new file mode 100644 index 0000000..9730e39 --- /dev/null +++ b/example/getpassck @@ -0,0 +1,37 @@ +#!/bin/sh +# \ +exec expect "$0" ${1+"$@"} +# +# Name: getpassck +# +# Description: +# This script demonstrates when programs using getpass sometimes +# fail. The reason is that some implementations of getpass prompt +# before the pty/tty has completed the switch to no-echo. This may +# not be obvious from examination of the implementation of getpass +# itself because the driver itself may cut corners and be +# responsible for allowing the call to return prematurely. +# +# Directions: +# Simply run this script. It will loop 100 times attempting to +# generate the getpass problem. If the bug cannot be reproduced, +# you will see 100 failed attempts to su. If the bug can be +# reproduced, the script exits as soon as it is detected. +# +# Author: Don Libes <don@libes.com> +# Version: 1.0, Wed Mar 9 12:36:12 EST 2005 +# + +for {set i 0} {$i < 100} {incr i} { + spawn -noecho su + expect ": " ;# get password prompt as quickly as possible + send "X\r" ;# send password + expect X { + puts "Password was echoed! This system has the getpass problem." + exit + } "orry" { + close + wait + } +} +puts "Failed to reproduce getpass problem." diff --git a/example/irsh b/example/irsh new file mode 100755 index 0000000..029c8c8 --- /dev/null +++ b/example/irsh @@ -0,0 +1,11 @@ +#!/depot/path/expect -- + +# Do rsh interactively. For example, consider the following command: +# rsh <remote> ls -l "|" more +# where it would be nice to get a listing page by page + +spawn -noecho rlogin [lindex $argv 0] +set timeout -1 +expect "% " ;# customize appropriately +send "[lrange $argv 1 end];exit\r" +interact diff --git a/example/kibitz b/example/kibitz new file mode 100755 index 0000000..eacb139 --- /dev/null +++ b/example/kibitz @@ -0,0 +1,415 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# allow another user to share a shell (or other program) with you +# See kibitz(1) man page for complete info. +# Author: Don Libes, NIST +# Date written: December 5, 1991 +# Date last editted: October 19, 1994 +# Version: 2.11 +exp_version -exit 5.0 + +# if environment variable "EXPECT_PROMPT" exists, it is taken as a regular +# expression which matches the end of your login prompt (but does not other- +# wise occur while logging in). + +set prompt "(%|#|\\$) $" ;# default prompt +set noproc 0 +set tty "" ;# default if no -tty flag +set allow_escape 1 ;# allow escapes if true +set escape_char \035 ;# control-right-bracket +set escape_printable "^\]" +set verbose 1 ;# if true, describe what kibitz is doing + +set kibitz "kibitz" ;# where kibitz lives if some unusual place. + ;# this must end in "kibitz", but can have + ;# things in front (like directory names). +#set proxy "kibitz" ;# uncomment and set if you want kibitz to use + ;# some other account on remote systems + +# The following code attempts to intuit whether cat buffers by default. +# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems. +if {[file exists $exp_exec_library/cat-buffers]} { + set catflags "-u" +} else { + set catflags "" +} +# If this fails, you can also force it by commenting in one of the following. +# Or, you can use the -catu flag to the script. +#set catflags "" +#set catflags "-u" + +# Some flags must be passed onto the remote kibitz process. They are stored +# in "kibitz_flags". Currently, they include -tty and -silent. +set kibitz_flags "" + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -- $flag \ + "-noproc" { + set noproc 1 + set argv [lrange $argv 1 end] + } "-catu" { + set catflags "-u" + set argv [lrange $argv 1 end] + } "-tty" { + set tty [lindex $argv 1] + set argv [lrange $argv 2 end] + set kibitz_flags "$kibitz_flags -tty $tty" + } "-noescape" { + set allow_escape 0 + set argv [lrange $argv 1 end] + } "-escape" { + set escape_char [lindex $argv 1] + set escape_printable $escape_char + set argv [lrange $argv 2 end] + } "-silent" { + set verbose 0 + set argv [lrange $argv 1 end] + set kibitz_flags "$kibitz_flags -silent" + } "-proxy" { + set proxy [lindex $argv 1] + set argv [lrange $argv 2 end] + } default { + break + } +} + +if {([llength $argv]<1) && ($noproc==0)} { + send_user "usage: kibitz \[args] user \[program ...]\n" + send_user " or: kibitz \[args] user@host \[program ...]\n" + exit +} + +log_user 0 +set timeout -1 + +set user [lindex $argv 0] +if {[string match -r $user]} { + send_user "KRUN" ;# this tells user_number 1 that we're running + ;# and to prepare for possible error messages + set user_number 3 + # need to check that it exists first! + set user [lindex $argv 1] +} else { + set user_number [expr 1+(0==[string first - $user])] +} + +# at this point, user_number and user are correctly determined +# User who originated kibitz session has user_number == 1 on local machine. +# User who is responding to kibitz has user_number == 2. +# User who originated kibitz session has user_number == 3 on remote machine. + +# user 1 invokes kibitz as "kibitz user[@host]" +# user 2 invokes kibitz as "kibitz -####" (some pid). +# user 3 invokes kibitz as "kibitz -r user". + +# uncomment for debugging: leaves each user's session in a file: 1, 2 or 3 +#exec rm -f $user_number +#exp_internal -f $user_number 0 + +set user2_islocal 1 ;# assume local at first + +# later move inside following if $user_number == 1 +# return true if x is a prefix of xjunk, given that prefixes are only +# valid at . delimiters +# if !do_if0, skip the whole thing - this is here just to make caller simpler +proc is_prefix {do_if0 x xjunk} { + if 0!=$do_if0 {return 0} + set split [split $xjunk .] + for {set i [expr [llength $split]-1]} {$i>=0} {incr i -1} { + if {[string match $x [join [lrange $split 0 $i] .]]} {return 1} + } + return 0 +} + +# get domainname. Unfortunately, on some systems, domainname(1) +# returns NIS domainname which is not the internet domainname. +proc domainname {} { + # open pops stack upon failure + set rc [catch {open /etc/resolv.conf r} file] + if {$rc==0} { + while {-1!=[gets $file buf]} { + if 1==[scan $buf "domain %s" name] { + close $file + return $name + } + } + close $file + } + + # fall back to using domainname + if {0==[catch {exec domainname} name]} {return $name} + + error "could not figure out domainname" +} + +if $user_number==1 { + if $noproc==0 { + if {[llength $argv]>1} { + set pid [eval spawn [lrange $argv 1 end]] + } else { + # if running as CGI, shell may not be set! + set shell /bin/sh + catch {set shell $env(SHELL)} + set pid [spawn $shell] + } + set shell $spawn_id + } + + # is user2 remote? + regexp (\[^@\]*)@*(.*) $user ignore tmp host + set user $tmp + if ![string match $host ""] { + set h_rc [catch {exec hostname} hostname] + set d_rc [catch domainname domainname] + + if {![is_prefix $h_rc $host $hostname] + && ![is_prefix $d_rc $host $hostname.$domainname]} { + set user2_islocal 0 + } + } + + if !$user2_islocal { + if $verbose {send_user "connecting to $host\n"} + + if ![info exists proxy] { + proc whoami {} { + global env + if {[info exists env(USER)]} {return $env(USER)} + if {[info exists env(LOGNAME)]} {return $env(LOGNAME)} + if {![catch {exec whoami} user]} {return $user} + if {![catch {exec logname} user]} {return $user} + # error "can't figure out who you are!" + } + set proxy [whoami] + } + spawn rlogin $host -l $proxy -8 + set userin $spawn_id + set userout $spawn_id + + catch {set prompt $env(EXPECT_PROMPT)} + + set timeout 120 + expect { + assword: { + stty -echo + send_user "password (for $proxy) on $host: " + set old_timeout $timeout; set timeout -1 + expect_user -re "(.*)\n" + send_user "\n" + set timeout $old_timeout + send "$expect_out(1,string)\r" + # bother resetting echo? + exp_continue + } incorrect* { + send_user "invalid password or account\n" + exit + } "TERM = *) " { + send "\r" + exp_continue + } timeout { + send_user "connection to $host timed out\n" + exit + } eof { + send_user "connection to host failed: $expect_out(buffer)" + exit + } -re $prompt + } + if {$verbose} {send_user "starting kibitz on $host\n"} + # the kill protects user1 from receiving user3's + # prompt if user2 exits via expect's exit. + send "$kibitz $kibitz_flags -r $user;kill -9 $$\r" + + expect { + -re "kibitz $kibitz_flags -r $user.*KRUN" {} + -re "kibitz $kibitz_flags -r $user.*(kibitz\[^\r\]*)\r" { + send_user "unable to start kibitz on $host: \"$expect_out(1,string)\"\n" + send_user "try rlogin by hand followed by \"kibitz $user\"\n" + exit + } + timeout { + send_user "unable to start kibitz on $host: " + set expect_out(buffer) "timed out" + set timeout 0; expect -re .+ + send_user $expect_out(buffer) + exit + } + } + expect { + -re ".*\n" { + # pass back diagnostics + # should really strip out extra cr + send_user $expect_out(buffer) + exp_continue + } + KABORT exit + default exit + KDATA + } + } +} + +if {$user_number==2} { + set pid [string trimleft $user -] +} + +set local_io [expr ($user_number==3)||$user2_islocal] +if {$local_io||($user_number==2)} { + if {0==[info exists pid]} {set pid [pid]} + + set userinfile /tmp/exp0.$pid + set useroutfile /tmp/exp1.$pid +} + +proc prompt1 {} { + return "kibitz[info level].[history nextid]> " +} + +set esc_match {} +if {$allow_escape} { + set esc_match { + $escape_char { + send_user "\nto exit kibitz, enter: exit\n" + send_user "to suspend kibitz, press appropriate job control sequence\n" + send_user "to return to kibitzing, enter: return\n" + interpreter + send_user "returning to kibitz\n" + } + } +} + +proc prompt1 {} { + return "kibitz[info level].[history nextid]> " +} + +set timeout -1 + +# kibitzer executes following code +if {$user_number==2} { + # for readability, swap variables + set tmp $userinfile + set userinfile $useroutfile + set useroutfile $tmp + + if ![file readable $userinfile] { + send_user "Eh? No one is asking you to kibitz.\n" + exit -1 + } + spawn -open [open "|cat $catflags < $userinfile" "r"] + set userin $spawn_id + + spawn -open [open $useroutfile w] + set userout $spawn_id + # open will hang until other user's cat starts + + stty -echo raw + if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"} + + # While user is reading message, try to delete other fifo + catch {exec rm -f $userinfile} + + eval interact $esc_match \ + -output $userout \ + -input $userin + + exit +} + +# only user_numbers 1 and 3 execute remaining code + +proc abort {} { + # KABORT tells user_number 1 that user_number 3 has run into problems + # and is exiting, and diagnostics have been returned already + if {$::user_number==3} {send_user KABORT} + exit +} + +if {$local_io} { + proc mkfifo {f} { + if 0==[catch {exec mkfifo $f}] return ;# POSIX + if 0==[catch {exec mknod $f p}] return + # some systems put mknod in wierd places + if 0==[catch {exec /usr/etc/mknod $f p}] return ;# Sun + if 0==[catch {exec /etc/mknod $f p}] return ;# AIX, Cray + puts "Couldn't figure out how to make a fifo - where is mknod?" + abort + } + + proc rmfifos {} { + global userinfile useroutfile + catch {exec rm -f $userinfile $useroutfile} + } + + trap {rmfifos; exit} {SIGINT SIGQUIT SIGTERM} + + # create 2 fifos to communicate with other user + mkfifo $userinfile + mkfifo $useroutfile + # make sure other user can access despite umask + exec chmod 666 $userinfile $useroutfile + + if {$verbose} {send_user "asking $user to type: kibitz -$pid\n"} + + # can't use exec since write insists on being run from a tty! + set rc [catch { + system echo "Can we talk? Run: \"kibitz -$pid\"" | \ + write $user $tty + } + ] + if {$rc} {rmfifos;abort} + + spawn -open [open $useroutfile w] + set userout $spawn_id + # open will hang until other user's cat starts + + spawn -open [open "|cat $catflags < $userinfile" "r"] + set userin $spawn_id + catch {exec rm $userinfile} +} + +stty -echo raw + +if {$user_number==3} { + send_user "KDATA" ;# this tells user_number 1 to send data + + interact { + -output $userout + -input $userin eof { + wait -i $userin + return -tcl + } -output $user_spawn_id + } +} else { + if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"} + + if {$noproc} { + interact { + -output $userout + -input $userin eof {wait -i $userin; return} + -output $user_spawn_id + } + } else { + eval interact $esc_match { + -output $shell \ + -input $userin eof { + wait -i $userin + close -i $shell + return + } -output $shell \ + -input $shell eof { + close -i $userout + wait -i $userout + return + } -output "$user_spawn_id $userout" + } + wait -i $shell + } +} + +if {$local_io} rmfifos diff --git a/example/kibitz.man b/example/kibitz.man new file mode 100644 index 0000000..ef1d320 --- /dev/null +++ b/example/kibitz.man @@ -0,0 +1,266 @@ +.TH KIBITZ 1 "19 October 1994" +.SH NAME +kibitz \- allow two people to interact with one shell +.SH SYNOPSIS +.B kibitz +[ +.I kibitz-args +] +.I user +[ +.I program program-args... +] +.br +.B kibitz +[ +.I kibitz-args +] +.I user@host +[ +.I program program-args... +] +.SH INTRODUCTION +.B kibitz +allows two (or more) people to interact with one shell (or any arbitrary +program). Uses include: +.RS +.TP 4 +\(bu +A novice user can ask an expert user for help. Using +.BR kibitz , +the expert can see what the user is doing, and offer advice or +show how to do it right. +.TP +\(bu +By running +.B kibitz +and then starting a full-screen editor, people may carry out a +conversation, retaining the ability to scroll backwards, +save the entire conversation, or even edit it while in progress. +.TP +\(bu +People can team up on games, document editing, or other cooperative +tasks where each person has strengths and weaknesses that complement one +another. +.SH USAGE +To start +.BR kibitz , +user1 +runs kibitz with the argument of the +user to kibitz. For example: + + kibitz user2 + +.B kibitz +starts a new shell (or another program, if given on the command +line), while prompting user2 to run +.BR kibitz . +If user2 runs +.B kibitz +as directed, the keystrokes of both users become the input of +the shell. Similarly, both users receive the output from the +shell. + +To terminate +.B kibitz +it suffices to terminate the shell itself. For example, if either user +types ^D (and the shell accepts this to be EOF), the shell terminates +followed by +.BR kibitz . + +Normally, all characters are passed uninterpreted. However, if the +escape character (described when +.B kibitz +starts) is issued, the user +may talk directly to the +.B kibitz +interpreter. Any +.BR Expect (1) +or +.BR Tcl (3) +commands may be given. +Also, job control may be used while in the interpreter, to, for example, +suspend or restart +.BR kibitz . + +Various processes +can provide various effects. For example, you can emulate a two-way write(1) +session with the command: + + kibitz user2 sleep 1000000 +.SH ARGUMENTS +.B kibitz +takes arguments, these should also be separated by whitespace. + +The +.B \-noproc +flag runs +.B kibitz +with no process underneath. Characters are passed to the other +.BR kibitz . +This is particularly useful for connecting multiple +interactive processes together. +In this mode, characters are not echoed back to the typist. + +.B \-noescape +disables the escape character. + +.BI \-escape " char" +sets the escape character. The default escape character is ^]. + +.B \-silent +turns off informational messages describing what kibitz is doing to +initiate a connection. + +.BI \-tty " ttyname" +defines the tty to which the invitation should be sent. + +If you start +.B kibitz +to user2 on a remote computer, +.B kibitz +performs a +.B rlogin +to the remote computer with your current username. The flag +.BI \-proxy " username" +causes +.B rlogin +to use +.I username +for the remote login (e.g. if your account on the remote computer has a +different username). If the +.B -proxy +flag is not given, +.B kibitz +tries to determine your current username by (in that order) inspecting the +environment variables USER and LOGNAME, then by using the commands +.B whoami +and +.BR logname . + +The arguments +.B -noescape +and +.B -escape +can also be given by user2 when prompted to run +.BR kibitz . + +.SH MORE THAN TWO USERS +The current implementation of kibitz explicitly understands only two users, +however, it is nonetheless possible to have a three (or more) -way kibitz, +by kibitzing another +.BR kibitz . +For example, the following command runs +.B kibitz +with the current user, user2, and user3: + + % kibitz user2 kibitz user3 + +Additional users may be added by simply appending more "kibitz user" +commands. + +The +.B xkibitz +script is similar to +.B kibitz +but supports the ability to add additional users (and drop them) +dynamically. +.SH CAVEATS +.B kibitz +assumes the 2nd user has the same terminal type and size as the 1st user. +If this assumption is incorrect, graphical programs may display oddly. + +.B kibitz +handles character graphics, but cannot handle bitmapped graphics. Thus, +.nf + + % xterm -e kibitz will work + % kibitz xterm will not work + +.fi +However, you can get the effect of the latter command by using +.B xkibitz +(see SEE ALSO below). +.B kibitz +uses the same permissions as used by rlogin, rsh, etc. Thus, you +can only +.B kibitz +to users at hosts for which you can rlogin. +Similarly, +.B kibitz +will prompt for a password on the remote host if +rlogin would. + +If you +.B kibitz +to users at remote hosts, +.B kibitz +needs to distinguish your prompt from other things that may precede it +during login. +(Ideally, the end of it is preferred but any part should suffice.) +If you have an unusual prompt, +set the environment variable EXPECT_PROMPT to an egrep(1)-style +regular expression. +Brackets should be preceded with one backslash in ranges, +and three backslashes for literal brackets. +The default prompt r.e. is "($|%|#)\ ". + +.B kibitz +requires the +.B kibitz +program on both hosts. +.B kibitz +requires +.BR expect (1). + +By comparison, the +.B xkibitz +script uses the X authorization mechanism for inter-host communication +so it does not need to login, recognize your prompt, or require kibitz +on the remote host. It does however need permission to access +the other X servers. +.SH BUGS +An early version of Sun's tmpfs had a bug in it that causes +.B kibitz +to blow up. If +.B kibitz +reports "error flushing ...: Is a directory" +ask Sun for patch #100174. + +If your Expect is not compiled with multiple-process support (i.e., you do not +have a working select or poll), you will not be able to run kibitz. +.SH ENVIRONMENT +The environment variable SHELL is used to determine the shell to start, if no +other program is given on the command line. + +If the environment variable EXPECT_PROMPT exists, it is taken as a regular +expression which matches the end of your login prompt (but does not otherwise +occur while logging in). See also CAVEATS above. + +If the environment variables USER or LOGNAME are defined, they are used to +determine the current user name for a +.B kibitz +to a remote computer. See description of the +.B -proxy +option in ARGUMENTS above. +.SH SEE ALSO +.BR Tcl (3), +.BR libexpect (3), +.BR xkibitz (1) +.br +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.br +.I +"Kibitz \- Connecting Multiple Interactive Programs Together", \fRby Don Libes, +Software \- Practice & Experience, John Wiley & Sons, West Sussex, England, +Vol. 23, No. 5, May, 1993. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology + +.B kibitz +is in the public domain. +NIST and I would +appreciate credit if this program or parts of it are used. diff --git a/example/lpunlock b/example/lpunlock new file mode 100755 index 0000000..2b7ea24 --- /dev/null +++ b/example/lpunlock @@ -0,0 +1,101 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# This script unhangs a printer which claims it is "waiting for lock". +# Written by Don Libes. Based on English instructions from Scott Paisley. + +# lpunlock figures out if the printer is on a server, and if so which, +# by looking in the local printcap file. (You can override this by +# supplying a server name as an additional argument.) It then rlogins +# to the server, recreates the device and resets the queue via lpc. + +# assumes user has root privs on remote host via /.rhosts + +# assumes printer is name of device on remote system + +proc usage {} { + send_user "usage: lpunlock <printer> \[<server>\]\n" + send_user "example: lpunlock lw-isg durer\n" + exit +} + +if {$argc==0} usage +set printer [lindex $argv 0] + +set client [exec hostname] + +if {$argc == 1} { + # if no arg2, look in local printcap for info + spawn ed /etc/printcap + expect "\n" ;# discard character count + send "/$printer/\r" + for {} {1} {} { + expect -re ".*:rm=(\[^:]*):.*\r\n" { + set server $expect_out(1,string) + break + } "\r\n*\\\r\n" { ;# look at next line of entry + send "\r" + } "\r\n*\n" { ;# no more lines of entry - give up + set server $client + break + } + } +} else { + if {$argc == 2} { + set server [lindex $argv 1] + } else usage +} + +set whoami [exec whoami] +if {[string match $server $client] && [string match $whoami "root"]} { + spawn csh + expect "# " +} else { + # login to the print server as root. + # Set timeout high because login is slow. + set timeout 60 + spawn rlogin $server -l root + expect timeout exit \ + eof exit \ + "Password*" { + send_user "\ncouldn't login to $server as root\n" + exit + } "1#*" + set timeout 10 +} + +# run lpc and 'stop printer' +send lpc\r ; expect "lpc>*" +send stop $printer\r ; expect "unknown*" exit \ + "disabled*lpc>*" + +# exit lpc and cd /dev +send quit\r ; expect "#*" +send cd /dev\r ; expect "#*" + +# figure out major/minor device numbers +send ls -l /dev/$printer\r ; expect timeout { + send_user "\nbad device - couldn't get major/minor numbers\n"; exit + } "crw*#*" +scan $expect_out(buffer) "ls -l %*s %*s 1 root %d, %d" major minor + +# delete the lock and the printer device itself +send rm /var/spool/$printer/lock /dev/$printer\r ; expect #* + +# recreate the printer device +send mknod $printer c $major $minor\r ; expect #* + +# run lpc and 'start printer' +send lpc\r ; expect lpc>* +send start $printer\r ; expect started*lpc>* +send quit\r ; expect #* + +# logout +send exit\r ; expect eof + +send_user Printer unlocked and restarted.\n diff --git a/example/mkpasswd b/example/mkpasswd new file mode 100755 index 0000000..6016b56 --- /dev/null +++ b/example/mkpasswd @@ -0,0 +1,216 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# mkpasswd - make a password, if username given, set it. +# Author: Don Libes, NIST + +# defaults +set length 9 +set minnum 2 +set minlower 2 +set minupper 2 +set minspecial 1 +set verbose 0 +set distribute 0 + +if {[file executable /bin/nispasswd]} { + set defaultprog /bin/nispasswd +} elseif {[file executable /bin/yppasswd]} { + set defaultprog /bin/yppasswd +} elseif {[file executable /bin/passwd]} { + set defaultprog /bin/passwd +} else { + set defaultprog passwd +} +set prog $defaultprog + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -- $flag \ + "-l" { + set length [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-d" { + set minnum [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-c" { + set minlower [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-C" { + set minupper [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-s" { + set minspecial [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-v" { + set verbose 1 + set argv [lrange $argv 1 end] + } "-p" { + set prog [lindex $argv 1] + set argv [lrange $argv 2 end] + } "-2" { + set distribute 1 + set argv [lrange $argv 1 end] + } default { + set user [lindex $argv 0] + set argv [lrange $argv 1 end] + break + } +} + +if {[llength $argv]} { + puts "usage: mkpasswd \[args] \[user]" + puts " where arguments are:" + puts " -l # (length of password, default = $length)" + puts " -d # (min # of digits, default = $minnum)" + puts " -c # (min # of lowercase chars, default = $minlower)" + puts " -C # (min # of uppercase chars, default = $minupper)" + puts " -s # (min # of special chars, default = $minspecial)" + puts " -v (verbose, show passwd interaction)" + puts " -p prog (program to set password, default = $defaultprog)" + exit 1 +} + +if {$minnum + $minlower + $minupper + $minspecial > $length} { + puts "impossible to generate $length-character password\ + with $minnum numbers, $minlower lowercase letters,\ + $minupper uppercase letters and\ + $minspecial special characters." + exit 1 +} + +# if there is any underspecification, use additional lowercase letters +set minlower [expr {$length - ($minnum + $minupper + $minspecial)}] + +set lpass "" ;# password chars typed by left hand +set rpass "" ;# password chars typed by right hand + +# insert char into password at a random position, thereby spreading +# the different kinds of characters throughout the password +proc insert {pvar char} { + upvar $pvar p + + set p [linsert $p [rand [expr {(1+[llength $p])}]] $char] +} + +proc rand {m} { + expr {int($m*rand())} +} + +# choose left or right starting hand +set initially_left [set isleft [rand 2]] + +# given a size, distribute between left and right hands +# taking into account where we left off +proc psplit {max lvar rvar} { + upvar $lvar left $rvar right + global isleft + + if {$isleft} { + set right [expr $max/2] + set left [expr $max-$right] + set isleft [expr !($max%2)] + } else { + set left [expr $max/2] + set right [expr $max-$left] + set isleft [expr $max%2] + } +} + +if {$distribute} { + set lkeys {q w e r t a s d f g z x c v b} + set rkeys {y u i o p h j k l n m} + set lnums {1 2 3 4 5 6} + set rnums {7 8 9 0} + set lspec {! @ # \$ %} + set rspec {^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /} +} else { + set lkeys {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} + set rkeys {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} + set lnums {0 1 2 3 4 5 6 7 8 9} + set rnums {0 1 2 3 4 5 6 7 8 9} + set lspec {! @ # \$ % ~ ^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /} + set rspec {! @ # \$ % ~ ^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /} +} + +set lkeys_length [llength $lkeys] +set rkeys_length [llength $rkeys] +set lnums_length [llength $lnums] +set rnums_length [llength $rnums] +set lspec_length [llength $lspec] +set rspec_length [llength $rspec] + +psplit $minnum left right +for {set i 0} {$i<$left} {incr i} { + insert lpass [lindex $lnums [rand $lnums_length]] +} +for {set i 0} {$i<$right} {incr i} { + insert rpass [lindex $rnums [rand $rnums_length]] +} + +psplit $minlower left right +for {set i 0} {$i<$left} {incr i} { + insert lpass [lindex $lkeys [rand $lkeys_length]] +} +for {set i 0} {$i<$right} {incr i} { + insert rpass [lindex $rkeys [rand $rkeys_length]] +} + +psplit $minupper left right +for {set i 0} {$i<$left} {incr i} { + insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]] +} +for {set i 0} {$i<$right} {incr i} { + insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]] +} + +psplit $minspecial left right +for {set i 0} {$i<$left} {incr i} { + insert lpass [lindex $lspec [rand $lspec_length]] +} +for {set i 0} {$i<$right} {incr i} { + insert rpass [lindex $rspec [rand $rspec_length]] +} + +# merge results together +foreach l $lpass r $rpass { + if {$initially_left} { + append password $l $r + } else { + append password $r $l + } +} + +if {[info exists user]} { + if {!$verbose} { + log_user 0 + } + + spawn $prog $user + expect { + "assword*:" { + # some systems say "Password (again):" + send "$password\r" + exp_continue + } + } + + # if user isn't watching, check status + if {!$verbose} { + if {[lindex [wait] 3]} { + puts -nonewline "$expect_out(buffer)" + exit 1 + } + } + + if {$verbose} { + puts -nonewline "password for $user is " + } +} + +puts "$password" diff --git a/example/mkpasswd.man b/example/mkpasswd.man new file mode 100644 index 0000000..9da760c --- /dev/null +++ b/example/mkpasswd.man @@ -0,0 +1,100 @@ +.TH MKPASSWD 1 "22 August 1994" +.SH NAME +mkpasswd \- generate new password, optionally apply it to a user +.SH SYNOPSIS +.B mkpasswd +.I +[ +.I args +] +[ +.I user +] +.SH INTRODUCTION +.B mkpasswd +generates passwords and can apply them automatically to users. +mkpasswd is based on the code from Chapter 23 of the O'Reilly book +"Exploring Expect". +.SH USAGE +With no arguments, +.B mkpasswd +returns a new password. + + mkpasswd + +With a user name, +.B mkpasswd +assigns a new password to the user. + + mkpasswd don + +The passwords are randomly generated according to the flags below. + +.SH FLAGS +The +.B \-l +flag defines the length of the password. The default is 9. +The following example creates a 20 character password. + + mkpasswd -l 20 + +The +.B \-d +flag defines the minimum number of digits that must be in the password. +The default is 2. The following example creates a password with at least +3 digits. + + mkpasswd -d 3 + +The +.B \-c +flag defines the minimum number of lowercase alphabetic characters that must be in the password. +The default is 2. + +The +.B \-C +flag defines the minimum number of uppercase alphabetic characters that must be in the password. +The default is 2. + +The +.B \-s +flag defines the minimum number of special characters that must be in the password. +The default is 1. + +The +.B \-p +flag names a program to set the password. +By default, /etc/yppasswd is used if present, otherwise /bin/passwd is used. + +The +.B \-2 +flag causes characters to be chosen so that they alternate between +right and left hands (qwerty-style), making it harder for anyone +watching passwords being entered. This can also make it easier for +a password-guessing program. + +The +.B \-v +flag causes the password-setting interaction to be visible. +By default, it is suppressed. + +.SH EXAMPLE +The following example creates a 15-character password +that contains at least 3 digits and 5 uppercase characters. + + mkpasswd -l 15 -d 3 -C 5 + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology + +.B mkpasswd +is in the public domain. +NIST and I would +appreciate credit if this program or parts of it are used. + + diff --git a/example/multixterm b/example/multixterm new file mode 100755 index 0000000..d0abfe7 --- /dev/null +++ b/example/multixterm @@ -0,0 +1,993 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# +# NAME +# multixterm - drive multiple xterms separately or together +# +# SYNOPSIS +# multixterm [-xa "xterm args"] +# [-xc "command"] +# [-xd "directory"] +# [-xf "file"] +# [-xn "xterm names"] +# [-xv] (enable verbose mode) +# [-xh] or [-x?] (help) +# [xterm names or user-defined args...] +# +# DESCRIPTION +# Multixterm creates multiple xterms that can be driven together +# or separately. +# +# In its simplest form, multixterm is run with no arguments and +# commands are interactively entered in the first entry field. +# Press return (or click the "new xterm" button) to create a new +# xterm running that command. +# +# Keystrokes in the "stdin window" are redirected to all xterms +# started by multixterm. xterms may be driven separately simply +# by focusing on them. +# +# The stdin window must have the focus for keystrokes to be sent +# to the xterms. When it has the focus, the color changes to +# aquamarine. As characters are entered, the color changes to +# green for a second. This provides feedback since characters +# are not echoed in the stdin window. +# +# Typing in the stdin window while holding down the alt or meta +# keys sends an escape character before the typed characters. +# This provides support for programs such as emacs. +# +# ARGUMENTS +# The optional -xa argument indicates arguments to pass to +# xterm. +# +# The optional -xc argument indicates a command to be run in +# each named xterm (see -xn). With no -xc argument, the command +# is the current shell. +# +# The optional -xd argument indicates a directory to search for +# files that will appear in the Files menu. By default, the +# directory is: ~/lib/multixterm +# +# The optional -xf argument indicates a file to be read at +# startup. See FILES below for more info. +# +# The optional -xn argument indicates a name for each xterm. +# This name will also be substituted for any %n in the command +# argument (see -xc). +# +# The optional -xv flag puts multixterm into a verbose mode +# where it will describe some of the things it is doing +# internally. The verbose output is not intended to be +# understandable to anyone but the author. +# +# Less common options may be changed by the startup file (see +# FILES below). +# +# All the usual X and wish flags are supported (i.e., -display, +# -name). There are so many of them that to avoid colliding and +# make them easy to remember, all the multixterm flags begin +# with -x. +# +# If any arguments do not match the flags above, the remainder +# of the command line is made available for user processing. By +# default, the remainder is used as a list of xterm names in the +# style of -xn. The default behavior may be changed using the +# .multixtermrc file (see DOT FILE below). +# +# EXAMPLE COMMAND LINE ARGUMENTS +# The following command line starts up two xterms using ssh to +# the hosts bud and dexter. +# +# multixterm -xc "ssh %n" bud dexter +# +# FILES +# Command files may be used to drive or initialize multixterm. +# The File menu may be used to invoke other files. If files +# exist in the command file directory (see -xd above), they will +# appear in the File menu. Files may also be loaded by using +# File->Open. Any filename is acceptable but the File->Open +# browser defaults to files with a .mxt suffix. +# +# Files are written in Tcl and may change any variables or +# invoke any procedures. The primary variables of interest are +# 'xtermCmd' which identifies the command (see -xc) and +# 'xtermNames' which is a list of names (see -xn). The +# procedure xtermStartAll, starts xterms for each name in the +# list. Other variables and procedures may be discovered by +# examining multixterm itself. +# +# EXAMPLE FILE +# The following file does the same thing as the earlier example +# command line: +# +# # start two xterms connected to bud and dexter +# set xtermCmd "ssh %n" +# set xtermNames {bud dexter} +# xtermStartAll +# +# DOT FILE +# At startup, multixterm reads ~/.multixtermrc if present. This +# is similar to the command files (see FILES above) except that +# .multixtermrc may not call xtermStartAll. Instead it is +# called implicitly, similar to the way that it is implicit in +# the command line use of -xn. +# +# The following example .multixtermrc file makes every xterm run +# ssh to the hosts named on the command line. +# +# set xtermCmd "ssh %n" +# +# Then multixterm could be called simply: +# +# multixterm bud dexter +# +# If any command-line argument does not match a multixterm flag, +# the remainder of the command line is made available to +# .multixtermrc in the argv variable. If argv is non-empty when +# .multixtermrc returns, it is assigned to xtermNames unless +# xtermNames is non-empty in which case, the content of argv is +# ignored. +# +# Commands from .multixtermrc are evaluated early in the +# initialization of multixterm. Anything that must be done late +# in the initialization (such as adding additional bindings to +# the user interface) may be done by putting the commands inside +# a procedure called "initLate". +# +# MENUS +# Except as otherwise noted, the menus are self-explanatory. +# Some of the menus have dashed lines as the first entry. +# Clicking on the dashed lines will "tear off" the menus. +# +# USAGE SUGGESTION - ALIASES AND COMMAND FILES +# Aliases may be used to store lengthy command-line invocations. +# Command files can be also be used to store such invocations +# as well as providing a convenient way to share configurations. +# +# Tcl is a general-purpose language. Thus multixterm command +# files can be extremely flexible, such as loading hostnames +# from other programs or files that may change from day-to-day. +# In addition, command files can be used for other purposes. +# For example, command files may be used to prepared common +# canned interaction sequences. For example, the command to +# send the same string to all xterms is: +# +# xtermSend "a particularly long string" +# +# The File menu (torn-off) makes canned sequences particularly +# convenient. Interactions could also be bound to a mouse +# button, keystroke, or added to a menu via the .multixtermrc +# file. +# +# USAGE SUGGESTION - HANDLING MANY XTERMS BY TILING +# The following .multixtermrc causes tiny xterms to tile across +# and down the screen. (You may have to adjust the parameters +# for your screen.) This can be very helpful when dealing with +# large numbers of xterms. +# +# set yPos 0 +# set xPos 0 +# +# trace variable xtermArgs r traceArgs +# +# proc traceArgs {args} { +# global xPos yPos +# set ::xtermArgs "-geometry 80x12+$xPos+$yPos -font 6x10" +# if {$xPos} { +# set xPos 0 +# incr yPos 145 +# if {$yPos > 800} {set yPos 0} +# } else { +# set xPos 500 +# } +# } +# +# The xtermArgs variable in the code above is the variable +# corresponding to the -xa argument. +# +# xterms can be also be created directly. The following command +# file creates three xterms overlapped horizontally: +# +# set xPos 0 +# +# foreach name {bud dexter hotdog} { +# set ::xtermArgs "-geometry 80x12+$xPos+0 -font 6x10" +# set ::xtermNames $name +# xtermStartAll +# incr xPos 300 +# } +# +# USAGE SUGGESTION - SELECTING HOSTS BY NICKNAME +# The following .multixtermrc shows an example of changing the +# default handling of the arguments from hostnames to a filename +# containing hostnames: +# +# set xtermNames [exec cat $argv] +# +# The following is a variation, retrieving the host names from +# the yp database: +# +# set xtermNames [exec ypcat $argv] +# +# The following hardcodes two sets of hosts, so that you can +# call multixterm with either "cluster1" or "cluster2": +# +# switch $argv { +# cluster1 { +# set xtermNames "bud dexter" +# } +# cluster2 { +# set xtermNames "frank hotdog weiner" +# } +# } +# +# COMPARE/CONTRAST +# It is worth comparing multixterm to xkibitz. Multixterm +# connects a separate process to each xterm. xkibitz connects +# the same process to each xterm. +# +# LIMITATIONS +# Multixterm provides no way to remotely control scrollbars, +# resize, and most other window system related functions. +# +# Multixterm can only control new xterms that multixterm itself +# has started. +# +# As a convenience, the File menu shows a limited number of +# files. To show all the files, use File->Open. +# +# FILES +# $DOTDIR/.multixtermrc initial command file +# ~/.multixtermrc fallback command file +# ~/lib/multixterm/ default command file directory +# +# BUGS +# If multixterm is killed using an uncatchable kill, the xterms +# are not killed. This appears to be a bug in xterm itself. +# +# Send/expect sequences can be done in multixterm command files. +# However, due to the richness of the possibilities, to document +# it properly would take more time than the author has at present. +# +# REQUIREMENTS +# Requires Expect 5.36.0 or later. +# Requires Tk 8.3.3 or later. +# +# VERSION +#! $::versionString +# The latest version of multixterm is available from +# http://expect.nist.gov/example/multixterm . If your version of Expect +# and Tk are too old (see REQUIREMENTS above), download a new version of +# Expect from http://expect.nist.gov +# +# DATE +#! $::versionDate +# +# AUTHOR +# Don Libes <don@libes.com> +# +# LICENSE +# Multixterm is in the public domain; however the author would +# appreciate acknowledgement if multixterm or parts of it or ideas from +# it are used. + +###################################################################### +# user-settable things - override them in the ~/.multixtermrc file +# or via command-line options +###################################################################### + +set palette #d8d8ff ;# lavender +set colorTyping green +set colorFocusIn aquamarine + +set xtermNames {} +set xtermCmd $env(SHELL) +set xtermArgs "" +set cmdDir ~/lib/multixterm +set inputLabel "stdin window" + +set fileMenuMax 30 ;# max number of files shown in File menu +set tearoffMenuMin 2 ;# min number of files needed to enable the File + ;# menu to be torn off + +proc initLate {} {} ;# anything that must be done late in initialization + ;# such as adding/modifying bindings, may be done by + ;# redefining this + +###################################################################### +# end of user-settable things +###################################################################### + +###################################################################### +# sanity checking +###################################################################### + +set versionString 1.8 +set versionDate "2004/06/29" + +package require Tcl +catch {package require Tk} ;# early versions of Tk had no package +package require Expect + +proc exit1 {msg} { + puts "multixterm: $msg" + exit 1 +} + +exp_version -exit 5.36 + +proc tkBad {} { + exit1 "requires Tk 8.3.3 or later but you are using Tk $::tk_patchLevel." +} + +if {$tk_version < 8.3} { + tkBad +} elseif {$tk_version == 8.3} { + if {[lindex [split $tk_patchLevel .] 2] < 3} tkBad +} + +###################################################################### +# process args - has to be done first to get things like -xv working ASAP +###################################################################### + +# set up verbose mechanism early + +set verbose 0 +proc verbose {msg} { + if {$::verbose} { + if {[info level] > 1} { + set proc [lindex [info level -1] 0] + } else { + set proc main + } + puts "$proc: $msg" + } +} + +# read a single argument from the command line +proc arg_read1 {var args} { + if {0 == [llength $args]} { + set argname -$var + } else { + set argname $args + } + + upvar argv argv + upvar $var v + + verbose "$argname" + if {[llength $argv] < 2} { + exit1 "$argname requires an argument" + } + + set v [lindex $argv 1] + verbose "set $var $v" + set argv [lrange $argv 2 end] +} + +proc xtermUsage {{msg {}}} { + if {![string equal $msg ""]} { + puts "multixtermrc: $msg" + } + puts {usage: multixterm [flags] ... where flags are: + [-xa "xterm args"] + [-xc "command"] + [-xd "directory"] + [-xf "file"] + [-xn "xterm names"] + [-xv] (enable verbose mode) + [-xh] or [-x?] (help) + [xterm names or user-defined args...]} + exit +} + +while {[llength $argv]} { + set flag [lindex $argv 0] + switch -- $flag -x? - -xh { + xtermUsage + } -xc { + arg_read1 xtermCmd -xc + } -xn { + arg_read1 xtermNames -xn + } -xa { + arg_read1 xtermArgs -xa + } -xf { + arg_read1 cmdFile -xf + if {![file exists $cmdFile]} { + exit1 "can't read $cmdFile" + } + } -xd { + arg_read1 cmdDir -xd + if {![file exists $cmdDir]} { + exit1 "can't read $cmdDir" + } + } -xv { + set argv [lrange $argv 1 end] + set verbose 1 + puts "main: verbose on" + } default { + verbose "remaining args: $argv" + break ;# let user handle remaining args later + } +} + +###################################################################### +# determine and load rc file - has to be done now so that widgets +# can be affected +###################################################################### + +# if user has no $DOTDIR, fall back to home directory +if {![info exists env(DOTDIR)]} { + set env(DOTDIR) ~ +} +# catch bogus DOTDIR, otherwise glob will lose the bogus directory +# and it won't appear in the error msg +if {[catch {glob $env(DOTDIR)} dotdir]} { + exit1 "$env(DOTDIR)/.multixtermrc can't be found because $env(DOTDIR) doesn't exist or can't be read" +} +set rcFile $dotdir/.multixtermrc + +set fileTypes { + {{Multixterm Files} *.mxt} + {{All Files} *} +} + +proc openFile {{fn {}}} { + verbose "opening $fn" + if {[string equal $fn ""]} { + set fn [tk_getOpenFile \ + -initialdir $::cmdDir \ + -filetypes $::fileTypes \ + -title "multixterm file"] + if {[string match $fn ""]} return + } + uplevel #0 source [list $fn] + verbose "xtermNames = \"$::xtermNames\"" + verbose "xtermCmd = $::xtermCmd" +} + +if {[file exists $rcFile]} { + openFile $rcFile +} else { + verbose "$rcFile: not found" +} + +if {![string equal "" $argv]} { + if {[string equal $xtermNames ""]} { + set xtermNames $argv + } +} + +###################################################################### +# Describe and initialize some important globals +###################################################################### + +# ::activeList and ::activeArray both track which xterms to send +# (common) keystrokes to. Each element in activeArray is connected to +# the active menu. The list version is just a convenience making the +# send function easier/faster. + +set activeList {} + +# ::names is an array of xterm names indexed by process spawn ids. + +set names(x) "" +unset names(x) + +# ::xtermSid is an array of xterm spawn ids indexed by process spawn ids. +# ::xtermPid is an array of xterm pids indexed by process spawn id. + +###################################################################### +# create an xterm and establish connections +###################################################################### + +proc xtermStart {cmd name} { + verbose "starting new xterm running $cmd with name $name" + + ###################################################################### + # create pty for xterm + ###################################################################### + set pid [spawn -noecho -pty] + verbose "spawn -pty: pid = $pid, spawn_id = $spawn_id" + set sidXterm $spawn_id + stty raw -echo < $spawn_out(slave,name) + + regexp ".*(.)(.)" $spawn_out(slave,name) dummy c1 c2 + if {[string compare $c1 "/"] == 0} { + set c1 0 + } + + ###################################################################### + # prepare to start xterm by making sure xterm name is unique + # X doesn't care but active menu won't make sense unless names are unique + ###################################################################### + set unique 1 + foreach oldName [array names ::names] { + if {[string match "$name" $::names($oldName)]} { + set unique 0 + } + } + verbose "uniqueness of $name: $unique" + + set safe [safe $name] + + # if not unique, look at the numerical suffixes of all matching + # names, find the biggest and increment it + if {!$unique} { + set suffix 2 + foreach oldName [array names ::names] { + verbose "regexp ^[set safe](\[0-9]+)$ $::names($oldName) X num" + if {[regexp "^[set safe](\[0-9]+)$" $::names($oldName) X num]} { + verbose "matched, checking suffix" + if {$num >= $suffix} { + set suffix [expr $num+1] + verbose "new suffix: $suffix" + } + } + } + append name $suffix + verbose "new name: $name" + } + + ###################################################################### + # start new xterm + ###################################################################### + set xtermpid [eval exec xterm -name [list $name] -S$c1$c2$spawn_out(slave,fd) $::xtermArgs &] + verbose "xterm: pid = $xtermpid" + close -slave + + # xterm first sends back window id, save in environment so it can be + # passed on to the new process + log_user 0 + expect { + eof {wait;return} + -re (.*)\n { + # convert hex to decimal + # note quotes must be used here to avoid diagnostic from expr + set ::env(WINDOWID) [expr "0x$expect_out(1,string)"] + } + } + + ###################################################################### + # start new process + ###################################################################### + set pid [eval spawn -noecho $cmd] + verbose "$cmd: pid = $pid, spawn_id = $spawn_id" + set sidCmd $spawn_id + lappend ::activeList $sidCmd + set ::activeArray($sidCmd) 1 + + ###################################################################### + # link everything back to spawn id of new process + ###################################################################### + set ::xtermSid($sidCmd) $sidXterm + set ::names($sidCmd) $name + set ::xtermPid($sidCmd) $xtermpid + + ###################################################################### + # connect proc output to xterm output + # connect xterm input to proc input + ###################################################################### + expect_background { + -i $sidCmd + -re ".+" [list sendTo $sidXterm] + eof [list xtermKill $sidCmd] + -i $sidXterm + -re ".+" [list sendTo $sidCmd] + eof [list xtermKill $sidCmd] + } + + .m.e entryconfig Active -state normal + .m.e.active add checkbutton -label $name -variable activeArray($sidCmd) \ + -command [list xtermActiveUpdate $sidCmd] + set ::activeArray($sidCmd) 1 +} + +proc xtermActiveUpdate {sid} { + if {$::activeArray($sid)} { + verbose "activating $sid" + } else { + verbose "deactivating $sid" + } + activeListUpdate +} + +proc activeListUpdate {} { + set ::activeList {} + foreach n [array names ::activeArray] { + if {$::activeArray($n)} { + lappend ::activeList $n + } + } +} + +# make a string safe to go through regexp +proc safe {s} { + string map {{[} {\[} {*} {\*} {+} {\+} {^} {\^} {$} {\\$}} $s +} + +# utility to map xterm name to spawn id +# multixterm doesn't use this but a user might want to +proc xtermGet {name} { + foreach sid [array names ::names] { + if {[string equal $name $::names($sid)]} { + return $sid + } + } + error "no such term with name: $name" +} + +# utility to activate an xterm +# multixterm doesn't use this but a user might want to +proc xtermActivate {sid} { + set ::activeArray($sid) 1 + xtermActiveUpdate $sid +} + +# utility to deactivate an xterm +# multixterm doesn't use this but a user might want to +proc xtermDeactivate {sid} { + set ::activeArray($sid) 0 + xtermActiveUpdate $sid +} + +# utility to do an explicit Expect +# multixterm doesn't use this but a user might want to +proc xtermExpect {args} { + # check if explicit spawn_id in args + for {set i 0} {$i < [llength $args]} {incr i} { + switch -- [lindex $args $i] "-i" { + set sidCmd [lindex $args [incr i]] + break + } + } + + if {![info exists sidCmd]} { + # nothing explicit, so get it from the environment + + upvar spawn_id spawn_id + + # mimic expect's normal behavior in obtaining spawn_id + if {[info exists spawn_id]} { + set sidCmd $spawn_id + } else { + set sidCmd $::spawn_id + } + } + + # turn off bg expect, do fg expect, then re-enable bg expect + + expect_background -i $sidCmd ;# disable bg expect + eval expect $args ;# fg expect + ;# reenable bg expect + expect_background { + -i $sidCmd + -re ".+" [list sendTo $::xtermSid($sidCmd)] + eof [list xtermKill $sidCmd] + } +} + +###################################################################### +# connect main window keystrokes to all xterms +###################################################################### +proc xtermSend {A} { + if {[info exists ::afterId]} { + after cancel $::afterId + } + .input config -bg $::colorTyping + set ::afterId [after 1000 {.input config -bg $colorCurrent}] + + exp_send -raw -i $::activeList -- $A +} + +proc sendTo {to} { + exp_send -raw -i $to -- $::expect_out(buffer) +} + +# catch the case where there's no selection +proc xtermPaste {} {catch {xtermSend [selection get]}} + +###################################################################### +# clean up an individual process death or xterm death +###################################################################### +proc xtermKill {s} { + verbose "killing xterm $s" + + if {![info exists ::xtermPid($s)]} { + verbose "too late, already dead" + return + } + + catch {exec /bin/kill -9 $::xtermPid($s)} + unset ::xtermPid($s) + + # remove sid from activeList + verbose "removing $s from active array" + catch {unset ::activeArray($s)} + activeListUpdate + + verbose "removing from background handler $s" + catch {expect_background -i $s} + verbose "removing from background handler $::xtermSid($s)" + catch {expect_background -i $::xtermSid($s)} + verbose "closing proc" + catch {close -i $s} + verbose "closing xterm" + catch {close -i $::xtermSid($s)} + verbose "waiting on proc" + wait -i $s + wait -i $::xtermSid($s) + verbose "done waiting" + unset ::xtermSid($s) + + # remove from active menu + verbose "deleting active menu entry $::names($s)" + + # figure out which it is + # avoid using name as an index since we haven't gone to any pains to + # make it safely interpreted by index-pattern code. instead step + # through, doing the comparison ourselves + set last [.m.e.active index last] + # skip over tearoff + for {set i 1} {$i <= $last} {incr i} { + if {![catch {.m.e.active entrycget $i -label} label]} { + if {[string equal $label $::names($s)]} break + } + } + .m.e.active delete $i + unset ::names($s) + + # if none left, disable menu + # this leaves tearoff clone but that seems reasonable + if {0 == [llength [array names ::xtermSid]]} { + .m.e entryconfig Active -state disable + } +} + +###################################################################### +# create windows +###################################################################### +tk_setPalette $palette + +menu .m -tearoff 0 +.m add cascade -menu .m.f -label "File" -underline 0 +.m add cascade -menu .m.e -label "Edit" -underline 0 +.m add cascade -menu .m.help -label "Help" -underline 0 +set files [glob -nocomplain $cmdDir/*] +set filesLength [llength $files] +if {$filesLength >= $tearoffMenuMin} { + set filesTearoff 1 +} else { + set filesTearoff 0 +} +menu .m.f -tearoff $filesTearoff -title "multixterm files" +menu .m.e -tearoff 0 +menu .m.help -tearoff 0 +.m.f add command -label Open -command openFile -underline 0 + +if {$filesLength} { + .m.f add separator + set files [lsort $files] + set files [lrange $files 0 $fileMenuMax] + foreach f $files { + .m.f add command -label $f -command [list openFile $f] + } + .m.f add separator +} + +.m.f add command -label "Exit" -command exit -underline 0 +.m.e add command -label "Paste" -command xtermPaste -underline 0 +.m.e add cascade -label "Active" -menu .m.e.active -underline 0 +.m.help add command -label "About" -command about -underline 0 +.m.help add command -label "Man Page" -command help -underline 0 +. config -m .m + +menu .m.e.active -tearoff 1 -title "multixterm active" +.m.e entryconfig Active -state disabled +# disable the Active menu simply because it looks goofy seeing an empty menu +# for consistency, though, it should be enabled + +entry .input -textvar inputLabel -justify center -state disabled +entry .cmd -textvar xtermCmd +button .exec -text "new xterm" -command {xtermStart $xtermCmd $xtermCmd} + +grid .input -sticky ewns +grid .cmd -sticky ew +grid .exec -sticky ew -ipadx 3 -ipady 3 + +grid columnconfigure . 0 -weight 1 +grid rowconfigure . 0 -weight 1 ;# let input window only expand + +bind .cmd <Return> {xtermStart $xtermCmd $xtermCmd} + +# send all keypresses to xterm +bind .input <KeyPress> {xtermSend %A ; break} +bind .input <Alt-KeyPress> {xtermSend \033%A; break} +bind .input <Meta-KeyPress> {xtermSend \033%A; break} +bind .input <<Paste>> {xtermPaste ; break} +bind .input <<PasteSelection>> {xtermPaste ; break} + +# arrow keys - note that if they've been rebound through .Xdefaults +# you'll have to change these definitions. +bind .input <Up> {xtermSend \033OA; break} +bind .input <Down> {xtermSend \033OB; break} +bind .input <Right> {xtermSend \033OC; break} +bind .input <Left> {xtermSend \033OD; break} +# Strange: od -c reports these as \033[A et al but when keypad mode +# is initialized, they send \033OA et al. Presuming most people +# want keypad mode, I'll go with the O versions. Perhaps the other +# version is just a Sun-ism anyway. + +set colorCurrent [.input cget -bg] +set colorFocusOut $colorCurrent + +# change color to show focus +bind .input <FocusOut> colorFocusOut +bind .input <FocusIn> colorFocusIn +proc colorFocusIn {} {.input config -bg [set ::colorCurrent $::colorFocusIn]} +proc colorFocusOut {} {.input config -bg [set ::colorCurrent $::colorFocusOut]} + +# convert normal mouse events to focusIn +bind .input <1> {focus .input; break} +bind .input <Shift-1> {focus .input; break} + +# ignore all other mouse events that might make selection visible +bind .input <Double-1> break +bind .input <Triple-1> break +bind .input <B1-Motion> break +bind .input <B2-Motion> break + +set scriptName [info script] ;# must get while it's active + +proc about {} { + set w .about + if {[winfo exists $w]} { + wm deiconify $w + raise $w + return + } + toplevel $w + wm title $w "about multixterm" + wm iconname $w "about multixterm" + wm resizable $w 0 0 + + button $w.b -text Dismiss -command [list wm withdraw $w] + + label $w.title -text "multixterm" -font "Times 16" -borderwidth 10 -fg red + label $w.version -text "Version $::versionString, Released $::versionDate" + label $w.author -text "Written by Don Libes <don@libes.com>" + label $w.using -text "Using Expect [exp_version],\ + Tcl $::tcl_patchLevel,\ + Tk $::tk_patchLevel" + grid $w.title + grid $w.version + grid $w.author + grid $w.using + grid $w.b -sticky ew +} + +proc help {} { + if {[winfo exists .help]} { + wm deiconify .help + raise .help + return + } + toplevel .help + wm title .help "multixterm help" + wm iconname .help "multixterm help" + + scrollbar .help.sb -command {.help.text yview} + text .help.text -width 74 -height 30 -yscroll {.help.sb set} -wrap word + + button .help.ok -text Dismiss -command {destroy .help} -relief raised + bind .help <Return> {destroy .help;break} + grid .help.sb -row 0 -column 0 -sticky ns + grid .help.text -row 0 -column 1 -sticky nsew + grid .help.ok -row 1 -columnspan 2 -sticky ew -ipadx 3 -ipady 3 + + # let text box only expand + grid rowconfigure .help 0 -weight 1 + grid columnconfigure .help 1 -weight 1 + + set script [auto_execok $::scriptName] + if {[llength $script] == 0} { + set script /depot/tcl/bin/multixterm ;# fallback + } + if {[catch {open $script} fid]} { + .help.text insert end "Could not open help file: $script" + } else { + # skip to the beginning of the actual help (starts with "NAME") + while {-1 != [gets $fid buf]} { + if {1 == [regexp "NAME" $buf]} { + .help.text insert end "\n NAME\n" + break + } + } + + while {-1 != [gets $fid buf]} { + if {0 == [regexp "^#(.?)(.*)" $buf X key buf]} break + if {$key == "!"} { + set buf [subst -nocommands $buf] + set key " " + } + .help.text insert end $key$buf\n + } + } + + # support scrolling beyond Tk's built-in Next/Previous + foreach w {"" .sb .text .ok} { + set W .help$w + bind $W <space> {scrollPage 1} ;#more + bind $W <Delete> {scrollPage -1} ;#more + bind $W <BackSpace> {scrollPage -1} ;#more + bind $W <Control-v> {scrollPage 1} ;#emacs + bind $W <Meta-v> {scrollPage -1} ;#emacs + bind $W <Control-f> {scrollPage 1} ;#vi + bind $W <Control-b> {scrollPage -1} ;#vi + bind $W <F35> {scrollPage 1} ;#sun + bind $W <F29> {scrollPage -1} ;#sun + bind $W <Down> {scrollLine 1} + bind $W <Up> {scrollLine -1} + } +} + +proc scrollPage {dir} { + tkScrollByPages .help.sb v $dir + return -code break +} + +proc scrollLine {dir} { + tkScrollByUnits .help.sb v $dir + return -code break +} + +###################################################################### +# exit handling +###################################################################### + +# xtermKillAll is not intended to be user-callable. It just kills +# the processes and that's it. A user-callable version would update +# the data structures, close the channels, etc. + +proc xtermKillAll {} { + foreach sid [array names ::xtermPid] { + exec /bin/kill -9 $::xtermPid($sid) + } +} + +rename exit _exit +proc exit {{x 0}} {xtermKillAll;_exit $x} + +wm protocol . WM_DELETE_WINDOW exit +trap exit SIGINT + +###################################################################### +# start any xterms requested +###################################################################### +proc xtermStartAll {} { + verbose "xtermNames = \"$::xtermNames\"" + foreach n $::xtermNames { + regsub -all "%n" $::xtermCmd $n cmdOut + xtermStart $cmdOut $n + } + set ::xtermNames {} +} + +initLate + +# now that xtermStartAll and its accompanying support has been set up +# run it to start anything defined by rc file or command-line args. + +xtermStartAll ;# If nothing has been requested, this is a no-op. + +# finally do any explicit command file +if {[info exists cmdFile]} { + openFile $cmdFile +} + diff --git a/example/multixterm.man b/example/multixterm.man new file mode 100644 index 0000000..bc78522 --- /dev/null +++ b/example/multixterm.man @@ -0,0 +1,299 @@ +.TH MULTIXTERM 1 "16 August 2002" +.SH NAME +multixterm \- drive multiple xterms separately or together +.SH SYNOPSIS +.B multixterm +[ +.I args +] +.SH DESCRIPTION +Multixterm creates multiple xterms that can be driven together +or separately. + +In its simplest form, multixterm is run with no arguments and +commands are interactively entered in the first entry field. +Press return (or click the "new xterm" button) to create a new +xterm running that command. + +Keystrokes in the "stdin window" are redirected to all xterms +started by multixterm. xterms may be driven separately simply +by focusing on them. + +The stdin window must have the focus for keystrokes to be sent +to the xterms. When it has the focus, the color changes to +aquamarine. As characters are entered, the color changes to +green for a second. This provides feedback since characters +are not echoed in the stdin window. + +Typing in the stdin window while holding down the alt or meta +keys sends an escape character before the typed characters. +This provides support for programs such as emacs. + +.SH ARGUMENTS +.RS +.TP 4 +-xa +The optional \-xa argument indicates arguments to pass to +xterm. + +.TP +-xc +The optional \-xc argument indicates a command to be run in +each named xterm (see \-xn). With no \-xc argument, the command +is the current shell. + +.TP 4 +-xd +The optional \-xd argument indicates a directory to search for +files that will appear in the Files menu. By default, the +directory is: ~/lib/multixterm + +.TP 4 +-xf +The optional \-xf argument indicates a file to be read at +startup. See FILES below for more info. + +.TP 4 +-xn +The optional \-xn argument indicates a name for each xterm. +This name will also be substituted for any %n in the command +argument (see \-xc). + +.TP 4 +-xv +The optional \-xv flag puts multixterm into a verbose mode +where it will describe some of the things it is doing +internally. The verbose output is not intended to be +understandable to anyone but the author. + +.RE +Less common options may be changed by the startup file (see +FILES below). + +All the usual X and wish flags are supported (i.e., \-display, +\-name). There are so many of them that to avoid colliding and +make them easy to remember, all the multixterm flags begin +with \-x. + +If any arguments do not match the flags above, the remainder of the +command line is made available for user processing. By default, the +remainder is used as a list of xterm names in the style of \-xn. The +default behavior may be changed using the .multixtermrc file (see DOT +FILE below). + +.SH "EXAMPLE COMMAND LINE ARGUMENTS" +The following command line starts up two xterms using ssh to +the hosts bud and dexter. + + multixterm \-xc "ssh %n" bud dexter + +.SH FILES +Command files may be used to drive or initialize multixterm. +The File menu may be used to invoke other files. If files +exist in the command file directory (see \-xd above), they will +appear in the File menu. Files may also be loaded by using +File->Open. Any filename is acceptable but the File->Open +browser defaults to files with a .mxt suffix. + +Files are written in Tcl and may change any variables or +invoke any procedures. The primary variables of interest are 'xtermCmd' +which identifies the command (see \-xc) and 'xtermNames' +which is a list of names (see \-xn). The procedure +xtermStartAll, starts xterms for each name in the list. Other +variables and procedures may be discovered by examining +multixterm itself. + +.SH "EXAMPLE FILE" +The following file does the same thing as the earlier example +command line: +.nf + + # start two xterms connected to bud and dexter + set xtermCmd "ssh %n" + set xtermNames {bud dexter} + xtermStartAll + +.fi +.SH "DOT FILE" +At startup, multixterm reads ~/.multixtermrc if present. This +is similar to the command files (see FILES above) except +that .multixtermrc may not call xtermStartAll. Instead it is +called implicitly, similar to the way that it is implicit in +the command line use of \-xn. + +The following example .multixtermrc file makes every xterm run +ssh to the hosts named on the command line. + + set xtermCmd "ssh %n" + +Then multixterm could be called simply: + + multixterm bud dexter + +If any command-line argument does not match a multixterm flag, +the remainder of the command line is made available to .multixtermrc +in the argv variable. If argv is non-empty when .multixtermrc returns, it is assigned to xtermNames unless xtermNames is non-empty in which case, the +content of argv is ignored. + +Commands from multixterm are evaluated early in the +initialization of multixterm. Anything that must be done late +in the initialization (such as adding additional bindings to +the user interface) may be done by putting the commands inside +a procedure called "initLate". + +.SH MENUS +Except as otherwise noted, the menus are self-explanatory. +Some of the menus have dashed lines as the first entry. +Clicking on the dashed lines will "tear off" the menus. + +.SH "USAGE SUGGESTION \- ALIASES AND COMMAND FILES" +Aliases may be used to store lengthy command-line invocations. +Command files can be also be used to store such invocations +as well as providing a convenient way to share configurations. + +Tcl is a general-purpose language. Thus multixterm command +files can be extremely flexible, such as loading hostnames +from other programs or files that may change from day-to-day. +In addition, command files can be used for other purposes. +For example, command files may be used to prepared common +canned interaction sequences. For example, the command to +send the same string to all xterms is: + + xtermSend "a particularly long string" + +The File menu (torn-off) makes canned sequences particularly +convenient. Interactions could also be bound to a mouse button, +keystroke, or added to a menu via the .multixtermrc file. + +The following .multixtermrc causes tiny xterms to tile across +and down the screen. (You may have to adjust the parameters +for your screen.) This can be very helpful when dealing with +large numbers of xterms. +.nf + + set yPos 0 + set xPos 0 + + trace variable xtermArgs r traceArgs + + proc traceArgs {args} { + global xPos yPos + set ::xtermArgs "-geometry 80x12+$xPos+$yPos \-font 6x10" + if {$xPos} { + set xPos 0 + incr yPos 145 + if {$yPos > 800} {set yPos 0} + } else { + set xPos 500 + } + } +.fi + +The xtermArgs variable in the code above is the variable corresponding +to the \-xa argument. + +xterms can be also be created directly. The following command file +creates three xterms overlapped +horizontally: +.nf + + set xPos 0 + foreach name {bud dexter hotdog} { + set ::xtermArgs "-geometry 80x12+$xPos+0 \-font 6x10" + set ::xtermNames $name + xtermStartAll + incr xPos 300 + } + +.fi +.SH "USAGE SUGGESTION \- SELECTING HOSTS BY NICKNAME" +The following .multixtermrc shows an example of changing the +default handling of the arguments from hostnames to a filename +containing hostnames: + + set xtermNames [exec cat $argv] + +The following is a variation, retrieving the host names from +the yp database: + + set xtermNames [exec ypcat $argv] + +The following hardcodes two sets of hosts, so that you can +call multixterm with either "cluster1" or "cluster2": +.nf + + switch $argv { + cluster1 { + set xtermNames "bud dexter" + } + cluster2 { + set xtermNames "frank hotdog weiner" + } + } + +.fi + + +.SH COMPARE/CONTRAST +It is worth comparing multixterm to xkibitz. Multixterm +connects a separate process to each xterm. xkibitz connects +the same process to each xterm. + +.SH LIMITATIONS + +Multixterm provides no way to remotely control scrollbars, resize, and +most other window system related functions. + +Because xterm has no mechanism for propagating size information to +external processes, particularly for character graphic applications +(e.g., vi, emacs), you may have to manually ensure that the spawned +process behind each xterm has the correct size. For example, if you +create or set the xterm to a size, you may have to send an explicit +stty command with the correct size to the spawned process(es). +Alternatively, you can add the correct size argument when an xterm is +created (i.e., "-geometry 80x20"). + +Multixterm can only control new xterms that multixterm itself has +started. + +As a convenience, the File menu shows a limited number of +files. To show all the files, use File->Open. + +.SH FILES +$DOTDIR/.multixtermrc initial command file +.br +~/.multixtermrc fallback command file +.br +~/lib/multixterm/ default command file directory + +.SH BUGS +If multixterm is killed using an uncatchable kill, the xterms +are not killed. This appears to be a bug in xterm itself. + +Send/expect sequences can be done in multixterm command files. +However, due to the richness of the possibilities, to document +it properly would take more time than the author has at present. + +.SH REQUIREMENTS +Requires Expect 5.36.0 or later. +.br +Requires Tk 8.3.3 or later. + +.SH VERSION +This man page describes version 1.8 of multixterm. + +The latest version of multixterm is available from +http://expect.nist.gov/example/multixterm . If your version of Expect +and Tk are too old (see REQUIREMENTS above), download a new version of +Expect from http://expect.nist.gov + +.SH DATE +April 30, 2002 + +.SH AUTHOR +Don Libes <don@libes.com> + +.SH LICENSE +Multixterm is in the public domain; however the author would +appreciate acknowledgement if multixterm or parts of it or ideas from +it are used. diff --git a/example/passmass b/example/passmass new file mode 100755 index 0000000..e3c18e6 --- /dev/null +++ b/example/passmass @@ -0,0 +1,216 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# passmass: change password on many machines +# Synopsis: passmass host1 host2 host3 .... +# Don Libes - March 11, 1991 + +# Description: Change passwords on the named machines. +# +# See passmass.man for further info. + +exp_version -exit 5.0 + +if {$argc==0} { + send_user "usage: $argv0 host1 host2 host3 . . .\n" + exit +} + +expect_before -i $user_spawn_id \003 exit + +proc badhost {host emsg} { + global badhosts + + send_user "\r\n\007password not changed on $host - $emsg\n\n" + if {0==[llength $badhosts]} { + set badhosts $host + } else { + set badhosts [concat $badhosts $host] + } +} + +# set defaults +set login "rlogin" +set program "passwd" +set user [exec whoami] +set su 0 + +set timeout -1 +stty -echo + +if {!$su} { + send_user "old password: " + expect_user -re "(.*)\n" + send_user "\n" + set password(old) $expect_out(1,string) + set password(login) $expect_out(1,string) + send_user "new password: " + expect_user -re "(.*)\n" + send_user "\n" + set password(new) $expect_out(1,string) + send_user "retype new password: " + expect_user -re "(.*)\n" + set password(newcheck) $expect_out(1,string) + send_user "\n" +} else { + send_user "login password: " + expect_user -re "(.*)\n" + send_user "\n" + set password(login) $expect_out(1,string) + send_user "root password: " + expect_user -re "(.*)\n" + send_user "\n" + set password(old) $expect_out(1,string) + send_user "new password: " + expect_user -re "(.*)\n" + send_user "\n" + set password(new) $expect_out(1,string) + send_user "retype new password: " + expect_user -re "(.*)\n" + set password(newcheck) $expect_out(1,string) + send_user "\n" +} + +stty echo +trap exit SIGINT + +if ![string match $password(new) $password(newcheck)] { + send_user "mismatch - password unchanged\n" + exit +} + +set timeout -1 + +set badhosts {} +for {set i 0} {$i<$argc} {incr i} { + set arg [lindex $argv $i] + switch -- $arg "-user" { + incr i + set user [lindex $argv $i] + continue + } "-prompt" { + incr i + set prompt [lindex $argv $i] + continue + } "-rlogin" { + set login "rlogin" + continue + } "-slogin" { + set login "slogin" + continue + } "-ssh" { + set login "ssh" + continue + } "-telnet" { + set login "telnet" + continue + } "-program" { + incr i + set program [lindex $argv $i] + continue + } "-timeout" { + incr i + set timeout [lindex $argv $i] + continue + } "-su" { + incr i + set su [lindex $argv $i] + continue + } + + set host $arg + if {[string match $login "rlogin"]} { + set pid [spawn rlogin $host -l $user] + } elseif {[string match $login "slogin"]} { + set pid [spawn slogin $host -l $user] + } elseif {[string match $login "ssh"]} { + set pid [spawn ssh $host -l $user] + } else { + set pid [spawn telnet $host] + expect -nocase -re "(login|username):.*" { + send "$user\r" + } + } + + if ![info exists prompt] { + if {[string match $user "root"]} { + set prompt "# " + } else { + set prompt "(%|\\\$|#) " + } + } + + set logged_in 0 + while {1} { + expect -nocase "password*" { + send "$password(login)\r" + } eof { + badhost $host "spawn failed" + break + } timeout { + badhost $host "could not log in (or unrecognized prompt)" + exec kill $pid + expect eof + break + } -re "incorrect|invalid" { + badhost $host "bad password or login" + exec kill $pid + expect eof + break + } -re $prompt { + set logged_in 1 + break + } + } + + if (!$logged_in) { + wait + continue + } + + if ($su) { + send "su -\r" + expect -nocase "password:" + send "$password(old)\r" + expect "# " + send "$program root\r" + } else { + send "$program\r" + } + + expect -nocase -re "(old|existing login) password:.*" { + send "$password(old)\r" + expect -nocase "sorry*" { + badhost $host "old password is bad?" + continue + } -nocase "password:" + } -nocase -re "new password:" { + # got prompt, fall through + } timeout { + badhost $host "could not recognize prompt for password" + continue + } + send "$password(new)\r" + expect -re "not changed|unchanged" { + badhost $host "new password is bad?" + continue + } -nocase -re "(password|verification|verify|again):.*" + send "$password(new)\r" + expect -nocase -re "(not changed|incorrect|choose new).*" { + badhost $host "password is bad?" + continue + } -re "$prompt" + send_user "\n" + + close + wait +} + +if {[llength $badhosts]} { + send_user "\nfailed to set password on $badhosts\n" +} diff --git a/example/passmass.man b/example/passmass.man new file mode 100644 index 0000000..dcaeccd --- /dev/null +++ b/example/passmass.man @@ -0,0 +1,106 @@ +.TH PASSMASS 1 "7 October 1993" +.SH NAME +passmass \- change password on multiple machines +.SH SYNOPSIS +.B passmass +[ +.I host1 host2 host3 ... +] +.SH INTRODUCTION +.B Passmass +changes a password on multiple machines. If you have accounts on +several machines that do not share password databases, Passmass can +help you keep them all in sync. This, in turn, will make it easier to +change them more frequently. + +When Passmass runs, it asks you for the old and new passwords. +(If you are changing root passwords and have equivalencing, the old +password is not used and may be omitted.) + +Passmass understands the "usual" conventions. Additional arguments +may be used for tuning. They affect all hosts which follow until +another argument overrides it. For example, if you are known as +"libes" on host1 and host2, but "don" on host3, you would say: + + passmass host1 host2 -user don host3 + +Arguments are: +.RS +.TP 4 +-user +User whose password will be changed. By default, the current user is used. + +.TP 4 +-rlogin +Use rlogin to access host. (default) + +.TP 4 +-slogin +Use slogin to access host. + +.TP 4 +-ssh +Use ssh to access host. + +.TP 4 +-telnet +Use telnet to access host. + +.TP 4 +-program + +Next argument is a program to run to set the password. Default is +"passwd". Other common choices are "yppasswd" and "set passwd" (e.g., +VMS hosts). A program name such as "password fred" can be used to +create entries for new accounts (when run as root). + +.TP 4 +-prompt +Next argument is a prompt suffix pattern. This allows +the script to know when the shell is prompting. The default is +"# " for root and "% " for non-root accounts. + +.TP 4 +-timeout +Next argument is the number of seconds to wait for responses. +Default is 30 but some systems can be much slower logging in. + +.TP 4 +-su + +Next argument is 1 or 0. If 1, you are additionally prompted for a +root password which is used to su after logging in. root's password +is changed rather than the user's. This is useful for hosts which +do not allow root to log in. + +.SH HOW TO USE +The best way to run Passmass is to put the command in a one-line shell +script or alias. Whenever you get a new account on a new machine, add +the appropriate arguments to the command. Then run it whenever you +want to change your passwords on all the hosts. + +.SH CAVEATS + +Using the same password on multiple hosts carries risks. In +particular, if the password can be stolen, then all of your accounts +are at risk. Thus, you should not use Passmass in situations where +your password is visible, such as across a network which hackers are +known to eavesdrop. + +On the other hand, if you have enough accounts with different +passwords, you may end up writing them down somewhere - and +.I that +can be a security problem. Funny story: my college roommate had an +11"x13" piece of paper on which he had listed accounts and passwords +all across the Internet. This was several years worth of careful work +and he carried it with him everywhere he went. +Well one day, he forgot to remove it from his jeans, and we found a +perfectly blank sheet of paper when we took out the wash the following +day! +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/passwd.cgi b/example/passwd.cgi new file mode 100644 index 0000000..f6756e9 --- /dev/null +++ b/example/passwd.cgi @@ -0,0 +1,106 @@ +#!/depot/path/expect -- + +# This is a CGI script to process requests created by the accompanying +# passwd.html form. This script is pretty basic, although it is +# reasonably robust. (Purposely intent users can make the script bomb +# by mocking up their own HTML form, however they can't expose or steal +# passwords or otherwise open any security holes.) This script doesn't +# need any special permissions. The usual (ownership nobody) is fine. +# +# With a little more code, the script can do much more exotic things - +# for example, you could have the script: +# +# - telnet to another host first (useful if you run CGI scripts on a +# firewall), or +# +# - change passwords on multiple password server hosts, or +# +# - verify that passwords aren't in the dictionary, or +# +# - verify that passwords are at least 8 chars long and have at least 2 +# digits, 2 uppercase, 2 lowercase, or whatever restrictions you like, +# or +# +# - allow short passwords by responding appropriately to passwd +# +# and so on. Have fun! +# +# Don Libes, NIST + +puts "Content-type: text/html\n" ;# note extra newline + +puts " +<head> +<title>Passwd Change Acknowledgment</title> +</head> + +<h2>Passwd Change Acknowledgment</h2> +" + +proc cgi2ascii {buf} { + regsub -all {\+} $buf { } buf + regsub -all {([\\["$])} $buf {\\\1} buf + regsub -all -nocase "%0d%0a" $buf "\n" buf + regsub -all -nocase {%([a-f0-9][a-f0-9])} $buf {[format %c 0x\1]} buf + eval return \"$buf\" +} + +foreach pair [split [read stdin $env(CONTENT_LENGTH)] &] { + regexp (.*)=(.*) $pair dummy varname val + set val [cgi2ascii $val] + set var($varname) $val +} + +log_user 0 + +proc errormsg {s} {puts "<h3>Error: $s</h3>"} +proc successmsg {s} {puts "<h3>$s</h3>"} + +# Need to su first to get around passwd's requirement that passwd cannot +# be run by a totally unrelated user. Seems rather pointless since it's +# so easy to satisfy, eh? + +# Change following line appropriately for your site. +# (We use yppasswd, but you might use something else.) +spawn /bin/su $var(name) -c "/bin/yppasswd $var(name)" +# This fails on SunOS 4.1.3 (passwd says "you don't have a login name") +# run on (or telnet first to) host running SunOS 4.1.4 or later. + +expect { + "Unknown login:" { + errormsg "unknown user: $var(name)" + exit + } default { + errormsg "$expect_out(buffer)" + exit + } "Password:" +} +send "$var(old)\r" +expect { + "unknown user" { + errormsg "unknown user: $var(name)" + exit + } "Sorry" { + errormsg "Old password incorrect" + exit + } default { + errormsg "$expect_out(buffer)" + exit + } "Old password:" +} +send "$var(old)\r" +expect "New password:" +send "$var(new1)\r" +expect "New password:" +send "$var(new2)\r" +expect -re (.*)\r\n { + set error $expect_out(1,string) +} +close +wait + +if {[info exists error]} { + errormsg "$error" +} else { + successmsg "Password changed successfully." +} diff --git a/example/passwd.html b/example/passwd.html new file mode 100644 index 0000000..8d53a6c --- /dev/null +++ b/example/passwd.html @@ -0,0 +1,25 @@ +<HTML> +<head> +<title>Change your login password</title> +</head> +<body> + +This HTML creates a form for letting users change login passwords with +a browser. To actually use this form, install the corresponding +accompanying cgi script and then modify the action value to identify +where you put the cgi script. (Also read the comments at the +beginning of the CGI script.) - Don Libes +<hr> + +<form method=post +action="http://www-i.cme.nist.gov/cgi-bin/expect/passwd.cgi"> +<h2>Change your login password</h2> +<br>Username: <input name="name"> +<br>Old password: <input type=password name="old"> +<br>New password: <input type=password name="new1"> +<br>New password: <input type=password name="new2"> +<br>New password must be entered twice to avoid typos. +<br><input type=submit value="Change password"> +</form> +</body> +</html> diff --git a/example/passwdprompt b/example/passwdprompt new file mode 100755 index 0000000..163e493 --- /dev/null +++ b/example/passwdprompt @@ -0,0 +1,35 @@ +#!/depot/path/expect + +# This script prompts for a passwd from stdin while echoing *'s + +# Prompt MUST be passed as argument to avoid falling into the classic +# prompt-before-echo-has-been-disabled mistake. + +proc getpass {prompt} { + set sttyOld [stty -echo raw] + send_user $prompt + + set timeout -1 + set passwd "" + + expect { + -re "\r" { + send_user \r\n + } -re "\010|\177" { + if {[string length $passwd] > 0} { + # not all ttys support destructive spaces + send "\010 \010" + regexp (.*). $passwd x passwd + } + exp_continue + } -re . { + send_user * + append passwd $expect_out(0,string) + exp_continue + } + } + eval stty $sttyOld + return $passwd +} + +puts "The password you entered was: [getpass "Password: "]" diff --git a/example/read1char b/example/read1char new file mode 100644 index 0000000..43a3df8 --- /dev/null +++ b/example/read1char @@ -0,0 +1,13 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# read a single character +# Author: Don Libes, NIST + +stty raw +expect ? +send_user $expect_out(buffer) diff --git a/example/reprompt b/example/reprompt new file mode 100644 index 0000000..02db985 --- /dev/null +++ b/example/reprompt @@ -0,0 +1,20 @@ +#!/depot/path/expect -- + +# Name: reprompt +# Description: reprompt every so often until user enters something +# Usage: reprompt timeout prompt +# Author: Don Libes, NIST + +foreach {timeout prompt} $argv {} + +send_error $prompt +expect { + timeout { + send_error "\nwake up!!\a" + send_error \n$prompt + exp_continue + } + -re .+ { + send_user $expect_out(buffer) + } +} diff --git a/example/rftp b/example/rftp new file mode 100755 index 0000000..c5db679 --- /dev/null +++ b/example/rftp @@ -0,0 +1,341 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# rftp - ftp a directory hierarchy (i.e. recursive ftp) +# Version 2.10 +# Don Libes, NIST +exp_version -exit 5.0 + +# rftp is much like ftp except that the command ~g copies everything in +# the remote current working directory to the local current working +# directory. Similarly ~p copies in the reverse direction. ~l just +# lists the remote directories. + +# rftp takes an argument of the host to ftp to. Username and password +# are prompted for. Other ftp options can be set interactively at that +# time. If your local ftp understands .netrc, that is also used. + +# ~/.rftprc is sourced after the user has logged in to the remote site +# and other ftp commands may be sent at that time. .rftprc may also be +# used to override the following rftp defaults. The lines should use +# the same syntax as these: + +set file_timeout 3600 ;# timeout (seconds) for retrieving files +set timeout 1000000 ;# timeout (seconds) for other ftp dialogue +set default_type binary ;# default type, i.e., ascii, binary, tenex +set binary {} ;# files matching are transferred as binary +set ascii {} ;# as above, but as ascii +set tenex {} ;# as above, but as tenex + +# The values of binary, ascii and tenex should be a list of (Tcl) regular +# expressions. For example, the following definitions would force files +# ending in *.Z and *.tar to be transferred as binaries and everything else +# as text. + +# set default_type ascii +# set binary {*.Z *.tar} + +# If you are on a UNIX machine, you can probably safely ignore all of this +# and transfer everything as "binary". + +# The current implementation requires that the source host be able to +# provide directory listings in UNIX format. Hence, you cannot copy +# from a VMS host (although you can copy to it). In fact, there is no +# standard for the output that ftp produces, and thus, ftps that differ +# significantly from the ubiquitous UNIX implementation may not work +# with rftp (at least, not without changing the scanning and parsing). + +####################end of documentation############################### + +match_max -d 100000 ;# max size of a directory listing + +# return name of file from one line of directory listing +proc getname {line} { + # if it's a symbolic link, return local name + set i [lsearch $line "->"] + if {-1==$i} { + # not a sym link, return last token of line as name + return [lindex $line [expr [llength $line]-1]] + } else { + # sym link, return "a" of "a -> b" + return [lindex $line [expr $i-1]] + } +} + +proc putfile {name} { + global current_type default_type + global binary ascii tenex + global file_timeout + + switch -- $name $binary {set new_type binary} \ + $ascii {set new_type ascii} \ + $tenex {set new_type tenex} \ + default {set new_type $default_type} + + if {$current_type != $new_type} { + settype $new_type + } + + set timeout $file_timeout + send "put $name\r" + expect timeout { + send_user "ftp timed out in response to \"put $name\"\n" + exit + } "ftp>*" +} + +proc getfile {name} { + global current_type default_type + global binary ascii tenex + global file_timeout + + switch -- $name $binary {set new_type binary} \ + $ascii {set new_type ascii} \ + $tenex {set new_type tenex} \ + default {set new_type $default_type} + + if {$current_type != $new_type} { + settype $new_type + } + + set timeout $file_timeout + send "get $name\r" + expect timeout { + send_user "ftp timed out in response to \"get $name\"\n" + exit + } "ftp>*" +} + +# returns 1 if successful, 0 otherwise +proc putdirectory {name} { + send "mkdir $name\r" + expect "550*denied*ftp>*" { + send_user "failed to make remote directory $name\n" + return 0 + } timeout { + send_user "timed out on make remote directory $name\n" + return 0 + } -re "(257|550.*exists).*ftp>.*" + # 550 is returned if directory already exists + + send "cd $name\r" + expect "550*ftp>*" { + send_user "failed to cd to remote directory $name\n" + return 0 + } timeout { + send_user "timed out on cd to remote directory $name\n" + return 0 + } -re "2(5|0)0.*ftp>.*" + # some ftp's return 200, some return 250 + + send "lcd $name\r" + # hard to know what to look for, since my ftp doesn't return status + # codes. It is evidentally very locale-dependent. + # So, assume success. + expect "ftp>*" + putcurdirectory + send "lcd ..\r" + expect "ftp>*" + send "cd ..\r" + expect timeout { + send_user "failed to cd to remote directory ..\n" + return 0 + } -re "2(5|0)0.*ftp>.*" + + return 1 +} + +# returns 1 if successful, 0 otherwise +proc getdirectory {name transfer} { + send "cd $name\r" + # this can fail normally if it's a symbolic link, and we are just + # experimenting + expect "550*$name*ftp>*" { + send_user "failed to cd to remote directory $name\n" + return 0 + } timeout { + send_user "timed out on cd to remote directory $name\n" + return 0 + } -re "2(5|0)0.*ftp>.*" + # some ftp's return 200, some return 250 + + if {$transfer} { + send "!mkdir $name\r" + expect "denied*" return timeout return "ftp>" + send "lcd $name\r" + # hard to know what to look for, since my ftp doesn't return + # status codes. It is evidentally very locale-dependent. + # So, assume success. + expect "ftp>*" + } + getcurdirectory $transfer + if {$transfer} { + send "lcd ..\r" + expect "ftp>*" + } + send "cd ..\r" + expect timeout { + send_user "failed to cd to remote directory ..\n" + return 0 + } -re "2(5|0)0.*ftp>.*" + + return 1 +} + +proc putentry {name type} { + switch -- $type d { + # directory + if {$name=="." || $name==".."} return + putdirectory $name + } - { + # file + putfile $name + } l { + # symlink, could be either file or directory + # first assume it's a directory + if {[putdirectory $name]} return + putfile $name + } default { + send_user "can't figure out what $name is, skipping\n" + } +} + +proc getentry {name type transfer} { + switch -- $type d { + # directory + if {$name=="." || $name==".."} return + getdirectory $name $transfer + } - { + # file + if {!$transfer} return + getfile $name + } l { + # symlink, could be either file or directory + # first assume it's a directory + if {[getdirectory $name $transfer]} return + if {!$transfer} return + getfile $name + } default { + send_user "can't figure out what $name is, skipping\n" + } +} + +proc putcurdirectory {} { + send "!/bin/ls -alg\r" + expect timeout { + send_user "failed to get directory listing\n" + return + } "ftp>*" + + set buf $expect_out(buffer) + + while {1} { + # if end of listing, succeeded! + if 0==[regexp "(\[^\n]*)\n(.*)" $buf dummy line buf] return + + set token [lindex $line 0] + switch -- $token !/bin/ls { + # original command + } total { + # directory header + } . { + # unreadable + } default { + # either file or directory + set name [getname $line] + set type [string index $line 0] + putentry $name $type + } + } +} + +# look at result of "dir". If transfer==1, get all files and directories +proc getcurdirectory {transfer} { + send "dir\r" + expect timeout { + send_user "failed to get directory listing\n" + return + } "ftp>*" + + set buf $expect_out(buffer) + + while {1} { + regexp "(\[^\n]*)\n(.*)" $buf dummy line buf + + set token [lindex $line 0] + switch -- $token dir { + # original command + } 200 { + # command successful + } 150 { + # opening data connection + } total { + # directory header + } 226 { + # transfer complete, succeeded! + return + } ftp>* { + # next prompt, failed! + return + } . { + # unreadable + } default { + # either file or directory + set name [getname $line] + set type [string index $line 0] + getentry $name $type $transfer + } + } +} + +proc settype {t} { + global current_type + + send "type $t\r" + set current_type $t + expect "200*ftp>*" +} + +proc final_msg {} { + # write over the previous prompt with our message + send_user "\rQuit ftp or cd to another directory and press ~g, ~p, or ~l\n" + # and then reprompt + send_user "ftp> " +} + +if {[file readable ~/.rftprc]} {source ~/.rftprc} +set first_time 1 + +if {$argc>1} { + send_user "usage: rftp [host]" + exit +} + +send_user "Once logged in, cd to the directory to be transferred and press:\n" +send_user "~p to put the current directory from the local to the remote host\n" +send_user "~g to get the current directory from the remote host to the local host\n" +send_user "~l to list the current directory from the remote host\n" + +if {$argc==0} {spawn ftp} else {spawn ftp $argv} +interact -echo ~g { + if {$first_time} { + set first_time 0 + settype $default_type + } + getcurdirectory 1 + final_msg +} -echo ~p { + if {$first_time} { + set first_time 0 + settype $default_type + } + putcurdirectory + final_msg +} -echo ~l { + getcurdirectory 0 + final_msg +} diff --git a/example/rlogin-cwd b/example/rlogin-cwd new file mode 100755 index 0000000..b217373 --- /dev/null +++ b/example/rlogin-cwd @@ -0,0 +1,21 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# rlogin-cwd - rlogin but with same directory +# +# You can extend this idea to save any arbitrary information across rlogin +# Don Libes - Oct 17, 1991. + +set prompt "(%|#|\\$) $" ;# default prompt +catch {set prompt $env(EXPECT_PROMPT)} + +eval spawn rlogin $argv +set timeout 60 +expect eof exit timeout {send_user "timed out\n"; exit} -re $prompt +send "cd [pwd]\r" +interact diff --git a/example/robohunt b/example/robohunt new file mode 100755 index 0000000..853ce1e --- /dev/null +++ b/example/robohunt @@ -0,0 +1,87 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# Synopsis +# robohunt player-name [-nodisplay] + +# Plays hunt automatically. Optional "-nodisplay" argument disables output. + +# by Don Libes + +expect_version -exit 5.0 + +set timeout 1 + +proc random {} { + global ia ic im jran + + set jran [expr ($jran*$ia + $ic) % $im] + return $jran +} + +set ia 7141 +set ic 54773 +set im 259200 +set jran [pid] + +# given a direction and number, moves that many spaces in that direction +proc mv {dir num} { + # first try firing a bullet (what the hell...open some walls to move!) + send "f" + for {set i 0} {$i<$num} {incr i} { + send $dir + } +} + +# move a random distance/direction + +# 31 is arbitrarily used as a max distance to move in any one direction +# this is a compromise between long horizontal and vertical moves +# but since excess movement is good for stabbing, this is reasonable +proc move {} { + set num [random] + set mask [expr $num&3] + set num [expr $num&31] + if $mask==0 {send "H"; mv "h" $num; return} + if $mask==1 {send "L"; mv "l" $num; return} + if $mask==2 {send "K"; mv "k" $num; return} + send "J"; mv "j" $num; return +} + +if {2==$argc} { set output 0 } {set output 1} +if {1>$argc} { send_user "usage: robohunt name \[-nodisplay\]\n"; exit} +spawn hunt -b -c -n [lindex $argv 0] +expect "team" +send "\r" + +set several_moves 5 + +expect "Monitor:" +after 1000 +expect ;# flush output +log_user 0 +# output is turned off so that we can first strip out ^Gs before they +# are sent to the tty. It seems to drive xterms crazy - because our +# rather stupid algorithm off not checking after every move can cause +# the game to send a lot of them. + +for {} {1} {} { + # make several moves at a time, before checking to see if we are dead + # this is a compromise between just ignoring our status after each move + # and looking at our status after each move + for {set j $several_moves} {$j} {incr j -1} { + move + } + + expect { + -re ^\007+ {exp_continue} + -re "\\? " {send y} + -re .+ + } + if $output {send_user -raw $expect_out(buffer)} +} diff --git a/example/rogue.exp b/example/rogue.exp new file mode 100755 index 0000000..083acdf --- /dev/null +++ b/example/rogue.exp @@ -0,0 +1,23 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# Look for a GREAT game of rogue. +# Idea is that any game with a Strength of 18 is unusually good. +# Written by Don Libes - March, 1990 + +set timeout -1 +while {1} { + spawn rogue + expect "Str: 18" break \ + "Str: 16" + send "Q" + expect "quit?" + send "y" + close + wait +} +interact diff --git a/example/telnet-cwd b/example/telnet-cwd new file mode 100755 index 0000000..bd16048 --- /dev/null +++ b/example/telnet-cwd @@ -0,0 +1,19 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# telnet-cwd - telnet but with same directory +# +# You can extend this idea to save any arbitrary information across telnet +# Don Libes - Oct 17, 1991. + +set prompt "(%|#|\\$) $" ;# default prompt +catch {set prompt $env(EXPECT_PROMPT)} + +eval spawn telnet $argv +interact -o -nobuffer -re $prompt return +send "cd [pwd]\r" +interact diff --git a/example/telnet-in-bg b/example/telnet-in-bg new file mode 100644 index 0000000..1aecfef --- /dev/null +++ b/example/telnet-in-bg @@ -0,0 +1,18 @@ +# Start telnet and when you press ^Z, put telnet in background and save any +# remaining output in "telnet.log". You can actually apply this technique +# to any interactive program - I just chose telnet here. + +# Author: Don Libes, NIST, 1/5/95 + +spawn -ignore HUP telnet $argv ;# start telnet +interact \032 return ;# interact until ^Z + +if {[fork]} exit ;# disconnect from terminal +disconnect + +set log [open logfile w] ;# open logfile +expect -re .+ { ;# and record everything to it + puts -nonewline $log $expect_out(buffer) + exp_continue +} + diff --git a/example/term_expect b/example/term_expect new file mode 100755 index 0000000..2abecfd --- /dev/null +++ b/example/term_expect @@ -0,0 +1,602 @@ +#!/depot/path/expectk + +# Name: tkterm - terminal emulator using Expect and Tk text widget, v3.0 +# Author: Don Libes, July '94 +# Last updated: Mar '04 + +# This is primarily for regression testing character-graphic applications. +# You can certainly use it as a terminal emulator - however many features +# in a real terminal emulator are not supported (although I'll probably +# add some of them later). + +# A paper on the implementation: Libes, D., Automation and Testing of +# Interactive Character Graphic Programs", Software - Practice & +# Experience, John Wiley & Sons, West Sussex, England, Vol. 27(2), +# p. 123-137, February 1997. + +############################### +# Quick overview of this emulator +############################### +# Very good attributes: +# Understands both termcap and terminfo +# Understands meta-key (zsh, emacs, etc work) +# Is fast +# Understands X selections +# Looks best with fixed-width font but doesn't require it +# Supports scrollbars +# Good-enough-for-starters attributes: +# Understands one kind of standout mode (reverse video) +# Should-be-fixed-soon attributes: +# Does not support resize +# Probably-wont-be-fixed-soon attributes: +# Assumes only one terminal exists + +############################################### +# To try out this package, just run it. Using it in +# your scripts is simple. Here are directions: +############################################### +# 0) make sure Expect is linked into your Tk-based program (or vice versa) +# 1) modify the variables/procedures below these comments appropriately +# 2) source this file +# 3) pack the text widget ($term) if you have so configured it (see +# "term_alone" below). As distributed, it packs into . automatically. + +############################################# +# Variables that must be initialized before using this: +############################################# +set rows 24 ;# number of rows in term +set rowsDumb $rows ;# number of rows in term when in dumb mode - this can + ;# increase during runtime +set cols 80 ;# number of columns in term +set term .t ;# name of text widget used by term +set sb .sb ;# name of scrollbar used by term in dumb mode +set term_alone 1 ;# if 1, directly pack term into . + ;# else you must pack +set termcap 1 ;# if your applications use termcap +set terminfo 1 ;# if your applications use terminfo + ;# (you can use both, but note that + ;# starting terminfo is slow) +set term_shell $env(SHELL) ;# program to run in term + +############################################# +# Readable variables of interest +############################################# +# cur_row ;# current row where insert marker is +# cur_col ;# current col where insert marker is +# term_spawn_id ;# spawn id of term + +############################################# +# Procs you may want to initialize before using this: +############################################# + +# term_exit is called if the spawned process exits +proc term_exit {} { + exit +} + +# term_chars_changed is called after every change to the displayed chars +# You can use if you want matches to occur in the background (a la bind) +# If you want to test synchronously, then just do so - you don't need to +# redefine this procedure. +proc term_chars_changed {} { +} + +# term_cursor_changed is called after the cursor is moved +proc term_cursor_changed {} { +} + +# Example tests you can make +# +# Test if cursor is at some specific location +# if {$cur_row == 1 && $cur_col == 0} ... +# +# Test if "foo" exists anywhere in line 4 +# if {[string match *foo* [$term get 4.0 4.end]]} +# +# Test if "foo" exists at line 4 col 7 +# if {[string match foo* [$term get 4.7 4.end]]} +# +# Test if a specific character at row 4 col 5 is in standout +# if {-1 != [lsearch [$term tag names 4.5] standout]} ... +# +# Return contents of screen +# $term get 1.0 end +# +# Return indices of first string on lines 4 to 6 that is in standout mode +# $term tag nextrange standout 4.0 6.end +# +# Replace all occurrences of "foo" with "bar" on screen +# for {set i 1} {$i<=$rows} {incr i} { +# regsub -all "foo" [$term get $i.0 $i.end] "bar" x +# $term delete $i.0 $i.end +# $term insert $i.0 $x +# } + +############################################# +# End of things of interest +############################################# + +# Terminal definitions are provided in both termcap and terminfo +# styles because we cannot be sure which a system might have. The +# definitions generally follow that of xterm which in turn follows +# that of vt100. This is useful for the most common archaic software +# which has vt100 definitions hardcoded. + +unset env(DISPLAY) +set env(LINES) $rows +set env(COLUMNS) $cols + +if {$termcap} { + set env(TERM) "tt" + set env(TERMCAP) {tt: + :ks=\E[?1h\E: + :ke=\E[?1l\E>: + :cm=\E[%d;%dH: + :up=\E[A: + :nd=\E[C: + :cl=\E[H\E[J: + :ce=\E[K: + :do=^J: + :so=\E[7m: + :se=\E[m: + :k1=\EOP: + :k2=\EOQ: + :k3=\EOR: + :k4=\EOS: + :k5=\EOT: + :k6=\EOU: + :k7=\EOV: + :k8=\EOW: + :k9=\EOX: + } +} + +if {$terminfo} { + # ncurses ignores 2-char term names so use a longer name here + set env(TERM) "tkterm" + set env(TERMINFO) /tmp + set ttsrc "/tmp/tt.src" + set file [open $ttsrc w] + + puts $file {tkterm|Don Libes' tk text widget terminal emulator, + smkx=\E[?1h\E, + rmkx=\E[?1l\E>, + cup=\E[%p1%d;%p2%dH, + cuu1=\E[A, + cuf1=\E[C, + clear=\E[H\E[J, + el=\E[K, + ind=\n, + cr=\r, + smso=\E[7m, + rmso=\E[m, + kf1=\EOP, + kf2=\EOQ, + kf3=\EOR, + kf4=\EOS, + kf5=\EOT, + kf6=\EOU, + kf7=\EOV, + kf8=\EOW, + kf9=\EOX, + } + close $file + + set oldpath $env(PATH) + set env(PATH) "$env(PATH):/usr/5bin:/usr/lib/terminfo" + if {1==[catch {exec tic $ttsrc} msg]} { + puts "WARNING: tic failed - if you don't have terminfo support on" + puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"." + puts "Here is the original error from running tic:" + puts $msg + } + set env(PATH) $oldpath + + exec rm $ttsrc +} + +set term_standout 0 ;# if in standout mode or not + +log_user 0 + +# start a shell and text widget for its output +set stty_init "-tabs" +eval spawn $term_shell +stty rows $rows columns $cols < $spawn_out(slave,name) +set term_spawn_id $spawn_id + +# this shouldn't be needed if Ousterhout fixes text bug +text $term \ + -yscroll "$sb set" \ + -relief sunken -bd 1 -width $cols -height $rows -wrap none -setgrid 1 + +# define scrollbars +scrollbar .sb -command "$term yview" + +proc graphicsGet {} {return $::graphics(mode)} +proc graphicsSet {mode} { + set ::graphics(mode) $mode + + if {$mode} { + # in graphics mode, no scroll bars + grid forget $::sb + } else { + grid $::sb -column 0 -row 0 -sticky ns + } +} + +if {$term_alone} { + grid $term -column 1 -row 0 -sticky nsew + # let text box only expand + grid rowconfigure . 0 -weight 1 + grid columnconfigure . 1 -weight 1 +} + +$term tag configure standout -background black -foreground white + +proc term_clear {} { + global term + + $term delete 1.0 end + term_init +} + +# pine is the only program I know that requires clear_to_eol, sigh +proc term_clear_to_eol {} { + global cols cur_col cur_row + + # save current col/row + set col $cur_col + set row $cur_row + + set space_rem_on_line [expr $cols - $cur_col] + term_insert [format %[set space_rem_on_line]s ""] + + # restore current col/row + set cur_col $col + set cur_row $row +} + +proc term_init {} { + global rows cols cur_row cur_col term + + # initialize it with blanks to make insertions later more easily + set blankline [format %*s $cols ""]\n + for {set i 1} {$i <= $rows} {incr i} { + $term insert $i.0 $blankline + } + + set cur_row 1 + set cur_col 0 + + $term mark set insert $cur_row.$cur_col + + set ::rowsDumb $rows +} + +proc term_down {} { + global cur_row rows cols term + + if {$cur_row < $rows} { + incr cur_row + } else { + if {[graphicsGet]} { + # in graphics mode + + # already at last line of term, so scroll screen up + $term delete 1.0 "1.end + 1 chars" + + # recreate line at end + $term insert end [format %*s $cols ""]\n + } else { + # in dumb mode + incr cur_row + + if {$cur_row > $::rowsDumb} { + set ::rowsDumb $cur_row + } + + $term insert $cur_row.0 [format %*s $cols ""]\n + $term see $cur_row.0 + } + } +} + +proc term_up {} { + global cur_row rows cols term + + set cur_rowOld $cur_row + incr cur_row -1 + + if {($cur_rowOld > $rows) && ($cur_rowOld == $::rowsDumb)} { + if {[regexp "^ *$" [$::term get $cur_rowOld.0 $cur_rowOld.end]]} { + # delete line + $::term delete $cur_rowOld.0 end + } + incr ::rowsDumb -1 + } +} + +proc term_insert {s} { + global cols cur_col cur_row + global term term_standout + + set chars_rem_to_write [string length $s] + set space_rem_on_line [expr $cols - $cur_col] + + if {$term_standout} { + set tag_action "add" + } else { + set tag_action "remove" + } + + ################## + # write first line + ################## + + if {$chars_rem_to_write > $space_rem_on_line} { + set chars_to_write $space_rem_on_line + set newline 1 + } else { + set chars_to_write $chars_rem_to_write + set newline 0 + } + + $term delete $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write] + $term insert $cur_row.$cur_col [ + string range $s 0 [expr $space_rem_on_line-1] + ] + + $term tag $tag_action standout $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write] + + # discard first line already written + incr chars_rem_to_write -$chars_to_write + set s [string range $s $chars_to_write end] + + # update cur_col + incr cur_col $chars_to_write + # update cur_row + if {$newline} { + term_down + } + + ################## + # write full lines + ################## + while {$chars_rem_to_write >= $cols} { + $term delete $cur_row.0 $cur_row.end + $term insert $cur_row.0 [string range $s 0 [expr $cols-1]] + $term tag $tag_action standout $cur_row.0 $cur_row.end + + # discard line from buffer + set s [string range $s $cols end] + incr chars_rem_to_write -$cols + + set cur_col 0 + term_down + } + + ################# + # write last line + ################# + + if {$chars_rem_to_write} { + $term delete $cur_row.0 $cur_row.$chars_rem_to_write + $term insert $cur_row.0 $s + $term tag $tag_action standout $cur_row.0 $cur_row.$chars_rem_to_write + set cur_col $chars_rem_to_write + } + + term_chars_changed +} + +proc term_update_cursor {} { + global cur_row cur_col term + + $term mark set insert $cur_row.$cur_col + + term_cursor_changed +} + +term_init +graphicsSet 0 + +set flush 0 +proc screen_flush {} { + global flush + incr flush + if {$flush == 24} { + update idletasks + set flush 0 + } +} + +expect_background { + -i $term_spawn_id + -re "^\[^\x01-\x1f]+" { + # Text + term_insert $expect_out(0,string) + term_update_cursor + } "^\r" { + # (cr,) Go to beginning of line + screen_flush + set cur_col 0 + term_update_cursor + } "^\n" { + # (ind,do) Move cursor down one line + term_down + term_update_cursor + } "^\b" { + # Backspace nondestructively + incr cur_col -1 + term_update_cursor + } "^\a" { + bell + } "^\t" { + # Tab, shouldn't happen + send_error "got a tab!?" + } eof { + term_exit + } "^\x1b\\\[A" { + # (cuu1,up) Move cursor up one line + term_up + term_update_cursor + } "^\x1b\\\[C" { + # (cuf1,nd) Non-destructive space + incr cur_col + term_update_cursor + } -re "^\x1b\\\[(\[0-9]*);(\[0-9]*)H" { + # (cup,cm) Move to row y col x + set cur_row [expr $expect_out(1,string)+1] + set cur_col $expect_out(2,string) + term_update_cursor + } "^\x1b\\\[H\x1b\\\[J" { + # (clear,cl) Clear screen + term_clear + term_update_cursor + } "^\x1b\\\[K" { + # (el,ce) Clear to end of line + term_clear_to_eol + term_update_cursor + } "^\x1b\\\[7m" { + # (smso,so) Begin standout mode + set term_standout 1 + } "^\x1b\\\[m" { + # (rmso,se) End standout mode + set term_standout 0 + } "^\x1b\\\[?1h\x1b" { + # (smkx,ks) start keyboard-transmit mode + # terminfo invokes these when going in/out of graphics mode + graphicsSet 1 + } "^\x1b\\\[?1l\x1b>" { + # (rmkx,ke) end keyboard-transmit mode + graphicsSet 0 + } +} + +bind $term <Any-Enter> { + focus %W +} + +bind $term <Meta-KeyPress> { + if {"%A" != ""} { + exp_send -i $term_spawn_id "\033%A" + } +} + +bind $term <KeyPress> { + exp_send -i $term_spawn_id -- %A + break +} + +bind $term <Control-space> {exp_send -null} +bind $term <Control-at> {exp_send -null} + +bind $term <F1> {exp_send -i $term_spawn_id "\033OP"} +bind $term <F2> {exp_send -i $term_spawn_id "\033OQ"} +bind $term <F3> {exp_send -i $term_spawn_id "\033OR"} +bind $term <F4> {exp_send -i $term_spawn_id "\033OS"} +bind $term <F5> {exp_send -i $term_spawn_id "\033OT"} +bind $term <F6> {exp_send -i $term_spawn_id "\033OU"} +bind $term <F7> {exp_send -i $term_spawn_id "\033OV"} +bind $term <F8> {exp_send -i $term_spawn_id "\033OW"} +bind $term <F9> {exp_send -i $term_spawn_id "\033OX"} + +set term_counter 0 +proc term_expect {args} { + upvar timeout localTimeout + upvar #0 timeout globalTimeout + set timeout 10 + catch {set timeout $globalTimeout} + catch {set timeout $localTimeout} + + global term_counter + incr term_counter + global [set strobe _data_[set term_counter]] + global [set tstrobe _timer_[set term_counter]] + + proc term_chars_changed {} "uplevel #0 set $strobe 1" + + set $strobe 1 + set $tstrobe 0 + + if {$timeout >= 0} { + set mstimeout [expr 1000*$timeout] + after $mstimeout "set $strobe 1; set $tstrobe 1" + set timeout_act {} + } + + set argc [llength $args] + if {$argc%2 == 1} { + lappend args {} + incr argc + } + + for {set i 0} {$i<$argc} {incr i 2} { + set act_index [expr $i+1] + if {[string compare timeout [lindex $args $i]] == 0} { + set timeout_act [lindex $args $act_index] + set args [lreplace $args $i $act_index] + incr argc -2 + break + } + } + + while {![info exists act]} { + if {![set $strobe]} { + tkwait var $strobe + } + set $strobe 0 + + if {[set $tstrobe]} { + set act $timeout_act + } else { + for {set i 0} {$i<$argc} {incr i 2} { + if {[uplevel [lindex $args $i]]} { + set act [lindex $args [incr i]] + break + } + } + } + } + + proc term_chars_changed {} {} + + if {$timeout >= 0} { + after $mstimeout unset $strobe $tstrobe + } else { + unset $strobe $tstrobe + } + + set code [catch {uplevel $act} string] + if {$code > 4} {return -code $code $string} + if {$code == 4} {return -code continue} + if {$code == 3} {return -code break} + if {$code == 2} {return -code return} + if {$code == 1} {return -code error -errorinfo $errorInfo \ + -errorcode $errorCode $string} + return $string +} + +################################################## +# user-supplied code goes below here +################################################## + +set timeout 200 + +# for example, wait for a shell prompt +term_expect {regexp "%" [$term get 1.0 3.end]} + +# invoke game of rogue +exp_send "myrogue\r" + +# wait for strength of 18 +term_expect \ + {regexp "Str: 18" [$term get 24.0 24.end]} { + # do something + } {timeout} { + puts "ulp...timed out!" + } {regexp "Str: 16" [$term get 24.0 24.end]} + +# and so on... + diff --git a/example/timed-read b/example/timed-read new file mode 100755 index 0000000..8e63f0f --- /dev/null +++ b/example/timed-read @@ -0,0 +1,12 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# read a complete line from stdin +# aborting after the number of seconds (given as an argument) +# - Don Libes +set timeout $argv +expect -re \n {send_user $expect_out(buffer)} diff --git a/example/timed-run b/example/timed-run new file mode 100755 index 0000000..80def48 --- /dev/null +++ b/example/timed-run @@ -0,0 +1,13 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# run a program for a given amount of time +# i.e. time 20 long_running_program + +set timeout [lindex $argv 0] +eval spawn [lrange $argv 1 end] +expect diff --git a/example/tknewsbiff b/example/tknewsbiff new file mode 100755 index 0000000..9a2da4b --- /dev/null +++ b/example/tknewsbiff @@ -0,0 +1,521 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect +package require Tk + +# Name: tknewsbiff +# Author: Don Libes +# Version: 1.2b +# Written: January 1, 1994 + +# Description: When unread news appears in your favorite groups, pop up +# a little window describing which newsgroups and how many articles. +# Go away when articles are no longer unread. +# Optionally, run a UNIX program (to play a sound, read news, etc.) + +# Default config file in ~/.tknewsbiff[-host] + +# These two procedures are needed because Tk provides no command to undo +# the "wm unmap" command. You must remember whether it was iconic or not. +# PUBLIC +proc unmapwindow {} { + global _window_open + + switch [wm state .] \ + iconic { + set _window_open 0 + } normal { + set _window_open 1 + } + wm withdraw . +} +unmapwindow +# window state starts out as "iconic" before it is mapped, Tk bug? +# make sure that when we map it, it will be open (i.e., "normal") +set _window_open 1 + +# PUBLIC +proc mapwindow {} { + global _window_open + + if {$_window_open} { + wm deiconify . + } else { + wm iconify . + } +} + +proc _abort {msg} { + global argv0 + + puts "$argv0: $msg" + exit 1 +} + +if {[info exists env(DOTDIR)]} { + set home $env(DOTDIR) +} else { + set home [glob ~] +} + +set delay 60 +set width 27 +set height 10 +set _default_config_file $home/.tknewsbiff +set _config_file $_default_config_file +set _default_server news +set server $_default_server +set server_timeout 60 + +log_user 0 + +listbox .list -yscroll ".scrollbar set" -font "*-m-*" -setgrid 1 +scrollbar .scrollbar -command ".list yview" -relief raised +.list config -highlightthickness 0 -border 0 +.scrollbar config -highlightthickness 0 +pack .scrollbar -side left -fill y +pack .list -side left -fill both -expand 1 + +while {[llength $argv]>0} { + set arg [lindex $argv 0] + + if {[file readable $arg]} { + if {0==[string compare active [file tail $arg]]} { + set active_file $arg + set argv [lrange $argv 1 end] + } else { + # must be a config file + set _config_file $arg + set argv [lrange $argv 1 end] + } + } elseif {[file readable $_config_file-$arg]} { + # maybe it's a hostname suffix for a newsrc file? + set _config_file $_default_config_file-$arg + set argv [lrange $argv 1 end] + } else { + # maybe it's just a hostname for regular newsrc file? + set server $arg + set argv [lrange $argv 1 end] + } +} + +proc _read_config_file {} { + global _config_file argv0 watch_list ignore_list + + # remove previous user-provided proc in case user simply + # deleted it from config file + proc user {} {} + + set watch_list {} + set ignore_list {} + + if {[file exists $_config_file]} { + # uplevel allows user to set global variables + if {[catch {uplevel source $_config_file} msg]} { + _abort "error reading $_config_file\n$msg" + } + } + + if {[llength $watch_list]==0} { + watch * + } +} + +# PUBLIC +proc watch {args} { + global watch_list + + lappend watch_list $args +} + +# PUBLIC +proc ignore {ng} { + global ignore_list + + lappend ignore_list $ng +} + +# get time and server +_read_config_file + +# if user didn't set newsrc, try ~/.newsrc-server convention. +# if that fails, fall back to just plain ~/.newsrc +if {![info exists newsrc]} { + set newsrc $home/.newsrc-$server + if {![file readable $newsrc]} { + set newsrc $home/.newsrc + if {![file readable $newsrc]} { + _abort "cannot tell what newgroups you read +found neither $home/.newsrc-$server nor $home/.newsrc" + } + } +} + +# PRIVATE +proc _read_newsrc {} { + global db newsrc + + if {[catch {set file [open $newsrc]} msg]} { + _abort $msg + } + while {-1 != [gets $file buf]} { + if {[regexp "!" $buf]} continue + if {[regexp "(\[^:]*):.*\[-, ](\[0-9]+)" $buf dummy ng seen]} { + set db($ng,seen) $seen + } + # only way 2nd regexp can fail is on lines + # that have a : but no number + } + close $file +} + +proc _unknown_host {} { + global server _default_server + + if {0==[string compare $_default_server $server]} { + puts "tknewsbiff: default server <$server> is not known" + } else { + puts "tknewsbiff: server <$server> is not known" + } + + puts "Give tknewsbiff an argument - either the name of your news server +or active file. I.e., + + tknewsbiff news.nist.gov + tknewsbiff /usr/news/lib/active + +If you have a correctly defined configuration file (.tknewsbiff), +an argument is not required. See the man page for more info." + exit 1 +} + +# read active file +# PRIVATE +proc _read_active {} { + global db server active_list active_file + upvar #0 server_timeout timeout + + set active_list {} + + if {[info exists active_file]} { + spawn -open [open $active_file] + } else { + spawn telnet $server nntp + expect { + "20*\n" { + # should get 200 or 201 + } "NNTP server*\n" { + puts "tknewsbiff: unexpected response from server:" + puts "$expect_out(buffer)" + return 1 + } "unknown host" { + _unknown_host + } timeout { + close + wait + return 1 + } eof { + # loadav too high probably + wait + return 1 + } + } + exp_send "list\r" + expect "list\r\n" ;# ignore echo of "list" command + expect -re "215\[^\n]*\n" ;# skip "Newsgroups in form" line + } + + expect { + -re "(\[^ ]*) 0*(\[^ ]+) \[^\n]*\n" { + set ng $expect_out(1,string) + set hi $expect_out(2,string) + lappend active_list $ng + set db($ng,hi) $hi + exp_continue + } + ".\r\n" close + ".\r\r\n" close + timeout close + eof + } + + wait + return 0 +} + +# test in various ways for good newsgroups +# return 1 if good, 0 if not good +# PRIVATE +proc _isgood {ng threshold} { + global db seen_list ignore_list + + # skip if we don't subscribe to it + if {![info exists db($ng,seen)]} {return 0} + + # skip if the threshold isn't exceeded + if {$db($ng,hi) - $db($ng,seen) < $threshold} {return 0} + + # skip if it matches an ignore command + foreach igpat $ignore_list { + if {[string match $igpat $ng]} {return 0} + } + + # skip if we've seen it before + if {[lsearch -exact $seen_list $ng]!=-1} {return 0} + + # passed all tests, so remember that we've seen it + lappend seen_list $ng + return 1 +} + +# return 1 if not seen on previous turn +# PRIVATE +proc _isnew {ng} { + global previous_seen_list + + if {[lsearch -exact $previous_seen_list $ng]==-1} { + return 1 + } else { + return 0 + } +} + +# schedule display of newsgroup in global variable "newsgroup" +# PUBLIC +proc display {} { + global display_list newsgroup + + lappend display_list $newsgroup +} + +# PRIVATE +proc _update_ngs {} { + global watch_list active_list newsgroup + + foreach watch $watch_list { + set threshold 1 + set display display + set new {} + + set ngpat [lindex $watch 0] + set watch [lrange $watch 1 end] + + while {[llength $watch] > 0} { + switch -- [lindex $watch 0] \ + -threshold { + set threshold [lindex $watch 1] + set watch [lrange $watch 2 end] + } -display { + set display [lindex $watch 1] + set watch [lrange $watch 2 end] + } -new { + set new [lindex $watch 1] + set watch [lrange $watch 2 end] + } default { + _abort "watch: expecting -threshold -display or -new but found: [lindex $watch 0]" + } + } + + foreach ng $active_list { + if {[string match $ngpat $ng]} { + if {[_isgood $ng $threshold]} { + if {[llength $display]} { + set newsgroup $ng + uplevel $display + } + if {[_isnew $ng]} { + if {[llength $new]} { + set newsgroup $ng + uplevel $new + } + } + } + } + } + } +} + +# initialize display + +set min_reasonable_width 8 + +wm minsize . $min_reasonable_width 1 +wm maxsize . 999 999 +if {0 == [info exists active_file] && + 0 != [string compare $server $_default_server]} { + wm title . "news@$server" + wm iconname . "news@$server" +} + +# PRIVATE +proc _update_window {} { + global server display_list height width min_reasonable_width + + if {0 == [llength $display_list]} { + unmapwindow + return + } + + # make height correspond to length of display_list or + # user's requested max height, whichever is smaller + + if {[llength $display_list] < $height} { + set current_height [llength $display_list] + } else { + set current_height $height + } + + # force reasonable min width + if {$width < $min_reasonable_width} { + set width $min_reasonable_width + } + + wm geometry . ${width}x$current_height + wm maxsize . 999 [llength $display_list] + + _display_ngs $width + + if {[string compare [wm state .] withdrawn]==0} { + mapwindow + } +} + +# actually write all newsgroups to the window +# PRIVATE +proc _display_ngs {width} { + global db display_list + + set str_width [expr $width-7] + + .list delete 0 end + foreach ng $display_list { + .list insert end [format \ + "%-$str_width.${str_width}s %5d" $ng \ + [expr $db($ng,hi) - $db($ng,seen)]] + } +} + +# PUBLIC +proc help {} { + catch {destroy .help} + toplevel .help + message .help.text -aspect 400 -text \ +{tknewsbiff - written by Don Libes, NIST, 1/1/94 + +tknewsbiff displays newsgroups with unread articles based on your .newsrc\ +and your .tknewsbiff files.\ +If no articles are unread, no window is displayed. + +Click mouse button 1 for this help,\ +button 2 to force display to query news server immediately,\ +and button 3 to remove window from screen until the next update. + +Example .tknewsbiff file:} + message .help.sample -font "*-r-normal-*-m-*" \ + -relief raised -aspect 10000 -text \ +{set width 30 ;# max width, defaults to 27 +set height 17 ;# max height, defaults to 10 +set delay 120 ;# in seconds, defaults to 60 +set server news.nist.gov ;# defaults to "news" +set server_timeout 60 ;# in seconds, defaults to 60 +set newsrc ~/.newsrc ;# defaults to ~/.newsrc + ;# after trying ~/.newsrc-$server +# Groups to watch. +watch comp.lang.tcl +watch dc.dining -new "play yumyum" +watch nist.security -new "exec red-alert" +watch nist.* +watch dc.general -threshold 5 +watch *.sources.* -threshold 20 +watch alt.howard-stern -threshold 100 -new "play robin" + +# Groups to ignore (but which match patterns above). +# Note: newsgroups that you don't read are ignored automatically. +ignore *.d +ignore nist.security +ignore nist.sport + +# Change background color of newsgroup list +.list config -bg honeydew1 + +# Play a sound file +proc play {sound} { + exec play /usr/local/lib/sounds/$sound.au +}} + message .help.end -aspect 10000 -text \ +"Other customizations are possible. See man page for more information." + + button .help.ok -text "ok" -command {destroy .help} + pack .help.text + pack .help.sample + pack .help.end -anchor w + pack .help.ok -fill x -padx 2 -pady 2 +} + +spawn cat -u; set _cat_spawn_id $spawn_id +set _update_flag 0 + +# PUBLIC +proc update-now {} { + global _update_flag _cat_spawn_id + + if {$_update_flag} return ;# already set, do nothing + set _update_flag 1 + + exp_send -i $_cat_spawn_id "\r" +} + +bind .list <1> help +bind .list <2> update-now +bind .list <3> unmapwindow +bind .list <Configure> { + scan [wm geometry .] "%%dx%%d" w h + _display_ngs $w +} + +# PRIVATE +proc _sleep {timeout} { + global _cat_spawn_id _update_flag + + set _update_flag 0 + + # restore to idle cursor + .list config -cursor ""; update + + # sleep for a little while, subject to click from "update" button + expect -i $_cat_spawn_id -re "...." ;# two crlfs + + # change to busy cursor + .list config -cursor watch; update +} + +set previous_seen_list {} +set seen_list {} + +# PRIVATE +proc _init_ngs {} { + global display_list db + global seen_list previous_seen_list + + set previous_seen_list $seen_list + + set display_list {} + set seen_list {} + + catch {unset db} +} + +for {} {1} {_sleep $delay} { + _init_ngs + + _read_newsrc + if {[_read_active]} continue + _read_config_file + + _update_ngs + user + _update_window +} diff --git a/example/tknewsbiff.man b/example/tknewsbiff.man new file mode 100644 index 0000000..dc5d4ad --- /dev/null +++ b/example/tknewsbiff.man @@ -0,0 +1,412 @@ +.TH TKNEWSBIFF 1 "1 January 1994" +.SH NAME +tknewsbiff \- pop up a window when news appears +.SH SYNOPSIS +.B tknewsbiff +[ +.I server or config-file +] +.br +.SH INTRODUCTION +.B tknewsbiff +pops up a window when there is unread news in your favorite newsgroups +and removes the window after you've read the news. tknewsbiff can +optionally play a sound, start your newsreader, etc. + +.SH SELECTING NEWSGROUPS + +By default, the configuration file ~/.tknewsbiff describes how +tknewsbiff behaves. The syntax observes the usual Tcl rules +- however, even if you don't know Tcl, all but the most esoteric +configurations will be obvious. + +Each newsgroup (or set of newsgroups) to be watched is described by +using the "watch" command. For example: + +.nf + +watch dc.dining +watch nist.* +watch comp.unix.wizard -threshold 3 +watch *.sources.* -threshold 20 + +.fi + +For each newsgroup pattern, any newsgroup that matches it and which +you are subscribed to (according to your newsrc file) is eligible for +reporting. By default, tknewsbiff reports on the newsgroup if there +is at least one unread article. The "-threshold" flag changes the +threshold to the following number. For example, "-threshold 3" means +there must be at least three articles unread before tknewsbiff will +report the newsgroup. + +If no watch commands are given (or no configuration file exists), all +groups which are subscribed to are watched. + +To suppress newsgroups that would otherwise be reported, use the +"ignore" command. For example, the following matches all comp.* and +nist.* newgroups except for nist.posix or .d (discussion) groups: + +.nf + +watch comp.* +watch nist.* +ignore nist.posix.* +ignore *.d + +.fi + +The flag "-new" describes a command to be executed when the newsgroup +is first reported as having unread news. For example, the following +lines invoke the UNIX command "play" to play a sound. + +.nf + +watch dc.dining -new "exec play /usr/local/sounds/yumyum.au" +watch rec.auto* -new "exec play /usr/local/sounds/vroom.au" + +.fi + +You can cut down on the verbosity of actions by defining procedures. +For example, if you have many -new flags that all play sound files, +you could define a sound procedure. This would allow the -new +specification to be much shorter. + +.nf + +proc play {sound} { + exec play /usr/local/sounds/$sound.au +} + +watch dc.dining -new "play yumyum" +watch rec.auto* -new "play vroom" + +.fi + +As an aside, you can put an "&" at the end of an "exec" command to get +commands to execute asynchronously. However, it's probably not a good +idea to do this when playing sound files anyway. + +"newsgroup" is a read-only variable which contains the name of the +newsgroup that is being reported. This is useful when the action is +triggered by a pattern. For example, the following line could run the +newsgroup name through a speech synthesizer: + +.nf + +watch * -new { + exec play herald.au + exec speak "New news has arrived in $newsgroup." +} + +.fi + +The flag "\-display" describes a command to be executed every time the +newsgroup is reported as having unread news. The special command +"display" is the default command. It schedules $newsgroup to be +written to tknewsbiff's display when it is rewritten. For example, by +explicitly providing a -display flag that omits the display command, +you can disable the display of newsgroups that are already reported +via -new. + +.nf + +watch dc.dining -new {exec play yumyum.au} -display {} + +.fi + +If you want to execute an action repeatedly and +.I still +display the newsgroup in the default manner, +explicitly invoke the display command via the -display flag. For example: + +.nf + +watch *security* -display { + exec play red-alert.au + display +} + +.fi + +Actions associated with the -new and -display flags are executed only +once for each matching newsgroup. The command executed is the one +associated with the first pattern in the configuration file that +matches and observes the given threshold. + +Any command that is simply listed in the configuration file is +executed each time before the update loop in tknewsbiff. The reserved +(but user-defined) procedure "user" is run immediately after the +newsgroups are scheduled to be written to the display and before they +are actually written. + +For example, suppose unread articles appear in several rec.auto groups +and you play the same sound for each one. To prevent playing the +sound several times in a row, make the -new command simply set a flag. +In the user procedure, play the sound if the flag is set (and then +reset the flag). + +The user procedure could also be used to start a newsreader. This +would avoid the possibility of starting multiple newsreaders just +because multiple newsgroups contained unread articles. (A check +should, of course, be made to make sure that a newsreader is not +already running.) + +.SH MORE VARIABLES + +The following example lines show variables that can affect the +behavior of tknewsbiff + +.nf + +set delay 120 +set server news.nist.gov +set server_timeout 60 +set newsrc ~/.newsrc +set width 40 +set height 20 +set active_file /usr/news/lib/active + +.fi + +tknewsbiff alternates between checking for unread news and +sleeping (kind of like many undergraduates). The "delay" variable +describes how many seconds to sleep. + +The "server" variable names an NNTP news-server. +The default is "news". The "server" variable is +only used if the "active_file" variable is not set. + +The "server_timeout" variable describes how how many seconds to wait +for a response from the server before giving up. -1 means wait +forever or until the server itself times out. The default is 60 +seconds. + +The "newsrc" variable describes the name of your .newsrc file. By +default, tknewsbiff looks in your home directory for a newsrc file. A +server-specific newsrc is used if found. For example, if you have set +server to "cubit.nist.gov", then tknewsbiff looks for +~/.newsrc-cubit.nist.gov. (This is the Emacs gnus convention - which +is very convenient when you read news from multiple servers.) If +there is no server-specific newsrc, tknewsbiff uses ~/.newsrc. + +The "width" variable describes the width that tknewsbiff will use to +display information. If any newsgroup names are long enough, they +will be truncated so that the article counts can still be shown. You +can manually resize the window to see what was truncated. However, if +your configuration file sets the width variable, the window will be +restored to that size the next time that tknewsbiff checks for unread +news and updates its display. + +The "height" variable describes the maximum height that tknewsbiff +will use to display information. If fewer newsgroups are reported, +tknewsbiff will shrink the window appropriately. You can manually +resize the window but if your configuration file sets the height +variable, the window will be restored to that size the next time that +tknewsbiff checks for unread news and updates its display. + +The "active_file" variable describes the name of the news active file. +If set, the active file is read directly in preference to using NNTP +(even if the "server" variable is set). This is particularly useful +for testing out new configuration files since you can edit a fake +active file and then click button 2 to immediately see how tknewsbiff +responds (see BUTTONS below). + +If the environment variable DOTDIR is set, then its value is used as a +directory in which to find all dotfiles instead of from the home +directory. In particular, this affects the tknewsbiff configuration +file and the .newsrc file (assuming the newsrc variable is not set +explicitly). + +.SH WATCHING DIFFERENT NEWS SERVERS + +To watch multiple servers, run tknewsbiff multiple times. (Since you +need different .newsrc files and the servers have different newsgroups +and article numbers anyway, there is no point in trying to do this in +a single process.) + +You can point tknewsbiff at a different server with an appropriate +argument. The argument is tried both as a configuration file name and +as a suffix to the string "~/.tknewsbiff-". So if you want to watch +the server "kidney", store the tknewsbiff configuration information in +~/.tknewsbiff-kidney". The following two commands will both use that +configuration file. + +.nf + + tknewsbiff kidney + tknewsbiff ~/.tknewsbiff-kidney + +.fi + +In both cases, the actual server to contact is set by the value of the +server variable in the configuration file. + +If no configuration file is found, the argument is used as the server +to contact. This allows tknewsbiff to be run with no preparation +whatsoever. + +If the argument is the special keyword "active" (or ends in +"/active"), it is used as the name of an active file. This is in turn +used to initialize the variable "active_file" so that tknewsbiff reads +from the active file directly rather than using NNTP. + +Creating your own active file is a convenient way of testing your +configuration file. For example, after running the following command, +you can repeatedly edit your active file and trigger the update-now +command (either by pressing button 2 or setting the delay variable +very low) to see how tknewsbiff responds. + +The active file must follow the format of a real active file. The +format is one newsgroup per line. After the newsgroup name is the +number of the highest article, the lowest article. Lastly is the +letter y or m. m means the newsgroup is moderated. y means posting +is allowed. + +.SH WINDOW + +When unread news is found, a window is popped up. The window lists +the names of the newsgroups and the number of unread articles in each +(unless suppressed by the -display flag). When there is no longer any +unread news, the window disappears (although the process continues to +run). + +.SH BUTTONS + +Button or key bindings may be assigned by bind commands. Feel free to +change them. The default bind commands are: + +.nf + +bind .list <1> help +bind .list <2> update-now +bind .list <3> unmapwindow + +.fi + +By default button 1 (left) is bound to "help". The help command +causes tknewsbiff to pop up a help window. + +By default, button 2 (middle) is bound to "update-now". The update-now +command causes tknewsbiff to immediately check for unread news. If +your news server is slow or maintains a very large number of +newsgroups, or you have a large number of patterns in your +configuration file, tknewsbiff can take considerable time before +actually updating the window. + +By default, button 3 (right) is bound to "unmapwindow". The +unmapwindow command causes tknewsbiff to remove the window from the +display until the next time it finds unread news. (The mapwindow +command causes tknewsbiff to restore the window.) + +As an example, here is a binding to pop up an xterm and run rn when +you hold down the shift key and press button 1 in the listing window. + +.nf + +bind .list <Shift-1> { + exec xterm -e rn & +} + +.fi + +Here is a similar binding. However it tells rn to look only at the +newsgroup that is under the mouse when you pressed it. (The +"display_list" variable is described later in this man page.) + +.nf + +bind .list <Shift-1> { + exec xterm -e rn [lindex $display_list [.list nearest %y]] & +} + +.fi + +.SH OTHER COMMANDS AND VARIABLES + +Built-in commands already mentioned are: watch, ignore, display, help, +update-now, unmapwindow, and mapwindow. + +Any Tcl and Tk command can also be given. In particular, the list of +newsgroups is stored in the list widget ".list", and the scroll bar is +stored in the scrollbar widget ".scroll". So for example, if you want +to change the foreground and background colors of the newsgroup list, +you can say: + +.nf + + .list config -bg honeydew1 -fg orchid2 + +.fi + +These can also be controlled by the X resource database as well. +However, the configuration file allows arbitrarily complex commands to +be evaluated rather than simple assignments. + +Certain Tcl/Tk commands can disrupt proper function of tknewsbiff. +These will probably be obvious to anyone who knows enough to give +these commands in the first place. As a simple example, the program +assumes the font in the list box is of fixed width. The newsgroups +will likely not align if you use a variable-width font. + +The following variables are accessible and can be used for esoteric +uses. All other variables are private. Private variables and +commands begin with "_" so you don't need to worry about accidental +collisions. + +The array "db" is a database which maintains information about read +and unread news. db($newsgroup,hi) is the highest article that +exists. db($newsgroup,seen) is the highest article that you have +read. + +A number of lists maintain interesting information. "active_list" is a +list of known newsgroups. "seen_list" is a list of newsgroups that +have been seen so far as the -new and -display flags are being +processed. "previous_seen_list" is "seen_list" from the previous +cycle. "ignore_list" is the list of newsgroup patterns to ignore. +"watch_list" is the list of newsgroup patterns to watch. +"display_list" is the list of newsgroup will be displayed at the next +opportunity. + +.SH UPDATING YOUR FILES + +tknewsbiff automatically rereads your configuration file each time it +wakes up to check for unread news. To force tknewsbiff to reread the +file immediately (such as if you are testing a new configuration or +have just modified your newsrc file), press button 2 in the display +(see BUTTONS above). + +.SH CAVEATS + +tknewsbiff defines the number of unread articles as the highest +existing article minus the highest article that you've read. So if +you've read the last article in the newsgroup but no others, +tknewsbiff thinks there are no unread articles. (It's impossible to +do any better by reading the active file and it would be very time +consuming to do this more accurately via NNTP since servers provide no +efficient way of reporting their own holes in the newsgroups.) +Fortunately, this definition is considered a feature by most people. +It allows you to read articles and then mark them "unread" but not +have tknewsbiff continue telling you that they are unread. + +.SH UNWARRANTED CONCERNS + +Your news administrator may wonder if many people using tknewsbiff +severely impact an NNTP server. In fact, the impact is negligible +even when the delay is very low. To gather all the information it +needs, tknewsbiff uses a single NNTP query - it just asks for the +active file. The NNTP server does no computation, formatting, etc, it +just sends the file. All the interesting processing happens locally +in the tknewsbiff program itself. + +.SH BUGS + +The man page is longer than the program. + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/tkpasswd b/example/tkpasswd new file mode 100755 index 0000000..376c56a --- /dev/null +++ b/example/tkpasswd @@ -0,0 +1,612 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect +package require Tk + +# tkpasswd - Change passwords using Expectk +# Author: Don Libes, NIST, October 1, 1993 +# Version: 1.8 - Added support for Tk 4.1 + +# There is no man page. However, there is some on-line help when you run +# the program. Technical details and insights are described in the +# O'Reilly book "Exploring Expect". + +proc prog_exists {prog} { + return [llength [auto_execok $prog]] +} + +frame .type -relief raised -bd 1 + +radiobutton .passwd -text passwd -variable passwd_cmd \ + -value {passwd {cat /etc/passwd}} \ + -anchor w -command get_users -relief flat +pack .passwd -in .type -fill x + +if {[prog_exists yppasswd]} { + radiobutton .yppasswd -text yppasswd -variable passwd_cmd \ + -value {yppasswd {ypcat passwd}} \ + -anchor w -command get_users -relief flat + pack .yppasswd -in .type -fill x +} + +if {[prog_exists nispasswd]} { + radiobutton .nispasswd -text nispasswd -variable passwd_cmd \ + -value {nispasswd {niscat passwd}} \ + -anchor w -command get_users -relief flat + pack .nispasswd -in .type -fill x +} +pack .type -fill x + +frame .sort -relief raised -bd 1 +radiobutton .unsorted -text unsorted -variable sort_cmd -value " " \ + -anchor w -relief flat -command get_users +radiobutton .name -text name -variable sort_cmd -value "| sort" \ + -anchor w -relief flat -command get_users +radiobutton .uid -text uid -variable sort_cmd -value "| sort -t: -n +2" \ + -anchor w -relief flat -command get_users +pack .unsorted .name .uid -in .sort -fill x +pack .sort -fill x + +frame .users -relief raised -bd 1 +# has to be wide enough for 8+1+5=14 +text .names -yscrollcommand ".scroll set" -width 14 -height 1 \ + -font {Courier 12 bold} -setgrid 1 +.names tag configure nopassword -relief raised +.names tag configure selection -relief raised + +set iscolor 0 +if {[winfo depth .] > 1} { + set iscolor 1 +} + +if {$iscolor} { + .names tag configure nopassword -background red + .names tag configure selection -background green +} else { + .names tag configure nopassword -background black -foreground white + .names tag configure selection -background white -foreground black +} +scrollbar .scroll -command ".names yview" -relief raised +pack .scroll -in .users -side left -fill y +pack .names -in .users -side left -fill y +pack .users -expand 1 -fill y + +wm minsize . 14 1 +wm maxsize . 14 999 +wm geometry . 14x10 + +frame .password_frame -relief raised -bd 1 +entry .password -textvar password -relief sunken -width 1 +focus .password +bind .password <Return> password_set +label .prompt -text "Password:" -bd 0 +button .password_set -text "set" -command password_set +button .generate_button -text "generate" -command password_generate +pack .prompt .password -in .password_frame -fill x -padx 2 -pady 2 +pack .password_set .generate_button -in .password_frame -side left -expand 1 -fill x -padx 2 -pady 2 +pack .password_frame -fill x + +set dict_loaded 0 +checkbutton .dict -text "test dictionary" -variable dict_check \ + -command {if {!$dict_loaded} load_dict} \ + -anchor w +pack .dict -fill x -padx 2 -pady 2 + + +button .quit -text quit -command exit +button .help_button -text help -command help +pack .quit .help_button -side left -expand 1 -fill x -padx 2 -pady 2 + +proc help {} { + if {[catch {toplevel .help}]} return + message .help.text -text \ +"tkpasswd - written by Don Libes, NIST, 10/1/93. + +Click on passwd (local users) or yppasswd (NIS users).\ +Select user using mouse (or keys - see below).\ +Enter password or press ^G to generate a random password.\ +(Press ^A to adjust the generation parameters.)\ +Press return to set the password.\ +If the dictionary is enabled and the password is in it,\ +the password is rejected. + +You must be root to set local passwords besides your own.\ +If you are not root, you must also enter an old password\ +when requested. + +You do not have to move mouse into password field(s) to enter password.\ +^U clears password field.\ +^N and ^P select next/previous user.\ +M-n and M-p select next/previous user with no password.\ +(Users with no passwords are highlighted.)" + + button .help.ok -text "ok" -command {destroy .help} + pack .help.text + pack .help.ok -fill x -padx 2 -pady 2 +} + +# get list of local users +proc get_users {} { + global sort_cmd passwd_cmd + global nopasswords ;# line numbers of entries with no passwords + global last_line ;# last line of text box + global selection_line + + .names delete 1.0 end + + set file [open "|[lindex $passwd_cmd 1] $sort_cmd"] + set last_line 1 + set nopasswords {} + while {[gets $file buf] != -1} { + set buf [split $buf :] + if {[llength $buf]>2} { + # normal password entry + .names insert end "[format "%-8.8s %5d" [lindex $buf 0] [lindex $buf 2]]\n" + if {0==[string compare [lindex $buf 1] ""]} { + .names tag add nopassword \ + {end - 2 line linestart} \ + {end - 2 line lineend} + lappend nopasswords $last_line + } + } else { + # +name style entry + .names insert end "$buf\n" + } + incr last_line + } + incr last_line -1 + close $file + set selection_line 0 +} + +proc feedback {msg} { + global password + + set password $msg + .password select from 0 + .password select to end + update +} + +proc load_dict {} { + global dict dict_loaded + + feedback "loading dictionary..." + + if {0==[catch {open /usr/dict/words} file]} { + foreach w [split [read $file] "\n"] {set dict($w) ""} + close $file + set dict_loaded 1 + feedback "dictionary loaded" + } else { + feedback "dictionary missing" + .dict deselect + } +} + +# put whatever security checks you like in here +proc weak_password {password} { + global dict dict_check + + if {$dict_check} { + feedback "checking password" + + if {[info exists dict($password)]} { + feedback "sorry - in dictionary" + return 1 + } + } + return 0 +} + +proc password_set {} { + global password passwd_cmd selection_line + + set new_password $password + + if {$selection_line==0} { + feedback "select a user first" + return + } + set user [lindex [.names get selection.first selection.last] 0] + + if {[weak_password $password]} return + + feedback "setting password . . ." + + set cmd [lindex $passwd_cmd 0] + spawn -noecho $cmd $user + log_user 0 + set last_msg "error in $cmd" + while {1} { + expect { + -nocase "old password:" { + exp_send "[get_old_password]\r" + } "assword*:" { + exp_send "$new_password\r" + } -re "(.*)\r\n" { + set last_msg $expect_out(1,string) + } eof break + } + } + set status [wait] + if {[lindex $status 3]==0} { + feedback "set successfully" + } else { + feedback $last_msg + } +} + +# defaults for generating passwords +set length 9 +set minnum 2 +set minlower 5 +set minupper 2 +set distribute 0 + +proc parameter_filename {} { + set file .tkpasswd.rc + if {[info exists env(DOTDIR)]} { + set file "$env(DOTDIR)/$file" + } + return ~/$file +} + +catch {source [parameter_filename]} + +# save parameters in a file +proc save_parameters {} { + global minnum minlower minupper length + + if {[catch {open [parameter_filename] w} f]} { + # should never happen, so don't bother with window code + puts "tkpasswd: could not write [parameter_filename]" + return + } + puts $f "# This is the .tkpasswd.rc file. Do not edit it by hand as" + puts $f "# it is automatically maintained by tkpasswd. Any manual" + puts $f "# modifications will be lost." + puts $f "" + puts $f "set length $length" + puts $f "set minnum $minnum" + puts $f "set minupper $minupper" + puts $f "set minlower $minlower" + close $f +} + +# insert char into password at a random position +proc insert {pvar char} { + upvar $pvar p + + set p [linsert $p [rand [expr 1+[llength $p]]] $char] +} + +# given a size, distribute between left and right hands +# taking into account where we left off +proc psplit {max lvar rvar} { + upvar $lvar left $rvar right + global isleft + + if {$isleft} { + set right [expr $max/2] + set left [expr $max-$right] + set isleft [expr !($max%2)] + } else { + set left [expr $max/2] + set right [expr $max-$left] + set isleft [expr $max%2] + } +} + +proc password_generate {} { + global password length minnum minlower minupper + global lpass rpass initially_left isleft + global distribute + + if {$distribute} { + set lkeys {q w e r t a s d f g z x c v b} + set rkeys {y u i o p h j k l n m} + set lnums {1 2 3 4 5 6} + set rnums {7 8 9 0} + } else { + set lkeys {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} + set rkeys {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} + set lnums {0 1 2 3 4 5 6 7 8 9} + set rnums {0 1 2 3 4 5 6 7 8 9} + } + set lkeys_length [llength $lkeys] + set rkeys_length [llength $rkeys] + set lnums_length [llength $lnums] + set rnums_length [llength $rnums] + + # if there is any underspecification, use additional lowercase letters + set minlower [expr $length - ($minnum + $minupper)] + + + set lpass "" ;# password chars typed by left hand + set rpass "" ;# password chars typed by right hand + set password "" ;# merged password + + # choose left or right starting hand + set initially_left [set isleft [rand 2]] + + psplit $minnum left right + for {set i 0} {$i<$left} {incr i} { + insert lpass [lindex $lnums [rand $lnums_length]] + } + for {set i 0} {$i<$right} {incr i} { + insert rpass [lindex $rnums [rand $rnums_length]] + } + + psplit $minlower left right + for {set i 0} {$i<$left} {incr i} { + insert lpass [lindex $lkeys [rand $lkeys_length]] + } + for {set i 0} {$i<$right} {incr i} { + insert rpass [lindex $rkeys [rand $rkeys_length]] + } + + psplit $minupper left right + for {set i 0} {$i<$left} {incr i} { + insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]] + } + for {set i 0} {$i<$right} {incr i} { + insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]] + } + + # merge results together + if {$initially_left} { + regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass + while {[llength $lpass]} { + regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass + regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass + } + if {[llength $rpass]} { + append password $rpass + } + } else { + regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass + while {[llength $rpass]} { + regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass + regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass + } + if {[llength $lpass]} { + append password $lpass + } + } +} + +proc rand {m} { + expr {int($m*rand())} +} + +proc gen_bad_args {msg} { + if {![llength [info commands .parameters.errmsg]]} { + message .parameters.errmsg -aspect 300 + pack .parameters.errmsg + } + .parameters.errmsg configure -text "$msg\ + Please adjust the password generation arguments." +} + + +# tell tab what window to move between +set parm_tabList {} + +# The procedure below is invoked in response to tabs in the entry +# windows. It moves the focus to the next window in the tab list. +# Arguments: +# +# list - Ordered list of windows to receive focus + +proc Tab {list} { + set i [lsearch $list [focus]] + if {$i < 0} { + set i 0 + } else { + incr i + if {$i >= [llength $list]} { + set i 0 + } + } + focus [lindex $list $i] +} + +# adjust args used in password generation +proc adjust_parameters {} { + global parm_tabList + set parm_tabList {} + + toplevel [set w .parameters] + + message $w.text -aspect 300 -text \ +"These parameters control generation of random passwords. + +It is not necessary to move the mouse into this window to operate it.\ +Press <tab> to move to the next entry.\ +Press <return> or click the <ok> button when you are done." + + foreach desc { + {length {total length}} + {minnum {minimum number of digits}} + {minupper {minimum number of uppercase letters}} + {minlower {minimum number of lowercase letters}}} { + set name [lindex $desc 0] + set text [lindex $desc 1] + frame $w.$name -bd 1 + entry $w.$name.entry -relief sunken -width 2 -textvar $name + bind $w.$name.entry <Tab> "Tab \$parm_tabList" + bind $w.$name.entry <Return> "destroy_parm_window" + label $w.$name.text -text $text + pack $w.$name.entry -side left + pack $w.$name.text -side left + lappend parm_tabList $w.$name.entry + } + frame $w.2 -bd 1 + checkbutton $w.2.cb -text "alternate characters across hands" \ + -relief flat -variable distribute + pack $w.2.cb -side left + + button $w.ok -text "ok" -command "destroy_parm_window" + pack $w.text -expand 1 -fill x + pack $w.length $w.minnum $w.minupper $w.minlower $w.2 -expand 1 -fill x + pack $w.ok -side left -fill x -expand 1 -padx 2 -pady 2 + + set oldfocus [focus] + tkwait visibility $w.length.entry + focus $w.length.entry + tkwait window $w + focus $oldfocus + save_parameters +} + +proc isnumber {n} { + regexp "^\[0-9\]+$" $n +} + +# destroy parm window IF all values are legal +proc destroy_parm_window {} { + global minnum minlower minupper length + + set mustbe "must be a number greater than or equal to zero." + + # check all variables + if {![isnumber $length]} { + gen_bad_args "The total length $mustbe" + return + } + if {![isnumber $minlower]} { + gen_bad_args "The minimum number of lowercase characters $mustbe" + return + } + if {![isnumber $minupper]} { + gen_bad_args "The minimum number of uppercase characters $mustbe" + return + } + if {![isnumber $minnum]} { + gen_bad_args "The minimum number of digits $mustbe" + return + } + + # check constraints + if {$minnum + $minlower + $minupper > $length} { + gen_bad_args \ + "It is impossible to generate a $length-character password with\ + $minnum number[pluralize $minnum],\ + $minlower lowercase letter[pluralize $minlower], and\ + $minupper uppercase letter[pluralize $minupper]." + return + } + + destroy .parameters +} + +# return appropriate ending for a count of "n" nouns +proc pluralize {n} { + expr $n!=1?"s":"" +} + + +proc get_old_password {} { + global old + + toplevel .old + label .old.label -text "Old password:" + catch {unset old} + entry .old.entry -textvar old -relief sunken -width 1 + + pack .old.label + pack .old.entry -fill x -padx 2 -pady 2 + + bind .old.entry <Return> {destroy .old} + set oldfocus [focus] + focus .old.entry + tkwait visibility .old + grab .old + tkwait window .old + focus $oldfocus + return $old +} + +.unsorted select +.passwd invoke + +proc make_selection {} { + global selection_line last_line + + .names tag remove selection 0.0 end + + # don't let selection go off top of screen + if {$selection_line < 1} { + set selection_line $last_line + } elseif {$selection_line > $last_line} { + set selection_line 1 + } + .names yview -pickplace [expr $selection_line-1] + .names tag add selection $selection_line.0 [expr 1+$selection_line].0 +} + +proc select_next_nopassword {direction} { + global selection_line last_line nopasswords + + if {0==[llength $nopasswords]} { + feedback "no null passwords" + return + } + + if {$direction==1} { + # is there a better way to get last element of list? + if {$selection_line>=[lindex $nopasswords [expr [llength $nopasswords]-1]]} { + set selection_line 0 + } + foreach i $nopasswords { + if {$selection_line<$i} break + } + } else { + if {$selection_line<=[lindex $nopasswords 0]} { + set selection_line $last_line + } + set j [expr [llength $nopasswords]-1] + for {} {$j>=0} {incr j -1} { + set i [lindex $nopasswords $j] + if {$selection_line>$i} break + } + } + set selection_line $i + make_selection +} + +proc select {w coords} { + global selection_line + + $w mark set insert "@$coords linestart" + $w mark set anchor insert + set first [$w index "anchor linestart"] + set last [$w index "insert lineend + 1c"] + scan $first %d selection_line + + $w tag remove selection 0.0 end + $w tag add selection $first $last +} + +bind Text <1> {select %W %x,%y} +bind Text <Double-1> {select %W %x,%y} +bind Text <Triple-1> {select %W %x,%y} +bind Text <2> {select %W %x,%y} +bind Text <3> {select %W %x,%y} +bind Text <B1-Motion> {} +bind Text <Shift-1> {} +bind Text <Shift-B1-Motion> {} +bind Text <B2-Motion> {} + +bind .password <Control-n> {incr selection_line 1; make_selection} +bind .password <Control-p> {incr selection_line -1;make_selection} +bind .password <Meta-n> {select_next_nopassword 1} +bind .password <Meta-p> {select_next_nopassword -1} +bind .password <Control-g> {password_generate} +bind .password <Control-a> {adjust_parameters} +bind .password <Control-u> {set password ""} +bind Entry <Control-c> {exit} diff --git a/example/tkterm b/example/tkterm new file mode 100755 index 0000000..16ee972 --- /dev/null +++ b/example/tkterm @@ -0,0 +1,539 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect +package require Tk + +# Name: tkterm - terminal emulator using Expect and Tk text widget, v3.0 +# Author: Don Libes, July '94 +# Last updated: Mar '04 + +# This is primarily for regression testing character-graphic applications. +# You can certainly use it as a terminal emulator - however many features +# in a real terminal emulator are not supported (although I'll probably +# add some of them later). + +# A paper on the implementation: Libes, D., Automation and Testing of +# Interactive Character Graphic Programs", Software - Practice & +# Experience, John Wiley & Sons, West Sussex, England, Vol. 27(2), +# p. 123-137, February 1997. + +############################### +# Quick overview of this emulator +############################### +# Very good attributes: +# Understands both termcap and terminfo +# Understands meta-key (zsh, emacs, etc work) +# Is fast +# Understands X selections +# Looks best with fixed-width font but doesn't require it +# Supports scrollbars +# Good-enough-for-starters attributes: +# Understands one kind of standout mode (reverse video) +# Should-be-fixed-soon attributes: +# Does not support resize +# Probably-wont-be-fixed-soon attributes: +# Assumes only one terminal exists + +############################################### +# To try out this package, just run it. Using it in +# your scripts is simple. Here are directions: +############################################### +# 0) make sure Expect is linked into your Tk-based program (or vice versa) +# 1) modify the variables/procedures below these comments appropriately +# 2) source this file +# 3) pack the text widget ($term) if you have so configured it (see +# "term_alone" below). As distributed, it packs into . automatically. + +############################################# +# Variables that must be initialized before using this: +############################################# +set rows 24 ;# number of rows in term +set rowsDumb $rows ;# number of rows in term when in dumb mode - this can + ;# increase during runtime +set cols 80 ;# number of columns in term +set term .t ;# name of text widget used by term +set sb .sb ;# name of scrollbar used by term in dumb mode +set term_alone 1 ;# if 1, directly pack term into . + ;# else you must pack +set termcap 1 ;# if your applications use termcap +set terminfo 1 ;# if your applications use terminfo + ;# (you can use both, but note that + ;# starting terminfo is slow) +set term_shell $env(SHELL) ;# program to run in term + +############################################# +# Readable variables of interest +############################################# +# cur_row ;# current row where insert marker is +# cur_col ;# current col where insert marker is +# term_spawn_id ;# spawn id of term + +############################################# +# Procs you may want to initialize before using this: +############################################# + +# term_exit is called if the spawned process exits +proc term_exit {} { + exit +} + +# term_chars_changed is called after every change to the displayed chars +# You can use if you want matches to occur in the background (a la bind) +# If you want to test synchronously, then just do so - you don't need to +# redefine this procedure. +proc term_chars_changed {} { +} + +# term_cursor_changed is called after the cursor is moved +proc term_cursor_changed {} { +} + +# Example tests you can make +# +# Test if cursor is at some specific location +# if {$cur_row == 1 && $cur_col == 0} ... +# +# Test if "foo" exists anywhere in line 4 +# if {[string match *foo* [$term get 4.0 4.end]]} +# +# Test if "foo" exists at line 4 col 7 +# if {[string match foo* [$term get 4.7 4.end]]} +# +# Test if a specific character at row 4 col 5 is in standout +# if {-1 != [lsearch [$term tag names 4.5] standout]} ... +# +# Return contents of screen +# $term get 1.0 end +# +# Return indices of first string on lines 4 to 6 that is in standout mode +# $term tag nextrange standout 4.0 6.end +# +# Replace all occurrences of "foo" with "bar" on screen +# for {set i 1} {$i<=$rows} {incr i} { +# regsub -all "foo" [$term get $i.0 $i.end] "bar" x +# $term delete $i.0 $i.end +# $term insert $i.0 $x +# } + +############################################# +# End of things of interest +############################################# + +# Terminal definitions are provided in both termcap and terminfo +# styles because we cannot be sure which a system might have. The +# definitions generally follow that of xterm which in turn follows +# that of vt100. This is useful for the most common archaic software +# which has vt100 definitions hardcoded. + +unset env(DISPLAY) +set env(LINES) $rows +set env(COLUMNS) $cols + +if {$termcap} { + set env(TERM) "tt" + set env(TERMCAP) {tt: + :ks=\E[?1h\E: + :ke=\E[?1l\E>: + :cm=\E[%d;%dH: + :up=\E[A: + :nd=\E[C: + :cl=\E[H\E[J: + :ce=\E[K: + :do=^J: + :so=\E[7m: + :se=\E[m: + :k1=\EOP: + :k2=\EOQ: + :k3=\EOR: + :k4=\EOS: + :k5=\EOT: + :k6=\EOU: + :k7=\EOV: + :k8=\EOW: + :k9=\EOX: + } +} + +if {$terminfo} { + # ncurses ignores 2-char term names so use a longer name here + set env(TERM) "tkterm" + set env(TERMINFO) /tmp + set ttsrc "/tmp/tt.src" + set file [open $ttsrc w] + + puts $file {tkterm|Don Libes' tk text widget terminal emulator, + smkx=\E[?1h\E, + rmkx=\E[?1l\E>, + cup=\E[%p1%d;%p2%dH, + cuu1=\E[A, + cuf1=\E[C, + clear=\E[H\E[J, + el=\E[K, + ind=\n, + cr=\r, + smso=\E[7m, + rmso=\E[m, + kf1=\EOP, + kf2=\EOQ, + kf3=\EOR, + kf4=\EOS, + kf5=\EOT, + kf6=\EOU, + kf7=\EOV, + kf8=\EOW, + kf9=\EOX, + } + close $file + + set oldpath $env(PATH) + set env(PATH) "$env(PATH):/usr/5bin:/usr/lib/terminfo" + if {1==[catch {exec tic $ttsrc} msg]} { + puts "WARNING: tic failed - if you don't have terminfo support on" + puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"." + puts "Here is the original error from running tic:" + puts $msg + } + set env(PATH) $oldpath + + exec rm $ttsrc +} + +set term_standout 0 ;# if in standout mode or not + +log_user 0 + +# start a shell and text widget for its output +set stty_init "-tabs" +eval spawn $term_shell +stty rows $rows columns $cols < $spawn_out(slave,name) +set term_spawn_id $spawn_id + +# this shouldn't be needed if Ousterhout fixes text bug +text $term \ + -yscroll "$sb set" \ + -relief sunken -bd 1 -width $cols -height $rows -wrap none -setgrid 1 + +# define scrollbars +scrollbar .sb -command "$term yview" + +proc graphicsGet {} {return $::graphics(mode)} +proc graphicsSet {mode} { + set ::graphics(mode) $mode + + if {$mode} { + # in graphics mode, no scroll bars + grid forget $::sb + } else { + grid $::sb -column 0 -row 0 -sticky ns + } +} + +if {$term_alone} { + grid $term -column 1 -row 0 -sticky nsew + # let text box only expand + grid rowconfigure . 0 -weight 1 + grid columnconfigure . 1 -weight 1 +} + +$term tag configure standout -background black -foreground white + +proc term_clear {} { + global term + + $term delete 1.0 end + term_init +} + +# pine is the only program I know that requires clear_to_eol, sigh +proc term_clear_to_eol {} { + global cols cur_col cur_row + + # save current col/row + set col $cur_col + set row $cur_row + + set space_rem_on_line [expr $cols - $cur_col] + term_insert [format %[set space_rem_on_line]s ""] + + # restore current col/row + set cur_col $col + set cur_row $row +} + +proc term_init {} { + global rows cols cur_row cur_col term + + # initialize it with blanks to make insertions later more easily + set blankline [format %*s $cols ""]\n + for {set i 1} {$i <= $rows} {incr i} { + $term insert $i.0 $blankline + } + + set cur_row 1 + set cur_col 0 + + $term mark set insert $cur_row.$cur_col + + set ::rowsDumb $rows +} + +# NOT YET COMPLETE! +proc term_resize {rowsNew colsNew} { + global rows cols term + + foreach {set r 1} {$r < $rows} {incr r} { + if {$colsNew > $cols} { + # add columns + $term insert $i.$column $blanks + } elseif {$colsNew < $cols} { + # remove columns + # ? + } + } + + if {$rowsNew > $rows} { + # add rows + } elseis {$rowsNew < $rows} { + # remove rows + } +} + +proc term_down {} { + global cur_row rows cols term + + if {$cur_row < $rows} { + incr cur_row + } else { + if {[graphicsGet]} { + # in graphics mode + + # already at last line of term, so scroll screen up + $term delete 1.0 "1.end + 1 chars" + + # recreate line at end + $term insert end [format %*s $cols ""]\n + } else { + # in dumb mode + incr cur_row + + if {$cur_row > $::rowsDumb} { + set ::rowsDumb $cur_row + } + + $term insert $cur_row.0 [format %*s $cols ""]\n + $term see $cur_row.0 + } + } +} + +proc term_up {} { + global cur_row rows cols term + + set cur_rowOld $cur_row + incr cur_row -1 + + if {($cur_rowOld > $rows) && ($cur_rowOld == $::rowsDumb)} { + if {[regexp "^ *$" [$::term get $cur_rowOld.0 $cur_rowOld.end]]} { + # delete line + $::term delete $cur_rowOld.0 end + } + incr ::rowsDumb -1 + } +} + +proc term_insert {s} { + global cols cur_col cur_row + global term term_standout + + set chars_rem_to_write [string length $s] + set space_rem_on_line [expr $cols - $cur_col] + + if {$term_standout} { + set tag_action "add" + } else { + set tag_action "remove" + } + + ################## + # write first line + ################## + + if {$chars_rem_to_write > $space_rem_on_line} { + set chars_to_write $space_rem_on_line + set newline 1 + } else { + set chars_to_write $chars_rem_to_write + set newline 0 + } + + $term delete $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write] + $term insert $cur_row.$cur_col [ + string range $s 0 [expr $space_rem_on_line-1] + ] + + $term tag $tag_action standout $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write] + + # discard first line already written + incr chars_rem_to_write -$chars_to_write + set s [string range $s $chars_to_write end] + + # update cur_col + incr cur_col $chars_to_write + # update cur_row + if {$newline} { + term_down + } + + ################## + # write full lines + ################## + while {$chars_rem_to_write >= $cols} { + $term delete $cur_row.0 $cur_row.end + $term insert $cur_row.0 [string range $s 0 [expr $cols-1]] + $term tag $tag_action standout $cur_row.0 $cur_row.end + + # discard line from buffer + set s [string range $s $cols end] + incr chars_rem_to_write -$cols + + set cur_col 0 + term_down + } + + ################# + # write last line + ################# + + if {$chars_rem_to_write} { + $term delete $cur_row.0 $cur_row.$chars_rem_to_write + $term insert $cur_row.0 $s + $term tag $tag_action standout $cur_row.0 $cur_row.$chars_rem_to_write + set cur_col $chars_rem_to_write + } + + term_chars_changed +} + +proc term_update_cursor {} { + global cur_row cur_col term + + $term mark set insert $cur_row.$cur_col + + term_cursor_changed +} + +term_init +graphicsSet 0 + +set flush 0 +proc screen_flush {} { + global flush + incr flush + if {$flush == 24} { + update idletasks + set flush 0 + } +} + +expect_background { + -i $term_spawn_id + -re "^\[^\x01-\x1f]+" { + # Text + term_insert $expect_out(0,string) + term_update_cursor + } "^\r" { + # (cr,) Go to beginning of line + screen_flush + set cur_col 0 + term_update_cursor + } "^\n" { + # (ind,do) Move cursor down one line + term_down + term_update_cursor + } "^\b" { + # Backspace nondestructively + incr cur_col -1 + term_update_cursor + } "^\a" { + bell + } "^\t" { + # Tab, shouldn't happen + send_error "got a tab!?" + } eof { + term_exit + } "^\x1b\\\[A" { + # (cuu1,up) Move cursor up one line + term_up + term_update_cursor + } "^\x1b\\\[C" { + # (cuf1,nd) Non-destructive space + incr cur_col + term_update_cursor + } -re "^\x1b\\\[(\[0-9]*);(\[0-9]*)H" { + # (cup,cm) Move to row y col x + set cur_row [expr $expect_out(1,string)+1] + set cur_col $expect_out(2,string) + term_update_cursor + } "^\x1b\\\[H\x1b\\\[J" { + # (clear,cl) Clear screen + term_clear + term_update_cursor + } "^\x1b\\\[K" { + # (el,ce) Clear to end of line + term_clear_to_eol + term_update_cursor + } "^\x1b\\\[7m" { + # (smso,so) Begin standout mode + set term_standout 1 + } "^\x1b\\\[m" { + # (rmso,se) End standout mode + set term_standout 0 + } "^\x1b\\\[?1h\x1b" { + # (smkx,ks) start keyboard-transmit mode + # terminfo invokes these when going in/out of graphics mode + graphicsSet 1 + } "^\x1b\\\[?1l\x1b>" { + # (rmkx,ke) end keyboard-transmit mode + graphicsSet 0 + } +} + +# New and incomplete! +bind $term <Configure> { + scan [wm geometry .] "%dx%dx" rows cols + stty rows $rows columns $cols < $spawn_out(slave,name) + + # when this is working, uncomment ... + # term_resize $rows $cols +} + +bind $term <Any-Enter> { + focus %W +} + +bind $term <Meta-KeyPress> { + if {"%A" != ""} { + exp_send -i $term_spawn_id "\033%A" + } +} + +bind $term <KeyPress> { + exp_send -i $term_spawn_id -- %A + break +} + +bind $term <Control-space> {exp_send -null} +bind $term <Control-at> {exp_send -null} + +bind $term <F1> {exp_send -i $term_spawn_id "\033OP"} +bind $term <F2> {exp_send -i $term_spawn_id "\033OQ"} +bind $term <F3> {exp_send -i $term_spawn_id "\033OR"} +bind $term <F4> {exp_send -i $term_spawn_id "\033OS"} +bind $term <F5> {exp_send -i $term_spawn_id "\033OT"} +bind $term <F6> {exp_send -i $term_spawn_id "\033OU"} +bind $term <F7> {exp_send -i $term_spawn_id "\033OV"} +bind $term <F8> {exp_send -i $term_spawn_id "\033OW"} +bind $term <F9> {exp_send -i $term_spawn_id "\033OX"} diff --git a/example/unbuffer b/example/unbuffer new file mode 100755 index 0000000..ad5db7b --- /dev/null +++ b/example/unbuffer @@ -0,0 +1,31 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# -*- tcl -*- +# Description: unbuffer stdout of a program +# Author: Don Libes, NIST + +if {[string compare [lindex $argv 0] "-p"] == 0} { + # pipeline + set stty_init "-echo" + eval [list spawn -noecho] [lrange $argv 1 end] + close_on_eof -i $user_spawn_id 0 + interact { + eof { + # flush remaining output from child + expect -timeout 1 -re .+ + return + } + } +} else { + set stty_init "-opost" + set timeout -1 + eval [list spawn -noecho] $argv + expect + exit [lindex [wait] 3] +} diff --git a/example/unbuffer.c b/example/unbuffer.c new file mode 100644 index 0000000..d494bf8 --- /dev/null +++ b/example/unbuffer.c @@ -0,0 +1,13 @@ +/* unbuffer.c */ + +#include <stdio.h> +#include "expect.h" + +main(argc,argv) +int argc; +char *argv[]; +{ + argv++; + exp_timeout = -1; + exp_expectl(exp_spawnv(*argv,argv),exp_end); +} diff --git a/example/unbuffer.man b/example/unbuffer.man new file mode 100644 index 0000000..9e514cf --- /dev/null +++ b/example/unbuffer.man @@ -0,0 +1,82 @@ +.TH UNBUFFER 1 "1 June 1994" +.SH NAME +unbuffer \- unbuffer output +.SH SYNOPSIS +.B unbuffer +.I program +[ +.I args +] +.SH INTRODUCTION +.B unbuffer +disables the output buffering that occurs when program output +is redirected from non-interactive programs. +For example, suppose you are watching the output from a fifo by running it +through od and then more. +.nf + + od -c /tmp/fifo | more + +.fi +You will not see anything until a full page +of output has been produced. + +You can disable this automatic buffering as follows: + +.nf + + unbuffer od -c /tmp/fifo | more + +.fi +Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations. To use unbuffer in a pipeline, use the -p flag. +Example: +.nf + + process1 | unbuffer -p process2 | process3 +.fi +.SH CAVEATS + +unbuffer -p may appear to work incorrectly if a process feeding input +to unbuffer exits. Consider: +.nf + process1 | unbuffer -p process2 | process3 + +.fi +If process1 exits, process2 may not yet have finished. It is +impossible for unbuffer to know long to wait for process2 and process2 +may not ever finish, for example, if it is a filter. For expediency, +unbuffer simply exits when it encounters an EOF from either its input +or process2. + +In order to have a version of unbuffer that worked in all situations, +an oracle would be necessary. If you want an application-specific +solution, workarounds or hand-coded Expect may be more suitable. For +example, the following example shows how to allow grep to finish +processing when the cat before it finishes first. Using cat to feed +grep would never require unbuffer in real life. It is merely a +placeholder for some imaginary process that may or may not finish. +Similarly, the final cat at the end of the pipeline is also a +placeholder for another process. + +.nf + +$ cat /tmp/abcdef.log | grep abc | cat +abcdef +xxxabc defxxx +$ cat /tmp/abcdef.log | unbuffer grep abc | cat +$ (cat /tmp/abcdef.log ; sleep 1) | unbuffer grep abc | cat +abcdef +xxxabc defxxx +$ +.fi +.SH BUGS + +The man page is longer than the program. + +.SH SEE ALSO +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/virterm b/example/virterm new file mode 100755 index 0000000..bab254b --- /dev/null +++ b/example/virterm @@ -0,0 +1,639 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + +# Name: virterm - terminal emulator using Expect, v1.0, December, 1994 +# Author: Adrian Mariano <adrian@cam.cornell.edu> +# +# Derived from Done Libes' tkterm + +# This is a program for interacting with applications that use terminal +# control sequences. It is a subset of Don Libes' tkterm emulator +# with a compatible interface so that programs can be written to work +# under both. +# +# Internally, it uses arrays instead of the Tk widget. Nonetheless, this +# code is not as fast as it should be. I need an Expect profiler to go +# any further. +# +# standout mode is not supported like it is in tkterm. +# the only terminal widget operation that is supported for the user +# is the "get" operation. +############################################### +# Variables that must be initialized before using this: +############################################# +set rows 24 ;# number of rows in term +set cols 80 ;# number of columns in term +set term myterm ;# name of text widget used by term +set termcap 1 ;# if your applications use termcap +set terminfo 0 ;# if your applications use terminfo + ;# (you can use both, but note that + ;# starting terminfo is slow) +set term_shell $env(SHELL) ;# program to run in term + +############################################# +# Readable variables of interest +############################################# +# cur_row ;# current row where insert marker is +# cur_col ;# current col where insert marker is +# term_spawn_id ;# spawn id of term + +############################################# +# Procs you may want to initialize before using this: +############################################# + +# term_exit is called if the associated proc exits +proc term_exit {} { + exit +} + +# term_chars_changed is called after every change to the displayed chars +# You can use if you want matches to occur in the background (a la bind) +# If you want to test synchronously, then just do so - you don't need to +# redefine this procedure. +proc term_chars_changed {} { +} + +# term_cursor_changed is called after the cursor is moved +proc term_cursor_changed {} { +} + +# Example tests you can make +# +# Test if cursor is at some specific location +# if {$cur_row == 1 && $cur_col == 0} ... +# +# Test if "foo" exists anywhere in line 4 +# if {[string match *foo* [$term get 4.0 4.end]]} +# +# Test if "foo" exists at line 4 col 7 +# if {[string match foo* [$term get 4.7 4.end]]} +# +# Return contents of screen +# $term get 1.0 end + +############################################# +# End of things of interest +############################################# + +set blankline "" +set env(LINES) $rows +set env(COLUMNS) $cols + +set env(TERM) "tt" +if {$termcap} { + set env(TERMCAP) {tt: + :cm=\E[%d;%dH: + :up=\E[A: + :cl=\E[H\E[J: + :do=^J: + :so=\E[7m: + :se=\E[m: + :nd=\E[C: + } +} + +if {$terminfo} { + set env(TERMINFO) /tmp + set ttsrc "/tmp/tt.src" + set file [open $ttsrc w] + + puts $file {tt|textterm|Don Libes' tk text widget terminal emulator, + cup=\E[%p1%d;%p2%dH, + cuu1=\E[A, + cuf1=\E[C, + clear=\E[H\E[J, + ind=\n, + cr=\r, + smso=\E[7m, + rmso=\E[m, + } + close $file + + set oldpath $env(PATH) + set env(PATH) "/usr/5bin:/usr/lib/terminfo" + if {1==[catch {exec tic $ttsrc} msg]} { + puts "WARNING: tic failed - if you don't have terminfo support on" + puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"." + puts "Here is the original error from running tic:" + puts $msg + } + set env(PATH) $oldpath + + exec rm $ttsrc +} + +log_user 0 + +# start a shell and text widget for its output +set stty_init "-tabs" +eval spawn $term_shell +stty rows $rows columns $cols < $spawn_out(slave,name) +set term_spawn_id $spawn_id + +proc term_replace {reprow repcol text} { + global termdata + set middle $termdata($reprow) + set termdata($reprow) \ + [string range $middle 0 [expr $repcol-1]]$text[string \ + range $middle [expr $repcol+[string length $text]] end] +} + + +proc parseloc {input row col} { + upvar $row r $col c + global rows + switch -glob -- $input \ + end { set r $rows; set c end } \ + *.* { regexp (.*)\\.(.*) $input dummy r c + if {$r == "end"} { set r $rows } + } +} + +proc myterm {command first second args} { + global termdata + if {[string compare get $command]} { + send_error "Unknown terminal command: $command\r" + } else { + parseloc $first startrow startcol + parseloc $second endrow endcol + if {$endcol != "end"} {incr endcol -1} + if {$startrow == $endrow} { + set data [string range $termdata($startrow) $startcol $endcol] + } else { + set data [string range $termdata($startrow) $startcol end] + for {set i [expr $startrow + 1]} {$i < $endrow} {incr i} { + append data $termdata($i) + } + append data [string range $termdata($endrow) 0 $endcol] + } + return $data + } +} + + +proc scrollup {} { + global termdata blankline + for {set i 1} {$i < $rows} {incr i} { + set termdata($i) $termdata([expr $i+1]) + } + set termdata($rows) $blankline +} + + +proc term_init {} { + global rows cols cur_row cur_col term termdata blankline + + # initialize it with blanks to make insertions later more easily + set blankline [format %*s $cols ""]\n + for {set i 1} {$i <= $rows} {incr i} { + set termdata($i) "$blankline" + } + + set cur_row 1 + set cur_col 0 +} + + +proc term_down {} { + global cur_row rows cols term + + if {$cur_row < $rows} { + incr cur_row + } else { + scrollup + } +} + + +proc term_insert {s} { + global cols cur_col cur_row term + + set chars_rem_to_write [string length $s] + set space_rem_on_line [expr $cols - $cur_col] + + ################## + # write first line + ################## + + if {$chars_rem_to_write <= $space_rem_on_line} { + term_replace $cur_row $cur_col \ + [string range $s 0 [expr $space_rem_on_line-1]] + incr cur_col $chars_rem_to_write + term_chars_changed + return + } + + set chars_to_write $space_rem_on_line + set newline 1 + + term_replace $cur_row $cur_col\ + [string range $s 0 [expr $space_rem_on_line-1]] + + # discard first line already written + incr chars_rem_to_write -$chars_to_write + set s [string range $s $chars_to_write end] + + # update cur_col + incr cur_col $chars_to_write + # update cur_row + if {$newline} { + term_down + } + + ################## + # write full lines + ################## + while {$chars_rem_to_write >= $cols} { + term_replace $cur_row 0 [string range $s 0 [expr $cols-1]] + + # discard line from buffer + set s [string range $s $cols end] + incr chars_rem_to_write -$cols + + set cur_col 0 + term_down + } + + ################# + # write last line + ################# + + if {$chars_rem_to_write} { + term_replace $cur_row 0 $s + set cur_col $chars_rem_to_write + } + + term_chars_changed +} + +term_init + +expect_before { + -i $term_spawn_id + -re "^\[^\x01-\x1f]+" { + # Text + term_insert $expect_out(0,string) + term_cursor_changed + } "^\r" { + # (cr,) Go to to beginning of line + set cur_col 0 + term_cursor_changed + } "^\n" { + # (ind,do) Move cursor down one line + term_down + term_cursor_changed + } "^\b" { + # Backspace nondestructively + incr cur_col -1 + term_cursor_changed + } "^\a" { + # Bell, pass back to user + send_user "\a" + } "^\t" { + # Tab, shouldn't happen + send_error "got a tab!?" + } eof { + term_exit + } "^\x1b\\\[A" { + # (cuu1,up) Move cursor up one line + incr cur_row -1 + term_cursor_changed + } "^\x1b\\\[C" { + # (cuf1,nd) Nondestructive space + incr cur_col + term_cursor_changed + } -re "^\x1b\\\[(\[0-9]*);(\[0-9]*)H" { + # (cup,cm) Move to row y col x + set cur_row [expr $expect_out(1,string)+1] + set cur_col $expect_out(2,string) + term_cursor_changed + } "^\x1b\\\[H\x1b\\\[J" { + # (clear,cl) Clear screen + term_init + term_cursor_changed + } "^\x1b\\\[7m" { # unsupported + # (smso,so) Begin standout mode + # set term_standout 1 + } "^\x1b\\\[m" { # unsupported + # (rmso,se) End standout mode + # set term_standout 0 + } +} + + +proc term_expect {args} { + global cur_row cur_col # used by expect_background actions + + set desired_timeout [ + uplevel { + if {[info exists timeout]} { + set timeout + } else { + uplevel #0 { + if {[info exists timeout]} { + set timeout + } else { + expr 10 + } + } + } + } + ] + + set timeout $desired_timeout + + set timeout_act {} + + set argc [llength $args] + if {$argc%2 == 1} { + lappend args {} + incr argc + } + + for {set i 0} {$i<$argc} {incr i 2} { + set act_index [expr $i+1] + if {[string compare timeout [lindex $args $i]] == 0} { + set timeout_act [lindex $args $act_index] + set args [lreplace $args $i $act_index] + incr argc -2 + break + } + } + + set got_timeout 0 + + set start_time [timestamp] + + while {![info exists act]} { + expect timeout {set got_timeout 1} + set timeout [expr $desired_timeout - [timestamp] + $start_time] + if {! $got_timeout} \ + { + for {set i 0} {$i<$argc} {incr i 2} { + if {[uplevel [lindex $args $i]]} { + set act [lindex $args [incr i]] + break + } + } + } else { set act $timeout_act } + + if {![info exists act]} { + + } + } + + set code [catch {uplevel $act} string] + if {$code > 4} {return -code $code $string} + if {$code == 4} {return -code continue} + if {$code == 3} {return -code break} + if {$code == 2} {return -code return} + if {$code == 1} {return -code error -errorinfo $errorInfo \ + -errorcode $errorCode $string} + return $string +} + + +# ======= end of terminal emulator ======== + +# The following is a program to interact with the Cornell Library catalog + + +proc waitfornext {} { + global cur_row cur_col term + term_expect {expr {$cur_col==15 && $cur_row == 24 && + " NEXT COMMAND: " == [$term get 24.0 24.16]}} {} +} + +proc sendcommand {command} { + global cur_col + exp_send $command + term_expect {expr {$cur_col == 79}} {} +} + +proc removespaces {intext} { + regsub -all " *\n" $intext \n intext + regsub "\n+$" $intext \n intext + return $intext +} + +proc output {text} { + exp_send_user $text +} + + + +proc connect {} { + global term + term_expect {regexp {.*[>%]} [$term get 1.0 3.end]} + exp_send "tn3270 notis.library.cornell.edu\r" + term_expect {regexp "desk" [$term get 19.0 19.end]} { + exp_send "\r" + } + waitfornext + exp_send_error "connected.\n\n" +} + + +proc dosearch {search} { + global term + exp_send_error "Searching for '$search'..." + if {[string match ?=* "$search"]} {set typ ""} else {set typ "k="} + sendcommand "$typ$search\r" + waitfornext + set countstr [$term get 2.17 2.35] + if {![regsub { Entries Found *} $countstr "" number]} { + set number 1 + exp_send_error "one entry found.\n\n" + return 1 + } + if {$number == 0} { + exp_send_error "no matches.\n\n" + return 0 + } + exp_send_error "$number entries found.\n" + if {$number > 250} { + exp_send_error "(only the first 250 can be displayed)\n" + } + exp_send_error "\n" + return $number +} + + +proc getshort {count} { + global term + output [removespaces [$term get 5.0 19.0]] + while {[regexp "CONTINUED on next page" [$term get 19.0 19.end]]} { + sendcommand "for\r" + waitfornext + output [removespaces [$term get 5.0 19.0]] + } +} + +proc getonecitation {} { + global term + output [removespaces [$term get 4.0 19.0]] + while {[regexp "FORward page" [$term get 20.0 20.end]]} { + sendcommand "for\r" + waitfornext + output [removespaces [$term get 5.0 19.0]] + } +} + + +proc getcitlist {} { + global term + getonecitation + set citcount 1 + while {[regexp "NEXt record" [$term get 20.0 21.end]]} { + sendcommand "nex\r" + waitfornext + getonecitation + incr citcount + if {$citcount % 10 == 0} {exp_send_error "$citcount.."} + } +} + +proc getlong {count} { + if {$count != 1} { + sendcommand "1\r" + waitfornext + } + sendcommand "lon\r" + waitfornext + getcitlist +} + +proc getmed {count} { + if {$count != 1} { + sendcommand "1\r" + waitfornext + } + sendcommand "bri\r" + waitfornext + getcitlist +} + +################################################################# +# +set help { +libsearch version 1.0 by Adrian Mariano (adrian@cam.cornell.edu) + +Invocation: libsearch [options] search text + + -i : interactive + -s : short listing + -l : long listing + -o file : output file (default stdout) + -h : print out list of options and version number + -H : print terse keyword search help + +The search will be a keyword search. +Example: libsearch -i sound and arabic + +} + +################################################################# + +proc searchhelp {} { + send_error { +? truncation wildcard default operator is AND + +AND - both words appear in record +OR - one of the words appears +NOT - first word appears, second words does not +ADJ - words are adjacent +SAME- words appear in the same field (any order) + +.su. - subject b.fmt. - books eng.lng. - English +.ti. - title m.fmt. - music spa.lng. - Spanish +.au. - author s.fmt. - serials fre.lng. - French + +.dt. or .dt1. -- limits to a specific publication year. E.g., 1990.dt. + +} +} + +proc promptuser {prompt} { + exp_send_error "$prompt" + expect_user -re "(.*)\n" + return "$expect_out(1,string)" +} + + +set searchtype 1 +set outfile "" +set search "" +set interactive 0 + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -glob -- $flag \ + "-i" { set interactive 1; set argv [lrange $argv 1 end]} \ + "-s" { set searchtype 0; set argv [lrange $argv 1 end] } \ + "-l" { set searchtype 2; set argv [lrange $argv 1 end] } \ + "-o" { set outfile [lindex $argv 1]; set argv [lrange $argv 2 end] } \ + "-H" { searchhelp; exit } \ + "-h" { send_error "$help"; exit } \ + "-*" { send_error "\nUnknown option: $flag\n$help";exit }\ + default { set search [join $argv]; set argv {};} +} +if { "$search" == "" } { + send_error "No search specified\n$help" + exit +} + +exp_send_error "Connecting to the library..." + +set timeout 200 + +trap { log_user 1;exp_send "\003"; + expect_before + expect tn3270 {exp_send "quit\r"} + expect "Connection closed." {exp_send "exit\r"} + expect eof ; send_error "\n"; + exit} SIGINT + + +connect + +set result [dosearch $search] + +if {$interactive} { + set quit 0 + while {!$quit} { + if {!$result} { + switch "[promptuser {(h)elp (n)ewsearch (q)uit? }]" { + n { } + h { searchhelp } + q { set quit 1} + } + } else { + switch "[promptuser {(s)hort (m)ed (l)ong (h)elp (n)ewsearch (q)uit? }]" { + s { getshort $result; ;} + l { getlong $result; ;} + m { getmed $result; ; } + n { research; } + h { searchhelp } + q { set quit 1; } + } + } + } +} else { + if {$result} { + switch $searchtype { + 0 { getshort $result} + 1 { getmed $result } + 2 { getlong $result } + } + } +} + + + + + + diff --git a/example/vrfy b/example/vrfy new file mode 100755 index 0000000..49c1b18 --- /dev/null +++ b/example/vrfy @@ -0,0 +1,27 @@ +#!/depot/path/expect -f + + +# separate address into user and host +regexp (.*)@(.*) $argv ignore user host + +log_user 0 +set timeout -1 + +# host might be an mx record, convert to a real host via nslookup +spawn nslookup +expect "> " +send "set query=mx\r" +expect "> " +send "$host\r" +expect { + "No mail exchanger" {} + -re "mail exchanger = (\[^\r]*)" { + set host $expect_out(1,string) + } +} + +spawn telnet $host smtp +expect "220*\r\n" +send "vrfy $user\r" +expect "250" {send_user "GOOD\n"} \ + "550" {send_user "BAD\n"} diff --git a/example/weather b/example/weather new file mode 100755 index 0000000..4bd0e1b --- /dev/null +++ b/example/weather @@ -0,0 +1,81 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# weather - Expect script to get the weather (courtesy University of Michigan) +# Don Libes +# Version 1.10 + +# local weather is retrieved if no argument +# argument is the National Weather Service designation for an area +# I.e., WBC = Washington DC (oh yeah, that's obvious) + +# Notes from Larry Virden <lvirden@yahoo.com> about the new host, +# rainmaker.wunderground.com: "[the] new site requires the +# machine doing the request be located in reverse dns lookup +# or it refuses to provide data." This appears to be a blind error +# condition on the part of rainmaker. + +exp_version -exit 5.0 + +if {$argc>0} {set code $argv} else {set code "WBC"} + +proc timedout {} { + send_user "Weather server timed out. Try again later when weather server is not so busy.\n" + exit 1 +} + +set timeout 60 + +set env(TERM) vt100 ;# actual value doesn't matter, just has to be set + +spawn telnet rainmaker.wunderground.com 3000 +while {1} { + expect timeout { + send_user "failed to contact weather server\n" + exit + } "Press Return to continue*" { + # this prompt used sometimes, eg, upon opening connection + send "\r" + } "Press Return for menu*" { + # this prompt used sometimes, eg, upon opening connection + send "\r" + } "M to display main menu*" { + # sometimes ask this if there is a weather watch in effect + send "M\r" + } "Change scrolling to screen*Selection:" { + break + } eof { + send_user "failed to telnet to weather server\n" + exit + } +} +send "C\r" +expect timeout timedout "Selection:" +send "4\r" +expect timeout timedout "Selection:" +send "1\r" +expect timeout timedout "Selection:" +send "1\r" +expect timeout timedout "city code:" +send "$code\r" +expect $code ;# discard this + +while {1} { + expect timeout { + timedout + } "Press Return to continue*:*" { + send "\r" + } "Press Return to display statement, M for menu:*" { + send "\r" + } -re "(.*)CITY FORECAST MENU.*Selection:" { + break + } +} + +send "X\r" +expect diff --git a/example/xkibitz b/example/xkibitz new file mode 100755 index 0000000..b61a22f --- /dev/null +++ b/example/xkibitz @@ -0,0 +1,219 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# share an xterm with other users +# See xkibitz(1) man page for complete info. +# Compare with kibitz. +# Author: Don Libes, NIST +# Version: 1.2 + +proc help {} { + puts "Commands Meaning" + puts "-------- -------" + puts "return return to program" + puts "= list" + puts "+ <display> add" + puts "- <tag> drop" + puts "where <display> is an X display name such as nist.gov or nist.gov:0.0" + puts "and <tag> is a tag from the = command." + puts "+ and - require whitespace before argument." + puts {return command must be spelled out ("r", "e", "t", ...).} +} + +proc prompt1 {} { + return "xkibitz> " +} + +proc h {} help +proc ? {} help + +# disable history processing - there seems to be some incestuous relationship +# between history and unknown in Tcl 8.0 +proc history {args} {} +proc unknown {args} { + puts "$args: invalid command" + help +} + +set tag2pid(0) [pid] +set pid2tty([pid]) "/dev/tty" +if {[info exists env(DISPLAY)]} { + set pid2display([pid]) $env(DISPLAY) +} else { + set pid2display([pid]) "" +} + +# small int allowing user to more easily identify display +# maxtag always points at highest in use +set maxtag 0 + +proc + {display} { + global ids pid2display pid2tag tag2pid maxtag pid2sid + global pid2tty env + + if {![string match *:* $display]} { + append display :0.0 + } + + if {![info exists env(XKIBITZ_XTERM_ARGS)]} { + set env(XKIBITZ_XTERM_ARGS) "" + } + + set dummy1 [open /dev/null] + set dummy2 [open /dev/null] + spawn -pty -noecho + close $dummy1 + close $dummy2 + + stty raw -echo < $spawn_out(slave,name) + # Linux needs additional stty, sounds like a bug in its stty to me. + # raw should imply this stuff, no? + stty -icrnl -icanon < $spawn_out(slave,name) + + regexp ".*(.)(.)" $spawn_out(slave,name) dummy c1 c2 + if {[string compare $c1 "/"] == 0} { + # On Pyramid and AIX, ttynames such as /dev/pts/1 + # requre suffix to be padded with a 0 + set c1 0 + } + + set pid [eval exec xterm \ + -display $display \ + -geometry [stty columns]x[stty rows] \ + -S$c1$c2$spawn_out(slave,fd) \ + $env(XKIBITZ_XTERM_ARGS) &] + close -slave + + # xterm first sends back window id, discard + log_user 0 + expect { + eof {wait;return} + \n + } + log_user 1 + + lappend ids $spawn_id + set pid2display($pid) $display + incr maxtag + set tag2pid($maxtag) $pid + set pid2tag($pid) $maxtag + set pid2sid($pid) $spawn_id + set pid2tty($pid) $spawn_out(slave,name) + return +} + +proc = {} { + global pid2display tag2pid pid2tty + + puts "Tag Size Display" + foreach tag [lsort -integer [array names tag2pid]] { + set pid $tag2pid($tag) + set tty $pid2tty($pid) + + puts [format "%3d [stty columns < $tty]x[stty rows < $tty] $pid2display($pid)" $tag] + } +} + +proc - {tag} { + global tag2pid pid2tag pid2display maxtag ids pid2sid + global pid2tty + + if {![info exists tag2pid($tag)]} { + puts "no such tag" + return + } + if {$tag == 0} { + puts "cannot drop self" + return + } + + set pid $tag2pid($tag) + + # close and remove spawn_id from list + set spawn_id $pid2sid($pid) + set index [lsearch $ids $spawn_id] + set ids [lreplace $ids $index $index] + + exec kill -9 $pid + close + wait + + unset tag2pid($tag) + unset pid2tag($pid) + unset pid2display($pid) + unset pid2sid($pid) + unset pid2tty($pid) + + # lower maxtag if possible + while {![info exists tag2pid($maxtag)]} { + incr maxtag -1 + } +} + +rename exit exitReal + +proc exit {} { + global pid2display + + unset pid2display([pid]) ;# avoid killing self + + foreach pid [array names pid2display] { + catch {exec kill -9 $pid} + } + exitReal +} + +trap exit HUP + +trap { + set r [stty rows] + set c [stty columns] + stty rows $r columns $c < $app_tty + foreach pid [array names pid2tty] { + if {$pid == [pid]} continue + stty rows $r columns $c < $pid2tty($pid) + } +} WINCH + +set escape \035 ;# control-right-bracket +set escape_printable "^\]" + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -- $flag \ + "-escape" { + set escape [lindex $argv 1] + set escape_printable $escape + set argv [lrange $argv 2 end] + } "-display" { + + [lindex $argv 1] + set argv [lrange $argv 2 end] + } default { + break + } +} + +if {[llength $argv]>0} { + eval spawn -noecho $argv +} else { + spawn -noecho $env(SHELL) +} +set prog $spawn_id +set app_tty $spawn_out(slave,name) + +puts "Escape sequence is $escape_printable" + +interact { + -input $user_spawn_id -reset $escape { + puts "\nfor help enter: ? or h or help" + interpreter -eof exit + } -output $prog + -input ids -output $prog + -input $prog eof exit -output $user_spawn_id -output ids +} + diff --git a/example/xkibitz.man b/example/xkibitz.man new file mode 100644 index 0000000..c1d7fcc --- /dev/null +++ b/example/xkibitz.man @@ -0,0 +1,170 @@ +.TH XKIBITZ 1 "06 October 1994" +.SH NAME +xkibitz \- allow multiple people to interact in an xterm +.SH SYNOPSIS +.B xkibitz +[ +.I xkibitz-args +] [ +.I program program-args... +] +.br +.SH INTRODUCTION +.B xkibitz +allows users in separate xterms to share one shell (or any program +that runs in an xterm). Uses include: +.RS +.TP 4 +\(bu +A novice user can ask an expert user for help. Using +.BR xkibitz , +the expert can see what the user is doing, and offer advice or +show how to do it right. +.TP +\(bu +By running +.B xkibitz +and then starting a full-screen editor, people may carry out a +conversation, retaining the ability to scroll backwards, +save the entire conversation, or even edit it while in progress. +.TP +\(bu +People can team up on games, document editing, or other cooperative +tasks where each person has strengths and weaknesses that complement one +another. +.TP +\(bu +If you want to have a large number of people do an on-line code +walk-through, you can sit two in front of each workstation, and then +connect them all together while you everyone looks at code together +in the editor. +.SH USAGE +To start +.BR xkibitz , +one user (the master) runs xkibitz with no arguments. + +.B xkibitz +starts a new shell (or another program, if given on the command +line). The user can interact normally with the shell, or +upon entering an escape (described when xkibitz starts) can add +users to the interaction. + +To add users, enter "+ display" where display is the X display name. +If there is no ":X.Y" in the display name, ":0.0" is assumed. +The master user must have permission to access each display. +Each display is assigned +a tag \- a small integer which can be used to reference the display. + +To show the current tags and displays, enter "=". + +To drop a display, enter "- tag" where tag is the display's tag +according to the "=" command. + +To return to the shared shell, enter "return". Then the keystrokes of +all users become the input of the shell. Similarly, all users receive +the output from the shell. + +To terminate +.B xkibitz +it suffices to terminate the shell itself. For example, if any user +types ^D (and the shell accepts this to be EOF), the shell terminates +followed by +.BR xkibitz . + +Normally, all characters are passed uninterpreted. However, in the +escape dialogue the user talks directly to the +.B xkibitz +interpreter. Any +.BR Expect (1) +or +.BR Tcl (3) +commands may also be given. +Also, job control may be used while in the interpreter, to, for example, +suspend or restart +.BR xkibitz . + +Various processes +can produce various effects. For example, you can emulate a multi-way write(1) +session with the command: + + xkibitz sleep 1000000 +.PP +.SH ARGUMENTS +.B xkibitz +understands a few special arguments +which should appear before the +.I program +name (if given). +Each argument should be separated by whitespace. +If the arguments themselves takes arguments, +these should also be separated by whitespace. + +.B \-escape +sets the escape character. The default escape character is ^]. + +.B \-display +adds a display much like the "+" command. Multiple \-display flags +can be given. For example, to start up xkibitz with three additional +displays: + + xkibitz -display mercury -display fox -display dragon:1.0 + +.SH CAVEATS +Due to limitations in both X and UNIX, resize propagation is weak. + +When the master user resizes the xterm, all the other xterms are logically +resized. +Unfortunately, xkibitz cannot force the physical xterm size to correspond +with the logical xterm sizes. + +The other users are free to resize their xterm but their sizes are not +propagated. The master can check the logical sizes with the "=" command. + +Deducing the window size is a non-portable operation. The code is known +to work for recent versions of SunOS, AIX, Unicos, and HPUX. Send back +mods if you add support for anything else. +.SH ENVIRONMENT +The environment variable SHELL is used to determine and start a shell, if no +other program is given on the command line. + +If the environment variable DISPLAY is defined, its value is used for the +display name of the +.B xkibitz +master (the display with tag number 0). Otherwise this name remains empty. + +Additional arguments may be passed to new xterms through +the environment variable XKIBITZ_XTERM_ARGS. +For example, to create xterms +with a scrollbar and a green pointer cursor: +.nf + + XKIBITZ_XTERM_ARGS="-sb -ms green" + export XKIBITZ_XTERM_ARGS + +.fi +(this is for the Bourne shell - use whatever syntax is appropriate for your +favorite shell). Any option can be given that is valid for the +.B xterm +command, with the exception of +.BR -display , +.B -geometry +and +.BI -S +as those are set by +.BR xkibitz . +.SH SEE ALSO +.BR Tcl (3), +.BR libexpect (3) +.BR kibitz (1) +.br +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, +O'Reilly and Associates, January 1995. +.br +.I +"kibitz \- Connecting Multiple Interactive Programs Together", \fRby Don Libes, +Software \- Practice & Experience, John Wiley & Sons, West Sussex, England, +Vol. 23, No. 5, May, 1993. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology diff --git a/example/xpstat b/example/xpstat new file mode 100755 index 0000000..ebbfbcf --- /dev/null +++ b/example/xpstat @@ -0,0 +1,274 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# This script acts as a front-end for xpilot. Run it in the background, +# and it will pop up a window for each server it finds running. After +# you run it, press the "?" button for more info. + +# Store the filename of your xpilot client in the following variable. +set xpilot /usr/local/bin/xpilot + +# Author: Don Libes, NIST, 12/29/92 + +# I never have figured out how to get the alias out of xrdb. For now, just +# read it ourselves out of .Xdefaults - ugh. + +log_user 0 + +set timeout 60 + +proc probe {} { + global max db hosts world + + set timeout -1 + + expect_before eof {wait;return 0} + + expect -re "Server on (.*). Enter command> " { + exp_send "S\r" + set host $expect_out(1,string) + # replace dots in hostnames by underscores + regsub -all . $host _ host + # force lowercase to avoid Tk widget name problems + set host [string tolower $host] + lappend hosts $host + } + expect -re "WORLD\[^:]*: (\[^\r]*)\r" { + set worldtmp $expect_out(1,string) + } + expect -re "AUTHOR\[^:]*: (\[^\r]*)\r" { + set author $expect_out(1,string) + } + set world($host) "$worldtmp by $author" + + # skip over junk to get players + expect { + -re -+ {} + -re "Enter command> " { + set max($host) 0 + display $host + return 1 + } + } + set i 0 + expect { + -re "\\.\\.\\. . (................) (...) *(\[^ ]*) *(\[^\r]*)\r" { + # strip trailing blanks + set alias [string trimright $expect_out(1,string)] + set db($host,$i,alias) $alias + + # strip leading zeros + scan $expect_out(2,string) %d db($host,$i,life) + + set db($host,$i,score) $expect_out(3,string) + + set db($host,name,$alias) $expect_out(4,string) + + incr i + exp_continue + } + -re "Enter command>" + + } + set max($host) $i + display $host + + return 1 +} + +proc resize {w a b} { + # 27 is a guess at a fixed-width sufficiently comfortable for + # the variable-width font. I don't know how to do better. + $w configure -width 27 +} + +proc play {host} { + global xpilot alias + + exec xhost $host + catch {exec $xpilot -name $alias($host) -join $host} status +} + +proc show-help {x y msg} { + catch {destroy .help} + toplevel .help + wm geometry .help +$x+$y + + message .help.text -text $msg + + button .help.ok -text "ok" -command {destroy .help} + pack .help.text + pack .help.ok -fill x +} + +# pop up window with alias +proc show-alias {host seln x y} { + global db + + catch {destroy .alias} + toplevel .alias + wm geometry .alias +$x+$y + wm transient .alias . + + regexp "(.*\[^ ]) +\[-0-9]+ +\[0-9]+$" $seln discard alias + + button .alias.b -text "$db($host,name,$alias)" -command { + destroy .alias + } + .alias.b config -padx 1 -pady 1 -highlightthickness 0 + pack .alias.b +} + +proc help {x y} { + show-help $x $y "xpstat - written by Don Libes, NIST, December 29, 1992 + +This script acts as a front-end for xpilot. Run it in the background, and it will pop up a window for each server it finds running. Press the \"?\" button for this info. + +This program polls each xpilot server once a minute. To make it poll immediately, press \"update\". Press \"play as\" to enter the current game with the alias to the right. Edit to taste. (Your alias is initialized from the value of xpilot.name in ~/.Xdefaults.) + +Double-click the left button on an alias to see the real user name. To remove the user name window, click on it with the left button. + +Pan the world/author text, player list, or your own alias by holding the middle mouse button down and moving the mouse." +} + +# if user presses "update" try to update screen immediately +proc prod {x y} { + global cat_spawn_id updateflag + + if {$updateflag} { + show-help $x $y "I heard you, gimme a break. I'm waiting for the xpilot server to respond..." + } + set updateflag 1 + + exp_send -i $cat_spawn_id "\r" +} + +proc display {host} { + global world db alias max env + + set w .$host + if {![winfo exists $w]} { + + # window does not exist, create it + + toplevel $w -class xpstat + wm minsize $w 1 1 + wm title $w "xpilot@$host" + wm iconname $w "$host xpilot stats" + entry $w.world -state disabled -textvar world($host) + + listbox $w.players -yscroll "resize $w.players" -font 7x13bold + $w.players config -highlightthickness 0 -border 0 + $w.world config -highlightthickness 0 + + bind $w.players <Double-Button-1> { + scan %W ".%%\[^.]" host + show-alias $host [selection get] %X %Y + } + + message $w.msg -text "no players" -aspect 1000 -justify center + + button $w.help -text ? -command { + help 10 20 + } + + button $w.update -text "update" + bind $w.update <1> { + after 1 prod %X %Y + } + + button $w.play -text "play as" + bind $w.play <1> { + scan %W ".%%\[^.]" host + after 1 play $host + } + + entry $w.alias -textvar alias($host) -width 10 + set alias($host) $env(USER) + + bind $w.alias <Return> { + scan %W ".%%\[^.]" host + play $host + } + + $w.play config -padx 1 -pady 1 -highlightthickness 0 + $w.update config -padx 1 -pady 1 -highlightthickness 0 + $w.help config -padx 1 -pady 1 -highlightthickness 0 + $w.alias config -highlightthickness 0 + + pack $w.world -expand 1 -fill x + pack $w.msg + pack $w.help $w.update $w.play -side left + pack $w.alias -side left -expand 1 -fill x + set max($host,was) 0 + } + + if {$max($host)==0} { + # put up "no players" message? + if {$max($host,was)>0} { + pack $w.msg -after $w.world -fill x -side top + pack forget $w.world + } + } else { + # remove "no players" message? + if {$max($host,was)==0} { + pack $w.players -after $w.world -side top + pack forget $w.msg + } + } + + $w.players delete 0 end + + for {set i 0} {$i<$max($host)} {incr i} { + $w.players insert end [format "%-17s %4d %d" \ + $db($host,$i,alias) \ + $db($host,$i,score) \ + $db($host,$i,life) \ + ] + } + + set max($host,was) $max($host) +} + +wm withdraw . +set oldhosts {} + +set updateflag 0 ;# 1 if user pressed "update" button + +# look for desired alias in the .Xdefaults file +set status [catch {exec egrep "xpilot.name:" [glob ~/.Xdefaults]} output] +if {$status==0} { + regexp "xpilot.name:\[ \t]*(\[^\r]*)" $output dummy env(USER) +} + +spawn cat -u; set cat_spawn_id $spawn_id + +while {1} { + global xpilot hosts + + set hosts {} + + eval spawn $xpilot $argv + while {[probe]} {exp_send "N\r"} + catch {expect_before} ;# disable expect_before from inside probe + + # clean up hosts that no longer are running xpilots + + foreach host $oldhosts { + # if host not in hosts + if {-1==[lsearch $hosts $host]} { + destroy .$host + } + } + set oldhosts $hosts + + set updateflag 0 + + # sleep for a little while, subject to click from "update" button + expect -i $cat_spawn_id -re "...." ;# two crlfs +} diff --git a/example/xrlogin b/example/xrlogin new file mode 100644 index 0000000..172da2f --- /dev/null +++ b/example/xrlogin @@ -0,0 +1,22 @@ +#!/depot/path/expect -- +# xrlogin - rlogin but with current DISPLAY +# +# You can extend this idea to save any arbitrary information across rlogin +# Don Libes - Oct 17, 1991. + +if {[llength $argv] != 1} { + puts "usage: xrlogin remotehost" + exit +} + +set prompt "(%|#|\\$) $" ;# default prompt +catch {set prompt $env(EXPECT_PROMPT)} + +set timeout -1 +eval spawn rlogin $argv +expect eof exit -re $prompt +if {[string match "unix:0.0" $env(DISPLAY)]} { + set env(DISPLAY) "[exec hostname].[exec domainname]:0.0\r" +} +send "setenv DISPLAY $env(DISPLAY)\r" +interact diff --git a/expTcl.c b/expTcl.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/expTcl.c diff --git a/expTcl.h b/expTcl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/expTcl.h diff --git a/exp_chan.c b/exp_chan.c new file mode 100644 index 0000000..963337d --- /dev/null +++ b/exp_chan.c @@ -0,0 +1,708 @@ +/* + * exp_chan.c + * + * Channel driver for Expect channels. + * Based on UNIX File channel from TclUnixChan.c + * + */ + +#include <sys/types.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <ctype.h> /* for isspace */ +#include <time.h> /* for time(3) */ + +#include "expect_cf.h" + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <errno.h> + +#include "tclInt.h" /* Internal definitions for Tcl. */ + +#include "tcl.h" + +#include "string.h" + +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" +#include "tcldbg.h" /* Dbg_StdinMode */ + +extern int expSetBlockModeProc _ANSI_ARGS_((int fd, int mode)); +static int ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData, + int mode)); +static int ExpCloseProc _ANSI_ARGS_((ClientData instanceData, + Tcl_Interp *interp)); +static int ExpInputProc _ANSI_ARGS_((ClientData instanceData, + char *buf, int toRead, int *errorCode)); +static int ExpOutputProc _ANSI_ARGS_(( + ClientData instanceData, char *buf, int toWrite, + int *errorCode)); +static void ExpWatchProc _ANSI_ARGS_((ClientData instanceData, + int mask)); +static int ExpGetHandleProc _ANSI_ARGS_((ClientData instanceData, + int direction, ClientData *handlePtr)); + +/* + * This structure describes the channel type structure for Expect-based IO: + */ + +Tcl_ChannelType expChannelType = { + "exp", /* Type name. */ + ExpBlockModeProc, /* Set blocking/nonblocking mode.*/ + ExpCloseProc, /* Close proc. */ + ExpInputProc, /* Input proc. */ + ExpOutputProc, /* Output proc. */ + NULL, /* Seek proc. */ + NULL, /* Set option proc. */ + NULL, /* Get option proc. */ + ExpWatchProc, /* Initialize notifier. */ + ExpGetHandleProc, /* Get OS handles out of channel. */ + NULL, /* Close2 proc */ +}; + +typedef struct ThreadSpecificData { + /* + * List of all exp channels currently open. This is per thread and is + * used to match up fd's to channels, which rarely occurs. + */ + + ExpState *firstExpPtr; + int channelCount; /* this is process-wide as it is used to + give user some hint as to why a spawn has failed + by looking at process-wide resource usage */ +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +/* + *---------------------------------------------------------------------- + * + * ExpBlockModeProc -- + * + * Helper procedure to set blocking and nonblocking modes on a + * file based channel. Invoked by generic IO level code. + * + * Results: + * 0 if successful, errno when failed. + * + * Side effects: + * Sets the device into blocking or non-blocking mode. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +ExpBlockModeProc(instanceData, mode) + ClientData instanceData; /* Exp state. */ + int mode; /* The mode to set. Can be one of + * TCL_MODE_BLOCKING or + * TCL_MODE_NONBLOCKING. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + + if (esPtr->fdin == 0) { + /* Forward status to debugger. Required for FIONBIO systems, + * which are unable to query the fd for its current state. + */ + Dbg_StdinMode (mode); + } + + /* [Expect SF Bug 1108551] (July 7 2005) + * Exclude manipulation of the blocking status for stdin/stderr. + * + * This is handled by the Tcl core itself and we must absolutely + * not pull the rug out from under it. The standard setting to + * non-blocking will mess with the core which had them set to + * blocking, and makes all its decisions based on that assumption. + * Setting to non-blocking can cause hangs and crashes. + * + * Stdin is ok however, apparently. + * (Sep 9 2005) No, it is not. + */ + + if ((esPtr->fdin == 0) || + (esPtr->fdin == 1) || + (esPtr->fdin == 2)) { + return 0; + } + + return expSetBlockModeProc (esPtr->fdin, mode); +} + +int +expSetBlockModeProc(fd, mode) + int fd; + int mode; /* The mode to set. Can be one of + * TCL_MODE_BLOCKING or + * TCL_MODE_NONBLOCKING. */ +{ + int curStatus; + /*printf("ExpBlockModeProc(%d)\n",mode); + printf("fdin = %d\n",fd);*/ + +#ifndef USE_FIONBIO + curStatus = fcntl(fd, F_GETFL); + /*printf("curStatus = %d\n",curStatus);*/ + if (mode == TCL_MODE_BLOCKING) { + curStatus &= (~(O_NONBLOCK)); + } else { + curStatus |= O_NONBLOCK; + } + /*printf("new curStatus %d\n",curStatus);*/ + if (fcntl(fd, F_SETFL, curStatus) < 0) { + return errno; + } + curStatus = fcntl(fd, F_GETFL); +#else /* USE_FIONBIO */ + if (mode == TCL_MODE_BLOCKING) { + curStatus = 0; + } else { + curStatus = 1; + } + if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) { + return errno; + } +#endif /* !USE_FIONBIO */ + return 0; +} +/* + *---------------------------------------------------------------------- + * + * ExpInputProc -- + * + * This procedure is invoked from the generic IO level to read + * input from an exp-based channel. + * + * Results: + * The number of bytes read is returned or -1 on error. An output + * argument contains a POSIX error code if an error occurs, or zero. + * + * Side effects: + * Reads input from the input device of the channel. + * + *---------------------------------------------------------------------- + */ + +static int +ExpInputProc(instanceData, buf, toRead, errorCodePtr) + ClientData instanceData; /* Exp state. */ + char *buf; /* Where to store data read. */ + int toRead; /* How much space is available + * in the buffer? */ + int *errorCodePtr; /* Where to store error code. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + int bytesRead; /* How many bytes were actually + * read from the input device? */ + + *errorCodePtr = 0; + + /* + * Assume there is always enough input available. This will block + * appropriately, and read will unblock as soon as a short read is + * possible, if the channel is in blocking mode. If the channel is + * nonblocking, the read will never block. + */ + + bytesRead = read(esPtr->fdin, buf, (size_t) toRead); + /*printf("ExpInputProc: read(%d,,) = %d\r\n",esPtr->fdin,bytesRead);*/ + if (bytesRead > -1) { + /* strip parity if requested */ + if (esPtr->parity == 0) { + char *end = buf+bytesRead; + for (;buf < end;buf++) { + *buf &= 0x7f; + } + } + return bytesRead; + } + *errorCodePtr = errno; + return -1; +} + +/* + *---------------------------------------------------------------------- + * + * ExpOutputProc-- + * + * This procedure is invoked from the generic IO level to write + * output to an exp channel. + * + * Results: + * The number of bytes written is returned or -1 on error. An + * output argument contains a POSIX error code if an error occurred, + * or zero. + * + * Side effects: + * Writes output on the output device of the channel. + * + *---------------------------------------------------------------------- + */ + +static int +ExpOutputProc(instanceData, buf, toWrite, errorCodePtr) + ClientData instanceData; /* Exp state. */ + char *buf; /* The data buffer. */ + int toWrite; /* How many bytes to write? */ + int *errorCodePtr; /* Where to store error code. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + int written = 0; + + *errorCodePtr = 0; + + if (toWrite < 0) Tcl_Panic("ExpOutputProc: called with negative char count"); + if (toWrite ==0) { + return 0; + } + + written = write(esPtr->fdout, buf, (size_t) toWrite); + if (written == 0) { + /* This shouldn't happen but I'm told that it does + * nonetheless (at least on SunOS 4.1.3). Since this is + * not a documented return value, the most reasonable + * thing is to complain here and retry in the hopes that + * it is some transient condition. */ + sleep(1); + expDiagLogU("write() failed to write anything - will sleep(1) and retry...\n"); + *errorCodePtr = EAGAIN; + return -1; + } else if (written < 0) { + *errorCodePtr = errno; + return -1; + } + return written; +} + +/* + *---------------------------------------------------------------------- + * + * ExpCloseProc -- + * + * This procedure is called from the generic IO level to perform + * channel-type-specific cleanup when an exp-based channel is closed. + * + * Results: + * 0 if successful, errno if failed. + * + * Side effects: + * Closes the device of the channel. + * + *---------------------------------------------------------------------- + */ + +/*ARGSUSED*/ +static int +ExpCloseProc(instanceData, interp) + ClientData instanceData; /* Exp state. */ + Tcl_Interp *interp; /* For error reporting - unused. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + ExpState **nextPtrPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + esPtr->registered = FALSE; + +#if 0 + /* + Really should check that we created one first. Since we're sharing fds + with Tcl, perhaps a filehandler was created with a plain tcl file - we + wouldn't want to delete that. Although if user really close Expect's + user_spawn_id, it probably doesn't matter anyway. + */ + + Tcl_DeleteFileHandler(esPtr->fdin); +#endif /*0*/ + + Tcl_Free((char*)esPtr->input.buffer); + Tcl_DecrRefCount (esPtr->input.newchars); + + /* Actually file descriptor should have been closed earlier. */ + /* So do nothing here */ + + /* + * Conceivably, the process may not yet have been waited for. If this + * becomes a requirement, we'll have to revisit this code. But for now, if + * it's just Tcl exiting, the processes will exit on their own soon + * anyway. + */ + + for (nextPtrPtr = &(tsdPtr->firstExpPtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == esPtr) { + (*nextPtrPtr) = esPtr->nextPtr; + break; + } + } + tsdPtr->channelCount--; + + if (esPtr->bg_status == blocked || + esPtr->bg_status == disarm_req_while_blocked) { + esPtr->freeWhenBgHandlerUnblocked = 1; + /* + * If we're in the middle of a bg event handler, then the event + * handler will have to take care of freeing esPtr. + */ + } else { + expStateFree(esPtr); + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * ExpWatchProc -- + * + * Initialize the notifier to watch the fd from this channel. + * + * Results: + * None. + * + * Side effects: + * Sets up the notifier so that a future event on the channel will + * be seen by Tcl. + * + *---------------------------------------------------------------------- + */ + +static void +ExpWatchProc(instanceData, mask) + ClientData instanceData; /* The exp state. */ + int mask; /* Events of interest; an OR-ed + * combination of TCL_READABLE, + * TCL_WRITABLE and TCL_EXCEPTION. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + + /* + * Make sure we only register for events that are valid on this exp. + * Note that we are passing Tcl_NotifyChannel directly to + * Tcl_CreateExpHandler with the channel pointer as the client data. + */ + + mask &= esPtr->validMask; + if (mask) { + /*printf(" CreateFileHandler: %d (mask = %d)\r\n",esPtr->fdin,mask);*/ + Tcl_CreateFileHandler(esPtr->fdin, mask, + (Tcl_FileProc *) Tcl_NotifyChannel, + (ClientData) esPtr->channel); + } else { + /*printf(" DeleteFileHandler: %d (mask = %d)\r\n",esPtr->fdin,mask);*/ + Tcl_DeleteFileHandler(esPtr->fdin); + } +} + +/* + *---------------------------------------------------------------------- + * + * ExpGetHandleProc -- + * + * Called from Tcl_GetChannelHandle to retrieve OS handles from + * an exp-based channel. + * + * Results: + * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if + * there is no handle for the specified direction. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ExpGetHandleProc(instanceData, direction, handlePtr) + ClientData instanceData; /* The exp state. */ + int direction; /* TCL_READABLE or TCL_WRITABLE */ + ClientData *handlePtr; /* Where to store the handle. */ +{ + ExpState *esPtr = (ExpState *) instanceData; + + if (direction & TCL_WRITABLE) { + *handlePtr = (ClientData) esPtr->fdin; + } + if (direction & TCL_READABLE) { + *handlePtr = (ClientData) esPtr->fdin; + } else { + return TCL_ERROR; + } + return TCL_OK; +} + +int +expChannelCountGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->channelCount; +} +#if 0 /* Converted to macros */ +int +expSizeGet(esPtr) + ExpState *esPtr; +{ + return esPtr->input.use; +} + +int +expSizeZero(esPtr) + ExpState *esPtr; +{ + return (esPtr->input.use == 0); +} +#endif +/* return 0 for success or negative for failure */ +int +expWriteChars(esPtr,buffer,lenBytes) + ExpState *esPtr; + char *buffer; + int lenBytes; +{ + int rc; + retry: + rc = Tcl_WriteChars(esPtr->channel,buffer,lenBytes); + if ((rc == -1) && (errno == EAGAIN)) goto retry; + + if (!exp_strict_write) { + /* + * 5.41 compatbility behaviour. Ignore any and all write errors + * the OS may have thrown. + */ + return 0; + } + + /* just return 0 rather than positive byte counts */ + return ((rc > 0) ? 0 : rc); +} + +int +expWriteCharsUni(esPtr,buffer,lenChars) + ExpState *esPtr; + Tcl_UniChar *buffer; + int lenChars; +{ + int rc; + Tcl_DString ds; + + Tcl_DStringInit (&ds); + Tcl_UniCharToUtfDString (buffer,lenChars,&ds); + + rc = expWriteChars(esPtr,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds)); + + Tcl_DStringFree (&ds); + + return rc; +} + +void +expStateFree(esPtr) + ExpState *esPtr; +{ + if (esPtr->fdBusy) { + close(esPtr->fdin); + } + + esPtr->valid = FALSE; + + if (!esPtr->keepForever) { + ckfree((char *)esPtr); + } +} + +/* close all connections + * + * The kernel would actually do this by default, however Tcl is going to come + * along later and try to reap its exec'd processes. If we have inherited any + * via spawn -open, Tcl can hang if we don't close the connections first. + */ +void +exp_close_all(interp) +Tcl_Interp *interp; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ExpState *esPtr; + ExpState *esNextPtr; + + /* Save the nextPtr in a local variable before calling 'exp_close' + as 'expStateFree' can be called from it under some + circumstances, possibly causing the memory allocator to smash + the value in 'esPtr'. - Andreas Kupries + */ + + /* no need to keep things in sync (i.e., tsdPtr, count) since we could only + be doing this if we're exiting. Just close everything down. */ + + for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esNextPtr) { + esNextPtr = esPtr->nextPtr; + exp_close(interp,esPtr); + } +} + +/* wait for any of our own spawned processes we call waitpid rather + * than wait to avoid running into someone else's processes. Yes, + * according to Ousterhout this is the best way to do it. + * returns the ExpState or 0 if nothing to wait on */ +ExpState * +expWaitOnAny() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + int result; + ExpState *esPtr; + + for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) { + if (esPtr->pid == exp_getpid) continue; /* skip ourself */ + if (esPtr->user_waited) continue; /* one wait only! */ + if (esPtr->sys_waited) break; + restart: + result = waitpid(esPtr->pid,&esPtr->wait,WNOHANG); + if (result == esPtr->pid) break; + if (result == 0) continue; /* busy, try next */ + if (result == -1) { + if (errno == EINTR) goto restart; + else break; + } + } + return esPtr; +} + +ExpState * +expWaitOnOne() { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ExpState *esPtr; + int pid; + /* should really be recoded using the common wait code in command.c */ + WAIT_STATUS_TYPE status; + + pid = wait(&status); + for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) { + if (esPtr->pid == pid) { + esPtr->sys_waited = TRUE; + esPtr->wait = status; + return esPtr; + } + } + /* Should not reach this location. If it happens return a value + * causing an easy crash */ + return NULL; +} + +void +exp_background_channelhandlers_run_all() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ExpState *esPtr; + + /* kick off any that already have input waiting */ + for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) { + /* is bg_interp the best way to check if armed? */ + if (esPtr->bg_interp && !expSizeZero(esPtr)) { + exp_background_channelhandler((ClientData)esPtr,0); + } + } +} + +ExpState * +expCreateChannel(interp,fdin,fdout,pid) + Tcl_Interp *interp; + int fdin; + int fdout; + int pid; +{ + ExpState *esPtr; + int mask; + Tcl_ChannelType *channelTypePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + channelTypePtr = &expChannelType; + + esPtr = (ExpState *) ckalloc((unsigned) sizeof(ExpState)); + + esPtr->nextPtr = tsdPtr->firstExpPtr; + tsdPtr->firstExpPtr = esPtr; + + sprintf(esPtr->name,"exp%d",fdin); + + /* + * For now, stupidly assume this. We we will likely have to revisit this + * later to prevent people from doing stupid things. + */ + mask = TCL_READABLE | TCL_WRITABLE; + + /* not sure about this - what about adopted channels */ + esPtr->validMask = mask | TCL_EXCEPTION; + esPtr->fdin = fdin; + esPtr->fdout = fdout; + + /* set close-on-exec for everything but std channels */ + /* (system and stty commands need access to std channels) */ + if (fdin != 0 && fdin != 2) { + expCloseOnExec(fdin); + if (fdin != fdout) expCloseOnExec(fdout); + } + + esPtr->fdBusy = FALSE; + esPtr->channel = Tcl_CreateChannel(channelTypePtr, esPtr->name, + (ClientData) esPtr, mask); + Tcl_RegisterChannel(interp,esPtr->channel); + esPtr->registered = TRUE; + Tcl_SetChannelOption(interp,esPtr->channel,"-buffering","none"); + Tcl_SetChannelOption(interp,esPtr->channel,"-blocking","0"); + Tcl_SetChannelOption(interp,esPtr->channel,"-translation","lf"); + + esPtr->pid = pid; + + esPtr->input.max = 1; + esPtr->input.use = 0; + esPtr->input.buffer = (Tcl_UniChar*) Tcl_Alloc (sizeof (Tcl_UniChar)); + esPtr->input.newchars = Tcl_NewObj(); + Tcl_IncrRefCount (esPtr->input.newchars); + + esPtr->umsize = exp_default_match_max; + /* this will reallocate object with an appropriate sized buffer */ + expAdjust(esPtr); + + esPtr->printed = 0; + esPtr->echoed = 0; + esPtr->rm_nulls = exp_default_rm_nulls; + esPtr->parity = exp_default_parity; + esPtr->close_on_eof = exp_default_close_on_eof; + esPtr->key = expect_key++; + esPtr->force_read = FALSE; + esPtr->fg_armed = FALSE; + esPtr->chan_orig = 0; + esPtr->fd_slave = EXP_NOFD; +#ifdef HAVE_PTYTRAP + esPtr->slave_name = 0; +#endif /* HAVE_PTYTRAP */ + esPtr->open = TRUE; + esPtr->notified = FALSE; + esPtr->user_waited = FALSE; + esPtr->sys_waited = FALSE; + esPtr->bg_interp = 0; + esPtr->bg_status = unarmed; + esPtr->bg_ecount = 0; + esPtr->freeWhenBgHandlerUnblocked = FALSE; + esPtr->keepForever = FALSE; + esPtr->valid = TRUE; + tsdPtr->channelCount++; + + return esPtr; +} + +void +expChannelInit() { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tsdPtr->channelCount = 0; +} diff --git a/exp_clib.c b/exp_clib.c new file mode 100644 index 0000000..172c05e --- /dev/null +++ b/exp_clib.c @@ -0,0 +1,2970 @@ +/* exp_clib.c - top-level functions in the expect C library, libexpect.a + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <setjmp.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> +#include <sys/ioctl.h> + +#ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#ifdef CRAY +# ifndef TCSETCTTY +# if defined(HAVE_TERMIOS) +# include <termios.h> +# else +# include <termio.h> +# endif +# endif +#endif + +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif + +#ifdef HAVE_STRREDIR_H +#include <sys/strredir.h> +# ifdef SRIOCSREDIR +# undef TIOCCONS +# endif +#endif + +#include <signal.h> +/*#include <memory.h> - deprecated - ANSI C moves them into string.h */ +#include "string.h" + +#include <errno.h> + +#ifdef NO_STDLIB_H + +/* + * Tcl's compat/stdlib.h + */ + +/* + * stdlib.h -- + * + * Declares facilities exported by the "stdlib" portion of + * the C library. This file isn't complete in the ANSI-C + * sense; it only declares things that are needed by Tcl. + * This file is needed even on many systems with their own + * stdlib.h (e.g. SunOS) because not all stdlib.h files + * declare all the procedures needed here (such as strtod). + * + * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $ + */ + +#ifndef _STDLIB +#define _STDLIB + +extern void abort _ANSI_ARGS_((void)); +extern double atof _ANSI_ARGS_((CONST char *string)); +extern int atoi _ANSI_ARGS_((CONST char *string)); +extern long atol _ANSI_ARGS_((CONST char *string)); +extern char * calloc _ANSI_ARGS_((unsigned int numElements, + unsigned int size)); +extern void exit _ANSI_ARGS_((int status)); +extern int free _ANSI_ARGS_((char *blockPtr)); +extern char * getenv _ANSI_ARGS_((CONST char *name)); +extern char * malloc _ANSI_ARGS_((unsigned int numBytes)); +extern void qsort _ANSI_ARGS_((VOID *base, int n, int size, + int (*compar)(CONST VOID *element1, CONST VOID + *element2))); +extern char * realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes)); +extern double strtod _ANSI_ARGS_((CONST char *string, char **endPtr)); +extern long strtol _ANSI_ARGS_((CONST char *string, char **endPtr, + int base)); +extern unsigned long strtoul _ANSI_ARGS_((CONST char *string, + char **endPtr, int base)); + +#endif /* _STDLIB */ + +/* + * end of Tcl's compat/stdlib.h + */ + +#else +#include <stdlib.h> /* for malloc */ +#endif + +#include <tcl.h> +#include "expect.h" +#define TclRegError exp_TclRegError + +/* + * regexp code - from tcl8.0.4/generic/regexp.c + */ + +/* + * TclRegComp and TclRegExec -- TclRegSub is elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + * + * *** NOTE: this code has been altered slightly for use in Tcl: *** + * *** 1. Use ckalloc and ckfree instead of malloc and free. *** + * *** 2. Add extra argument to regexp to specify the real *** + * *** start of the string separately from the start of the *** + * *** current search. This is needed to search for multiple *** + * *** matches within a string. *** + * *** 3. Names have been changed, e.g. from regcomp to *** + * *** TclRegComp, to avoid clashes with other *** + * *** regexp implementations used by applications. *** + * *** 4. Added errMsg declaration and TclRegError procedure *** + * *** 5. Various lint-like things, such as casting arguments *** + * *** in procedure calls. *** + * + * *** NOTE: This code has been altered for use in MT-Sturdy Tcl *** + * *** 1. All use of static variables has been changed to access *** + * *** fields of a structure. *** + * *** 2. This in addition to changes to TclRegError makes the *** + * *** code multi-thread safe. *** + * + * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $ + */ + +#if 0 +#include "tclInt.h" +#include "tclPort.h" +#endif + +/* + * The variable below is set to NULL before invoking regexp functions + * and checked after those functions. If an error occurred then TclRegError + * will set the variable to point to a (static) error message. This + * mechanism unfortunately does not support multi-threading, but the + * procedures TclRegError and TclGetRegError can be modified to use + * thread-specific storage for the variable and thereby make the code + * thread-safe. + */ + +static char *errMsg = NULL; + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that TclRegComp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in TclRegExec() needs it and TclRegComp() is + * computing it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE (OPEN+NSUBEXP) /* no Analogous to OPEN. */ + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +#define FAIL(m) { TclRegError(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define META "^$.[()|?+*\\" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +/* + * Global work variables for TclRegComp(). + */ +struct regcomp_state { + char *regparse; /* Input-scan pointer. */ + int regnpar; /* () count. */ + char *regcode; /* Code-emit pointer; ®dummy = don't. */ + long regsize; /* Code size. */ +}; + +static char regdummy; + +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define MAGIC 0234 + + +/* + * Forward declarations for TclRegComp()'s friends. + */ + +static char * reg _ANSI_ARGS_((int paren, int *flagp, + struct regcomp_state *rcstate)); +static char * regatom _ANSI_ARGS_((int *flagp, + struct regcomp_state *rcstate)); +static char * regbranch _ANSI_ARGS_((int *flagp, + struct regcomp_state *rcstate)); +static void regc _ANSI_ARGS_((int b, + struct regcomp_state *rcstate)); +static void reginsert _ANSI_ARGS_((int op, char *opnd, + struct regcomp_state *rcstate)); +static char * regnext _ANSI_ARGS_((char *p)); +static char * regnode _ANSI_ARGS_((int op, + struct regcomp_state *rcstate)); +static void regoptail _ANSI_ARGS_((char *p, char *val)); +static char * regpiece _ANSI_ARGS_((int *flagp, + struct regcomp_state *rcstate)); +static void regtail _ANSI_ARGS_((char *p, char *val)); + +#ifdef STRCSPN +static int strcspn _ANSI_ARGS_((char *s1, char *s2)); +#endif + +/* + - TclRegComp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ +regexp * +TclRegComp(exp) +char *exp; +{ + register regexp *r; + register char *scan; + register char *longest; + register int len; + int flags; + struct regcomp_state state; + struct regcomp_state *rcstate= &state; + + if (exp == NULL) + FAIL("NULL argument"); + + /* First pass: determine size, legality. */ + rcstate->regparse = exp; + rcstate->regnpar = 1; + rcstate->regsize = 0L; + rcstate->regcode = ®dummy; + regc(MAGIC, rcstate); + if (reg(0, &flags, rcstate) == NULL) + return(NULL); + + /* Small enough for pointer-storage convention? */ + if (rcstate->regsize >= 32767L) /* Probably could be 65535L. */ + FAIL("regexp too big"); + + /* Allocate space. */ + r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)rcstate->regsize); + if (r == NULL) + FAIL("out of space"); + + /* Second pass: emit code. */ + rcstate->regparse = exp; + rcstate->regnpar = 1; + rcstate->regcode = r->program; + regc(MAGIC, rcstate); + if (reg(0, &flags, rcstate) == NULL) { + ckfree ((char*) r); + return(NULL); + } + + /* Dig out information for optimizations. */ + r->regstart = '\0'; /* Worst-case defaults. */ + r->reganch = 0; + r->regmust = NULL; + r->regmlen = 0; + scan = r->program+1; /* First BRANCH. */ + if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(scan) == EXACTLY) + r->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + r->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + r->regmust = longest; + r->regmlen = len; + } + } + + return(r); +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static char * +reg(paren, flagp, rcstate) +int paren; /* Parenthesized? */ +int *flagp; +struct regcomp_state *rcstate; +{ + register char *ret; + register char *br; + register char *ender; + register int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (rcstate->regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = rcstate->regnpar; + rcstate->regnpar++; + ret = regnode(OPEN+parno,rcstate); + } else + ret = NULL; + + /* Pick up the branches, linking them together. */ + br = regbranch(&flags,rcstate); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*rcstate->regparse == '|') { + rcstate->regparse++; + br = regbranch(&flags,rcstate); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END,rcstate); + regtail(ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + /* Check for proper termination. */ + if (paren && *rcstate->regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *rcstate->regparse != '\0') { + if (*rcstate->regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char * +regbranch(flagp, rcstate) +int *flagp; +struct regcomp_state *rcstate; +{ + register char *ret; + register char *chain; + register char *latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(BRANCH,rcstate); + chain = NULL; + while (*rcstate->regparse != '\0' && *rcstate->regparse != '|' && + *rcstate->regparse != ')') { + latest = regpiece(&flags, rcstate); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING,rcstate); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static char * +regpiece(flagp, rcstate) +int *flagp; +struct regcomp_state *rcstate; +{ + register char *ret; + register char op; + register char *next; + int flags; + + ret = regatom(&flags,rcstate); + if (ret == NULL) + return(NULL); + + op = *rcstate->regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret, rcstate); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret, rcstate); /* Either x */ + regoptail(ret, regnode(BACK,rcstate)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH,rcstate)); /* or */ + regtail(ret, regnode(NOTHING,rcstate)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret, rcstate); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH,rcstate); /* Either */ + regtail(ret, next); + regtail(regnode(BACK,rcstate), ret); /* loop back */ + regtail(next, regnode(BRANCH,rcstate)); /* or */ + regtail(ret, regnode(NOTHING,rcstate)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret, rcstate); /* Either x */ + regtail(ret, regnode(BRANCH,rcstate)); /* or */ + next = regnode(NOTHING,rcstate); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + rcstate->regparse++; + if (ISMULT(*rcstate->regparse)) + FAIL("nested *?+"); + + return(ret); +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static char * +regatom(flagp, rcstate) +int *flagp; +struct regcomp_state *rcstate; +{ + register char *ret; + int flags; + + *flagp = WORST; /* Tentatively. */ + + switch (*rcstate->regparse++) { + case '^': + ret = regnode(BOL,rcstate); + break; + case '$': + ret = regnode(EOL,rcstate); + break; + case '.': + ret = regnode(ANY,rcstate); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int clss; + register int classend; + + if (*rcstate->regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT,rcstate); + rcstate->regparse++; + } else + ret = regnode(ANYOF,rcstate); + if (*rcstate->regparse == ']' || *rcstate->regparse == '-') + regc(*rcstate->regparse++,rcstate); + while (*rcstate->regparse != '\0' && *rcstate->regparse != ']') { + if (*rcstate->regparse == '-') { + rcstate->regparse++; + if (*rcstate->regparse == ']' || *rcstate->regparse == '\0') + regc('-',rcstate); + else { + clss = UCHARAT(rcstate->regparse-2)+1; + classend = UCHARAT(rcstate->regparse); + if (clss > classend+1) + FAIL("invalid [] range"); + for (; clss <= classend; clss++) + regc((char)clss,rcstate); + rcstate->regparse++; + } + } else + regc(*rcstate->regparse++,rcstate); + } + regc('\0',rcstate); + if (*rcstate->regparse != ']') + FAIL("unmatched []"); + rcstate->regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags, rcstate); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + /* NOTREACHED */ + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + /* NOTREACHED */ + case '\\': + if (*rcstate->regparse == '\0') + FAIL("trailing \\"); + ret = regnode(EXACTLY,rcstate); + regc(*rcstate->regparse++,rcstate); + regc('\0',rcstate); + *flagp |= HASWIDTH|SIMPLE; + break; + default: { + register int len; + register char ender; + + rcstate->regparse--; + len = strcspn(rcstate->regparse, META); + if (len <= 0) + FAIL("internal disaster"); + ender = *(rcstate->regparse+len); + if (len > 1 && ISMULT(ender)) + len--; /* Back off clear of ?+* operand. */ + *flagp |= HASWIDTH; + if (len == 1) + *flagp |= SIMPLE; + ret = regnode(EXACTLY,rcstate); + while (len > 0) { + regc(*rcstate->regparse++,rcstate); + len--; + } + regc('\0',rcstate); + } + break; + } + + return(ret); +} + +/* + - regnode - emit a node + */ +static char * /* Location. */ +regnode(op, rcstate) +int op; +struct regcomp_state *rcstate; +{ + register char *ret; + register char *ptr; + + ret = rcstate->regcode; + if (ret == ®dummy) { + rcstate->regsize += 3; + return(ret); + } + + ptr = ret; + *ptr++ = (char)op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + rcstate->regcode = ptr; + + return(ret); +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void +regc(b, rcstate) +int b; +struct regcomp_state *rcstate; +{ + if (rcstate->regcode != ®dummy) + *rcstate->regcode++ = (char)b; + else + rcstate->regsize++; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +static void +reginsert(op, opnd, rcstate) +int op; +char *opnd; +struct regcomp_state *rcstate; +{ + register char *src; + register char *dst; + register char *place; + + if (rcstate->regcode == ®dummy) { + rcstate->regsize += 3; + return; + } + + src = rcstate->regcode; + rcstate->regcode += 3; + dst = rcstate->regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; /* Op node, where operand used to be. */ + *place++ = (char)op; + *place++ = '\0'; + *place = '\0'; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void +regtail(p, val) +char *p; +char *val; +{ + register char *scan; + register char *temp; + register int offset; + + if (p == ®dummy) + return; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (char)((offset>>8)&0377); + *(scan+2) = (char)(offset&0377); +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void +regoptail(p, val) +char *p; +char *val; +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + +/* + * TclRegExec and friends + */ + +/* + * Global work variables for TclRegExec(). + */ +struct regexec_state { + char *reginput; /* String-input pointer. */ + char *regbol; /* Beginning of input, for ^ check. */ + char **regstartp; /* Pointer to startp array. */ + char **regendp; /* Ditto for endp. */ +}; + +/* + * Forwards. + */ +static int regtry _ANSI_ARGS_((regexp *prog, char *string, + struct regexec_state *restate)); +static int regmatch _ANSI_ARGS_((char *prog, + struct regexec_state *restate)); +static int regrepeat _ANSI_ARGS_((char *p, + struct regexec_state *restate)); + +#ifdef DEBUG +int regnarrate = 0; +void regdump _ANSI_ARGS_((regexp *r)); +static char *regprop _ANSI_ARGS_((char *op)); +#endif + +/* + - TclRegExec - match a regexp against a string + */ +int +TclRegExec(prog, string, start) +register regexp *prog; +register char *string; +char *start; +{ + register char *s; + struct regexec_state state; + struct regexec_state *restate= &state; + + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + TclRegError("NULL parameter"); + return(0); + } + + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + TclRegError("corrupted program"); + return(0); + } + + /* If there is a "must appear" string, look for it. */ + if (prog->regmust != NULL) { + s = string; + while ((s = strchr(s, prog->regmust[0])) != NULL) { + if (strncmp(s, prog->regmust, (size_t) prog->regmlen) + == 0) + break; /* Found it. */ + s++; + } + if (s == NULL) /* Not present. */ + return(0); + } + + /* Mark beginning of line for ^ . */ + restate->regbol = start; + + /* Simplest case: anchored match need be tried only once. */ + if (prog->reganch) + return(regtry(prog, string, restate)); + + /* Messy cases: unanchored match. */ + s = string; + if (prog->regstart != '\0') + /* We know what char it must start with. */ + while ((s = strchr(s, prog->regstart)) != NULL) { + if (regtry(prog, s, restate)) + return(1); + s++; + } + else + /* We don't -- general case. */ + do { + if (regtry(prog, s, restate)) + return(1); + } while (*s++ != '\0'); + + /* Failure. */ + return(0); +} + +/* + - regtry - try match at specific point + */ +static int /* 0 failure, 1 success */ +regtry(prog, string, restate) +regexp *prog; +char *string; +struct regexec_state *restate; +{ + register int i; + register char **sp; + register char **ep; + + restate->reginput = string; + restate->regstartp = prog->startp; + restate->regendp = prog->endp; + + sp = prog->startp; + ep = prog->endp; + for (i = NSUBEXP; i > 0; i--) { + *sp++ = NULL; + *ep++ = NULL; + } + if (regmatch(prog->program + 1,restate)) { + prog->startp[0] = string; + prog->endp[0] = restate->reginput; + return(1); + } else + return(0); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +static int /* 0 failure, 1 success */ +regmatch(prog, restate) +char *prog; +struct regexec_state *restate; +{ + register char *scan; /* Current node. */ + char *next; /* Next node. */ + + scan = prog; +#ifdef DEBUG + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != NULL) { +#ifdef DEBUG + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); +#endif + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (restate->reginput != restate->regbol) { + return 0; + } + break; + case EOL: + if (*restate->reginput != '\0') { + return 0; + } + break; + case ANY: + if (*restate->reginput == '\0') { + return 0; + } + restate->reginput++; + break; + case EXACTLY: { + register int len; + register char *opnd; + + opnd = OPERAND(scan); + /* Inline the first character, for speed. */ + if (*opnd != *restate->reginput) { + return 0 ; + } + len = strlen(opnd); + if (len > 1 && strncmp(opnd, restate->reginput, (size_t) len) + != 0) { + return 0; + } + restate->reginput += len; + break; + } + case ANYOF: + if (*restate->reginput == '\0' + || strchr(OPERAND(scan), *restate->reginput) == NULL) { + return 0; + } + restate->reginput++; + break; + case ANYBUT: + if (*restate->reginput == '\0' + || strchr(OPERAND(scan), *restate->reginput) != NULL) { + return 0; + } + restate->reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; + + doOpen: + no = OP(scan) - OPEN; + save = restate->reginput; + + if (regmatch(next,restate)) { + /* + * Don't set startp if some later invocation of the + * same parentheses already has. + */ + if (restate->regstartp[no] == NULL) { + restate->regstartp[no] = save; + } + return 1; + } else { + return 0; + } + } + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; + + doClose: + no = OP(scan) - CLOSE; + save = restate->reginput; + + if (regmatch(next,restate)) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (restate->regendp[no] == NULL) + restate->regendp[no] = save; + return 1; + } else { + return 0; + } + } + case BRANCH: { + register char *save; + + if (OP(next) != BRANCH) { /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + } else { + do { + save = restate->reginput; + if (regmatch(OPERAND(scan),restate)) + return(1); + restate->reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return 0; + } + break; + } + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = restate->reginput; + no = regrepeat(OPERAND(scan),restate); + while (no >= min) { + /* If it could work, try it. */ + if (nextch == '\0' || *restate->reginput == nextch) + if (regmatch(next,restate)) + return(1); + /* Couldn't or didn't -- back up. */ + no--; + restate->reginput = save + no; + } + return(0); + } + case END: + return(1); /* Success! */ + default: + if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) { + goto doOpen; + } else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) { + goto doClose; + } + TclRegError("memory corruption"); + return 0; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + TclRegError("corrupted pointers"); + return(0); +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int +regrepeat(p, restate) +char *p; +struct regexec_state *restate; +{ + register int count = 0; + register char *scan; + register char *opnd; + + scan = restate->reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + TclRegError("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + restate->reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static char * +regnext(p) +register char *p; +{ + register int offset; + + if (p == ®dummy) + return(NULL); + + offset = NEXT(p); + if (offset == 0) + return(NULL); + + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#ifdef DEBUG + +static char *regprop(); + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +void +regdump(r) +regexp *r; +{ + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; + + + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } + + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static char * +regprop(op) +char *op; +{ + register char *p; + static char buf[50]; + + (void) strcpy(buf, ":"); + + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + default: + if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) { + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + } else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) { + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + } else { + TclRegError("corrupted opcode"); + } + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); +} +#endif + +/* + * The following is provided for those people who do not have strcspn() in + * their C libraries. They should get off their butts and do something + * about it; at least one public-domain implementation of those (highly + * useful) string routines has been published on Usenet. + */ +#ifdef STRCSPN +/* + * strcspn - find length of initial segment of s1 consisting entirely + * of characters not from s2 + */ + +static int +strcspn(s1, s2) +char *s1; +char *s2; +{ + register char *scan1; + register char *scan2; + register int count; + + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); +} +#endif + +/* + *---------------------------------------------------------------------- + * + * TclRegError -- + * + * This procedure is invoked by the regexp code when an error + * occurs. It saves the error message so it can be seen by the + * code that called Spencer's code. + * + * Results: + * None. + * + * Side effects: + * The value of "string" is saved in "errMsg". + * + *---------------------------------------------------------------------- + */ + +void +exp_TclRegError(string) + char *string; /* Error message. */ +{ + errMsg = string; +} + +char * +TclGetRegError() +{ + return errMsg; +} + +/* + * end of regexp definitions and code + */ + +/* + * stolen from exp_log.c - this function is called from the Expect library + * but the one that the library supplies calls Tcl functions. So we supply + * our own. + */ + +static +void +expDiagLogU(str) + char *str; +{ + if (exp_is_debugging) { + fprintf(stderr,str); + if (exp_logfile) fprintf(exp_logfile,str); + } +} + +/* + * expect-specific definitions and code + */ + +#include "expect.h" +#include "exp_int.h" + +/* exp_glob.c - expect functions for doing glob + * + * Based on Tcl's glob functions but modified to support anchors and to + * return information about the possibility of future matches + * + * Modifications by: Don Libes, NIST, 2/6/90 + */ + +/* The following functions implement expect's glob-style string + * matching Exp_StringMatch allow's implements the unanchored front + * (or conversely the '^') feature. Exp_StringMatch2 does the rest of + * the work. + */ + +/* Exp_StringMatch2 -- + * + * Like Tcl_StringMatch except that + * 1) returns number of characters matched, -1 if failed. + * (Can return 0 on patterns like "" or "$") + * 2) does not require pattern to match to end of string + * 3) much of code is stolen from Tcl_StringMatch + * 4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor) + */ +static +int +Exp_StringMatch2(string,pattern) + register char *string; /* String. */ + register char *pattern; /* Pattern, which may contain + * special characters. */ +{ + char c2; + int match = 0; /* # of chars matched */ + + while (1) { + /* If at end of pattern, success! */ + if (*pattern == 0) { + return match; + } + + /* If last pattern character is '$', verify that entire + * string has been matched. + */ + if ((*pattern == '$') && (pattern[1] == 0)) { + if (*string == 0) return(match); + else return(-1); + } + + /* Check for a "*" as the next pattern character. It matches + * any substring. We handle this by calling ourselves + * recursively for each postfix of string, until either we + * match or we reach the end of the string. + */ + + if (*pattern == '*') { + int head_len; + char *tail; + pattern += 1; + if (*pattern == 0) { + return(strlen(string)+match); /* DEL */ + } + /* find longest match - switched to this on 12/31/93 */ + head_len = strlen(string); /* length before tail */ + tail = string + head_len; + while (head_len >= 0) { + int rc; + + if (-1 != (rc = Exp_StringMatch2(tail, pattern))) { + return rc + match + head_len; /* DEL */ + } + tail--; + head_len--; + } + return -1; /* DEL */ + } + + /* + * after this point, all patterns must match at least one + * character, so check this + */ + + if (*string == 0) return -1; + + /* Check for a "?" as the next pattern character. It matches + * any single character. + */ + + if (*pattern == '?') { + goto thisCharOK; + } + + /* Check for a "[" as the next pattern character. It is followed + * by a list of characters that are acceptable, or by a range + * (two characters separated by "-"). + */ + + if (*pattern == '[') { + pattern += 1; + while (1) { + if ((*pattern == ']') || (*pattern == 0)) { + return -1; /* was 0; DEL */ + } + if (*pattern == *string) { + break; + } + if (pattern[1] == '-') { + c2 = pattern[2]; + if (c2 == 0) { + return -1; /* DEL */ + } + if ((*pattern <= *string) && (c2 >= *string)) { + break; + } + if ((*pattern >= *string) && (c2 <= *string)) { + break; + } + pattern += 2; + } + pattern += 1; + } + + while (*pattern != ']') { + if (*pattern == 0) { + pattern--; + break; + } + pattern += 1; + } + goto thisCharOK; + } + + /* If the next pattern character is backslash, strip it off + * so we do exact matching on the character that follows. + */ + + if (*pattern == '\\') { + pattern += 1; + if (*pattern == 0) { + return -1; + } + } + + /* There's no special character. Just make sure that the next + * characters of each string match. + */ + + if (*pattern != *string) { + return -1; + } + + thisCharOK: pattern += 1; + string += 1; + match++; + } +} + + +static +int /* returns # of chars that matched */ +Exp_StringMatch(string, pattern,offset) +char *string; +char *pattern; +int *offset; /* offset from beginning of string where pattern matches */ +{ + char *s; + int sm; /* count of chars matched or -1 */ + int caret = FALSE; + int star = FALSE; + + *offset = 0; + + if (pattern[0] == '^') { + caret = TRUE; + pattern++; + } else if (pattern[0] == '*') { + star = TRUE; + } + + /* + * test if pattern matches in initial position. + * This handles front-anchor and 1st iteration of non-front-anchor. + * Note that 1st iteration must be tried even if string is empty. + */ + + sm = Exp_StringMatch2(string,pattern); + if (sm >= 0) return(sm); + + if (caret) return -1; + if (star) return -1; + + if (*string == '\0') return -1; + + for (s = string+1;*s;s++) { + sm = Exp_StringMatch2(s,pattern); + if (sm != -1) { + *offset = s-string; + return(sm); + } + } + return -1; +} + + +#define EXP_MATCH_MAX 2000 +/* public */ +char *exp_buffer = 0; +char *exp_buffer_end = 0; +char *exp_match = 0; +char *exp_match_end = 0; +int exp_match_max = EXP_MATCH_MAX; /* bytes */ +int exp_full_buffer = FALSE; /* don't return on full buffer */ +int exp_remove_nulls = TRUE; +int exp_timeout = 10; /* seconds */ +int exp_pty_timeout = 5; /* seconds - see CRAY below */ +int exp_autoallocpty = TRUE; /* if TRUE, we do allocation */ +int exp_pty[2]; /* master is [0], slave is [1] */ +int exp_pid; +char *exp_stty_init = 0; /* initial stty args */ +int exp_ttycopy = TRUE; /* copy tty parms from /dev/tty */ +int exp_ttyinit = TRUE; /* set tty parms to sane state */ +int exp_console = FALSE; /* redirect console */ +void (*exp_child_exec_prelude)() = 0; +void (*exp_close_in_child)() = 0; + +#ifdef HAVE_SIGLONGJMP +sigjmp_buf exp_readenv; /* for interruptable read() */ +#else +jmp_buf exp_readenv; /* for interruptable read() */ +#endif /* HAVE_SIGLONGJMP */ + +int exp_reading = FALSE; /* whether we can longjmp or not */ + +int exp_is_debugging = FALSE; +FILE *exp_debugfile = 0; + +FILE *exp_logfile = 0; +int exp_logfile_all = FALSE; /* if TRUE, write log of all interactions */ +int exp_loguser = TRUE; /* if TRUE, user sees interactions on stdout */ + + +char *exp_printify(); +int exp_getptymaster(); +int exp_getptyslave(); + +#define sysreturn(x) return(errno = x, -1) + +void exp_init_pty(); + +/* + The following functions are linked from the Tcl library. They + don't cause anything else in the library to be dragged in, so it + shouldn't cause any problems (e.g., bloat). + + The functions are relatively small but painful enough that I don't care + to recode them. You may, if you absolutely want to get rid of any + vestiges of Tcl. +*/ + +static unsigned int bufsiz = 2*EXP_MATCH_MAX; + +static struct f { + int valid; + + char *buffer; /* buffer of matchable chars */ + char *buffer_end; /* one beyond end of matchable chars */ + char *match_end; /* one beyond end of matched string */ + int msize; /* size of allocate space */ + /* actual size is one larger for null */ +} *fs = 0; + +static int fd_alloc_max = -1; /* max fd allocated */ + +/* translate fd or fp to fd */ +static struct f * +fdfp2f(fd,fp) +int fd; +FILE *fp; +{ + if (fd == -1) return(fs + fileno(fp)); + else return(fs + fd); +} + +static struct f * +fd_new(fd) +int fd; +{ + int i, low; + struct f *fp; + struct f *newfs; /* temporary, so we don't lose old fs */ + + if (fd > fd_alloc_max) { + if (!fs) { /* no fd's yet allocated */ + newfs = (struct f *)malloc(sizeof(struct f)*(fd+1)); + low = 0; + } else { /* enlarge fd table */ + newfs = (struct f *)realloc((char *)fs,sizeof(struct f)*(fd+1)); + low = fd_alloc_max+1; + } + fs = newfs; + fd_alloc_max = fd; + for (i = low; i <= fd_alloc_max; i++) { /* init new entries */ + fs[i].valid = FALSE; + } + } + + fp = fs+fd; + + if (!fp->valid) { + /* initialize */ + fp->buffer = malloc((unsigned)(bufsiz+1)); + if (!fp->buffer) return 0; + fp->msize = bufsiz; + fp->valid = TRUE; + } + fp->buffer_end = fp->buffer; + fp->match_end = fp->buffer; + return fp; + +} + +static +void +exp_setpgrp() +{ +#ifdef MIPS_BSD + /* required on BSD side of MIPS OS <jmsellen@watdragon.waterloo.edu> */ +# include <sysv/sys.s> + syscall(SYS_setpgrp); +#endif + +#ifdef SETPGRP_VOID + (void) setpgrp(); +#else + (void) setpgrp(0,0); +#endif +} + +/* returns fd of master side of pty */ +int +exp_spawnv(file,argv) +char *file; +char *argv[]; /* some compiler complains about **argv? */ +{ + int cc; + int errorfd; /* place to stash fileno(stderr) in child */ + /* while we're setting up new stderr */ + int ttyfd; + int sync_fds[2]; + int sync2_fds[2]; + int status_pipe[2]; + int child_errno; + char sync_byte; +#ifdef PTYTRAP_DIES + int slave_write_ioctls = 1; + /* by default, slave will be write-ioctled this many times */ +#endif + + static int first_time = TRUE; + + if (first_time) { + first_time = FALSE; + exp_init_pty(); + exp_init_tty(); + expDiagLogPtrSet(expDiagLogU); + + /* + * TIP 27; It is unclear why this code produces a + * warning. The equivalent code in exp_main_sub.c + * (line 512) does not generate a warning ! + */ + + expErrnoMsgSet(Tcl_ErrnoMsg); + } + + if (!file || !argv) sysreturn(EINVAL); + if (!argv[0] || strcmp(file,argv[0])) { + exp_debuglog("expect: warning: file (%s) != argv[0] (%s)\n", + file, + argv[0]?argv[0]:""); + } + +#ifdef PTYTRAP_DIES +/* any extraneous ioctl's that occur in slave must be accounted for +when trapping, see below in child half of fork */ +#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300) + slave_write_ioctls++; +#endif +#endif /*PTYTRAP_DIES*/ + + if (exp_autoallocpty) { + if (0 > (exp_pty[0] = exp_getptymaster())) sysreturn(ENODEV); + } + fcntl(exp_pty[0],F_SETFD,1); /* close on exec */ +#ifdef PTYTRAP_DIES + exp_slave_control(exp_pty[0],1);*/ +#endif + + if (!fd_new(exp_pty[0])) { + errno = ENOMEM; + return -1; + } + + if (-1 == (pipe(sync_fds))) { + return -1; + } + if (-1 == (pipe(sync2_fds))) { + close(sync_fds[0]); + close(sync_fds[1]); + return -1; + } + + if (-1 == pipe(status_pipe)) { + close(sync_fds[0]); + close(sync_fds[1]); + close(sync2_fds[0]); + close(sync2_fds[1]); + return -1; + } + + if ((exp_pid = fork()) == -1) return(-1); + if (exp_pid) { + /* parent */ + close(sync_fds[1]); + close(sync2_fds[0]); + close(status_pipe[1]); + + if (!exp_autoallocpty) close(exp_pty[1]); + +#ifdef PTYTRAP_DIES +#ifdef HAVE_PTYTRAP + if (exp_autoallocpty) { + /* trap initial ioctls in a feeble attempt to not */ + /* block the initially. If the process itself */ + /* ioctls /dev/tty, such blocks will be trapped */ + /* later during normal event processing */ + + while (slave_write_ioctls) { + int cc; + + cc = exp_wait_for_slave_open(exp_pty[0]); +#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300) + if (cc == TIOCSCTTY) slave_write_ioctls = 0; +#endif + if (cc & IOC_IN) slave_write_ioctls--; + else if (cc == -1) { + printf("failed to trap slave pty"); + return -1; + } + } + } +#endif +#endif /*PTYTRAP_DIES*/ + + /* + * wait for slave to initialize pty before allowing + * user to send to it + */ + + exp_debuglog("parent: waiting for sync byte\r\n"); + cc = read(sync_fds[0],&sync_byte,1); + if (cc == -1) { + exp_errorlog("parent sync byte read: %s\r\n",Tcl_ErrnoMsg(errno)); + return -1; + } + + /* turn on detection of eof */ + exp_slave_control(exp_pty[0],1); + + /* + * tell slave to go on now now that we have initialized pty + */ + + exp_debuglog("parent: telling child to go ahead\r\n"); + cc = write(sync2_fds[1]," ",1); + if (cc == -1) { + exp_errorlog("parent sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); + return -1; + } + + exp_debuglog("parent: now unsynchronized from child\r\n"); + + close(sync_fds[0]); + close(sync2_fds[1]); + + /* see if child's exec worked */ + + retry: + switch (read(status_pipe[0],&child_errno,sizeof child_errno)) { + case -1: + if (errno == EINTR) goto retry; + /* well it's not really the child's errno */ + /* but it can be treated that way */ + child_errno = errno; + break; + case 0: + /* child's exec succeeded */ + child_errno = 0; + break; + default: + /* child's exec failed; err contains exec's errno */ + waitpid(exp_pid, NULL, 0); + errno = child_errno; + exp_pty[0] = -1; + } + close(status_pipe[0]); + return(exp_pty[0]); + } + + /* + * child process - do not return from here! all errors must exit() + */ + + close(sync_fds[0]); + close(sync2_fds[1]); + close(status_pipe[0]); + fcntl(status_pipe[1],F_SETFD,1); /* close on exec */ + +#ifdef CRAY + (void) close(exp_pty[0]); +#endif + +/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */ +/* is called. setpgrp works though. */ +#if defined(POSIX) && !defined(ultrix) +#define DO_SETSID +#endif +#ifdef __convex__ +#define DO_SETSID +#endif + +#ifdef DO_SETSID + setsid(); +#else +#ifdef SYSV3 +#ifndef CRAY + exp_setpgrp(); +#endif /* CRAY */ +#else /* !SYSV3 */ + exp_setpgrp(); + +#ifdef TIOCNOTTY + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd >= 0) { + (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); + (void) close(ttyfd); + } +#endif /* TIOCNOTTY */ + +#endif /* SYSV3 */ +#endif /* DO_SETSID */ + + /* save error fd while we're setting up new one */ + errorfd = fcntl(2,F_DUPFD,3); + /* and here is the macro to restore it */ +#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);} + + if (exp_autoallocpty) { + + close(0); + close(1); + close(2); + + /* since we closed fd 0, open of pty slave must return fd 0 */ + + if (0 > (exp_pty[1] = exp_getptyslave(exp_ttycopy,exp_ttyinit, + exp_stty_init))) { + restore_error_fd + fprintf(stderr,"open(slave pty): %s\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + /* sanity check */ + if (exp_pty[1] != 0) { + restore_error_fd + fprintf(stderr,"exp_getptyslave: slave = %d but expected 0\n", + exp_pty[1]); + exit(-1); + } + } else { + if (exp_pty[1] != 0) { + close(0); fcntl(exp_pty[1],F_DUPFD,0); + } + close(1); fcntl(0,F_DUPFD,1); + close(2); fcntl(0,F_DUPFD,1); + close(exp_pty[1]); + } + + + +/* The test for hpux may have to be more specific. In particular, the */ +/* code should be skipped on the hp9000s300 and hp9000s720 (but there */ +/* is no documented define for the 720!) */ + +#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux) + /* 4.3+BSD way to acquire controlling terminal */ + /* according to Stevens - Adv. Prog..., p 642 */ +#ifdef __QNX__ /* posix in general */ + if (tcsetct(0, getpid()) == -1) { + restore_error_fd + expErrorLog("failed to get controlling terminal using TIOCSCTTY"); + exit(-1); + } +#else + (void) ioctl(0,TIOCSCTTY,(char *)0); + /* ignore return value - on some systems, it is defined but it + * fails and it doesn't seem to cause any problems. Or maybe + * it works but returns a bogus code. Noone seems to be able + * to explain this to me. The systems are an assortment of + * different linux systems (and FreeBSD 2.5), RedHat 5.2 and + * Debian 2.0 + */ +#endif +#endif + +#ifdef CRAY + (void) setsid(); + (void) ioctl(0,TCSETCTTY,0); + (void) close(0); + if (open("/dev/tty", O_RDWR) < 0) { + restore_error_fd + fprintf(stderr,"open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + (void) close(1); + (void) close(2); + (void) dup(0); + (void) dup(0); + setptyutmp(); /* create a utmp entry */ + + /* _CRAY2 code from Hal Peterson <hrp@cray.com>, Cray Research, Inc. */ +#ifdef _CRAY2 + /* + * Interpose a process between expect and the spawned child to + * keep the slave side of the pty open to allow time for expect + * to read the last output. This is a workaround for an apparent + * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at + * least). + */ + if ((pid = fork()) == -1) { + restore_error_fd + fprintf(stderr,"second fork: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + + if (pid) { + /* Intermediate process. */ + int status; + int timeout; + char *t; + + /* How long should we wait? */ + timeout = exp_pty_timeout; + + /* Let the spawned process run to completion. */ + while (wait(&status) < 0 && errno == EINTR) + /* empty body */; + + /* Wait for the pty to clear. */ + sleep(timeout); + + /* Duplicate the spawned process's status. */ + if (WIFSIGNALED(status)) + kill(getpid(), WTERMSIG(status)); + + /* The kill may not have worked, but this will. */ + exit(WEXITSTATUS(status)); + } +#endif /* _CRAY2 */ +#endif /* CRAY */ + + if (exp_console) { +#ifdef SRIOCSREDIR + int fd; + + if ((fd = open("/dev/console", O_RDONLY)) == -1) { + restore_error_fd + fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]); + exit(-1); + } + if (ioctl(fd, SRIOCSREDIR, 0) == -1) { + restore_error_fd + fprintf(stderr, "spawn %s: cannot redirect console, check permissions of /dev/console\n",argv[0]); + } + close(fd); +#endif + +#ifdef TIOCCONS + int on = 1; + if (ioctl(0,TIOCCONS,(char *)&on) == -1) { + restore_error_fd + fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]); + exit(-1); + } +#endif /* TIOCCONS */ + } + + /* tell parent that we are done setting up pty */ + /* The actual char sent back is irrelevant. */ + + /* exp_debuglog("child: telling parent that pty is initialized\r\n");*/ + cc = write(sync_fds[1]," ",1); + if (cc == -1) { + restore_error_fd + fprintf(stderr,"child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + close(sync_fds[1]); + + /* wait for master to let us go on */ + cc = read(sync2_fds[0],&sync_byte,1); + if (cc == -1) { + restore_error_fd + exp_errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + close(sync2_fds[0]); + + /* exp_debuglog("child: now unsynchronized from parent\r\n"); */ + + /* (possibly multiple) masters are closed automatically due to */ + /* earlier fcntl(,,CLOSE_ON_EXEC); */ + + /* just in case, allow user to explicitly close other files */ + if (exp_close_in_child) (*exp_close_in_child)(); + + /* allow user to do anything else to child */ + if (exp_child_exec_prelude) (*exp_child_exec_prelude)(); + + (void) execvp(file,argv); + + /* Unfortunately, by now we've closed fd's to stderr, logfile + * and debugfile. The only reasonable thing to do is to send + * *back the error as part of the program output. This will + * be *picked up in an expect or interact command. + */ + + write(status_pipe[1], &errno, sizeof errno); + exit(-1); + /*NOTREACHED*/ +} + +/* returns fd of master side of pty */ +/*VARARGS*/ +int +exp_spawnl TCL_VARARGS_DEF(char *,arg1) +/*exp_spawnl(va_alist)*/ +/*va_dcl*/ +{ + va_list args; /* problematic line here */ + int i; + char *arg, **argv; + + arg = TCL_VARARGS_START(char *,arg1,args); + /*va_start(args);*/ + for (i=1;;i++) { + arg = va_arg(args,char *); + if (!arg) break; + } + va_end(args); + if (i == 0) sysreturn(EINVAL); + if (!(argv = (char **)malloc((i+1)*sizeof(char *)))) sysreturn(ENOMEM); + argv[0] = TCL_VARARGS_START(char *,arg1,args); + /*va_start(args);*/ + for (i=1;;i++) { + argv[i] = va_arg(args,char *); + if (!argv[i]) break; + } + i = exp_spawnv(argv[0],argv+1); + free((char *)argv); + return(i); +} + +/* allow user-provided fd to be passed to expect funcs */ +int +exp_spawnfd(fd) +int fd; +{ + if (!fd_new(fd)) { + errno = ENOMEM; + return -1; + } + return fd; +} + +/* remove nulls from s. Initially, the number of chars in s is c, */ +/* not strlen(s). This count does not include the trailing null. */ +/* returns number of nulls removed. */ +static int +rm_nulls(s,c) +char *s; +int c; +{ + char *s2 = s; /* points to place in original string to put */ + /* next non-null character */ + int count = 0; + int i; + + for (i=0;i<c;i++,s++) { + if (0 == *s) { + count++; + continue; + } + if (count) *s2 = *s; + s2++; + } + return(count); +} + +static int i_read_errno;/* place to save errno, if i_read() == -1, so it + doesn't get overwritten before we get to read it */ + +/*ARGSUSED*/ +static void +sigalarm_handler(n) +int n; /* signal number, unused by us */ +{ +#ifdef REARM_SIG + signal(SIGALRM,sigalarm_handler); +#endif + +#ifdef HAVE_SIGLONGJMP + siglongjmp(exp_readenv,1); +#else + longjmp(exp_readenv,1); +#endif /* HAVE_SIGLONGJMP */ +} + +/* interruptable read */ +static int +i_read(fd,fp,buffer,length,timeout) +int fd; +FILE *fp; +char *buffer; +int length; +int timeout; +{ + int cc = -2; + + /* since setjmp insists on returning 1 upon longjmp(,0), */ + /* longjmp(,2 (EXP_RESTART)) instead. */ + + /* no need to set alarm if -1 (infinite) or 0 (poll with */ + /* guaranteed data) */ + + if (timeout > 0) alarm(timeout); + + /* restart read if setjmp returns 0 (first time) or 2 (EXP_RESTART). */ + /* abort if setjmp returns 1 (EXP_ABORT). */ +#ifdef HAVE_SIGLONGJMP + if (EXP_ABORT != sigsetjmp(exp_readenv,1)) { +#else + if (EXP_ABORT != setjmp(exp_readenv)) { +#endif /* HAVE_SIGLONGJMP */ + exp_reading = TRUE; + if (fd == -1) { + int c; + c = getc(fp); + if (c == EOF) { +/*fprintf(stderr,"<<EOF>>",c);fflush(stderr);*/ + if (feof(fp)) cc = 0; + else cc = -1; + } else { +/*fprintf(stderr,"<<%c>>",c);fflush(stderr);*/ + buffer[0] = c; + cc = 1; + } + } else { +#ifndef HAVE_PTYTRAP + cc = read(fd,buffer,length); +#else +# include <sys/ptyio.h> + + fd_set rdrs; + fd_set excep; + + restart: + FD_ZERO(&rdrs); + FD_ZERO(&excep); + FD_SET(fd,&rdrs); + FD_SET(fd,&excep); + if (-1 == (cc = select(fd+1, + (SELECT_MASK_TYPE *)&rdrs, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)&excep, + (struct timeval *)0))) { + /* window refreshes trigger EINTR, ignore */ + if (errno == EINTR) goto restart; + } + if (FD_ISSET(fd,&rdrs)) { + cc = read(fd,buffer,length); + } else if (FD_ISSET(fd,&excep)) { + struct request_info ioctl_info; + ioctl(fd,TIOCREQCHECK,&ioctl_info); + if (ioctl_info.request == TIOCCLOSE) { + cc = 0; /* indicate eof */ + } else { + ioctl(fd, TIOCREQSET, &ioctl_info); + /* presumably, we trapped an open here */ + goto restart; + } + } +#endif /* HAVE_PTYTRAP */ + } +#if 0 + /* can't get fread to return early! */ + else { + if (!(cc = fread(buffer,1,length,fp))) { + if (ferror(fp)) cc = -1; + } + } +#endif + i_read_errno = errno; /* errno can be overwritten by the */ + /* time we return */ + } + exp_reading = FALSE; + + if (timeout > 0) alarm(0); + return(cc); +} + +/* I tried really hard to make the following two functions share the code */ +/* that makes the ecase array, but I kept running into a brick wall when */ +/* passing var args into the funcs and then again into a make_cases func */ +/* I would very much appreciate it if someone showed me how to do it right */ + +/* takes triplets of args, with a final "exp_last" arg */ +/* triplets are type, pattern, and then int to return */ +/* returns negative value if error (or EOF/timeout) occurs */ +/* some negative values can also have an associated errno */ + +/* the key internal variables that this function depends on are: + exp_buffer + exp_buffer_end + exp_match_end +*/ +static int +expectv(fd,fp,ecases) +int fd; +FILE *fp; +struct exp_case *ecases; +{ + int cc = 0; /* number of chars returned in a single read */ + int buf_length; /* numbers of chars in exp_buffer */ + int old_length; /* old buf_length */ + int first_time = TRUE; /* force old buffer to be tested before */ + /* additional reads */ + int polled = 0; /* true if poll has caused read() to occur */ + + struct exp_case *ec; /* points to current ecase */ + + time_t current_time; /* current time (when we last looked)*/ + time_t end_time; /* future time at which to give up */ + int remtime; /* remaining time in timeout */ + + struct f *f; + int return_val; + int sys_error = 0; +#define return_normally(x) {return_val = x; goto cleanup;} +#define return_errno(x) {sys_error = x; goto cleanup;} + + f = fdfp2f(fd,fp); + if (!f) return_errno(ENOMEM); + + exp_buffer = f->buffer; + exp_buffer_end = f->buffer_end; + exp_match_end = f->match_end; + + buf_length = exp_buffer_end - exp_match_end; + if (buf_length) { + /* + * take end of previous match to end of buffer + * and copy to beginning of buffer + */ + memmove(exp_buffer,exp_match_end,buf_length); + } + exp_buffer_end = exp_buffer + buf_length; + *exp_buffer_end = '\0'; + + if (!ecases) return_errno(EINVAL); + + /* compile if necessary */ + for (ec=ecases;ec->type != exp_end;ec++) { + if ((ec->type == exp_regexp) && !ec->re) { + TclRegError((char *)0); + if (!(ec->re = TclRegComp(ec->pattern))) { + fprintf(stderr,"regular expression %s is bad: %s",ec->pattern,TclGetRegError()); + return_errno(EINVAL); + } + } + } + + /* get the latest buffer size. Double the user input for two */ + /* reasons. 1) Need twice the space in case the match */ + /* straddles two bufferfuls, 2) easier to hack the division by */ + /* two when shifting the buffers later on */ + + bufsiz = 2*exp_match_max; + if (f->msize != bufsiz) { + /* if truncated, forget about some data */ + if (buf_length > bufsiz) { + /* copy end of buffer down */ + + /* copy one less than what buffer can hold to avoid */ + /* triggering buffer-full handling code below */ + /* which will immediately dump the first half */ + /* of the buffer */ + memmove(exp_buffer,exp_buffer+(buf_length - bufsiz)+1, + bufsiz-1); + buf_length = bufsiz-1; + } + exp_buffer = realloc(exp_buffer,bufsiz+1); + if (!exp_buffer) return_errno(ENOMEM); + exp_buffer[buf_length] = '\0'; + exp_buffer_end = exp_buffer + buf_length; + f->msize = bufsiz; + } + + /* some systems (i.e., Solaris) require fp be flushed when switching */ + /* directions - do this again afterwards */ + if (fd == -1) fflush(fp); + + if (exp_timeout != -1) signal(SIGALRM,sigalarm_handler); + + /* remtime and current_time updated at bottom of loop */ + remtime = exp_timeout; + + time(¤t_time); + end_time = current_time + remtime; + + for (;;) { + /* when buffer fills, copy second half over first and */ + /* continue, so we can do matches over multiple buffers */ + if (buf_length == bufsiz) { + int first_half, second_half; + + if (exp_full_buffer) { + exp_debuglog("expect: full buffer\r\n"); + exp_match = exp_buffer; + exp_match_end = exp_buffer + buf_length; + exp_buffer_end = exp_match_end; + return_normally(EXP_FULLBUFFER); + } + first_half = bufsiz/2; + second_half = bufsiz - first_half; + + memcpy(exp_buffer,exp_buffer+first_half,second_half); + buf_length = second_half; + exp_buffer_end = exp_buffer + second_half; + } + + /* + * always check first if pattern is already in buffer + */ + if (first_time) { + first_time = FALSE; + goto after_read; + } + + /* + * check for timeout + * we should timeout if either + * 1) exp_timeout > remtime <= 0 (normal) + * 2) exp_timeout == 0 and we have polled at least once + * + */ + if (((exp_timeout > remtime) && (remtime <= 0)) || + ((exp_timeout == 0) && polled)) { + exp_debuglog("expect: timeout\r\n"); + exp_match_end = exp_buffer; + return_normally(EXP_TIMEOUT); + } + + /* remember that we have actually checked at least once */ + polled = 1; + + cc = i_read(fd,fp, + exp_buffer_end, + bufsiz - buf_length, + remtime); + + if (cc == 0) { + exp_debuglog("expect: eof\r\n"); + return_normally(EXP_EOF); /* normal EOF */ + } else if (cc == -1) { /* abnormal EOF */ + /* ptys produce EIO upon EOF - sigh */ + if (i_read_errno == EIO) { + /* convert to EOF indication */ + exp_debuglog("expect: eof\r\n"); + return_normally(EXP_EOF); + } + exp_debuglog("expect: error (errno = %d)\r\n",i_read_errno); + return_errno(i_read_errno); + } else if (cc == -2) { + exp_debuglog("expect: timeout\r\n"); + exp_match_end = exp_buffer; + return_normally(EXP_TIMEOUT); + } + + old_length = buf_length; + buf_length += cc; + exp_buffer_end += buf_length; + + if (exp_logfile_all || (exp_loguser && exp_logfile)) { + fwrite(exp_buffer + old_length,1,cc,exp_logfile); + } + if (exp_loguser) fwrite(exp_buffer + old_length,1,cc,stdout); + if (exp_debugfile) fwrite(exp_buffer + old_length,1,cc,exp_debugfile); + + /* if we wrote to any logs, flush them */ + if (exp_debugfile) fflush(exp_debugfile); + if (exp_loguser) { + fflush(stdout); + if (exp_logfile) fflush(exp_logfile); + } + + /* remove nulls from input, so we can use C-style strings */ + /* doing it here lets them be sent to the screen, just */ + /* in case they are involved in formatting operations */ + if (exp_remove_nulls) { + buf_length -= rm_nulls(exp_buffer + old_length, cc); + } + /* cc should be decremented as well, but since it will not */ + /* be used before being set again, there is no need */ + exp_buffer_end = exp_buffer + buf_length; + *exp_buffer_end = '\0'; + exp_match_end = exp_buffer; + + after_read: + exp_debuglog("expect: does {%s} match ",exp_printify(exp_buffer)); + /* pattern supplied */ + for (ec=ecases;ec->type != exp_end;ec++) { + int matched = -1; + + exp_debuglog("{%s}? ",exp_printify(ec->pattern)); + if (ec->type == exp_glob) { + int offset; + matched = Exp_StringMatch(exp_buffer,ec->pattern,&offset); + if (matched >= 0) { + exp_match = exp_buffer + offset; + exp_match_end = exp_match + matched; + } + } else if (ec->type == exp_exact) { + char *p = strstr(exp_buffer,ec->pattern); + if (p) { + matched = 1; + exp_match = p; + exp_match_end = p + strlen(ec->pattern); + } + } else if (ec->type == exp_null) { + char *p; + + for (p=exp_buffer;p<exp_buffer_end;p++) { + if (*p == 0) { + matched = 1; + exp_match = p; + exp_match_end = p+1; + } + } + } else { + TclRegError((char *)0); + if (TclRegExec(ec->re,exp_buffer,exp_buffer)) { + matched = 1; + exp_match = ec->re->startp[0]; + exp_match_end = ec->re->endp[0]; + } else if (TclGetRegError()) { + fprintf(stderr,"r.e. match (pattern %s) failed: %s",ec->pattern,TclGetRegError()); + } + } + + if (matched != -1) { + exp_debuglog("yes\nexp_buffer is {%s}\n", + exp_printify(exp_buffer)); + return_normally(ec->value); + } else exp_debuglog("no\n"); + } + + /* + * Update current time and remaining time. + * Don't bother if we are waiting forever or polling. + */ + if (exp_timeout > 0) { + time(¤t_time); + remtime = end_time - current_time; + } + } + cleanup: + f->buffer = exp_buffer; + f->buffer_end = exp_buffer_end; + f->match_end = exp_match_end; + + /* some systems (i.e., Solaris) require fp be flushed when switching */ + /* directions - do this before as well */ + if (fd == -1) fflush(fp); + + if (sys_error) { + errno = sys_error; + return -1; + } + return return_val; +} + +int +exp_fexpectv(fp,ecases) +FILE *fp; +struct exp_case *ecases; +{ + return(expectv(-1,fp,ecases)); +} + +int +exp_expectv(fd,ecases) +int fd; +struct exp_case *ecases; +{ + return(expectv(fd,(FILE *)0,ecases)); +} + +/*VARARGS*/ +int +exp_expectl TCL_VARARGS_DEF(int,arg1) +/*exp_expectl(va_alist)*/ +/*va_dcl*/ +{ + va_list args; + int fd; + struct exp_case *ec, *ecases; + int i; + enum exp_type type; + + fd = TCL_VARARGS_START(int,arg1,args); + /* va_start(args);*/ + /* fd = va_arg(args,int);*/ + /* first just count the arg sets */ + for (i=0;;i++) { + type = va_arg(args,enum exp_type); + if (type == exp_end) break; + + /* Ultrix 4.2 compiler refuses enumerations comparison!? */ + if ((int)type < 0 || (int)type >= (int)exp_bogus) { + fprintf(stderr,"bad type (set %d) in exp_expectl\n",i); + sysreturn(EINVAL); + } + + va_arg(args,char *); /* COMPUTED BUT NOT USED */ + if (type == exp_compiled) { + va_arg(args,regexp *); /* COMPUTED BUT NOT USED */ + } + va_arg(args,int); /* COMPUTED BUT NOT USED*/ + } + va_end(args); + + if (!(ecases = (struct exp_case *) + malloc((1+i)*sizeof(struct exp_case)))) + sysreturn(ENOMEM); + + /* now set up the actual cases */ + fd = TCL_VARARGS_START(int,arg1,args); + /*va_start(args);*/ + /*va_arg(args,int);*/ /*COMPUTED BUT NOT USED*/ + for (ec=ecases;;ec++) { + ec->type = va_arg(args,enum exp_type); + if (ec->type == exp_end) break; + ec->pattern = va_arg(args,char *); + if (ec->type == exp_compiled) { + ec->re = va_arg(args,regexp *); + } else { + ec->re = 0; + } + ec->value = va_arg(args,int); + } + va_end(args); + i = expectv(fd,(FILE *)0,ecases); + + for (ec=ecases;ec->type != exp_end;ec++) { + /* free only if regexp and we compiled it for user */ + if (ec->type == exp_regexp) { + free((char *)ec->re); + } + } + free((char *)ecases); + return(i); +} + +int +exp_fexpectl TCL_VARARGS_DEF(FILE *,arg1) +/*exp_fexpectl(va_alist)*/ +/*va_dcl*/ +{ + va_list args; + FILE *fp; + struct exp_case *ec, *ecases; + int i; + enum exp_type type; + + fp = TCL_VARARGS_START(FILE *,arg1,args); + /*va_start(args);*/ + /*fp = va_arg(args,FILE *);*/ + /* first just count the arg-pairs */ + for (i=0;;i++) { + type = va_arg(args,enum exp_type); + if (type == exp_end) break; + + /* Ultrix 4.2 compiler refuses enumerations comparison!? */ + if ((int)type < 0 || (int)type >= (int)exp_bogus) { + fprintf(stderr,"bad type (set %d) in exp_expectl\n",i); + sysreturn(EINVAL); + } + + va_arg(args,char *); /* COMPUTED BUT NOT USED */ + if (type == exp_compiled) { + va_arg(args,regexp *); /* COMPUTED BUT NOT USED */ + } + va_arg(args,int); /* COMPUTED BUT NOT USED*/ + } + va_end(args); + + if (!(ecases = (struct exp_case *) + malloc((1+i)*sizeof(struct exp_case)))) + sysreturn(ENOMEM); + +#if 0 + va_start(args); + va_arg(args,FILE *); /*COMPUTED, BUT NOT USED*/ +#endif + (void) TCL_VARARGS_START(FILE *,arg1,args); + + for (ec=ecases;;ec++) { + ec->type = va_arg(args,enum exp_type); + if (ec->type == exp_end) break; + ec->pattern = va_arg(args,char *); + if (ec->type == exp_compiled) { + ec->re = va_arg(args,regexp *); + } else { + ec->re = 0; + } + ec->value = va_arg(args,int); + } + va_end(args); + i = expectv(-1,fp,ecases); + + for (ec=ecases;ec->type != exp_end;ec++) { + /* free only if regexp and we compiled it for user */ + if (ec->type == exp_regexp) { + free((char *)ec->re); + } + } + free((char *)ecases); + return(i); +} + +/* like popen(3) but works in both directions */ +FILE * +exp_popen(program) +char *program; +{ + FILE *fp; + int ec; + + if (0 > (ec = exp_spawnl("sh","sh","-c",program,(char *)0))) return(0); + if (!(fp = fdopen(ec,"r+"))) return(0); + setbuf(fp,(char *)0); + return(fp); +} + +int +exp_disconnect() +{ + int ttyfd; + +#ifndef EALREADY +#define EALREADY 37 +#endif + + /* presumably, no stderr, so don't bother with error message */ + if (exp_disconnected) sysreturn(EALREADY); + exp_disconnected = TRUE; + + freopen("/dev/null","r",stdin); + freopen("/dev/null","w",stdout); + freopen("/dev/null","w",stderr); + +#ifdef POSIX + setsid(); +#else +#ifdef SYSV3 + /* put process in our own pgrp, and lose controlling terminal */ + exp_setpgrp(); + signal(SIGHUP,SIG_IGN); + if (fork()) exit(0); /* first child exits (as per Stevens, */ + /* UNIX Network Programming, p. 79-80) */ + /* second child process continues as daemon */ +#else /* !SYSV3 */ + exp_setpgrp(); +/* Pyramid lacks this defn */ +#ifdef TIOCNOTTY + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd >= 0) { + /* zap controlling terminal if we had one */ + (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); + (void) close(ttyfd); + } +#endif /* TIOCNOTTY */ +#endif /* SYSV3 */ +#endif /* POSIX */ + return(0); +} + +/* send to log if open and debugging enabled */ +/* send to stderr if debugging enabled */ +/* use this function for recording unusual things in the log */ +/*VARARGS*/ +void +exp_debuglog TCL_VARARGS_DEF(char *,arg1) +{ + char *fmt; + va_list args; + + fmt = TCL_VARARGS_START(char *,arg1,args); + if (exp_debugfile) vfprintf(exp_debugfile,fmt,args); + if (exp_is_debugging) { + vfprintf(stderr,fmt,args); + if (exp_logfile) vfprintf(exp_logfile,fmt,args); + } + + va_end(args); +} + + +/* send to log if open */ +/* send to stderr */ +/* use this function for error conditions */ +/*VARARGS*/ +void +exp_errorlog TCL_VARARGS_DEF(char *,arg1) +{ + char *fmt; + va_list args; + + fmt = TCL_VARARGS_START(char *,arg1,args); + vfprintf(stderr,fmt,args); + if (exp_debugfile) vfprintf(exp_debugfile,fmt,args); + if (exp_logfile) vfprintf(exp_logfile,fmt,args); + va_end(args); +} + +#include <ctype.h> + +char * +exp_printify(s) +char *s; +{ + static int destlen = 0; + static char *dest = 0; + char *d; /* ptr into dest */ + unsigned int need; + + if (s == 0) return("<null>"); + + /* worst case is every character takes 4 to printify */ + need = strlen(s)*4 + 1; + if (need > destlen) { + if (dest) ckfree(dest); + dest = ckalloc(need); + destlen = need; + } + + for (d = dest;*s;s++) { + if (*s == '\r') { + strcpy(d,"\\r"); d += 2; + } else if (*s == '\n') { + strcpy(d,"\\n"); d += 2; + } else if (*s == '\t') { + strcpy(d,"\\t"); d += 2; + } else if (isascii(*s) && isprint(*s)) { + *d = *s; d += 1; + } else { + sprintf(d,"\\x%02x",*s & 0xff); d += 4; + } + } + *d = '\0'; + return(dest); +} diff --git a/exp_closetcl.c b/exp_closetcl.c new file mode 100644 index 0000000..911e040 --- /dev/null +++ b/exp_closetcl.c @@ -0,0 +1,16 @@ +#if OBSOLETE +/* exp_closetcl.c - close tcl files */ + +/* isolated in it's own file since it has hooks into Tcl and exp_clib user */ +/* might like to avoid dragging it in */ + +#include "expect_cf.h" + +void (*exp_close_in_child)() = 0; + +void +exp_close_tcl_files() { + /* I don't believe this function is used any longer, at least in + the Expect program.*/ +} +#endif /* OBSOLETE */ diff --git a/exp_command.c b/exp_command.c new file mode 100644 index 0000000..b554b18 --- /dev/null +++ b/exp_command.c @@ -0,0 +1,3587 @@ +/* exp_command.c - the bulk of the Expect commands + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" + +#include <stdio.h> +#include <sys/types.h> +/*#include <sys/time.h> seems to not be present on SVR3 systems */ +/* and it's not used anyway as far as I can tell */ + +/* AIX insists that stropts.h be included before ioctl.h, because both */ +/* define _IO but only ioctl.h checks first. Oddly, they seem to be */ +/* defined differently! */ +#ifdef HAVE_STROPTS_H +# include <sys/stropts.h> +#endif +#include <sys/ioctl.h> + +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif +#include <sys/file.h> + +#include <errno.h> +#include <signal.h> + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#ifdef HAVE_PTYTRAP +#include <sys/ptyio.h> +#endif + +#ifdef CRAY +# ifndef TCSETCTTY +# if defined(HAVE_TERMIOS) +# include <termios.h> +# else +# include <termio.h> +# endif +# endif +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <math.h> /* for log/pow computation in send -h */ +#include <ctype.h> /* all this for ispunct! */ + +#include "tclInt.h" /* need OpenFile */ +/*#include <varargs.h> tclInt.h drags in varargs.h. Since Pyramid */ +/* objects to including varargs.h twice, just */ +/* omit this one. */ + +#include "tcl.h" +#include "string.h" +#include "expect.h" +#include "expect_tcl.h" +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" +#include "exp_event.h" +#include "exp_pty.h" +#include "exp_tty_in.h" +#ifdef TCL_DEBUGGER +#include "tcldbg.h" +#endif + +/* + * These constants refer to the UTF string that encodes a null character. + */ + +#define NULL_STRING "\300\200" /* hex C080 */ +#define NULL_LENGTH 2 + +#define SPAWN_ID_VARNAME "spawn_id" + +void exp_ecmd_remove_state_direct_and_indirect(Tcl_Interp *interp, ExpState *esPtr); + + +int exp_forked = FALSE; /* whether we are child process */ + +/* the following are use to create reserved addresses, to be used as ClientData */ +/* args to be used to tell commands how they were called. */ +/* The actual values won't be used, only the addresses, but I give them */ +/* values out of my irrational fear the compiler might collapse them all. */ +static int sendCD_error = 2; /* called as send_error */ +static int sendCD_user = 3; /* called as send_user */ +static int sendCD_proc = 4; /* called as send or send_spawn */ +static int sendCD_tty = 6; /* called as send_tty */ + +/* + * expect_key is just a source for generating a unique stamp. As each + * expect/interact command begins, it generates a new key and marks all + * the spawn ids of interest with it. Then, if someone comes along and + * marks them with yet a newer key, the old command will recognize this + * reexamine the state of the spawned process. + */ +int expect_key = 0; + +/* + * exp_configure_count is incremented whenever a spawned process is closed + * or an indirect list is modified. This forces any (stack of) expect or + * interact commands to reexamine the state of the world and adjust + * accordingly. + */ +int exp_configure_count = 0; + +#ifdef HAVE_PTYTRAP +/* slaveNames provides a mapping from the pty slave names to our */ +/* spawn id entry. This is needed only on HPs for stty, sigh. */ +static Tcl_HashTable slaveNames; +#endif /* HAVE_PTYTRAP */ + +typedef struct ThreadSpecificData { + /* + * List of all exp channels currently open. This is per thread and is + * used to match up fd's to channels, which rarely occurs. + */ + + ExpState *stdinout; + ExpState *stderrX; /* grr....stderr is a macro */ + ExpState *devtty; + ExpState *any; /* for any_spawn_id */ + + Tcl_Channel *diagChannel; /* Unused - exp_log.c has its own. */ + Tcl_DString diagDString; /* Unused */ + int diagEnabled; /* Unused */ + + /* Table of structures for all Tcl channels used as -open argument + * in a exp_spawn call. For refCounting of Tcl channels used by + * more than one Expect channel. + */ + + Tcl_HashTable origins; + +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +#ifdef FULLTRAPS +static void +init_traps(RETSIGTYPE (*traps[])()) +{ + int i; + + for (i=1;i<NSIG;i++) { + traps[i] = SIG_ERR; + } +} +#endif + +/* Do not terminate format strings with \n!!! */ +/*VARARGS*/ +void +exp_error TCL_VARARGS_DEF(Tcl_Interp *,arg1) +/*exp_error(va_alist)*/ +/*va_dcl*/ +{ + Tcl_Interp *interp; + char *fmt; + va_list args; + char buffer[2000]; + + interp = TCL_VARARGS_START(Tcl_Interp *,arg1,args); + fmt = va_arg(args,char *); + vsprintf(buffer,fmt,args); + Tcl_SetResult(interp,buffer,TCL_VOLATILE); + va_end(args); +} + +/* returns current ExpState or 0. If 0, may be immediately followed by return TCL_ERROR. */ +struct ExpState * +expStateCurrent( + Tcl_Interp *interp, + int opened, + int adjust, + int any) +{ + static char *user_spawn_id = "exp0"; + + char *name = exp_get_var(interp,SPAWN_ID_VARNAME); + if (!name) name = user_spawn_id; + + return expStateFromChannelName(interp,name,opened,adjust,any,SPAWN_ID_VARNAME); +} + +ExpState * +expStateCheck( + Tcl_Interp *interp, + ExpState *esPtr, + int open, + int adjust, + char *msg) +{ + if (open && !esPtr->open) { + exp_error(interp,"%s: spawn id %s not open",msg,esPtr->name); + return(0); + } + if (adjust) expAdjust(esPtr); + return esPtr; +} + +ExpState * +expStateFromChannelName( + Tcl_Interp *interp, + char *name, + int open, + int adjust, + int any, + char *msg) +{ + ExpState *esPtr; + Tcl_Channel channel; + CONST char *chanName; + + if (any) { + if (0 == strcmp(name,EXP_SPAWN_ID_ANY_LIT)) { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->any; + } + } + + channel = Tcl_GetChannel(interp,name,(int *)0); + if (!channel) return(0); + + chanName = Tcl_GetChannelName(channel); + if (!isExpChannelName(chanName)) { + exp_error(interp,"%s: %s is not an expect channel - use spawn -open to convert",msg,chanName); + return(0); + } + + esPtr = (ExpState *)Tcl_GetChannelInstanceData(channel); + + return expStateCheck(interp,esPtr,open,adjust,msg); +} + +/* zero out the wait status field */ +static void +exp_wait_zero(WAIT_STATUS_TYPE *status) +{ + int i; + + for (i=0;i<sizeof(WAIT_STATUS_TYPE);i++) { + ((char *)status)[i] = 0; + } +} + +/* called just before an ExpState entry is about to be invalidated */ +void +exp_state_prep_for_invalidation( + Tcl_Interp *interp, + ExpState *esPtr) +{ + exp_ecmd_remove_state_direct_and_indirect(interp,esPtr); + + exp_configure_count++; + + if (esPtr->fg_armed) { + exp_event_disarm_fg(esPtr); + } +} + +/*ARGSUSED*/ +void +exp_trap_on(int master) +{ +#ifdef HAVE_PTYTRAP + if (master == -1) return; + exp_slave_control(master,1); +#endif /* HAVE_PTYTRAP */ +} + +int +exp_trap_off(char *name) +{ +#ifdef HAVE_PTYTRAP + ExpState *esPtr; + int enable = 0; + + Tcl_HashEntry *entry = Tcl_FindHashEntry(&slaveNames,name); + if (!entry) { + expDiagLog("exp_trap_off: no entry found for %s\n",name); + return -1; + } + + esPtr = (ExpState *)Tcl_GetHashValue(entry); + + exp_slave_control(esPtr->fdin,0); + + return esPtr->fdin; +#else + return name[0]; /* pacify lint, use arg and return something */ +#endif +} + +static +void +expBusy(ExpState *esPtr) +{ + int x = open("/dev/null",0); + if (x != esPtr->fdin) { + fcntl(x,F_DUPFD,esPtr->fdin); + close(x); + } + expCloseOnExec(esPtr->fdin); + esPtr->fdBusy = TRUE; +} + +int +exp_close( + Tcl_Interp *interp, + ExpState *esPtr) +{ + if (0 == expStateCheck(interp,esPtr,1,0,"close")) return TCL_ERROR; + esPtr->open = FALSE; + + /* restore blocking for some shells that would otherwise be */ + /* surprised finding stdio or /dev/tty nonblocking */ + (void) Tcl_SetChannelOption(interp,esPtr->channel,"-blocking","on"); + + /* Since we're closing the channel, not Tcl, we need to get Tcl's + buffers flushed. Because the channel was nonblocking, EAGAINs + could leave things buffered. They need to be synchronously + written now! */ + Tcl_Flush(esPtr->channel); + + /* + * Ignore close errors from ptys. Ptys on some systems return errors for + * no evident reason. Anyway, receiving an error upon pty-close doesn't + * mean anything anyway as far as I know. + */ + + close(esPtr->fdin); + if (esPtr->fd_slave != EXP_NOFD) close(esPtr->fd_slave); + if (esPtr->fdin != esPtr->fdout) close(esPtr->fdout); + + if (esPtr->chan_orig) { + esPtr->chan_orig->refCount --; + if (esPtr->chan_orig->refCount <= 0) { + /* + * Ignore close errors from Tcl channels. They indicate things + * like broken pipelines, etc, which don't affect our + * subsequent handling. + */ + + ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey); + char* cName = Tcl_GetChannelName(esPtr->chan_orig->channel_orig); + Tcl_HashEntry* entry = Tcl_FindHashEntry(&tsdPtr->origins,cName); + ExpOrigin* orig = (ExpOrigin*) Tcl_GetHashValue(entry); + + Tcl_DeleteHashEntry(entry); + ckfree ((char*)orig); + + if (!esPtr->leaveopen) { + Tcl_VarEval(interp,"close ", cName, (char *)0); + } + } + } + +#ifdef HAVE_PTYTRAP + if (esPtr->slave_name) { + Tcl_HashEntry *entry; + + entry = Tcl_FindHashEntry(&slaveNames,esPtr->slave_name); + Tcl_DeleteHashEntry(entry); + + ckfree(esPtr->slave_name); + esPtr->slave_name = 0; + } +#endif + + exp_state_prep_for_invalidation(interp,esPtr); + + if (esPtr->user_waited) { + if (esPtr->registered) { + Tcl_UnregisterChannel(interp,esPtr->channel); + /* at this point esPtr may have been freed so don't touch it + any longer */ + } + } else { + expBusy(esPtr); + } + + return(TCL_OK); +} + +/* report whether this ExpState represents special spawn_id_any */ +/* we need a separate function because spawn_id_any is thread-specific */ +/* and can't be seen outside this file */ +int +expStateAnyIs(ExpState *esPtr) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return (esPtr == tsdPtr->any); +} + +int +expDevttyIs(ExpState *esPtr) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return (esPtr == tsdPtr->devtty); +} + +int +expStdinoutIs(ExpState *esPtr) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return (tsdPtr->stdinout == esPtr); +} + +ExpState * +expStdinoutGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return tsdPtr->stdinout; +} + +ExpState * +expDevttyGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return tsdPtr->devtty; +} + +void +exp_init_spawn_id_vars(Tcl_Interp *interp) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_SetVar(interp, "user_spawn_id", tsdPtr->stdinout->name,0); + Tcl_SetVar(interp,"error_spawn_id", tsdPtr->stderrX->name,0); + Tcl_SetVar(interp, "any_spawn_id", EXP_SPAWN_ID_ANY_LIT,0); + + /* user_spawn_id is NOT /dev/tty which could (at least in theory + * anyway) be later re-opened on a different fd, while stdin might + * have been redirected away from /dev/tty + */ + + if (exp_dev_tty != -1) { + Tcl_SetVar(interp,"tty_spawn_id",tsdPtr->devtty->name,0); + } +} + +void +exp_init_spawn_ids(Tcl_Interp *interp) +{ + static ExpState any_placeholder; /* can be shared process-wide */ + + /* note whether 0,1,2 are connected to a terminal so that if we */ + /* disconnect, we can shut these down. We would really like to */ + /* test if 0,1,2 are our controlling tty, but I don't know any */ + /* way to do that portably. Anyway, the likelihood of anyone */ + /* disconnecting after redirecting to a non-controlling tty is */ + /* virtually zero. */ + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tsdPtr->stdinout = expCreateChannel(interp,0,1,isatty(0)?exp_getpid:EXP_NOPID); + tsdPtr->stdinout->keepForever = 1; + /* hmm, now here's an example of a output-only descriptor!! */ + tsdPtr->stderrX = expCreateChannel(interp,2,2,isatty(2)?exp_getpid:EXP_NOPID); + tsdPtr->stderrX->keepForever = 1; + + if (exp_dev_tty != -1) { + tsdPtr->devtty = expCreateChannel(interp,exp_dev_tty,exp_dev_tty,exp_getpid); + tsdPtr->devtty->keepForever = 1; + } + + /* set up a dummy channel to give us something when we need to find out if + people have passed us "any_spawn_id" */ + tsdPtr->any = &any_placeholder; + + /* Set up the hash table for managing the channels used via + * -open. + */ + + Tcl_InitHashTable (&tsdPtr->origins, TCL_STRING_KEYS); +} + +void +expCloseOnExec(int fd) +{ + (void) fcntl(fd,F_SETFD,1); +} + +#define STTY_INIT "stty_init" + +#if 0 +/* + * DEBUGGING UTILITIES - DON'T DELETE */ +static void +show_pgrp( + int fd, + char *string) +{ + int pgrp; + + fprintf(stderr,"getting pgrp for %s\n",string); + if (-1 == ioctl(fd,TIOCGETPGRP,&pgrp)) perror("TIOCGETPGRP"); + else fprintf(stderr,"%s pgrp = %d\n",string,pgrp); + if (-1 == ioctl(fd,TIOCGPGRP,&pgrp)) perror("TIOCGPGRP"); + else fprintf(stderr,"%s pgrp = %d\n",string,pgrp); + if (-1 == tcgetpgrp(fd,pgrp)) perror("tcgetpgrp"); + else fprintf(stderr,"%s pgrp = %d\n",string,pgrp); +} + +static void +set_pgrp(int fd) +{ + int pgrp = getpgrp(0); + if (-1 == ioctl(fd,TIOCSETPGRP,&pgrp)) perror("TIOCSETPGRP"); + if (-1 == ioctl(fd,TIOCSPGRP,&pgrp)) perror("TIOCSPGRP"); + if (-1 == tcsetpgrp(fd,pgrp)) perror("tcsetpgrp"); +} +#endif + +static +void +expSetpgrp() +{ +#ifdef MIPS_BSD + /* required on BSD side of MIPS OS <jmsellen@watdragon.waterloo.edu> */ +# include <sysv/sys.s> + syscall(SYS_setpgrp); +#endif + +#ifdef SETPGRP_VOID + (void) setpgrp(); +#else + (void) setpgrp(0,0); +#endif +} + + +/*ARGSUSED*/ +static void +set_slave_name( + ExpState *esPtr, + char *name) +{ +#ifdef HAVE_PTYTRAP + int newptr; + Tcl_HashEntry *entry; + + /* save slave name */ + esPtr->slave_name = ckalloc(strlen(exp_pty_slave_name)+1); + strcpy(esPtr->slave_name,exp_pty_slave_name); + + entry = Tcl_CreateHashEntry(&slaveNames,exp_pty_slave_name,&newptr); + Tcl_SetHashValue(entry,(ClientData)esPtr); +#endif /* HAVE_PTYTRAP */ +} + +/* arguments are passed verbatim to execvp() */ +/*ARGSUSED*/ +static int +Exp_SpawnObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + ExpState *esPtr = 0; + int slave; + int pid; +#ifdef TIOCNOTTY + /* tell Saber to ignore non-use of ttyfd */ + /*SUPPRESS 591*/ + int ttyfd; +#endif /* TIOCNOTTY */ + int errorfd; /* place to stash fileno(stderr) in child */ + /* while we're setting up new stderr */ + int master, k; + int write_master; /* write fd of Tcl-opened files */ + int ttyinit = TRUE; + int ttycopy = TRUE; + int echo = TRUE; + int console = FALSE; + int pty_only = FALSE; + char** argv; + +#ifdef FULLTRAPS + /* Allow user to reset signals in child */ + /* The following array contains indicates */ + /* whether sig should be DFL or IGN */ + /* ERR is used to indicate no initialization */ + RETSIGTYPE (*traps[NSIG])(); +#endif + int ignore[NSIG]; /* if true, signal in child is ignored */ + /* if false, signal gets default behavior */ + int i; /* trusty overused temporary */ + + char *argv0 = Tcl_GetString (objv[0]); + char *chanName = 0; + int leaveopen = FALSE; + int rc, wc; + CONST char *stty_init; + int slave_write_ioctls = 1; + /* by default, slave will be write-ioctled this many times */ + int slave_opens = 3; + /* by default, slave will be opened this many times */ + /* first comes from initial allocation */ + /* second comes from stty */ + /* third is our own signal that stty is done */ + + int sync_fds[2]; + int sync2_fds[2]; + int status_pipe[2]; + int child_errno; + char sync_byte; + int cmdIndex; + Tcl_Obj* cmdObj; + char* command; + + static char* options[] = { + "-console", + "-ignore", + "-leaveopen", + "-noecho", + "-nottycopy", + "-nottyinit", + "-open", + "-pty", +#ifdef FULLTRAPS + "-trap", +#endif + NULL + }; + enum options { + SPAWN_CONSOLE + ,SPAWN_IGNORE + ,SPAWN_LEAVEOPEN + ,SPAWN_NOECHO + ,SPAWN_NOTTYCOPY + ,SPAWN_NOTTYINIT + ,SPAWN_OPEN + ,SPAWN_PTY +#ifdef FULLTRAPS + ,SPAWN_TRAP +#endif + }; + + Tcl_Channel channel; + Tcl_DString dstring; + Tcl_DStringInit(&dstring); + +#ifdef FULLTRAPS + init_traps(&traps); +#endif + /* don't ignore any signals in child by default */ + for (i=1;i<NSIG;i++) { + ignore[i] = FALSE; + } + + /* Check and process switches */ + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case SPAWN_NOTTYINIT: + ttyinit = FALSE; + slave_write_ioctls--; + slave_opens--; + break; + case SPAWN_NOTTYCOPY: + ttycopy = FALSE; + break; + case SPAWN_NOECHO: + echo = FALSE; + break; + case SPAWN_CONSOLE: + console = TRUE; + break; + case SPAWN_PTY: + pty_only = TRUE; + break; + case SPAWN_OPEN: + i ++; + if (i >= objc) { + exp_error(interp,"usage: -open file-identifier"); + return TCL_ERROR; + } + chanName = Tcl_GetString (objv[i]); + break; + case SPAWN_LEAVEOPEN: + i ++; + if (i >= objc) { + exp_error(interp,"usage: -open file-identifier"); + return TCL_ERROR; + } + chanName = Tcl_GetString (objv[i]); + leaveopen = TRUE; + break; + case SPAWN_IGNORE: { + int sig; + i ++; + if (i >= objc) { + exp_error(interp,"usage: -ignore signal"); + return TCL_ERROR; + } + sig = exp_string_to_signal(interp,Tcl_GetString (objv[i])); + if (sig == -1) { + exp_error(interp,"usage: -ignore %s: unknown signal name",Tcl_GetString (objv[i])); + return TCL_ERROR; + } + ignore[sig] = TRUE; + } + break; +#ifdef FULLTRAPS + case SPAWN_TRAP: { + /* objv[i+1] is list of signals */ + /* objv[i+2] is action */ + + static char* actions [] = { + "SIG_DFL", "SIG_IGN", NULL + }; + enum actions { + ACTION_SIGDFL, ACTION_SIGIGN; + } + int theaction; + + int j; + RETSIGTYPE (*sig_handler)(); + int lc; /* number of signals in list */ + Tcl_Obj** lv; /* list of signals */ + + if ((objc - i) < 3) { + exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN"); + return TCL_ERROR; + } + + /* Check and process action */ + + if (Tcl_GetIndexFromObj(interp, objv[i+2], actions, "action", 0, + &theaction) != TCL_OK) { + exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN"); + return TCL_ERROR; + } + switch ((enum actions) theaction) { + case ACTION_SIGDFL: + sig_handler = SIG_DFL; + break; + case ACTION_SIGIGN: + sig_handler = SIG_IGN; + break; + } + + /* Check and process list of signals */ + + if (TCL_OK != Tcl_ListObjGetElements (inter, objv[i+1], &lc, &lv)) { + expErrorLogU(Tcl_GetStringResult(interp)); + expErrorLogU("\r\n"); + exp_error(interp,"usage: -trap {siglist} ..."); + return TCL_ERROR; + } + + for (j=0;j<lc;j++) { + int sig = exp_string_to_signal(interp,Tcl_GetString (lv[j])); + if (sig == -1) { + return TCL_ERROR; + } + traps[sig] = sig_handler; + } + + i += 2; + } + break; +#endif + } + } + + /* Additional checking of arguments */ + + if (chanName && (i < objc)) { + exp_error(interp,"usage: -[leave]open [fileXX]"); + return TCL_ERROR; + } + + if (!pty_only && !chanName && (i == objc)) { + exp_error(interp,"usage: spawn [spawn-args] program [program-args]"); + return(TCL_ERROR); + } + + cmdIndex = i; + cmdObj = objv[i]; + + stty_init = exp_get_var(interp,STTY_INIT); + if (stty_init) { + slave_write_ioctls++; + slave_opens++; + } + +/* any extraneous ioctl's that occur in slave must be accounted for + when trapping, see below in child half of fork */ +#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300) + slave_write_ioctls++; + slave_opens++; +#endif + + exp_pty_slave_name = 0; + + Tcl_ReapDetachedProcs(); + + if (!chanName) { + if (echo) { + int c = 0; + expStdoutLogU(argv0,0); + for (c = 1; c < objc; c++) { + expStdoutLogU(" ",0); + expStdoutLogU(Tcl_GetString (objv[c]),0); + } + expStdoutLogU("\r\n",0); + } + + if (0 > (master = exp_getptymaster())) { + /* + * failed to allocate pty, try and figure out why + * so we can suggest to user what to do about it. + */ + + int testfd; + + if (exp_pty_error) { + exp_error(interp,"%s",exp_pty_error); + return TCL_ERROR; + } + + if (expChannelCountGet() > 10) { + exp_error(interp,"The system only has a finite number of ptys and you have many of them in use. The usual reason for this is that you forgot (or didn't know) to call \"wait\" after closing each of them."); + return TCL_ERROR; + } + + testfd = open("/",0); + close(testfd); + + if (testfd != -1) { + exp_error(interp,"The system has no more ptys. Ask your system administrator to create more."); + } else { + exp_error(interp,"- You have too many files are open. Close some files or increase your per-process descriptor limit."); + } + return(TCL_ERROR); + } + + /* ordinarily channel creation takes care of close-on-exec + * but because that will occur *after* fork, force close-on-exec + * now in this case. + */ + expCloseOnExec(master); + +#define SPAWN_OUT "spawn_out" + Tcl_SetVar2(interp,SPAWN_OUT,"slave,name",exp_pty_slave_name,0); + + if (pty_only) { + write_master = master; + } + } else { + /* + * process "-open $channel" + */ + int mode, rfd, wfd; + ClientData rfdc, wfdc; + + if (echo) { + expStdoutLogU(argv0,0); + expStdoutLogU(" [open ...]\r\n",0); + } + if (!(channel = Tcl_GetChannel(interp,chanName,&mode))) { + return TCL_ERROR; + } + if (!mode) { + exp_error(interp,"channel is neither readable nor writable"); + return TCL_ERROR; + } + if (mode & TCL_READABLE) { + if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_READABLE, &rfdc)) { + return TCL_ERROR; + } + rfd = (int)(long) rfdc; + } + if (mode & TCL_WRITABLE) { + if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_WRITABLE, &wfdc)) { + return TCL_ERROR; + } + wfd = (int)(long) wfdc; + } + master = ((mode & TCL_READABLE)?rfd:wfd); + + /* make a new copy of file descriptor */ + if (-1 == (write_master = master = dup(master))) { + exp_error(interp,"fdopen: %s",Tcl_PosixError(interp)); + return TCL_ERROR; + } + + /* if writefilePtr is different, dup that too */ + if ((mode & TCL_READABLE) && (mode & TCL_WRITABLE) && (wfd != rfd)) { + if (-1 == (write_master = dup(wfd))) { + exp_error(interp,"fdopen: %s",Tcl_PosixError(interp)); + return TCL_ERROR; + } + } + + /* + * It would be convenient now to tell Tcl to close its + * file descriptor. Alas, if involved in a pipeline, Tcl + * will be unable to complete a wait on the process. + * So simply remember that we meant to close it. We will + * do so later in our own close routine. + */ + } + + if (chanName || pty_only) { + esPtr = expCreateChannel(interp,master,write_master,EXP_NOPID); + + if (chanName) { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_HashEntry *entry = Tcl_FindHashEntry(&tsdPtr->origins,chanName); + + if (entry) { + esPtr->chan_orig = (ExpOrigin*) Tcl_GetHashValue(entry); + esPtr->chan_orig->refCount ++; + + } else { + int newptr; + ExpOrigin* orig = (ExpOrigin*) ckalloc (sizeof (ExpOrigin)); + + esPtr->chan_orig = orig; + orig->channel_orig = channel; + orig->refCount = 1; + + entry = Tcl_CreateHashEntry(&tsdPtr->origins,chanName,&newptr); + Tcl_SetHashValue(entry, (ClientData) orig); + } + + esPtr->leaveopen = leaveopen; + } + + if (exp_pty_slave_name) set_slave_name(esPtr,exp_pty_slave_name); + + /* make it appear as if process has been waited for */ + esPtr->sys_waited = TRUE; + exp_wait_zero(&esPtr->wait); + + /* tell user of new spawn id */ + Tcl_SetVar(interp,SPAWN_ID_VARNAME,esPtr->name,0); + + if (!chanName) { + char value[20]; + + /* + * open the slave side in the same process to support + * the -pty flag. + */ + + if (0 > (esPtr->fd_slave = exp_getptyslave(ttycopy,ttyinit, + stty_init))) { + exp_error(interp,"open(slave pty): %s\r\n",Tcl_PosixError(interp)); + return TCL_ERROR; + } + + exp_slave_control(master,1); + + sprintf(value,"%d",esPtr->fd_slave); + Tcl_SetVar2(interp,SPAWN_OUT,"slave,fd",value,0); + } + Tcl_SetObjResult (interp, Tcl_NewIntObj (EXP_NOPID)); + expDiagLog("spawn: returns {%s}\r\n",Tcl_GetStringResult(interp)); + + return TCL_OK; + } + + command = Tcl_TranslateFileName(interp,Tcl_GetString (cmdObj),&dstring); + if (NULL == command) { + goto parent_error; + } + + if (-1 == pipe(sync_fds)) { + exp_error(interp,"too many programs spawned? could not create pipe: %s",Tcl_PosixError(interp)); + goto parent_error; + } + + if (-1 == pipe(sync2_fds)) { + close(sync_fds[0]); + close(sync_fds[1]); + exp_error(interp,"too many programs spawned? could not create pipe: %s",Tcl_PosixError(interp)); + goto parent_error; + } + + if (-1 == pipe(status_pipe)) { + close(sync_fds[0]); + close(sync_fds[1]); + close(sync2_fds[0]); + close(sync2_fds[1]); + exp_error(interp,"too many programs spawned? could not create pipe: %s",Tcl_PosixError(interp)); + goto parent_error; + } + + if ((pid = fork()) == -1) { + exp_error(interp,"fork: %s",Tcl_PosixError(interp)); + goto parent_error; + } + + if (pid) { /* parent */ + close(sync_fds[1]); + close(sync2_fds[0]); + close(status_pipe[1]); + + esPtr = expCreateChannel(interp,master,master,pid); + + if (exp_pty_slave_name) set_slave_name(esPtr,exp_pty_slave_name); + +#ifdef CRAY + setptypid(pid); +#endif + + /* + * wait for slave to initialize pty before allowing + * user to send to it + */ + + expDiagLog("parent: waiting for sync byte\r\n"); + while (((rc = read(sync_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) { + /* empty */; + } + if (rc == -1) { + expErrorLogU("parent: sync byte read: "); + expErrorLogU(Tcl_ErrnoMsg(errno)); + expErrorLogU("\r\n"); + exit(-1); + } + + /* turn on detection of eof */ + exp_slave_control(master,1); + + /* + * tell slave to go on now, now that we have initialized pty + */ + + expDiagLog("parent: telling child to go ahead\r\n"); + wc = write(sync2_fds[1]," ",1); + if (wc == -1) { + expErrorLog("parent: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + + expDiagLog("parent: now unsynchronized from child\r\n"); + close(sync_fds[0]); + close(sync2_fds[1]); + + /* see if child's exec worked */ + retry: + switch (read(status_pipe[0],&child_errno,sizeof child_errno)) { + case -1: + if (errno == EINTR) goto retry; + /* well it's not really the child's errno */ + /* but it can be treated that way */ + child_errno = errno; + break; + case 0: + /* child's exec succeeded */ + child_errno = 0; + break; + default: + /* child's exec failed; child_errno contains exec's errno */ + close(status_pipe[0]); + waitpid(pid, NULL, 0); + /* in order to get Tcl to set errorcode, we must */ + /* hand set errno */ + errno = child_errno; + exp_error(interp, "couldn't execute \"%s\": %s", + command,Tcl_PosixError(interp)); + goto parent_error; + } + close(status_pipe[0]); + + /* tell user of new spawn id */ + Tcl_SetVar(interp,SPAWN_ID_VARNAME,esPtr->name,0); + + Tcl_SetObjResult (interp, Tcl_NewIntObj (pid)); + expDiagLog("spawn: returns {%s}\r\n",Tcl_GetStringResult(interp)); + + Tcl_DStringFree(&dstring); + return(TCL_OK); + } + + /* child process - do not return from here! all errors must exit() */ + + close(sync_fds[0]); + close(sync2_fds[1]); + close(status_pipe[0]); + expCloseOnExec(status_pipe[1]); + + if (exp_dev_tty != -1) { + close(exp_dev_tty); + exp_dev_tty = -1; + } + +#ifdef CRAY + (void) close(master); +#endif + +/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */ +/* is called. setpgrp works though. */ +#if defined(POSIX) && !defined(ultrix) +#define DO_SETSID +#endif +#ifdef __convex__ +#define DO_SETSID +#endif + +#ifdef DO_SETSID + setsid(); +#else +#ifdef SYSV3 +#ifndef CRAY + expSetpgrp(); +#endif /* CRAY */ +#else /* !SYSV3 */ + expSetpgrp(); + +/* Pyramid lacks this defn */ +#ifdef TIOCNOTTY + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd >= 0) { + (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); + (void) close(ttyfd); + } +#endif /* TIOCNOTTY */ + +#endif /* SYSV3 */ +#endif /* DO_SETSID */ + + /* save stderr elsewhere to avoid BSD4.4 bogosity that warns */ + /* if stty finds dev(stderr) != dev(stdout) */ + + /* save error fd while we're setting up new one */ + errorfd = fcntl(2,F_DUPFD,3); + /* and here is the macro to restore it */ +#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);} + + close(0); + close(1); + close(2); + + /* since we closed fd 0, open of pty slave must return fd 0 */ + + /* since exp_getptyslave may have to run stty, (some of which work on fd */ + /* 0 and some of which work on 1) do the dup's inside exp_getptyslave. */ + + if (0 > (slave = exp_getptyslave(ttycopy,ttyinit,stty_init))) { + restore_error_fd + + if (exp_pty_error) { + expErrorLog("open(slave pty): %s\r\n",exp_pty_error); + } else { + expErrorLog("open(slave pty): %s\r\n",Tcl_ErrnoMsg(errno)); + } + exit(-1); + } + /* sanity check */ + if (slave != 0) { + restore_error_fd + expErrorLog("exp_getptyslave: slave = %d but expected 0\n",slave); + exit(-1); + } + +/* The test for hpux may have to be more specific. In particular, the */ +/* code should be skipped on the hp9000s300 and hp9000s720 (but there */ +/* is no documented define for the 720!) */ + +/*#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hpux)*/ +#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux) + /* 4.3+BSD way to acquire controlling terminal */ + /* according to Stevens - Adv. Prog..., p 642 */ + /* Oops, it appears that the CIBAUD is on Linux also */ + /* so let's try without... */ +#ifdef __QNX__ + if (tcsetct(0, getpid()) == -1) { + restore_error_fd + expErrorLog("failed to get controlling terminal using TIOCSCTTY"); + exit(-1); + } +#else + (void) ioctl(0,TIOCSCTTY,(char *)0); + /* ignore return value - on some systems, it is defined but it + * fails and it doesn't seem to cause any problems. Or maybe + * it works but returns a bogus code. Noone seems to be able + * to explain this to me. The systems are an assortment of + * different linux systems (and FreeBSD 2.5), RedHat 5.2 and + * Debian 2.0 + */ +#endif +#endif + +#ifdef CRAY + (void) setsid(); + (void) ioctl(0,TCSETCTTY,0); + (void) close(0); + if (open("/dev/tty", O_RDWR) < 0) { + restore_error_fd + expErrorLog("open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + (void) close(1); + (void) close(2); + (void) dup(0); + (void) dup(0); + setptyutmp(); /* create a utmp entry */ + + /* _CRAY2 code from Hal Peterson <hrp@cray.com>, Cray Research, Inc. */ +#ifdef _CRAY2 + /* + * Interpose a process between expect and the spawned child to + * keep the slave side of the pty open to allow time for expect + * to read the last output. This is a workaround for an apparent + * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at + * least). + */ + if ((pid = fork()) == -1) { + restore_error_fd + expErrorLog("second fork: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + + if (pid) { + /* Intermediate process. */ + int status; + int timeout; + char *t; + + /* How long should we wait? */ + if (t = exp_get_var(interp,"pty_timeout")) + timeout = atoi(t); + else if (t = exp_get_var(interp,"timeout")) + timeout = atoi(t)/2; + else + timeout = 5; + + /* Let the spawned process run to completion. */ + while (wait(&status) < 0 && errno == EINTR) + /* empty body */; + + /* Wait for the pty to clear. */ + sleep(timeout); + + /* Duplicate the spawned process's status. */ + if (WIFSIGNALED(status)) + kill(getpid(), WTERMSIG(status)); + + /* The kill may not have worked, but this will. */ + exit(WEXITSTATUS(status)); + } +#endif /* _CRAY2 */ +#endif /* CRAY */ + + if (console) exp_console_set(); + +#ifdef FULLTRAPS + for (i=1;i<NSIG;i++) { + if (traps[i] != SIG_ERR) { + signal(i,traps[i]); + } + } +#endif /* FULLTRAPS */ + + for (i=1;i<NSIG;i++) { + signal(i,ignore[i]?SIG_IGN:SIG_DFL); + } + + /* + * avoid fflush of cmdfile, logfile, & diagfile since this screws up + * the parents seek ptr. There is no portable way to fclose a shared + * read-stream!!!! + */ + + /* (possibly multiple) masters are closed automatically due to */ + /* earlier fcntl(,,CLOSE_ON_EXEC); */ + + /* tell parent that we are done setting up pty */ + /* The actual char sent back is irrelevant. */ + + /* expDiagLog("child: telling parent that pty is initialized\r\n");*/ + wc = write(sync_fds[1]," ",1); + if (wc == -1) { + restore_error_fd + expErrorLog("child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + close(sync_fds[1]); + + /* wait for master to let us go on */ + while (((rc = read(sync2_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) { + /* empty */; + } + + if (rc == -1) { + restore_error_fd + expErrorLog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno)); + exit(-1); + } + close(sync2_fds[0]); + + /* expDiagLog("child: now unsynchronized from parent\r\n"); */ + + argv = (char**) ckalloc ((objc+1)*sizeof(char*)); + for (k=0, i=cmdIndex;i<objc;k++,i++) { + argv[k] = ckalloc (1+strlen(Tcl_GetString (objv[i]))); + strcpy (argv[k],Tcl_GetString (objv[i])); + } + argv[k] = NULL; + + execvp(command,argv); + + for (k=0,i=cmdIndex;i<objc;k++,i++) { + ckfree (argv[k]); + } + ckfree((char*)argv); + + /* Alas, by now we've closed fd's to stderr, logfile and diagfile. + * The only reasonable thing to do is to send back the error as part of + * the program output. This will be picked up in an expect or interact + * command. + */ + + /* if exec failed, communicate the reason back to the parent */ + write(status_pipe[1], &errno, sizeof errno); + exit(-1); + /*NOTREACHED*/ + parent_error: + Tcl_DStringFree(&dstring); + if (esPtr) { + exp_close(interp,esPtr); + waitpid(esPtr->pid,(int *)&esPtr->wait,0); + if (esPtr->registered) { + Tcl_UnregisterChannel(interp,esPtr->channel); + } + } + return TCL_ERROR; +} + +/*ARGSUSED*/ +static int +Exp_ExpPidObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + char *chanName = 0; + ExpState *esPtr = 0; + + static char* options[] = { "-i", NULL }; + enum options { PID_ID }; + int i; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case PID_ID: + i++; + if (i >= objc) goto usage; + chanName = Tcl_GetString (objv[i]); + break; + } + } + + if (chanName) { + esPtr = expStateFromChannelName(interp,chanName,0,0,0,"exp_pid"); + } else { + esPtr = expStateCurrent(interp,0,0,0); + } + if (!esPtr) return TCL_ERROR; + + Tcl_SetObjResult (interp, Tcl_NewIntObj (esPtr->pid)); + return TCL_OK; + usage: + exp_error(interp,"usage: -i spawn_id"); + return TCL_ERROR; +} + +/*ARGSUSED*/ +static int +Exp_GetpidDeprecatedObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + expDiagLog("getpid is deprecated, use pid\r\n"); + Tcl_SetObjResult (interp, Tcl_NewIntObj (getpid())); + return(TCL_OK); +} + +/*ARGSUSED*/ +static int +Exp_SleepObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + double s; + + if (objc != 2) { + exp_error(interp,"must have one arg: seconds"); + return TCL_ERROR; + } + + if (TCL_OK != Tcl_GetDoubleFromObj (interp, objv[1], &s)) { + if (0 == strlen (Tcl_GetString(objv[1]))) { + /* Keep undocumented acceptance of "" as 0 = no delay */ + return TCL_OK; + } + return TCL_ERROR; + } + + return exp_dsleep(interp,s); +} + +struct slow_arg { + int size; + double time; +}; + +/* returns 0 for success, -1 for failure */ +static int +get_slow_args( + Tcl_Interp *interp, + struct slow_arg *x) +{ + int sc; /* return from scanf */ + CONST char *s = exp_get_var(interp,"send_slow"); + if (!s) { + exp_error(interp,"send -s: send_slow has no value"); + return(-1); + } + if (2 != (sc = sscanf(s,"%d %lf",&x->size,&x->time))) { + exp_error(interp,"send -s: found %d value(s) in send_slow but need 2",sc); + return(-1); + } + if (x->size <= 0) { + exp_error(interp,"send -s: size (%d) in send_slow must be positive", x->size); + return(-1); + } + if (x->time <= 0) { + exp_error(interp,"send -s: time (%f) in send_slow must be larger",x->time); + return(-1); + } + return(0); +} + +/* returns 0 for success, -1 for failure, pos. for Tcl return value */ +static int +slow_write( + Tcl_Interp *interp, + ExpState *esPtr, + char *buffer, + int rembytes, + struct slow_arg *arg) +{ + int rc; + + while (rembytes > 0) { + int i, bytelen, charlen; + char *p; + + p = buffer; + charlen = (arg->size<rembytes?arg->size:rembytes); + + /* count out the right number of UTF8 chars */ + for (i=0;i<charlen;i++) { + p = Tcl_UtfNext(p); + } + bytelen = p-buffer; + + if (0 > expWriteChars(esPtr,buffer,bytelen)) { return(-1); } + rembytes -= bytelen; + buffer += bytelen; + + /* skip sleep after last write */ + if (rembytes > 0) { + rc = exp_dsleep(interp,arg->time); + if (rc>0) return rc; + } + } + return(0); +} + +struct human_arg { + float alpha; /* average interarrival time in seconds */ + float alpha_eow; /* as above but for eow transitions */ + float c; /* shape */ + float min, max; +}; + +/* returns -1 if error, 0 if success */ +static int +get_human_args( + Tcl_Interp *interp, + struct human_arg *x) +{ + int sc; /* return from scanf */ + CONST char *s = exp_get_var(interp,"send_human"); + + if (!s) { + exp_error(interp,"send -h: send_human has no value"); + return(-1); + } + if (5 != (sc = sscanf(s,"%f %f %f %f %f", + &x->alpha,&x->alpha_eow,&x->c,&x->min,&x->max))) { + if (sc == EOF) sc = 0; /* make up for overloaded return */ + exp_error(interp,"send -h: found %d value(s) in send_human but need 5",sc); + return(-1); + } + if (x->alpha < 0 || x->alpha_eow < 0) { + exp_error(interp,"send -h: average interarrival times (%f %f) must be non-negative in send_human", x->alpha,x->alpha_eow); + return(-1); + } + if (x->c <= 0) { + exp_error(interp,"send -h: variability (%f) in send_human must be positive",x->c); + return(-1); + } + x->c = 1/x->c; + + if (x->min < 0) { + exp_error(interp,"send -h: minimum (%f) in send_human must be non-negative",x->min); + return(-1); + } + if (x->max < 0) { + exp_error(interp,"send -h: maximum (%f) in send_human must be non-negative",x->max); + return(-1); + } + if (x->max < x->min) { + exp_error(interp,"send -h: maximum (%f) must be >= minimum (%f) in send_human",x->max,x->min); + return(-1); + } + return(0); +} + +/* Compute random numbers from 0 to 1, for expect's send -h */ +/* This implementation sacrifices beauty for portability */ +static float +unit_random() +{ + /* current implementation is pathetic but works */ + /* 99991 is largest prime in my CRC - can't hurt, eh? */ + return((float)(1+(rand()%99991))/99991.0); +} + +void +exp_init_unit_random() +{ + srand(getpid()); +} + +/* This function is my implementation of the Weibull distribution. */ +/* I've added a max time and an "alpha_eow" that captures the slight */ +/* but noticable change in human typists when hitting end-of-word */ +/* transitions. */ +/* returns 0 for success, -1 for failure, pos. for Tcl return value */ +static int +human_write( + Tcl_Interp *interp, + ExpState *esPtr, + char *buffer, + struct human_arg *arg) +{ + char *sp; + int size; + float t; + float alpha; + int wc; + int in_word = TRUE; + Tcl_UniChar ch; + + expDiagLog("human_write: avg_arr=%f/%f 1/shape=%f min=%f max=%f\r\n", + arg->alpha,arg->alpha_eow,arg->c,arg->min,arg->max); + + for (sp = buffer;*sp;sp += size) { + size = Tcl_UtfToUniChar(sp, &ch); + /* use the end-of-word alpha at eow transitions */ + if (in_word && (Tcl_UniCharIsPunct(ch) || Tcl_UniCharIsSpace(ch))) + alpha = arg->alpha_eow; + else alpha = arg->alpha; + in_word = !(Tcl_UniCharIsPunct(ch) || Tcl_UniCharIsSpace(ch)); + + t = alpha * pow(-log((double)unit_random()),arg->c); + + /* enforce min and max times */ + if (t<arg->min) t = arg->min; + else if (t>arg->max) t = arg->max; + + /* skip sleep before writing first character */ + if (sp != buffer) { + wc = exp_dsleep(interp,(double)t); + if (wc > 0) return wc; + } + + wc = expWriteChars(esPtr, sp, size); + if (0 > wc) return(wc); + } + return(0); +} + +struct exp_i *exp_i_pool = 0; +struct exp_state_list *exp_state_list_pool = 0; + +#define EXP_I_INIT_COUNT 10 +#define EXP_FD_INIT_COUNT 10 + +struct exp_i * +exp_new_i() +{ + int n; + struct exp_i *i; + + if (!exp_i_pool) { + /* none avail, generate some new ones */ + exp_i_pool = i = (struct exp_i *)ckalloc( + EXP_I_INIT_COUNT * sizeof(struct exp_i)); + for (n=0;n<EXP_I_INIT_COUNT-1;n++,i++) { + i->next = i+1; + } + i->next = 0; + } + + /* now that we've made some, unlink one and give to user */ + + i = exp_i_pool; + exp_i_pool = exp_i_pool->next; + i->value = 0; + i->variable = 0; + i->state_list = 0; + i->ecount = 0; + i->next = 0; + return i; +} + +struct exp_state_list * +exp_new_state(ExpState *esPtr) +{ + int n; + struct exp_state_list *fd; + + if (!exp_state_list_pool) { + /* none avail, generate some new ones */ + exp_state_list_pool = fd = (struct exp_state_list *)ckalloc( + EXP_FD_INIT_COUNT * sizeof(struct exp_state_list)); + for (n=0;n<EXP_FD_INIT_COUNT-1;n++,fd++) { + fd->next = fd+1; + } + fd->next = 0; + } + + /* now that we've made some, unlink one and give to user */ + + fd = exp_state_list_pool; + exp_state_list_pool = exp_state_list_pool->next; + fd->esPtr = esPtr; + /* fd->next is assumed to be changed by caller */ + return fd; +} + +void +exp_free_state(struct exp_state_list *fd_first) +{ + struct exp_state_list *fd, *penultimate; + + if (!fd_first) return; + + /* link entire chain back in at once by first finding last pointer */ + /* making that point back to pool, and then resetting pool to this */ + + /* run to end */ + for (fd = fd_first;fd;fd=fd->next) { + penultimate = fd; + } + penultimate->next = exp_state_list_pool; + exp_state_list_pool = fd_first; +} + +/* free a single fd */ +void +exp_free_state_single(struct exp_state_list *fd) +{ + fd->next = exp_state_list_pool; + exp_state_list_pool = fd; +} + +void +exp_free_i( + Tcl_Interp *interp, + struct exp_i *i, + Tcl_VarTraceProc *updateproc)/* proc to invoke if indirect is written */ +{ + if (i->next) exp_free_i(interp,i->next,updateproc); + + exp_free_state(i->state_list); + + if (i->direct == EXP_INDIRECT) { + Tcl_UntraceVar(interp,i->variable, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES, + updateproc, (ClientData)i); + } + + /* here's the long form + if duration & direct free(var) free(val) + PERM DIR 1 + PERM INDIR 1 1 + TMP DIR + TMP INDIR 1 + Also if i->variable was a bogus variable name, i->value might not be + set, so test i->value to protect this + TMP in this case does NOT mean from the "expect" command. Rather + it means "an implicit spawn id from any expect or expect_XXX + command". In other words, there was no variable name provided. + */ + if (i->value + && (((i->direct == EXP_DIRECT) && (i->duration == EXP_PERMANENT)) + || ((i->direct == EXP_INDIRECT) && (i->duration == EXP_TEMPORARY)))) { + ckfree(i->value); + } else if (i->duration == EXP_PERMANENT) { + if (i->value) ckfree(i->value); + if (i->variable) ckfree(i->variable); + } + + i->next = exp_i_pool; + exp_i_pool = i; +} + +/* generate a descriptor for a "-i" flag */ +/* can only fail on bad direct descriptors */ +/* indirect descriptors always succeed */ +struct exp_i * +exp_new_i_complex( + Tcl_Interp *interp, + char *arg, /* spawn id list or a variable containing a list */ + int duration, /* if we have to copy the args */ + /* should only need do this in expect_before/after */ + Tcl_VarTraceProc *updateproc) /* proc to invoke if indirect is written */ +{ + struct exp_i *i; + char **stringp; + + i = exp_new_i(); + + i->direct = (isExpChannelName(arg) || (0 == strcmp(arg, EXP_SPAWN_ID_ANY_LIT))?EXP_DIRECT:EXP_INDIRECT); +#if OBSOLETE + i->direct = (isdigit(arg[0]) || (arg[0] == '-'))?EXP_DIRECT:EXP_INDIRECT; +#endif + if (i->direct == EXP_DIRECT) { + stringp = &i->value; + } else { + stringp = &i->variable; + } + + i->duration = duration; + if (duration == EXP_PERMANENT) { + *stringp = ckalloc(strlen(arg)+1); + strcpy(*stringp,arg); + } else { + *stringp = arg; + } + + i->state_list = 0; + if (TCL_ERROR == exp_i_update(interp,i)) { + exp_free_i(interp,i,(Tcl_VarTraceProc *)0); + return 0; + } + + /* if indirect, ask Tcl to tell us when variable is modified */ + + if (i->direct == EXP_INDIRECT) { + Tcl_TraceVar(interp, i->variable, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES, + updateproc, (ClientData) i); + } + + return i; +} + +void +exp_i_add_state( + struct exp_i *i, + ExpState *esPtr) +{ + struct exp_state_list *new_state; + + new_state = exp_new_state(esPtr); + new_state->next = i->state_list; + i->state_list = new_state; +} + +/* this routine assumes i->esPtr is meaningful */ +/* returns TCL_ERROR only on direct */ +/* indirects always succeed */ +static int +exp_i_parse_states( + Tcl_Interp *interp, + struct exp_i *i) +{ + struct ExpState *esPtr; + char *p = i->value; + int argc; + char **argv; + int j; + + if (Tcl_SplitList(NULL, p, &argc, &argv) != TCL_OK) goto error; + + for (j = 0; j < argc; j++) { + esPtr = expStateFromChannelName(interp,argv[j],1,0,1,""); + if (!esPtr) goto error; + exp_i_add_state(i,esPtr); + } + ckfree((char*)argv); + return TCL_OK; + error: + expDiagLogU("exp_i_parse_states: "); + expDiagLogU(Tcl_GetStringResult(interp)); + return TCL_ERROR; +} + +/* updates a single exp_i struct */ +/* return TCL_ERROR only on direct variables */ +/* indirect variables always succeed */ +int +exp_i_update( + Tcl_Interp *interp, + struct exp_i *i) +{ + char *p; /* string representation of list of spawn ids */ + + if (i->direct == EXP_INDIRECT) { + p = Tcl_GetVar(interp,i->variable,TCL_GLOBAL_ONLY); + if (!p) { + p = ""; + /* *really* big variable names could blow up expDiagLog! */ + expDiagLog("warning: indirect variable %s undefined",i->variable); + } + + if (i->value) { + if (streq(p,i->value)) return TCL_OK; + + /* replace new value with old */ + ckfree(i->value); + } + i->value = ckalloc(strlen(p)+1); + strcpy(i->value,p); + + exp_free_state(i->state_list); + i->state_list = 0; + } else { + /* no free, because this should only be called on */ + /* "direct" i's once */ + i->state_list = 0; + } + return exp_i_parse_states(interp, i); +} + +struct exp_i * +exp_new_i_simple( + ExpState *esPtr, + int duration) /* if we have to copy the args */ + /* should only need do this in expect_before/after */ +{ + struct exp_i *i; + + i = exp_new_i(); + + i->direct = EXP_DIRECT; + i->duration = duration; + + exp_i_add_state(i,esPtr); + + return i; +} + +/*ARGSUSED*/ +static int +Exp_SendLogObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + static char* options[] = { "--", NULL }; + enum options { LOG_QUOTE }; + int i; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + if (((enum options) index) == LOG_QUOTE) { + i++; + break; + } + } + + if (i != (objc-1)) goto usage; + + expLogDiagU(Tcl_GetString (objv[i])); + return(TCL_OK); + + usage: + exp_error(interp,"usage: send [args] string"); + return TCL_ERROR; +} + + +/* I've rewritten this to be unbuffered. I did this so you could shove */ +/* large files through "send". If you are concerned about efficiency */ +/* you should quote all your send args to make them one single argument. */ +/*ARGSUSED*/ +static int +Exp_SendObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ExpState *esPtr = 0; + int rc; /* final result of this procedure */ + struct human_arg human_args; + struct slow_arg slow_args; +#define SEND_STYLE_STRING_MASK 0x07 /* mask to detect a real string arg */ +#define SEND_STYLE_PLAIN 0x01 +#define SEND_STYLE_HUMAN 0x02 +#define SEND_STYLE_SLOW 0x04 +#define SEND_STYLE_ZERO 0x10 +#define SEND_STYLE_BREAK 0x20 + int send_style = SEND_STYLE_PLAIN; + int want_cooked = TRUE; + char *string; /* string to send */ + int len = -1; /* length of string to send */ + int zeros; /* count of how many ascii zeros to send */ + + char *chanName = 0; + struct exp_state_list *state_list; + struct exp_i *i; + int j; + + static char *options[] = { + "-i", "-h", "-s", "-null", "-0", "-raw", "-break", "--", (char *)0 + }; + enum options { + SEND_SPAWNID, SEND_HUMAN, SEND_SLOW, SEND_NULL, SEND_ZERO, + SEND_RAW, SEND_BREAK, SEND_LAST + }; + + for (j = 1; j < objc; j++) { + char *name; + int index; + + name = Tcl_GetString(objv[j]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[j], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case SEND_SPAWNID: + j++; + chanName = Tcl_GetString(objv[j]); + break; + + case SEND_LAST: + j++; + goto getString; + + case SEND_HUMAN: + if (-1 == get_human_args(interp,&human_args)) + return(TCL_ERROR); + send_style = SEND_STYLE_HUMAN; + break; + + case SEND_SLOW: + if (-1 == get_slow_args(interp,&slow_args)) + return(TCL_ERROR); + send_style = SEND_STYLE_SLOW; + break; + + case SEND_NULL: + case SEND_ZERO: + j++; + if (j >= objc) { + zeros = 1; + } else if (Tcl_GetIntFromObj(interp, objv[j], &zeros) + != TCL_OK) { + return TCL_ERROR; + } + if (zeros < 1) return TCL_OK; + send_style = SEND_STYLE_ZERO; + string = "<zero(s)>"; + break; + + case SEND_RAW: + want_cooked = FALSE; + break; + + case SEND_BREAK: + send_style = SEND_STYLE_BREAK; + string = "<break>"; + break; + } + } + + if (send_style & SEND_STYLE_STRING_MASK) { + getString: + if (j != objc-1) { + exp_error(interp,"usage: send [args] string"); + return TCL_ERROR; + } + string = Tcl_GetStringFromObj(objv[j], &len); + } else { + len = strlen(string); + } + + if (clientData == &sendCD_user) esPtr = tsdPtr->stdinout; + else if (clientData == &sendCD_error) esPtr = tsdPtr->stderrX; + else if (clientData == &sendCD_tty) { + esPtr = tsdPtr->devtty; + if (!esPtr) { + exp_error(interp,"send_tty: cannot send to controlling terminal in an environment when there is no controlling terminal to send to!"); + return TCL_ERROR; + } + } else if (!chanName) { + /* we want to check if it is open */ + /* but since stdin could be closed, we have to first */ + /* get the fd and then convert it from 0 to 1 if necessary */ + if (!(esPtr = expStateCurrent(interp,0,0,0))) return(TCL_ERROR); + } + + if (esPtr) { + i = exp_new_i_simple(esPtr,EXP_TEMPORARY); + } else { + i = exp_new_i_complex(interp,chanName,FALSE,(Tcl_VarTraceProc *)0); + if (!i) return TCL_ERROR; + } + +#define send_to_stderr (clientData == &sendCD_error) +#define send_to_proc (clientData == &sendCD_proc) +#define send_to_user ((clientData == &sendCD_user) || \ + (clientData == &sendCD_tty)) + + if (send_to_proc) { + want_cooked = FALSE; + expDiagLogU("send: sending \""); + expDiagLogU(expPrintify(string)); + expDiagLogU("\" to {"); + /* if closing brace doesn't appear, that's because an error */ + /* was encountered before we could send it */ + } else { + expLogDiagU(string); + } + + for (state_list=i->state_list;state_list;state_list=state_list->next) { + esPtr = state_list->esPtr; + + if (send_to_proc) { + expDiagLog(" %s ",esPtr->name); + } + + /* check validity of each - i.e., are they open */ + if (0 == expStateCheck(interp,esPtr,1,0,"send")) { + rc = TCL_ERROR; + goto finish; + } + if (want_cooked) string = exp_cook(string,&len); + + switch (send_style) { + case SEND_STYLE_PLAIN: + rc = expWriteChars(esPtr,string,len); + break; + case SEND_STYLE_SLOW: + rc = slow_write(interp,esPtr,string,len,&slow_args); + break; + case SEND_STYLE_HUMAN: + rc = human_write(interp,esPtr,string,&human_args); + break; + case SEND_STYLE_ZERO: + for (;zeros>0;zeros--) { + rc = expWriteChars(esPtr,NULL_STRING,NULL_LENGTH); + } + /* catching error on last write is sufficient */ + break; + case SEND_STYLE_BREAK: + exp_tty_break(interp,esPtr->fdout); + rc = 0; + break; + } + + if (rc != 0) { + if (rc == -1) { + exp_error(interp,"write(spawn_id=%d): %s",esPtr->fdout,Tcl_PosixError(interp)); + rc = TCL_ERROR; + } + goto finish; + } + } + if (send_to_proc) expDiagLogU("}\r\n"); + + rc = TCL_OK; + finish: + exp_free_i(interp,i,(Tcl_VarTraceProc *)0); + return rc; +} + +/*ARGSUSED*/ +static int +Exp_LogFileObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + static char resultbuf[1000]; + char *chanName = 0; + int leaveOpen = FALSE; + int logAll = FALSE; + int append = TRUE; + char *filename = 0; + int i; + + static char* options[] = { + "-a", + "-info", + "-leaveopen", + "-noappend", + "-open", + NULL + }; + enum options { + LOGFILE_A, + LOGFILE_INFO, + LOGFILE_LEAVEOPEN, + LOGFILE_NOAPPEND, + LOGFILE_OPEN + }; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case LOGFILE_A: + logAll = TRUE; + break; + case LOGFILE_INFO: + resultbuf[0] = '\0'; + if (expLogChannelGet()) { + /* FUTURE: Use List-ops to construct a proper Tcl_Obj */ + if (expLogAllGet()) strcat(resultbuf,"-a "); + if (!expLogAppendGet()) strcat(resultbuf,"-noappend "); + if (expLogFilenameGet()) { + strcat(resultbuf,expLogFilenameGet()); + } else { + if (expLogLeaveOpenGet()) { + strcat(resultbuf,"-leaveopen "); + } + strcat(resultbuf,Tcl_GetChannelName(expLogChannelGet())); + } + Tcl_SetResult(interp,resultbuf,TCL_STATIC); + } + return TCL_OK; + case LOGFILE_LEAVEOPEN: + i ++; + if (i >= objc) goto usage_error; + chanName = Tcl_GetString (objv[i]); + leaveOpen = TRUE; + break; + case LOGFILE_NOAPPEND: + append = FALSE; + break; + case LOGFILE_OPEN: + i++; + if (i >= objc) goto usage_error; + chanName = Tcl_GetString (objv[i]); + break; + } + } + + if (i == (objc - 1)) { + filename = Tcl_GetString (objv[i]); + } else if (objc > i) { + /* too many arguments */ + goto usage_error; + } + + if (chanName && filename) { + goto usage_error; + } + + /* check if user merely wants to change logAll (-a) */ + if (expLogChannelGet() && (chanName || filename)) { + if (filename && (0 == strcmp(filename,expLogFilenameGet()))) { + expLogAllSet(logAll); + return TCL_OK; + } else if (chanName && + (0 == strcmp(chanName,Tcl_GetChannelName(expLogChannelGet())))) { + expLogAllSet(logAll); + return TCL_OK; + } else { + exp_error(interp,"cannot start logging without first stopping logging"); + return TCL_ERROR; + } + } + + if (filename) { + if (TCL_ERROR == expLogChannelOpen(interp,filename,append)) { + return TCL_ERROR; + } + } else if (chanName) { + if (TCL_ERROR == expLogChannelSet(interp,chanName)) { + return TCL_ERROR; + } + } else { + expLogChannelClose(interp); + if (logAll) { + exp_error(interp,"cannot use -a without a file or channel"); + return TCL_ERROR; + } + } + expLogAllSet(logAll); + expLogLeaveOpenSet(leaveOpen); + + return TCL_OK; + + usage_error: + exp_error(interp,"usage: log_file [-info] [-noappend] [[-a] file] [-[leave]open [open ...]]"); + return TCL_ERROR; +} + +/*ARGSUSED*/ +static int +Exp_LogUserObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int old_loguser = expLogUserGet(); + + if (objc == 0 || (objc == 2 && streq(Tcl_GetString (objv[1]),"-info"))) { + /* do nothing */ + } else if (objc == 2) { + int flag; + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[1], &flag)) { + if (0 == strlen (Tcl_GetString(objv[1]))) { + /* Keep undocumented acceptance of "" as 0. */ + flag = 0; + } else { + return TCL_ERROR; + } + } + expLogUserSet(flag); + } else { + exp_error(interp,"usage: [-info|1|0]"); + } + + Tcl_SetObjResult (interp, Tcl_NewIntObj (old_loguser)); + return(TCL_OK); +} + +#ifdef TCL_DEBUGGER +/*ARGSUSED*/ +static int +Exp_DebugObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int now = FALSE; /* soon if FALSE, now if TRUE */ + int exp_tcl_debugger_was_available = exp_tcl_debugger_available; + + static char* options[] = { "-now", NULL }; + enum options { DEBUG_NOW }; + int i; + + if (objc > 3) goto usage; + + if (objc == 1) { + Tcl_SetObjResult (interp, Tcl_NewIntObj (exp_tcl_debugger_available)); + return TCL_OK; + } + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case DEBUG_NOW: + now = TRUE; + break; + } + } + + if (i == objc) { + if (now) { + Dbg_On(interp,1); + exp_tcl_debugger_available = 1; + } else { + goto usage; + } + } else { + int flag; + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[i], &flag)) { + goto usage; + } + if (!flag) { + Dbg_Off(interp); + exp_tcl_debugger_available = 0; + } else { + Dbg_On(interp,now); + exp_tcl_debugger_available = 1; + } + } + Tcl_SetObjResult (interp, Tcl_NewBooleanObj (exp_tcl_debugger_was_available)); + return(TCL_OK); + usage: + exp_error(interp,"usage: [[-now] 1|0]"); + return TCL_ERROR; +} +#endif + + +/*ARGSUSED*/ +static int +Exp_ExpInternalObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int newChannel = FALSE; + Tcl_Channel oldChannel; + static char resultbuf[1000]; + int flag, i; + + static char* options[] = { + "-f", + "-info", + NULL + }; + enum options { + INTERNAL_F, + INTERNAL_INFO + }; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case INTERNAL_INFO: + /* FUTURE: Construct a proper list Tcl_Obj here */ + /* Should check that there are no arguments coming after -info */ + + resultbuf[0] = '\0'; + oldChannel = expDiagChannelGet(); + if (oldChannel) { + sprintf(resultbuf,"-f %s ",expDiagFilename()); + } + strcat(resultbuf,expDiagToStderrGet()?"1":"0"); + Tcl_SetResult(interp,resultbuf,TCL_STATIC); + return TCL_OK; + case INTERNAL_F: + i ++; + if (i >= objc) goto usage; + expDiagChannelClose(interp); + if (TCL_OK != expDiagChannelOpen(interp,Tcl_GetString (objv[i]))) { + return TCL_ERROR; + } + newChannel = TRUE; + break; + } + } + + if (i >= objc) goto usage; + + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[i], &flag)) { + goto usage; + } + + /* if no -f given, close file */ + if (!newChannel) { + expDiagChannelClose(interp); + } + + expDiagToStderrSet(flag); + return(TCL_OK); + usage: + exp_error(interp,"usage: [-f file] 0|1"); + return TCL_ERROR; +} + +char *exp_onexit_action = 0; + +/*ARGSUSED*/ +static int +Exp_ExitObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int value = 0; + + objc--; + objv++; + + if (objc) { + if (exp_flageq(Tcl_GetString (objv[0]),"-onexit",3)) { + objc--; + objv++; + if (objc) { + int len; + char* act = Tcl_GetStringFromObj (objv[0], &len); + + if (exp_onexit_action) + ckfree(exp_onexit_action); + + exp_onexit_action = ckalloc(len + 1); + strcpy(exp_onexit_action,act); + + } else if (exp_onexit_action) { + Tcl_AppendResult(interp,exp_onexit_action,(char *)0); + } + return TCL_OK; + } else if (exp_flageq(Tcl_GetString (objv[0]),"-noexit",3)) { + objc--; + objv++; + exp_exit_handlers((ClientData)interp); + return TCL_OK; + } + } + + if (objc) { + if (Tcl_GetIntFromObj(interp, objv[0], &value) != TCL_OK) { + return TCL_ERROR; + } + } + + /* + * Restore previous definition of close. Needed when expect is + * dynamically loaded after close has been redefined + * e.g. the virtual file system in tclkit + */ + Tcl_Eval(interp, "rename _close.pre_expect close"); + Tcl_Exit(value); + /*NOTREACHED*/ + return TCL_ERROR; +} + +/*ARGSUSED*/ +static int +Exp_ConfigureObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + /* Magic configuration stuff. */ + int i, opt, val; + + static CONST84 char* options [] = { + "-strictwrite", NULL + }; + enum options { + EXP_STRICTWRITE + }; + + if ((objc < 3) || (objc % 2 == 0)) { + Tcl_WrongNumArgs (interp, 1, objv, "-strictwrite value"); + return TCL_ERROR; + } + + for (i=1; i < objc; i+=2) { + if (Tcl_GetIndexFromObj (interp, objv [i], options, "option", + 0, &opt) != TCL_OK) { + return TCL_ERROR; + } + switch (opt) { + case EXP_STRICTWRITE: + if (Tcl_GetBooleanFromObj (interp, objv [i+1], &val) != TCL_OK) { + return TCL_ERROR; + } + exp_strict_write = val; + break; + } + } + + return TCL_OK; +} + +/*ARGSUSED*/ +static int +Exp_CloseObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int onexec_flag = FALSE; /* true if -onexec seen */ + int close_onexec; + int slave_flag = FALSE; + ExpState *esPtr = 0; + char *chanName = 0; + int i; + + static char* options[] = { + "-i", + "-onexec", + "-slave", + NULL + }; + enum options { + CLOSE_ID, + CLOSE_ONEXEC, + CLOSE_SLAVE + }; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case CLOSE_ID: + i++; + if (i == objc) { + exp_error(interp,"usage: -i spawn_id"); + return(TCL_ERROR); + } + chanName = Tcl_GetString(objv[i]); + break; + case CLOSE_ONEXEC: + i++; + if (i == objc) { + on_exec_usage: + exp_error(interp,"usage: -onexec 0|1"); + return(TCL_ERROR); + } + onexec_flag = TRUE; + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[i], &close_onexec)) { + goto on_exec_usage; + } + break; + case CLOSE_SLAVE: + slave_flag = TRUE; + break; + } + } + + if (i < objc) { + /* doesn't look like our format, it must be a Tcl-style file */ + /* handle. Lucky that formats are easily distinguishable. */ + /* Historical note: we used "close" long before there was a */ + /* Tcl builtin by the same name. */ + + Tcl_CmdInfo* close_info; + + Tcl_ResetResult(interp); + + close_info = (Tcl_CmdInfo*) Tcl_GetAssocData (interp, EXP_CMDINFO_CLOSE, NULL); + return(close_info->objProc(close_info->objClientData,interp,objc,objv)); + } + + if (chanName) { + esPtr = expStateFromChannelName(interp,chanName,1,0,0,"close"); + } else { + esPtr = expStateCurrent(interp,1,0,0); + } + if (!esPtr) return TCL_ERROR; + + if (slave_flag) { + if (esPtr->fd_slave != EXP_NOFD) { + close(esPtr->fd_slave); + esPtr->fd_slave = EXP_NOFD; + + exp_slave_control(esPtr->fdin,1); + + return TCL_OK; + } else { + exp_error(interp,"no such slave"); + return TCL_ERROR; + } + } + + if (onexec_flag) { + /* heck, don't even bother to check if fd is open or a real */ + /* spawn id, nothing else depends on it */ + fcntl(esPtr->fdin,F_SETFD,close_onexec); + return TCL_OK; + } + + return(exp_close(interp,esPtr)); +} + +/*ARGSUSED*/ +static int +tcl_tracer( + ClientData clientData, + Tcl_Interp *interp, + int level, + CONST char *command, + Tcl_Command cmdInfo, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int i; + + /* come out on stderr, by using expErrorLog */ + expErrorLog("%2d",level); + for (i = 0;i<level;i++) expErrorLogU(" "); + expErrorLogU((char*)command); + expErrorLogU("\r\n"); + return TCL_OK; +} + +static void +tcl_tracer_del(ClientData clientData) +{ + /* Nothing */ +} + +/*ARGSUSED*/ +static int +Exp_StraceObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + static int trace_level = 0; + static Tcl_Trace trace_handle; + + if (objc > 1 && streq(Tcl_GetString (objv[1]),"-info")) { + Tcl_SetObjResult (interp, Tcl_NewIntObj (trace_level)); + return TCL_OK; + } + + if (objc != 2) { + exp_error(interp,"usage: trace level"); + return(TCL_ERROR); + } + /* tracing already in effect, undo it */ + if (trace_level > 0) Tcl_DeleteTrace(interp,trace_handle); + + /* get and save new trace level */ + + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[1], &trace_level)) { + return TCL_ERROR; + } + + if (trace_level > 0) + trace_handle = Tcl_CreateObjTrace(interp, trace_level,0, + tcl_tracer,(ClientData)0, + tcl_tracer_del); + return(TCL_OK); +} + +/* following defn's are stolen from tclUnix.h */ + +/* + * The type of the status returned by wait varies from UNIX system + * to UNIX system. The macro below defines it: + */ + +#if 0 +#ifndef NO_UNION_WAIT +# define WAIT_STATUS_TYPE union wait +#else +# define WAIT_STATUS_TYPE int +#endif +#endif /* 0 */ + +/* + * following definitions stolen from tclUnix.h + * (should have been made public!) + + * Supply definitions for macros to query wait status, if not already + * defined in header files above. + */ + +#if 0 +#ifndef WIFEXITED +# define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0) +#endif + +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff) +#endif + +#ifndef WIFSIGNALED +# define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff))) +#endif + +#ifndef WTERMSIG +# define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f) +#endif + +#ifndef WIFSTOPPED +# define WIFSTOPPED(stat) (((*((int *) &(stat))) & 0xff) == 0177) +#endif + +#ifndef WSTOPSIG +# define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff) +#endif +#endif /* 0 */ + +/* end of stolen definitions */ + +/* Describe the processes created with Expect's fork. + This allows us to wait on them later. + + This is maintained as a linked list. As additional procs are forked, + new links are added. As procs disappear, links are marked so that we + can reuse them later. +*/ + +struct forked_proc { + int pid; + WAIT_STATUS_TYPE wait_status; + enum {not_in_use, wait_done, wait_not_done} link_status; + struct forked_proc *next; +} *forked_proc_base = 0; + +void +fork_clear_all() +{ + struct forked_proc *f; + + for (f=forked_proc_base;f;f=f->next) { + f->link_status = not_in_use; + } +} + +void +fork_init( + struct forked_proc *f, + int pid) +{ + f->pid = pid; + f->link_status = wait_not_done; +} + +/* make an entry for a new proc */ +void +fork_add(int pid) +{ + struct forked_proc *f; + + for (f=forked_proc_base;f;f=f->next) { + if (f->link_status == not_in_use) break; + } + + /* add new entry to the front of the list */ + if (!f) { + f = (struct forked_proc *)ckalloc(sizeof(struct forked_proc)); + f->next = forked_proc_base; + forked_proc_base = f; + } + fork_init(f,pid); +} + +/* Provide a last-chance guess for this if not defined already */ +#ifndef WNOHANG +#define WNOHANG WNOHANG_BACKUP_VALUE +#endif + +/* wait returns are a hodgepodge of things + If wait fails, something seriously has gone wrong, for example: + bogus arguments (i.e., incorrect, bogus spawn id) + no children to wait on + async event failed + If wait succeeeds, something happened on a particular pid + 3rd arg is 0 if successfully reaped (if signal, additional fields supplied) + 3rd arg is -1 if unsuccessfully reaped (additional fields supplied) +*/ +/*ARGSUSED*/ +static int +Exp_WaitObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + char *chanName = 0; + struct ExpState *esPtr; + struct forked_proc *fp = 0; /* handle to a pure forked proc */ + struct ExpState esTmp; /* temporary memory for either f or fp */ + char spawn_id[20]; + + int nowait = FALSE; + int result = 0; /* 0 means child was successfully waited on */ + /* -1 means an error occurred */ + /* -2 means no eligible children to wait on */ + + static char* options[] = { + "-i", + "-nowait", + NULL + }; + enum options { + WAIT_ID, + WAIT_NOWAIT + }; + int i; + +#define NO_CHILD (-2) + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case WAIT_ID: + i++; + if (i >= objc) goto usage; + chanName = Tcl_GetString (objv[i]); + break; + case WAIT_NOWAIT: + nowait = TRUE; + break; + } + } + + if (!chanName) { + esPtr = expStateCurrent(interp,0,0,1); + } else { + esPtr = expStateFromChannelName(interp,chanName,0,0,1,"wait"); + } + if (!esPtr) return TCL_ERROR; + + if (!expStateAnyIs(esPtr)) { + /* check if waited on already */ + /* things opened by "open" or set with -nowait */ + /* are marked sys_waited already */ + if (!esPtr->sys_waited) { + if (nowait) { + Tcl_Pid pid = (Tcl_Pid)(long)esPtr->pid; + /* should probably generate an error */ + /* if SIGCHLD is trapped. */ + + /* pass to Tcl, so it can do wait */ + /* in background */ + Tcl_DetachPids(1,&pid); + exp_wait_zero(&esPtr->wait); + } else { + while (1) { + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(rc); + } + + result = waitpid(esPtr->pid,(int *)&esPtr->wait,0); + if (result == esPtr->pid) break; + if (result == -1) { + if (errno == EINTR) continue; + else break; + } + } + } + } + + /* + * Now have Tcl reap anything we just detached. + * This also allows procs user has created with "exec &" + * and and associated with an "exec &" process to be reaped. + */ + + Tcl_ReapDetachedProcs(); + exp_rearm_sigchld(interp); /* new */ + + strcpy(spawn_id,esPtr->name); + } else { + /* wait for any of our own spawned processes */ + /* we call waitpid rather than wait to avoid running into */ + /* someone else's processes. Yes, according to Ousterhout */ + /* this is the best way to do it. */ + + int waited_on_forked_process = 0; + + esPtr = expWaitOnAny(); + if (!esPtr) { + /* if it's not a spawned process, maybe its a forked process */ + for (fp=forked_proc_base;fp;fp=fp->next) { + if (fp->link_status == not_in_use) continue; + restart: + result = waitpid(fp->pid,(int *)&fp->wait_status,WNOHANG); + if (result == fp->pid) { + waited_on_forked_process = 1; + break; + } + if (result == 0) continue; /* busy, try next */ + if (result == -1) { + if (errno == EINTR) goto restart; + else break; + } + } + + if (waited_on_forked_process) { + /* + * The literal spawn id in the return value from wait appears + * as a -1 to indicate a forked process was waited on. + */ + strcpy(spawn_id,"-1"); + } else { + result = NO_CHILD; /* no children */ + Tcl_ReapDetachedProcs(); + } + exp_rearm_sigchld(interp); + } + } + + /* sigh, wedge forked_proc into an ExpState structure so we don't + * have to rewrite remaining code (too much) + */ + if (fp) { + esPtr = &esTmp; + esPtr->pid = fp->pid; + esPtr->wait = fp->wait_status; + } + + /* non-portable assumption that pid_t can be printed with %d */ + + if (result == -1) { + Tcl_Obj* d = Tcl_NewListObj (0,NULL); + + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (esPtr->pid)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (spawn_id, -1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (-1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (errno)); + Tcl_ListObjAppendElement (interp, d, LITERAL ("POSIX")); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_ErrnoId(),-1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_ErrnoMsg(errno),-1)); + + Tcl_SetObjResult (interp, d); + result = TCL_OK; + } else if (result == NO_CHILD) { + exp_error(interp,"no children"); + return TCL_ERROR; + } else { + Tcl_Obj* d = Tcl_NewListObj (0,NULL); + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (esPtr->pid)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (spawn_id,-1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (0)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewIntObj (WEXITSTATUS(esPtr->wait))); + + if (WIFSIGNALED(esPtr->wait)) { + Tcl_ListObjAppendElement (interp, d, LITERAL ("CHILDKILLED")); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_SignalId ((int) (WTERMSIG(esPtr->wait))),-1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_SignalMsg((int) (WTERMSIG(esPtr->wait))),-1)); + } else if (WIFSTOPPED(esPtr->wait)) { + Tcl_ListObjAppendElement (interp, d, LITERAL ("CHILDSUSP")); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_SignalId ((int) (WSTOPSIG(esPtr->wait))),-1)); + Tcl_ListObjAppendElement (interp, d, Tcl_NewStringObj (Tcl_SignalMsg((int) (WSTOPSIG(esPtr->wait))),-1)); + } + + Tcl_SetObjResult (interp, d); + } + + if (fp) { + fp->link_status = not_in_use; + return ((result == -1)?TCL_ERROR:TCL_OK); + } + + esPtr->sys_waited = TRUE; + esPtr->user_waited = TRUE; + + /* if user has already called close, forget about this entry entirely */ + if (!esPtr->open) { + if (esPtr->registered) { + Tcl_UnregisterChannel(interp,esPtr->channel); + } + } + + return ((result == -1)?TCL_ERROR:TCL_OK); + + usage: + exp_error(interp,"usage: -i spawn_id"); + return(TCL_ERROR); +} + +/*ARGSUSED*/ +static int +Exp_ForkObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int rc; + if (objc > 1) { + exp_error(interp,"usage: fork"); + return(TCL_ERROR); + } + + rc = fork(); + if (rc == -1) { + exp_error(interp,"fork: %s",Tcl_PosixError(interp)); + return TCL_ERROR; + } else if (rc == 0) { + /* child */ + exp_forked = TRUE; + exp_getpid = getpid(); + fork_clear_all(); + } else { + /* parent */ + fork_add(rc); + } + + /* both child and parent follow remainder of code */ + Tcl_SetObjResult (interp, Tcl_NewIntObj (rc)); + expDiagLog("fork: returns {%s}\r\n",Tcl_GetStringResult(interp)); + return(TCL_OK); +} + +/*ARGSUSED*/ +static int +Exp_DisconnectObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + +#ifdef TIOCNOTTY + /* tell CenterLine to ignore non-use of ttyfd */ + /*SUPPRESS 591*/ + int ttyfd; +#endif /* TIOCNOTTY */ + + if (objc > 1) { + exp_error(interp,"usage: disconnect"); + return(TCL_ERROR); + } + + if (exp_disconnected) { + exp_error(interp,"already disconnected"); + return(TCL_ERROR); + } + if (!exp_forked) { + exp_error(interp,"can only disconnect child process"); + return(TCL_ERROR); + } + exp_disconnected = TRUE; + + /* ignore hangup signals generated by testing ptys in getptymaster */ + /* and other places */ + signal(SIGHUP,SIG_IGN); + + /* reopen prevents confusion between send/expect_user */ + /* accidentally mapping to a real spawned process after a disconnect */ + + /* if we're in a child that's about to be disconnected from the + controlling tty, close and reopen 0, 1, and 2 but associated + with /dev/null. This prevents send and expect_user doing + special things if newly spawned processes accidentally + get allocated 0, 1, and 2. + */ + + if (isatty(0)) { + ExpState *stdinout = tsdPtr->stdinout; + if (stdinout->valid) { + exp_close(interp,stdinout); + if (stdinout->registered) { + Tcl_UnregisterChannel(interp,stdinout->channel); + } + } + open("/dev/null",0); + open("/dev/null",1); + /* tsdPtr->stdinout = expCreateChannel(interp,0,1,EXP_NOPID);*/ + /* tsdPtr->stdinout->keepForever = 1;*/ + } + if (isatty(2)) { + ExpState *devtty = tsdPtr->devtty; + + /* reopen stderr saves error checking in error/log routines. */ + if (devtty->valid) { + exp_close(interp,devtty); + if (devtty->registered) { + Tcl_UnregisterChannel(interp,devtty->channel); + } + } + open("/dev/null",1); + /* tsdPtr->devtty = expCreateChannel(interp,2,2,EXP_NOPID);*/ + /* tsdPtr->devtty->keepForever = 1;*/ + } + + Tcl_UnsetVar(interp,"tty_spawn_id",TCL_GLOBAL_ONLY); + +#ifdef DO_SETSID + setsid(); +#else +#ifdef SYSV3 + /* put process in our own pgrp, and lose controlling terminal */ +#ifdef sysV88 + /* With setpgrp first, child ends up with closed stdio */ + /* according to Dave Schmitt <daves@techmpc.csg.gss.mot.com> */ + if (fork()) exit(0); + expSetpgrp(); +#else + expSetpgrp(); + /*signal(SIGHUP,SIG_IGN); moved out to above */ + if (fork()) exit(0); /* first child exits (as per Stevens, */ + /* UNIX Network Programming, p. 79-80) */ + /* second child process continues as daemon */ +#endif +#else /* !SYSV3 */ + expSetpgrp(); + +/* Pyramid lacks this defn */ +#ifdef TIOCNOTTY + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd >= 0) { + /* zap controlling terminal if we had one */ + (void) ioctl(ttyfd, TIOCNOTTY, (char *)0); + (void) close(ttyfd); + } +#endif /* TIOCNOTTY */ + +#endif /* SYSV3 */ +#endif /* DO_SETSID */ + return(TCL_OK); +} + +/*ARGSUSED*/ +static int +Exp_OverlayObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int newfd, oldfd; + int dash_name = 0; + char *command; + int k, j; + char **argv; + + int i; + + for (i=1;i<objc;i++) { + char *name; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } else if (streq (name,"-")) { /* - by itself */ + dash_name = 1; + continue; + } + + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &newfd)) { + return TCL_ERROR; + } + newfd = - newfd; /* Negation rids us of the effect the '-' prefix had. */ + + i ++; + if (i >= objc) { + exp_error(interp,"overlay -# requires additional argument"); + return(TCL_ERROR); + } + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &oldfd)) { + return TCL_ERROR; + } + + expDiagLog("overlay: mapping fd %d to %d\r\n",oldfd,newfd); + if (oldfd != newfd) (void) dup2(oldfd,newfd); + else expDiagLog("warning: overlay: old fd == new fd (%d)\r\n",oldfd); + } + + if (i >= objc) { + exp_error(interp,"need program name"); + return(TCL_ERROR); + } + + /* convert to string array for execvp. + * Take only the arguments after the command name (i+1 ...). The arguments + * before are arguments of overlay, not of the invoked command. The + * command name is at index. + */ + + argv = (char**) ckalloc ((objc+1)*sizeof(char*)); + + for (k=i+1,j=1;k<objc;k++,j++) { + argv[j] = ckalloc (1+strlen(Tcl_GetString (objv[k]))); + strcpy (argv[j],Tcl_GetString (objv[k])); + } + argv[j] = NULL; + + /* command, handle '-' */ + command = Tcl_GetString (objv[i]); + argv[0] = ckalloc (2+strlen(command)); + if (dash_name) { + argv [0][0] = '-'; + strcpy (argv[0]+1,command); + } else { + strcpy (argv[0],command); + } + + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + + (void) execvp(command,argv); + + for (k=0;k<objc;k++) { + ckfree (argv[k]); + } + ckfree ((char*)argv); + + exp_error(interp,"execvp(%s): %s\r\n", + Tcl_GetString(objv[0]), + Tcl_PosixError(interp)); + return(TCL_ERROR); +} + +/*ARGSUSED*/ +int +Exp_InterpreterObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tcl_Obj *eofObj = 0; + int i; + int index; + int rc; + + static char *options[] = { + "-eof", (char *)0 + }; + enum options { + FLAG_EOF + }; + + for (i = 1; i < objc; i++) { + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case FLAG_EOF: + i++; + if (i >= objc) { + Tcl_WrongNumArgs(interp, 1, objv,"-eof cmd"); + return TCL_ERROR; + } + eofObj = objv[i]; + Tcl_IncrRefCount(eofObj); + break; + } + } + + /* errors and ok, are caught by exp_interpreter() and discarded */ + /* to return TCL_OK, type "return" */ + rc = exp_interpreter(interp,eofObj); + if (eofObj) { + Tcl_DecrRefCount(eofObj); + } + return rc; +} + +/* this command supercede's Tcl's builtin CONTINUE command */ +/*ARGSUSED*/ +int +Exp_ExpContinueObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + if (objc == 1) { + return EXP_CONTINUE; + } else if ((objc == 2) && + (0 == strcmp(Tcl_GetString (objv[1]),"-continue_timer"))) { + return EXP_CONTINUE_TIMER; + } + + exp_error(interp,"usage: exp_continue [-continue_timer]\n"); + return(TCL_ERROR); +} + +/* most of this is directly from Tcl's definition for return */ +/*ARGSUSED*/ +int +Exp_InterReturnObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) +{ + /* let Tcl's return command worry about args */ + /* if successful (i.e., TCL_RETURN is returned) */ + /* modify the result, so that we will handle it specially */ + + Tcl_CmdInfo* return_info = (Tcl_CmdInfo*) + Tcl_GetAssocData (interp, EXP_CMDINFO_RETURN, NULL); + + int result = return_info->objProc(return_info->objClientData,interp,objc,objv); + if (result == TCL_RETURN) + result = EXP_TCL_RETURN; + return result; +} + +/*ARGSUSED*/ +int +Exp_OpenObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + ExpState *esPtr; + char *chanName = 0; + int newfd; + int leaveopen = FALSE; + Tcl_Channel channel; + + static char* options[] = { + "-i", + "-leaveopen", + NULL + }; + enum options { + OPEN_ID, + OPEN_LEAVEOPEN + }; + int i; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + goto usage; + } + switch ((enum options) index) { + case OPEN_ID: + i++; + if (i >= objc) goto usage; + chanName = Tcl_GetString (objv[i]); + break; + case OPEN_LEAVEOPEN: + leaveopen = TRUE; + break; + } + } + + if (!chanName) { + esPtr = expStateCurrent(interp,1,0,0); + } else { + esPtr = expStateFromChannelName(interp,chanName,1,0,0,"exp_open"); + } + if (!esPtr) return TCL_ERROR; + + /* make a new copy of file descriptor */ + if (-1 == (newfd = dup(esPtr->fdin))) { + exp_error(interp,"dup: %s",Tcl_PosixError(interp)); + return TCL_ERROR; + } + + if (!leaveopen) { + /* remove from Expect's memory in anticipation of passing to Tcl */ + if (esPtr->pid != EXP_NOPID) { + Tcl_Pid pid = (Tcl_Pid)(long)esPtr->pid; + Tcl_DetachPids(1,&pid); + esPtr->pid = EXP_NOPID; + esPtr->sys_waited = esPtr->user_waited = TRUE; + } + exp_close(interp,esPtr); + } + + /* + * Tcl's MakeFileChannel only allows us to pass a single file descriptor + * but that shouldn't be a problem in practice since all of the channels + * that Expect generates only have one fd. Of course, this code won't + * work if someone creates a pipeline, then passes it to spawn, and then + * again to exp_open. For that to work, Tcl would need a new API. + * Oh, and we're also being rather cavalier with the permissions here, + * but they're likely to be right for the same reasons. + */ + channel = Tcl_MakeFileChannel((ClientData)(long)newfd,TCL_READABLE|TCL_WRITABLE); + Tcl_RegisterChannel(interp, channel); + Tcl_AppendResult(interp, Tcl_GetChannelName(channel), (char *) NULL); + return TCL_OK; + + usage: + exp_error(interp,"usage: -i spawn_id"); + return TCL_ERROR; +} + +/* return 1 if a string is substring of a flag */ +/* this version is the code used by the macro that everyone calls */ +int +exp_flageq_code( + char *flag, + char *string, + int minlen) /* at least this many chars must match */ +{ + for (;*flag;flag++,string++,minlen--) { + if (*string == '\0') break; + if (*string != *flag) return 0; + } + if (*string == '\0' && minlen <= 0) return 1; + return 0; +} + +void +exp_create_commands(interp,c) + Tcl_Interp *interp; + struct exp_cmd_data *c; +{ + Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); + Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); + char cmdnamebuf[80]; + + for (;c->name;c++) { + /* if already defined, don't redefine */ + if ((c->flags & EXP_REDEFINE) || + !(Tcl_FindHashEntry(&globalNsPtr->cmdTable,c->name) || + Tcl_FindHashEntry(&currNsPtr->cmdTable,c->name))) { + if (c->objproc) + Tcl_CreateObjCommand(interp,c->name, + c->objproc,c->data,exp_deleteObjProc); + else + Tcl_CreateCommand(interp,c->name,c->proc, + c->data,exp_deleteProc); + } + if (!(c->name[0] == 'e' && + c->name[1] == 'x' && + c->name[2] == 'p') + && !(c->flags & EXP_NOPREFIX)) { + sprintf(cmdnamebuf,"exp_%s",c->name); + if (c->objproc) + Tcl_CreateObjCommand(interp,cmdnamebuf,c->objproc,c->data, + exp_deleteObjProc); + else + Tcl_CreateCommand(interp,cmdnamebuf,c->proc, + c->data,exp_deleteProc); + } + } +} + +static struct exp_cmd_data cmd_data[] = { + {"close", Exp_CloseObjCmd, 0, (ClientData)0, EXP_REDEFINE}, +#ifdef TCL_DEBUGGER + {"debug", Exp_DebugObjCmd, 0, (ClientData)0, 0}, +#endif + {"exp_internal", Exp_ExpInternalObjCmd, 0, (ClientData)0, 0}, + {"disconnect", Exp_DisconnectObjCmd, 0, (ClientData)0, 0}, + {"exit", Exp_ExitObjCmd, 0, (ClientData)0, EXP_REDEFINE}, + {"exp_continue", Exp_ExpContinueObjCmd, 0, (ClientData)0, 0}, + {"fork", Exp_ForkObjCmd, 0, (ClientData)0, 0}, + {"exp_pid", Exp_ExpPidObjCmd, 0, (ClientData)0, 0}, + {"getpid", Exp_GetpidDeprecatedObjCmd, 0, (ClientData)0, 0}, + {"interpreter", Exp_InterpreterObjCmd, 0, (ClientData)0, 0}, + {"log_file", Exp_LogFileObjCmd, 0, (ClientData)0, 0}, + {"log_user", Exp_LogUserObjCmd, 0, (ClientData)0, 0}, + {"exp_open", Exp_OpenObjCmd, 0, (ClientData)0, 0}, + {"overlay", Exp_OverlayObjCmd, 0, (ClientData)0, 0}, + {"inter_return", Exp_InterReturnObjCmd, 0, (ClientData)0, 0}, + {"send", Exp_SendObjCmd, 0, (ClientData)&sendCD_proc,0}, + {"send_error", Exp_SendObjCmd, 0, (ClientData)&sendCD_error,0}, + {"send_log", Exp_SendLogObjCmd, 0, (ClientData)0, 0}, + {"send_tty", Exp_SendObjCmd, 0, (ClientData)&sendCD_tty,0}, + {"send_user", Exp_SendObjCmd, 0, (ClientData)&sendCD_user,0}, + {"sleep", Exp_SleepObjCmd, 0, (ClientData)0, 0}, + {"spawn", Exp_SpawnObjCmd, 0, (ClientData)0, 0}, + {"strace", Exp_StraceObjCmd, 0, (ClientData)0, 0}, + {"wait", Exp_WaitObjCmd, 0, (ClientData)0, 0}, + {"exp_configure",Exp_ConfigureObjCmd, 0, (ClientData)0, 0}, + {0}}; + +void +exp_init_most_cmds(Tcl_Interp *interp) +{ + exp_create_commands(interp,cmd_data); + +#ifdef HAVE_PTYTRAP + Tcl_InitHashTable(&slaveNames,TCL_STRING_KEYS); +#endif /* HAVE_PTYTRAP */ +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_command.h b/exp_command.h new file mode 100644 index 0000000..c8c0780 --- /dev/null +++ b/exp_command.h @@ -0,0 +1,358 @@ +/* command.h - definitions for expect commands + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifdef HAVE_SYS_WAIT_H + /* ISC doesn't def WNOHANG unless _POSIX_SOURCE is def'ed */ +# ifdef WNOHANG_REQUIRES_POSIX_SOURCE +# define _POSIX_SOURCE +# endif +# include <sys/wait.h> +# ifdef WNOHANG_REQUIRES_POSIX_SOURCE +# undef _POSIX_SOURCE +# endif +#endif + +#ifdef __APPLE__ +/* From: "Daniel A. Steffen" <steffen@ics.mq.edu.au> */ +# undef panic +#endif + +#include <tclPort.h> + +#define EXP_CHANNELNAMELEN (16 + TCL_INTEGER_SPACE) + +EXTERN char * exp_get_var _ANSI_ARGS_((Tcl_Interp *,char *)); + +EXTERN int exp_default_match_max; +EXTERN int exp_default_parity; +EXTERN int exp_default_rm_nulls; +EXTERN int exp_default_close_on_eof; + +EXTERN int exp_one_arg_braced _ANSI_ARGS_((Tcl_Obj *)); + +EXTERN Tcl_Obj* exp_eval_with_one_arg _ANSI_ARGS_((ClientData, + Tcl_Interp *, struct Tcl_Obj * CONST objv[])); + +EXTERN void exp_lowmemcpy _ANSI_ARGS_((char *,char *,int)); + +EXTERN int exp_flageq_code _ANSI_ARGS_((char *,char *,int)); + +#define exp_flageq(flag,string,minlen) \ +(((string)[0] == (flag)[0]) && (exp_flageq_code(((flag)+1),((string)+1),((minlen)-1)))) + +/* exp_flageq for single char flags */ +#define exp_flageq1(flag,string) \ + ((string[0] == flag) && (string[1] == '\0')) + +#define EXP_SPAWN_ID_USER 0 +#define EXP_SPAWN_ID_ANY_LIT "-1" + +#define EXP_CHANNEL_PREFIX "exp" +#define EXP_CHANNEL_PREFIX_LENGTH 3 +#define isExpChannelName(name) \ + (0 == strncmp(name,EXP_CHANNEL_PREFIX,EXP_CHANNEL_PREFIX_LENGTH)) + +#define exp_is_stdinfd(x) ((x) == 0) +#define exp_is_devttyfd(x) ((x) == exp_dev_tty) + +#define EXP_NOPID 0 /* Used when there is no associated pid to */ + /* wait for. For example: */ + /* 1) When fd opened by someone else, e.g., */ + /* Tcl's open */ + /* 2) When entry not in use */ + /* 3) To tell user pid of "spawn -open" */ + /* 4) stdin, out, error */ + +#define EXP_NOFD -1 + +/* these are occasionally useful to distinguish between various expect */ +/* commands and are also used as array indices into the per-fd eg[] arrays */ +#define EXP_CMD_BEFORE 0 +#define EXP_CMD_AFTER 1 +#define EXP_CMD_BG 2 +#define EXP_CMD_FG 3 + +/* + * This structure describes per-instance state of an Exp channel. + */ + +typedef struct ExpOrigin { + int refCount; /* Number of times this channel is used. */ + Tcl_Channel channel_orig; /* If opened by someone else, i.e. tcl::open */ +} ExpOrigin; + + +typedef struct ExpUniBuf { + Tcl_UniChar* buffer; /* char buffer, holdings unicode chars (fixed width) */ + int max; /* number of CHARS the buffer has space for (== old msize) */ + int use; /* number of CHARS the buffer is currently holding */ + Tcl_Obj* newchars; /* Object to hold newly read characters */ +} ExpUniBuf; + +typedef struct ExpState { + Tcl_Channel channel; /* Channel associated with this file. */ + char name[EXP_CHANNELNAMELEN+1]; /* expect and interact set variables + to channel name, so for efficiency + cache it here */ + int fdin; /* input fd */ + int fdout; /* output fd - usually the same as fdin, although + may be different if channel opened by tcl::open */ + ExpOrigin* chan_orig; /* If opened by someone else, i.e. tcl::open */ + int fd_slave; /* slave fd if "spawn -pty" used */ + + /* this may go away if we find it is not needed */ + /* it might be needed by inherited channels */ + int validMask; /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, or TCL_EXCEPTION: indicates + * which operations are valid on the file. */ + + int pid; /* pid or EXP_NOPID if no pid */ + + ExpUniBuf input; /* input buffer */ + + int umsize; /* # of bytes (min) that is guaranteed to match */ + /* this comes from match_max command */ + int printed; /* # of characters! written to stdout (if logging on) */ + /* but not actually returned via a match yet */ + int echoed; /* additional # of characters (beyond "printed" above) */ + /* echoed back but not actually returned via a match */ + /* yet. This supports interact -echo */ + + int rm_nulls; /* if nulls should be stripped before pat matching */ + int open; /* if fdin/fdout open */ + int user_waited; /* if user has issued "wait" command */ + int sys_waited; /* if wait() (or variant) has been called */ + int registered; /* if channel registered */ + WAIT_STATUS_TYPE wait; /* raw status from wait() */ + int parity; /* if parity should be preserved */ + int close_on_eof; /* if channel should be closed automatically on eof */ + int key; /* unique id that identifies what command instance */ + /* last touched this buffer */ + int force_read; /* force read to occur (even if buffer already has */ + /* data). This supports interact CAN_MATCH */ + int notified; /* If Tcl_NotifyChannel has been called and we */ + /* have not yet read from the channel. */ + int notifiedMask; /* Mask reported when notified. */ + + int fg_armed; /* If we have requested Tk_CreateFileHandler to be */ + /* responding to foreground events. Note that */ + /* other handlers can have stolen it away so this */ + /* doesn't necessarily mean the handler is set. */ + /* However, if fg_armed is 0, then the handlers */ + /* definitely needs to be set. The significance of */ + /* this flag is so we can remember to turn it off. */ +#ifdef HAVE_PTYTRAP + char *slave_name; /* Full name of slave, i.e., /dev/ttyp0 */ +#endif /* HAVE_PTYTRAP */ + /* may go away */ + int leaveopen; /* If we should not call Tcl's close when we close - */ + /* only relevant if Tcl does the original open */ + + Tcl_Interp *bg_interp; /* interp to process the bg cases */ + int bg_ecount; /* number of background ExpStates */ + enum { + blocked, /* blocked because we are processing the */ + /* file handler */ + armed, /* normal state when bg handler in use */ + unarmed, /* no bg handler in use */ + disarm_req_while_blocked /* while blocked, a request */ + /* was received to disarm it. Rather than */ + /* processing the request immediately, defer */ + /* it so that when we later try to unblock */ + /* we will see at that time that it should */ + /* instead be disarmed */ + } bg_status; + + /* + * If the channel is freed while in the middle of a bg event handler, + * remember that and defer freeing of the ExpState structure until + * it is safe. + */ + int freeWhenBgHandlerUnblocked; + + /* If channel is closed but not yet waited on, we tie up the fd by + * attaching it to /dev/null. We play this little game so that we + * can embed the fd in the channel name. If we didn't tie up the + * fd, we'd get channel name collisions. I'd consider naming the + * channels independently of the fd, but this makes debugging easier. + */ + int fdBusy; + + /* + * stdinout and stderr never go away so that our internal refs to them + * don't have to be invalidated. Having to worry about invalidating them + * would be a major pain. */ + int keepForever; + + /* Remember that "reserved" esPtrs are no longer in use. */ + int valid; + + struct ExpState *nextPtr; /* Pointer to next file in list of all + * file channels. */ +} ExpState; + +#define EXP_SPAWN_ID_BAD ((ExpState *)0) + +#define EXP_TIME_INFINITY -1 + +extern Tcl_ChannelType expChannelType; + +#define EXP_TEMPORARY 1 /* expect */ +#define EXP_PERMANENT 2 /* expect_after, expect_before, expect_bg */ + +#define EXP_DIRECT 1 +#define EXP_INDIRECT 2 + +EXTERN void expAdjust _ANSI_ARGS_((ExpState *)); +EXTERN int expWriteChars _ANSI_ARGS_((ExpState *,char *,int)); +EXTERN int expWriteCharsUni _ANSI_ARGS_((ExpState *,Tcl_UniChar *,int)); +EXTERN void exp_buffer_shuffle _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,char *,char *)); +EXTERN int exp_close _ANSI_ARGS_((Tcl_Interp *,ExpState *)); +EXTERN void exp_close_all _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_ecmd_remove_fd_direct_and_indirect + _ANSI_ARGS_((Tcl_Interp *,int)); +EXTERN void exp_trap_on _ANSI_ARGS_((int)); +EXTERN int exp_trap_off _ANSI_ARGS_((char *)); + +EXTERN void exp_strftime(char *format, const struct tm *timeptr,Tcl_DString *dstring); + +#define exp_deleteProc (void (*)())0 +#define exp_deleteObjProc (void (*)())0 + +EXTERN int expect_key; +EXTERN int exp_configure_count; /* # of times descriptors have been closed */ + /* or indirect lists have been changed */ +EXTERN int exp_nostack_dump; /* TRUE if user has requested unrolling of */ + /* stack with no trace */ + +EXTERN void exp_init_pty _ANSI_ARGS_((void)); +EXTERN void exp_pty_exit _ANSI_ARGS_((void)); +EXTERN void exp_init_tty _ANSI_ARGS_((void)); +EXTERN void exp_init_stdio _ANSI_ARGS_((void)); +/*EXTERN void exp_init_expect _ANSI_ARGS_((Tcl_Interp *));*/ +EXTERN void exp_init_spawn_ids _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_spawn_id_vars _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_trap _ANSI_ARGS_((void)); +EXTERN void exp_init_send _ANSI_ARGS_((void)); +EXTERN void exp_init_unit_random _ANSI_ARGS_((void)); +EXTERN void exp_init_sig _ANSI_ARGS_((void)); +EXTERN void expChannelInit _ANSI_ARGS_((void)); +EXTERN int expChannelCountGet _ANSI_ARGS_((void)); + +EXTERN int exp_tcl2_returnvalue _ANSI_ARGS_((int)); +EXTERN int exp_2tcl_returnvalue _ANSI_ARGS_((int)); + +EXTERN void exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp *)); +EXTERN int exp_string_to_signal _ANSI_ARGS_((Tcl_Interp *,char *)); + +EXTERN char *exp_onexit_action; + +#define exp_new(x) (x *)malloc(sizeof(x)) + +struct exp_state_list { + ExpState *esPtr; + struct exp_state_list *next; +}; + +/* describes a -i flag */ +struct exp_i { + int cmdtype; /* EXP_CMD_XXX. When an indirect update is */ + /* triggered by Tcl, this helps tell us in what */ + /* exp_i list to look in. */ + int direct; /* if EXP_DIRECT, then the spawn ids have been given */ + /* literally, else indirectly through a variable */ + int duration; /* if EXP_PERMANENT, char ptrs here had to be */ + /* malloc'd because Tcl command line went away - */ + /* i.e., in expect_before/after */ + char *variable; + char *value; /* if type == direct, this is the string that the */ + /* user originally supplied to the -i flag. It may */ + /* lose relevance as the fd_list is manipulated */ + /* over time. If type == direct, this is the */ + /* cached value of variable use this to tell if it */ + /* has changed or not, and ergo whether it's */ + /* necessary to reparse. */ + + int ecount; /* # of ecases this is used by */ + + struct exp_state_list *state_list; + struct exp_i *next; +}; + +EXTERN struct exp_i * exp_new_i_complex _ANSI_ARGS_((Tcl_Interp *, + char *, int, Tcl_VarTraceProc *)); +EXTERN struct exp_i * exp_new_i_simple _ANSI_ARGS_((ExpState *,int)); +EXTERN struct exp_state_list *exp_new_state _ANSI_ARGS_((ExpState *)); +EXTERN void exp_free_i _ANSI_ARGS_((Tcl_Interp *,struct exp_i *, + Tcl_VarTraceProc *)); +EXTERN void exp_free_state _ANSI_ARGS_((struct exp_state_list *)); +EXTERN void exp_free_state_single _ANSI_ARGS_((struct exp_state_list *)); +EXTERN int exp_i_update _ANSI_ARGS_((Tcl_Interp *, + struct exp_i *)); + +/* + * definitions for creating commands + */ + +#define EXP_NOPREFIX 1 /* don't define with "exp_" prefix */ +#define EXP_REDEFINE 2 /* stomp on old commands with same name */ + +#define exp_proc(cmdproc) 0, cmdproc + +struct exp_cmd_data { + char *name; + Tcl_ObjCmdProc *objproc; + Tcl_CmdProc *proc; + ClientData data; + int flags; +}; + +EXTERN void exp_create_commands _ANSI_ARGS_((Tcl_Interp *, + struct exp_cmd_data *)); +EXTERN void exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_expect_cmds _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_interact_cmds _ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_init_tty_cmds(); + +EXTERN ExpState * expStateCheck _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,int,char *)); +EXTERN ExpState * expStateCurrent _ANSI_ARGS_((Tcl_Interp *,int,int,int)); +EXTERN ExpState * expStateFromChannelName _ANSI_ARGS_((Tcl_Interp *,char *,int,int,int,char *)); +EXTERN void expStateFree _ANSI_ARGS_((ExpState *)); + +EXTERN ExpState * expCreateChannel _ANSI_ARGS_((Tcl_Interp *,int,int,int)); +EXTERN ExpState * expWaitOnAny _ANSI_ARGS_((void)); +EXTERN ExpState * expWaitOnOne _ANSI_ARGS_((void)); +EXTERN void expExpectVarsInit _ANSI_ARGS_((void)); +EXTERN int expStateAnyIs _ANSI_ARGS_((ExpState *)); +EXTERN int expDevttyIs _ANSI_ARGS_((ExpState *)); +EXTERN int expStdinoutIs _ANSI_ARGS_((ExpState *)); +EXTERN ExpState * expStdinoutGet _ANSI_ARGS_((void)); +EXTERN ExpState * expDevttyGet _ANSI_ARGS_((void)); + +/* generic functions that really should be provided by Tcl */ +#if 0 /* Redefined as macros. */ +EXTERN int expSizeGet _ANSI_ARGS_((ExpState *)); +EXTERN int expSizeZero _ANSI_ARGS_((ExpState *)); +#else +#define expSizeGet(esPtr) ((esPtr)->input.use) +#define expSizeZero(esPtr) (((esPtr)->input.use) == 0) +#endif + +#define EXP_CMDINFO_CLOSE "expect/cmdinfo/close" +#define EXP_CMDINFO_RETURN "expect/cmdinfo/return" + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_console.c b/exp_console.c new file mode 100644 index 0000000..7e2f823 --- /dev/null +++ b/exp_console.c @@ -0,0 +1,70 @@ +/* exp_console.c - grab console. This stuff is in a separate file to +avoid unpleasantness of AIX (3.2.4) .h files which provide no way to +reference TIOCCONS and include both sys/ioctl.h and sys/sys/stropts.h +without getting some sort of warning from the compiler. The problem +is that both define _IO but only ioctl.h checks to see if it is +defined first. This would suggest that it is sufficient to include +ioctl.h after stropts.h. Unfortunately, ioctl.h, having seen that _IO +is defined, then fails to define other important things (like _IOW). + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/ioctl.h> + +/* Solaris needs this for console redir */ +#ifdef HAVE_STRREDIR_H +#include <sys/strredir.h> +# ifdef SRIOCSREDIR +# undef TIOCCONS +# endif +#endif + +#ifdef HAVE_SYS_FCNTL_H +#include <sys/fcntl.h> +#endif + +#include "tcl.h" +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" + +static void +exp_console_manipulation_failed(s) +char *s; +{ + expErrorLog("expect: spawn: cannot %s console, check permissions of /dev/console\n",s); + exit(-1); +} + +void +exp_console_set() +{ +#ifdef SRIOCSREDIR + int fd; + + if ((fd = open("/dev/console", O_RDONLY)) == -1) { + exp_console_manipulation_failed("open"); + } + if (ioctl(fd, SRIOCSREDIR, 0) == -1) { + exp_console_manipulation_failed("redirect"); + } + close(fd); +#endif + +#ifdef TIOCCONS + int on = 1; + + if (ioctl(0,TIOCCONS,(char *)&on) == -1) { + exp_console_manipulation_failed("redirect"); + } +#endif /*TIOCCONS*/ +} diff --git a/exp_event.c b/exp_event.c new file mode 100644 index 0000000..8ebe4b6 --- /dev/null +++ b/exp_event.c @@ -0,0 +1,349 @@ +/* exp_event.c - event interface for Expect + +Written by: Don Libes, NIST, 2/6/90 + +I hereby place this software in the public domain. However, the author and +NIST would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_PTYTRAP +# include <sys/ptyio.h> +#endif + +#include "tcl.h" +#include "exp_prog.h" +#include "exp_command.h" /* for ExpState defs */ +#include "exp_event.h" + +typedef struct ThreadSpecificData { + int rr; /* round robin ptr */ +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +void +exp_event_disarm_bg(esPtr) +ExpState *esPtr; +{ + Tcl_DeleteChannelHandler(esPtr->channel,exp_background_channelhandler,(ClientData)esPtr); +} + +static void +exp_arm_background_channelhandler_force(esPtr) +ExpState *esPtr; +{ + Tcl_CreateChannelHandler(esPtr->channel, + TCL_READABLE|TCL_EXCEPTION, + exp_background_channelhandler, + (ClientData)esPtr); + + esPtr->bg_status = armed; +} + +void +exp_arm_background_channelhandler(esPtr) +ExpState *esPtr; +{ + switch (esPtr->bg_status) { + case unarmed: + exp_arm_background_channelhandler_force(esPtr); + break; + case disarm_req_while_blocked: + esPtr->bg_status = blocked; /* forget request */ + break; + case armed: + case blocked: + /* do nothing */ + break; + } +} + +void +exp_disarm_background_channelhandler(esPtr) +ExpState *esPtr; +{ + switch (esPtr->bg_status) { + case blocked: + esPtr->bg_status = disarm_req_while_blocked; + break; + case armed: + esPtr->bg_status = unarmed; + exp_event_disarm_bg(esPtr); + break; + case disarm_req_while_blocked: + case unarmed: + /* do nothing */ + break; + } +} + +/* ignore block status and forcibly disarm handler - called from exp_close. */ +/* After exp_close returns, we will not have an opportunity to disarm */ +/* because the fd will be invalid, so we force it here. */ +void +exp_disarm_background_channelhandler_force(esPtr) +ExpState *esPtr; +{ + switch (esPtr->bg_status) { + case blocked: + case disarm_req_while_blocked: + case armed: + esPtr->bg_status = unarmed; + exp_event_disarm_bg(esPtr); + break; + case unarmed: + /* do nothing */ + break; + } +} + +/* this can only be called at the end of the bg handler in which */ +/* case we know the status is some kind of "blocked" */ +void +exp_unblock_background_channelhandler(esPtr) + ExpState *esPtr; +{ + switch (esPtr->bg_status) { + case blocked: + exp_arm_background_channelhandler_force(esPtr); + break; + case disarm_req_while_blocked: + exp_disarm_background_channelhandler_force(esPtr); + break; + } +} + +/* this can only be called at the beginning of the bg handler in which */ +/* case we know the status must be "armed" */ +void +exp_block_background_channelhandler(esPtr) +ExpState *esPtr; +{ + esPtr->bg_status = blocked; + exp_event_disarm_bg(esPtr); +} + + +/*ARGSUSED*/ +static void +exp_timehandler(clientData) +ClientData clientData; +{ + *(int *)clientData = TRUE; +} + +static void exp_channelhandler(clientData,mask) +ClientData clientData; +int mask; +{ + ExpState *esPtr = (ExpState *)clientData; + + esPtr->notified = TRUE; + esPtr->notifiedMask = mask; + + exp_event_disarm_fg(esPtr); +} + +void +exp_event_disarm_fg(esPtr) +ExpState *esPtr; +{ + /*printf("DeleteChannelHandler: %s\r\n",esPtr->name);*/ + Tcl_DeleteChannelHandler(esPtr->channel,exp_channelhandler,(ClientData)esPtr); + + /* remember that ChannelHandler has been disabled so that */ + /* it can be turned on for fg expect's as well as bg */ + esPtr->fg_armed = FALSE; +} + +/* returns status, one of EOF, TIMEOUT, ERROR or DATA */ +/* can now return RECONFIGURE, too */ +/*ARGSUSED*/ +int exp_get_next_event(interp,esPtrs,n,esPtrOut,timeout,key) +Tcl_Interp *interp; +ExpState *(esPtrs[]); +int n; /* # of esPtrs */ +ExpState **esPtrOut; /* 1st ready esPtr, not set if none */ +int timeout; /* seconds */ +int key; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + ExpState *esPtr; + int i; /* index into in-array */ +#ifdef HAVE_PTYTRAP + struct request_info ioctl_info; +#endif + + int old_configure_count = exp_configure_count; + + int timerFired = FALSE; + Tcl_TimerToken timerToken = 0;/* handle to Tcl timehandler descriptor */ + /* We must delete any timer before returning. Doing so throughout + * the code makes it unreadable; isolate the unreadable nonsense here. + */ +#define RETURN(x) { \ + if (timerToken) Tcl_DeleteTimerHandler(timerToken); \ + return(x); \ + } + + for (;;) { + /* if anything has been touched by someone else, report that */ + /* an event has been received */ + + for (i=0;i<n;i++) { + tsdPtr->rr++; + if (tsdPtr->rr >= n) tsdPtr->rr = 0; + + esPtr = esPtrs[tsdPtr->rr]; + + if (esPtr->key != key) { + esPtr->key = key; + esPtr->force_read = FALSE; + *esPtrOut = esPtr; + RETURN(EXP_DATA_OLD); + } else if ((!esPtr->force_read) && (!expSizeZero(esPtr))) { + *esPtrOut = esPtr; + RETURN(EXP_DATA_OLD); + } else if (esPtr->notified) { + /* this test of the mask should be redundant but SunOS */ + /* raises both READABLE and EXCEPTION (for no */ + /* apparent reason) when selecting on a plain file */ + if (esPtr->notifiedMask & TCL_READABLE) { + *esPtrOut = esPtr; + esPtr->notified = FALSE; + RETURN(EXP_DATA_NEW); + } + /* + * at this point we know that the event must be TCL_EXCEPTION + * indicating either EOF or HP ptytrap. + */ +#ifndef HAVE_PTYTRAP + RETURN(EXP_EOF); +#else + if (ioctl(esPtr->fdin,TIOCREQCHECK,&ioctl_info) < 0) { + expDiagLog("ioctl error on TIOCREQCHECK: %s", Tcl_PosixError(interp)); + RETURN(EXP_TCLERROR); + } + if (ioctl_info.request == TIOCCLOSE) { + RETURN(EXP_EOF); + } + if (ioctl(esPtr->fdin, TIOCREQSET, &ioctl_info) < 0) { + expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno)); + } + /* presumably, we trapped an open here */ + /* so simply continue by falling thru */ +#endif /* !HAVE_PTYTRAP */ + } + } + + if (!timerToken) { + if (timeout >= 0) { + timerToken = Tcl_CreateTimerHandler(1000*timeout, + exp_timehandler, + (ClientData)&timerFired); + } + } + + /* make sure that all fds that should be armed are */ + for (i=0;i<n;i++) { + esPtr = esPtrs[i]; + /*printf("CreateChannelHandler: %s\r\n",esPtr->name);*/ + Tcl_CreateChannelHandler( + esPtr->channel, + TCL_READABLE | TCL_EXCEPTION, + exp_channelhandler, + (ClientData)esPtr); + esPtr->fg_armed = TRUE; + } + + Tcl_DoOneEvent(0); /* do any event */ + + if (timerFired) return(EXP_TIMEOUT); + + if (old_configure_count != exp_configure_count) { + RETURN(EXP_RECONFIGURE); + } + } +} + +/* Having been told there was an event for a specific ExpState, get it */ +/* This returns status, one of EOF, TIMEOUT, ERROR or DATA */ +/*ARGSUSED*/ +int +exp_get_next_event_info(interp,esPtr) +Tcl_Interp *interp; +ExpState *esPtr; +{ +#ifdef HAVE_PTYTRAP + struct request_info ioctl_info; +#endif + + if (esPtr->notifiedMask & TCL_READABLE) return EXP_DATA_NEW; + + /* ready_mask must contain TCL_EXCEPTION */ +#ifndef HAVE_PTYTRAP + return(EXP_EOF); +#else + if (ioctl(esPtr->fdin,TIOCREQCHECK,&ioctl_info) < 0) { + expDiagLog("ioctl error on TIOCREQCHECK: %s", + Tcl_PosixError(interp)); + return(EXP_TCLERROR); + } + if (ioctl_info.request == TIOCCLOSE) { + return(EXP_EOF); + } + if (ioctl(esPtr->fdin, TIOCREQSET, &ioctl_info) < 0) { + expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno)); + } + /* presumably, we trapped an open here */ + /* call it an error for lack of anything more descriptive */ + /* it will be thrown away by caller anyway */ + return EXP_TCLERROR; +#endif +} + +/*ARGSUSED*/ +int /* returns TCL_XXX */ +exp_dsleep(interp,sec) +Tcl_Interp *interp; +double sec; +{ + int timerFired = FALSE; + + Tcl_CreateTimerHandler((int)(sec*1000),exp_timehandler,(ClientData)&timerFired); + + while (!timerFired) { + Tcl_DoOneEvent(0); + } + return TCL_OK; +} + +static char destroy_cmd[] = "destroy ."; + +static void +exp_event_exit_real(interp) +Tcl_Interp *interp; +{ + Tcl_Eval(interp,destroy_cmd); +} + +/* set things up for later calls to event handler */ +void +exp_init_event() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->rr = 0; + + exp_event_exit = exp_event_exit_real; +} diff --git a/exp_event.h b/exp_event.h new file mode 100644 index 0000000..5eb7561 --- /dev/null +++ b/exp_event.h @@ -0,0 +1,21 @@ +/* exp_event.h - event definitions */ + +int exp_get_next_event _ANSI_ARGS_((Tcl_Interp *,ExpState **, int, ExpState **, int, int)); +int exp_get_next_event_info _ANSI_ARGS_((Tcl_Interp *, ExpState *)); +int exp_dsleep _ANSI_ARGS_((Tcl_Interp *, double)); +void exp_init_event _ANSI_ARGS_((void)); + +extern void (*exp_event_exit) _ANSI_ARGS_((Tcl_Interp *)); + +void exp_event_disarm _ANSI_ARGS_((ExpState *,Tcl_FileProc *)); +void exp_event_disarm_bg _ANSI_ARGS_((ExpState *)); +void exp_event_disarm_fg _ANSI_ARGS_((ExpState *)); + +void exp_arm_background_channelhandler _ANSI_ARGS_((ExpState *)); +void exp_disarm_background_channelhandler _ANSI_ARGS_((ExpState *)); +void exp_disarm_background_channelhandler_force _ANSI_ARGS_((ExpState *)); +void exp_unblock_background_channelhandler _ANSI_ARGS_((ExpState *)); +void exp_block_background_channelhandler _ANSI_ARGS_((ExpState *)); + +void exp_background_channelhandler _ANSI_ARGS_((ClientData,int)); + diff --git a/exp_glob.c b/exp_glob.c new file mode 100644 index 0000000..4e2282c --- /dev/null +++ b/exp_glob.c @@ -0,0 +1,399 @@ +/* exp_glob.c - expect functions for doing glob + +Based on Tcl's glob functions but modified to support anchors and to +return information about the possibility of future matches + +Modifications by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" +#include "tcl.h" +#include "exp_int.h" + +/* Proper forward declaration of internal function */ +static int +Exp_StringCaseMatch2 _ANSI_ARGS_((CONST Tcl_UniChar *string, /* String. */ + CONST Tcl_UniChar *stop, /* First char _after_ string */ + CONST Tcl_UniChar *pattern, /* Pattern, which may contain + * special characters. */ + CONST Tcl_UniChar *pstop, /* First char _after_ pattern */ + int nocase)); + +/* The following functions implement expect's glob-style string matching */ +/* Exp_StringMatch allow's implements the unanchored front (or conversely */ +/* the '^') feature. Exp_StringMatch2 does the rest of the work. */ + +int /* returns # of CHARS that matched */ +Exp_StringCaseMatch(string, strlen, pattern, plen, nocase, offset) /* INTL */ + Tcl_UniChar *string; + Tcl_UniChar *pattern; + int strlen; + int plen; + int nocase; + int *offset; /* offset in chars from beginning of string where pattern matches */ +{ + CONST Tcl_UniChar *s; + CONST Tcl_UniChar *stop = string + strlen; + CONST Tcl_UniChar *pstop = pattern + plen; + int ssm, sm; /* count of bytes matched or -1 */ + int caret = FALSE; + int star = FALSE; + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog("\nESCM pattern(%d)=\"",plen); + expDiagLogU(expPrintifyUni(pattern,plen)); + expDiagLog("\"\n"); + expDiagLog(" string(%d)=\"",strlen); + expDiagLogU(expPrintifyUni(string,strlen)); + expDiagLog("\"\n"); + expDiagLog(" nocase=%d\n",nocase); +#endif + + *offset = 0; + + if (pattern[0] == '^') { + caret = TRUE; + pattern++; + } else if (pattern[0] == '*') { + star = TRUE; + } + + /* + * test if pattern matches in initial position. + * This handles front-anchor and 1st iteration of non-front-anchor. + * Note that 1st iteration must be tried even if string is empty. + */ + + sm = Exp_StringCaseMatch2(string,stop,pattern,pstop,nocase); + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog("@0 => %d\n",sm); +#endif + + if (sm >= 0) return(sm); + + if (caret) return -1; + if (star) return -1; + + if (*string == '\0') return -1; + + s = string + 1; + sm = 0; +#if 0 + if ((*pattern != '[') && (*pattern != '?') + && (*pattern != '\\') && (*pattern != '$') + && (*pattern != '*')) { + while (*s && (s < stop) && *pattern != *s) { + s++; + sm++; + } + } + if (sm) { + printf("skipped %d chars of %d\n", sm, strlen); fflush(stdout); + } +#endif + for (;s < stop; s++) { + ssm = Exp_StringCaseMatch2(s,stop,pattern,pstop,nocase); + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog("@%d => %d\n",s-string,ssm); +#endif + + if (ssm != -1) { + *offset = s-string; + return(ssm+sm); + } + } + return -1; +} + +/* Exp_StringCaseMatch2 -- + * + * Like Tcl_StringCaseMatch except that + * 1: returns number of characters matched, -1 if failed. + * (Can return 0 on patterns like "" or "$") + * 2: does not require pattern to match to end of string + * 3: Much of code is stolen from Tcl_StringMatch + * 4: front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor) +*/ + +static int +Exp_StringCaseMatch2(string,stop,pattern,pstop,nocase) /* INTL */ + register CONST Tcl_UniChar *string; /* String. */ + register CONST Tcl_UniChar *stop; /* First char _after_ string */ + register CONST Tcl_UniChar *pattern; /* Pattern, which may contain + * special characters. */ + register CONST Tcl_UniChar *pstop; /* First char _after_ pattern */ + int nocase; +{ + Tcl_UniChar ch1, ch2, p; + int match = 0; /* # of bytes matched */ + CONST Tcl_UniChar *oldString; + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" ESCM2 pattern=\""); + expDiagLogU(expPrintifyUni(pattern,pstop-pattern)); + expDiagLog("\"\n"); + expDiagLog(" string=\""); + expDiagLogU(expPrintifyUni(string,stop-string)); + expDiagLog("\"\n"); + expDiagLog(" nocase=%d\n",nocase); +#endif + + while (1) { +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" * ==========\n"); + expDiagLog(" * pattern=\""); + expDiagLogU(expPrintifyUni(pattern,pstop-pattern)); + expDiagLog("\"\n"); + expDiagLog(" * string=\""); + expDiagLogU(expPrintifyUni(string,stop-string)); + expDiagLog("\"\n"); +#endif + /* If at end of pattern, success! */ + if (pattern >= pstop) { + return match; + } + + /* If last pattern character is '$', verify that entire + * string has been matched. + */ + if ((*pattern == '$') && ((pattern + 1) >= pstop)) { + if (string == stop) return(match); + else return(-1); + } + + /* Check for a "*" as the next pattern character. It matches + * any substring. We handle this by calling ourselves + * recursively for each postfix of string, until either we match + * or we reach the end of the string. + * + * ZZZ: Check against Tcl core, port optimizations found there over here. + */ + + if (*pattern == '*') { + CONST Tcl_UniChar *tail; + + /* + * Skip all successive *'s in the pattern + */ + while ((pattern < pstop) && (*pattern == '*')) { + ++pattern; + } + + if (pattern >= pstop) { + return((stop-string)+match); /* DEL */ + } + + p = *pattern; + if (nocase) { + p = Tcl_UniCharToLower(p); + } + + /* find LONGEST match */ + + /* + * NOTES + * + * The original code used 'strlen' to find the end of the + * string. With the recursion coming this was done over and + * over again, making this an O(n**2) operation overall. Now + * the pointer to the end is passed in from the caller, and + * even the topmost context now computes it from start and + * length instead of seaching. + * + * The conversion to unicode also allow us to step back via + * decrement, in linear time overall. The previously used + * Tcl_UtfPrev crawled to the previous character from the + * beginning of the string, another O(n**2) operation. + */ + + tail = stop - 1; + while (1) { + int rc; +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" skip back '%c'\n",p); +#endif + /* + * Optimization for matching - cruise through the string + * quickly if the next char in the pattern isn't a special + * character. + * + * NOTE: We cruise backwards to keep the semantics of + * finding the LONGEST match. + * + * XXX JH: should this add '&& (p != '$')' ??? + */ + if ((p != '[') && (p != '?') && (p != '\\')) { + if (nocase) { + while ((tail >= string) && (p != *tail) + && (p != Tcl_UniCharToLower(*tail))) { + tail--;; + } + } else { + /* + * XXX JH: Should this be (tail > string)? + * ZZZ AK: No. tail == string is perfectly acceptable, + * if p == *tail. Backing before string is ok too, + * that is the condition to break the outer loop. + */ + while ((tail >= string) && (p != *tail)) { tail --; } + } + } + + /* if we've backed up to before the beginning of string, give up */ + if (tail < string) break; + + rc = Exp_StringCaseMatch2(tail, stop, pattern, pstop, nocase); +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" (*) rc=%d\n",rc); +#endif + if (rc != -1 ) { + return match + (tail - string) + rc; + /* match = # of bytes we've skipped before this */ + /* (...) = # of bytes we've skipped due to "*" */ + /* rc = # of bytes we've matched after "*" */ + } + + /* if we've backed up to beginning of string, give up */ + if (tail == string) break; + + tail --; + if (tail < string) tail = string; + } + return -1; /* DEL */ + } + + /* + * after this point, all patterns must match at least one + * character, so check this + */ + + if (string >= stop) return -1; + + /* Check for a "?" as the next pattern character. It matches + * any single character. + */ + + if (*pattern == '?') { + pattern++; + oldString = string; + string ++; + match ++; /* incr by # of matched chars */ + continue; + } + + /* Check for a "[" as the next pattern character. It is + * followed by a list of characters that are acceptable, or by a + * range (two characters separated by "-"). + */ + + if (*pattern == '[') { + Tcl_UniChar ch, startChar, endChar; + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" class\n"); +#endif + pattern++; + oldString = string; + ch = *string++; + + while (1) { + if ((pattern >= pstop) || (*pattern == ']')) { +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" end-of-pattern or class/1\n"); +#endif + return -1; /* was 0; DEL */ + } + startChar = *pattern ++; + if (nocase) { + startChar = Tcl_UniCharToLower(startChar); + } + if (*pattern == '-') { + pattern++; + if (pattern >= pstop) { +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" end-of-pattern/2\n"); +#endif + return -1; /* DEL */ + } + endChar = *pattern ++; + if (nocase) { + endChar = Tcl_UniCharToLower(endChar); + } + if (((startChar <= ch) && (ch <= endChar)) + || ((endChar <= ch) && (ch <= startChar))) { + /* + * Matches ranges of form [a-z] or [z-a]. + */ + +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" matched-range\n"); +#endif + break; + } + } else if (startChar == ch) { +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" matched-char\n"); +#endif + break; + } + } + while ((pattern < pstop) && (*pattern != ']')) { + pattern++; + } + if (pattern < pstop) { + /* + * Skip closing bracket if there was any. + * Fixes SF Bug 1873404. + */ + pattern++; + } +#ifdef EXP_INTERNAL_TRACE_GLOB + expDiagLog(" skipped remainder of pattern\n"); +#endif + match += (string - oldString); /* incr by # matched chars */ + continue; + } + + /* If the next pattern character is backslash, strip it off so + * we do exact matching on the character that follows. + */ + + if (*pattern == '\\') { + pattern ++; + if (pattern >= pstop) { + return -1; + } + } + + /* There's no special character. Just make sure that the next + * characters of each string match. + */ + + oldString = string; + ch1 = *string ++; + ch2 = *pattern ++; + if (nocase) { + if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) { + return -1; + } + } else if (ch1 != ch2) { + return -1; + } + match += (string - oldString); /* incr by # matched chars */ + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_int.h b/exp_int.h new file mode 100644 index 0000000..a7cd496 --- /dev/null +++ b/exp_int.h @@ -0,0 +1,39 @@ +/* exp_int.h - private symbols common to both expect program and library + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifndef _EXPECT_INT_H +#define _EXPECT_INT_H + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +#ifndef HAVE_MEMCPY +#define memcpy(x,y,len) bcopy(y,x,len) +#endif + +#include <errno.h> + +void exp_console_set _ANSI_ARGS_((void)); +void expDiagLogPtrSet _ANSI_ARGS_((void (*)_ANSI_ARGS_((char *)))); +void expDiagLogPtr _ANSI_ARGS_((char *)); +void expDiagLogPtrX _ANSI_ARGS_((char *,int)); +void expDiagLogPtrStr _ANSI_ARGS_((char *,char *)); +void expDiagLogPtrStrStr _ANSI_ARGS_((char *,char *,char *)); +void expErrnoMsgSet _ANSI_ARGS_((char * (*) _ANSI_ARGS_((int)))); +char * expErrnoMsg _ANSI_ARGS_((int)); + +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include <stdlib.h> /* for malloc */ +#endif /*NO_STDLIB_H*/ + +#endif /* _EXPECT_INT_H */ diff --git a/exp_inter.c b/exp_inter.c new file mode 100644 index 0000000..a7c2fbe --- /dev/null +++ b/exp_inter.c @@ -0,0 +1,2263 @@ +/* interact (using select) - give user keyboard control + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" +#include <stdio.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include <ctype.h> + +#include "tclInt.h" +#include "string.h" + +#include "exp_tty_in.h" +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" +#include "exp_event.h" /* exp_get_next_event decl */ + +/* Tcl 8.5+ moved this internal - needed for when I compile expect against 8.5. */ +#ifndef TCL_REG_BOSONLY +#define TCL_REG_BOSONLY 002000 +#endif + +typedef struct ThreadSpecificData { + Tcl_Obj *cmdObjReturn; + Tcl_Obj *cmdObjInterpreter; +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +#define INTER_OUT "interact_out" +#define out(var,val) \ + expDiagLog("interact: set %s(%s) ",INTER_OUT,var); \ + expDiagLogU(expPrintify(val)); \ + expDiagLogU("\"\r\n"); \ + Tcl_SetVar2(interp,INTER_OUT,var,val,0); + +/* + * tests if we are running this using a real tty + * + * these tests are currently only used to control what gets written to the + * logfile. Note that removal of the test of "..._is_tty" means that stdin + * or stdout could be redirected and yet stdout would still be logged. + * However, it's not clear why anyone would use log_file when these are + * redirected in the first place. On the other hand, it is reasonable to + * run expect as a daemon in which case, stdin/out do not appear to be + * ttys, yet it makes sense for them to be logged with log_file as if they + * were. + */ +#if 0 +#define real_tty_output(x) (exp_stdout_is_tty && (((x)==1) || ((x)==exp_dev_tty))) +#define real_tty_input(x) (exp_stdin_is_tty && (((x)==0) || ((x)==exp_dev_tty))) +#endif + +#define real_tty_output(x) ((x->fdout == 1) || (expDevttyIs(x))) +#define real_tty_input(x) (exp_stdin_is_tty && ((x->fdin==0) || (expDevttyIs(x)))) + +#define new(x) (x *)ckalloc(sizeof(x)) + +struct action { + Tcl_Obj *statement; + int tty_reset; /* if true, reset tty mode upon action */ + int iread; /* if true, reread indirects */ + int iwrite; /* if true, write spawn_id element */ + struct action *next; /* chain only for later for freeing */ +}; + +struct keymap { + Tcl_Obj *keys; /* original pattern provided by user */ + int re; /* true if looking to match a regexp. */ + int null; /* true if looking to match 0 byte */ + int case_sensitive; + int echo; /* if keystrokes should be echoed */ + int writethru; /* if keystrokes should go through to process */ + int indices; /* true if should write indices */ + struct action action; + struct keymap *next; +}; + +struct output { + struct exp_i *i_list; + struct action *action_eof; + struct output *next; +}; + +struct input { + struct exp_i *i_list; + struct output *output; + struct action *action_eof; + struct action *action_timeout; + struct keymap *keymap; + int timeout_nominal; /* timeout nominal */ + int timeout_remaining; /* timeout remaining */ + struct input *next; +}; + +/* + * Once we are handed an ExpState from the event handler, we can figure out + * which "struct input *" it references by using expStateToInput. This has is + * populated by expCreateStateToInput. + */ + +struct input * +expStateToInput( + Tcl_HashTable *hash, + ExpState *esPtr) +{ + Tcl_HashEntry *entry = Tcl_FindHashEntry(hash,(char *)esPtr); + + if (!entry) { + /* should never happen */ + return 0; + } + return ((struct input *)Tcl_GetHashValue(entry)); +} + +void +expCreateStateToInput( + Tcl_HashTable *hash, + ExpState *esPtr, + struct input *inp) +{ + Tcl_HashEntry *entry; + int newPtr; + + entry = Tcl_CreateHashEntry(hash,(char *)esPtr,&newPtr); + Tcl_SetHashValue(entry,(ClientData)inp); +} + +static void free_input(Tcl_Interp *interp, struct input *i); +static void free_keymap(struct keymap *km); +static void free_output(Tcl_Interp *interp, struct output *o); +static void free_action(struct action *a); +static struct action *new_action(struct action **base); +static int inter_eval( + Tcl_Interp *interp, + struct action *action, + ExpState *esPtr); + +/* intMatch() accepts user keystrokes and returns one of MATCH, +CANMATCH, or CANTMATCH. These describe whether the keystrokes match a +key sequence, and could or can't if more characters arrive. The +function assigns a matching keymap if there is a match or can-match. +A matching keymap is assigned on can-match so we know whether to echo +or not. + +intMatch is optimized (if you can call it that) towards a small +number of key mappings, but still works well for large maps, since no +function calls are made, and we stop as soon as there is a single-char +mismatch, and go on to the next one. A hash table or compiled DFA +probably would not buy very much here for most maps. + +The basic idea of how this works is it does a smart sequential search. +At each position of the input string, we attempt to match each of the +keymaps. If at least one matches, the first match is returned. + +If there is a CANMATCH and there are more keymaps to try, we continue +trying. If there are no more keymaps to try, we stop trying and +return with an indication of the first keymap that can match. + +Note that I've hacked up the regexp pattern matcher in two ways. One +is to force the pattern to always be anchored at the front. That way, +it doesn't waste time attempting to match later in the string (before +we're ready). The other is to return can-match. + +*/ + +static int +intMatch( + ExpState *esPtr, + struct keymap *keymap, /* linked list of keymaps */ + struct keymap **km_match, /* keymap that matches or can match */ + int *matchLen, /* # of bytes that matched */ + int *skip, /* # of chars to skip */ + Tcl_RegExpInfo *info) +{ + Tcl_UniChar *string; + struct keymap *km; + char *ks; /* string from a keymap */ + + Tcl_UniChar *start_search; /* where in string to start searching */ + int offset; /* # of chars from string to start searching */ + + Tcl_UniChar *string_end; + int numchars; + int rm_nulls; /* skip nulls if true */ + Tcl_UniChar ch; + + string = esPtr->input.buffer; + numchars = esPtr->input.use; /* Actually #chars */ + + /* assert (*km == 0) */ + + /* a shortcut that should help master output which typically */ + /* is lengthy and has no key maps. Otherwise it would mindlessly */ + /* iterate on each character anyway. */ + if (!keymap) { + *skip = numchars; + return(EXP_CANTMATCH); + } + + rm_nulls = esPtr->rm_nulls; + + string_end = string + numchars; + + /* + * Maintain both a character index and a string pointer so we + * can easily index into either the UTF or the Unicode representations. + */ + + for (start_search = string, offset = 0; + start_search < string_end; + start_search ++, offset++) { + + ch = *start_search; + + if (*km_match) break; /* if we've already found a CANMATCH */ + /* don't bother starting search from positions */ + /* further along the string */ + + for (km=keymap;km;km=km->next) { + Tcl_UniChar *s; /* current character being examined */ + + if (km->null) { + if (ch == 0) { + *skip = start_search-string; + *matchLen = 1; /* s - start_search == 1 */ + *km_match = km; + return(EXP_MATCH); + } + } else if (!km->re) { + int kslen; + Tcl_UniChar sch, ksch; + + /* fixed string */ + + ks = Tcl_GetString(km->keys); + for (s = start_search;; s++, ks += kslen) { + /* if we hit the end of this map, must've matched! */ + if (*ks == 0) { + *skip = start_search-string; + *matchLen = s-start_search; + *km_match = km; + return(EXP_MATCH); + } + + /* if we ran out of user-supplied characters, and */ + /* still haven't matched, it might match if the user */ + /* supplies more characters next time */ + + if (s == string_end) { + /* skip to next key entry, but remember */ + /* possibility that this entry might match */ + if (!*km_match) *km_match = km; + break; + } + + sch = *s; + kslen = Tcl_UtfToUniChar(ks, &ksch); + + if (sch == ksch) continue; + if ((sch == '\0') && rm_nulls) { + kslen = 0; + continue; + } + break; + } + } else { + /* regexp */ + Tcl_RegExp re; + int flags; + int result; + Tcl_Obj* buf; + + re = Tcl_GetRegExpFromObj(NULL, km->keys, + TCL_REG_ADVANCED|TCL_REG_BOSONLY|TCL_REG_CANMATCH); + flags = (offset > 0) ? TCL_REG_NOTBOL : 0; + + /* ZZZ: Future optimization: Avoid copying */ + buf = Tcl_NewUnicodeObj (esPtr->input.buffer, esPtr->input.use); + Tcl_IncrRefCount (buf); + result = Tcl_RegExpExecObj(NULL, re, buf, offset, + -1 /* nmatches */, flags); + Tcl_DecrRefCount (buf); + if (result > 0) { + *km_match = km; + *skip = start_search-string; + Tcl_RegExpGetInfo(re, info); + *matchLen = info->matches[0].end; + return EXP_MATCH; + } else if (result == 0) { + Tcl_RegExpGetInfo(re, info); + + /* + * Check to see if there was a partial match starting + * at the current character. + */ + if (info->extendStart == 0) { + if (!*km_match) *km_match = km; + } + } + } + } + } + + if (*km_match) { + /* report CANMATCH for -re and -ex */ + + /* + * since canmatch is only detected after we've advanced too far, + * adjust start_search back to make other computations simpler + */ + start_search--; + + *skip = start_search - string; + *matchLen = string_end - start_search; + return(EXP_CANMATCH); + } + + *skip = start_search-string; + return(EXP_CANTMATCH); +} + +/* put regexp result in variables */ +static void +intRegExpMatchProcess( + Tcl_Interp *interp, + ExpState *esPtr, + struct keymap *km, /* ptr for above while parsing */ + Tcl_RegExpInfo *info, + int offset) +{ + char name[20], value[20]; + int i; + Tcl_Obj* buf = Tcl_NewUnicodeObj (esPtr->input.buffer,esPtr->input.use); + + for (i=0;i<=info->nsubs;i++) { + int start, end; + Tcl_Obj *val; + + start = info->matches[i].start + offset; + if (start == -1) continue; + end = (info->matches[i].end-1) + offset; + + if (km->indices) { + /* start index */ + sprintf(name,"%d,start",i); + sprintf(value,"%d",start); + out(name,value); + + /* end index */ + sprintf(name,"%d,end",i); + sprintf(value,"%d",end); + out(name,value); + } + + /* string itself */ + sprintf(name,"%d,string",i); + val = Tcl_GetRange(buf, start, end); + expDiagLog("interact: set %s(%s) \"",INTER_OUT,name); + expDiagLogU(expPrintifyObj(val)); + expDiagLogU("\"\r\n"); + Tcl_SetVar2Ex(interp,INTER_OUT,name,val,0); + } + Tcl_DecrRefCount (buf); +} + +/* + * echo chars + */ +static void +intEcho( + ExpState *esPtr, + int skipBytes, + int matchBytes) +{ + int seenBytes; /* either printed or echoed */ + int echoBytes; + int offsetBytes; + + /* write is unlikely to fail, since we just read from same descriptor */ + seenBytes = esPtr->printed + esPtr->echoed; + if (skipBytes >= seenBytes) { + echoBytes = matchBytes; + offsetBytes = skipBytes; + } else if ((matchBytes + skipBytes - seenBytes) > 0) { + echoBytes = matchBytes + skipBytes - seenBytes; + offsetBytes = seenBytes; + } + + (void) expWriteCharsUni(esPtr, + esPtr->input.buffer + offsetBytes, + echoBytes); + + esPtr->echoed = matchBytes + skipBytes - esPtr->printed; +} + +/* + * intRead() does the logical equivalent of a read() for the interact command. + * Returns # of bytes read or negative number (EXP_XXX) indicating unusual event. + */ +static int +intRead( + Tcl_Interp *interp, + ExpState *esPtr, + int warnOnBufferFull, + int interruptible, + int key) +{ + Tcl_UniChar *eobOld; /* old end of buffer */ + int cc; + int numchars; + Tcl_UniChar *str; + + str = esPtr->input.buffer; + numchars = esPtr->input.use; + eobOld = str + numchars; + + /* We drop one third when are at least 2/3 full */ + /* condition is (size >= max*2/3) <=> (size*3 >= max*2) */ + if (numchars*3 >= esPtr->input.max*2) { + /* + * In theory, interact could be invoked when this situation + * already exists, hence the "probably" in the warning below + */ + if (warnOnBufferFull) { + expDiagLogU("WARNING: interact buffer is full, probably because your\r\n"); + expDiagLogU("patterns have matched all of it but require more chars\r\n"); + expDiagLogU("in order to complete the match.\r\n"); + expDiagLogU("Dumping first half of buffer in order to continue\r\n"); + expDiagLogU("Recommend you enlarge the buffer or fix your patterns.\r\n"); + } + exp_buffer_shuffle(interp,esPtr,0,INTER_OUT,"interact"); + } + if (!interruptible) { + cc = Tcl_ReadChars(esPtr->channel, esPtr->input.newchars, + esPtr->input.max - esPtr->input.use, + 0 /* no append */); + } else { +#ifdef SIMPLE_EVENT + cc = intIRead(esPtr->channel, esPtr->input.newchars, + esPtr->input.max - esPtr->input.use, + 0 /* no append */); +#endif + } + + if (cc > 0) { + memcpy (esPtr->input.buffer + esPtr->input.use, + Tcl_GetUnicodeFromObj (esPtr->input.newchars, NULL), + cc * sizeof (Tcl_UniChar)); + esPtr->input.use += cc; + + expDiagLog("spawn id %s sent <",esPtr->name); + expDiagLogU(expPrintifyUni(eobOld,cc)); + expDiagLogU(">\r\n"); + + esPtr->key = key; + } + return cc; +} + + + +#ifdef SIMPLE_EVENT + +/* + +The way that the "simple" interact works is that the original Expect +process reads from the tty and writes to the spawned process. A child +process is forked to read from the spawned process and write to the +tty. It looks like this: + + user + --> tty >-- + / \ + ^ v + child original + process Expect + ^ process + | v + \ / + < spawned < + process + +*/ + + + +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff) +#endif + +#include <setjmp.h> + +#ifdef HAVE_SIGLONGJMP +static sigjmp_buf env; /* for interruptable read() */ +#else +static jmp_buf env; /* for interruptable read() */ +#endif /* HAVE_SIGLONGJMP */ + +static int reading; /* while we are reading */ + /* really, while "env" is valid */ +static int deferred_interrupt = FALSE; /* if signal is received, but not */ + /* in expIRead record this here, so it will */ + /* be handled next time through expIRead */ + +static void +sigchld_handler() +{ + if (reading) { +#ifdef HAVE_SIGLONGJMP + siglongjmp(env,1); +#else + longjmp(env,1); +#endif /* HAVE_SIGLONGJMP */ + } + deferred_interrupt = TRUE; +} + +#define EXP_CHILD_EOF -100 + +/* + * Name: expIRead, do an interruptable read + * + * intIRead() reads from chars from the user. + * + * It returns early if it detects the death of a proc (either the spawned + * process or the child (surrogate). + */ +static int +intIRead( + Tcl_Channel channel, + Tcl_Obj *obj, + int size, + int flags) +{ + int cc = EXP_CHILD_EOF; + + if (deferred_interrupt) return(cc); + + if ( +#ifdef HAVE_SIGLONGJMP + 0 == sigsetjmp(env,1) +#else + 0 == setjmp(env) +#endif /* HAVE_SIGLONGJMP */ + ) { + reading = TRUE; + cc = Tcl_ReadChars(channel,obj,size,flags); + } + reading = FALSE; + return(cc); +} + +/* exit status for the child process created by cmdInteract */ +#define CHILD_DIED -2 +#define SPAWNED_PROCESS_DIED -3 + +static void +clean_up_after_child( + Tcl_Interp *interp, + ExpState *esPtr) +{ + expWaitOnOne(); /* wait for slave */ + expWaitOnOne(); /* wait for child */ + + deferred_interrupt = FALSE; + if (esPtr->close_on_eof) { + exp_close(interp,esPtr); +} +} +#endif /*SIMPLE_EVENT*/ + +static int +update_interact_fds( + Tcl_Interp *interp, + int *esPtrCount, + Tcl_HashTable **esPtrToInput, /* map from ExpStates to "struct inputs" */ + ExpState ***esPtrs, + struct input *input_base, + int do_indirect, /* if true do indirects */ + int *config_count, + int *real_tty_caller) +{ + struct input *inp; + struct output *outp; + struct exp_state_list *fdp; + int count; + + int real_tty = FALSE; + + *config_count = exp_configure_count; + + count = 0; + for (inp = input_base;inp;inp=inp->next) { + + if (do_indirect) { + /* do not update "direct" entries (again) */ + /* they were updated upon creation */ + if (inp->i_list->direct == EXP_INDIRECT) { + exp_i_update(interp,inp->i_list); + } + for (outp = inp->output;outp;outp=outp->next) { + if (outp->i_list->direct == EXP_INDIRECT) { + exp_i_update(interp,outp->i_list); + } + } + } + + /* revalidate all input descriptors */ + for (fdp = inp->i_list->state_list;fdp;fdp=fdp->next) { + count++; + /* have to "adjust" just in case spawn id hasn't had */ + /* a buffer sized yet */ + if (!expStateCheck(interp,fdp->esPtr,1,1,"interact")) { + return(TCL_ERROR); + } + } + + /* revalidate all output descriptors */ + for (outp = inp->output;outp;outp=outp->next) { + for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) { + /* make user_spawn_id point to stdout */ + if (!expStdinoutIs(fdp->esPtr)) { + if (!expStateCheck(interp,fdp->esPtr,1,0,"interact")) + return(TCL_ERROR); + } + } + } + } + if (!do_indirect) return TCL_OK; + + if (*esPtrToInput == 0) { + *esPtrToInput = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable)); + *esPtrs = (ExpState **)ckalloc(count * sizeof(ExpState *)); + } else { + /* if hash table already exists, delete it and start over */ + Tcl_DeleteHashTable(*esPtrToInput); + *esPtrs = (ExpState **)ckrealloc((char *)*esPtrs,count * sizeof(ExpState *)); + } + Tcl_InitHashTable(*esPtrToInput,TCL_ONE_WORD_KEYS); + + count = 0; + for (inp = input_base;inp;inp=inp->next) { + for (fdp = inp->i_list->state_list;fdp;fdp=fdp->next) { + /* build map to translate from spawn_id to struct input */ + expCreateStateToInput(*esPtrToInput,fdp->esPtr,inp); + + /* build input to ready() */ + (*esPtrs)[count] = fdp->esPtr; + + if (real_tty_input(fdp->esPtr)) real_tty = TRUE; + + count++; + } + } + *esPtrCount = count; + + *real_tty_caller = real_tty; /* tell caller if we have found that */ + /* we are using real tty */ + + return TCL_OK; +} + +/*ARGSUSED*/ +static char * +inter_updateproc( + ClientData clientData, + Tcl_Interp *interp, /* Interpreter containing variable. */ + char *name1, /* Name of variable. */ + char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ +{ + exp_configure_count++; + return 0; +} + +#define finish(x) { status = x; goto done; } + +static char return_cmd[] = "return"; +static char interpreter_cmd[] = "interpreter"; + +/*ARGSUSED*/ +int +Exp_InteractObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST initial_objv[]) /* Argument objects. */ +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_Obj *CONST *objv_copy; /* original, for error messages */ + Tcl_Obj **objv = (Tcl_Obj **) initial_objv; + char *string; + Tcl_UniChar *ustring; + +#ifdef SIMPLE_EVENT + int pid; +#endif /*SIMPLE_EVENT*/ + + /*declarations*/ + int input_count; /* count of struct input descriptors */ + + Tcl_HashTable *esPtrToInput = 0; /* map from ExpState to "struct inputs" */ + ExpState **esPtrs; + struct keymap *km; /* ptr for above while parsing */ + Tcl_RegExpInfo reInfo; + ExpState *u = 0; + ExpState *esPtr = 0; + Tcl_Obj *chanName = 0; + int need_to_close_master = FALSE; /* if an eof is received */ + /* we use this to defer close until later */ + + int next_tty_reset = FALSE; /* if we've seen a single -reset */ + int next_iread = FALSE;/* if we've seen a single -iread */ + int next_iwrite = FALSE;/* if we've seen a single -iread */ + int next_re = FALSE; /* if we've seen a single -re */ + int next_null = FALSE; /* if we've seen the null keyword */ + int next_writethru = FALSE;/*if macros should also go to proc output */ + int next_indices = FALSE;/* if we should write indices */ + int next_echo = FALSE; /* if macros should be echoed */ + int status = TCL_OK; /* final return value */ + int i; /* misc temp */ + int size; /* size temp */ + + int timeout_simple = TRUE; /* if no or global timeout */ + + int real_tty; /* TRUE if we are interacting with real tty */ + int tty_changed = FALSE;/* true if we had to change tty modes for */ + /* interact to work (i.e., to raw, noecho) */ + int was_raw; + int was_echo; + exp_tty tty_old; + + Tcl_Obj *replace_user_by_process = 0; /* for -u flag */ + + struct input *input_base; +#define input_user input_base + struct input *input_default; + struct input *inp; /* overused ptr to struct input */ + struct output *outp; /* overused ptr to struct output */ + + int dash_input_count = 0; /* # of "-input"s seen */ + int dash_o_count = 0; /* # of "-o"s seen */ + int arbitrary_timeout; + int default_timeout; + struct action action_timeout; /* common to all */ + struct action action_eof; /* common to all */ + struct action **action_eof_ptr; /* allow -input/ouput to */ + /* leave their eof-action assignable by a later */ + /* -eof */ + struct action *action_base = 0; + struct keymap **end_km; + + int key; + int configure_count; /* monitor reconfigure events */ + Tcl_Obj* new_cmd = NULL; + + if ((objc == 2) && exp_one_arg_braced(objv[1])) { + /* expect {...} */ + + new_cmd = exp_eval_with_one_arg(clientData,interp,objv); + if (!new_cmd) return TCL_ERROR; + + /* Replace old arguments with result of reparse */ + Tcl_ListObjGetElements (interp, new_cmd, &objc, &objv); + + } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) { + /* expect -brace {...} ... fake command line for reparsing */ + + Tcl_Obj *new_objv[2]; + new_objv[0] = objv[0]; + new_objv[1] = objv[2]; + + new_cmd = exp_eval_with_one_arg(clientData,interp,new_objv); + if (!new_cmd) return TCL_ERROR; + /* Replace old arguments with result of reparse */ + Tcl_ListObjGetElements (interp, new_cmd, &objc, &objv); + } + + objv_copy = objv; + + objv++; + objc--; + + default_timeout = EXP_TIME_INFINITY; + arbitrary_timeout = EXP_TIME_INFINITY; /* if user specifies */ + /* a bunch of timeouts with EXP_TIME_INFINITY, this will be */ + /* left around for us to find. */ + + input_user = new(struct input); + input_user->i_list = exp_new_i_simple(expStdinoutGet(),EXP_TEMPORARY); /* stdin by default */ + input_user->output = 0; + input_user->action_eof = &action_eof; + input_user->timeout_nominal = EXP_TIME_INFINITY; + input_user->action_timeout = 0; + input_user->keymap = 0; + + end_km = &input_user->keymap; + inp = input_user; + action_eof_ptr = &input_user->action_eof; + + input_default = new(struct input); + input_default->i_list = exp_new_i_simple((ExpState *)0,EXP_TEMPORARY); /* fix up later */ + input_default->output = 0; + input_default->action_eof = &action_eof; + input_default->timeout_nominal = EXP_TIME_INFINITY; + input_default->action_timeout = 0; + input_default->keymap = 0; + input_default->next = 0; /* no one else */ + input_user->next = input_default; + + /* default and common -eof action */ + action_eof.statement = tsdPtr->cmdObjReturn; + action_eof.tty_reset = FALSE; + action_eof.iread = FALSE; + action_eof.iwrite = FALSE; + + /* + * Parse the command arguments. + */ + for (;objc>0;objc--,objv++) { + string = Tcl_GetString(*objv); + if (string[0] == '-') { + static char *switches[] = { + "--", "-exact", "-re", "-input", + "-output", "-u", "-o", "-i", + "-echo", "-nobuffer", "-indices", "-f", + "-reset", "-F", "-iread", "-iwrite", + "-eof", "-timeout", "-nobrace", (char *)0 + }; + enum switches { + EXP_SWITCH_DASH, EXP_SWITCH_EXACT, + EXP_SWITCH_REGEXP, EXP_SWITCH_INPUT, + EXP_SWITCH_OUTPUT, EXP_SWITCH_USER, + EXP_SWITCH_OPPOSITE, EXP_SWITCH_SPAWN_ID, + EXP_SWITCH_ECHO, EXP_SWITCH_NOBUFFER, + EXP_SWITCH_INDICES, EXP_SWITCH_FAST, + EXP_SWITCH_RESET, EXP_SWITCH_CAPFAST, + EXP_SWITCH_IREAD, EXP_SWITCH_IWRITE, + EXP_SWITCH_EOF, EXP_SWITCH_TIMEOUT, + EXP_SWITCH_NOBRACE + }; + int index; + + /* + * Allow abbreviations of switches and report an error if we + * get an invalid switch. + */ + + if (Tcl_GetIndexFromObj(interp, *objv, switches, "switch", 0, + &index) != TCL_OK) { + goto error; + } + switch ((enum switches) index) { + case EXP_SWITCH_DASH: + case EXP_SWITCH_EXACT: + objc--; + objv++; + goto pattern; + case EXP_SWITCH_REGEXP: + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"-re pattern"); + goto error; + } + next_re = TRUE; + objc--; + objv++; + + /* + * Try compiling the expression so we can report + * any errors now rather then when we first try to + * use it. + */ + + if (!(Tcl_GetRegExpFromObj(interp, *objv, + TCL_REG_ADVANCED|TCL_REG_BOSONLY))) { + goto error; + } + goto pattern; + case EXP_SWITCH_INPUT: + dash_input_count++; + if (dash_input_count == 2) { + inp = input_default; + input_user->next = input_default; + } else if (dash_input_count > 2) { + struct input *previous_input = inp; + inp = new(struct input); + previous_input->next = inp; + } + inp->output = 0; + inp->action_eof = &action_eof; + action_eof_ptr = &inp->action_eof; + inp->timeout_nominal = default_timeout; + inp->action_timeout = &action_timeout; + inp->keymap = 0; + end_km = &inp->keymap; + inp->next = 0; + objc--;objv++; + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"-input spawn_id"); + goto error; + } + inp->i_list = exp_new_i_complex(interp,Tcl_GetString(*objv), + EXP_TEMPORARY,inter_updateproc); + if (!inp->i_list) { + goto error; + } + break; + case EXP_SWITCH_OUTPUT: { + struct output *tmp; + + /* imply a "-input" */ + if (dash_input_count == 0) dash_input_count = 1; + + outp = new(struct output); + + /* link new output in front of others */ + tmp = inp->output; + inp->output = outp; + outp->next = tmp; + + objc--;objv++; + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"-output spawn_id"); + goto error; + } + outp->i_list = exp_new_i_complex(interp,Tcl_GetString(*objv), + EXP_TEMPORARY,inter_updateproc); + if (!outp->i_list) { + goto error; + } + outp->action_eof = &action_eof; + action_eof_ptr = &outp->action_eof; + break; + } + case EXP_SWITCH_USER: + objc--;objv++; + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"-u spawn_id"); + goto error; + } + replace_user_by_process = *objv; + + /* imply a "-input" */ + if (dash_input_count == 0) dash_input_count = 1; + break; + case EXP_SWITCH_OPPOSITE: + /* apply following patterns to opposite side */ + /* of interaction */ + + end_km = &input_default->keymap; + + if (dash_o_count > 0) { + exp_error(interp,"cannot use -o more than once"); + goto error; + } + dash_o_count++; + + /* imply two "-input" */ + if (dash_input_count < 2) { + dash_input_count = 2; + inp = input_default; + action_eof_ptr = &inp->action_eof; + } + break; + case EXP_SWITCH_SPAWN_ID: + /* substitute master */ + + objc--;objv++; + chanName = *objv; + /* will be used later on */ + + end_km = &input_default->keymap; + + /* imply two "-input" */ + if (dash_input_count < 2) { + dash_input_count = 2; + inp = input_default; + action_eof_ptr = &inp->action_eof; + } + break; + case EXP_SWITCH_ECHO: + next_echo = TRUE; + break; + case EXP_SWITCH_NOBUFFER: + next_writethru = TRUE; + break; + case EXP_SWITCH_INDICES: + next_indices = TRUE; + break; + case EXP_SWITCH_RESET: + next_tty_reset = TRUE; + break; + case EXP_SWITCH_IREAD: + next_iread = TRUE; + break; + case EXP_SWITCH_IWRITE: + next_iwrite= TRUE; + break; + case EXP_SWITCH_EOF: { + struct action *action; + + objc--;objv++; + expDiagLogU("-eof is deprecated, use eof\r\n"); + *action_eof_ptr = action = new_action(&action_base); + action->statement = *objv; + action->tty_reset = next_tty_reset; + next_tty_reset = FALSE; + action->iwrite = next_iwrite; + next_iwrite = FALSE; + action->iread = next_iread; + next_iread = FALSE; + break; + } + case EXP_SWITCH_TIMEOUT: { + int t; + struct action *action; + expDiagLogU("-timeout is deprecated, use timeout\r\n"); + + objc--;objv++; + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"-timeout time"); + goto error; + } + + if (Tcl_GetIntFromObj(interp, *objv, &t) != TCL_OK) { + goto error; + } + objc--;objv++; + if (t != -1) + arbitrary_timeout = t; + /* we need an arbitrary timeout to start */ + /* search for lowest one later */ + + timeout_simple = FALSE; + action = inp->action_timeout = new_action(&action_base); + inp->timeout_nominal = t; + + action->statement = *objv; + action->tty_reset = next_tty_reset; + next_tty_reset = FALSE; + action->iwrite = next_iwrite; + next_iwrite = FALSE; + action->iread = next_iread; + next_iread = FALSE; + break; + } + case EXP_SWITCH_FAST: + case EXP_SWITCH_CAPFAST: + /* noop compatibility switches for fast mode */ + break; + case EXP_SWITCH_NOBRACE: + /* nobrace does nothing but take up space */ + /* on the command line which prevents */ + /* us from re-expanding any command lines */ + /* of one argument that looks like it should */ + /* be expanded to multiple arguments. */ + break; + } + continue; + } else { + static char *options[] = { + "eof", "timeout", "null", (char *)0 + }; + enum options { + EXP_OPTION_EOF, EXP_OPTION_TIMEOUT, EXP_OPTION_NULL + }; + int index; + + /* + * Match keywords exactly, otherwise they are patterns. + */ + + if (Tcl_GetIndexFromObj(interp, *objv, options, "option", + 1 /* exact */, &index) != TCL_OK) { + Tcl_ResetResult(interp); + goto pattern; + } + switch ((enum options) index) { + case EXP_OPTION_EOF: { + struct action *action; + + objc--;objv++; + *action_eof_ptr = action = new_action(&action_base); + + action->statement = *objv; + + action->tty_reset = next_tty_reset; + next_tty_reset = FALSE; + action->iwrite = next_iwrite; + next_iwrite = FALSE; + action->iread = next_iread; + next_iread = FALSE; + break; + } + case EXP_OPTION_TIMEOUT: { + int t; + struct action *action; + + objc--;objv++; + if (objc < 1) { + Tcl_WrongNumArgs(interp,1,objv_copy,"timeout time [action]"); + goto error; + } + if (Tcl_GetIntFromObj(interp, *objv, &t) != TCL_OK) { + goto error; + } + objc--;objv++; + + /* we need an arbitrary timeout to start */ + /* search for lowest one later */ + if (t != -1) arbitrary_timeout = t; + + timeout_simple = FALSE; + action = inp->action_timeout = new_action(&action_base); + inp->timeout_nominal = t; + + if (objc >= 1) { + action->statement = *objv; + } else { + action->statement = 0; + } + + action->tty_reset = next_tty_reset; + next_tty_reset = FALSE; + action->iwrite = next_iwrite; + next_iwrite = FALSE; + action->iread = next_iread; + next_iread = FALSE; + break; + } + case EXP_OPTION_NULL: + next_null = TRUE; + goto pattern; + } + continue; + } + + /* + * pick up the pattern + */ + + pattern: + km = new(struct keymap); + + /* so that we can match in order user specified */ + /* link to end of keymap list */ + *end_km = km; + km->next = 0; + end_km = &km->next; + + km->echo = next_echo; + km->writethru = next_writethru; + km->indices = next_indices; + km->action.tty_reset = next_tty_reset; + km->action.iwrite = next_iwrite; + km->action.iread = next_iread; + + next_indices = next_echo = next_writethru = FALSE; + next_tty_reset = FALSE; + next_iwrite = next_iread = FALSE; + + km->keys = *objv; + + km->null = FALSE; + km->re = 0; + if (next_re) { + km->re = TRUE; + next_re = FALSE; + } + if (next_null) { + km->null = TRUE; + next_null = FALSE; + } + + objc--;objv++; + if (objc >= 1) { + km->action.statement = *objv; + } else { + km->action.statement = 0; + } + + expDiagLogU("defining key "); + expDiagLogU(Tcl_GetString(km->keys)); + expDiagLogU(", action "); + expDiagLogU(km->action.statement?expPrintify(Tcl_GetString(km->action.statement)):"interpreter"); + expDiagLogU("\r\n"); + + /* imply a "-input" */ + if (dash_input_count == 0) dash_input_count = 1; + } + + /* if the user has not supplied either "-output" for the */ + /* default two "-input"s, fix them up here */ + + if (!input_user->output) { + struct output *o = new(struct output); + if (!chanName) { + if (!(esPtr = expStateCurrent(interp,1,1,0))) { + goto error; + } + o->i_list = exp_new_i_simple(esPtr,EXP_TEMPORARY); + } else { + o->i_list = exp_new_i_complex(interp,Tcl_GetString(chanName), + EXP_TEMPORARY,inter_updateproc); + if (!o->i_list) { + goto error; + } + } + o->next = 0; /* no one else */ + o->action_eof = &action_eof; + input_user->output = o; + } + + if (!input_default->output) { + struct output *o = new(struct output); + o->i_list = exp_new_i_simple(expStdinoutGet(),EXP_TEMPORARY);/* stdout by default */ + o->next = 0; /* no one else */ + o->action_eof = &action_eof; + input_default->output = o; + } + + /* if user has given "-u" flag, substitute process for user */ + /* in first two -inputs */ + if (replace_user_by_process) { + /* through away old ones */ + exp_free_i(interp,input_user->i_list, inter_updateproc); + exp_free_i(interp,input_default->output->i_list,inter_updateproc); + + /* replace with arg to -u */ + input_user->i_list = exp_new_i_complex(interp, + Tcl_GetString(replace_user_by_process), + EXP_TEMPORARY,inter_updateproc); + if (!input_user->i_list) + goto error; + input_default->output->i_list = exp_new_i_complex(interp, + Tcl_GetString(replace_user_by_process), + EXP_TEMPORARY,inter_updateproc); + if (!input_default->output->i_list) + goto error; + } + + /* + * now fix up for default spawn id + */ + + /* user could have replaced it with an indirect, so force update */ + if (input_default->i_list->direct == EXP_INDIRECT) { + exp_i_update(interp,input_default->i_list); + } + + if (input_default->i_list->state_list + && (input_default->i_list->state_list->esPtr == EXP_SPAWN_ID_BAD)) { + if (!chanName) { + if (!(esPtr = expStateCurrent(interp,1,1,0))) { + goto error; + } + input_default->i_list->state_list->esPtr = esPtr; + } else { + /* discard old one and install new one */ + exp_free_i(interp,input_default->i_list,inter_updateproc); + input_default->i_list = exp_new_i_complex(interp,Tcl_GetString(chanName), + EXP_TEMPORARY,inter_updateproc); + if (!input_default->i_list) + goto error; + } + } + + /* + * check for user attempting to interact with self + * they're almost certainly just fooling around + */ + + /* user could have replaced it with an indirect, so force update */ + if (input_user->i_list->direct == EXP_INDIRECT) { + exp_i_update(interp,input_user->i_list); + } + + if (input_user->i_list->state_list && input_default->i_list->state_list + && (input_user->i_list->state_list->esPtr == input_default->i_list->state_list->esPtr)) { + exp_error(interp,"cannot interact with self - set spawn_id to a spawned process"); + goto error; + } + + esPtrs = 0; + + /* + * all data structures are sufficiently set up that we can now + * "finish()" to terminate this procedure + */ + + status = update_interact_fds(interp,&input_count,&esPtrToInput,&esPtrs,input_base,1,&configure_count,&real_tty); + if (status == TCL_ERROR) finish(TCL_ERROR); + + if (real_tty) { + tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo); + } + + for (inp = input_base,i=0;inp;inp=inp->next,i++) { + /* start timers */ + inp->timeout_remaining = inp->timeout_nominal; + } + + key = expect_key++; + + /* declare ourselves "in sync" with external view of close/indirect */ + configure_count = exp_configure_count; + +#ifndef SIMPLE_EVENT + /* loop waiting (in event handler) for input */ + for (;;) { + int te; /* result of Tcl_Eval */ + int rc; /* return code from ready. This is further refined by matcher. */ + int cc; /* # of chars from read() */ + struct action *action = 0; + time_t previous_time; + time_t current_time; + int matchLen; /* # of chars matched */ + int skip; /* # of chars not involved in match */ + int print; /* # of chars to print */ + int oldprinted; /* old version of u->printed */ + int change; /* if action requires cooked mode */ + int attempt_match = TRUE; + struct input *soonest_input; + int timeout; /* current as opposed to default_timeout */ + Tcl_Time temp_time; + + /* calculate how long to wait */ + /* by finding shortest remaining timeout */ + if (timeout_simple) { + timeout = default_timeout; + } else { + timeout = arbitrary_timeout; + + for (inp=input_base;inp;inp=inp->next) { + if ((inp->timeout_remaining != EXP_TIME_INFINITY) && + (inp->timeout_remaining <= timeout)) { + soonest_input = inp; + timeout = inp->timeout_remaining; + } + } + + Tcl_GetTime (&temp_time); + previous_time = temp_time.sec; + /* timestamp here rather than simply saving old */ + /* current time (after ready()) to account for */ + /* possibility of slow actions */ + + /* timeout can actually be EXP_TIME_INFINITY here if user */ + /* explicitly supplied it in a few cases (or */ + /* the count-down code is broken) */ + } + + /* update the world, if necessary */ + if (configure_count != exp_configure_count) { + status = update_interact_fds(interp,&input_count, + &esPtrToInput,&esPtrs,input_base,1, + &configure_count,&real_tty); + if (status) finish(status); + } + + rc = exp_get_next_event(interp,esPtrs,input_count,&u,timeout,key); + if (rc == EXP_TCLERROR) + goto error; + if (rc == EXP_RECONFIGURE) continue; + if (rc == EXP_TIMEOUT) { + if (timeout_simple) { + action = &action_timeout; + goto got_action; + } else { + action = soonest_input->action_timeout; + /* arbitrarily pick first fd out of list */ + u = soonest_input->i_list->state_list->esPtr; + } + } + if (!timeout_simple) { + int time_diff; + + Tcl_GetTime (&temp_time); + current_time = temp_time.sec; + time_diff = current_time - previous_time; + + /* update all timers */ + for (inp=input_base;inp;inp=inp->next) { + if (inp->timeout_remaining != EXP_TIME_INFINITY) { + inp->timeout_remaining -= time_diff; + if (inp->timeout_remaining < 0) + inp->timeout_remaining = 0; + } + } + } + + /* at this point, we have some kind of event which can be */ + /* immediately processed - i.e. something that doesn't block */ + + /* figure out who we are */ + inp = expStateToInput(esPtrToInput,u); + + /* reset timer */ + inp->timeout_remaining = inp->timeout_nominal; + + switch (rc) { + case EXP_DATA_NEW: + cc = intRead(interp,u,1,0,key); + if (cc > 0) break; + + rc = EXP_EOF; + /* + * FALLTHRU + * + * Most systems have read() return 0, allowing + * control to fall thru and into this code. On some + * systems (currently HP and new SGI), read() does + * see eof, and it must be detected earlier. Then + * control jumps directly to this EXP_EOF label. + */ + case EXP_EOF: + action = inp->action_eof; + attempt_match = FALSE; + skip = expSizeGet(u); + expDiagLog("interact: received eof from spawn_id %s\r\n",u->name); + /* actual close is done later so that we have a */ + /* chance to flush out any remaining characters */ + need_to_close_master = TRUE; + break; + case EXP_DATA_OLD: + cc = 0; + break; + case EXP_TIMEOUT: + action = inp->action_timeout; + attempt_match = FALSE; + skip = expSizeGet(u); + break; + } + + km = 0; + + if (attempt_match) { + rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo); + if ((rc == EXP_MATCH) && km && km->re) { + intRegExpMatchProcess(interp,u,km,&reInfo,skip); + } + } else { + attempt_match = TRUE; + } + + /* + * dispose of chars that should be skipped + * i.e., chars that cannot possibly be part of a match. + */ + if (km && km->writethru) { + print = skip + matchLen; + } else print = skip; + + if (km && km->echo) { + intEcho(u,skip,matchLen); + } + oldprinted = u->printed; + + /* + * If expect has left characters in buffer, it has + * already echoed them to the screen, thus we must + * prevent them being rewritten. Unfortunately this + * gives the possibility of matching chars that have + * already been output, but we do so since the user + * could have avoided it by flushing the output + * buffers directly. + */ + if (print > u->printed) { /* usual case */ + for (outp = inp->output;outp;outp=outp->next) { + struct exp_state_list *fdp; + for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) { + /* send to channel (and log if chan is stdout or devtty) */ + /* + * Following should eventually be rewritten to ...WriteCharsAnd... + */ + int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr, + u->input.buffer + u->printed, + print - u->printed); + if (wc < 0) { + expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp)); + action = outp->action_eof; + change = (action && action->tty_reset); + + if (change && tty_changed) + exp_tty_set(interp,&tty_old,was_raw,was_echo); + te = inter_eval(interp,action,u); + + if (change && real_tty) tty_changed = + exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo); + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + } + u->printed = print; + } + + /* u->printed is now accurate with respect to the buffer */ + /* However, we're about to shift the old data out of the */ + /* buffer. Thus size, printed, and echoed must be */ + /* updated */ + + /* first update size based on skip information */ + /* then set skip to the total amount skipped */ + + size = expSizeGet(u); + if (rc == EXP_MATCH) { + action = &km->action; + + skip += matchLen; + size -= skip; + if (size) { + ustring = u->input.buffer; + memmove(ustring, ustring + skip, size * sizeof(Tcl_UniChar)); + } + } else { + ustring = u->input.buffer; + if (skip) { + size -= skip; + memcpy(ustring, ustring + skip, size * sizeof(Tcl_UniChar)); + } + } + u->input.use = size; + + /* now update printed based on total amount skipped */ + + u->printed -= skip; + /* if more skipped than printed (i.e., keymap encountered) */ + /* for printed positive */ + if (u->printed < 0) u->printed = 0; + + /* if we are in the middle of a match, force the next event */ + /* to wait for more data to arrive */ + u->force_read = (rc == EXP_CANMATCH); + + /* finally reset echoed if necessary */ + if (rc != EXP_CANMATCH) { + if (skip >= oldprinted + u->echoed) u->echoed = 0; + } + + if (rc == EXP_EOF) { + if (u->close_on_eof) { + exp_close(interp,u); + } + need_to_close_master = FALSE; + } + + if (action) { +got_action: + change = (action && action->tty_reset); + if (change && tty_changed) + exp_tty_set(interp,&tty_old,was_raw,was_echo); + + te = inter_eval(interp,action,u); + + if (change && real_tty) tty_changed = + exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo); + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + +#else /* SIMPLE_EVENT */ +/* deferred_interrupt = FALSE;*/ +{ + int te; /* result of Tcl_Eval */ + ExpState *u; /*master*/ + int rc; /* return code from ready. This is further */ + /* refined by matcher. */ + int cc; /* chars count from read() */ + struct action *action = 0; + time_t previous_time; + time_t current_time; + int matchLen, skip; + int change; /* if action requires cooked mode */ + int attempt_match = TRUE; + struct input *soonest_input; + int print; /* # of chars to print */ + int oldprinted; /* old version of u->printed */ + + int timeout; /* current as opposed to default_timeout */ + + if (-1 == (pid = fork())) { + exp_error(interp,"fork: %s",Tcl_PosixError(interp)); + finish(TCL_ERROR); + } + if (pid == 0) { + /* + * This is a new child process. + * It exists only for this interact command and will go away when + * the interact returns. + * + * The purpose of this child process is to read output from the + * spawned process and send it to the user tty. + * (See diagram above.) + */ + + exp_close(interp,expStdinoutGet()); + + u = esPtrs[1]; /* get 2nd ExpState */ + input_count = 1; + + while (1) { + + /* calculate how long to wait */ + /* by finding shortest remaining timeout */ + if (timeout_simple) { + timeout = default_timeout; + } else { + timeout = arbitrary_timeout; + + for (inp=input_base;inp;inp=inp->next) { + if ((inp->timeout_remaining != EXP_TIME_INFINITY) && + (inp->timeout_remaining < timeout)) + soonest_input = inp; + timeout = inp->timeout_remaining; + } + + Tcl_GetTime (&temp_time); + previous_time = temp_time.sec; + /* timestamp here rather than simply saving old */ + /* current time (after ready()) to account for */ + /* possibility of slow actions */ + + /* timeout can actually be EXP_TIME_INFINITY here if user */ + /* explicitly supplied it in a few cases (or */ + /* the count-down code is broken) */ + } + + /* +1 so we can look at the "other" file descriptor */ + rc = exp_get_next_event(interp,esPtrs+1,input_count,&u,timeout,key); + if (!timeout_simple) { + int time_diff; + + Tcl_GetTime (&temp_time); + current_time = temp_time.sec; + time_diff = current_time - previous_time; + + /* update all timers */ + for (inp=input_base;inp;inp=inp->next) { + if (inp->timeout_remaining != EXP_TIME_INFINITY) { + inp->timeout_remaining -= time_diff; + if (inp->timeout_remaining < 0) + inp->timeout_remaining = 0; + } + } + } + + /* at this point, we have some kind of event which can be */ + /* immediately processed - i.e. something that doesn't block */ + + /* figure out who we are */ + inp = expStateToInput(esPtrToInput,u); + + switch (rc) { + case EXP_DATA_NEW: + cc = intRead(interp,u,0,0,key); + if (cc > 0) break; + /* + * FALLTHRU + * + * Most systems have read() return 0, allowing + * control to fall thru and into this code. On some + * systems (currently HP and new SGI), read() does + * see eof, and it must be detected earlier. Then + * control jumps directly to this EXP_EOF label. + */ + case EXP_EOF: + action = inp->action_eof; + attempt_match = FALSE; + skip = expSizeGet(u); + rc = EXP_EOF; + expDiagLog("interact: child received eof from spawn_id %s\r\n",u->name); + exp_close(interp,u); + break; + case EXP_DATA_OLD: + cc = 0; + break; + } + + km = 0; + + if (attempt_match) { + rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo); + if ((rc == EXP_MATCH) && km && km->re) { + intRegExpMatchProcess(interp,u,km,&reInfo,skip); + } + } else { + attempt_match = TRUE; + } + + /* dispose of chars that should be skipped */ + + /* skip is chars not involved in match */ + /* print is with chars involved in match */ + + if (km && km->writethru) { + print = skip + matchLen; + } else print = skip; + + if (km && km->echo) { + intEcho(u,skip,matchLen); + } + oldprinted = u->printed; + + /* If expect has left characters in buffer, it has */ + /* already echoed them to the screen, thus we must */ + /* prevent them being rewritten. Unfortunately this */ + /* gives the possibility of matching chars that have */ + /* already been output, but we do so since the user */ + /* could have avoided it by flushing the output */ + /* buffers directly. */ + if (print > u->printed) { /* usual case */ + for (outp = inp->output;outp;outp=outp->next) { + struct exp_state_list *fdp; + for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) { + /* send to channel (and log if chan is stdout or devtty) */ + int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr, + u->input.buffer + u->printed, + print - u->printed); + if (wc < 0) { + expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp)); + action = outp->action_eof; + + te = inter_eval(interp,action,u); + + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + } + u->printed = print; + } + + /* u->printed is now accurate with respect to the buffer */ + /* However, we're about to shift the old data out of the */ + /* buffer. Thus size, printed, and echoed must be */ + /* updated */ + + /* first update size based on skip information */ + /* then set skip to the total amount skipped */ + + size = expSizeGet(u); + if (rc == EXP_MATCH) { + action = &km->action; + + skip += matchLen; + size -= skip; + if (size) { + memcpy(u->buffer, u->buffer + skip, size); + } + } else { + if (skip) { + size -= skip; + memcpy(u->buffer, u->buffer + skip, size); + } + } + Tcl_SetObjLength(size); + + /* now update printed based on total amount skipped */ + + u->printed -= skip; + /* if more skipped than printed (i.e., keymap encountered) */ + /* for printed positive */ + if (u->printed < 0) u->printed = 0; + + /* if we are in the middle of a match, force the next event */ + /* to wait for more data to arrive */ + u->force_read = (rc == EXP_CANMATCH); + + /* finally reset echoed if necessary */ + if (rc != EXP_CANMATCH) { + if (skip >= oldprinted + u->echoed) u->echoed = 0; + } + + if (action) { + te = inter_eval(interp,action,u); + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + } else { + /* + * This is the original Expect process. + * + * It now loops, reading keystrokes from the user tty + * and sending them to the spawned process. + * (See diagram above.) + */ + +#include <signal.h> + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + expDiagLog("fork = %d\r\n",pid); + signal(SIGCHLD,sigchld_handler); +/* restart:*/ +/* tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);*/ + + u = esPtrs[0]; /* get 1st ExpState */ + input_count = 1; + + while (1) { + /* calculate how long to wait */ + /* by finding shortest remaining timeout */ + if (timeout_simple) { + timeout = default_timeout; + } else { + timeout = arbitrary_timeout; + + for (inp=input_base;inp;inp=inp->next) { + if ((inp->timeout_remaining != EXP_TIME_INFINITY) && + (inp->timeout_remaining < timeout)) + soonest_input = inp; + timeout = inp->timeout_remaining; + } + + Tcl_GetTime (&temp_time); + previous_time = temp_time.sec; + /* timestamp here rather than simply saving old */ + /* current time (after ready()) to account for */ + /* possibility of slow actions */ + + /* timeout can actually be EXP_TIME_INFINITY here if user */ + /* explicitly supplied it in a few cases (or */ + /* the count-down code is broken) */ + } + + rc = exp_get_next_event(interp,esPtrs,input_count,&u,timeout,key); + if (!timeout_simple) { + int time_diff; + + Tcl_GetTime (&temp_time); + current_time = temp_time.sec; + time_diff = current_time - previous_time; + + /* update all timers */ + for (inp=input_base;inp;inp=inp->next) { + if (inp->timeout_remaining != EXP_TIME_INFINITY) { + inp->timeout_remaining -= time_diff; + if (inp->timeout_remaining < 0) + inp->timeout_remaining = 0; + } + } + } + + /* at this point, we have some kind of event which can be */ + /* immediately processed - i.e. something that doesn't block */ + + /* figure out who we are */ + inp = expStateToInput(esPtrToInput,u); + + switch (rc) { + case EXP_DATA_NEW: + cc = intRead(interp,u,0,1,key); + if (cc > 0) { + break; + } else if (cc == EXP_CHILD_EOF) { + /* user could potentially have two outputs in which */ + /* case we might be looking at the wrong one, but */ + /* the likelihood of this is nil */ + action = inp->output->action_eof; + attempt_match = FALSE; + skip = expSizeGet(u); + rc = EXP_EOF; + expDiagLogU("interact: process died/eof\r\n"); + clean_up_after_child(interp,esPtrs[1]); + break; + } + /* + * FALLTHRU + * + * Most systems have read() return 0, allowing + * control to fall thru and into this code. On some + * systems (currently HP and new SGI), read() does + * see eof, and it must be detected earlier. Then + * control jumps directly to this EXP_EOF label. + */ + case EXP_EOF: + action = inp->action_eof; + attempt_match = FALSE; + skip = expSizeGet(u); + rc = EXP_EOF; + expDiagLogU("user sent EOF or disappeared\n\n"); + break; + case EXP_DATA_OLD: + cc = 0; + break; + } + + km = 0; + + if (attempt_match) { + rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo); + if ((rc == EXP_MATCH) && km && km->re) { + intRegExpMatchProcess(interp,u,km,&reInfo,skip); + } + } else { + attempt_match = TRUE; + } + + /* dispose of chars that should be skipped */ + + /* skip is chars not involved in match */ + /* print is with chars involved in match */ + + if (km && km->writethru) { + print = skip + matchLen; + } else print = skip; + + if (km && km->echo) { + intEcho(u,skip,matchLen); + } + oldprinted = u->printed; + + /* If expect has left characters in buffer, it has */ + /* already echoed them to the screen, thus we must */ + /* prevent them being rewritten. Unfortunately this */ + /* gives the possibility of matching chars that have */ + /* already been output, but we do so since the user */ + /* could have avoided it by flushing the output */ + /* buffers directly. */ + if (print > u->printed) { /* usual case */ + for (outp = inp->output;outp;outp=outp->next) { + struct exp_state_list *fdp; + for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) { + /* send to channel (and log if chan is stdout or devtty) */ + int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr, + u->input.buffer + u->printed, + print - u->printed); + if (wc < 0) { + expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp)); + clean_up_after_child(interp,fdp->esPtr); + action = outp->action_eof; + change = (action && action->tty_reset); + if (change && tty_changed) + exp_tty_set(interp,&tty_old,was_raw,was_echo); + te = inter_eval(interp,action,u); + + if (change && real_tty) tty_changed = + exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo); + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + } + u->printed = print; + } + + /* u->printed is now accurate with respect to the buffer */ + /* However, we're about to shift the old data out of the */ + /* buffer. Thus size, printed, and echoed must be */ + /* updated */ + + /* first update size based on skip information */ + /* then set skip to the total amount skipped */ + + size = expSizeGet(u); + if (rc == EXP_MATCH) { + action = &km->action; + + skip += matchLen; + size -= skip; + if (size) { + memcpy(u->buffer, u->buffer + skip, size); + } + } else { + if (skip) { + size -= skip; + memcpy(u->buffer, u->buffer + skip, size); + } + } + Tcl_SetObjLength(size); + + /* now update printed based on total amount skipped */ + + u->printed -= skip; + /* if more skipped than printed (i.e., keymap encountered) */ + /* for printed positive */ + if (u->printed < 0) u->printed = 0; + + /* if we are in the middle of a match, force the next event */ + /* to wait for more data to arrive */ + u->force_read = (rc == EXP_CANMATCH); + + /* finally reset echoed if necessary */ + if (rc != EXP_CANMATCH) { + if (skip >= oldprinted + u->echoed) u->echoed = 0; + } + + if (action) { + change = (action && action->tty_reset); + if (change && tty_changed) + exp_tty_set(interp,&tty_old,was_raw,was_echo); + + te = inter_eval(interp,action,u); + + if (change && real_tty) tty_changed = + exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo); + switch (te) { + case TCL_BREAK: + case TCL_CONTINUE: + finish(te); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + case TCL_OK: + /* god knows what the user might */ + /* have done to us in the way of */ + /* closed fds, so .... */ + action = 0; /* reset action */ + continue; + default: + finish(te); + } + } + } + } +} +#endif /* SIMPLE_EVENT */ + + done: +#ifdef SIMPLE_EVENT + /* force child to exit upon eof from master */ + if (pid == 0) { + exit(SPAWNED_PROCESS_DIED); + } +#endif /* SIMPLE_EVENT */ + + if (need_to_close_master && u->close_on_eof) exp_close(interp,u); + + if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo); + if (esPtrs) ckfree((char *)esPtrs); + if (esPtrToInput) Tcl_DeleteHashTable(esPtrToInput); + free_input(interp,input_base); + free_action(action_base); + + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return(status); + + error: + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return TCL_ERROR; +} + +/* version of Tcl_Eval for interact */ +static int +inter_eval( + Tcl_Interp *interp, + struct action *action, + ExpState *esPtr) +{ + int status; + + if (action->iwrite) { + out("spawn_id",esPtr->name); + } + + if (action->statement) { + status = Tcl_EvalObjEx(interp,action->statement,0); + } else { + expStdoutLogU("\r\n",1); + status = exp_interpreter(interp,(Tcl_Obj *)0); + } + + return status; +} + +static void +free_keymap(struct keymap *km) +{ + if (km == 0) return; + free_keymap(km->next); + + ckfree((char *)km); +} + +static void +free_action(struct action *a) +{ + struct action *next; + + while (a) { + next = a->next; + ckfree((char *)a); + a = next; + } +} + +static void +free_input( + Tcl_Interp *interp, + struct input *i) +{ + if (i == 0) return; + free_input(interp,i->next); + + exp_free_i(interp,i->i_list,inter_updateproc); + free_output(interp,i->output); + free_keymap(i->keymap); + ckfree((char *)i); +} + +static struct action * +new_action(struct action **base) +{ + struct action *o = new(struct action); + + /* stick new action into beginning of list of all actions */ + o->next = *base; + *base = o; + + return o; +} + +static void +free_output( + Tcl_Interp *interp, + struct output *o) +{ + if (o == 0) return; + free_output(interp,o->next); + exp_free_i(interp,o->i_list,inter_updateproc); + + ckfree((char *)o); +} + + +static struct exp_cmd_data cmd_data[] = { +{"interact", Exp_InteractObjCmd, 0, 0, 0}, +{0}}; + +void +exp_init_interact_cmds(Tcl_Interp *interp) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + exp_create_commands(interp,cmd_data); + + tsdPtr->cmdObjReturn = Tcl_NewStringObj("return",6); + Tcl_IncrRefCount(tsdPtr->cmdObjReturn); +#if 0 + tsdPtr->cmdObjInterpreter = Tcl_NewStringObj("interpreter",11); + Tcl_IncrRefCount(tsdPtr->cmdObjInterpreter); +#endif +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_log.c b/exp_log.c new file mode 100644 index 0000000..b378641 --- /dev/null +++ b/exp_log.c @@ -0,0 +1,768 @@ +/* exp_log.c - logging routines and other things common to both Expect + program and library. Note that this file must NOT have any + references to Tcl except for including tclInt.h +*/ + +#include "expect_cf.h" +#include <stdio.h> +/*#include <varargs.h> tclInt.h drags in varargs.h. Since Pyramid */ +/* objects to including varargs.h twice, just */ +/* omit this one. */ +#include "tclInt.h" +#ifdef NO_STDLIB_H +#include "../compat/stdlib.h" +#else +#include <stdlib.h> /* for malloc */ +#endif +#include <ctype.h> + +#include "expect_comm.h" +#include "exp_int.h" +#include "exp_rename.h" +#include "exp_command.h" +#include "exp_log.h" + +typedef struct ThreadSpecificData { + Tcl_Channel diagChannel; + Tcl_DString diagFilename; + int diagToStderr; + + Tcl_Channel logChannel; + Tcl_DString logFilename; /* if no name, then it came from -open or -leaveopen */ + int logAppend; + int logLeaveOpen; + int logAll; /* if TRUE, write log of all interactions + * despite value of logUser - i.e., even if + * user is not seeing it (via stdout) + */ + int logUser; /* TRUE if user sees interactions on stdout */ +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +/* + * create a reasonably large buffer for the bulk of the output routines + * that are not too large + */ +static char bigbuf[2000]; + +static void expDiagWriteCharsUni _ANSI_ARGS_((Tcl_UniChar *str,int len)); + +/* + * Following this are several functions that log the conversation. Some + * general notes on all of them: + */ + +/* + * ignore sprintf return value ("character count") because it's not + * defined in terms of UTF so it would be misinterpreted if we passed + * it on. + */ + +/* + * if necessary, they could be made more efficient by skipping vsprintf based + * on booleans + */ + +/* Most of them have multiple calls to printf-style functions. */ +/* At first glance, it seems stupid to reformat the same arguments again */ +/* but we have no way of telling how long the formatted output will be */ +/* and hence cannot allocate a buffer to do so. */ +/* Fortunately, in production code, most of the duplicate reformatting */ +/* will be skipped, since it is due to handling errors and debugging. */ + +/* + * Name: expWriteBytesAndLogIfTtyU + * + * Output to channel (and log if channel is stdout or devtty) + * + * Returns: TCL_OK or TCL_ERROR; + */ + +int +expWriteBytesAndLogIfTtyU(esPtr,buf,lenChars) + ExpState *esPtr; + Tcl_UniChar *buf; + int lenChars; +{ + int wc; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (esPtr->valid) + wc = expWriteCharsUni(esPtr,buf,lenChars); + + if (tsdPtr->logChannel && ((esPtr->fdout == 1) || expDevttyIs(esPtr))) { + Tcl_DString ds; + Tcl_DStringInit (&ds); + Tcl_UniCharToUtfDString (buf,lenChars,&ds); + Tcl_WriteChars(tsdPtr->logChannel,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds)); + Tcl_DStringFree (&ds); + } + return wc; +} + +/* + * Name: expLogDiagU + * + * Send to the Log (and Diag if open). This is for writing to the log. + * (In contrast, expDiagLog... is for writing diagnostics.) + */ + +void +expLogDiagU(buf) +char *buf; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + expDiagWriteChars(buf,-1); + if (tsdPtr->logChannel) { + Tcl_WriteChars(tsdPtr->logChannel, buf, -1); + } +} + +/* + * Name: expLogInteractionU + * + * Show chars to user if they've requested it, UNLESS they're seeing it + * already because they're typing it and tty driver is echoing it. + * Also send to Diag and Log if appropriate. + */ +void +expLogInteractionU(esPtr,buf,buflen) + ExpState *esPtr; + Tcl_UniChar *buf; + int buflen; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (tsdPtr->logAll || (tsdPtr->logUser && tsdPtr->logChannel)) { + Tcl_DString ds; + Tcl_DStringInit (&ds); + Tcl_UniCharToUtfDString (buf,buflen,&ds); + Tcl_WriteChars(tsdPtr->logChannel,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds)); + Tcl_DStringFree (&ds); + } + + /* hmm.... if stdout is closed such as by disconnect, loguser + should be forced FALSE */ + + /* don't write to user if they're seeing it already, i.e., typing it! */ + if (tsdPtr->logUser && (!expStdinoutIs(esPtr)) && (!expDevttyIs(esPtr))) { + ExpState *stdinout = expStdinoutGet(); + if (stdinout->valid) { + (void) expWriteCharsUni(stdinout,buf,buflen); + } + } + expDiagWriteCharsUni(buf,buflen); +} + +/* send to log if open */ +/* send to stderr if debugging enabled */ +/* use this for logging everything but the parent/child conversation */ +/* (this turns out to be almost nothing) */ +/* uppercase L differentiates if from math function of same name */ +#define LOGUSER (tsdPtr->logUser || force_stdout) +/*VARARGS*/ +void +expStdoutLog TCL_VARARGS_DEF(int,arg1) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + int force_stdout; + char *fmt; + va_list args; + + force_stdout = TCL_VARARGS_START(int,arg1,args); + fmt = va_arg(args,char *); + + if ((!tsdPtr->logUser) && (!force_stdout) && (!tsdPtr->logAll)) return; + + (void) vsprintf(bigbuf,fmt,args); + expDiagWriteBytes(bigbuf,-1); + if (tsdPtr->logAll || (LOGUSER && tsdPtr->logChannel)) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1); + if (LOGUSER) fprintf(stdout,"%s",bigbuf); + va_end(args); +} + +/* just like log but does no formatting */ +/* send to log if open */ +/* use this function for logging the parent/child conversation */ +void +expStdoutLogU(buf,force_stdout) +char *buf; +int force_stdout; /* override value of logUser */ +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + int length; + + if ((!tsdPtr->logUser) && (!force_stdout) && (!tsdPtr->logAll)) return; + + length = strlen(buf); + expDiagWriteBytes(buf,length); + if (tsdPtr->logAll || (LOGUSER && tsdPtr->logChannel)) Tcl_WriteChars(tsdPtr->logChannel,buf,-1); + if (LOGUSER) { +#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)) + Tcl_WriteChars (Tcl_GetStdChannel (TCL_STDOUT), buf, length); + Tcl_Flush (Tcl_GetStdChannel (TCL_STDOUT)); +#else + fwrite(buf,1,length,stdout); +#endif + } +} + +/* send to log if open */ +/* send to stderr */ +/* use this function for error conditions */ +/*VARARGS*/ +void +expErrorLog TCL_VARARGS_DEF(char *,arg1) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + char *fmt; + va_list args; + + fmt = TCL_VARARGS_START(char *,arg1,args); + (void) vsprintf(bigbuf,fmt,args); + + expDiagWriteChars(bigbuf,-1); + fprintf(stderr,"%s",bigbuf); + if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1); + + va_end(args); +} + +/* just like errorlog but does no formatting */ +/* send to log if open */ +/* use this function for logging the parent/child conversation */ +/*ARGSUSED*/ +void +expErrorLogU(buf) +char *buf; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + int length = strlen(buf); + fwrite(buf,1,length,stderr); + expDiagWriteChars(buf,-1); + if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,buf,-1); +} + + + +/* send diagnostics to Diag, Log, and stderr */ +/* use this function for recording unusual things in the log */ +/*VARARGS*/ +void +expDiagLog TCL_VARARGS_DEF(char *,arg1) +{ + char *fmt; + va_list args; + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if ((tsdPtr->diagToStderr == 0) && (tsdPtr->diagChannel == 0)) return; + + fmt = TCL_VARARGS_START(char *,arg1,args); + + (void) vsprintf(bigbuf,fmt,args); + + expDiagWriteBytes(bigbuf,-1); + if (tsdPtr->diagToStderr) { + fprintf(stderr,"%s",bigbuf); + if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1); + } + + va_end(args); +} + + +/* expDiagLog for unformatted strings + this also takes care of arbitrary large strings */ +void +expDiagLogU(str) +char *str; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if ((tsdPtr->diagToStderr == 0) && (tsdPtr->diagChannel == 0)) return; + + expDiagWriteBytes(str,-1); + + if (tsdPtr->diagToStderr) { + fprintf(stderr,"%s",str); + if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,str,-1); + } +} + +/* expPrintf prints to stderr. It's just a utility for making + debugging easier. */ + +/*VARARGS*/ +void +expPrintf TCL_VARARGS_DEF(char *,arg1) +{ + char *fmt; + va_list args; + char bigbuf[2000]; + int len, rc; + + fmt = TCL_VARARGS_START(char *,arg1,args); + len = vsprintf(bigbuf,arg1,args); + retry: + rc = write(2,bigbuf,len); + if ((rc == -1) && (errno == EAGAIN)) goto retry; + + va_end(args); +} + + +void +expDiagToStderrSet(val) + int val; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tsdPtr->diagToStderr = val; +} + + +int +expDiagToStderrGet() { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->diagToStderr; +} + +Tcl_Channel +expDiagChannelGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->diagChannel; +} + +void +expDiagChannelClose(interp) + Tcl_Interp *interp; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->diagChannel) return; + Tcl_UnregisterChannel(interp,tsdPtr->diagChannel); + Tcl_DStringFree(&tsdPtr->diagFilename); + tsdPtr->diagChannel = 0; +} + +/* currently this registers the channel, however the exp_internal + command doesn't currently give the channel name to the user so + this is kind of useless - but we might change this someday */ +int +expDiagChannelOpen(interp,filename) + Tcl_Interp *interp; + char *filename; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + char *newfilename; + + Tcl_ResetResult(interp); + newfilename = Tcl_TranslateFileName(interp,filename,&tsdPtr->diagFilename); + if (!newfilename) return TCL_ERROR; + + /* Tcl_TildeSubst doesn't store into dstring */ + /* if no ~, so force string into dstring */ + /* this is only needed so that next time around */ + /* we can get dstring for -info if necessary */ + if (Tcl_DStringValue(&tsdPtr->diagFilename)[0] == '\0') { + Tcl_DStringAppend(&tsdPtr->diagFilename,filename,-1); + } + + tsdPtr->diagChannel = Tcl_OpenFileChannel(interp,newfilename,"a",0777); + if (!tsdPtr->diagChannel) { + Tcl_DStringFree(&tsdPtr->diagFilename); + return TCL_ERROR; + } + Tcl_RegisterChannel(interp,tsdPtr->diagChannel); + Tcl_SetChannelOption(interp,tsdPtr->diagChannel,"-buffering","none"); + return TCL_OK; +} + +void +expDiagWriteObj(obj) + Tcl_Obj *obj; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->diagChannel) return; + + Tcl_WriteObj(tsdPtr->diagChannel,obj); +} + +/* write 8-bit bytes */ +void +expDiagWriteBytes(str,len) +char *str; +int len; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->diagChannel) return; + + Tcl_Write(tsdPtr->diagChannel,str,len); +} + +/* write UTF chars */ +void +expDiagWriteChars(str,len) +char *str; +int len; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->diagChannel) return; + + Tcl_WriteChars(tsdPtr->diagChannel,str,len); +} + +/* write Unicode chars */ +static void +expDiagWriteCharsUni(str,len) +Tcl_UniChar *str; +int len; +{ + Tcl_DString ds; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->diagChannel) return; + + Tcl_DStringInit (&ds); + Tcl_UniCharToUtfDString (str,len,&ds); + Tcl_WriteChars(tsdPtr->diagChannel,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds)); + Tcl_DStringFree (&ds); +} + +char * +expDiagFilename() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return Tcl_DStringValue(&tsdPtr->diagFilename); +} + +void +expLogChannelClose(interp) + Tcl_Interp *interp; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->logChannel) return; + + if (Tcl_DStringLength(&tsdPtr->logFilename)) { + /* it's a channel that we created */ + Tcl_UnregisterChannel(interp,tsdPtr->logChannel); + Tcl_DStringFree(&tsdPtr->logFilename); + } else { + /* it's a channel that tcl::open created */ + if (!tsdPtr->logLeaveOpen) { + Tcl_UnregisterChannel(interp,tsdPtr->logChannel); + } + } + tsdPtr->logChannel = 0; + tsdPtr->logAll = 0; /* can't write to log if none open! */ +} + +/* currently this registers the channel, however the exp_log_file + command doesn't currently give the channel name to the user so + this is kind of useless - but we might change this someday */ +int +expLogChannelOpen(interp,filename,append) + Tcl_Interp *interp; + char *filename; + int append; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + char *newfilename; + char mode[2]; + + if (append) { + strcpy(mode,"a"); + } else { + strcpy(mode,"w"); + } + + Tcl_ResetResult(interp); + newfilename = Tcl_TranslateFileName(interp,filename,&tsdPtr->logFilename); + if (!newfilename) return TCL_ERROR; + + /* Tcl_TildeSubst doesn't store into dstring */ + /* if no ~, so force string into dstring */ + /* this is only needed so that next time around */ + /* we can get dstring for -info if necessary */ + if (Tcl_DStringValue(&tsdPtr->logFilename)[0] == '\0') { + Tcl_DStringAppend(&tsdPtr->logFilename,filename,-1); + } + + tsdPtr->logChannel = Tcl_OpenFileChannel(interp,newfilename,mode,0777); + if (!tsdPtr->logChannel) { + Tcl_DStringFree(&tsdPtr->logFilename); + return TCL_ERROR; + } + Tcl_RegisterChannel(interp,tsdPtr->logChannel); + Tcl_SetChannelOption(interp,tsdPtr->logChannel,"-buffering","none"); + expLogAppendSet(append); + return TCL_OK; +} + +int +expLogAppendGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->logAppend; +} + +void +expLogAppendSet(app) + int app; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->logAppend = app; +} + +int +expLogAllGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->logAll; +} + +void +expLogAllSet(app) + int app; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->logAll = app; + /* should probably confirm logChannel != 0 */ +} + +int +expLogToStdoutGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->logUser; +} + +void +expLogToStdoutSet(app) + int app; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->logUser = app; +} + +int +expLogLeaveOpenGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->logLeaveOpen; +} + +void +expLogLeaveOpenSet(app) + int app; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->logLeaveOpen = app; +} + +Tcl_Channel +expLogChannelGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->logChannel; +} + +/* to set to a pre-opened channel (presumably by tcl::open) */ +int +expLogChannelSet(interp,name) + Tcl_Interp *interp; + char *name; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + int mode; + + if (0 == (tsdPtr->logChannel = Tcl_GetChannel(interp,name,&mode))) { + return TCL_ERROR; + } + if (!(mode & TCL_WRITABLE)) { + tsdPtr->logChannel = 0; + Tcl_SetResult(interp,"channel is not writable",TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + +char * +expLogFilenameGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return Tcl_DStringValue(&tsdPtr->logFilename); +} + +int +expLogUserGet() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return tsdPtr->logUser; +} + +void +expLogUserSet(logUser) + int logUser; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tsdPtr->logUser = logUser; +} + + + +/* generate printable versions of random ASCII strings. Primarily used */ +/* in diagnostic mode, "expect -d" */ +static char * +expPrintifyReal(s) +char *s; +{ + static int destlen = 0; + static char *dest = 0; + char *d; /* ptr into dest */ + unsigned int need; + Tcl_UniChar ch; + + if (s == 0) return("<null>"); + + /* worst case is every character takes 4 to printify */ + need = strlen(s)*6 + 1; + if (need > destlen) { + if (dest) ckfree(dest); + dest = ckalloc(need); + destlen = need; + } + + for (d = dest;*s;) { + s += Tcl_UtfToUniChar(s, &ch); + if (ch == '\r') { + strcpy(d,"\\r"); d += 2; + } else if (ch == '\n') { + strcpy(d,"\\n"); d += 2; + } else if (ch == '\t') { + strcpy(d,"\\t"); d += 2; + } else if ((ch < 0x80) && isprint(UCHAR(ch))) { + *d = (char)ch; d += 1; + } else { + sprintf(d,"\\u%04x",ch); d += 6; + } + } + *d = '\0'; + return(dest); +} + +/* generate printable versions of random ASCII strings. Primarily used */ +/* in diagnostic mode, "expect -d" */ +static char * +expPrintifyRealUni(s,numchars) +Tcl_UniChar *s; +int numchars; +{ + static int destlen = 0; + static char *dest = 0; + char *d; /* ptr into dest */ + unsigned int need; + Tcl_UniChar ch; + + if (s == 0) return("<null>"); + if (numchars == 0) return(""); + + /* worst case is every character takes 6 to printify */ + need = numchars*6 + 1; + if (need > destlen) { + if (dest) ckfree(dest); + dest = ckalloc(need); + destlen = need; + } + + for (d = dest;numchars > 0;numchars--) { + ch = *s; s++; + + if (ch == '\r') { + strcpy(d,"\\r"); d += 2; + } else if (ch == '\n') { + strcpy(d,"\\n"); d += 2; + } else if (ch == '\t') { + strcpy(d,"\\t"); d += 2; + } else if ((ch < 0x80) && isprint(UCHAR(ch))) { + *d = (char)ch; d += 1; + } else { + sprintf(d,"\\u%04x",ch); d += 6; + } + } + *d = '\0'; + return(dest); +} + +char * +expPrintifyObj(obj) + Tcl_Obj *obj; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + /* don't bother writing into bigbuf if we're not going to ever use it */ + if ((!tsdPtr->diagToStderr) && (!tsdPtr->diagChannel)) return((char *)0); + + return expPrintifyReal(Tcl_GetString(obj)); +} + +char * +expPrintify(s) /* INTL */ +char *s; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + /* don't bother writing into bigbuf if we're not going to ever use it */ + if ((!tsdPtr->diagToStderr) && (!tsdPtr->diagChannel)) return((char *)0); + + return expPrintifyReal(s); +} + +char * +expPrintifyUni(s,numchars) /* INTL */ +Tcl_UniChar *s; +int numchars; +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + /* don't bother writing into bigbuf if we're not going to ever use it */ + if ((!tsdPtr->diagToStderr) && (!tsdPtr->diagChannel)) return((char *)0); + + return expPrintifyRealUni(s,numchars); +} + +void +expDiagInit() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_DStringInit(&tsdPtr->diagFilename); + tsdPtr->diagChannel = 0; + tsdPtr->diagToStderr = 0; +} + +void +expLogInit() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_DStringInit(&tsdPtr->logFilename); + tsdPtr->logChannel = 0; + tsdPtr->logAll = FALSE; + tsdPtr->logUser = TRUE; +} diff --git a/exp_log.h b/exp_log.h new file mode 100644 index 0000000..ca78386 --- /dev/null +++ b/exp_log.h @@ -0,0 +1,47 @@ +/* exp_log.h */ + +extern void expErrorLog _ANSI_ARGS_(TCL_VARARGS(char *,fmt)); +extern void expErrorLogU _ANSI_ARGS_((char *)); + +extern void expStdoutLog _ANSI_ARGS_(TCL_VARARGS(int,force_stdout)); +extern void expStdoutLogU _ANSI_ARGS_((char *buf, int force_stdout)); + +EXTERN void expDiagInit _ANSI_ARGS_((void)); +EXTERN int expDiagChannelOpen _ANSI_ARGS_((Tcl_Interp *,char *)); +EXTERN Tcl_Channel expDiagChannelGet _ANSI_ARGS_((void)); +EXTERN void expDiagChannelClose _ANSI_ARGS_((Tcl_Interp *)); +EXTERN char * expDiagFilename _ANSI_ARGS_((void)); +EXTERN int expDiagToStderrGet _ANSI_ARGS_((void)); +EXTERN void expDiagToStderrSet _ANSI_ARGS_((int)); +EXTERN void expDiagWriteBytes _ANSI_ARGS_((char *,int)); +EXTERN void expDiagWriteChars _ANSI_ARGS_((char *,int)); +EXTERN void expDiagWriteObj _ANSI_ARGS_((Tcl_Obj *)); +EXTERN void expDiagLog _ANSI_ARGS_(TCL_VARARGS(char *,fmt)); +EXTERN void expDiagLogU _ANSI_ARGS_((char *)); + +EXTERN char * expPrintify _ANSI_ARGS_((char *)); +EXTERN char * expPrintifyUni _ANSI_ARGS_((Tcl_UniChar *,int)); +EXTERN char * expPrintifyObj _ANSI_ARGS_((Tcl_Obj *)); +EXTERN void expPrintf _ANSI_ARGS_(TCL_VARARGS(char *,fmt)); + +EXTERN void expLogInit _ANSI_ARGS_((void)); +EXTERN int expLogChannelOpen _ANSI_ARGS_((Tcl_Interp *,char *,int)); +EXTERN Tcl_Channel expLogChannelGet _ANSI_ARGS_((void)); +EXTERN int expLogChannelSet _ANSI_ARGS_((Tcl_Interp *,char *)); +EXTERN void expLogChannelClose _ANSI_ARGS_((Tcl_Interp *)); +EXTERN char * expLogFilenameGet _ANSI_ARGS_((void)); +EXTERN void expLogAppendSet _ANSI_ARGS_((int)); +EXTERN int expLogAppendGet _ANSI_ARGS_((void)); +EXTERN void expLogLeaveOpenSet _ANSI_ARGS_((int)); +EXTERN int expLogLeaveOpenGet _ANSI_ARGS_((void)); +EXTERN void expLogAllSet _ANSI_ARGS_((int)); +EXTERN int expLogAllGet _ANSI_ARGS_((void)); +EXTERN void expLogToStdoutSet _ANSI_ARGS_((int)); +EXTERN int expLogToStdoutGet _ANSI_ARGS_((void)); +EXTERN void expLogDiagU _ANSI_ARGS_((char *)); +EXTERN int expWriteBytesAndLogIfTtyU _ANSI_ARGS_((ExpState *,Tcl_UniChar *,int)); + +EXTERN int expLogUserGet _ANSI_ARGS_((void)); +EXTERN void expLogUserSet _ANSI_ARGS_((int)); + +EXTERN void expLogInteractionU _ANSI_ARGS_((ExpState *,Tcl_UniChar *,int)); diff --git a/exp_main_exp.c b/exp_main_exp.c new file mode 100644 index 0000000..be1addd --- /dev/null +++ b/exp_main_exp.c @@ -0,0 +1,60 @@ +/* main.c - main() and some logging routines for expect + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +/* Don't use stubs since we are in the main application. */ +#undef USE_TCL_STUBS + +#include "expect_cf.h" +#include <stdio.h> +#include "tcl.h" +#include "expect_tcl.h" +#include <stdlib.h> + +int +main(argc, argv) +int argc; +char *argv[]; +{ + int rc = 0; + char buffer [30]; + + Tcl_Interp *interp = Tcl_CreateInterp(); + Tcl_FindExecutable(argv[0]); + + if (Tcl_Init(interp) == TCL_ERROR) { + fprintf(stderr,"Tcl_Init failed: %s\n",Tcl_GetStringResult (interp)); + (void) exit(1); + } + + if (Expect_Init(interp) == TCL_ERROR) { + fprintf(stderr,"Expect_Init failed: %s\n",Tcl_GetStringResult (interp)); + (void) exit(1); + } + + exp_parse_argv(interp,argc,argv); + + /* become interactive if requested or "nothing to do" */ + if (exp_interactive) + (void) exp_interpreter(interp,(Tcl_Obj *)0); + else if (exp_cmdfile) + rc = exp_interpret_cmdfile(interp,exp_cmdfile); + else if (exp_cmdfilename) + rc = exp_interpret_cmdfilename(interp,exp_cmdfilename); + + /* assert(exp_cmdlinecmds != 0) */ + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + + sprintf(buffer, "exit %d", rc); + Tcl_Eval(interp, buffer); + /*NOTREACHED*/ + return 0; /* Needed only to prevent compiler warning. */ +} + diff --git a/exp_main_sub.c b/exp_main_sub.c new file mode 100644 index 0000000..a3f186d --- /dev/null +++ b/exp_main_sub.c @@ -0,0 +1,1023 @@ +/* exp_main_sub.c - miscellaneous subroutines for Expect or Tk main() */ + +#include "expect_cf.h" +#include <stdio.h> +#include <errno.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include "tcl.h" +#include "tclInt.h" +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_tty_in.h" +#include "exp_log.h" +#include "exp_event.h" +#ifdef TCL_DEBUGGER +#include "tcldbg.h" +#endif + +#ifndef EXP_VERSION +#define EXP_VERSION PACKAGE_VERSION +#endif +#ifdef __CENTERLINE__ +#undef EXP_VERSION +#define EXP_VERSION "5.45.0" /* I give up! */ + /* It is not necessary that number */ + /* be accurate. It is just here to */ + /* pacify Centerline which doesn't */ + /* seem to be able to get it from */ + /* the Makefile. */ +#undef SCRIPTDIR +#define SCRIPTDIR "example/" +#undef EXECSCRIPTDIR +#define EXECSCRIPTDIR "example/" +#endif +char exp_version[] = PACKAGE_VERSION; +#define NEED_TCL_MAJOR 7 +#define NEED_TCL_MINOR 5 + +char *exp_argv0 = "this program"; /* default program name */ +void (*exp_app_exit)() = 0; +void (*exp_event_exit)() = 0; +FILE *exp_cmdfile = 0; +char *exp_cmdfilename = 0; +int exp_cmdlinecmds = FALSE; +int exp_interactive = FALSE; +int exp_buffer_command_input = FALSE;/* read in entire cmdfile at once */ +int exp_fgets(); + +Tcl_Interp *exp_interp; /* for use by signal handlers who can't figure out */ + /* the interpreter directly */ +int exp_tcl_debugger_available = FALSE; + +int exp_getpid; + +int exp_strict_write = 0; + + +static void +usage(interp) +Tcl_Interp *interp; +{ + char buffer [] = "exit 1"; + expErrorLog("usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]\r\n"); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + Tcl_Eval(interp, buffer); +} + +/* this clumsiness because pty routines don't know Tcl definitions */ +/*ARGSUSED*/ +static +void +exp_pty_exit_for_tcl(clientData) +ClientData clientData; +{ + exp_pty_exit(); +} + +static +void +exp_init_pty_exit() +{ + Tcl_CreateExitHandler(exp_pty_exit_for_tcl,(ClientData)0); +} + +/* This can be called twice or even recursively - it's safe. */ +void +exp_exit_handlers(clientData) +ClientData clientData; +{ + extern int exp_forked; + + Tcl_Interp *interp = (Tcl_Interp *)clientData; + + /* use following checks to prevent recursion in exit handlers */ + /* if this code ever supports multiple interps, these should */ + /* become interp-specific */ + + static int did_app_exit = FALSE; + static int did_expect_exit = FALSE; + + if (!did_expect_exit) { + did_expect_exit = TRUE; + /* called user-defined exit routine if one exists */ + if (exp_onexit_action) { + int result = Tcl_GlobalEval(interp,exp_onexit_action); + if (result != TCL_OK) Tcl_BackgroundError(interp); + } + } else { + expDiagLogU("onexit handler called recursively - forcing exit\r\n"); + } + + if (exp_app_exit) { + if (!did_app_exit) { + did_app_exit = TRUE; + (*exp_app_exit)(interp); + } else { + expDiagLogU("application exit handler called recursively - forcing exit\r\n"); + } + } + + if (!exp_disconnected + && !exp_forked + && (exp_dev_tty != -1) + && isatty(exp_dev_tty)) { + if (exp_ioctled_devtty) { + exp_tty_set(interp,&exp_tty_original,exp_dev_tty,0); + } + } + /* all other files either don't need to be flushed or will be + implicitly closed at exit. Spawned processes are free to continue + running, however most will shutdown after seeing EOF on stdin. + Some systems also deliver SIGHUP and other sigs to idle processes + which will blow them away if not prepared. + */ + + exp_close_all(interp); +} + +static int +history_nextid(interp) +Tcl_Interp *interp; +{ + /* unncessarily tricky coding - if nextid isn't defined, + maintain our own static version */ + + static int nextid = 0; + CONST char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0); + if (nextidstr) { + /* intentionally ignore failure */ + (void) sscanf(nextidstr,"%d",&nextid); + } + return ++nextid; +} + +/* this stupidity because Tcl needs commands in writable space */ +static char prompt1[] = "prompt1"; +static char prompt2[] = "prompt2"; + +static char *prompt2_default = "+> "; +static char prompt1_default[] = "expect%d.%d> "; + +/*ARGSUSED*/ +int +Exp_Prompt1ObjCmd(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; +int objc; +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + static char buffer[200]; + + Interp *iPtr = (Interp *)interp; + + sprintf(buffer,prompt1_default,iPtr->numLevels,history_nextid(interp)); + Tcl_SetResult(interp,buffer,TCL_STATIC); + return(TCL_OK); +} + +/*ARGSUSED*/ +int +Exp_Prompt2ObjCmd(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; +int objc; +Tcl_Obj *CONST objv[]; +{ + Tcl_SetResult(interp,prompt2_default,TCL_STATIC); + return(TCL_OK); +} + +/*ARGSUSED*/ +static int +ignore_procs(interp,s) +Tcl_Interp *interp; +char *s; /* function name */ +{ + return ((s[0] == 'p') && + (s[1] == 'r') && + (s[2] == 'o') && + (s[3] == 'm') && + (s[4] == 'p') && + (s[5] == 't') && + ((s[6] == '1') || + (s[6] == '2')) && + (s[7] == '\0') + ); +} + +/* handle an error from Tcl_Eval or Tcl_EvalFile */ +static void +handle_eval_error(interp,check_for_nostack) +Tcl_Interp *interp; +int check_for_nostack; +{ + char *msg; + + /* if errorInfo has something, print it */ + /* else use what's in the interp result */ + + msg = Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY); + if (!msg) msg = Tcl_GetStringResult (interp); + else if (check_for_nostack) { + /* suppress errorInfo if generated via */ + /* error ... -nostack */ + if (0 == strncmp("-nostack",msg,8)) return; + + /* + * This shouldn't be necessary, but previous test fails + * because of recent change John made - see eval_trap_action() + * in exp_trap.c for more info + */ + if (exp_nostack_dump) { + exp_nostack_dump = FALSE; + return; + } + } + + /* no \n at end, since ccmd will already have one. */ + /* Actually, this is not true if command is last in */ + /* file and has no newline after it, oh well */ + expErrorLogU(exp_cook(msg,(int *)0)); + expErrorLogU("\r\n"); +} + +/* user has pressed escape char from interact or somehow requested expect. +If a user-supplied command returns: + +TCL_ERROR, assume user is experimenting and reprompt +TCL_OK, ditto +TCL_RETURN, return TCL_OK (assume user just wants to escape() to return) +EXP_TCL_RETURN, return TCL_RETURN +anything else return it +*/ +int +exp_interpreter(interp,eofObj) +Tcl_Interp *interp; +Tcl_Obj *eofObj; +{ + Tcl_Obj *commandPtr = NULL; + int code; + int gotPartial; + Interp *iPtr = (Interp *)interp; + int tty_changed = FALSE; + exp_tty tty_old; + int was_raw, was_echo; + + Tcl_Channel inChannel, outChannel; + ExpState *esPtr = expStdinoutGet(); + /* int fd = fileno(stdin);*/ + + expect_key++; + commandPtr = Tcl_NewObj(); + Tcl_IncrRefCount(commandPtr); + + gotPartial = 0; + while (TRUE) { + if (Tcl_IsShared(commandPtr)) { + Tcl_DecrRefCount(commandPtr); + commandPtr = Tcl_DuplicateObj(commandPtr); + Tcl_IncrRefCount(commandPtr); + } + outChannel = expStdinoutGet()->channel; + if (outChannel) { + Tcl_Flush(outChannel); + } + if (!esPtr->open) { + code = EXP_EOF; + goto eof; + } + + /* force terminal state */ + tty_changed = exp_tty_cooked_echo(interp,&tty_old,&was_raw,&was_echo); + + if (!gotPartial) { + code = Tcl_Eval(interp,prompt1); + if (code == TCL_OK) { + expStdoutLogU(Tcl_GetStringResult(interp),1); + } + else expStdoutLog(1,prompt1_default,iPtr->numLevels,history_nextid(interp)); + } else { + code = Tcl_Eval(interp,prompt2); + if (code == TCL_OK) { + expStdoutLogU(Tcl_GetStringResult(interp),1); + } + else expStdoutLogU(prompt2_default,1); + } + + esPtr->force_read = 1; + code = exp_get_next_event(interp,&esPtr,1,&esPtr,EXP_TIME_INFINITY, + esPtr->key); + /* check for code == EXP_TCLERROR? */ + + if (code != EXP_EOF) { + inChannel = expStdinoutGet()->channel; + code = Tcl_GetsObj(inChannel, commandPtr); +#ifdef SIMPLE_EVENT + if (code == -1 && errno == EINTR) { + if (Tcl_AsyncReady()) { + (void) Tcl_AsyncInvoke(interp,TCL_OK); + } + continue; + } +#endif + if (code < 0) code = EXP_EOF; + if ((code == 0) && Tcl_Eof(inChannel) && !gotPartial) code = EXP_EOF; + } + + eof: + if (code == EXP_EOF) { + if (eofObj) { + code = Tcl_EvalObjEx(interp,eofObj,0); + } else { + code = TCL_OK; + } + goto done; + } + + expDiagWriteObj(commandPtr); + /* intentionally always write to logfile */ + if (expLogChannelGet()) { + Tcl_WriteObj(expLogChannelGet(),commandPtr); + } + /* no need to write to stdout, since they will see */ + /* it just from it having been echoed as they are */ + /* typing it */ + + /* + * Add the newline removed by Tcl_GetsObj back to the string. + */ + + if (Tcl_IsShared(commandPtr)) { + Tcl_DecrRefCount(commandPtr); + commandPtr = Tcl_DuplicateObj(commandPtr); + Tcl_IncrRefCount(commandPtr); + } + Tcl_AppendToObj(commandPtr, "\n", 1); + if (!TclObjCommandComplete(commandPtr)) { + gotPartial = 1; + continue; + } + + Tcl_AppendToObj(commandPtr, "\n", 1); + if (!TclObjCommandComplete(commandPtr)) { + gotPartial = 1; + continue; + } + + gotPartial = 0; + + if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo); + + code = Tcl_RecordAndEvalObj(interp, commandPtr, 0); + Tcl_DecrRefCount(commandPtr); + commandPtr = Tcl_NewObj(); + Tcl_IncrRefCount(commandPtr); + switch (code) { + char *str; + + case TCL_OK: + str = Tcl_GetStringResult(interp); + if (*str != 0) { + expStdoutLogU(exp_cook(str,(int *)0),1); + expStdoutLogU("\r\n",1); + } + continue; + case TCL_ERROR: + handle_eval_error(interp,1); + /* since user is typing by hand, we expect lots */ + /* of errors, and want to give another chance */ + continue; +#define finish(x) {code = x; goto done;} + case TCL_BREAK: + case TCL_CONTINUE: + finish(code); + case EXP_TCL_RETURN: + finish(TCL_RETURN); + case TCL_RETURN: + finish(TCL_OK); + default: + /* note that ccmd has trailing newline */ + expErrorLog("error %d: ",code); + expErrorLogU(Tcl_GetString(Tcl_GetObjResult(interp))); + expErrorLogU("\r\n"); + continue; + } + } + /* cannot fall thru here, must jump to label */ + done: + if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo); + + Tcl_DecrRefCount(commandPtr); + return(code); +} + +/*ARGSUSED*/ +int +Exp_ExpVersionObjCmd(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int emajor, umajor; + char *user_version; /* user-supplied version string */ + + if (objc == 1) { + Tcl_SetResult(interp,exp_version,TCL_STATIC); + return(TCL_OK); + } + if (objc > 3) { + exp_error(interp,"usage: expect_version [[-exit] version]"); + return(TCL_ERROR); + } + + user_version = Tcl_GetString (objv[objc==2?1:2]); + emajor = atoi(exp_version); + umajor = atoi(user_version); + + /* first check major numbers */ + if (emajor == umajor) { + int u, e; + + /* now check minor numbers */ + char *dot = strchr(user_version,'.'); + if (!dot) { + exp_error(interp,"version number must include a minor version number"); + return TCL_ERROR; + } + + u = atoi(dot+1); + dot = strchr(exp_version,'.'); + e = atoi(dot+1); + if (e >= u) return(TCL_OK); + } + + if (objc == 2) { + exp_error(interp,"%s requires Expect version %s (but using %s)", + exp_argv0,user_version,exp_version); + return(TCL_ERROR); + } + expErrorLog("%s requires Expect version %s (but is using %s)\r\n", + exp_argv0,user_version,exp_version); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + /*NOTREACHED, but keep compiler from complaining*/ + return TCL_ERROR; +} + +static char init_auto_path[] = "\ +if {$exp_library != \"\"} {\n\ + lappend auto_path $exp_library\n\ +}\n\ +if {$exp_exec_library != \"\"} {\n\ + lappend auto_path $exp_exec_library\n\ +}"; + +static void +DeleteCmdInfo (clientData, interp) + ClientData clientData; + Tcl_Interp *interp; +{ + ckfree (clientData); +} + + +int +Expect_Init(interp) +Tcl_Interp *interp; +{ + static int first_time = TRUE; + + Tcl_CmdInfo* close_info = NULL; + Tcl_CmdInfo* return_info = NULL; + + if (first_time) { +#ifndef USE_TCL_STUBS + int tcl_major = atoi(TCL_VERSION); + char *dot = strchr(TCL_VERSION,'.'); + int tcl_minor = atoi(dot+1); + + if (tcl_major < NEED_TCL_MAJOR || + (tcl_major == NEED_TCL_MAJOR && tcl_minor < NEED_TCL_MINOR)) { + + char bufa [20]; + char bufb [20]; + Tcl_Obj* s = Tcl_NewStringObj (exp_argv0,-1); + + sprintf(bufa,"%d.%d",tcl_major,tcl_minor); + sprintf(bufb,"%d.%d",NEED_TCL_MAJOR,NEED_TCL_MINOR); + + Tcl_AppendStringsToObj (s, + " compiled with Tcl ", bufa, + " but needs at least Tcl ", bufb, + "\n", NULL); + Tcl_SetObjResult (interp, s); + return TCL_ERROR; + } +#endif + } + +#ifndef USE_TCL_STUBS + if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } +#else + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { + return TCL_ERROR; + } +#endif + + /* + * Save initial close and return for later use + */ + + close_info = (Tcl_CmdInfo*) ckalloc (sizeof (Tcl_CmdInfo)); + if (Tcl_GetCommandInfo(interp, "close", close_info) == 0) { + ckfree ((char*) close_info); + return TCL_ERROR; + } + return_info = (Tcl_CmdInfo*) ckalloc (sizeof (Tcl_CmdInfo)); + if (Tcl_GetCommandInfo(interp, "return", return_info) == 0){ + ckfree ((char*) close_info); + ckfree ((char*) return_info); + return TCL_ERROR; + } + Tcl_SetAssocData (interp, EXP_CMDINFO_CLOSE, DeleteCmdInfo, (ClientData) close_info); + Tcl_SetAssocData (interp, EXP_CMDINFO_RETURN, DeleteCmdInfo, (ClientData) return_info); + + /* + * Expect redefines close so we need to save the original (pre-expect) + * definition so it can be restored before exiting. + * + * Needed when expect is dynamically loaded after close has + * been redefined e.g. the virtual file system in tclkit + */ + if (TclRenameCommand(interp, "close", "_close.pre_expect") != TCL_OK) { + return TCL_ERROR; + } + + if (Tcl_PkgProvide(interp, "Expect", PACKAGE_VERSION) != TCL_OK) { + return TCL_ERROR; + } + + Tcl_Preserve(interp); + Tcl_CreateExitHandler(Tcl_Release,(ClientData)interp); + + if (first_time) { + exp_getpid = getpid(); + exp_init_pty(); + exp_init_pty_exit(); + exp_init_tty(); /* do this only now that we have looked at */ + /* original tty state */ + exp_init_stdio(); + exp_init_sig(); + exp_init_event(); + exp_init_trap(); + exp_init_unit_random(); + exp_init_spawn_ids(interp); + expChannelInit(); + expDiagInit(); + expLogInit(); + expDiagLogPtrSet(expDiagLogU); + expErrnoMsgSet(Tcl_ErrnoMsg); + + Tcl_CreateExitHandler(exp_exit_handlers,(ClientData)interp); + + first_time = FALSE; + } + + /* save last known interp for emergencies */ + exp_interp = interp; + + /* initialize commands */ + exp_init_most_cmds(interp); /* add misc cmds to interpreter */ + exp_init_expect_cmds(interp); /* add expect cmds to interpreter */ + exp_init_main_cmds(interp); /* add main cmds to interpreter */ + exp_init_trap_cmds(interp); /* add trap cmds to interpreter */ + exp_init_tty_cmds(interp); /* add tty cmds to interpreter */ + exp_init_interact_cmds(interp); /* add interact cmds to interpreter */ + + /* initialize variables */ + exp_init_spawn_id_vars(interp); + expExpectVarsInit(); + + /* + * For each of the the Tcl variables, "expect_library", + *"exp_library", and "exp_exec_library", set the variable + * if it does not already exist. This mechanism allows the + * application calling "Expect_Init()" to set these varaibles + * to alternate locations from where Expect was built. + */ + + if (Tcl_GetVar(interp, "expect_library", TCL_GLOBAL_ONLY) == NULL) { + Tcl_SetVar(interp,"expect_library",SCRIPTDIR,0);/* deprecated */ + } + if (Tcl_GetVar(interp, "exp_library", TCL_GLOBAL_ONLY) == NULL) { + Tcl_SetVar(interp,"exp_library",SCRIPTDIR,0); + } + if (Tcl_GetVar(interp, "exp_exec_library", TCL_GLOBAL_ONLY) == NULL) { + Tcl_SetVar(interp,"exp_exec_library",EXECSCRIPTDIR,0); + } + + Tcl_Eval(interp,init_auto_path); + Tcl_ResetResult(interp); + +#ifdef TCL_DEBUGGER + Dbg_IgnoreFuncs(interp,ignore_procs); +#endif + + return TCL_OK; +} + +static char sigint_init_default[80]; +static char sigterm_init_default[80]; +static char debug_init_default[] = "trap {exp_debug 1} SIGINT"; + +void +exp_parse_argv(interp,argc,argv) +Tcl_Interp *interp; +int argc; +char **argv; +{ + char argc_rep[10]; /* enough space for storing literal rep of argc */ + + int sys_rc = TRUE; /* read system rc file */ + int my_rc = TRUE; /* read personal rc file */ + + int c; + int rc; + + extern int optind; + extern char *optarg; + char *args; /* ptr to string-rep of all args */ + char *debug_init; + + exp_argv0 = argv[0]; + +#ifdef TCL_DEBUGGER + Dbg_ArgcArgv(argc,argv,1); +#endif + + /* initially, we must assume we are not interactive */ + /* this prevents interactive weirdness courtesy of unknown via -c */ + /* after handling args, we can change our mind */ + Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); + + /* there's surely a system macro to do this but I don't know what it is */ +#define EXP_SIG_EXIT(signalnumber) (0x80|signalnumber) + + sprintf(sigint_init_default, "trap {exit %d} SIGINT", EXP_SIG_EXIT(SIGINT)); + Tcl_Eval(interp,sigint_init_default); + sprintf(sigterm_init_default,"trap {exit %d} SIGTERM",EXP_SIG_EXIT(SIGTERM)); + Tcl_Eval(interp,sigterm_init_default); + + /* + * [#418892]. The '+' character in front of every other option + * declaration causes 'GNU getopt' to deactivate its + * non-standard behaviour and switch to POSIX. Other + * implementations of 'getopt' might recognize the option '-+' + * because of this, but the following switch will catch this + * and generate a usage message. + */ + + while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) { + switch(c) { + case '-': + /* getopt already handles -- internally, however */ + /* this allows us to abort getopt when dash is at */ + /* the end of another option which is required */ + /* in order to allow things like -n- on #! line */ + goto abort_getopt; + case 'c': /* command */ + exp_cmdlinecmds = TRUE; + rc = Tcl_Eval(interp,optarg); + if (rc != TCL_OK) { + expErrorLogU(exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0)); + expErrorLogU("\r\n"); + } + break; + case 'd': expDiagToStderrSet(TRUE); + expDiagLog("expect version %s\r\n",exp_version); + break; +#ifdef TCL_DEBUGGER + case 'D': + exp_tcl_debugger_available = TRUE; + if (Tcl_GetInt(interp,optarg,&rc) != TCL_OK) { + expErrorLog("%s: -D argument must be 0 or 1\r\n",exp_argv0); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + + /* set up trap handler before Dbg_On so user does */ + /* not have to see it at first debugger prompt */ + if (0 == (debug_init = getenv("EXPECT_DEBUG_INIT"))) { + debug_init = debug_init_default; + } + Tcl_Eval(interp,debug_init); + if (rc == 1) Dbg_On(interp,0); + break; +#endif + case 'f': /* name of cmd file */ + exp_cmdfilename = optarg; + break; + case 'b': /* read cmdfile one part at a time */ + exp_cmdfilename = optarg; + exp_buffer_command_input = TRUE; + break; + case 'i': /* interactive */ + exp_interactive = TRUE; + break; + case 'n': /* don't read personal rc file */ + my_rc = FALSE; + break; + case 'N': /* don't read system-wide rc file */ + sys_rc = FALSE; + break; + case 'v': + printf("expect version %s\n", exp_version); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 0"; + Tcl_Eval(interp, buffer); + } + break; + default: usage(interp); + } + } + + abort_getopt: + + for (c = 0;c<argc;c++) { + expDiagLog("argv[%d] = ",c); + expDiagLogU(argv[c]); + expDiagLogU(" "); + } + expDiagLogU("\r\n"); + + /* if user hasn't explicitly requested we be interactive */ + /* look for a file or some other source of commands */ + if (!exp_interactive) { + /* get cmd file name, if we haven't got it already */ + if (!exp_cmdfilename && (optind < argc)) { + exp_cmdfilename = argv[optind]; + optind++; + + /* + * [#418892]. Skip a "--" found immediately + * behind the name of the script to + * execute. Don't try this if there are no + * arguments behind the "--" anymore. All + * other appearances of "--" are handled by + * the "getopt"-loop above. + */ + + if ((optind < argc) && + (0 == strcmp ("--", argv[optind]))) { + optind++; + } + } + + if (exp_cmdfilename) { + if (streq(exp_cmdfilename,"-")) { + exp_cmdfile = stdin; + exp_cmdfilename = 0; + } else if (exp_buffer_command_input) { + errno = 0; + exp_cmdfile = fopen(exp_cmdfilename,"r"); + if (exp_cmdfile) { + exp_cmdfilename = 0; + expCloseOnExec(fileno(exp_cmdfile)); + } else { + CONST char *msg; + + if (errno == 0) { + msg = "could not read - odd file name?"; + } else { + msg = Tcl_ErrnoMsg(errno); + } + expErrorLog("%s: %s\r\n",exp_cmdfilename,msg); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + } + } else if (!exp_cmdlinecmds) { + if (isatty(0)) { + /* no other source of commands, force interactive */ + exp_interactive = TRUE; + } else { + /* read cmds from redirected stdin */ + exp_cmdfile = stdin; + } + } + } + + if (exp_interactive) { + Tcl_SetVar(interp, "tcl_interactive","1",TCL_GLOBAL_ONLY); + } + + /* collect remaining args and make into argc, argv0, and argv */ + sprintf(argc_rep,"%d",argc-optind); + Tcl_SetVar(interp,"argc",argc_rep,0); + expDiagLog("set argc %s\r\n",argc_rep); + + if (exp_cmdfilename) { + Tcl_SetVar(interp,"argv0",exp_cmdfilename,0); + expDiagLog("set argv0 \"%s\"\r\n",exp_cmdfilename); + } else { + Tcl_SetVar(interp,"argv0",exp_argv0,0); + expDiagLog("set argv0 \"%s\"\r\n",exp_argv0); + } + + args = Tcl_Merge(argc-optind,argv+optind); + expDiagLogU("set argv \""); + expDiagLogU(args); + expDiagLogU("\"\r\n"); + Tcl_SetVar(interp,"argv",args,0); + Tcl_Free(args); + + exp_interpret_rcfiles(interp,my_rc,sys_rc); +} + +static void +print_result (interp) + Tcl_Interp* interp; +{ + char* msg = Tcl_GetStringResult (interp); + if (msg[0] != 0) { + expErrorLogU(msg); + expErrorLogU("\r\n"); + } +} + +static void +run_exit (interp) + Tcl_Interp* interp; +{ + /* SF #439042 -- Allow overide of "exit" by user / script + */ + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); +} + +/* read rc files */ +void +exp_interpret_rcfiles(interp,my_rc,sys_rc) +Tcl_Interp *interp; +int my_rc; +int sys_rc; +{ + int rc; + + if (sys_rc) { + char file[200]; + int fd; + + sprintf(file,"%s/expect.rc",SCRIPTDIR); + if (-1 != (fd = open(file,0))) { + if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) { + expErrorLog("error executing system initialization file: %s\r\n",file); + if (rc != TCL_ERROR) + expErrorLog("Tcl_Eval = %d\r\n",rc); + print_result (interp); + run_exit (interp); + } + close(fd); + } + } + if (my_rc) { + char file[200]; + char *home; + int fd; + char *getenv(); + + if ((NULL != (home = getenv("DOTDIR"))) || + (NULL != (home = getenv("HOME")))) { + sprintf(file,"%s/.expect.rc",home); + if (-1 != (fd = open(file,0))) { + if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) { + expErrorLog("error executing file: %s\r\n",file); + if (rc != TCL_ERROR) + expErrorLog("Tcl_Eval = %d\r\n",rc); + print_result (interp); + run_exit (interp); + } + close(fd); + } + } + } +} + +int +exp_interpret_cmdfilename(interp,filename) +Tcl_Interp *interp; +char *filename; +{ + int rc; + + expDiagLog("executing commands from command file %s\r\n",filename); + + Tcl_ResetResult(interp); + if (TCL_OK != (rc = Tcl_EvalFile(interp,filename))) { + /* EvalFile doesn't bother to copy error to errorInfo */ + /* so force it */ + Tcl_AddErrorInfo(interp, ""); + handle_eval_error(interp,0); + } + return rc; +} + +int +exp_interpret_cmdfile(interp,fp) +Tcl_Interp *interp; +FILE *fp; +{ + int rc = 0; + int gotPartial; + int eof; + + Tcl_DString dstring; + Tcl_DStringInit(&dstring); + + expDiagLogU("executing commands from command file\r\n"); + + gotPartial = 0; + eof = FALSE; + while (1) { + char line[BUFSIZ];/* buffer for partial Tcl command */ + char *ccmd; /* pointer to complete Tcl command */ + + if (fgets(line,BUFSIZ,fp) == NULL) { + if (!gotPartial) break; + eof = TRUE; + } + ccmd = Tcl_DStringAppend(&dstring,line,-1); + if (!Tcl_CommandComplete(ccmd) && !eof) { + gotPartial = 1; + continue; /* continue collecting command */ + } + gotPartial = 0; + + rc = Tcl_Eval(interp,ccmd); + Tcl_DStringFree(&dstring); + if (rc != TCL_OK) { + handle_eval_error(interp,0); + break; + } + if (eof) break; + } + Tcl_DStringFree(&dstring); + return rc; +} + +static struct exp_cmd_data cmd_data[] = { + {"exp_version", Exp_ExpVersionObjCmd, 0, 0, 0}, + {"prompt1", Exp_Prompt1ObjCmd, 0, 0, EXP_NOPREFIX}, + {"prompt2", Exp_Prompt2ObjCmd, 0, 0, EXP_NOPREFIX}, +{0}}; + +void +exp_init_main_cmds(interp) +Tcl_Interp *interp; +{ + exp_create_commands(interp,cmd_data); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_memmove.c b/exp_memmove.c new file mode 100644 index 0000000..324bc2d --- /dev/null +++ b/exp_memmove.c @@ -0,0 +1,25 @@ +/* memmove - some systems lack this */ + +#include "expect_cf.h" +#include "tcl.h" + +/* like memcpy but can handle overlap */ +#ifndef HAVE_MEMMOVE +char * +memmove(dest,src,n) +VOID *dest; +CONST VOID *src; +int n; +{ + char *d; + CONST char *s; + + d = dest; + s = src; + if (s<d && (d < s+n)) { + for (d+=n, s+=n; 0<n; --n) + *--d = *--s; + } else for (;0<n;--n) *d++ = *s++; + return dest; +} +#endif /* HAVE_MEMMOVE */ diff --git a/exp_noevent.c b/exp_noevent.c new file mode 100644 index 0000000..d145b49 --- /dev/null +++ b/exp_noevent.c @@ -0,0 +1,176 @@ +/* interact (with only one process) - give user keyboard control + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +/* This file exists for deficient versions of UNIX that lack select, +poll, or some other multiplexing hook. Instead, this code uses two +processes per spawned process. One sends characters from the spawnee +to the spawner; a second send chars the other way. + +This will work on any UNIX system. The only sacrifice is that it +doesn't support multiple processes. Eventually, it should catch +SIGCHLD on dead processes and do the right thing. But it is pretty +gruesome to imagine so many processes to do all this. If you change +it successfully, please mail back the changes to me. - Don +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include "tcl.h" +#include "exp_prog.h" +#include "exp_command.h" /* for struct ExpState defs */ +#include "exp_event.h" + +/*ARGSUSED*/ +void +exp_arm_background_filehandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_disarm_background_filehandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_disarm_background_filehandler_force(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_unblock_background_filehandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_block_background_filehandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_event_disarm(fd) +int fd; +{ +} + +/* returns status, one of EOF, TIMEOUT, ERROR or DATA */ +/*ARGSUSED*/ +int +exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key) +Tcl_Interp *interp; +ExpState (*esPtrs)[]; +int n; /* # of esPtrs */ +ExpState **esPtrOut; /* 1st event master, not set if none */ +int timeout; /* seconds */ +int key; +{ + if (n > 1) { + exp_error(interp,"expect not compiled with multiprocess support"); + /* select a different INTERACT_TYPE in Makefile */ + return(TCL_ERROR); + } + + esPtr = *esPtrOut = esPtrs[0]; + + if (esPtr->key != key) { + esPtr->key = key; + esPtr->force_read = FALSE; + return(EXP_DATA_OLD); + } else if ((!esPtr->force_read) && (esPtr->size != 0)) { + return(EXP_DATA_OLD); + } + + return(EXP_DATA_NEW); +} + +/*ARGSUSED*/ +int +exp_get_next_event_info(interp,esPtr,ready_mask) +Tcl_Interp *interp; +ExpState *esPtr; +int ready_mask; +{ +} + +/* There is no portable way to do sub-second sleeps on such a system, so */ +/* do the next best thing (without a busy loop) and fake it: sleep the right */ +/* amount of time over the long run. Note that while "subtotal" isn't */ +/* reinitialized, it really doesn't matter for such a gross hack as random */ +/* scheduling pauses will easily introduce occasional one second delays. */ +int /* returns TCL_XXX */ +exp_dsleep(interp,sec) +Tcl_Interp *interp; +double sec; +{ + static double subtotal = 0; + int seconds; + + subtotal += sec; + if (subtotal < 1) return TCL_OK; + seconds = subtotal; + subtotal -= seconds; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(rc); + } + sleep(seconds); + return TCL_OK; +} + +#if 0 +/* There is no portable way to do sub-second sleeps on such a system, so */ +/* do the next best thing (without a busy loop) and fake it: sleep the right */ +/* amount of time over the long run. Note that while "subtotal" isn't */ +/* reinitialized, it really doesn't matter for such a gross hack as random */ +/* scheduling pauses will easily introduce occasional one second delays. */ +int /* returns TCL_XXX */ +exp_usleep(interp,usec) +Tcl_Interp *interp; +long usec; /* microseconds */ +{ + static subtotal = 0; + int seconds; + + subtotal += usec; + if (subtotal < 1000000) return TCL_OK; + seconds = subtotal/1000000; + subtotal = subtotal%1000000; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); + } + sleep(seconds); + return TCL_OK; +} +#endif /*0*/ + +/* set things up for later calls to event handler */ +void +exp_init_event() +{ + exp_event_exit = 0; +} diff --git a/exp_poll.c b/exp_poll.c new file mode 100644 index 0000000..69324b0 --- /dev/null +++ b/exp_poll.c @@ -0,0 +1,526 @@ +/* exp_poll.c - This file contains UNIX specific procedures for + * poll-based notifier, which is the lowest-level part of the Tcl + * event loop. This file works together with ../generic/tclNotify.c. + * + * Design and implementation of this program was paid for by U.S. tax + * dollars. Therefore it is public domain. However, the author and + * NIST would appreciate credit if this program or parts of it are + * used. + * + * Written by Don Libes, NIST, 2/6/90 + * Rewritten by Don Libes, 2/96 for new Tcl notifier paradigm. + * Rewritten again by Don Libes, 8/97 for yet another Tcl notifier paradigm. + */ + +#include "tclInt.h" +#include "tclPort.h" +#include <signal.h> + +#include <poll.h> +#include <sys/types.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +/* Some systems require that the poll array be non-empty so provide a + * 1-elt array for starters. It will be ignored as soon as it grows + * larger. + */ + +static struct pollfd initialFdArray; +static struct pollfd *fdArray = &initialFdArray; +static int fdsInUse = 0; /* space in use */ +static int fdsMaxSpace = 1; /* space that has actually been allocated */ + +/* + * tclUnixNotify.c -- + * + * This file contains the implementation of the select-based + * Unix-specific notifier, which is the lowest-level part of the + * Tcl event loop. This file works together with + * ../generic/tclNotify.c. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) tclUnixNotfy.c 1.42 97/07/02 20:55:44 + */ + +/* + * This structure is used to keep track of the notifier info for a + * a registered file. + */ + +typedef struct FileHandler { + int fd; + int mask; /* Mask of desired events: TCL_READABLE, + * etc. */ + int readyMask; /* Mask of events that have been seen since the + * last time file handlers were invoked for + * this file. */ + Tcl_FileProc *proc; /* Procedure to call, in the style of + * Tcl_CreateFileHandler. */ + ClientData clientData; /* Argument to pass to proc. */ + int pollArrayIndex; /* index into poll array */ + struct FileHandler *nextPtr;/* Next in list of all files we care about. */ +} FileHandler; + +/* + * The following structure is what is added to the Tcl event queue when + * file handlers are ready to fire. + */ + +typedef struct FileHandlerEvent { + Tcl_Event header; /* Information that is standard for + * all events. */ + int fd; /* File descriptor that is ready. Used + * to find the FileHandler structure for + * the file (can't point directly to the + * FileHandler structure because it could + * go away while the event is queued). */ +} FileHandlerEvent; + +/* + * The following static structure contains the state information for the + * select based implementation of the Tcl notifier. + */ + +static struct { + FileHandler *firstFileHandlerPtr; + /* Pointer to head of file handler list. */ + fd_mask checkMasks[3*MASK_SIZE]; + /* This array is used to build up the masks + * to be used in the next call to select. + * Bits are set in response to calls to + * Tcl_CreateFileHandler. */ + fd_mask readyMasks[3*MASK_SIZE]; + /* This array reflects the readable/writable + * conditions that were found to exist by the + * last call to select. */ + int numFdBits; /* Number of valid bits in checkMasks + * (one more than highest fd for which + * Tcl_WatchFile has been called). */ +} notifier; + +/* + * The following static indicates whether this module has been initialized. + */ + +static int initialized = 0; + +/* + * Static routines defined in this file. + */ + +static void InitNotifier _ANSI_ARGS_((void)); +static void NotifierExitHandler _ANSI_ARGS_(( + ClientData clientData)); +static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, + int flags)); + +/* + *---------------------------------------------------------------------- + * + * InitNotifier -- + * + * Initializes the notifier state. + * + * Results: + * None. + * + * Side effects: + * Creates a new exit handler. + * + *---------------------------------------------------------------------- + */ + +static void +InitNotifier() +{ + initialized = 1; + memset(¬ifier, 0, sizeof(notifier)); + Tcl_CreateExitHandler(NotifierExitHandler, NULL); +} + +/* + *---------------------------------------------------------------------- + * + * NotifierExitHandler -- + * + * This function is called to cleanup the notifier state before + * Tcl is unloaded. + * + * Results: + * None. + * + * Side effects: + * Destroys the notifier window. + * + *---------------------------------------------------------------------- + */ + +static void +NotifierExitHandler(clientData) + ClientData clientData; /* Not used. */ +{ + initialized = 0; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetTimer -- + * + * This procedure sets the current notifier timer value. This + * interface is not implemented in this notifier because we are + * always running inside of Tcl_DoOneEvent. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetTimer(timePtr) + Tcl_Time *timePtr; /* Timeout value, may be NULL. */ +{ + /* + * The interval timer doesn't do anything in this implementation, + * because the only event loop is via Tcl_DoOneEvent, which passes + * timeout values to Tcl_WaitForEvent. + */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_CreateFileHandler -- + * + * This procedure registers a file handler with the Xt notifier. + * + * Results: + * None. + * + * Side effects: + * Creates a new file handler structure and registers one or more + * input procedures with Xt. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_CreateFileHandler(fd, mask, proc, clientData) + int fd; /* Handle of stream to watch. */ + int mask; /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, and TCL_EXCEPTION: + * indicates conditions under which + * proc should be called. */ + Tcl_FileProc *proc; /* Procedure to call for each + * selected event. */ + ClientData clientData; /* Arbitrary data to pass to proc. */ +{ + FileHandler *filePtr; + int index, bit; + int cur_fd_index; + + if (!initialized) { + InitNotifier(); + } + + for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL; + filePtr = filePtr->nextPtr) { + if (filePtr->fd == fd) { + break; + } + } + if (filePtr == NULL) { + filePtr = (FileHandler*) ckalloc(sizeof(FileHandler)); /* MLK */ + filePtr->fd = fd; + filePtr->readyMask = 0; + filePtr->nextPtr = notifier.firstFileHandlerPtr; + notifier.firstFileHandlerPtr = filePtr; + } + filePtr->proc = proc; + filePtr->clientData = clientData; + filePtr->pollArrayIndex = fdsInUse; + cur_fd_index = fdsInUse; + + fdsInUse++; + if (fdsInUse > fdsMaxSpace) { + if (fdArray != &initialFdArray) ckfree((char *)fdArray); + fdArray = (struct pollfd *)ckalloc(fdsInUse*sizeof(struct pollfd)); + fdsMaxSpace = fdsInUse; + } + + fdArray[cur_fd_index].fd = fd; + + /* I know that POLLIN/OUT is right. But I have no idea if POLLPRI + * corresponds well to TCL_EXCEPTION. + */ + + if (mask & TCL_READABLE) { + fdArray[cur_fd_index].events = POLLIN; + } + if (mask & TCL_WRITABLE) { + fdArray[cur_fd_index].events = POLLOUT; + } + if (mask & TCL_EXCEPTION) { + fdArray[cur_fd_index].events = POLLPRI; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DeleteFileHandler -- + * + * Cancel a previously-arranged callback arrangement for + * a file. + * + * Results: + * None. + * + * Side effects: + * If a callback was previously registered on file, remove it. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_DeleteFileHandler(fd) + int fd; /* Stream id for which to remove callback procedure. */ +{ + FileHandler *filePtr, *prevPtr, *lastPtr; + int index, bit, mask, i; + int cur_fd_index; + + if (!initialized) { + InitNotifier(); + } + + /* + * Find the entry for the given file (and return if there + * isn't one). + */ + + for (prevPtr = NULL, filePtr = notifier.firstFileHandlerPtr; ; + prevPtr = filePtr, filePtr = filePtr->nextPtr) { + if (filePtr == NULL) { + return; + } + if (filePtr->fd == fd) { + break; + } + } + + /* + * Clean up information in the callback record. + */ + + if (prevPtr == NULL) { + notifier.firstFileHandlerPtr = filePtr->nextPtr; + } else { + prevPtr->nextPtr = filePtr->nextPtr; + } + + /* back to poll-specific code - DEL */ + + cur_fd_index = filePtr->pollArrayIndex; + fdsInUse--; + + /* if this one is last, do nothing special */ + /* else swap with one at end of array */ + + if (cur_fd_index != fdsInUse) { + int lastfd_in_array = fdArray[fdsInUse].fd; + memcpy(&fdArray[cur_fd_index],&fdArray[fdsInUse],sizeof(struct pollfd)); + + /* update index to reflect new location in array */ + /* first find link corresponding to last element in array */ + + for (lastPtr = notifier.firstFileHandlerPtr; filePtr; lastPtr = lastPtr->nextPtr) { + if (lastPtr->fd == lastfd_in_array) { + lastPtr->pollArrayIndex = cur_fd_index; + break; + } + } + } + + fdsInUse--; + + ckfree((char *) filePtr); +} + +/* + *---------------------------------------------------------------------- + * + * FileHandlerEventProc -- + * + * This procedure is called by Tcl_ServiceEvent when a file event + * reaches the front of the event queue. This procedure is + * responsible for actually handling the event by invoking the + * callback for the file handler. + * + * Results: + * Returns 1 if the event was handled, meaning it should be removed + * from the queue. Returns 0 if the event was not handled, meaning + * it should stay on the queue. The only time the event isn't + * handled is if the TCL_FILE_EVENTS flag bit isn't set. + * + * Side effects: + * Whatever the file handler's callback procedure does. + * + *---------------------------------------------------------------------- + */ + +static int +FileHandlerEventProc(evPtr, flags) + Tcl_Event *evPtr; /* Event to service. */ + int flags; /* Flags that indicate what events to + * handle, such as TCL_FILE_EVENTS. */ +{ + FileHandler *filePtr; + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr; + int mask; + + if (!(flags & TCL_FILE_EVENTS)) { + return 0; + } + + /* + * Search through the file handlers to find the one whose handle matches + * the event. We do this rather than keeping a pointer to the file + * handler directly in the event, so that the handler can be deleted + * while the event is queued without leaving a dangling pointer. + */ + + for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL; + filePtr = filePtr->nextPtr) { + if (filePtr->fd != fileEvPtr->fd) { + continue; + } + + /* + * The code is tricky for two reasons: + * 1. The file handler's desired events could have changed + * since the time when the event was queued, so AND the + * ready mask with the desired mask. + * 2. The file could have been closed and re-opened since + * the time when the event was queued. This is why the + * ready mask is stored in the file handler rather than + * the queued event: it will be zeroed when a new + * file handler is created for the newly opened file. + */ + + mask = filePtr->readyMask & filePtr->mask; + filePtr->readyMask = 0; + if (mask != 0) { + (*filePtr->proc)(filePtr->clientData, mask); + } + break; + } + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_WaitForEvent -- + * + * This function is called by Tcl_DoOneEvent to wait for new + * events on the message queue. If the block time is 0, then + * Tcl_WaitForEvent just polls without blocking. + * + * Results: + * Returns -1 if the select would block forever, otherwise + * returns 0. + * + * Side effects: + * Queues file events that are detected by the select. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_WaitForEvent(timePtr) + Tcl_Time *timePtr; /* Maximum block time, or NULL. */ +{ + FileHandler *filePtr; + FileHandlerEvent *fileEvPtr; + int timeout; + struct timeval *timeoutPtr; + + int bit, index, mask, numFound; + + if (!initialized) { + InitNotifier(); + } + + /* + * Set up the timeout structure. Note that if there are no events to + * check for, we return with a negative result rather than blocking + * forever. + */ + + if (timePtr) { + timeout = timePtr->sec*1000 + timePtr->usec/1000; + + } else if (notifier.numFdBits == 0) { + return -1; + } else { + timeoutPtr = NULL; + } + + numFound = poll(fdArray,fdsInUse,timeout); + + /* + * Queue all detected file events before returning. + */ + + for (filePtr = notifier.firstFileHandlerPtr; + (filePtr != NULL) && (numFound > 0); + filePtr = filePtr->nextPtr) { + index = filePtr->pollArrayIndex; + mask = 0; + + if (fdArray[index].revents & POLLIN) { + mask |= TCL_READABLE; + } + if (fdArray[index].revents & POLLOUT) { + mask |= TCL_WRITABLE; + } + /* I have no idea if this is right ... */ + if (fdArray[index].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) { + mask |= TCL_EXCEPTION; + } + + if (!mask) { + continue; + } else { + numFound--; + } + + /* + * Don't bother to queue an event if the mask was previously + * non-zero since an event must still be on the queue. + */ + + if (filePtr->readyMask == 0) { + fileEvPtr = (FileHandlerEvent *) ckalloc( + sizeof(FileHandlerEvent)); + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); + } + filePtr->readyMask = mask; + } + return 0; +} + diff --git a/exp_prog.h b/exp_prog.h new file mode 100644 index 0000000..96928ce --- /dev/null +++ b/exp_prog.h @@ -0,0 +1,22 @@ +/* exp_prog.h - private symbols common to both expect program and library + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifndef _EXPECT_PROG_H +#define _EXPECT_PROG_H + +#include "expect_tcl.h" +#include "exp_int.h" + +/* yes, I have a weak mind */ +#define streq(x,y) (0 == strcmp((x),(y))) + +/* Constant strings for NewStringObj */ +#define LITERAL(s) Tcl_NewStringObj ((s), sizeof(s)-1) + +#endif /* _EXPECT_PROG_H */ diff --git a/exp_pty.c b/exp_pty.c new file mode 100644 index 0000000..0970211 --- /dev/null +++ b/exp_pty.c @@ -0,0 +1,368 @@ +/* exp_pty.c - generic routines to allocate and test ptys + +Written by: Don Libes, NIST, 3/9/93 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#include <signal.h> +#include <setjmp.h> +#include <sys/file.h> +#include "tcl.h" +#include "exp_int.h" +#include "expect_comm.h" +#include "exp_rename.h" +#include "exp_pty.h" + +#include <errno.h> + +#if 0 +void expDiagLog(); +void expDiagLogU(); +void expDiagLogPtrSet(); +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifdef O_NOCTTY +#define RDWR ((O_RDWR)|(O_NOCTTY)) +#else +#define RDWR O_RDWR +#endif + +static int locked = FALSE; +static char lock[] = "/tmp/ptylock.XXXX"; /* XX is replaced by pty id */ +static char locksrc[50] = "/tmp/expect.pid"; /* pid is replaced by real pid */ + /* locksrc is used as the link source, i.e., something to link from */ + +static int i_read_errno;/* place to save errno, if i_read() == -1, so it + doesn't get overwritten before we get to read it */ +#ifdef HAVE_SIGLONGJMP +static sigjmp_buf env; /* for interruptable read() */ +#else +static jmp_buf env; /* for interruptable read() */ +#endif /* HAVE_SIGLONGJMP */ + +static int env_valid = FALSE; /* whether we can longjmp or not */ + +/* sigalarm_handler and i_read are here just for supporting the sanity */ +/* checking of pty slave devices. I have only seen this happen on BSD */ +/* systems, but it may need to be done to the other pty implementations */ +/* as well. */ + +/* Note that this code is virtually replicated from other code in expect */ +/* At some point, I'll dump one, but not until I'm satisfied no other */ +/* changes are needed */ + +/*ARGSUSED*/ +static RETSIGTYPE +sigalarm_handler(n) +int n; /* unused, for compatibility with STDC */ +{ +#ifdef REARM_SIG + signal(SIGALRM,sigalarm_handler); +#endif + + /* check env_valid first to protect us from the alarm occurring */ + /* in the window between i_read and alarm(0) */ +#ifdef HAVE_SIGLONGJMP + if (env_valid) siglongjmp(env,1); +#else + if (env_valid) longjmp(env,1); +#endif /* HAVE_SIGLONGJMP */ +} + +/* interruptable read */ +static int +i_read(fd,buffer,length,timeout) +int fd; +char *buffer; +int length; +int timeout; +{ + int cc = -2; + + /* since setjmp insists on returning 1 upon longjmp(,0), */ + /* longjmp(,2) instead. */ + + /* restart read if setjmp returns 0 (first time) or 2. */ + /* abort if setjmp returns 1. */ + + alarm(timeout); + +#ifdef HAVE_SIGLONGJMP + if (1 != sigsetjmp(env,1)) { +#else + if (1 != setjmp(env)) { +#endif /* HAVE_SIGLONGJMP */ + env_valid = TRUE; + cc = read(fd,buffer,length); + } + env_valid = FALSE; + i_read_errno = errno; /* errno can be overwritten by the */ + /* time we return */ + alarm(0); + return(cc); +} + +static RETSIGTYPE (*oldAlarmHandler)(); +static RETSIGTYPE (*oldHupHandler)(); +static time_t current_time; /* time when testing began */ + +/* if TRUE, begin testing, else end testing */ +/* returns -1 for failure, 0 for success */ +int +exp_pty_test_start() +{ + int lfd; /* locksrc file descriptor */ + + oldAlarmHandler = signal(SIGALRM,sigalarm_handler); +#ifndef O_NOCTTY + /* Ignore hangup signals generated by pty testing */ + /* when running in background with no control tty. */ + /* Very few systems don't define O_NOCTTY. Only one */ + /* I know of is Next. */ + oldAlarmHandler = signal(SIGHUP,SIG_IGN); +#endif + + time(¤t_time); + + /* recreate locksrc to prevent locks from 'looking old', so */ + /* that they are not deleted (later on in this code) */ + sprintf(locksrc,"/tmp/expect.%d",getpid()); + (void) unlink(locksrc); + /* stanislav shalunov <shalunov@mccme.ru> notes that creat allows */ + /* race - someone could link to important file which root could then */ + /* smash. */ +/* if (-1 == (lfd = creat(locksrc,0777))) { */ + if (-1 == (lfd = open(locksrc,O_RDWR|O_CREAT|O_EXCL,0777))) { + static char buf[256]; + exp_pty_error = buf; + sprintf(exp_pty_error,"can't create %s, errno = %d\n",locksrc, errno); + return(-1); + } + close(lfd); + return 0; +} + +void +exp_pty_test_end() +{ + signal(SIGALRM,oldAlarmHandler); +#ifndef O_NOCTTY + signal(SIGALRM,oldHupHandler); +#endif + (void) unlink(locksrc); +} + +/* returns non-negative if successful */ +int +exp_pty_test( + char *master_name, + char *slave_name, + char bank, + char *num) /* string representation of number */ +{ + int master, slave; + int cc; + char c; + + /* make a lock file to prevent others (for now only */ + /* expects) from allocating pty while we are playing */ + /* with it. This allows us to rigorously test the */ + /* pty is usable. */ + if (exp_pty_lock(bank,num) == 0) { + expDiagLogPtrStr("pty master (%s) is locked...skipping\r\n",master_name); + return(-1); + } + /* verify no one else is using slave by attempting */ + /* to read eof from master side */ + if (0 > (master = open(master_name,RDWR))) return(-1); + +#ifdef __QNX__ + + /* QNX ptys don't have a lot of the same properties such as + read 0 at EOF, etc */ + /* if 1 should pacify C compiler without using nested ifdefs */ + if (1) return master; +#endif + +#ifdef HAVE_PTYTRAP + if (access(slave_name, R_OK|W_OK) != 0) { + expDiagLogPtrStr("could not open slave for pty master (%s)...skipping\r\n", + master_name); + (void) close(master); + return -1; + } + return(master); +#else + if (0 > (slave = open(slave_name,RDWR))) { + (void) close(master); + return -1; + } + (void) close(slave); + cc = i_read(master,&c,1,10); + (void) close(master); + if (!(cc == 0 || cc == -1)) { + expDiagLogPtrStr("%s slave open, skipping\r\n",slave_name); + locked = FALSE; /* leave lock file around so Expect's avoid */ + /* retrying this pty for near future */ + return -1; + } + + /* verify no one else is using master by attempting */ + /* to read eof from slave side */ + if (0 > (master = open(master_name,RDWR))) return(-1); + if (0 > (slave = open(slave_name,RDWR))) { + (void) close(master); + return -1; + } + (void) close(master); + cc = i_read(slave,&c,1,10); + (void) close(slave); + if (!(cc == 0 || cc == -1)) { + expDiagLogPtrStr("%s master open, skipping\r\n",master_name); + return -1; + } + + /* seems ok, let's use it */ + expDiagLogPtrStr("using master pty %s\n",master_name); + return(open(master_name,RDWR)); +#endif +} + +void +exp_pty_unlock(void) +{ + if (locked) { + (void) unlink(lock); + locked = FALSE; + } +} + +/* returns 1 if successfully locked, 0 otherwise */ +int +exp_pty_lock( + char bank, + char *num) /* string representation of number */ +{ + struct stat statbuf; + + if (locked) { + unlink(lock); + locked = FALSE; + } + + sprintf(lock,"/tmp/ptylock.%c%s",bank,num); + + if ((0 == stat(lock,&statbuf)) && + (statbuf.st_mtime+3600 < current_time)) { + (void) unlink(lock); + } + + if (-1 == (link(locksrc,lock))) locked = FALSE; + else locked = TRUE; + + return locked; +} + +/* + * expDiagLog needs a different definition, depending on whether its + * called inside of Expect or the clib. Allow it to be set using this + * function. It's done here because this file (and pty_XXX.c) are the + * ones that call expDiagLog from the two different environments. + */ + +static void (*expDiagLogPtrVal) _ANSI_ARGS_((char *)); + +void +expDiagLogPtrSet(fn) + void (*fn) _ANSI_ARGS_((char *)); +{ + expDiagLogPtrVal = fn; +} + +void +expDiagLogPtr(str) + char *str; +{ + (*expDiagLogPtrVal)(str); +} + + + +void +expDiagLogPtrX(fmt,num) + char *fmt; + int num; +{ + static char buf[1000]; + sprintf(buf,fmt,num); + (*expDiagLogPtrVal)(buf); +} + + +void +expDiagLogPtrStr(fmt,str1) + char *fmt; + char *str1; +{ + static char buf[1000]; + sprintf(buf,fmt,str1); + (*expDiagLogPtrVal)(buf); +} + +void +expDiagLogPtrStrStr(fmt,str1,str2) + char *fmt; + char *str1, *str2; +{ + static char buf[1000]; + sprintf(buf,fmt,str1,str2); + (*expDiagLogPtrVal)(buf); +} + +static char * (*expErrnoMsgVal) _ANSI_ARGS_((int)); + +char * +expErrnoMsg(errorNo) +int errorNo; +{ + return (*expErrnoMsgVal)(errorNo); +} + +void +expErrnoMsgSet(fn) + char * (*fn) _ANSI_ARGS_((int)); +{ + expErrnoMsgVal = fn; +} diff --git a/exp_pty.h b/exp_pty.h new file mode 100644 index 0000000..4ad73b1 --- /dev/null +++ b/exp_pty.h @@ -0,0 +1,19 @@ +/* exp_pty.h - declarations for pty allocation and testing + +Written by: Don Libes, NIST, 3/9/93 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +int exp_pty_test_start(void); +void exp_pty_test_end(void); +int exp_pty_test(char *master_name, char *slave_name, char bank, char *num); +void exp_pty_unlock(void); +int exp_pty_lock(char bank, char *num); +int exp_getptymaster(void); +int exp_getptyslave(int ttycopy, int ttyinit, CONST char *stty_args); + +extern char *exp_pty_slave_name; diff --git a/exp_regexp.c b/exp_regexp.c new file mode 100644 index 0000000..923c8c3 --- /dev/null +++ b/exp_regexp.c @@ -0,0 +1,1265 @@ +#if 0 /*WHOLE FILE*/ + +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + * + * *** NOTE: this code has been altered slightly for use in Tcl. *** + * *** The only change is to use ckalloc and ckfree instead of *** + * *** malloc and free. *** + + * *** and again for Expect!!! - DEL + + * *** More minor corrections stolen from tcl7.5p1/regexp.c - DEL + + */ + +#include "tcl.h" +#include "expect_cf.h" +#include "exp_prog.h" +#include "tclRegexp.h" +#include "exp_regexp.h" +#include "string.h" + +#define NOTSTATIC /* was at one time, but Expect needs access */ + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE (OPEN+NSUBEXP) /* no Analogous to OPEN. */ + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define META "^$.[()|?+*\\" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +/* + * Global work variables for regcomp(). + */ +static char *regparse; /* Input-scan pointer. */ +static int regnpar; /* () count. */ +static char regdummy; +static char *regcode; /* Code-emit pointer; ®dummy = don't. */ +static long regsize; /* Code size. */ + +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define MAGIC 0234 + + +/* + * Forward declarations for regcomp()'s friends. + */ +#ifndef STATIC +#define STATIC static +#endif +STATIC char *reg(); +STATIC char *regbranch(); +STATIC char *regpiece(); +STATIC char *regatom(); +STATIC char *regnode(); +STATIC char *regnext(); +STATIC void regc(); +STATIC void reginsert(); +STATIC void regtail(); +STATIC void regoptail(); +#ifdef STRCSPN +STATIC int strcspn(); +#endif + +/* regcomp originally appeared here - DEL */ + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static char * +reg(paren, flagp) +int paren; /* Parenthesized? */ +int *flagp; +{ + register char *ret; + register char *br; + register char *ender; + register int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = regnpar; + regnpar++; + ret = regnode(OPEN+parno); + } else + ret = NULL; + + /* Pick up the branches, linking them together. */ + br = regbranch(&flags); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*regparse == '|') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END); + regtail(ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + /* Check for proper termination. */ + if (paren && *regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char * +regbranch(flagp) +int *flagp; +{ + register char *ret; + register char *chain; + register char *latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { + latest = regpiece(&flags); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static char * +regpiece(flagp) +int *flagp; +{ + register char *ret; + register char op; + register char *next; + int flags; + + ret = regatom(&flags); + if (ret == NULL) + return(NULL); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret); /* Either x */ + regoptail(ret, regnode(BACK)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH); /* Either */ + regtail(ret, next); + regtail(regnode(BACK), ret); /* loop back */ + regtail(next, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret); /* Either x */ + regtail(ret, regnode(BRANCH)); /* or */ + next = regnode(NOTHING); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) + FAIL("nested *?+"); + + return(ret); +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static char * +regatom(flagp) +int *flagp; +{ + register char *ret; + int flags; + + *flagp = WORST; /* Tentatively. */ + + switch (*regparse++) { + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int clss; + register int classend; + + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); + regparse++; + } else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + clss = UCHARAT(regparse-2)+1; + classend = UCHARAT(regparse); + if (clss > classend+1) + FAIL("invalid [] range"); + for (; clss <= classend; clss++) + regc((char)clss); + regparse++; + } + } else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + /* NOTREACHED */ + break; + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + /* NOTREACHED */ + break; + case '\\': + if (*regparse == '\0') + FAIL("trailing \\"); + ret = regnode(EXACTLY); + regc(*regparse++); + regc('\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + default: { + register int len; + register char ender; + + regparse--; + len = strcspn(regparse, META); + if (len <= 0) + FAIL("internal disaster"); + ender = *(regparse+len); + if (len > 1 && ISMULT(ender)) + len--; /* Back off clear of ?+* operand. */ + *flagp |= HASWIDTH; + if (len == 1) + *flagp |= SIMPLE; + ret = regnode(EXACTLY); + while (len > 0) { + regc(*regparse++); + len--; + } + regc('\0'); + } + break; + } + + return(ret); +} + +/* + - regnode - emit a node + */ +static char * /* Location. */ +regnode(op) +int op; +{ + register char *ret; + register char *ptr; + + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return(ret); + } + + ptr = ret; + *ptr++ = (char)op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + regcode = ptr; + + return(ret); +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void +regc(b) +int b; +{ + if (regcode != ®dummy) + *regcode++ = (char)b; + else + regsize++; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +static void +reginsert(op, opnd) +int op; +char *opnd; +{ + register char *src; + register char *dst; + register char *place; + + if (regcode == ®dummy) { + regsize += 3; + return; + } + + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; /* Op node, where operand used to be. */ + *place++ = (char)op; + *place++ = '\0'; + *place = '\0'; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void +regtail(p, val) +char *p; +char *val; +{ + register char *scan; + register char *temp; + register int offset; + + if (p == ®dummy) + return; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (char)(offset>>8)&0377; + *(scan+2) = (char)offset&0377; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void +regoptail(p, val) +char *p; +char *val; +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + +/* + * regexec and friends + */ + +/* + * Global work variables for regexec(). + */ +static char *reginput; /* String-input pointer. */ +NOTSTATIC char *regbol; /* Beginning of input, for ^ check. */ +static char **regstartp; /* Pointer to startp array. */ +static char **regendp; /* Ditto for endp. */ + +/* + * Forwards. + */ + +NOTSTATIC int regtry(); +STATIC int regmatch(); +STATIC int regrepeat(); + +#ifdef DEBUG +int regnarrate = 0; +void regdump(); +STATIC char *regprop(); +#endif + +#if 0 +/* + - regexec - match a regexp against a string + */ +int +regexec(prog, string, stringlength, matchlength) +register regexp *prog; +register char *string; /* note: CURRENTLY ASSUMED TO BE NULL-TERMINATED!!! */ +int stringlength; /* length of string */ +int *matchlength; /* number of chars matched (or to be skipped) */ + /* set when MATCH or CANT_MATCH */ +{ + register char *s; + extern char *strchr(); + + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + regerror("NULL parameter"); + return(EXP_TCLERROR); + } + + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + regerror("corrupted program"); + return(EXP_KM_ERROR); + } + +#if THIS_RUINS_EXP +/* no need for this shortcut anyway */ + /* If there is a "must appear" string, look for it. */ + if (prog->regmust != NULL) { + s = string; + while ((s = strchr(s, prog->regmust[0])) != NULL) { + if (strncmp(s, prog->regmust, prog->regmlen) == 0) + break; /* Found it. */ + s++; + } + if (s == NULL) /* Not present. */ + return(0); + } +#endif + + /* Mark beginning of line for ^ . */ + regbol = string; + + /* Simplest case: anchored match need be tried only once. */ + if (prog->reganch) { + int r = regtry(prog,string,matchlength); + if (r == CANT_MATCH) *matchlength = stringlength; + return(r); + } + + /* Messy cases: unanchored match. */ + s = string; + if (prog->regstart != '\0') { + register char *s2 = s; + + /* We know what char it must start with. */ + while (1) { + int r; + + s2 = strchr(s2,prog->regstart); + if (s2 == 0) { + *matchlength = stringlength; + return(CANT_MATCH); + } + r = regtry(prog,s2,matchlength); + if (r == CANT_MATCH) { + s2++; + continue; + } + if (s2 == s) return(r); + *matchlength = s2-s; + return CANT_MATCH; + } + } else { + /* We don't -- general case. */ + register char *s2 = s; + int r = regtry(prog,s,matchlength); + if (r == EXP_MATCH) return(r); + else if (r == EXP_CANMATCH) return(r); + /* at this point, we know some characters at front */ + /* of string don't match */ + for (s2++;*s2;s2++) { + r = regtry(prog,s2,matchlength); + if (r == CANT_MATCH) continue; + /* if we match or can_match, say cant_match and */ + /* record the number of chars at front that don't match */ + *matchlength = s2-s; + return(CANT_MATCH); + } + /* made it thru string with CANT_MATCH all the way */ + *matchlength = stringlength; + return(CANT_MATCH); + } +} +#endif + +/* + - regtry - try match at specific point + */ +/* return CAN_MATCH, CANT_MATCH or MATCH */ +int /* 0 failure, 1 success */ +regtry(prog, string, matchlength) +regexp *prog; +char *string; +int *matchlength; /* only set for MATCH */ +{ + register int i; + register char **sp; + register char **ep; + int r; /* result of regmatch */ + + reginput = string; + regstartp = prog->startp; + regendp = prog->endp; + + sp = prog->startp; + ep = prog->endp; + for (i = NSUBEXP; i > 0; i--) { + *sp++ = NULL; + *ep++ = NULL; + } + r = regmatch(prog->program + 1); + if (EXP_MATCH == r) { + prog->startp[0] = string; + prog->endp[0] = reginput; + *matchlength = reginput-string; + return(EXP_MATCH); + } + return(r); /* CAN_MATCH or CANT_MATCH */ +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +/* returns CAN, CANT or MATCH */ +static int /* 0 failure, 1 success */ +regmatch(prog) +char *prog; +{ + register char *scan; /* Current node. */ + char *next; /* Next node. */ +#ifndef strchr /* May be #defined to something else */ + extern char *strchr(); +#endif + + scan = prog; +#ifdef DEBUG + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != NULL) { +#ifdef DEBUG + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); +#endif + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (reginput != regbol) +/* return(0);*/ + return(EXP_CANTMATCH); + break; + case EOL: + if (*reginput != '\0') +/* return(0);*/ +/* note this implies that "$" must match everything received to this point! */ + return(EXP_CANTMATCH); + break; + case ANY: + if (*reginput == '\0') +/* return(0);*/ + return(EXP_CANMATCH); + reginput++; + break; + case EXACTLY: { +/* register int len;*/ + register char *opnd; + + opnd = OPERAND(scan); + + /* this section of code is totally rewritten - DEL */ + /* group of literal chars in pattern */ + /* compare each one */ + do { + if (*opnd != *reginput) { + if (*reginput == '\0') { + return EXP_CANMATCH; + } else return EXP_CANTMATCH; + } + + reginput++; + opnd++; + } while (*opnd != '\0'); + } + break; + case ANYOF: +/* if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) + return(0); +*/ + if (*reginput == '\0') + return(EXP_CANMATCH); + if (strchr(OPERAND(scan),*reginput) == NULL) + return(EXP_CANTMATCH); + reginput++; + break; + case ANYBUT: +/* if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) + return(0); +*/ + if (*reginput == '\0') + return(EXP_CANMATCH); + if (strchr(OPERAND(scan),*reginput) != NULL) + return(EXP_CANTMATCH); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; + int r; /* result of regmatch */ + + doOpen: + no = OP(scan) - OPEN; + save = reginput; + + r = regmatch(next); + if (r == EXP_MATCH) { + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (regstartp[no] == NULL) + regstartp[no] = save; + } + return(r); + } + /* NOTREACHED */ + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; + int r; /* result of regmatch */ + + doClose: + no = OP(scan) - CLOSE; + save = reginput; + + r = regmatch(next); + if (r == EXP_MATCH) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (regendp[no] == NULL) + regendp[no] = save; + } + return(r); + } + /* NOTREACHED */ + break; + case BRANCH: { + register char *save; + int match_status; + + if (OP(next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + match_status = EXP_CANTMATCH; + + do { + int r; + + save = reginput; + r = regmatch(OPERAND(scan)); + if (r == EXP_MATCH) return(r); + if (r == EXP_CANMATCH) { + match_status = r; + } + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return(match_status); + /* NOTREACHED */ + } + } + /* NOTREACHED */ + break; + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; + int match_status; + + if (*reginput == '\0') return EXP_CANMATCH; + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + match_status = EXP_CANTMATCH; + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min) { + /* If it could work, try it. */ + /* 3rd condition allows for CAN_MATCH */ + if (nextch == '\0' || *reginput == nextch || *reginput == '\0') { + int r = regmatch(next); + if (r == EXP_MATCH) + return(EXP_MATCH); + if (r == EXP_CANMATCH) +/* match_status = r;*/ + return(EXP_CANMATCH); + } + /* Couldn't or didn't -- back up. */ + no--; + reginput = save + no; + } + return(match_status); + } + /* NOTREACHED */ + break; + case END: + /* Success! */ + if (*reginput == '\0') { + return(EXP_CANMATCH); + } else { + return(EXP_MATCH); + } + /* return(EXP_CANMATCH); Success! */ + /* NOTREACHED */ + break; + default: + if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) { + goto doOpen; + } else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) { + goto doClose; + } + regerror("memory corruption"); + return(EXP_TCLERROR); + /* NOTREACHED */ + break; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + regerror("corrupted pointers"); + return(EXP_TCLERROR); +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int +regrepeat(p) +char *p; +{ + register int count = 0; + register char *scan; + register char *opnd; +#ifndef strchr /* May be #defined to something else */ +/*DEL*/ extern char *strchr(); +#endif + + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + regerror("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static char * +regnext(p) +register char *p; +{ + register int offset; + + if (p == ®dummy) + return(NULL); + + offset = NEXT(p); + if (offset == 0) + return(NULL); + + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#ifdef DEBUG + +STATIC char *regprop(); + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +void +regdump(r) +regexp *r; +{ + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; + extern char *strchr(); + + + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } + + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static char * +regprop(op) +char *op; +{ + register char *p; + static char buf[50]; + + (void) strcpy(buf, ":"); + + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + default: + if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) { + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + } else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) { + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + } else { + TclRegError("corrupted opcode"); + } + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); +} +#endif + +/* + * The following is provided for those people who do not have strcspn() in + * their C libraries. They should get off their butts and do something + * about it; at least one public-domain implementation of those (highly + * useful) string routines has been published on Usenet. + */ +#ifdef STRCSPN +/* + * strcspn - find length of initial segment of s1 consisting entirely + * of characters not from s2 + */ + +static int +strcspn(s1, s2) +char *s1; +char *s2; +{ + register char *scan1; + register char *scan2; + register int count; + + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); +} +#endif +#endif /* 0 WHOLE FILE */ diff --git a/exp_regexp.h b/exp_regexp.h new file mode 100644 index 0000000..55116dd --- /dev/null +++ b/exp_regexp.h @@ -0,0 +1,10 @@ +#if 0 /* WHOLE FILE */ +/* access to regexp internals */ +#define regbol exp_regbol +#define regtry exp_regtry +#define regexec exp_regexec +#define regerror TclRegError +extern char *regbol; +int regtry(); + +#endif /*0 WHOLE FILE */ diff --git a/exp_rename.h b/exp_rename.h new file mode 100644 index 0000000..1815ad4 --- /dev/null +++ b/exp_rename.h @@ -0,0 +1,11 @@ +/* exp_rename.h - preface globals that appear in the expect library with "exp_" +so we don't conflict with the user. This saves me having to use exp_XXX +throughout the expect program itself, which was written well before the library +when I didn't have to worry about name conflicts. + +Written by: Don Libes, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. */ + diff --git a/exp_select.c b/exp_select.c new file mode 100644 index 0000000..de30853 --- /dev/null +++ b/exp_select.c @@ -0,0 +1,290 @@ +/* exp_select.c - select() interface for Expect + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +/* suppress file-empty warnings produced by some compilers */ +void exp_unused() {} + +#if 0 /* WHOLE FILE!!!! */ +#include "expect_cf.h" +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_SYSSELECT_H +# include <sys/select.h> /* Intel needs this for timeval */ +#endif + +#ifdef HAVE_PTYTRAP +# include <sys/ptyio.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef _AIX +/* AIX has some unusual definition of FD_SET */ +#include <sys/select.h> +#endif + +#if !defined( FD_SET ) && defined( HAVE_SYS_BSDTYPES_H ) + /* like AIX, ISC has it's own definition of FD_SET */ +# include <sys/bsdtypes.h> +#endif /* ! FD_SET && HAVE_SYS_BSDTYPES_H */ + +#include "tcl.h" +#include "exp_prog.h" +#include "exp_command.h" /* for struct exp_f defs */ +#include "exp_event.h" + +#ifdef HAVE_SYSCONF_H +#include <sys/sysconfig.h> +#endif + +#ifndef FD_SET +#define FD_SET(fd,fdset) (fdset)->fds_bits[0] |= (1<<(fd)) +#define FD_CLR(fd,fdset) (fdset)->fds_bits[0] &= ~(1<<(fd)) +#define FD_ZERO(fdset) (fdset)->fds_bits[0] = 0 +#define FD_ISSET(fd,fdset) (((fdset)->fds_bits[0]) & (1<<(fd))) +#ifndef AUX2 +typedef struct fd_set { + long fds_bits[1]; + /* any implementation so pathetic as to not define FD_SET will just */ + /* have to suffer with only 32 bits worth of fds */ +} fd_set; +#endif /* AUX2 */ +#endif + +static struct timeval zerotime = {0, 0}; +static struct timeval anytime = {0, 0}; /* can be changed by user */ + +/* returns status, one of EOF, TIMEOUT, ERROR or DATA */ +int +exp_get_next_event(interp,masters, n,master_out,timeout,key) +Tcl_Interp *interp; +int *masters; +int n; /* # of masters */ +int *master_out; /* 1st event master, not set if none */ +int timeout; /* seconds */ +int key; +{ + static rr = 0; /* round robin ptr */ + + int i; /* index into in-array */ + struct timeval *t; + + fd_set rdrs; + fd_set excep; +/* FIXME: This is really gross, but the folks at Lynx said their select is + * way hosed and to ignore all exceptions. + */ +#ifdef __Lynx__ +#define EXCEP 0 +#else +#define EXCEP &excep +#endif + + for (i=0;i<n;i++) { + struct exp_f *f; + int m; + + rr++; + if (rr >= n) rr = 0; + + m = masters[rr]; + f = exp_fs + m; + + if (f->key != key) { + f->key = key; + f->force_read = FALSE; + *master_out = m; + return(EXP_DATA_OLD); + } else if ((!f->force_read) && (f->size != 0)) { + *master_out = m; + return(EXP_DATA_OLD); + } + } + + if (timeout >= 0) { + t = &anytime; + t->tv_sec = timeout; + } else { + t = NULL; + } + + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); + + /* anything in the environment could have changed */ + return EXP_RECONFIGURE; + } + + FD_ZERO(&rdrs); + FD_ZERO(&excep); + for (i = 0;i < n;i++) { + FD_SET(masters[i],&rdrs); + FD_SET(masters[i],&excep); + } + + /* The reason all fd masks are (seemingly) redundantly cast to */ + /* SELECT_MASK_TYPE is that the HP defines its mask in terms of */ + /* of int * and yet defines FD_SET in terms of fd_set. */ + + if (-1 == select(exp_fd_max+1, + (SELECT_MASK_TYPE *)&rdrs, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)EXCEP, + t)) { + /* window refreshes trigger EINTR, ignore */ + if (errno == EINTR) goto restart; + else if (errno == EBADF) { + /* someone is rotten */ + for (i=0;i<n;i++) { + fd_set suspect; + FD_ZERO(&suspect); + FD_SET(masters[i],&suspect); + if (-1 == select(exp_fd_max+1, + (SELECT_MASK_TYPE *)&suspect, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + &zerotime)) { + exp_error(interp,"invalid spawn_id (%d)\r",masters[i]); + return(EXP_TCLERROR); + } + } + } else { + /* not prepared to handle anything else */ + exp_error(interp,"select: %s\r",Tcl_PosixError(interp)); + return(EXP_TCLERROR); + } + } + + for (i=0;i<n;i++) { + rr++; + if (rr >= n) rr = 0; /* ">" catches previous readys that */ + /* used more fds then we're using now */ + + if (FD_ISSET(masters[rr],&rdrs)) { + *master_out = masters[rr]; + return(EXP_DATA_NEW); +/*#ifdef HAVE_PTYTRAP*/ + } else if (FD_ISSET(masters[rr], &excep)) { +#ifndef HAVE_PTYTRAP + *master_out = masters[rr]; + return(EXP_EOF); +#else + struct request_info ioctl_info; + if (ioctl(masters[rr],TIOCREQCHECK,&ioctl_info) < 0) { + exp_DiagLog("ioctl error on TIOCREQCHECK: %s",Tcl_ErrnoMsg(errno)); + break; + } + if (ioctl_info.request == TIOCCLOSE) { + /* eof */ + *master_out = masters[rr]; + return(EXP_EOF); + } + if (ioctl(masters[rr], TIOCREQSET, &ioctl_info) < 0) + expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno)); + /* presumably, we trapped an open here */ + goto restart; +#endif /* HAVE_PTYTRAP */ + } + } + return(EXP_TIMEOUT); +} + +/*ARGSUSED*/ +int +exp_get_next_event_info(interp,fd,ready_mask) +Tcl_Interp *interp; +int fd; +int ready_mask; +{ + /* this function is only used when running with Tk */ + /* hence, it is merely a stub in this file but to */ + /* pacify lint, return something */ + return 0; +} + +int /* returns TCL_XXX */ +exp_dsleep(interp,sec) +Tcl_Interp *interp; +double sec; +{ + struct timeval t; + + t.tv_sec = sec; + t.tv_usec = (sec - t.tv_sec) * 1000000L; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return rc; + } + if (-1 == select(1, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + &t) + && errno == EINTR) + goto restart; + return TCL_OK; +} + +#if 0 +int /* returns TCL_XXX */ +exp_usleep(interp,usec) +Tcl_Interp *interp; +long usec; /* microseconds */ +{ + struct timeval t; + + t.tv_sec = usec/1000000L; + t.tv_usec = usec%1000000L; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); + } + if (-1 == select(1, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + &t) + && errno == EINTR) + goto restart; + return TCL_OK; +} +#endif /*0*/ + +/* set things up for later calls to event handler */ +void +exp_init_event() +{ +#if 0 +#ifdef _SC_OPEN_MAX + maxfds = sysconf(_SC_OPEN_MAX); +#else + maxfds = getdtablesize(); +#endif +#endif + + exp_event_exit = 0; +} +#endif /* WHOLE FILE !!!! */ diff --git a/exp_simple.c b/exp_simple.c new file mode 100644 index 0000000..780c05e --- /dev/null +++ b/exp_simple.c @@ -0,0 +1,465 @@ +/* + * tclUnixNotify.c -- + * + * This file contains Unix-specific procedures for the notifier, + * which is the lowest-level part of the Tcl event loop. This file + * works together with ../generic/tclNotify.c. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +static char sccsid[] = "@(#) tclUnixNotify.c 1.27 96/01/19 10:30:23"; + +#include "tclInt.h" +#include "tclPort.h" +#include <signal.h> + +/* + * The information below is used to provide read, write, and + * exception masks to select during calls to Tcl_DoOneEvent. + */ + +static fd_mask checkMasks[3*MASK_SIZE]; + /* This array is used to build up the masks + * to be used in the next call to select. + * Bits are set in response to calls to + * Tcl_WatchFile. */ +static fd_mask readyMasks[3*MASK_SIZE]; + /* This array reflects the readable/writable + * conditions that were found to exist by the + * last call to select. */ +static int numFdBits; /* Number of valid bits in checkMasks + * (one more than highest fd for which + * Tcl_WatchFile has been called). */ + +/* + *---------------------------------------------------------------------- + * + * Tcl_WatchFile -- + * + * Arrange for Tcl_DoOneEvent to include this file in the masks + * for the next call to select. This procedure is invoked by + * event sources, which are in turn invoked by Tcl_DoOneEvent + * before it invokes select. + * + * Results: + * None. + * + * Side effects: + * + * The notifier will generate a file event when the I/O channel + * given by fd next becomes ready in the way indicated by mask. + * If fd is already registered then the old mask will be replaced + * with the new one. Once the event is sent, the notifier will + * not send any more events about the fd until the next call to + * Tcl_NotifyFile. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_WatchFile(file, mask) + Tcl_File file; /* Generic file handle for a stream. */ + int mask; /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, and TCL_EXCEPTION: + * indicates conditions to wait for + * in select. */ +{ + int fd, type, index; + fd_mask bit; + + fd = (int) Tcl_GetFileInfo(file, &type); + + if (type != TCL_UNIX_FD) { + panic("Tcl_WatchFile: unexpected file type"); + } + + if (fd >= FD_SETSIZE) { + panic("Tcl_WatchFile can't handle file id %d", fd); + } + + index = fd/(NBBY*sizeof(fd_mask)); + bit = 1 << (fd%(NBBY*sizeof(fd_mask))); + if (mask & TCL_READABLE) { + checkMasks[index] |= bit; + } + if (mask & TCL_WRITABLE) { + (checkMasks+MASK_SIZE)[index] |= bit; + } + if (mask & TCL_EXCEPTION) { + (checkMasks+2*(MASK_SIZE))[index] |= bit; + } + if (numFdBits <= fd) { + numFdBits = fd+1; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_FileReady -- + * + * Indicates what conditions (readable, writable, etc.) were + * present on a file the last time the notifier invoked select. + * This procedure is typically invoked by event sources to see + * if they should queue events. + * + * Results: + * The return value is 0 if none of the conditions specified by mask + * was true for fd the last time the system checked. If any of the + * conditions were true, then the return value is a mask of those + * that were true. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_FileReady(file, mask) + Tcl_File file; /* Generic file handle for a stream. */ + int mask; /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, and TCL_EXCEPTION: + * indicates conditions caller cares about. */ +{ + int index, result, type, fd; + fd_mask bit; + + fd = (int) Tcl_GetFileInfo(file, &type); + if (type != TCL_UNIX_FD) { + panic("Tcl_FileReady: unexpected file type"); + } + + index = fd/(NBBY*sizeof(fd_mask)); + bit = 1 << (fd%(NBBY*sizeof(fd_mask))); + result = 0; + if ((mask & TCL_READABLE) && (readyMasks[index] & bit)) { + result |= TCL_READABLE; + } + if ((mask & TCL_WRITABLE) && ((readyMasks+MASK_SIZE)[index] & bit)) { + result |= TCL_WRITABLE; + } + if ((mask & TCL_EXCEPTION) && ((readyMasks+(2*MASK_SIZE))[index] & bit)) { + result |= TCL_EXCEPTION; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_WaitForEvent -- + * + * This procedure does the lowest level wait for events in a + * platform-specific manner. It uses information provided by + * previous calls to Tcl_WatchFile, plus the timePtr argument, + * to determine what to wait for and how long to wait. + * + * Results: + * None. + * + * Side effects: + * May put the process to sleep for a while, depending on timePtr. + * When this procedure returns, an event of interest to the application + * has probably, but not necessarily, occurred. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_WaitForEvent(timePtr) + Tcl_Time *timePtr; /* Specifies the maximum amount of time + * that this procedure should block before + * returning. The time is given as an + * interval, not an absolute wakeup time. + * NULL means block forever. */ +{ + struct timeval timeout, *timeoutPtr; + int numFound; + + memcpy((VOID *) readyMasks, (VOID *) checkMasks, + 3*MASK_SIZE*sizeof(fd_mask)); + if (timePtr == NULL) { + timeoutPtr = NULL; + } else { + timeoutPtr = &timeout; + timeout.tv_sec = timePtr->sec; + timeout.tv_usec = timePtr->usec; + } + numFound = select(numFdBits, (SELECT_MASK *) &readyMasks[0], + (SELECT_MASK *) &readyMasks[MASK_SIZE], + (SELECT_MASK *) &readyMasks[2*MASK_SIZE], timeoutPtr); + + /* + * Some systems don't clear the masks after an error, so + * we have to do it here. + */ + + if (numFound == -1) { + memset((VOID *) readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); + } + + /* + * Reset the check masks in preparation for the next call to + * select. + */ + + numFdBits = 0; + memset((VOID *) checkMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_Sleep -- + * + * Delay execution for the specified number of milliseconds. + * + * Results: + * None. + * + * Side effects: + * Time passes. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_Sleep(ms) + int ms; /* Number of milliseconds to sleep. */ +{ + static struct timeval delay; + Tcl_Time before, after; + + /* + * The only trick here is that select appears to return early + * under some conditions, so we have to check to make sure that + * the right amount of time really has elapsed. If it's too + * early, go back to sleep again. + */ + + TclGetTime(&before); + after = before; + after.sec += ms/1000; + after.usec += (ms%1000)*1000; + if (after.usec > 1000000) { + after.usec -= 1000000; + after.sec += 1; + } + while (1) { + delay.tv_sec = after.sec - before.sec; + delay.tv_usec = after.usec - before.usec; + if (delay.tv_usec < 0) { + delay.tv_usec += 1000000; + delay.tv_sec -= 1; + } + + /* + * Special note: must convert delay.tv_sec to int before comparing + * to zero, since delay.tv_usec is unsigned on some platforms. + */ + + if ((((int) delay.tv_sec) < 0) + || ((delay.tv_usec == 0) && (delay.tv_sec == 0))) { + break; + } + (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0, + (SELECT_MASK *) 0, &delay); + TclGetTime(&before); + } +} + + + + + + + +#if 0 /* WHOLE FILE */ + + + +/* interact (with only one process) - give user keyboard control + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +/* This file exists for deficient versions of UNIX that lack select, +poll, or some other multiplexing hook. Instead, this code uses two +processes per spawned process. One sends characters from the spawnee +to the spawner; a second send chars the other way. + +This will work on any UNIX system. The only sacrifice is that it +doesn't support multiple processes. Eventually, it should catch +SIGCHLD on dead processes and do the right thing. But it is pretty +gruesome to imagine so many processes to do all this. If you change +it successfully, please mail back the changes to me. - Don +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include "tcl.h" +#include "exp_prog.h" +#include "exp_command.h" /* for struct ExpState defs */ +#include "exp_event.h" + +/*ARGSUSED*/ +void +exp_arm_background_channelhandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_disarm_background_channelhandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_disarm_background_channelhandler_force(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_unblock_background_channelhandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_block_background_channelhandler(esPtr) +ExpState *esPtr; +{ +} + +/*ARGSUSED*/ +void +exp_event_disarm(fd) +int fd; +{ +} + +/* returns status, one of EOF, TIMEOUT, ERROR or DATA */ +/*ARGSUSED*/ +int +exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key) +Tcl_Interp *interp; +ExpState (*esPtrs)[]; +int n; /* # of esPtrs */ +ExpState **esPtrOut; /* 1st event master, not set if none */ +int timeout; /* seconds */ +int key; +{ + ExpState *esPtr; + + if (n > 1) { + exp_error(interp,"expect not compiled with multiprocess support"); + /* select a different INTERACT_TYPE in Makefile */ + return(TCL_ERROR); + } + + esPtr = *esPtrOut = esPtrs[0]; + + if (esPtr->key != key) { + esPtr->key = key; + esPtr->force_read = FALSE; + return(EXP_DATA_OLD); + } else if ((!esPtr->force_read) && (esPtr->size != 0)) { + return(EXP_DATA_OLD); + } + + return(EXP_DATA_NEW); +} + +/*ARGSUSED*/ +int +exp_get_next_event_info(interp,esPtr,ready_mask) +Tcl_Interp *interp; +ExpState *esPtr; +int ready_mask; +{ +} + +/* There is no portable way to do sub-second sleeps on such a system, so */ +/* do the next best thing (without a busy loop) and fake it: sleep the right */ +/* amount of time over the long run. Note that while "subtotal" isn't */ +/* reinitialized, it really doesn't matter for such a gross hack as random */ +/* scheduling pauses will easily introduce occasional one second delays. */ +int /* returns TCL_XXX */ +exp_dsleep(interp,sec) +Tcl_Interp *interp; +double sec; +{ + static double subtotal = 0; + int seconds; + + subtotal += sec; + if (subtotal < 1) return TCL_OK; + seconds = subtotal; + subtotal -= seconds; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(rc); + } + sleep(seconds); + return TCL_OK; +} + +#if 0 +/* There is no portable way to do sub-second sleeps on such a system, so */ +/* do the next best thing (without a busy loop) and fake it: sleep the right */ +/* amount of time over the long run. Note that while "subtotal" isn't */ +/* reinitialized, it really doesn't matter for such a gross hack as random */ +/* scheduling pauses will easily introduce occasional one second delays. */ +int /* returns TCL_XXX */ +exp_usleep(interp,usec) +Tcl_Interp *interp; +long usec; /* microseconds */ +{ + static subtotal = 0; + int seconds; + + subtotal += usec; + if (subtotal < 1000000) return TCL_OK; + seconds = subtotal/1000000; + subtotal = subtotal%1000000; + restart: + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); + } + sleep(seconds); + return TCL_OK; +} +#endif /*0*/ + +/* set things up for later calls to event handler */ +void +exp_init_event() +{ + exp_event_exit = 0; +} + +#endif /* WHOLE FILE! */ diff --git a/exp_strf.c b/exp_strf.c new file mode 100644 index 0000000..dc96073 --- /dev/null +++ b/exp_strf.c @@ -0,0 +1,618 @@ +/* exp_strp.c - functions for exp_timestamp */ +/* + * strftime.c + * + * Public-domain implementation of ANSI C library routine. + * + * It's written in old-style C for maximal portability. + * However, since I'm used to prototypes, I've included them too. + * + * If you want stuff in the System V ascftime routine, add the SYSV_EXT define. + * For extensions from SunOS, add SUNOS_EXT. + * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE. + * For VMS dates, add VMS_EXT. + * For complete POSIX semantics, add POSIX_SEMANTICS. + * + * The code for %c, %x, and %X now follows the 1003.2 specification for + * the POSIX locale. + * This version ignores LOCALE information. + * It also doesn't worry about multi-byte characters. + * So there. + * + * This file is also shipped with GAWK (GNU Awk), gawk specific bits of + * code are included if GAWK is defined. + * + * Arnold Robbins <arnold@skeeve.atl.ga.us> + * January, February, March, 1991 + * Updated March, April 1992 + * Updated April, 1993 + * Updated February, 1994 + * Updated May, 1994 + * Updated January 1995 + * Updated September 1995 + * + * Fixes from ado@elsie.nci.nih.gov + * February 1991, May 1992 + * Fixes from Tor Lillqvist tml@tik.vtt.fi + * May, 1993 + * Further fixes from ado@elsie.nci.nih.gov + * February 1994 + * %z code from chip@chinacat.unicom.com + * Applied September 1995 + * + * + * Modified by Don Libes for Expect, 10/93 and 12/95. + * Forced POSIX semantics. + * Replaced inline/min/max stuff with a single range function. + * Removed tzset stuff. + * Commented out tzname stuff. + * + * According to Arnold, the current version of this code can ftp'd from + * ftp.mathcs.emory.edu:/pub/arnold/strftime.shar.gz + * + */ + +#include "expect_cf.h" +#include "tcl.h" + +#include <stdio.h> +#include <ctype.h> +#include "string.h" + +/* according to Karl Vogel, time.h is insufficient on Pyramid */ +/* following is recommended by autoconf */ + +#ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + + + +#include <sys/types.h> + +#define SYSV_EXT 1 /* stuff in System V ascftime routine */ +#define POSIX2_DATE 1 /* stuff in Posix 1003.2 date command */ + +#if defined(POSIX2_DATE) && ! defined(SYSV_EXT) +#define SYSV_EXT 1 +#endif + +#if defined(POSIX2_DATE) +#define adddecl(stuff) stuff +#else +#define adddecl(stuff) +#endif + +#ifndef __STDC__ +#define const + +extern char *getenv(); +static int weeknumber(); +adddecl(static int iso8601wknum();) +#else + +#ifndef strchr +extern char *strchr(const char *str, int ch); +#endif + +extern char *getenv(const char *v); + +static int weeknumber(const struct tm *timeptr, int firstweekday); +adddecl(static int iso8601wknum(const struct tm *timeptr);) +#endif + +/* attempt to use strftime to compute timezone, else fallback to */ +/* less portable ways */ +#if !defined(HAVE_STRFTIME) +# if defined(HAVE_SV_TIMEZONE) +extern char *tzname[2]; +extern int daylight; +# else +# if defined(HAVE_TIMEZONE) + +char * +zone_name (tp) +struct tm *tp; +{ + char *timezone (); + struct timeval tv; + struct timezone tz; + + gettimeofday (&tv, &tz); + + return timezone (tz.tz_minuteswest, tp->tm_isdst); +} + +# endif /* HAVE_TIMEZONE */ +# endif /* HAVE_SV_TIMEZONE */ +#endif /* HAVE_STRFTIME */ + +static int +range(low,item,hi) +int low, item, hi; +{ + if (item < low) return low; + if (item > hi) return hi; + return item; +} + +/* strftime --- produce formatted time */ + +void +/*size_t*/ +#ifndef __STDC__ +exp_strftime(/*s,*/ format, timeptr, dstring) +/*char *s;*/ +char *format; +const struct tm *timeptr; +Tcl_DString *dstring; +#else +/*exp_strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)*/ +exp_strftime(char *format, const struct tm *timeptr,Tcl_DString *dstring) +#endif +{ + int copied; /* used to suppress copying when called recursively */ + +#if 0 + char *endp = s + maxsize; + char *start = s; +#endif + char *percentptr; + + char tbuf[100]; + int i; + + /* various tables, useful in North America */ + static char *days_a[] = { + "Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat", + }; + static char *days_l[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", + }; + static char *months_a[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + static char *months_l[] = { + "January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December", + }; + static char *ampm[] = { "AM", "PM", }; + +/* for (; *format && s < endp - 1; format++) {*/ + for (; *format ; format++) { + tbuf[0] = '\0'; + copied = 0; /* has not been copied yet */ + percentptr = strchr(format,'%'); + if (percentptr == 0) { + Tcl_DStringAppend(dstring,format,-1); + goto out; + } else if (percentptr != format) { + Tcl_DStringAppend(dstring,format,percentptr - format); + format = percentptr; + } +#if 0 + if (*format != '%') { + *s++ = *format; + continue; + } +#endif + again: + switch (*++format) { + case '\0': + Tcl_DStringAppend(dstring,"%",1); +#if 0 + *s++ = '%'; +#endif + goto out; + + case '%': + Tcl_DStringAppend(dstring,"%",1); + copied = 1; + break; +#if 0 + *s++ = '%'; + continue; +#endif + + case 'a': /* abbreviated weekday name */ + if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) + strcpy(tbuf, "?"); + else + strcpy(tbuf, days_a[timeptr->tm_wday]); + break; + + case 'A': /* full weekday name */ + if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) + strcpy(tbuf, "?"); + else + strcpy(tbuf, days_l[timeptr->tm_wday]); + break; + +#ifdef SYSV_EXT + case 'h': /* abbreviated month name */ +#endif + case 'b': /* abbreviated month name */ + if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) + strcpy(tbuf, "?"); + else + strcpy(tbuf, months_a[timeptr->tm_mon]); + break; + + case 'B': /* full month name */ + if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) + strcpy(tbuf, "?"); + else + strcpy(tbuf, months_l[timeptr->tm_mon]); + break; + + case 'c': /* appropriate date and time representation */ + sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d", + days_a[range(0, timeptr->tm_wday, 6)], + months_a[range(0, timeptr->tm_mon, 11)], + range(1, timeptr->tm_mday, 31), + range(0, timeptr->tm_hour, 23), + range(0, timeptr->tm_min, 59), + range(0, timeptr->tm_sec, 61), + timeptr->tm_year + 1900); + break; + + case 'd': /* day of the month, 01 - 31 */ + i = range(1, timeptr->tm_mday, 31); + sprintf(tbuf, "%02d", i); + break; + + case 'H': /* hour, 24-hour clock, 00 - 23 */ + i = range(0, timeptr->tm_hour, 23); + sprintf(tbuf, "%02d", i); + break; + + case 'I': /* hour, 12-hour clock, 01 - 12 */ + i = range(0, timeptr->tm_hour, 23); + if (i == 0) + i = 12; + else if (i > 12) + i -= 12; + sprintf(tbuf, "%02d", i); + break; + + case 'j': /* day of the year, 001 - 366 */ + sprintf(tbuf, "%03d", timeptr->tm_yday + 1); + break; + + case 'm': /* month, 01 - 12 */ + i = range(0, timeptr->tm_mon, 11); + sprintf(tbuf, "%02d", i + 1); + break; + + case 'M': /* minute, 00 - 59 */ + i = range(0, timeptr->tm_min, 59); + sprintf(tbuf, "%02d", i); + break; + + case 'p': /* am or pm based on 12-hour clock */ + i = range(0, timeptr->tm_hour, 23); + if (i < 12) + strcpy(tbuf, ampm[0]); + else + strcpy(tbuf, ampm[1]); + break; + + case 'S': /* second, 00 - 61 */ + i = range(0, timeptr->tm_sec, 61); + sprintf(tbuf, "%02d", i); + break; + + case 'U': /* week of year, Sunday is first day of week */ + sprintf(tbuf, "%02d", weeknumber(timeptr, 0)); + break; + + case 'w': /* weekday, Sunday == 0, 0 - 6 */ + i = range(0, timeptr->tm_wday, 6); + sprintf(tbuf, "%d", i); + break; + + case 'W': /* week of year, Monday is first day of week */ + sprintf(tbuf, "%02d", weeknumber(timeptr, 1)); + break; + + case 'x': /* appropriate date representation */ + sprintf(tbuf, "%s %s %2d %d", + days_a[range(0, timeptr->tm_wday, 6)], + months_a[range(0, timeptr->tm_mon, 11)], + range(1, timeptr->tm_mday, 31), + timeptr->tm_year + 1900); + break; + + case 'X': /* appropriate time representation */ + sprintf(tbuf, "%02d:%02d:%02d", + range(0, timeptr->tm_hour, 23), + range(0, timeptr->tm_min, 59), + range(0, timeptr->tm_sec, 61)); + break; + + case 'y': /* year without a century, 00 - 99 */ + i = timeptr->tm_year % 100; + sprintf(tbuf, "%02d", i); + break; + + case 'Y': /* year with century */ + sprintf(tbuf, "%d", 1900 + timeptr->tm_year); + break; + + case 'Z': /* time zone name or abbrevation */ +#if defined(HAVE_STRFTIME) + strftime(tbuf,sizeof tbuf,"%Z",timeptr); +#else +# if defined(HAVE_SV_TIMEZONE) + i = 0; + if (daylight && timeptr->tm_isdst) + i = 1; + strcpy(tbuf, tzname[i]); +# else + strcpy(tbuf, zone_name (timeptr)); +# if defined(HAVE_TIMEZONE) +# endif /* HAVE_TIMEZONE */ + /* no timezone available */ + /* feel free to add others here */ +# endif /* HAVE_SV_TIMEZONE */ +#endif /* HAVE STRFTIME */ + break; + +#ifdef SYSV_EXT + case 'n': /* same as \n */ + tbuf[0] = '\n'; + tbuf[1] = '\0'; + break; + + case 't': /* same as \t */ + tbuf[0] = '\t'; + tbuf[1] = '\0'; + break; + + case 'D': /* date as %m/%d/%y */ + exp_strftime("%m/%d/%y", timeptr, dstring); + copied = 1; +/* exp_strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);*/ + break; + + case 'e': /* day of month, blank padded */ + sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31)); + break; + + case 'r': /* time as %I:%M:%S %p */ + exp_strftime("%I:%M:%S %p", timeptr, dstring); + copied = 1; +/* exp_strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);*/ + break; + + case 'R': /* time as %H:%M */ + exp_strftime("%H:%M", timeptr, dstring); + copied = 1; +/* exp_strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);*/ + break; + + case 'T': /* time as %H:%M:%S */ + exp_strftime("%H:%M:%S", timeptr, dstring); + copied = 1; +/* exp_strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);*/ + break; +#endif + +#ifdef POSIX2_DATE + case 'C': + sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100); + break; + + + case 'E': + case 'O': + /* POSIX locale extensions, ignored for now */ + goto again; + case 'V': /* week of year according ISO 8601 */ + sprintf(tbuf, "%02d", iso8601wknum(timeptr)); + break; + + case 'u': + /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */ + sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 : + timeptr->tm_wday); + break; +#endif /* POSIX2_DATE */ + default: + tbuf[0] = '%'; + tbuf[1] = *format; + tbuf[2] = '\0'; + break; + } + if (!copied) + Tcl_DStringAppend(dstring,tbuf,-1); +#if 0 + i = strlen(tbuf); + if (i) { + if (s + i < endp - 1) { + strcpy(s, tbuf); + s += i; + } else + return 0; +#endif + } +out:; +#if 0 + if (s < endp && *format == '\0') { + *s = '\0'; + return (s - start); + } else + return 0; +#endif +} + +/* isleap --- is a year a leap year? */ + +#ifndef __STDC__ +static int +isleap(year) +int year; +#else +static int +isleap(int year) +#endif +{ + return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); +} + +#ifdef POSIX2_DATE +/* iso8601wknum --- compute week number according to ISO 8601 */ + +#ifndef __STDC__ +static int +iso8601wknum(timeptr) +const struct tm *timeptr; +#else +static int +iso8601wknum(const struct tm *timeptr) +#endif +{ + /* + * From 1003.2: + * If the week (Monday to Sunday) containing January 1 + * has four or more days in the new year, then it is week 1; + * otherwise it is the highest numbered week of the previous + * (52 or 53) year, and the next week is week 1. + * + * ADR: This means if Jan 1 was Monday through Thursday, + * it was week 1, otherwise week 53. + * + * XPG4 erroneously included POSIX.2 rationale text in the + * main body of the standard. Thus it requires week 53. + */ + + int weeknum, jan1day; + + /* get week number, Monday as first day of the week */ + weeknum = weeknumber(timeptr, 1); + + /* + * With thanks and tip of the hatlo to tml@tik.vtt.fi + * + * What day of the week does January 1 fall on? + * We know that + * (timeptr->tm_yday - jan1.tm_yday) MOD 7 == + * (timeptr->tm_wday - jan1.tm_wday) MOD 7 + * and that + * jan1.tm_yday == 0 + * and that + * timeptr->tm_wday MOD 7 == timeptr->tm_wday + * from which it follows that. . . + */ + jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7); + if (jan1day < 0) + jan1day += 7; + + /* + * If Jan 1 was a Monday through Thursday, it was in + * week 1. Otherwise it was last year's highest week, which is + * this year's week 0. + * + * What does that mean? + * If Jan 1 was Monday, the week number is exactly right, it can + * never be 0. + * If it was Tuesday through Thursday, the weeknumber is one + * less than it should be, so we add one. + * Otherwise, Friday, Saturday or Sunday, the week number is + * OK, but if it is 0, it needs to be 52 or 53. + */ + switch (jan1day) { + case 1: /* Monday */ + break; + case 2: /* Tuesday */ + case 3: /* Wednesday */ + case 4: /* Thursday */ + weeknum++; + break; + case 5: /* Friday */ + case 6: /* Saturday */ + case 0: /* Sunday */ + if (weeknum == 0) { +#ifdef USE_BROKEN_XPG4 + /* XPG4 (as of March 1994) says 53 unconditionally */ + weeknum = 53; +#else + /* get week number of last week of last year */ + struct tm dec31ly; /* 12/31 last year */ + dec31ly = *timeptr; + dec31ly.tm_year--; + dec31ly.tm_mon = 11; + dec31ly.tm_mday = 31; + dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1; + dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900); + weeknum = iso8601wknum(& dec31ly); +#endif + } + break; + } + + if (timeptr->tm_mon == 11) { + /* + * The last week of the year + * can be in week 1 of next year. + * Sigh. + * + * This can only happen if + * M T W + * 29 30 31 + * 30 31 + * 31 + */ + int wday, mday; + + wday = timeptr->tm_wday; + mday = timeptr->tm_mday; + if ( (wday == 1 && (mday >= 29 && mday <= 31)) + || (wday == 2 && (mday == 30 || mday == 31)) + || (wday == 3 && mday == 31)) + weeknum = 1; + } + + return weeknum; +} +#endif + +/* weeknumber --- figure how many weeks into the year */ + +/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */ + +#ifndef __STDC__ +static int +weeknumber(timeptr, firstweekday) +const struct tm *timeptr; +int firstweekday; +#else +static int +weeknumber(const struct tm *timeptr, int firstweekday) +#endif +{ + int wday = timeptr->tm_wday; + int ret; + + if (firstweekday == 1) { + if (wday == 0) /* sunday */ + wday = 6; + else + wday--; + } + ret = ((timeptr->tm_yday + 7 - wday) / 7); + if (ret < 0) + ret = 0; + return ret; +} diff --git a/exp_trap.c b/exp_trap.c new file mode 100644 index 0000000..390e0e3 --- /dev/null +++ b/exp_trap.c @@ -0,0 +1,554 @@ +/* exp_trap.c - Expect's trap command + +Written by: Don Libes, NIST, 9/1/93 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" + +#include <stdio.h> +#include <signal.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#include "tcl.h" + +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" + +#ifdef TCL_DEBUGGER +#include "tcldbg.h" +#endif + +#define NO_SIG 0 + +static struct trap { + char *action; /* Tcl command to execute upon sig */ + /* Each is handled by the eval_trap_action */ + int mark; /* TRUE if signal has occurred */ + Tcl_Interp *interp; /* interp to use or 0 if we should use the */ + /* interpreter active at the time the sig */ + /* is processed */ + int code; /* return our new code instead of code */ + /* available when signal is processed */ + CONST char *name; /* name of signal */ + int reserved; /* if unavailable for trapping */ +} traps[NSIG]; + +int sigchld_count = 0; /* # of sigchlds caught but not yet processed */ + +static int eval_trap_action(); + +static int got_sig; /* this records the last signal received */ + /* it is only a hint and can be wiped out */ + /* by multiple signals, but it will always */ + /* be left with a valid signal that is */ + /* pending */ + +static Tcl_AsyncHandler async_handler; + +static CONST char * +signal_to_string(sig) +int sig; +{ + if (sig <= 0 || sig > NSIG) return("SIGNAL OUT OF RANGE"); + return(traps[sig].name); +} + +/* current sig being processed by user sig handler */ +static int current_sig = NO_SIG; + +int exp_nostack_dump = FALSE; /* TRUE if user has requested unrolling of */ + /* stack with no trace */ + + + +/*ARGSUSED*/ +static int +tophalf(clientData,interp,code) +ClientData clientData; +Tcl_Interp *interp; +int code; +{ + struct trap *trap; /* last trap processed */ + int rc; + int i; + Tcl_Interp *sig_interp; + + expDiagLog("sighandler: handling signal(%d)\r\n",got_sig); + + if (got_sig <= 0 || got_sig >= NSIG) { + expErrorLog("caught impossible signal %d\r\n",got_sig); + abort(); + } + + /* start to work on this sig. got_sig can now be overwritten */ + /* and it won't cause a problem */ + current_sig = got_sig; + trap = &traps[current_sig]; + + trap->mark = FALSE; + + /* decrement below looks dangerous */ + /* Don't we need to temporarily block bottomhalf? */ + if (current_sig == SIGCHLD) { + sigchld_count--; + expDiagLog("sigchld_count-- == %d\n",sigchld_count); + } + + if (!trap->action) { + /* In this one case, we let ourselves be called when no */ + /* signaler predefined, since we are calling explicitly */ + /* from another part of the program, and it is just simpler */ + if (current_sig == 0) return code; + expErrorLog("caught unexpected signal: %s (%d)\r\n", + signal_to_string(current_sig),current_sig); + abort(); + } + + if (trap->interp) { + /* if trap requested original interp, use it */ + sig_interp = trap->interp; + } else if (interp) { + /* else if another interp is available, use it */ + sig_interp = interp; + } else { + /* fall back to exp_interp */ + sig_interp = exp_interp; + } + + rc = eval_trap_action(sig_interp,current_sig,trap,code); + current_sig = NO_SIG; + + /* + * scan for more signals to process + */ + + /* first check for additional SIGCHLDs */ + if (sigchld_count) { + got_sig = SIGCHLD; + traps[SIGCHLD].mark = TRUE; + Tcl_AsyncMark(async_handler); + } else { + got_sig = -1; + for (i=1;i<NSIG;i++) { + if (traps[i].mark) { + got_sig = i; + Tcl_AsyncMark(async_handler); + break; + } + } + } + return rc; +} + +#ifdef REARM_SIG +int sigchld_sleep; +static int rearm_sigchld = FALSE; /* TRUE if sigchld needs to be */ + /* rearmed (i.e., because it has */ + /* just gone off) */ +static int rearming_sigchld = FALSE; +#endif + +/* called upon receipt of a user-declared signal */ +static void +bottomhalf(sig) +int sig; +{ +#ifdef REARM_SIG + /* + * tiny window of death if same signal should arrive here + * before we've reinstalled it + */ + + /* In SV, sigchld must be rearmed after wait to avoid recursion */ + if (sig != SIGCHLD) { + signal(sig,bottomhalf); + } else { + /* request rearm */ + rearm_sigchld = TRUE; + if (rearming_sigchld) sigchld_sleep = TRUE; + } +#endif + + traps[sig].mark = TRUE; + got_sig = sig; /* just a hint - can be wiped out by another */ + Tcl_AsyncMark(async_handler); + + /* if we are called while this particular async is being processed */ + /* original async_proc will turn off "mark" so that when async_proc */ + /* is recalled, it will see that nothing was left to do */ + + /* In case of SIGCHLD though, we must recall it as many times as + * we have received it. + */ + if (sig == SIGCHLD) { + sigchld_count++; + } +#if 0 + /* if we are doing an i_read, restart it */ +#ifdef HAVE_SIGLONGJMP + if (env_valid && (sig != 0)) siglongjmp(env,2); +#else + if (env_valid && (sig != 0)) longjmp(env,2); +#endif /* HAVE_SIGLONGJMP */ +#endif /* 0 */ +} + +/*ARGSUSED*/ +void +exp_rearm_sigchld(interp) +Tcl_Interp *interp; +{ +#ifdef REARM_SIG + if (rearm_sigchld) { + rearm_sigchld = FALSE; + rearming_sigchld = TRUE; + signal(SIGCHLD,bottomhalf); + } + + rearming_sigchld = FALSE; + + /* if the rearming immediately caused another SIGCHLD, slow down */ + /* It's probably one of Tcl's intermediary pipeline processes that */ + /* Tcl hasn't caught up with yet. */ + if (sigchld_sleep) { + exp_dsleep(interp,0.2); + sigchld_sleep = FALSE; + } +#endif +} + + +void +exp_init_trap() +{ + int i; + + for (i=1;i<NSIG;i++) { + traps[i].name = Tcl_SignalId(i); + traps[i].action = 0; + traps[i].reserved = FALSE; + } + + /* + * fix up any special cases + */ + +#if defined(SIGCLD) + /* Tcl names it SIGCLD, not good for portable scripts */ + traps[SIGCLD].name = "SIGCHLD"; +#endif +#if defined(SIGALRM) + traps[SIGALRM].reserved = TRUE; +#endif +#if defined(SIGKILL) + traps[SIGKILL].reserved = TRUE; +#endif +#if defined(SIGSTOP) + traps[SIGSTOP].reserved = TRUE; +#endif + + async_handler = Tcl_AsyncCreate(tophalf,(ClientData)0); + +} + +/* given signal index or name as string, */ +/* returns signal index or -1 if bad arg */ +int +exp_string_to_signal(interp,s) +Tcl_Interp *interp; +char *s; +{ + int sig; + CONST char *name; + + /* try interpreting as an integer */ + if (1 == sscanf(s,"%d",&sig)) { + if (sig > 0 && sig < NSIG) return sig; + } else { + /* try interpreting as a string */ + for (sig=1;sig<NSIG;sig++) { + name = traps[sig].name; + if (streq(s,name) || streq(s,name+3)) return(sig); + } + } + + exp_error(interp,"invalid signal %s",s); + + return -1; +} + +/*ARGSUSED*/ +int +Exp_TrapObjCmd(clientData, interp, objc, objv) +ClientData clientData; +Tcl_Interp *interp; +int objc; +Tcl_Obj *CONST objv[]; +{ + char *action = 0; + int n; /* number of signals in list */ + Tcl_Obj **list; /* list of signals */ + char *arg; + int len; /* length of action */ + int i; + int show_name = FALSE; /* if user asked for current sig by name */ + int show_number = FALSE;/* if user asked for current sig by number */ + int show_max = FALSE; /* if user asked for NSIG-1 */ + int rc = TCL_OK; + int new_code = FALSE; /* if action result should overwrite orig */ + Tcl_Interp *new_interp = interp;/* interp in which to evaluate */ + /* action when signal occurs */ + + objc--; objv++; + + while (objc) { + arg = Tcl_GetString(*objv); + + if (streq(arg,"-code")) { + objc--; objv++; + new_code = TRUE; + } else if (streq(arg,"-interp")) { + objc--; objv++; + new_interp = 0; + } else if (streq(arg,"-name")) { + objc--; objv++; + show_name = TRUE; + } else if (streq(arg,"-number")) { + objc--; objv++; + show_number = TRUE; + } else if (streq(arg,"-max")) { + objc--; objv++; + show_max = TRUE; + } else break; + } + + if (show_name || show_number || show_max) { + if (objc > 0) goto usage_error; + if (show_max) { + Tcl_SetObjResult(interp,Tcl_NewIntObj(NSIG-1)); + } + + if (current_sig == NO_SIG) { + Tcl_SetResult(interp,"no signal in progress",TCL_STATIC); + return TCL_ERROR; + } + if (show_name) { + /* skip over "SIG" */ + /* TIP 27: Casting away the CONST should be ok because of TCL_STATIC + */ + Tcl_SetResult(interp,(char*)signal_to_string(current_sig) + 3,TCL_STATIC); + } else { + Tcl_SetObjResult(interp,Tcl_NewIntObj(current_sig)); + } + return TCL_OK; + } + + if (objc == 0 || objc > 2) goto usage_error; + + if (objc == 1) { + int sig = exp_string_to_signal(interp,arg); + if (sig == -1) return TCL_ERROR; + + if (traps[sig].action) { + Tcl_SetResult(interp,traps[sig].action,TCL_STATIC); + } else { + Tcl_SetResult(interp,"SIG_DFL",TCL_STATIC); + } + return TCL_OK; + } + + action = arg; + + /* objv[1] is the list of signals - crack it open */ + if (TCL_OK != Tcl_ListObjGetElements(interp,objv[1],&n,&list)) { + return TCL_ERROR; + } + + for (i=0;i<n;i++) { + char *s; + int sig; + + s = Tcl_GetString(list[i]); + + sig = exp_string_to_signal(interp,s); + if (sig == -1) { + rc = TCL_ERROR; + break; + } + + if (traps[sig].reserved) { + exp_error(interp,"cannot trap %s",signal_to_string(sig)); + rc = TCL_ERROR; + break; + } + + expDiagLog("trap: setting up signal %d (\"%s\")\r\n",sig,s); + if (traps[sig].action) ckfree(traps[sig].action); + if (streq(action,"SIG_DFL")) { + /* should've been free'd by now if nec. */ + traps[sig].action = 0; + signal(sig,SIG_DFL); +#ifdef REARM_SIG + if (sig == SIGCHLD) + rearm_sigchld = FALSE; +#endif /*REARM_SIG*/ + } else { + len = 1 + strlen(action); + traps[sig].action = ckalloc(len); + memcpy(traps[sig].action,action,len); + traps[sig].interp = new_interp; + traps[sig].code = new_code; + if (streq(action,"SIG_IGN")) { + signal(sig,SIG_IGN); + } else signal(sig,bottomhalf); + } + } + /* It is no longer necessary to free the split list since it */ + /* is still owned by Tcl, yes? */ + /* ckfree((char *)list); */ + return(rc); + usage_error: + exp_error(interp,"usage: trap [command or SIG_DFL or SIG_IGN] {list of signals}"); + return TCL_ERROR; +} + +/* called by tophalf() to process the given signal */ +static int +eval_trap_action(interp,sig,trap,oldcode) +Tcl_Interp *interp; +int sig; +struct trap *trap; +int oldcode; +{ + int code_flag; + int newcode; + Tcl_Obj *eip; /* errorInfo */ + Tcl_Obj *ecp; /* errorCode */ + Tcl_Obj *irp; /* interp's result */ + + expDiagLogU("async event handler: Tcl_Eval("); + expDiagLogU(trap->action); + expDiagLogU(")\r\n"); + + /* save to prevent user from redefining trap->code while trap */ + /* is executing */ + code_flag = trap->code; + + if (!code_flag) { + /* + * save return values + */ + + eip = Tcl_GetVar2Ex(interp,"errorInfo","",TCL_GLOBAL_ONLY); + if (eip) eip = Tcl_DuplicateObj(eip); + ecp = Tcl_GetVar2Ex(interp,"errorCode","",TCL_GLOBAL_ONLY); + if (ecp) ecp = Tcl_DuplicateObj(ecp); + irp = Tcl_GetObjResult(interp); + if (irp) irp = Tcl_DuplicateObj(irp); + } + + newcode = Tcl_GlobalEval(interp,trap->action); + + /* + * if new code is to be ignored (usual case - see "else" below) + * allow only OK/RETURN from trap, otherwise complain + */ + + if (code_flag) { + expDiagLog("return value = %d for trap %s, action ",newcode,signal_to_string(sig)); + expDiagLogU(trap->action); + expDiagLogU("\r\n"); + if (0 != strcmp(Tcl_GetStringResult(interp),"")) { + + /* + * Check errorinfo and see if it contains -nostack. + * This shouldn't be necessary, but John changed the + * top level interp so that it distorts arbitrary + * return values into TCL_ERROR, so by the time we + * get back, we'll have lost the value of errorInfo + */ + + eip = Tcl_GetVar2Ex(interp,"errorInfo","",TCL_GLOBAL_ONLY); + if (eip) { + exp_nostack_dump = (0 == strncmp("-nostack",Tcl_GetString(eip),8)); + } + } + } else if (newcode != TCL_OK && newcode != TCL_RETURN) { + if (newcode != TCL_ERROR) { + exp_error(interp,"return value = %d for trap %s, action %s\r\n",newcode,signal_to_string(sig),trap->action); + } + Tcl_BackgroundError(interp); + } + + if (!code_flag) { + /* + * restore values + */ + Tcl_ResetResult(interp); /* turns off Tcl's internal */ + /* flags: ERR_IN_PROGRESS, ERROR_CODE_SET */ + /* This also wipes clean errorInfo/Code/result which is why */ + /* all the calls to Tcl_Dup earlier */ + + if (eip) { + /* odd that Tcl doesn't have a call that does all this at once */ + int len; + char *s = Tcl_GetStringFromObj(eip,&len); + Tcl_AddObjErrorInfo(interp,s,len); + Tcl_DecrRefCount(eip); + /* we never incr'd it, but the code allows this */ + } else { + Tcl_UnsetVar(interp,"errorInfo",0); + } + + /* restore errorCode. Note that Tcl_AddErrorInfo (above) */ + /* resets it to NONE. If the previous value is NONE, it's */ + /* important to avoid calling Tcl_SetErrorCode since this */ + /* with cause Tcl to set its internal ERROR_CODE_SET flag. */ + if (ecp) { + if (!streq("NONE",Tcl_GetString(ecp))) + Tcl_SetErrorCode(interp,ecp); + /* we're just passing on the errorcode obj */ + /* presumably, Tcl will incr ref count */ + } else { + Tcl_UnsetVar(interp,"errorCode",0); + } + + newcode = oldcode; + + /* note that since newcode gets overwritten here by old code */ + /* it is possible to return in the middle of a trap by using */ + /* "return" (or "continue" for that matter)! */ + } + return newcode; +} + +static struct exp_cmd_data +cmd_data[] = { +{"trap", Exp_TrapObjCmd, 0, (ClientData)EXP_SPAWN_ID_BAD, 0}, +{0}}; + +void +exp_init_trap_cmds(interp) +Tcl_Interp *interp; +{ + exp_create_commands(interp,cmd_data); +} + diff --git a/exp_tstamp.h b/exp_tstamp.h new file mode 100644 index 0000000..5cadc7d --- /dev/null +++ b/exp_tstamp.h @@ -0,0 +1,2 @@ +EXTERN void exp_timestamp _ANSI_ARGS_((Tcl_Interp *,time_t *, + char *)); diff --git a/exp_tty.c b/exp_tty.c new file mode 100644 index 0000000..3f22c90 --- /dev/null +++ b/exp_tty.c @@ -0,0 +1,811 @@ +/* exp_tty.c - tty support routines */ + +#include "expect_cf.h" +#include <stdio.h> +#include <signal.h> +#include "string.h" + +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif + +#include <sys/stat.h> + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#include "tcl.h" +#include "exp_prog.h" +#include "exp_rename.h" +#include "exp_tty_in.h" +#include "exp_command.h" +#include "exp_log.h" +#include "exp_win.h" + +static int is_raw = FALSE; +static int is_noecho = FALSE; + +int exp_ioctled_devtty = FALSE; +int exp_stdin_is_tty; +int exp_stdout_is_tty; + +/*static*/ extern exp_tty exp_tty_current, exp_tty_cooked; +#define tty_current exp_tty_current +#define tty_cooked exp_tty_cooked + +int +exp_israw(void) +{ + return is_raw; +} + +int +exp_isecho(void) +{ + return !is_noecho; +} + +/* if set == 1, set it to raw, else unset it */ +void +exp_tty_raw(int set) +{ + if (set == 1) { + is_raw = TRUE; +#if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO) /* had POSIX too */ + tty_current.c_iflag = 0; + tty_current.c_oflag = 0; + tty_current.c_lflag &= ECHO; /* disable everything but echo */ + tty_current.c_cc[VMIN] = 1; + tty_current.c_cc[VTIME] = 0; + } else { + tty_current.c_iflag = tty_cooked.c_iflag; + tty_current.c_oflag = tty_cooked.c_oflag; +/* tty_current.c_lflag = tty_cooked.c_lflag;*/ +/* attempt 2 tty_current.c_lflag = tty_cooked.c_lflag & ~ECHO;*/ + /* retain current echo setting */ + tty_current.c_lflag = (tty_cooked.c_lflag & ~ECHO) | (tty_current.c_lflag & ECHO); + tty_current.c_cc[VMIN] = tty_cooked.c_cc[VMIN]; + tty_current.c_cc[VTIME] = tty_cooked.c_cc[VTIME]; +#else +# if defined(HAVE_SGTTYB) + tty_current.sg_flags |= RAW; + } else { + tty_current.sg_flags = tty_cooked.sg_flags; +# endif +#endif + is_raw = FALSE; + } +} + +void +exp_tty_echo(int set) +{ + if (set == 1) { + is_noecho = FALSE; +#if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO) /* had POSIX too */ + tty_current.c_lflag |= ECHO; + } else { + tty_current.c_lflag &= ~ECHO; +#else + tty_current.sg_flags |= ECHO; + } else { + tty_current.sg_flags &= ~ECHO; +#endif + is_noecho = TRUE; + } +} + +int +exp_tty_set_simple(exp_tty *tty) +{ +#ifdef HAVE_TCSETATTR + return(tcsetattr(exp_dev_tty, TCSADRAIN,tty)); +#else + return(ioctl (exp_dev_tty, TCSETSW ,tty)); +#endif +} + +int +exp_tty_get_simple(exp_tty *tty) +{ +#ifdef HAVE_TCSETATTR + return(tcgetattr(exp_dev_tty, tty)); +#else + return(ioctl (exp_dev_tty, TCGETS, tty)); +#endif +} + +/* returns 0 if nothing changed */ +/* if something changed, the out parameters are changed as well */ +int +exp_tty_raw_noecho( + Tcl_Interp *interp, + exp_tty *tty_old, + int *was_raw, + int *was_echo) +{ + if (exp_disconnected) return(0); + if (is_raw && is_noecho) return(0); + if (exp_dev_tty == -1) return(0); + + *tty_old = tty_current; /* save old parameters */ + *was_raw = is_raw; + *was_echo = !is_noecho; + expDiagLog("tty_raw_noecho: was raw = %d echo = %d\r\n",is_raw,!is_noecho); + + exp_tty_raw(1); + exp_tty_echo(-1); + + if (exp_tty_set_simple(&tty_current) == -1) { + expErrorLog("ioctl(raw): %s\r\n",Tcl_PosixError(interp)); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + + exp_ioctled_devtty = TRUE; + return(1); +} + +/* returns 0 if nothing changed */ +/* if something changed, the out parameters are changed as well */ +int +exp_tty_cooked_echo( + Tcl_Interp *interp, + exp_tty *tty_old, + int *was_raw, + int *was_echo) +{ + if (exp_disconnected) return(0); + if (!is_raw && !is_noecho) return(0); + if (exp_dev_tty == -1) return(0); + + *tty_old = tty_current; /* save old parameters */ + *was_raw = is_raw; + *was_echo = !is_noecho; + expDiagLog("tty_cooked_echo: was raw = %d echo = %d\r\n",is_raw,!is_noecho); + + exp_tty_raw(-1); + exp_tty_echo(1); + + if (exp_tty_set_simple(&tty_current) == -1) { + expErrorLog("ioctl(noraw): %s\r\n",Tcl_PosixError(interp)); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + exp_ioctled_devtty = TRUE; + + return(1); +} + +void +exp_tty_set( + Tcl_Interp *interp, + exp_tty *tty, + int raw, + int echo) +{ + if (exp_tty_set_simple(tty) == -1) { + expErrorLog("ioctl(set): %s\r\n",Tcl_PosixError(interp)); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + is_raw = raw; + is_noecho = !echo; + tty_current = *tty; + expDiagLog("tty_set: raw = %d, echo = %d\r\n",is_raw,!is_noecho); + exp_ioctled_devtty = TRUE; +} + +#if 0 +/* avoids scoping problems */ +void +exp_update_cooked_from_current() { + tty_cooked = tty_current; +} + +int +exp_update_real_tty_from_current() { + return(exp_tty_set_simple(&tty_current)); +} + +int +exp_update_current_from_real_tty() { + return(exp_tty_get_simple(&tty_current)); +} +#endif + +void +exp_init_stdio() +{ + exp_stdin_is_tty = isatty(0); + exp_stdout_is_tty = isatty(1); + + setbuf(stdout,(char *)0); /* unbuffer stdout */ +} + +/*ARGSUSED*/ +void +exp_tty_break( + Tcl_Interp *interp, + int fd) +{ +#ifdef POSIX + tcsendbreak(fd,0); +#else +# ifdef TIOCSBRK + ioctl(fd,TIOCSBRK,0); + exp_dsleep(interp,0.25); /* sleep for at least a quarter of a second */ + ioctl(fd,TIOCCBRK,0); +# else + /* dunno how to do this - ignore */ +# endif +#endif +} + +/* take strings with newlines and insert carriage-returns. This allows user */ +/* to write send_user strings without always putting in \r. */ +/* If len == 0, use strlen to compute it */ +/* NB: if terminal is not in raw mode, nothing is done. */ +char * +exp_cook( + char *s, + int *len) /* current and new length of s */ +{ + static int destlen = 0; + static char *dest = 0; + char *d; /* ptr into dest */ + unsigned int need; + + if (s == 0) return("<null>"); + + if (!is_raw) return(s); + + /* worst case is every character takes 2 to represent */ + need = 1 + 2*(len?*len:strlen(s)); + if (need > destlen) { + if (dest) ckfree(dest); + dest = ckalloc(need); + destlen = need; + } + + for (d = dest;*s;s++) { + if (*s == '\n') { + *d++ = '\r'; + *d++ = '\n'; + } else { + *d++ = *s; + } + } + *d = '\0'; + if (len) *len = d-dest; + return(dest); +} + +static int /* returns TCL_whatever */ +exec_stty( + Tcl_Interp *interp, + int argc, + char **argv, + int devtty) /* if true, redirect to /dev/tty */ +{ + int i; + int rc; + + Tcl_Obj *cmdObj = Tcl_NewStringObj("",0); + Tcl_IncrRefCount(cmdObj); + + Tcl_AppendStringsToObj(cmdObj,"exec ",(char *)0); + Tcl_AppendStringsToObj(cmdObj,STTY_BIN,(char *)0); + for (i=1;i<argc;i++) { + Tcl_AppendStringsToObj(cmdObj," ",argv[i],(char *)0); + } + if (devtty) Tcl_AppendStringsToObj(cmdObj, +#ifdef STTY_READS_STDOUT + " >/dev/tty", +#else + " </dev/tty", +#endif + (char *)0); + + Tcl_ResetResult(interp); + + /* + * normally, I wouldn't set one of Tcl's own variables, but in this + * case, I only want to see if Tcl resets it to non-NONE, and I don't + * know any other way of doing it + */ + + Tcl_SetVar(interp,"errorCode","NONE",0); + rc = Tcl_EvalObjEx(interp,cmdObj,TCL_EVAL_DIRECT); + + Tcl_DecrRefCount(cmdObj); + + /* if stty-reads-stdout, stty will fail since Exec */ + /* will detect the stderr. Only by examining errorCode */ + /* can we tell if a real error occurred. */ + +#ifdef STTY_READS_STDOUT + if (rc == TCL_ERROR) { + char *ec = Tcl_GetVar(interp,"errorCode",TCL_GLOBAL_ONLY); + if (ec && !streq(ec,"NONE")) return TCL_ERROR; + } +#endif + return TCL_OK; +} + +/*ARGSUSED*/ +static int +Exp_SttyCmd( + ClientData clientData, + Tcl_Interp *interp, + int argc, + char **argv) +{ + /* redirection symbol is not counted as a stty arg in terms */ + /* of recognition. */ + int saw_unknown_stty_arg = FALSE; + int saw_known_stty_arg = FALSE; + int no_args = TRUE; + + int rc = TCL_OK; + int cooked = FALSE; + int was_raw, was_echo; + + char **redirect; /* location of "<" */ + char *infile = 0; + int fd; /* (slave) fd of infile */ + int master = -1; /* master fd of infile */ + char **argv0 = argv; + + for (argv=argv0+1;*argv;argv++) { + if (argv[0][0] == '<') { + redirect = argv; + infile = *(argv+1); + if (!infile) { + expErrorLog("usage: < ttyname"); + return TCL_ERROR; + } + if (streq(infile,"/dev/tty")) { + infile = 0; + *argv = 0; + *(argv+1) = 0; + argc -= 2; + } else { + master = exp_trap_off(infile); + if (-1 == (fd = open(infile,2))) { + expErrorLog("couldn't open %s: %s", + infile,Tcl_PosixError(interp)); + return TCL_ERROR; + } + } + break; + } + } + + if (!infile) { /* work on /dev/tty */ + was_raw = exp_israw(); + was_echo = exp_isecho(); + + for (argv=argv0+1;*argv;argv++) { + if (streq(*argv,"raw") || + streq(*argv,"-cooked")) { + exp_tty_raw(1); + saw_known_stty_arg = TRUE; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else if (streq(*argv,"-raw") || + streq(*argv,"cooked")) { + cooked = TRUE; + exp_tty_raw(-1); + saw_known_stty_arg = TRUE; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else if (streq(*argv,"echo")) { + exp_tty_echo(1); + saw_known_stty_arg = TRUE; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else if (streq(*argv,"-echo")) { + exp_tty_echo(-1); + saw_known_stty_arg = TRUE; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else if (streq(*argv,"rows")) { + if (*(argv+1)) { + exp_win_rows_set(*(argv+1)); + argv++; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else { + Tcl_SetResult (interp, exp_win_rows_get(), TCL_VOLATILE); + return TCL_OK; + } + } else if (streq(*argv,"columns")) { + if (*(argv+1)) { + exp_win_columns_set(*(argv+1)); + argv++; + no_args = FALSE; + exp_ioctled_devtty = TRUE; + } else { + Tcl_SetResult (interp, exp_win_columns_get(), TCL_VOLATILE); + return TCL_OK; + } + } else { + saw_unknown_stty_arg = TRUE; + } + } + /* if any unknown args, let real stty try */ + if (saw_unknown_stty_arg || no_args) { + if (saw_unknown_stty_arg) { + exp_ioctled_devtty = TRUE; + } + + /* let real stty try */ + rc = exec_stty(interp,argc,argv0,1); + + /* find out what weird options user asked for */ + if (exp_tty_get_simple(&tty_current) == -1) { + exp_error(interp,"stty: ioctl(get): %s\r\n",Tcl_PosixError(interp)); + rc = TCL_ERROR; + } + if (cooked) { + /* find out user's new defn of 'cooked' */ + tty_cooked = tty_current; + } + } else if (saw_known_stty_arg) { + if (exp_tty_set_simple(&tty_current) == -1) { + if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) { + expErrorLog("stty: impossible in this context\n"); + expErrorLog("are you disconnected or in a batch, at, or cron script?"); + /* user could've conceivably closed /dev/tty as well */ + } + exp_error(interp,"stty: ioctl(user): %s\r\n",Tcl_PosixError(interp)); + rc = TCL_ERROR; + } + } + + /* if no result, make a crude one */ + if (0 == strcmp(Tcl_GetString(Tcl_GetObjResult(interp)),"")) { + char buf [11]; + sprintf(buf,"%sraw %secho", + (was_raw?"":"-"), + (was_echo?"":"-")); + Tcl_SetResult (interp, buf, TCL_VOLATILE); + } + } else { + /* a different tty */ + + /* temporarily zap redirect */ + char *redirect_save = *redirect; + *redirect = 0; + + for (argv=argv0+1;*argv;argv++) { + if (streq(*argv,"rows")) { + if (*(argv+1)) { + exp_win2_rows_set(fd,*(argv+1)); + argv++; + no_args = FALSE; + } else { + Tcl_SetResult (interp, exp_win2_rows_get(fd), TCL_VOLATILE); + goto done; + } + } else if (streq(*argv,"columns")) { + if (*(argv+1)) { + exp_win2_columns_set(fd,*(argv+1)); + argv++; + no_args = FALSE; + } else { + Tcl_SetResult (interp, exp_win2_columns_get(fd), TCL_VOLATILE); + goto done; + } + } else if (streq(*argv,"<")) { + break; + } else { + saw_unknown_stty_arg = TRUE; + break; + } + } + + /* restore redirect */ + *redirect = redirect_save; + + close(fd); /* no more use for this, from now on */ + /* pass by name */ + + if (saw_unknown_stty_arg || no_args) { +#ifdef STTY_READS_STDOUT + /* switch "<" to ">" */ + char original_redirect_char = (*redirect)[0]; + (*redirect)[0] = '>'; + /* stderr unredirected so we can get it directly! */ +#endif + rc = exec_stty(interp,argc,argv0,0); +#ifdef STTY_READS_STDOUT + /* restore redirect - don't know if necessary */ + (*redirect)[0] = original_redirect_char; +#endif + } + } + done: + exp_trap_on(master); + + return rc; +} + +/*ARGSUSED*/ +static int +Exp_SystemCmd( + ClientData clientData, + Tcl_Interp *interp, + int argc, + char **argv) +{ + int result = TCL_OK; + RETSIGTYPE (*old)(); /* save old sigalarm handler */ +#define MAX_ARGLIST 10240 + int i; + + WAIT_STATUS_TYPE waitStatus; + int systemStatus +; + int abnormalExit = FALSE; + char buf[MAX_ARGLIST]; + char *bufp = buf; + int total_len = 0, arg_len; + + int stty_args_recognized = TRUE; + int cmd_is_stty = FALSE; + int cooked = FALSE; + int was_raw, was_echo; + + if (argc == 1) return TCL_OK; + + if (streq(argv[1],"stty")) { + expDiagLogU("system stty is deprecated, use stty\r\n"); + + cmd_is_stty = TRUE; + was_raw = exp_israw(); + was_echo = exp_isecho(); + } + + if (argc > 2 && cmd_is_stty) { + exp_ioctled_devtty = TRUE; + + for (i=2;i<argc;i++) { + if (streq(argv[i],"raw") || + streq(argv[i],"-cooked")) { + exp_tty_raw(1); + } else if (streq(argv[i],"-raw") || + streq(argv[i],"cooked")) { + cooked = TRUE; + exp_tty_raw(-1); + } else if (streq(argv[i],"echo")) { + exp_tty_echo(1); + } else if (streq(argv[i],"-echo")) { + exp_tty_echo(-1); + } else stty_args_recognized = FALSE; + } + + /* if unknown args, fall thru and let real stty have a go */ + if (stty_args_recognized) { + if ( +#ifdef HAVE_TCSETATTR + tcsetattr(exp_dev_tty,TCSADRAIN, &tty_current) == -1 +#else + ioctl(exp_dev_tty, TCSETSW, &tty_current) == -1 +#endif + ) { + if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) { + expErrorLog("system stty: impossible in this context\n"); + expErrorLog("are you disconnected or in a batch, at, or cron script?"); + /* user could've conceivably closed /dev/tty as well */ + } + exp_error(interp,"system stty: ioctl(user): %s\r\n",Tcl_PosixError(interp)); + return(TCL_ERROR); + } + if (cmd_is_stty) { + char buf [11]; + sprintf(buf,"%sraw %secho", + (was_raw?"":"-"), + (was_echo?"":"-")); + Tcl_SetResult (interp, buf, TCL_VOLATILE); + } + return(TCL_OK); + } + } + + for (i = 1;i<argc;i++) { + total_len += (1 + (arg_len = strlen(argv[i]))); + if (total_len > MAX_ARGLIST) { + exp_error(interp,"args too long (>=%d chars)", + total_len); + return(TCL_ERROR); + } + memcpy(bufp,argv[i],arg_len); + bufp += arg_len; + /* no need to check bounds, we accted for it earlier */ + memcpy(bufp," ",1); + bufp += 1; + } + + *(bufp-1) = '\0'; + + old = signal(SIGCHLD, SIG_DFL); + systemStatus = system(buf); + signal(SIGCHLD, old); /* restore signal handler */ + expDiagLogU("system("); + expDiagLogU(buf); + expDiagLog(") = %d\r\n",i); + + if (systemStatus == -1) { + exp_error(interp,Tcl_PosixError(interp)); + return TCL_ERROR; + } + *(int *)&waitStatus = systemStatus; + + if (!stty_args_recognized) { + /* find out what weird options user asked for */ + if ( +#ifdef HAVE_TCSETATTR + tcgetattr(exp_dev_tty, &tty_current) == -1 +#else + ioctl(exp_dev_tty, TCGETS, &tty_current) == -1 +#endif + ) { + expErrorLog("ioctl(get): %s\r\n",Tcl_PosixError(interp)); + + /* SF #439042 -- Allow overide of "exit" by user / script + */ + { + char buffer [] = "exit 1"; + Tcl_Eval(interp, buffer); + } + } + if (cooked) { + /* find out user's new defn of 'cooked' */ + tty_cooked = tty_current; + } + } + + if (cmd_is_stty) { + char buf [11]; + sprintf(buf,"%sraw %secho", + (was_raw?"":"-"), + (was_echo?"":"-")); + Tcl_SetResult (interp, buf, TCL_VOLATILE); + } + +/* following macros stolen from Tcl's tclUnix.h file */ +/* we can't include the whole thing because it depends on other macros */ +/* that come out of Tcl's Makefile, sigh */ + +#if 0 + +#undef WIFEXITED +#ifndef WIFEXITED +# define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0) +#endif + +#undef WEXITSTATUS +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff) +#endif + +#undef WIFSIGNALED +#ifndef WIFSIGNALED +# define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff))) +#endif + +#undef WTERMSIG +#ifndef WTERMSIG +# define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f) +#endif + +#undef WIFSTOPPED +#ifndef WIFSTOPPED +# define WIFSTOPPED(stat) (((*((int *) &(stat))) & 0xff) == 0177) +#endif + +#undef WSTOPSIG +#ifndef WSTOPSIG +# define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff) +#endif + +#endif /* 0 */ + +/* stolen from Tcl. Again, this is embedded in another routine */ +/* (CleanupChildren in tclUnixAZ.c) that we can't use directly. */ + + if (!WIFEXITED(waitStatus) || (WEXITSTATUS(waitStatus) != 0)) { + char msg1[20], msg2[20]; + int pid = 0; /* fake a pid, since system() won't tell us */ + + result = TCL_ERROR; + sprintf(msg1, "%d", pid); + if (WIFEXITED(waitStatus)) { + sprintf(msg2, "%d", WEXITSTATUS(waitStatus)); + Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2, + (char *) NULL); + abnormalExit = TRUE; + } else if (WIFSIGNALED(waitStatus)) { + CONST char *p; + + p = Tcl_SignalMsg((int) (WTERMSIG(waitStatus))); + Tcl_SetErrorCode(interp, "CHILDKILLED", msg1, + Tcl_SignalId((int) (WTERMSIG(waitStatus))), p, + (char *) NULL); + Tcl_AppendResult(interp, "child killed: ", p, "\n", + (char *) NULL); + } else if (WIFSTOPPED(waitStatus)) { + CONST char *p; + + p = Tcl_SignalMsg((int) (WSTOPSIG(waitStatus))); + Tcl_SetErrorCode(interp, "CHILDSUSP", msg1, + Tcl_SignalId((int) (WSTOPSIG(waitStatus))), p, (char *) NULL); + Tcl_AppendResult(interp, "child suspended: ", p, "\n", + (char *) NULL); + } else { + Tcl_AppendResult(interp, + "child wait status didn't make sense\n", + (char *) NULL); + } + } + + if (abnormalExit && (Tcl_GetStringResult (interp)[0] == 0)) { + Tcl_AppendResult(interp, "child process exited abnormally", + (char *) NULL); + } + + return result; +} + +static struct exp_cmd_data +cmd_data[] = { +{"stty", exp_proc(Exp_SttyCmd), 0, 0}, +{"system", exp_proc(Exp_SystemCmd), 0, 0}, +{0}}; + +void +exp_init_tty_cmds(struct Tcl_Interp *interp) +{ + exp_create_commands(interp,cmd_data); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_tty.h b/exp_tty.h new file mode 100644 index 0000000..3013838 --- /dev/null +++ b/exp_tty.h @@ -0,0 +1,29 @@ +/* exp_tty.h - tty support definitions + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifndef __EXP_TTY_H__ +#define __EXP_TTY_H__ + +#include "expect_cf.h" + +extern int exp_dev_tty; +extern int exp_ioctled_devtty; +extern int exp_stdin_is_tty; +extern int exp_stdout_is_tty; + +void exp_tty_raw(int set); +void exp_tty_echo(int set); +void exp_tty_break(Tcl_Interp *interp, int fd); +int exp_tty_raw_noecho(Tcl_Interp *interp, exp_tty *tty_old, int *was_raw, int *was_echo); +int exp_israw(void); +int exp_isecho(void); + +void exp_tty_set(Tcl_Interp *interp, exp_tty *tty, int raw, int echo); +int exp_tty_set_simple(exp_tty *tty); +int exp_tty_get_simple(exp_tty *tty); + +#endif /* __EXP_TTY_H__ */ diff --git a/exp_tty_comm.c b/exp_tty_comm.c new file mode 100644 index 0000000..8b741a3 --- /dev/null +++ b/exp_tty_comm.c @@ -0,0 +1,37 @@ +/* exp_tty_comm.c - tty support routines common to both Expect program + and library */ + +#include "expect_cf.h" +#include <stdio.h> + +#include "tcl.h" +#include "exp_tty_in.h" +#include "exp_rename.h" +#include "expect_comm.h" +#include "exp_command.h" +#include "exp_log.h" + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +int exp_disconnected = FALSE; /* not disc. from controlling tty */ + +/*static*/ exp_tty exp_tty_current, exp_tty_cooked; +#define tty_current exp_tty_current +#define tty_cooked exp_tty_cooked + +void +exp_init_tty() +{ + extern exp_tty exp_tty_original; + + /* save original user tty-setting in 'cooked', just in case user */ + /* asks for it without earlier telling us what cooked means to them */ + tty_cooked = exp_tty_original; + + /* save our current idea of the terminal settings */ + tty_current = exp_tty_original; +} + diff --git a/exp_tty_in.h b/exp_tty_in.h new file mode 100644 index 0000000..d5f9a13 --- /dev/null +++ b/exp_tty_in.h @@ -0,0 +1,100 @@ +/* exp_tty_in.h - internal tty support definitions */ + +/* Definitions for handling termio inclusion are localized here */ +/* This file should be included only if direct access to tty structures are */ +/* required. This file is necessary to avoid mismatch between gcc's and */ +/* vendor's include files */ + +/* Written by Rob Savoye <rob@cygnus.com>. Mon Feb 22 11:16:53 RMT 1993 */ + +#ifndef __EXP_TTY_IN_H__ +#define __EXP_TTY_IN_H__ + +#include "expect_cf.h" + +#ifdef __MACHTEN__ +#include "sys/types.h" +#endif + +/* + * Set up some macros to isolate tty differences + */ + +/* On some hosts, termio is incomplete (broken) and sgtty is a better +choice. At the same time, termio has some definitions for modern +stuff like window sizes that sgtty lacks - that's why termio.h +is included even when we claim the basic style is sgtty +*/ + +/* test for pyramid may be unnecessary, but only Pyramid people have */ +/* complained - notably pclink@qus102.qld.npb.telecom.com.au (Rick) */ +#if defined(pyr) && defined(HAVE_TERMIO) && defined(HAVE_SGTTYB) +#undef HAVE_SGTTYB +#endif + +/* on ISC SVR3.2, termios is skeletal and termio is a better choice. */ +/* sgttyb must also be avoided because it redefines same things that */ +/* termio does */ +/* note that both SVR3.2 and AIX lacks TCGETS or TCGETA in termios.h */ +/* but SVR3.2 lacks both TCSETATTR and TCGETS/A */ +#if defined(HAVE_TERMIO) && defined(HAVE_TERMIOS) && !defined(HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H) && !defined(HAVE_TCSETATTR) +# undef HAVE_TERMIOS +# undef HAVE_SGTTYB +#endif + +#if defined(HAVE_TERMIO) && !defined(HAVE_TERMIOS) +# include <termio.h> +# undef POSIX +# define TERMINAL termio +# ifndef TCGETS +# define TCGETS TCGETA +# define TCSETS TCSETA +# define TCSETSW TCSETAW +# define TCSETSF TCSETAF +# endif +#endif + +#if defined(HAVE_SGTTYB) && !defined(HAVE_TERMIOS) +# undef HAVE_TERMIO +# undef POSIX +#ifndef TCGETS +# define TCGETS TIOCGETP +# define TCSETS TIOCSETP +#endif +#ifndef TCSETSW +# define TCSETSW TIOCSETN +#endif +# define TERMINAL sgttyb +# ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +# else +# include <fcntl.h> +# endif +# include <sgtty.h> +# include <sys/ioctl.h> +#endif + + +#if defined(HAVE_TERMIOS) +# undef HAVE_TERMIO +# undef HAVE_SGTTYB +# include <termios.h> +# define TERMINAL termios +# if !defined(TCGETS) || !defined(TCSETS) +# define TCGETS TCGETA +# define TCSETS TCSETA +# define TCSETSW TCSETAW +# define TCSETSF TCSETAF +# endif +#endif + +/* This section was written by: Don Libes, NIST, 2/6/90 */ + +typedef struct TERMINAL exp_tty; +extern exp_tty exp_tty_original; +extern exp_tty exp_tty_current; +extern exp_tty exp_tty_cooked; + +#include "exp_tty.h" + +#endif /* __EXP_TTY_IN_H__ */ diff --git a/exp_win.c b/exp_win.c new file mode 100644 index 0000000..97adbee --- /dev/null +++ b/exp_win.c @@ -0,0 +1,217 @@ +/* exp_win.c - window support + +Written by: Don Libes, NIST, 10/25/93 + +This file is in the public domain. However, the author and NIST +would appreciate credit if you use this file or parts of it. + +*/ + +#include "expect_cf.h" +#include "tcl.h" + +#ifdef NO_STDLIB_H +#include "../compat/stdlib.h" +#else +#include <stdlib.h> +#endif + +/* _IBCS2 required on some Intel platforms to allow the include files */ +/* to produce a definition for winsize. */ +#define _IBCS2 1 + +/* + * get everyone's window size definitions + * +note that this is tricky because (of course) everyone puts them in +different places. Worse, on some systems, some .h files conflict +and cannot both be included even though both exist. This is the +case, for example, on SunOS 4.1.3 using gcc where termios.h +conflicts with sys/ioctl.h + */ + +#ifdef HAVE_TERMIOS +# include <termios.h> +#else +# include <sys/ioctl.h> +#endif + +/* Sigh. On AIX 2.3, termios.h exists but does not define TIOCGWINSZ */ +/* Instead, it has to come from ioctl.h. However, As I said above, this */ +/* can't be cavalierly included on all machines, even when it exists. */ +#if defined(HAVE_TERMIOS) && !defined(HAVE_TIOCGWINSZ_IN_TERMIOS_H) +# include <sys/ioctl.h> +#endif + +/* SCO defines window size structure in PTEM and TIOCGWINSZ in termio.h */ +/* Sigh... */ +#if defined(HAVE_SYS_PTEM_H) +# include <sys/types.h> /* for stream.h's caddr_t */ +# include <sys/stream.h> /* for ptem.h's mblk_t */ +# include <sys/ptem.h> +#endif /* HAVE_SYS_PTEM_H */ + +#include "exp_tty_in.h" +#include "exp_win.h" + +#ifdef TIOCGWINSZ +typedef struct winsize exp_winsize; +#define columns ws_col +#define rows ws_row +#define EXP_WIN +#endif + +#if !defined(EXP_WIN) && defined(TIOCGSIZE) +typedef struct ttysize exp_winsize; +#define columns ts_cols +#define rows ts_lines +#define EXP_WIN +#endif + +#if !defined(EXP_WIN) +typedef struct { + int columns; + int rows; +} exp_winsize; +#endif + +static exp_winsize winsize = {0, 0}; +static exp_winsize win2size = {0, 0}; + +int exp_window_size_set(fd) +int fd; +{ +#ifdef TIOCSWINSZ + ioctl(fd,TIOCSWINSZ,&winsize); +#endif +#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ) + ioctl(fd,TIOCSSIZE,&winsize); +#endif +} + +int exp_window_size_get(fd) +int fd; +{ +#ifdef TIOCGWINSZ + ioctl(fd,TIOCGWINSZ,&winsize); +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) + ioctl(fd,TIOCGSIZE,&winsize); +#endif +#if !defined(EXP_WIN) + winsize.rows = 0; + winsize.columns = 0; +#endif +} + +void +exp_win_rows_set(rows) +char *rows; +{ + winsize.rows = atoi(rows); + exp_window_size_set(exp_dev_tty); +} + +char* +exp_win_rows_get() +{ + static char rows [20]; + exp_window_size_get(exp_dev_tty); + sprintf(rows,"%d",winsize.rows); + return rows; +} + +void +exp_win_columns_set(columns) +char *columns; +{ + winsize.columns = atoi(columns); + exp_window_size_set(exp_dev_tty); +} + +char* +exp_win_columns_get() +{ + static char columns [20]; + exp_window_size_get(exp_dev_tty); + sprintf(columns,"%d",winsize.columns); + return columns; +} + +/* + * separate copy of everything above - used for handling user stty requests + */ + +int exp_win2_size_set(fd) +int fd; +{ +#ifdef TIOCSWINSZ + ioctl(fd,TIOCSWINSZ,&win2size); +#endif +#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ) + ioctl(fd,TIOCSSIZE,&win2size); +#endif +} + +int exp_win2_size_get(fd) +int fd; +{ +#ifdef TIOCGWINSZ + ioctl(fd,TIOCGWINSZ,&win2size); +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) + ioctl(fd,TIOCGSIZE,&win2size); +#endif +} + +void +exp_win2_rows_set(fd,rows) +int fd; +char *rows; +{ + exp_win2_size_get(fd); + win2size.rows = atoi(rows); + exp_win2_size_set(fd); +} + +char* +exp_win2_rows_get(fd) +int fd; +{ + static char rows [20]; + exp_win2_size_get(fd); + sprintf(rows,"%d",win2size.rows); +#if !defined(EXP_WIN) + win2size.rows = 0; + win2size.columns = 0; +#endif + return rows; +} + +void +exp_win2_columns_set(fd,columns) +int fd; +char *columns; +{ + exp_win2_size_get(fd); + win2size.columns = atoi(columns); + exp_win2_size_set(fd); +} + +char* +exp_win2_columns_get(fd) +int fd; +{ + static char columns [20]; + exp_win2_size_get(fd); + sprintf(columns,"%d",win2size.columns); + return columns; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/exp_win.h b/exp_win.h new file mode 100644 index 0000000..8e77aea --- /dev/null +++ b/exp_win.h @@ -0,0 +1,22 @@ +/* exp_win.h - window support + +Written by: Don Libes, NIST, 10/25/93 + +This file is in the public domain. However, the author and NIST +would appreciate credit if you use this file or parts of it. +*/ + +#include <tcl.h> /* For _ANSI_ARGS_ */ + +int exp_window_size_set(); +int exp_window_size_get(); + +void exp_win_rows_set _ANSI_ARGS_ ((char* rows)); +char* exp_win_rows_get _ANSI_ARGS_ ((void)); +void exp_win_columns_set _ANSI_ARGS_ ((char* columns)); +char* exp_win_columns_get _ANSI_ARGS_ ((void)); + +void exp_win2_rows_set _ANSI_ARGS_ ((int fd, char* rows)); +char* exp_win2_rows_get _ANSI_ARGS_ ((int fd)); +void exp_win2_columns_set _ANSI_ARGS_ ((int fd, char* columns)); +char* exp_win2_columns_get _ANSI_ARGS_ ((int fd)); diff --git a/expect.c b/expect.c new file mode 100644 index 0000000..73f79c9 --- /dev/null +++ b/expect.c @@ -0,0 +1,3270 @@ +/* expect.c - expect commands + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include <sys/types.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <ctype.h> /* for isspace */ +#include <time.h> /* for time(3) */ + +#include "expect_cf.h" + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "tclInt.h" + +#include "string.h" + +#include "exp_rename.h" +#include "exp_prog.h" +#include "exp_command.h" +#include "exp_log.h" +#include "exp_event.h" +#include "exp_tty_in.h" +#include "exp_tstamp.h" /* this should disappear when interact */ + /* loses ref's to it */ +#ifdef TCL_DEBUGGER +#include "tcldbg.h" +#endif + +#include "retoglob.c" /* RE 2 GLOB translator C variant */ + +/* initial length of strings that we can guarantee patterns can match */ +int exp_default_match_max = 2000; +#define INIT_EXPECT_TIMEOUT_LIT "10" /* seconds */ +#define INIT_EXPECT_TIMEOUT 10 /* seconds */ +int exp_default_parity = TRUE; +int exp_default_rm_nulls = TRUE; +int exp_default_close_on_eof = TRUE; + +/* user variable names */ +#define EXPECT_TIMEOUT "timeout" +#define EXPECT_OUT "expect_out" + +extern int Exp_StringCaseMatch _ANSI_ARGS_((Tcl_UniChar *string, int strlen, + Tcl_UniChar *pattern,int plen, + int nocase,int *offset)); + +typedef struct ThreadSpecificData { + int timeout; +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +/* + * addr of these placeholders appear as clientData in ExpectCmd * when called + * as expect_user and expect_tty. It would be nicer * to invoked + * expDevttyGet() but C doesn't allow this in an array initialization, sigh. + */ +static ExpState StdinoutPlaceholder; +static ExpState DevttyPlaceholder; + +/* 1 ecase struct is reserved for each case in the expect command. Note that + * eof/timeout don't use any of theirs, but the algorithm is simpler this way. + */ + +struct ecase { /* case for expect command */ + struct exp_i *i_list; + Tcl_Obj *pat; /* original pattern spec */ + Tcl_Obj *body; /* ptr to body to be executed upon match */ + Tcl_Obj *gate; /* For PAT_RE, a gate-keeper glob pattern + * which is quicker to match and reduces + * the number of calls into expensive RE + * matching. Optional. + */ +#define PAT_EOF 1 +#define PAT_TIMEOUT 2 +#define PAT_DEFAULT 3 +#define PAT_FULLBUFFER 4 +#define PAT_GLOB 5 /* glob-style pattern list */ +#define PAT_RE 6 /* regular expression */ +#define PAT_EXACT 7 /* exact string */ +#define PAT_NULL 8 /* ASCII 0 */ +#define PAT_TYPES 9 /* used to size array of pattern type descriptions */ + int use; /* PAT_XXX */ + int simple_start; /* offset (chars) from start of buffer denoting where a + * glob or exact match begins */ + int transfer; /* if false, leave matched chars in input stream */ + int indices; /* if true, write indices */ + int iread; /* if true, reread indirects */ + int timestamp; /* if true, write timestamps */ +#define CASE_UNKNOWN 0 +#define CASE_NORM 1 +#define CASE_LOWER 2 + int Case; /* convert case before doing match? */ +}; + +/* descriptions of the pattern types, used for debugging */ +char *pattern_style[PAT_TYPES]; + +struct exp_cases_descriptor { + int count; + struct ecase **cases; +}; + +/* This describes an Expect command */ +static +struct exp_cmd_descriptor { + int cmdtype; /* bg, before, after */ + int duration; /* permanent or temporary */ + int timeout_specified_by_flag; /* if -timeout flag used */ + int timeout; /* timeout period if flag used */ + struct exp_cases_descriptor ecd; + struct exp_i *i_list; +} exp_cmds[4]; + +/* note that exp_cmds[FG] is just a fake, the real contents is stored in some + * dynamically-allocated variable. We use exp_cmds[FG] mostly as a well-known + * address and also as a convenience and so we allocate just a few of its + * fields that we need. + */ + +static void +exp_cmd_init( + struct exp_cmd_descriptor *cmd, + int cmdtype, + int duration) +{ + cmd->duration = duration; + cmd->cmdtype = cmdtype; + cmd->ecd.cases = 0; + cmd->ecd.count = 0; + cmd->i_list = 0; +} + +static int i_read_errno;/* place to save errno, if i_read() == -1, so it + doesn't get overwritten before we get to read it */ + +#ifdef SIMPLE_EVENT +static int alarm_fired; /* if alarm occurs */ +#endif + +void exp_background_channelhandlers_run_all(); + +/* exp_indirect_updateX is called by Tcl when an indirect variable is set */ +static char *exp_indirect_update1( /* 1-part Tcl variable names */ + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + struct exp_i *exp_i); +static char *exp_indirect_update2( /* 2-part Tcl variable names */ + ClientData clientData, + Tcl_Interp *interp, /* Interpreter containing variable. */ + char *name1, /* Name of variable. */ + char *name2, /* Second part of variable name. */ + int flags); /* Information about what happened. */ + +#ifdef SIMPLE_EVENT +/*ARGSUSED*/ +static RETSIGTYPE +sigalarm_handler(int n) /* unused, for compatibility with STDC */ +{ + alarm_fired = TRUE; +} +#endif /*SIMPLE_EVENT*/ + +/* free up everything in ecase */ +static void +free_ecase( + Tcl_Interp *interp, + struct ecase *ec, + int free_ilist) /* if we should free ilist */ +{ + if (ec->i_list->duration == EXP_PERMANENT) { + if (ec->pat) { Tcl_DecrRefCount(ec->pat); } + if (ec->gate) { Tcl_DecrRefCount(ec->gate); } + if (ec->body) { Tcl_DecrRefCount(ec->body); } + } + + if (free_ilist) { + ec->i_list->ecount--; + if (ec->i_list->ecount == 0) { + exp_free_i(interp,ec->i_list,exp_indirect_update2); + } + } + + ckfree((char *)ec); /* NEW */ +} + +/* free up any argv structures in the ecases */ +static void +free_ecases( + Tcl_Interp *interp, + struct exp_cmd_descriptor *eg, + int free_ilist) /* if true, free ilists */ +{ + int i; + + if (!eg->ecd.cases) return; + + for (i=0;i<eg->ecd.count;i++) { + free_ecase(interp,eg->ecd.cases[i],free_ilist); + } + ckfree((char *)eg->ecd.cases); + + eg->ecd.cases = 0; + eg->ecd.count = 0; +} + + +#if 0 +/* no standard defn for this, and some systems don't even have it, so avoid */ +/* the whole quagmire by calling it something else */ +static char *exp_strdup(char *s) +{ + char *news = ckalloc(strlen(s) + 1); + strcpy(news,s); + return(news); +} +#endif + +/* return TRUE if string appears to be a set of arguments + The intent of this test is to support the ability of commands to have + all their args braced as one. This conflicts with the possibility of + actually intending to have a single argument. + The bad case is in expect which can have a single argument with embedded + \n's although it's rare. Examples that this code should handle: + \n FALSE (pattern) + \n\n FALSE + \n \n \n FALSE + foo FALSE + foo\n FALSE + \nfoo\n TRUE (set of args) + \nfoo\nbar TRUE + + Current test is very cheap and almost always right :-) +*/ +int +exp_one_arg_braced(Tcl_Obj *objPtr) /* INTL */ +{ + int seen_nl = FALSE; + char *p = Tcl_GetString(objPtr); + + for (;*p;p++) { + if (*p == '\n') { + seen_nl = TRUE; + continue; + } + + if (!isspace(*p)) { /* INTL: ISO space */ + return(seen_nl); + } + } + return FALSE; +} + +/* called to execute a command of only one argument - a hack to commands */ +/* to be called with all args surrounded by an outer set of braces */ +/* Returns a list object containing the new set of arguments */ +/* Caller then has to either reinvoke itself, or better, simply replace + * its current argumnts */ +/*ARGSUSED*/ +Tcl_Obj* +exp_eval_with_one_arg( + ClientData clientData, + Tcl_Interp *interp, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tcl_Obj* res = Tcl_NewListObj (1,objv); + +#define NUM_STATIC_OBJS 20 + Tcl_Token *tokenPtr; + CONST char *p; + CONST char *next; + int rc; + int bytesLeft, numWords; + Tcl_Parse parse; + + /* + * Prepend the command name and the -nobrace switch so we can + * reinvoke without recursing. + */ + + Tcl_ListObjAppendElement (interp, res, Tcl_NewStringObj("-nobrace", -1)); + + p = Tcl_GetStringFromObj(objv[1], &bytesLeft); + + /* + * Treat the pattern/action block like a series of Tcl commands. + * For each command, parse the command words, perform substititions + * on each word, and add the words to an array of values. We don't + * actually evaluate the individual commands, just the substitutions. + */ + + do { + if (Tcl_ParseCommand(interp, p, bytesLeft, 0, &parse) + != TCL_OK) { + rc = TCL_ERROR; + goto done; + } + numWords = parse.numWords; + if (numWords > 0) { + /* + * Generate an array of objects for the words of the command. + */ + + /* + * For each word, perform substitutions then store the + * result in the objs array. + */ + + for (tokenPtr = parse.tokenPtr; numWords > 0; + numWords--, tokenPtr += (tokenPtr->numComponents + 1)) { + /* FUTURE: Save token information, do substitution later */ + + Tcl_Obj* w = Tcl_EvalTokens(interp, tokenPtr+1, + tokenPtr->numComponents); + /* w has refCount 1 here, if not NULL */ + if (w == NULL) { + Tcl_DecrRefCount (res); + res = NULL; + goto done; + + } + Tcl_ListObjAppendElement (interp, res, w); + Tcl_DecrRefCount (w); /* Local reference goes away */ + } + } + + /* + * Advance to the next command in the script. + */ + next = parse.commandStart + parse.commandSize; + bytesLeft -= next - p; + p = next; + Tcl_FreeParse(&parse); + } while (bytesLeft > 0); + + done: + return res; +} + +static void +ecase_clear(struct ecase *ec) +{ + ec->i_list = 0; + ec->pat = 0; + ec->body = 0; + ec->transfer = TRUE; + ec->simple_start = 0; + ec->indices = FALSE; + ec->iread = FALSE; + ec->timestamp = FALSE; + ec->Case = CASE_NORM; + ec->use = PAT_GLOB; + ec->gate = NULL; +} + +static struct ecase * +ecase_new(void) +{ + struct ecase *ec = (struct ecase *)ckalloc(sizeof(struct ecase)); + + ecase_clear(ec); + return ec; +} + +/* + +parse_expect_args parses the arguments to expect or its variants. +It normally returns TCL_OK, and returns TCL_ERROR for failure. +(It can't return i_list directly because there is no way to differentiate +between clearing, say, expect_before and signalling an error.) + +eg (expect_global) is initialized to reflect the arguments parsed +eg->ecd.cases is an array of ecases +eg->ecd.count is the # of ecases +eg->i_list is a linked list of exp_i's which represent the -i info + +Each exp_i is chained to the next so that they can be easily free'd if +necessary. Each exp_i has a reference count. If the -i is not used +(e.g., has no following patterns), the ref count will be 0. + +Each ecase points to an exp_i. Several ecases may point to the same exp_i. +Variables named by indirect exp_i's are read for the direct values. + +If called from a foreground expect and no patterns or -i are given, a +default exp_i is forced so that the command "expect" works right. + +The exp_i chain can be broken by the caller if desired. + +*/ + +static int +parse_expect_args( + Tcl_Interp *interp, + struct exp_cmd_descriptor *eg, + ExpState *default_esPtr, /* suggested ExpState if called as expect_user or _tty */ + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int i; + char *string; + struct ecase ec; /* temporary to collect args */ + + eg->timeout_specified_by_flag = FALSE; + + ecase_clear(&ec); + + /* Allocate an array to store the ecases. Force array even if 0 */ + /* cases. This will often be too large (i.e., if there are flags) */ + /* but won't affect anything. */ + + eg->ecd.cases = (struct ecase **)ckalloc(sizeof(struct ecase *) * (1+(objc/2))); + + eg->ecd.count = 0; + + for (i = 1;i<objc;i++) { + int index; + string = Tcl_GetString(objv[i]); + if (string[0] == '-') { + static char *flags[] = { + "-glob", "-regexp", "-exact", "-notransfer", "-nocase", + "-i", "-indices", "-iread", "-timestamp", "-timeout", + "-nobrace", "--", (char *)0 + }; + enum flags { + EXP_ARG_GLOB, EXP_ARG_REGEXP, EXP_ARG_EXACT, + EXP_ARG_NOTRANSFER, EXP_ARG_NOCASE, EXP_ARG_SPAWN_ID, + EXP_ARG_INDICES, EXP_ARG_IREAD, EXP_ARG_TIMESTAMP, + EXP_ARG_DASH_TIMEOUT, EXP_ARG_NOBRACE, EXP_ARG_DASH + }; + + /* + * Allow abbreviations of switches and report an error if we + * get an invalid switch. + */ + + if (Tcl_GetIndexFromObj(interp, objv[i], flags, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum flags) index) { + case EXP_ARG_GLOB: + case EXP_ARG_DASH: + i++; + /* assignment here is not actually necessary */ + /* since cases are initialized this way above */ + /* ec.use = PAT_GLOB; */ + if (i >= objc) { + Tcl_WrongNumArgs(interp, 1, objv,"-glob pattern"); + return TCL_ERROR; + } + goto pattern; + case EXP_ARG_REGEXP: + i++; + if (i >= objc) { + Tcl_WrongNumArgs(interp, 1, objv,"-regexp regexp"); + return TCL_ERROR; + } + ec.use = PAT_RE; + + /* + * Try compiling the expression so we can report + * any errors now rather then when we first try to + * use it. + */ + + if (!(Tcl_GetRegExpFromObj(interp, objv[i], + TCL_REG_ADVANCED))) { + goto error; + } + + /* Derive a gate keeper glob pattern which reduces the amount + * of RE matching. + */ + + { + Tcl_Obj* g; + Tcl_UniChar* str; + int strlen; + + str = Tcl_GetUnicodeFromObj (objv[i], &strlen); + g = exp_retoglob (str, strlen); + + if (g) { + ec.gate = g; + + expDiagLog("Gate keeper glob pattern for '%s'",Tcl_GetString(objv[i])); + expDiagLog(" is '%s'. Activating booster.\n",Tcl_GetString(g)); + } else { + /* Ignore errors, fall back to regular RE matching */ + expDiagLog("Gate keeper glob pattern for '%s'",Tcl_GetString(objv[i])); + expDiagLog(" is '%s'. Not usable, disabling the",Tcl_GetString(Tcl_GetObjResult (interp))); + expDiagLog(" performance booster.\n"); + } + } + + goto pattern; + case EXP_ARG_EXACT: + i++; + if (i >= objc) { + Tcl_WrongNumArgs(interp, 1, objv, "-exact string"); + return TCL_ERROR; + } + ec.use = PAT_EXACT; + goto pattern; + case EXP_ARG_NOTRANSFER: + ec.transfer = 0; + break; + case EXP_ARG_NOCASE: + ec.Case = CASE_LOWER; + break; + case EXP_ARG_SPAWN_ID: + i++; + if (i>=objc) { + Tcl_WrongNumArgs(interp, 1, objv, "-i spawn_id"); + goto error; + } + ec.i_list = exp_new_i_complex(interp, + Tcl_GetString(objv[i]), + eg->duration, exp_indirect_update2); + if (!ec.i_list) goto error; + ec.i_list->cmdtype = eg->cmdtype; + + /* link new i_list to head of list */ + ec.i_list->next = eg->i_list; + eg->i_list = ec.i_list; + break; + case EXP_ARG_INDICES: + ec.indices = TRUE; + break; + case EXP_ARG_IREAD: + ec.iread = TRUE; + break; + case EXP_ARG_TIMESTAMP: + ec.timestamp = TRUE; + break; + case EXP_ARG_DASH_TIMEOUT: + i++; + if (i>=objc) { + Tcl_WrongNumArgs(interp, 1, objv, "-timeout seconds"); + goto error; + } + if (Tcl_GetIntFromObj(interp, objv[i], + &eg->timeout) != TCL_OK) { + goto error; + } + eg->timeout_specified_by_flag = TRUE; + break; + case EXP_ARG_NOBRACE: + /* nobrace does nothing but take up space */ + /* on the command line which prevents */ + /* us from re-expanding any command lines */ + /* of one argument that looks like it should */ + /* be expanded to multiple arguments. */ + break; + } + /* + * Keep processing arguments, we aren't ready for the + * pattern yet. + */ + continue; + } else { + /* + * We have a pattern or keyword. + */ + + static char *keywords[] = { + "timeout", "eof", "full_buffer", "default", "null", + (char *)NULL + }; + enum keywords { + EXP_ARG_TIMEOUT, EXP_ARG_EOF, EXP_ARG_FULL_BUFFER, + EXP_ARG_DEFAULT, EXP_ARG_NULL + }; + + /* + * Match keywords exactly, otherwise they are patterns. + */ + + if (Tcl_GetIndexFromObj(interp, objv[i], keywords, "keyword", + 1 /* exact */, &index) != TCL_OK) { + Tcl_ResetResult(interp); + goto pattern; + } + switch ((enum keywords) index) { + case EXP_ARG_TIMEOUT: + ec.use = PAT_TIMEOUT; + break; + case EXP_ARG_EOF: + ec.use = PAT_EOF; + break; + case EXP_ARG_FULL_BUFFER: + ec.use = PAT_FULLBUFFER; + break; + case EXP_ARG_DEFAULT: + ec.use = PAT_DEFAULT; + break; + case EXP_ARG_NULL: + ec.use = PAT_NULL; + break; + } +pattern: + /* if no -i, use previous one */ + if (!ec.i_list) { + /* if no -i flag has occurred yet, use default */ + if (!eg->i_list) { + if (default_esPtr != EXP_SPAWN_ID_BAD) { + eg->i_list = exp_new_i_simple(default_esPtr,eg->duration); + } else { + default_esPtr = expStateCurrent(interp,0,0,1); + if (!default_esPtr) goto error; + eg->i_list = exp_new_i_simple(default_esPtr,eg->duration); + } + } + ec.i_list = eg->i_list; + } + ec.i_list->ecount++; + + /* save original pattern spec */ + /* keywords such as "-timeout" are saved as patterns here */ + /* useful for debugging but not otherwise used */ + + ec.pat = objv[i]; + if (eg->duration == EXP_PERMANENT) { + Tcl_IncrRefCount(ec.pat); + if (ec.gate) { + Tcl_IncrRefCount(ec.gate); + } + } + + i++; + if (i < objc) { + ec.body = objv[i]; + if (eg->duration == EXP_PERMANENT) Tcl_IncrRefCount(ec.body); + } else { + ec.body = NULL; + } + + *(eg->ecd.cases[eg->ecd.count] = ecase_new()) = ec; + + /* clear out for next set */ + ecase_clear(&ec); + + eg->ecd.count++; + } + } + + /* if no patterns at all have appeared force the current */ + /* spawn id to be added to list anyway */ + + if (eg->i_list == 0) { + if (default_esPtr != EXP_SPAWN_ID_BAD) { + eg->i_list = exp_new_i_simple(default_esPtr,eg->duration); + } else { + default_esPtr = expStateCurrent(interp,0,0,1); + if (!default_esPtr) goto error; + eg->i_list = exp_new_i_simple(default_esPtr,eg->duration); + } + } + + return(TCL_OK); + + error: + /* very hard to free case_master_list here if it hasn't already */ + /* been attached to a case, ugh */ + + /* note that i_list must be avail to free ecases! */ + free_ecases(interp,eg,0); + + if (eg->i_list) + exp_free_i(interp,eg->i_list,exp_indirect_update2); + return(TCL_ERROR); +} + +#define EXP_IS_DEFAULT(x) ((x) == EXP_TIMEOUT || (x) == EXP_EOF) + +static char yes[] = "yes\r\n"; +static char no[] = "no\r\n"; + +/* this describes status of a successful match */ +struct eval_out { + struct ecase *e; /* ecase that matched */ + ExpState *esPtr; /* ExpState that matched */ + Tcl_UniChar* matchbuf; /* Buffer that matched, */ + int matchlen; /* and #chars that matched, or + * #chars in buffer at EOF */ + /* This points into the esPtr->input.buffer ! */ +}; + + + + +/* + *---------------------------------------------------------------------- + * + * string_case_first -- + * + * Find the first instance of a pattern in a string. + * + * Results: + * Returns the pointer to the first instance of the pattern + * in the given string, or NULL if no match was found. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_UniChar * +string_case_first( /* INTL */ + register Tcl_UniChar *string, /* String (unicode). */ + int length, /* length of above string */ + register char *pattern) /* Pattern, which may contain + * special characters (utf8). */ +{ + Tcl_UniChar *s; + char *p; + int offset; + register int consumed = 0; + Tcl_UniChar ch1, ch2; + Tcl_UniChar *bufend = string + length; + + while ((*string != 0) && (string < bufend)) { + s = string; + p = pattern; + while ((*s) && (s < bufend)) { + ch1 = *s++; + consumed++; + offset = TclUtfToUniChar(p, &ch2); + if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) { + break; + } + p += offset; + } + if (*p == '\0') { + return string; + } + string++; + consumed++; + } + return NULL; +} + +Tcl_UniChar * +string_first( /* INTL */ + register Tcl_UniChar *string, /* String (unicode). */ + int length, /* length of above string */ + register char *pattern) /* Pattern, which may contain + * special characters (utf8). */ +{ + Tcl_UniChar *s; + char *p; + int offset; + register int consumed = 0; + Tcl_UniChar ch1, ch2; + Tcl_UniChar *bufend = string + length; + + while ((*string != 0) && (string < bufend)) { + s = string; + p = pattern; + while ((*s) && (s < bufend)) { + ch1 = *s++; + consumed++; + offset = TclUtfToUniChar(p, &ch2); + if (ch1 != ch2) { + break; + } + p += offset; + } + if (*p == '\0') { + return string; + } + string++; + consumed++; + } + return NULL; +} + +Tcl_UniChar * +string_first_char( /* INTL */ + register Tcl_UniChar *string, /* String. */ + register Tcl_UniChar pattern) +{ + /* unicode based Tcl_UtfFindFirst */ + + Tcl_UniChar find; + + while (1) { + find = *string; + if (find == pattern) { + return string; + } + if (*string == '\0') { + return NULL; + } + string ++; + } + return NULL; +} + +/* like eval_cases, but handles only a single cases that needs a real */ +/* string match */ +/* returns EXP_X where X is MATCH, NOMATCH, FULLBUFFER, TCLERRROR */ +static int +eval_case_string( + Tcl_Interp *interp, + struct ecase *e, + ExpState *esPtr, + struct eval_out *o, /* 'output' - i.e., final case of interest */ +/* next two args are for debugging, when they change, reprint buffer */ + ExpState **last_esPtr, + int *last_case, + char *suffix) +{ + Tcl_RegExp re; + Tcl_RegExpInfo info; + Tcl_Obj* buf; + Tcl_UniChar *str; + int numchars, flags, dummy, globmatch; + int result; + + str = esPtr->input.buffer; + numchars = esPtr->input.use; + + /* if ExpState or case changed, redisplay debug-buffer */ + if ((esPtr != *last_esPtr) || e->Case != *last_case) { + expDiagLog("\r\nexpect%s: does \"",suffix); + expDiagLogU(expPrintifyUni(str,numchars)); + expDiagLog("\" (spawn_id %s) match %s ",esPtr->name,pattern_style[e->use]); + *last_esPtr = esPtr; + *last_case = e->Case; + } + + if (e->use == PAT_RE) { + expDiagLog("\""); + expDiagLogU(expPrintify(Tcl_GetString(e->pat))); + expDiagLog("\"? "); + + if (e->gate) { + int plen; + Tcl_UniChar* pat = Tcl_GetUnicodeFromObj(e->gate,&plen); + + expDiagLog("Gate \""); + expDiagLogU(expPrintify(Tcl_GetString(e->gate))); + expDiagLog("\"? gate="); + + globmatch = Exp_StringCaseMatch(str, numchars, pat, plen, + (e->Case == CASE_NORM) ? 0 : 1, + &dummy); + } else { + expDiagLog("(No Gate, RE only) gate="); + + /* No gate => RE matching always */ + globmatch = 1; + } + if (globmatch < 0) { + expDiagLogU(no); + /* i.e. no match */ + } else { + expDiagLog("yes re="); + + if (e->Case == CASE_NORM) { + flags = TCL_REG_ADVANCED; + } else { + flags = TCL_REG_ADVANCED | TCL_REG_NOCASE; + } + + re = Tcl_GetRegExpFromObj(interp, e->pat, flags); + + /* ZZZ: Future optimization: Avoid copying */ + buf = Tcl_NewUnicodeObj (str, numchars); + Tcl_IncrRefCount (buf); + result = Tcl_RegExpExecObj(interp, re, buf, 0 /* offset */, + -1 /* nmatches */, 0 /* eflags */); + Tcl_DecrRefCount (buf); + if (result > 0) { + o->e = e; + + /* + * Retrieve the byte offset of the end of the + * matched string. + */ + + Tcl_RegExpGetInfo(re, &info); + o->matchlen = info.matches[0].end; + o->matchbuf = str; + o->esPtr = esPtr; + expDiagLogU(yes); + return(EXP_MATCH); + } else if (result == 0) { + expDiagLogU(no); + } else { /* result < 0 */ + return(EXP_TCLERROR); + } + } + } else if (e->use == PAT_GLOB) { + int match; /* # of chars that matched */ + + expDiagLog("\""); + expDiagLogU(expPrintify(Tcl_GetString(e->pat))); + expDiagLog("\"? "); + if (str) { + int plen; + Tcl_UniChar* pat = Tcl_GetUnicodeFromObj(e->pat,&plen); + + match = Exp_StringCaseMatch(str,numchars, pat, plen, + (e->Case == CASE_NORM) ? 0 : 1, + &e->simple_start); + if (match != -1) { + o->e = e; + o->matchlen = match; + o->matchbuf = str; + o->esPtr = esPtr; + expDiagLogU(yes); + return(EXP_MATCH); + } + } + expDiagLogU(no); + } else if (e->use == PAT_EXACT) { + int patLength; + char *pat = Tcl_GetStringFromObj(e->pat, &patLength); + Tcl_UniChar *p; + + if (e->Case == CASE_NORM) { + p = string_first(str, numchars, pat); /* NEW function in this file, see above */ + } else { + p = string_case_first(str, numchars, pat); + } + + expDiagLog("\""); + expDiagLogU(expPrintify(Tcl_GetString(e->pat))); + expDiagLog("\"? "); + if (p) { + /* Bug 3095935. Go from #bytes to #chars */ + patLength = Tcl_NumUtfChars (pat, patLength); + + e->simple_start = p - str; + o->e = e; + o->matchlen = patLength; + o->matchbuf = str; + o->esPtr = esPtr; + expDiagLogU(yes); + return(EXP_MATCH); + } else expDiagLogU(no); + } else if (e->use == PAT_NULL) { + CONST Tcl_UniChar *p; + expDiagLogU("null? "); + p = string_first_char (str, 0); /* NEW function in this file, see above */ + + if (p) { + o->e = e; + o->matchlen = p-str; /* #chars */ + o->matchbuf = str; + o->esPtr = esPtr; + expDiagLogU(yes); + return EXP_MATCH; + } + expDiagLogU(no); + } else if (e->use == PAT_FULLBUFFER) { + expDiagLogU(Tcl_GetString(e->pat)); + expDiagLogU("? "); + /* this must be the same test as in expIRead */ + /* We drop one third when are at least 2/3 full */ + /* condition is (size >= max*2/3) <=> (size*3 >= max*2) */ + if (((expSizeGet(esPtr)*3) >= (esPtr->input.max*2)) && (numchars > 0)) { + o->e = e; + o->matchlen = numchars; + o->matchbuf = str; + o->esPtr = esPtr; + expDiagLogU(yes); + return(EXP_FULLBUFFER); + } else { + expDiagLogU(no); + } + } + return(EXP_NOMATCH); +} + +/* sets o.e if successfully finds a matching pattern, eof, timeout or deflt */ +/* returns original status arg or EXP_TCLERROR */ +static int +eval_cases( + Tcl_Interp *interp, + struct exp_cmd_descriptor *eg, + ExpState *esPtr, + struct eval_out *o, /* 'output' - i.e., final case of interest */ +/* next two args are for debugging, when they change, reprint buffer */ + ExpState **last_esPtr, + int *last_case, + int status, + ExpState *(esPtrs[]), + int mcount, + char *suffix) +{ + int i; + ExpState *em; /* ExpState of ecase */ + struct ecase *e; + + if (o->e || status == EXP_TCLERROR || eg->ecd.count == 0) return(status); + + if (status == EXP_TIMEOUT) { + for (i=0;i<eg->ecd.count;i++) { + e = eg->ecd.cases[i]; + if (e->use == PAT_TIMEOUT || e->use == PAT_DEFAULT) { + o->e = e; + break; + } + } + return(status); + } else if (status == EXP_EOF) { + for (i=0;i<eg->ecd.count;i++) { + e = eg->ecd.cases[i]; + if (e->use == PAT_EOF || e->use == PAT_DEFAULT) { + struct exp_state_list *slPtr; + + for (slPtr=e->i_list->state_list; slPtr ;slPtr=slPtr->next) { + em = slPtr->esPtr; + if (expStateAnyIs(em) || em == esPtr) { + o->e = e; + return(status); + } + } + } + } + return(status); + } + + /* the top loops are split from the bottom loop only because I can't */ + /* split'em further. */ + + /* The bufferful condition does not prevent a pattern match from */ + /* occurring and vice versa, so it is scanned with patterns */ + for (i=0;i<eg->ecd.count;i++) { + struct exp_state_list *slPtr; + int j; + + e = eg->ecd.cases[i]; + if (e->use == PAT_TIMEOUT || + e->use == PAT_DEFAULT || + e->use == PAT_EOF) continue; + + for (slPtr = e->i_list->state_list; slPtr; slPtr = slPtr->next) { + em = slPtr->esPtr; + /* if em == EXP_SPAWN_ID_ANY, then user is explicitly asking */ + /* every case to be checked against every ExpState */ + if (expStateAnyIs(em)) { + /* test against each spawn_id */ + for (j=0;j<mcount;j++) { + status = eval_case_string(interp,e,esPtrs[j],o, + last_esPtr,last_case,suffix); + if (status != EXP_NOMATCH) return(status); + } + } else { + /* reject things immediately from wrong spawn_id */ + if (em != esPtr) continue; + + status = eval_case_string(interp,e,esPtr,o,last_esPtr,last_case,suffix); + if (status != EXP_NOMATCH) return(status); + } + } + } + return(EXP_NOMATCH); +} + +static void +ecases_remove_by_expi( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + struct exp_i *exp_i) +{ + int i; + + /* delete every ecase dependent on it */ + for (i=0;i<ecmd->ecd.count;) { + struct ecase *e = ecmd->ecd.cases[i]; + if (e->i_list == exp_i) { + free_ecase(interp,e,0); + + /* shift remaining elements down */ + /* but only if there are any left */ + if (i+1 != ecmd->ecd.count) { + memcpy(&ecmd->ecd.cases[i], + &ecmd->ecd.cases[i+1], + ((ecmd->ecd.count - i) - 1) * + sizeof(struct exp_cmd_descriptor *)); + } + ecmd->ecd.count--; + if (0 == ecmd->ecd.count) { + ckfree((char *)ecmd->ecd.cases); + ecmd->ecd.cases = 0; + } + } else { + i++; + } + } +} + +/* remove exp_i from list */ +static void +exp_i_remove( + Tcl_Interp *interp, + struct exp_i **ei, /* list to remove from */ + struct exp_i *exp_i) /* element to remove */ +{ + /* since it's in middle of list, free exp_i by hand */ + for (;*ei; ei = &(*ei)->next) { + if (*ei == exp_i) { + *ei = exp_i->next; + exp_i->next = 0; + exp_free_i(interp,exp_i,exp_indirect_update2); + break; + } + } +} + +/* remove exp_i from list and remove any dependent ecases */ +static void +exp_i_remove_with_ecases( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + struct exp_i *exp_i) +{ + ecases_remove_by_expi(interp,ecmd,exp_i); + exp_i_remove(interp,&ecmd->i_list,exp_i); +} + +/* remove ecases tied to a single direct spawn id */ +static void +ecmd_remove_state( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + ExpState *esPtr, + int direct) +{ + struct exp_i *exp_i, *next; + struct exp_state_list **slPtr; + + for (exp_i=ecmd->i_list;exp_i;exp_i=next) { + next = exp_i->next; + + if (!(direct & exp_i->direct)) continue; + + for (slPtr = &exp_i->state_list;*slPtr;) { + if (esPtr == ((*slPtr)->esPtr)) { + struct exp_state_list *tmp = *slPtr; + *slPtr = (*slPtr)->next; + exp_free_state_single(tmp); + + /* if last bg ecase, disarm spawn id */ + if ((ecmd->cmdtype == EXP_CMD_BG) && (!expStateAnyIs(esPtr))) { + esPtr->bg_ecount--; + if (esPtr->bg_ecount == 0) { + exp_disarm_background_channelhandler(esPtr); + esPtr->bg_interp = 0; + } + } + + continue; + } + slPtr = &(*slPtr)->next; + } + + /* if left with no ExpStates (and is direct), get rid of it */ + /* and any dependent ecases */ + if (exp_i->direct == EXP_DIRECT && !exp_i->state_list) { + exp_i_remove_with_ecases(interp,ecmd,exp_i); + } + } +} + +/* this is called from exp_close to clean up the ExpState */ +void +exp_ecmd_remove_state_direct_and_indirect( + Tcl_Interp *interp, + ExpState *esPtr) +{ + ecmd_remove_state(interp,&exp_cmds[EXP_CMD_BEFORE],esPtr,EXP_DIRECT|EXP_INDIRECT); + ecmd_remove_state(interp,&exp_cmds[EXP_CMD_AFTER],esPtr,EXP_DIRECT|EXP_INDIRECT); + ecmd_remove_state(interp,&exp_cmds[EXP_CMD_BG],esPtr,EXP_DIRECT|EXP_INDIRECT); + + /* force it - explanation in exp_tk.c where this func is defined */ + exp_disarm_background_channelhandler_force(esPtr); +} + +/* arm a list of background ExpState's */ +static void +state_list_arm( + Tcl_Interp *interp, + struct exp_state_list *slPtr) +{ + /* for each spawn id in list, arm if necessary */ + for (;slPtr;slPtr=slPtr->next) { + ExpState *esPtr = slPtr->esPtr; + if (expStateAnyIs(esPtr)) continue; + + if (esPtr->bg_ecount == 0) { + exp_arm_background_channelhandler(esPtr); + esPtr->bg_interp = interp; + } + esPtr->bg_ecount++; + } +} + +/* return TRUE if this ecase is used by this fd */ +static int +exp_i_uses_state( + struct exp_i *exp_i, + ExpState *esPtr) +{ + struct exp_state_list *fdp; + + for (fdp = exp_i->state_list;fdp;fdp=fdp->next) { + if (fdp->esPtr == esPtr) return 1; + } + return 0; +} + +static void +ecase_append( + Tcl_Interp *interp, + struct ecase *ec) +{ + if (!ec->transfer) Tcl_AppendElement(interp,"-notransfer"); + if (ec->indices) Tcl_AppendElement(interp,"-indices"); + if (!ec->Case) Tcl_AppendElement(interp,"-nocase"); + + if (ec->use == PAT_RE) Tcl_AppendElement(interp,"-re"); + else if (ec->use == PAT_GLOB) Tcl_AppendElement(interp,"-gl"); + else if (ec->use == PAT_EXACT) Tcl_AppendElement(interp,"-ex"); + Tcl_AppendElement(interp,Tcl_GetString(ec->pat)); + Tcl_AppendElement(interp,ec->body?Tcl_GetString(ec->body):""); +} + +/* append all ecases that match this exp_i */ +static void +ecase_by_exp_i_append( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + struct exp_i *exp_i) +{ + int i; + for (i=0;i<ecmd->ecd.count;i++) { + if (ecmd->ecd.cases[i]->i_list == exp_i) { + ecase_append(interp,ecmd->ecd.cases[i]); + } + } +} + +static void +exp_i_append( + Tcl_Interp *interp, + struct exp_i *exp_i) +{ + Tcl_AppendElement(interp,"-i"); + if (exp_i->direct == EXP_INDIRECT) { + Tcl_AppendElement(interp,exp_i->variable); + } else { + struct exp_state_list *fdp; + + /* if more than one element, add braces */ + if (exp_i->state_list->next) { + Tcl_AppendResult(interp," {",(char *)0); + } + + for (fdp = exp_i->state_list;fdp;fdp=fdp->next) { + char buf[25]; /* big enough for a small int */ + sprintf(buf,"%ld", (long)fdp->esPtr); + Tcl_AppendElement(interp,buf); + } + + if (exp_i->state_list->next) { + Tcl_AppendResult(interp,"} ",(char *)0); + } +} +} + +/* return current setting of the permanent expect_before/after/bg */ +int +expect_info( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + struct exp_i *exp_i; + int i; + int direct = EXP_DIRECT|EXP_INDIRECT; + char *iflag = 0; + int all = FALSE; /* report on all fds */ + ExpState *esPtr = 0; + + static char *flags[] = {"-i", "-all", "-noindirect", (char *)0}; + enum flags {EXP_ARG_I, EXP_ARG_ALL, EXP_ARG_NOINDIRECT}; + + /* start with 2 to skip over "cmdname -info" */ + for (i = 2;i<objc;i++) { + /* + * Allow abbreviations of switches and report an error if we + * get an invalid switch. + */ + + int index; + if (Tcl_GetIndexFromObj(interp, objv[i], flags, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum flags) index) { + case EXP_ARG_I: + i++; + if (i >= objc) { + Tcl_WrongNumArgs(interp, 1, objv,"-i spawn_id"); + return TCL_ERROR; + } + break; + case EXP_ARG_ALL: + all = TRUE; + break; + case EXP_ARG_NOINDIRECT: + direct &= ~EXP_INDIRECT; + break; + } + } + + if (all) { + /* avoid printing out -i when redundant */ + struct exp_i *previous = 0; + + for (i=0;i<ecmd->ecd.count;i++) { + if (previous != ecmd->ecd.cases[i]->i_list) { + exp_i_append(interp,ecmd->ecd.cases[i]->i_list); + previous = ecmd->ecd.cases[i]->i_list; + } + ecase_append(interp,ecmd->ecd.cases[i]); + } + return TCL_OK; + } + + if (!iflag) { + if (!(esPtr = expStateCurrent(interp,0,0,0))) { + return TCL_ERROR; + } + } else if (!(esPtr = expStateFromChannelName(interp,iflag,0,0,0,"dummy"))) { + /* not a valid ExpState so assume it is an indirect variable */ + Tcl_ResetResult(interp); + for (i=0;i<ecmd->ecd.count;i++) { + if (ecmd->ecd.cases[i]->i_list->direct == EXP_INDIRECT && + streq(ecmd->ecd.cases[i]->i_list->variable,iflag)) { + ecase_append(interp,ecmd->ecd.cases[i]); + } + } + return TCL_OK; + } + + /* print ecases of this direct_fd */ + for (exp_i=ecmd->i_list;exp_i;exp_i=exp_i->next) { + if (!(direct & exp_i->direct)) continue; + if (!exp_i_uses_state(exp_i,esPtr)) continue; + ecase_by_exp_i_append(interp,ecmd,exp_i); + } + + return TCL_OK; +} + +/* Exp_ExpectGlobalObjCmd is invoked to process expect_before/after/background */ +/*ARGSUSED*/ +int +Exp_ExpectGlobalObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int result = TCL_OK; + struct exp_i *exp_i, **eip; + struct exp_state_list *slPtr; /* temp for interating over state_list */ + struct exp_cmd_descriptor eg; + int count; + Tcl_Obj* new_cmd = NULL; + + struct exp_cmd_descriptor *ecmd = (struct exp_cmd_descriptor *) clientData; + + if ((objc == 2) && exp_one_arg_braced(objv[1])) { + /* expect {...} */ + + new_cmd = exp_eval_with_one_arg(clientData,interp,objv); + if (!new_cmd) return TCL_ERROR; + } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) { + /* expect -brace {...} ... fake command line for reparsing */ + + Tcl_Obj *new_objv[2]; + new_objv[0] = objv[0]; + new_objv[1] = objv[2]; + + new_cmd = exp_eval_with_one_arg(clientData,interp,new_objv); + if (!new_cmd) return TCL_ERROR; + } + + if (new_cmd) { + /* Replace old arguments with result of the reparse */ + Tcl_ListObjGetElements (interp, new_cmd, &objc, (Tcl_Obj***) &objv); + } + + if (objc > 1 && (Tcl_GetString(objv[1])[0] == '-')) { + if (exp_flageq("info",Tcl_GetString(objv[1])+1,4)) { + int res = expect_info(interp,ecmd,objc,objv); + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return res; + } + } + + exp_cmd_init(&eg,ecmd->cmdtype,EXP_PERMANENT); + + if (TCL_ERROR == parse_expect_args(interp,&eg,EXP_SPAWN_ID_BAD, + objc,objv)) { + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return TCL_ERROR; + } + + /* + * visit each NEW direct exp_i looking for spawn ids. + * When found, remove them from any OLD exp_i's. + */ + + /* visit each exp_i */ + for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) { + if (exp_i->direct == EXP_INDIRECT) continue; + /* for each spawn id, remove it from ecases */ + for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) { + ExpState *esPtr = slPtr->esPtr; + + /* validate all input descriptors */ + if (!expStateAnyIs(esPtr)) { + if (!expStateCheck(interp,esPtr,1,1,"expect")) { + result = TCL_ERROR; + goto cleanup; + } + } + + /* remove spawn id from exp_i */ + ecmd_remove_state(interp,ecmd,esPtr,EXP_DIRECT); + } + } + + /* + * For each indirect variable, release its old ecases and + * clean up the matching spawn ids. + * Same logic as in "expect_X delete" command. + */ + + for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) { + struct exp_i **old_i; + + if (exp_i->direct == EXP_DIRECT) continue; + + for (old_i = &ecmd->i_list;*old_i;) { + struct exp_i *tmp; + + if (((*old_i)->direct == EXP_DIRECT) || + (!streq((*old_i)->variable,exp_i->variable))) { + old_i = &(*old_i)->next; + continue; + } + + ecases_remove_by_expi(interp,ecmd,*old_i); + + /* unlink from middle of list */ + tmp = *old_i; + *old_i = tmp->next; + tmp->next = 0; + exp_free_i(interp,tmp,exp_indirect_update2); + } + + /* if new one has ecases, update it */ + if (exp_i->ecount) { + /* Note: The exp_indirect_ functions are Tcl_VarTraceProc's, and + * are used as such in other places of Expect. We cannot use a + * Tcl_Obj* as return value :( + */ + char *msg = exp_indirect_update1(interp,ecmd,exp_i); + if (msg) { + /* unusual way of handling error return */ + /* because of Tcl's variable tracing */ + Tcl_SetResult (interp, msg, TCL_VOLATILE); + result = TCL_ERROR; + goto indirect_update_abort; + } + } + } + /* empty i_lists have to be removed from global eg.i_list */ + /* before returning, even if during error */ + indirect_update_abort: + + /* + * New exp_i's that have 0 ecases indicate fd/vars to be deleted. + * Now that the deletions have been done, discard the new exp_i's. + */ + + for (exp_i=eg.i_list;exp_i;) { + struct exp_i *next = exp_i->next; + + if (exp_i->ecount == 0) { + exp_i_remove(interp,&eg.i_list,exp_i); + } + exp_i = next; + } + if (result == TCL_ERROR) goto cleanup; + + /* + * arm all new bg direct fds + */ + + if (ecmd->cmdtype == EXP_CMD_BG) { + for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) { + if (exp_i->direct == EXP_DIRECT) { + state_list_arm(interp,exp_i->state_list); + } + } + } + + /* + * now that old ecases are gone, add new ecases and exp_i's (both + * direct and indirect). + */ + + /* append ecases */ + + count = ecmd->ecd.count + eg.ecd.count; + if (eg.ecd.count) { + int start_index; /* where to add new ecases in old list */ + + if (ecmd->ecd.count) { + /* append to end */ + ecmd->ecd.cases = (struct ecase **)ckrealloc((char *)ecmd->ecd.cases, count * sizeof(struct ecase *)); + start_index = ecmd->ecd.count; + } else { + /* append to beginning */ + ecmd->ecd.cases = (struct ecase **)ckalloc(eg.ecd.count * sizeof(struct ecase *)); + start_index = 0; + } + memcpy(&ecmd->ecd.cases[start_index],eg.ecd.cases, + eg.ecd.count*sizeof(struct ecase *)); + ecmd->ecd.count = count; + } + + /* append exp_i's */ + for (eip = &ecmd->i_list;*eip;eip = &(*eip)->next) { + /* empty loop to get to end of list */ + } + /* *exp_i now points to end of list */ + + *eip = eg.i_list; /* connect new list to end of current list */ + + cleanup: + if (result == TCL_ERROR) { + /* in event of error, free any unreferenced ecases */ + /* but first, split up i_list so that exp_i's aren't */ + /* freed twice */ + + for (exp_i=eg.i_list;exp_i;) { + struct exp_i *next = exp_i->next; + exp_i->next = 0; + exp_i = next; + } + free_ecases(interp,&eg,1); + } else { + if (eg.ecd.cases) ckfree((char *)eg.ecd.cases); + } + + if (ecmd->cmdtype == EXP_CMD_BG) { + exp_background_channelhandlers_run_all(); + } + + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return(result); +} + +/* adjusts file according to user's size request */ +void +expAdjust(ExpState *esPtr) +{ + int new_msize, excess; + Tcl_UniChar *string; + + /* + * Resize buffer to user's request * 3 + 1. + * + * x3: in case the match straddles two bufferfuls, and to allow + * reading a bufferful even when we reach near fullness of two. + * (At shuffle time this means we look for 2/3 full buffer and + * drop a 1/3, i.e. half of that). + * + * NOTE: The unmodified expect got the same effect by comparing + * apples and oranges in shuffle mgmt, i.e bytes vs. chars, + * and automatically extending the buffer (Tcl_Obj string) + * to hold that much. + * + * +1: for trailing null. + */ + + new_msize = esPtr->umsize * 3 + 1; + + if (new_msize != esPtr->input.max) { + + if (esPtr->input.use > new_msize) { + /* + * too much data, forget about data at beginning of buffer + */ + + string = esPtr->input.buffer; + excess = esPtr->input.use - new_msize; /* #chars */ + + memcpy (string, string + excess, new_msize * sizeof (Tcl_UniChar)); + esPtr->input.use = new_msize; + + } else { + /* + * too little data - length < new_mbytes + * Make larger if the max is also too small. + */ + + if (esPtr->input.max < new_msize) { + esPtr->input.buffer = (Tcl_UniChar*) \ + Tcl_Realloc ((char*)esPtr->input.buffer, + new_msize * sizeof (Tcl_UniChar)); + } + } + + esPtr->key = expect_key++; + esPtr->input.max = new_msize; + } +} + +#if OBSOLETE +/* Strip parity */ +static void +expParityStrip( + Tcl_Obj *obj, + int offsetBytes) +{ + char *p, ch; + + int changed = FALSE; + + for (p = Tcl_GetString(obj) + offsetBytes;*p;p++) { + ch = *p & 0x7f; + if (ch != *p) changed = TRUE; + else *p &= 0x7f; + } + + if (changed) { + /* invalidate the unicode rep */ + if (obj->typePtr->freeIntRepProc) { + obj->typePtr->freeIntRepProc(obj); + } + } +} + +/* This function is only used when debugging. It checks when a string's + internal UTF is sane and whether an offset into the string appears to + be at a UTF boundary. +*/ +static void +expValid( + Tcl_Obj *obj, + int offset) +{ + char *s, *end; + int len; + + s = Tcl_GetStringFromObj(obj,&len); + + if (offset > len) { + printf("offset (%d) > length (%d)\n",offset,len); + fflush(stdout); + abort(); + } + + /* first test for null terminator */ + end = s + len; + if (*end != '\0') { + printf("obj lacks null terminator\n"); + fflush(stdout); + abort(); + } + + /* check for valid UTF sequence */ + while (*s) { + Tcl_UniChar uc; + + s += TclUtfToUniChar(s,&uc); + if (s > end) { + printf("UTF out of sync with terminator\n"); + fflush(stdout); + abort(); + } + } + s += offset; + while (*s) { + Tcl_UniChar uc; + + s += TclUtfToUniChar(s,&uc); + if (s > end) { + printf("UTF from offset out of sync with terminator\n"); + fflush(stdout); + abort(); + } + } +} +#endif /*OBSOLETE*/ + +/* Strip nulls from object, beginning at offset */ +static int +expNullStrip( + ExpUniBuf* buf, + int offsetChars) +{ + Tcl_UniChar *src, *src2, *dest, *end; + int newsize; /* size of obj after all nulls removed */ + + src2 = src = dest = buf->buffer + offsetChars; + end = buf->buffer + buf->use; + + while (src < end) { + if (*src) { + *dest = *src; + dest ++; + } + src ++; + } + newsize = offsetChars + (dest - src2); + buf->use = newsize; + return newsize; +} + +/* returns # of bytes read or (non-positive) error of form EXP_XXX */ +/* returns 0 for end of file */ +/* If timeout is non-zero, set an alarm before doing the read, else assume */ +/* the read will complete immediately. */ +/*ARGSUSED*/ +static int +expIRead( /* INTL */ + Tcl_Interp *interp, + ExpState *esPtr, + int timeout, + int save_flags) +{ + int cc = EXP_TIMEOUT; + int size; + + /* We drop one third when are at least 2/3 full */ + /* condition is (size >= max*2/3) <=> (size*3 >= max*2) */ + if (expSizeGet(esPtr)*3 >= esPtr->input.max*2) + exp_buffer_shuffle(interp,esPtr,save_flags,EXPECT_OUT,"expect"); + size = expSizeGet(esPtr); + +#ifdef SIMPLE_EVENT + restart: + + alarm_fired = FALSE; + + if (timeout > -1) { + signal(SIGALRM,sigalarm_handler); + alarm((timeout > 0)?timeout:1); + } +#endif + + cc = Tcl_ReadChars(esPtr->channel, esPtr->input.newchars, + esPtr->input.max - esPtr->input.use, + 0 /* no append */); + i_read_errno = errno; + + if (cc > 0) { + memcpy (esPtr->input.buffer + esPtr->input.use, + Tcl_GetUnicodeFromObj (esPtr->input.newchars, NULL), + cc * sizeof (Tcl_UniChar)); + esPtr->input.use += cc; + } + +#ifdef SIMPLE_EVENT + alarm(0); + + if (cc == -1) { + /* check if alarm went off */ + if (i_read_errno == EINTR) { + if (alarm_fired) { + return EXP_TIMEOUT; + } else { + if (Tcl_AsyncReady()) { + int rc = Tcl_AsyncInvoke(interp,TCL_OK); + if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); + } + goto restart; + } + } + } +#endif + return cc; +} + +/* + * expRead() does the logical equivalent of a read() for the expect command. + * This includes figuring out which descriptor should be read from. + * + * The result of the read() is left in a spawn_id's buffer rather than + * explicitly passing it back. Note that if someone else has modified a buffer + * either before or while this expect is running (i.e., if we or some event has + * called Tcl_Eval which did another expect/interact), expRead will also call + * this a successful read (for the purposes if needing to pattern match against + * it). + */ + +/* if it returns a negative number, it corresponds to a EXP_XXX result */ +/* if it returns a non-negative number, it means there is data */ +/* (0 means nothing new was actually read, but it should be looked at again) */ +int +expRead( + Tcl_Interp *interp, + ExpState *(esPtrs[]), /* If 0, then esPtrOut already known and set */ + int esPtrsMax, /* number of esPtrs */ + ExpState **esPtrOut, /* Out variable to leave new ExpState. */ + int timeout, + int key) +{ + ExpState *esPtr; + + int size; + int cc; + int write_count; + int tcl_set_flags; /* if we have to discard chars, this tells */ + /* whether to show user locally or globally */ + + if (esPtrs == 0) { + /* we already know the ExpState, just find out what happened */ + cc = exp_get_next_event_info(interp,*esPtrOut); + tcl_set_flags = TCL_GLOBAL_ONLY; + } else { + cc = exp_get_next_event(interp,esPtrs,esPtrsMax,esPtrOut,timeout,key); + tcl_set_flags = 0; + } + + esPtr = *esPtrOut; + + if (cc == EXP_DATA_NEW) { + /* try to read it */ + cc = expIRead(interp,esPtr,timeout,tcl_set_flags); + + /* the meaning of 0 from i_read means eof. Muck with it a */ + /* little, so that from now on it means "no new data arrived */ + /* but it should be looked at again anyway". */ + if (cc == 0) { + cc = EXP_EOF; + } else if (cc > 0) { + /* successfully read data */ + } else { + /* failed to read data - some sort of error was encountered such as + * an interrupt with that forced an error return + */ + } + } else if (cc == EXP_DATA_OLD) { + cc = 0; + } else if (cc == EXP_RECONFIGURE) { + return EXP_RECONFIGURE; + } + + if (cc == EXP_ABEOF) { /* abnormal EOF */ + /* On many systems, ptys produce EIO upon EOF - sigh */ + if (i_read_errno == EIO) { + /* Sun, Cray, BSD, and others */ + cc = EXP_EOF; + } else if (i_read_errno == EINVAL) { + /* Solaris 2.4 occasionally returns this */ + cc = EXP_EOF; + } else { + if (i_read_errno == EBADF) { + exp_error(interp,"bad spawn_id (process died earlier?)"); + } else { + exp_error(interp,"i_read(spawn_id fd=%d): %s",esPtr->fdin, + Tcl_PosixError(interp)); + if (esPtr->close_on_eof) { + exp_close(interp,esPtr); + } + } + return(EXP_TCLERROR); + /* was goto error; */ + } + } + + /* EOF, TIMEOUT, and ERROR return here */ + /* In such cases, there is no need to update screen since, if there */ + /* was prior data read, it would have been sent to the screen when */ + /* it was read. */ + if (cc < 0) return (cc); + + /* + * update display + */ + + size = expSizeGet(esPtr); + if (size) write_count = size - esPtr->printed; + else write_count = 0; + + if (write_count) { + /* + * Show chars to user if they've requested it, UNLESS they're seeing it + * already because they're typing it and tty driver is echoing it. + * Also send to Diag and Log if appropriate. + */ + expLogInteractionU(esPtr,esPtr->input.buffer + esPtr->printed, write_count); + + /* + * strip nulls from input, since there is no way for Tcl to deal with + * such strings. Doing it here lets them be sent to the screen, just + * in case they are involved in formatting operations + */ + if (esPtr->rm_nulls) size = expNullStrip(&esPtr->input,esPtr->printed); + esPtr->printed = size; /* count'm even if not logging */ + } + return(cc); +} + +/* when buffer fills, copy second half over first and */ +/* continue, so we can do matches over multiple buffers */ +void +exp_buffer_shuffle( /* INTL */ + Tcl_Interp *interp, + ExpState *esPtr, + int save_flags, + char *array_name, + char *caller_name) +{ + Tcl_UniChar *str; + Tcl_UniChar *p; + int numchars, newlen, skiplen; + Tcl_UniChar lostChar; + + /* + * allow user to see data we are discarding + */ + + expDiagLog("%s: set %s(spawn_id) \"%s\"\r\n", + caller_name,array_name,esPtr->name); + Tcl_SetVar2(interp,array_name,"spawn_id",esPtr->name,save_flags); + + /* + * The internal storage buffer object should only be referred + * to by the channel that uses it. We always copy the contents + * out of the object before passing the data to anyone outside + * of these routines. This ensures that the object always has + * a refcount of 1 so we can safely modify the contents in place. + */ + + str = esPtr->input.buffer; + numchars = esPtr->input.use; + + skiplen = numchars/3; + p = str + skiplen; + + /* + * before doing move, show user data we are discarding + */ + + lostChar = *p; + /* temporarily stick null in middle of string */ + *p = 0; + + expDiagLog("%s: set %s(buffer) \"",caller_name,array_name); + expDiagLogU(expPrintifyUni(str,numchars)); + expDiagLogU("\"\r\n"); + Tcl_SetVar2Ex(interp,array_name,"buffer", + Tcl_NewUnicodeObj (str, skiplen), + save_flags); + + /* + * restore damage + */ + *p = lostChar; + + /* + * move 2nd half of string down to 1st half + */ + + newlen = numchars - skiplen; + memmove(str, p, newlen * sizeof(Tcl_UniChar)); + esPtr->input.use = newlen; + + esPtr->printed -= skiplen; + if (esPtr->printed < 0) esPtr->printed = 0; +} + +/* map EXP_ style return value to TCL_ style return value */ +/* not defined to work on TCL_OK */ +int +exp_tcl2_returnvalue(int x) +{ + switch (x) { + case TCL_ERROR: return EXP_TCLERROR; + case TCL_RETURN: return EXP_TCLRET; + case TCL_BREAK: return EXP_TCLBRK; + case TCL_CONTINUE: return EXP_TCLCNT; + case EXP_CONTINUE: return EXP_TCLCNTEXP; + case EXP_CONTINUE_TIMER: return EXP_TCLCNTTIMER; + case EXP_TCL_RETURN: return EXP_TCLRETTCL; + } + /* Must not reach this location. Can happen only if x is an + * illegal value. Added return to suppress compiler warning. + */ + return -1000; +} + +/* map from EXP_ style return value to TCL_ style return values */ +int +exp_2tcl_returnvalue(int x) +{ + switch (x) { + case EXP_TCLERROR: return TCL_ERROR; + case EXP_TCLRET: return TCL_RETURN; + case EXP_TCLBRK: return TCL_BREAK; + case EXP_TCLCNT: return TCL_CONTINUE; + case EXP_TCLCNTEXP: return EXP_CONTINUE; + case EXP_TCLCNTTIMER: return EXP_CONTINUE_TIMER; + case EXP_TCLRETTCL: return EXP_TCL_RETURN; + } + /* Must not reach this location. Can happen only if x is an + * illegal value. Added return to suppress compiler warning. + */ + return -1000; +} + +/* variables predefined by expect are retrieved using this routine +which looks in the global space if they are not in the local space. +This allows the user to localize them if desired, and also to +avoid having to put "global" in procedure definitions. +*/ +char * +exp_get_var( + Tcl_Interp *interp, + char *var) +{ + char *val; + + if (NULL != (val = Tcl_GetVar(interp,var,0 /* local */))) + return(val); + return(Tcl_GetVar(interp,var,TCL_GLOBAL_ONLY)); +} + +static int +get_timeout(Tcl_Interp *interp) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + CONST char *t; + + if (NULL != (t = exp_get_var(interp,EXPECT_TIMEOUT))) { + tsdPtr->timeout = atoi(t); + } + return(tsdPtr->timeout); +} + +/* make a copy of a linked list (1st arg) and attach to end of another (2nd +arg) */ +static int +update_expect_states( + struct exp_i *i_list, + struct exp_state_list **i_union) +{ + struct exp_i *p; + + /* for each i_list in an expect statement ... */ + for (p=i_list;p;p=p->next) { + struct exp_state_list *slPtr; + + /* for each esPtr in the i_list */ + for (slPtr=p->state_list;slPtr;slPtr=slPtr->next) { + struct exp_state_list *tmpslPtr; + struct exp_state_list *u; + + if (expStateAnyIs(slPtr->esPtr)) continue; + + /* check this one against all so far */ + for (u = *i_union;u;u=u->next) { + if (slPtr->esPtr == u->esPtr) goto found; + } + /* if not found, link in as head of list */ + tmpslPtr = exp_new_state(slPtr->esPtr); + tmpslPtr->next = *i_union; + *i_union = tmpslPtr; + found:; + } + } + return TCL_OK; +} + +char * +exp_cmdtype_printable(int cmdtype) +{ + switch (cmdtype) { + case EXP_CMD_FG: return("expect"); + case EXP_CMD_BG: return("expect_background"); + case EXP_CMD_BEFORE: return("expect_before"); + case EXP_CMD_AFTER: return("expect_after"); + } + /*#ifdef LINT*/ + return("unknown expect command"); + /*#endif*/ +} + +/* exp_indirect_update2 is called back via Tcl's trace handler whenever */ +/* an indirect spawn id list is changed */ +/*ARGSUSED*/ +static char * +exp_indirect_update2( + ClientData clientData, + Tcl_Interp *interp, /* Interpreter containing variable. */ + char *name1, /* Name of variable. */ + char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ +{ + char *msg; + + struct exp_i *exp_i = (struct exp_i *)clientData; + exp_configure_count++; + msg = exp_indirect_update1(interp,&exp_cmds[exp_i->cmdtype],exp_i); + + exp_background_channelhandlers_run_all(); + + return msg; +} + +static char * +exp_indirect_update1( + Tcl_Interp *interp, + struct exp_cmd_descriptor *ecmd, + struct exp_i *exp_i) +{ + struct exp_state_list *slPtr; /* temp for interating over state_list */ + + /* + * disarm any ExpState's that lose all their active spawn ids + */ + + if (ecmd->cmdtype == EXP_CMD_BG) { + /* clean up each spawn id used by this exp_i */ + for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) { + ExpState *esPtr = slPtr->esPtr; + + if (expStateAnyIs(esPtr)) continue; + + /* silently skip closed or preposterous fds */ + /* since we're just disabling them anyway */ + /* preposterous fds will have been reported */ + /* by code in next section already */ + if (!expStateCheck(interp,slPtr->esPtr,1,0,"")) continue; + + /* check before decrementing, ecount may not be */ + /* positive if update is called before ecount is */ + /* properly synchronized */ + if (esPtr->bg_ecount > 0) { + esPtr->bg_ecount--; + } + if (esPtr->bg_ecount == 0) { + exp_disarm_background_channelhandler(esPtr); + esPtr->bg_interp = 0; + } + } + } + + /* + * reread indirect variable + */ + + exp_i_update(interp,exp_i); + + /* + * check validity of all fd's in variable + */ + + for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) { + /* validate all input descriptors */ + + if (expStateAnyIs(slPtr->esPtr)) continue; + + if (!expStateCheck(interp,slPtr->esPtr,1,1, + exp_cmdtype_printable(ecmd->cmdtype))) { + /* Note: Cannot construct a Tcl_Obj* here, the function is a + * Tcl_VarTraceProc and the API wants a char*. + * + * DANGER: The buffer may overflow if either the existing result, + * the variable name, or both become to large. + */ + static char msg[200]; + sprintf(msg,"%s from indirect variable (%s)", + Tcl_GetStringResult (interp),exp_i->variable); + return msg; + } + } + + /* for each spawn id in list, arm if necessary */ + if (ecmd->cmdtype == EXP_CMD_BG) { + state_list_arm(interp,exp_i->state_list); + } + + return (char *)0; +} + +int +expMatchProcess( + Tcl_Interp *interp, + struct eval_out *eo, /* final case of interest */ + int cc, /* EOF, TIMEOUT, etc... */ + int bg, /* 1 if called from background handler, */ + /* else 0 */ + char *detail) +{ + ExpState *esPtr = 0; + Tcl_Obj *body = 0; + Tcl_UniChar *buffer; + struct ecase *e = 0; /* points to current ecase */ + int match = -1; /* characters matched */ + /* uprooted by a NULL */ + int result = TCL_OK; + +#define out(indexName, value) \ + expDiagLog("%s: set %s(%s) \"",detail,EXPECT_OUT,indexName); \ + expDiagLogU(expPrintify(value)); \ + expDiagLogU("\"\r\n"); \ + Tcl_SetVar2(interp, EXPECT_OUT,indexName,value,(bg ? TCL_GLOBAL_ONLY : 0)); + + /* The numchars argument allows us to avoid sticking a \0 into the buffer */ +#define outuni(indexName, value,numchars) \ + expDiagLog("%s: set %s(%s) \"",detail,EXPECT_OUT,indexName); \ + expDiagLogU(expPrintifyUni(value,numchars)); \ + expDiagLogU("\"\r\n"); \ + Tcl_SetVar2Ex(interp, EXPECT_OUT,indexName,Tcl_NewUnicodeObj(value,numchars),(bg ? TCL_GLOBAL_ONLY : 0)); + + if (eo->e) { + e = eo->e; + body = e->body; + if (cc != EXP_TIMEOUT) { + esPtr = eo->esPtr; + match = eo->matchlen; + buffer = eo->matchbuf; + } + } else if (cc == EXP_EOF) { + /* read an eof but no user-supplied case */ + esPtr = eo->esPtr; + match = eo->matchlen; + buffer = eo->matchbuf; + } + + if (match >= 0) { + char name[20], value[20]; + int i; + + if (e && e->use == PAT_RE) { + Tcl_RegExp re; + int flags; + Tcl_RegExpInfo info; + Tcl_Obj *buf; + + /* No gate keeper required here, we know that the RE + * matches, we just do it again to get all the captured + * pieces + */ + + if (e->Case == CASE_NORM) { + flags = TCL_REG_ADVANCED; + } else { + flags = TCL_REG_ADVANCED | TCL_REG_NOCASE; + } + + re = Tcl_GetRegExpFromObj(interp, e->pat, flags); + Tcl_RegExpGetInfo(re, &info); + + buf = Tcl_NewUnicodeObj (buffer,esPtr->input.use); + for (i=0;i<=info.nsubs;i++) { + int start, end; + Tcl_Obj *val; + + start = info.matches[i].start; + end = info.matches[i].end-1; + if (start == -1) continue; + + if (e->indices) { + /* start index */ + sprintf(name,"%d,start",i); + sprintf(value,"%d",start); + out(name,value); + + /* end index */ + sprintf(name,"%d,end",i); + sprintf(value,"%d",end); + out(name,value); + } + + /* string itself */ + sprintf(name,"%d,string",i); + val = Tcl_GetRange(buf, start, end); + expDiagLog("%s: set %s(%s) \"",detail,EXPECT_OUT,name); + expDiagLogU(expPrintifyObj(val)); + expDiagLogU("\"\r\n"); + Tcl_SetVar2Ex(interp,EXPECT_OUT,name,val,(bg ? TCL_GLOBAL_ONLY : 0)); + } + Tcl_DecrRefCount (buf); + } else if (e && (e->use == PAT_GLOB || e->use == PAT_EXACT)) { + Tcl_UniChar *str; + + if (e->indices) { + /* start index */ + sprintf(value,"%d",e->simple_start); + out("0,start",value); + + /* end index */ + sprintf(value,"%d",e->simple_start + match - 1); + out("0,end",value); + } + + /* string itself */ + str = esPtr->input.buffer + e->simple_start; + outuni("0,string",str,match); + + /* redefine length of string that */ + /* matched for later extraction */ + match += e->simple_start; + } else if (e && e->use == PAT_NULL && e->indices) { + /* start index */ + sprintf(value,"%d",match-1); + out("0,start",value); + /* end index */ + sprintf(value,"%d",match-1); + out("0,end",value); + } else if (e && e->use == PAT_FULLBUFFER) { + expDiagLogU("expect_background: full buffer\r\n"); + } + } + + /* this is broken out of (match > 0) (above) since it can be */ + /* that an EOF occurred with match == 0 */ + if (eo->esPtr) { + Tcl_UniChar *str; + int numchars; + + out("spawn_id",esPtr->name); + + str = esPtr->input.buffer; + numchars = esPtr->input.use; + + /* Save buf[0..match] */ + outuni("buffer",str,match); + + /* "!e" means no case matched - transfer by default */ + if (!e || e->transfer) { + int remainder = numchars-match; + /* delete matched chars from input buffer */ + esPtr->printed -= match; + if (numchars != 0) { + memmove(str,str+match,remainder*sizeof(Tcl_UniChar)); + } + esPtr->input.use = remainder; + } + + if (cc == EXP_EOF) { + /* exp_close() deletes all background bodies */ + /* so save eof body temporarily */ + if (body) { Tcl_IncrRefCount(body); } + if (esPtr->close_on_eof) { + exp_close(interp,esPtr); + } + } + } + + if (body) { + if (!bg) { + result = Tcl_EvalObjEx(interp,body,0); + } else { + result = Tcl_EvalObjEx(interp,body,TCL_EVAL_GLOBAL); + if (result != TCL_OK) Tcl_BackgroundError(interp); + } + if (cc == EXP_EOF) { Tcl_DecrRefCount(body); } + } + return result; +} + +/* this function is called from the background when input arrives */ +/*ARGSUSED*/ +void +exp_background_channelhandler( /* INTL */ + ClientData clientData, + int mask) +{ + char backup[EXP_CHANNELNAMELEN+1]; /* backup copy of esPtr channel name! */ + + ExpState *esPtr; + Tcl_Interp *interp; + int cc; /* number of bytes returned in a single read */ + /* or negative EXP_whatever */ + struct eval_out eo; /* final case of interest */ + ExpState *last_esPtr; /* for differentiating when multiple esPtrs */ + /* to print out better debugging messages */ + int last_case; /* as above but for case */ + + /* restore our environment */ + esPtr = (ExpState *)clientData; + + /* backup just in case someone zaps esPtr in the middle of our work! */ + strcpy(backup,esPtr->name); + + interp = esPtr->bg_interp; + + /* temporarily prevent this handler from being invoked again */ + exp_block_background_channelhandler(esPtr); + + /* + * if mask == 0, then we've been called because the patterns changed not + * because the waiting data has changed, so don't actually do any I/O + */ + if (mask == 0) { + cc = 0; + } else { + esPtr->notifiedMask = mask; + esPtr->notified = FALSE; + cc = expRead(interp,(ExpState **)0,0,&esPtr,EXP_TIME_INFINITY,0); + } + +do_more_data: + eo.e = 0; /* no final case yet */ + eo.esPtr = 0; /* no final file selected yet */ + eo.matchlen = 0; /* nothing matched yet */ + + /* force redisplay of buffer when debugging */ + last_esPtr = 0; + + if (cc == EXP_EOF) { + /* do nothing */ + } else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/ + goto finish; + /* + * if we were going to do this right, we should differentiate between + * things like HP ioctl-open-traps that fall out here and should + * rightfully be ignored and real errors that should be reported. Come + * to think of it, the only errors will come from HP ioctl handshake + * botches anyway. + */ + } else { + /* normal case, got data */ + /* new data if cc > 0, same old data if cc == 0 */ + + /* below here, cc as general status */ + cc = EXP_NOMATCH; + } + + cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE], + esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background"); + cc = eval_cases(interp,&exp_cmds[EXP_CMD_BG], + esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background"); + cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER], + esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background"); + if (cc == EXP_TCLERROR) { + /* only likely problem here is some internal regexp botch */ + Tcl_BackgroundError(interp); + goto finish; + } + /* special eof code that cannot be done in eval_cases */ + /* or above, because it would then be executed several times */ + if (cc == EXP_EOF) { + eo.esPtr = esPtr; + eo.matchlen = expSizeGet(eo.esPtr); + eo.matchbuf = eo.esPtr->input.buffer; + expDiagLogU("expect_background: read eof\r\n"); + goto matched; + } + if (!eo.e) { + /* if we get here, there must not have been a match */ + goto finish; + } + + matched: + expMatchProcess(interp, &eo, cc, 1 /* bg */,"expect_background"); + + /* + * Event handler will not call us back if there is more input + * pending but it has already arrived. bg_status will be + * "blocked" only if armed. + */ + + /* + * Connection could have been closed on us. In this case, + * exitWhenBgStatusUnblocked will be 1 and we should disable the channel + * handler and release the esPtr. + */ + + /* First check that the esPtr is even still valid! */ + /* This ought to be sufficient. */ + if (0 == Tcl_GetChannel(interp,backup,(int *)0)) { + expDiagLog("expect channel %s lost in background handler\n",backup); + return; + } + + if ((!esPtr->freeWhenBgHandlerUnblocked) && (esPtr->bg_status == blocked)) { + if (0 != (cc = expSizeGet(esPtr))) { + goto do_more_data; + } + } + finish: + exp_unblock_background_channelhandler(esPtr); + if (esPtr->freeWhenBgHandlerUnblocked) + expStateFree(esPtr); +} + +/*ARGSUSED*/ +int +Exp_ExpectObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int cc; /* number of chars returned in a single read */ + /* or negative EXP_whatever */ + ExpState *esPtr = 0; + + int i; /* misc temporary */ + struct exp_cmd_descriptor eg; + struct exp_state_list *state_list; /* list of ExpStates to watch */ + struct exp_state_list *slPtr; /* temp for interating over state_list */ + ExpState **esPtrs; + int mcount; /* number of esPtrs to watch */ + + struct eval_out eo; /* final case of interest */ + + int result; /* Tcl result */ + + time_t start_time_total; /* time at beginning of this procedure */ + time_t start_time = 0; /* time when restart label hit */ + time_t current_time = 0; /* current time (when we last looked)*/ + time_t end_time; /* future time at which to give up */ + + ExpState *last_esPtr; /* for differentiating when multiple f's */ + /* to print out better debugging messages */ + int last_case; /* as above but for case */ + int first_time = 1; /* if not "restarted" */ + + int key; /* identify this expect command instance */ + int configure_count; /* monitor exp_configure_count */ + + int timeout; /* seconds */ + int remtime; /* remaining time in timeout */ + int reset_timer; /* should timer be reset after continue? */ + Tcl_Time temp_time; + Tcl_Obj* new_cmd = NULL; + + if ((objc == 2) && exp_one_arg_braced(objv[1])) { + /* expect {...} */ + + new_cmd = exp_eval_with_one_arg(clientData,interp,objv); + if (!new_cmd) return TCL_ERROR; + } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) { + /* expect -brace {...} ... fake command line for reparsing */ + + Tcl_Obj *new_objv[2]; + new_objv[0] = objv[0]; + new_objv[1] = objv[2]; + + new_cmd = exp_eval_with_one_arg(clientData,interp,new_objv); + if (!new_cmd) return TCL_ERROR; + } + + if (new_cmd) { + /* Replace old arguments with result of the reparse */ + Tcl_ListObjGetElements (interp, new_cmd, &objc, (Tcl_Obj***) &objv); + } + + Tcl_GetTime (&temp_time); + start_time_total = temp_time.sec; + start_time = start_time_total; + reset_timer = TRUE; + + if (&StdinoutPlaceholder == (ExpState *)clientData) { + clientData = (ClientData) expStdinoutGet(); + } else if (&DevttyPlaceholder == (ExpState *)clientData) { + clientData = (ClientData) expDevttyGet(); + } + + /* make arg list for processing cases */ + /* do it dynamically, since expect can be called recursively */ + + exp_cmd_init(&eg,EXP_CMD_FG,EXP_TEMPORARY); + state_list = 0; + esPtrs = 0; + if (TCL_ERROR == parse_expect_args(interp,&eg, (ExpState *)clientData, + objc,objv)) { + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return TCL_ERROR; + } + + restart_with_update: + /* validate all descriptors and flatten ExpStates into array */ + + if ((TCL_ERROR == update_expect_states(exp_cmds[EXP_CMD_BEFORE].i_list,&state_list)) + || (TCL_ERROR == update_expect_states(exp_cmds[EXP_CMD_AFTER].i_list, &state_list)) + || (TCL_ERROR == update_expect_states(eg.i_list,&state_list))) { + result = TCL_ERROR; + goto cleanup; + } + + /* declare ourselves "in sync" with external view of close/indirect */ + configure_count = exp_configure_count; + + /* count and validate state_list */ + mcount = 0; + for (slPtr=state_list;slPtr;slPtr=slPtr->next) { + mcount++; + /* validate all input descriptors */ + if (!expStateCheck(interp,slPtr->esPtr,1,1,"expect")) { + result = TCL_ERROR; + goto cleanup; + } + } + + /* make into an array */ + esPtrs = (ExpState **)ckalloc(mcount * sizeof(ExpState *)); + for (slPtr=state_list,i=0;slPtr;slPtr=slPtr->next,i++) { + esPtrs[i] = slPtr->esPtr; + } + + restart: + if (first_time) first_time = 0; + else { + Tcl_GetTime (&temp_time); + start_time = temp_time.sec; + } + + if (eg.timeout_specified_by_flag) { + timeout = eg.timeout; + } else { + /* get the latest timeout */ + timeout = get_timeout(interp); + } + + key = expect_key++; + + result = TCL_OK; + last_esPtr = 0; + + /* + * end of restart code + */ + + eo.e = 0; /* no final case yet */ + eo.esPtr = 0; /* no final ExpState selected yet */ + eo.matchlen = 0; /* nothing matched yet */ + + /* timeout code is a little tricky, be very careful changing it */ + if (timeout != EXP_TIME_INFINITY) { + /* if exp_continue -continue_timer, do not update end_time */ + if (reset_timer) { + Tcl_GetTime (&temp_time); + current_time = temp_time.sec; + end_time = current_time + timeout; + } else { + reset_timer = TRUE; + } + } + + /* remtime and current_time updated at bottom of loop */ + remtime = timeout; + + for (;;) { + if ((timeout != EXP_TIME_INFINITY) && (remtime < 0)) { + cc = EXP_TIMEOUT; + } else { + cc = expRead(interp,esPtrs,mcount,&esPtr,remtime,key); + } + + /*SUPPRESS 530*/ + if (cc == EXP_EOF) { + /* do nothing */ + } else if (cc == EXP_TIMEOUT) { + expDiagLogU("expect: timed out\r\n"); + } else if (cc == EXP_RECONFIGURE) { + reset_timer = FALSE; + goto restart_with_update; + } else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/ + goto error; + } else { + /* new data if cc > 0, same old data if cc == 0 */ + + /* below here, cc as general status */ + cc = EXP_NOMATCH; + + /* force redisplay of buffer when debugging */ + last_esPtr = 0; + } + + cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE], + esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,""); + cc = eval_cases(interp,&eg, + esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,""); + cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER], + esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,""); + if (cc == EXP_TCLERROR) goto error; + /* special eof code that cannot be done in eval_cases */ + /* or above, because it would then be executed several times */ + if (cc == EXP_EOF) { + eo.esPtr = esPtr; + eo.matchlen = expSizeGet(eo.esPtr); + eo.matchbuf = eo.esPtr->input.buffer; + expDiagLogU("expect: read eof\r\n"); + break; + } else if (cc == EXP_TIMEOUT) break; + + /* break if timeout or eof and failed to find a case for it */ + + if (eo.e) break; + + /* no match was made with current data, force a read */ + esPtr->force_read = TRUE; + + if (timeout != EXP_TIME_INFINITY) { + Tcl_GetTime (&temp_time); + current_time = temp_time.sec; + remtime = end_time - current_time; + } + } + + goto done; + +error: + result = exp_2tcl_returnvalue(cc); + done: + if (result != TCL_ERROR) { + result = expMatchProcess(interp, &eo, cc, 0 /* not bg */,"expect"); + } + + cleanup: + if (result == EXP_CONTINUE_TIMER) { + reset_timer = FALSE; + result = EXP_CONTINUE; + } + + if ((result == EXP_CONTINUE) && (configure_count == exp_configure_count)) { + expDiagLogU("expect: continuing expect\r\n"); + goto restart; + } + + if (state_list) { + exp_free_state(state_list); + state_list = 0; + } + if (esPtrs) { + ckfree((char *)esPtrs); + esPtrs = 0; + } + + if (result == EXP_CONTINUE) { + expDiagLogU("expect: continuing expect after update\r\n"); + goto restart_with_update; + } + + free_ecases(interp,&eg,0); /* requires i_lists to be avail */ + exp_free_i(interp,eg.i_list,exp_indirect_update2); + + if (new_cmd) { Tcl_DecrRefCount (new_cmd); } + return(result); +} + +/*ARGSUSED*/ +static int +Exp_TimestampObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + char *format = 0; + time_t seconds = -1; + int gmt = FALSE; /* local time by default */ + struct tm *tm; + Tcl_DString dstring; + int i; + + static char* options[] = { + "-format", + "-gmt", + "-seconds", + NULL + }; + enum options { + TS_FORMAT, + TS_GMT, + TS_SECONDS + }; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case TS_FORMAT: + i++; + if (i >= objc) goto usage_error; + format = Tcl_GetString (objv[i]); + break; + case TS_GMT: + gmt = TRUE; + break; + case TS_SECONDS: { + int sec; + i++; + if (i >= objc) goto usage_error; + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &sec)) { + goto usage_error; + } + seconds = sec; + } + break; + } + } + + if (i < objc) goto usage_error; + + if (seconds == -1) { + time(&seconds); + } + + if (format) { + if (gmt) { + tm = gmtime(&seconds); + } else { + tm = localtime(&seconds); + } + Tcl_DStringInit(&dstring); + exp_strftime(format,tm,&dstring); + Tcl_DStringResult(interp,&dstring); + } else { + Tcl_SetObjResult (interp, Tcl_NewIntObj (seconds)); + } + + return TCL_OK; + usage_error: + exp_error(interp,"args: [-seconds #] [-format format] [-gmt]"); + return TCL_ERROR; + +} + +/* Helper function hnadling the common processing of -d and -i options of + * various commands. + */ + +static int +process_di _ANSI_ARGS_ ((Tcl_Interp* interp, + int objc, + Tcl_Obj *CONST objv[], /* Argument objects. */ + int* at, + int* Default, + ExpState **esOut, + CONST char* cmd)); + +static int +process_di ( + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[], /* Argument objects. */ + int* at, + int* Default, + ExpState **esOut, + CONST char* cmd) +{ + static char* options[] = { + "-d", + "-i", + NULL + }; + enum options { + DI_DEFAULT, + DI_ID + }; + int def = FALSE; + char* chan = NULL; + int i; + ExpState *esPtr; + + for (i=1; i<objc; i++) { + char *name; + int index; + + name = Tcl_GetString(objv[i]); + if (name[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case DI_DEFAULT: + def = TRUE; + break; + case DI_ID: + i++; + if (i >= objc) { + exp_error(interp,"-i needs argument"); + return(TCL_ERROR); + } + chan = Tcl_GetString (objv[i]); + break; + } + } + + if (def && chan) { + exp_error(interp,"cannot do -d and -i at the same time"); + return(TCL_ERROR); + } + + /* Not all arguments processed, more than two remaining, only at most one + * remaining is expected/allowed. + */ + if (i < (objc-1)) { + exp_error(interp,"too many arguments"); + return(TCL_OK); + } + + if (!def) { + if (!chan) { + esPtr = expStateCurrent(interp,0,0,0); + } else { + esPtr = expStateFromChannelName(interp,chan,0,0,0,(char*)cmd); + } + if (!esPtr) return(TCL_ERROR); + } + + *at = i; + *Default = def; + *esOut = esPtr; + return TCL_OK; +} + + +/*ARGSUSED*/ +int +Exp_MatchMaxObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int size = -1; + ExpState *esPtr = 0; + int Default = FALSE; + int i; + + if (TCL_OK != process_di (interp, objc, objv, &i, &Default, &esPtr, "match_max")) + return TCL_ERROR; + + /* No size argument */ + if (i == objc) { + if (Default) { + size = exp_default_match_max; + } else { + size = esPtr->umsize; + } + Tcl_SetObjResult (interp, Tcl_NewIntObj (size)); + return(TCL_OK); + } + + /* + * All that's left is to set the size + */ + + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &size)) { + return TCL_ERROR; + } + + if (size <= 0) { + exp_error(interp,"must be positive"); + return(TCL_ERROR); + } + + if (Default) exp_default_match_max = size; + else esPtr->umsize = size; + + return(TCL_OK); +} + +/*ARGSUSED*/ +int +Exp_RemoveNullsObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int value = -1; + ExpState *esPtr = 0; + int Default = FALSE; + int i; + + if (TCL_OK != process_di (interp, objc, objv, &i, &Default, &esPtr, "remove_nulls")) + return TCL_ERROR; + + /* No flag argument */ + if (i == objc) { + if (Default) { + value = exp_default_rm_nulls; + } else { + value = esPtr->rm_nulls; + } + Tcl_SetObjResult (interp, Tcl_NewIntObj (value)); + return(TCL_OK); + } + + /* all that's left is to set the value */ + + if (TCL_OK != Tcl_GetBooleanFromObj (interp, objv[i], &value)) { + return TCL_ERROR; + } + + if ((value != 0) && (value != 1)) { + exp_error(interp,"must be 0 or 1"); + return(TCL_ERROR); + } + + if (Default) exp_default_rm_nulls = value; + else esPtr->rm_nulls = value; + + return(TCL_OK); +} + +/*ARGSUSED*/ +int +Exp_ParityObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int parity; + ExpState *esPtr = 0; + int Default = FALSE; + int i; + + if (TCL_OK != process_di (interp, objc, objv, &i, &Default, &esPtr, "parity")) + return TCL_ERROR; + + /* No parity argument */ + if (i == objc) { + if (Default) { + parity = exp_default_parity; + } else { + parity = esPtr->parity; + } + Tcl_SetObjResult (interp, Tcl_NewIntObj (parity)); + return(TCL_OK); + } + + /* all that's left is to set the parity */ + + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &parity)) { + return TCL_ERROR; + } + + if (Default) exp_default_parity = parity; + else esPtr->parity = parity; + + return(TCL_OK); +} + +/*ARGSUSED*/ +int +Exp_CloseOnEofObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + int close_on_eof; + ExpState *esPtr = 0; + int Default = FALSE; + int i; + + if (TCL_OK != process_di (interp, objc, objv, &i, &Default, &esPtr, "close_on_eof")) + return TCL_ERROR; + + /* No flag argument */ + if (i == objc) { + if (Default) { + close_on_eof = exp_default_close_on_eof; + } else { + close_on_eof = esPtr->close_on_eof; + } + Tcl_SetObjResult (interp, Tcl_NewIntObj (close_on_eof)); + return(TCL_OK); + } + + /* all that's left is to set the close_on_eof */ + + if (TCL_OK != Tcl_GetIntFromObj (interp, objv[i], &close_on_eof)) { + return TCL_ERROR; + } + + if (Default) exp_default_close_on_eof = close_on_eof; + else esPtr->close_on_eof = close_on_eof; + + return(TCL_OK); +} + +#if DEBUG_PERM_ECASES +/* This big chunk of code is just for debugging the permanent */ +/* expect cases */ +void +exp_fd_print(struct exp_state_list *slPtr) +{ + if (!slPtr) return; + printf("%d ",slPtr->esPtr); + exp_fd_print(slPtr->next); +} + +void +exp_i_print(struct exp_i *exp_i) +{ + if (!exp_i) return; + printf("exp_i %x",exp_i); + printf((exp_i->direct == EXP_DIRECT)?" direct":" indirect"); + printf((exp_i->duration == EXP_PERMANENT)?" perm":" tmp"); + printf(" ecount = %d\n",exp_i->ecount); + printf("variable %s, value %s\n", + ((exp_i->variable)?exp_i->variable:"--"), + ((exp_i->value)?exp_i->value:"--")); + printf("ExpStates: "); + exp_fd_print(exp_i->state_list); printf("\n"); + exp_i_print(exp_i->next); +} + +void +exp_ecase_print(struct ecase *ecase) +{ + printf("pat <%s>\n",ecase->pat); + printf("exp_i = %x\n",ecase->i_list); +} + +void +exp_ecases_print(struct exp_cases_descriptor *ecd) +{ + int i; + + printf("%d cases\n",ecd->count); + for (i=0;i<ecd->count;i++) exp_ecase_print(ecd->cases[i]); +} + +void +exp_cmd_print(struct exp_cmd_descriptor *ecmd) +{ + printf("expect cmd type: %17s",exp_cmdtype_printable(ecmd->cmdtype)); + printf((ecmd->duration==EXP_PERMANENT)?" perm ": "tmp "); + /* printdict */ + exp_ecases_print(&ecmd->ecd); + exp_i_print(ecmd->i_list); +} + +void +exp_cmds_print(void) +{ + exp_cmd_print(&exp_cmds[EXP_CMD_BEFORE]); + exp_cmd_print(&exp_cmds[EXP_CMD_AFTER]); + exp_cmd_print(&exp_cmds[EXP_CMD_BG]); +} + +/*ARGSUSED*/ +int +cmdX( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + exp_cmds_print(); + return TCL_OK; +} +#endif /*DEBUG_PERM_ECASES*/ + +void +expExpectVarsInit(void) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tsdPtr->timeout = INIT_EXPECT_TIMEOUT; +} + +static struct exp_cmd_data +cmd_data[] = { +{"expect", Exp_ExpectObjCmd, 0, (ClientData)0, 0}, +{"expect_after",Exp_ExpectGlobalObjCmd, 0, (ClientData)&exp_cmds[EXP_CMD_AFTER],0}, +{"expect_before",Exp_ExpectGlobalObjCmd,0, (ClientData)&exp_cmds[EXP_CMD_BEFORE],0}, +{"expect_user", Exp_ExpectObjCmd, 0, (ClientData)&StdinoutPlaceholder,0}, +{"expect_tty", Exp_ExpectObjCmd, 0, (ClientData)&DevttyPlaceholder,0}, +{"expect_background",Exp_ExpectGlobalObjCmd,0, (ClientData)&exp_cmds[EXP_CMD_BG],0}, + {"match_max", Exp_MatchMaxObjCmd, 0, (ClientData)0, 0}, + {"remove_nulls", Exp_RemoveNullsObjCmd, 0, (ClientData)0, 0}, + {"parity", Exp_ParityObjCmd, 0, (ClientData)0, 0}, + {"close_on_eof", Exp_CloseOnEofObjCmd, 0, (ClientData)0, 0}, + {"timestamp", Exp_TimestampObjCmd, 0, (ClientData)0, 0}, +{0}}; + +void +exp_init_expect_cmds(Tcl_Interp *interp) +{ + exp_create_commands(interp,cmd_data); + + Tcl_SetVar(interp,EXPECT_TIMEOUT,INIT_EXPECT_TIMEOUT_LIT,0); + + exp_cmd_init(&exp_cmds[EXP_CMD_BEFORE],EXP_CMD_BEFORE,EXP_PERMANENT); + exp_cmd_init(&exp_cmds[EXP_CMD_AFTER ],EXP_CMD_AFTER, EXP_PERMANENT); + exp_cmd_init(&exp_cmds[EXP_CMD_BG ],EXP_CMD_BG, EXP_PERMANENT); + exp_cmd_init(&exp_cmds[EXP_CMD_FG ],EXP_CMD_FG, EXP_TEMPORARY); + + /* preallocate to one element, so future realloc's work */ + exp_cmds[EXP_CMD_BEFORE].ecd.cases = 0; + exp_cmds[EXP_CMD_AFTER ].ecd.cases = 0; + exp_cmds[EXP_CMD_BG ].ecd.cases = 0; + + pattern_style[PAT_EOF] = "eof"; + pattern_style[PAT_TIMEOUT] = "timeout"; + pattern_style[PAT_DEFAULT] = "default"; + pattern_style[PAT_FULLBUFFER] = "full buffer"; + pattern_style[PAT_GLOB] = "glob pattern"; + pattern_style[PAT_RE] = "regular expression"; + pattern_style[PAT_EXACT] = "exact string"; + pattern_style[PAT_NULL] = "null"; + +#if 0 + Tcl_CreateObjCommand(interp,"x",cmdX,(ClientData)0,exp_deleteProc); +#endif +} + +void +exp_init_sig(void) { +#if 0 + signal(SIGALRM,sigalarm_handler); + signal(SIGINT,sigint_handler); +#endif +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/expect.h b/expect.h new file mode 100644 index 0000000..b1c185d --- /dev/null +++ b/expect.h @@ -0,0 +1,418 @@ +/* expect.h - include file for using the expect library, libexpect.a +from C or C++ (i.e., without Tcl) + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifndef _EXPECT_H +#define _EXPECT_H + +#include <stdio.h> +#include <setjmp.h> + +/* + * tcl.h -- + * + * This header file describes the externally-visible facilities + * of the Tcl interpreter. + * + * Copyright (c) 1987-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1993-1996 Lucent Technologies. + * Copyright (c) 1998-1999 Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: expect.h,v 5.33 2010/08/31 22:20:27 andreas_kupries Exp $ + */ + +#ifndef _TCL +#define _TCL + +#ifndef __WIN32__ +# if defined(_WIN32) || defined(WIN32) +# define __WIN32__ +# endif +#endif + +#ifdef __WIN32__ +# ifndef STRICT +# define STRICT +# endif +# ifndef USE_PROTOTYPE +# define USE_PROTOTYPE 1 +# endif +# ifndef HAS_STDARG +# define HAS_STDARG 1 +# endif +# ifndef USE_PROTOTYPE +# define USE_PROTOTYPE 1 +# endif + +/* + * Under Windows we need to call Tcl_Alloc in all cases to avoid competing + * C run-time library issues. + */ + +# ifndef USE_TCLALLOC +# define USE_TCLALLOC 1 +# endif +#endif /* __WIN32__ */ + +/* + * The following definitions set up the proper options for Macintosh + * compilers. We use this method because there is no autoconf equivalent. + */ + +#ifdef MAC_TCL +# ifndef HAS_STDARG +# define HAS_STDARG 1 +# endif +# ifndef USE_TCLALLOC +# define USE_TCLALLOC 1 +# endif +# ifndef NO_STRERROR +# define NO_STRERROR 1 +# endif +#endif + +/* + * Utility macros: STRINGIFY takes an argument and wraps it in "" (double + * quotation marks), JOIN joins two arguments. + */ + +#define VERBATIM(x) x +#ifdef _MSC_VER +# define STRINGIFY(x) STRINGIFY1(x) +# define STRINGIFY1(x) #x +# define JOIN(a,b) JOIN1(a,b) +# define JOIN1(a,b) a##b +#else +# ifdef RESOURCE_INCLUDED +# define STRINGIFY(x) STRINGIFY1(x) +# define STRINGIFY1(x) #x +# define JOIN(a,b) JOIN1(a,b) +# define JOIN1(a,b) a##b +# else +# ifdef __STDC__ +# define STRINGIFY(x) #x +# define JOIN(a,b) a##b +# else +# define STRINGIFY(x) "x" +# define JOIN(a,b) VERBATIM(a)VERBATIM(b) +# endif +# endif +#endif + +/* + * A special definition used to allow this header file to be included + * in resource files so that they can get obtain version information from + * this file. Resource compilers don't like all the C stuff, like typedefs + * and procedure declarations, that occur below. + */ + +#ifndef RESOURCE_INCLUDED + +#ifndef BUFSIZ +#include <stdio.h> +#endif + +/* + * Definitions that allow Tcl functions with variable numbers of + * arguments to be used with either varargs.h or stdarg.h. TCL_VARARGS + * is used in procedure prototypes. TCL_VARARGS_DEF is used to declare + * the arguments in a function definiton: it takes the type and name of + * the first argument and supplies the appropriate argument declaration + * string for use in the function definition. TCL_VARARGS_START + * initializes the va_list data structure and returns the first argument. + */ + +#if defined(__STDC__) || defined(HAS_STDARG) +# include <stdarg.h> + +# define TCL_VARARGS(type, name) (type name, ...) +# define TCL_VARARGS_DEF(type, name) (type name, ...) +# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name) +#else +# include <varargs.h> + +# ifdef __cplusplus +# define TCL_VARARGS(type, name) (type name, ...) +# define TCL_VARARGS_DEF(type, name) (type va_alist, ...) +# else +# define TCL_VARARGS(type, name) () +# define TCL_VARARGS_DEF(type, name) (va_alist) +# endif +# define TCL_VARARGS_START(type, name, list) \ + (va_start(list), va_arg(list, type)) +#endif + +/* + * Macros used to declare a function to be exported by a DLL. + * Used by Windows, maps to no-op declarations on non-Windows systems. + * The default build on windows is for a DLL, which causes the DLLIMPORT + * and DLLEXPORT macros to be nonempty. To build a static library, the + * macro STATIC_BUILD should be defined. + */ + +#ifdef STATIC_BUILD +# define DLLIMPORT +# define DLLEXPORT +#else +# if defined(__WIN32__) && (defined(_MSC_VER) || (defined(__GNUC__) && defined(__declspec))) +# define DLLIMPORT __declspec(dllimport) +# define DLLEXPORT __declspec(dllexport) +# else +# define DLLIMPORT +# define DLLEXPORT +# endif +#endif + +/* + * These macros are used to control whether functions are being declared for + * import or export. If a function is being declared while it is being built + * to be included in a shared library, then it should have the DLLEXPORT + * storage class. If is being declared for use by a module that is going to + * link against the shared library, then it should have the DLLIMPORT storage + * class. If the symbol is beind declared for a static build or for use from a + * stub library, then the storage class should be empty. + * + * The convention is that a macro called BUILD_xxxx, where xxxx is the + * name of a library we are building, is set on the compile line for sources + * that are to be placed in the library. When this macro is set, the + * storage class will be set to DLLEXPORT. At the end of the header file, the + * storage class will be reset to DLLIMPORt. + */ + +#undef TCL_STORAGE_CLASS +#ifdef BUILD_tcl +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifdef USE_TCL_STUBS +# define TCL_STORAGE_CLASS +# else +# define TCL_STORAGE_CLASS DLLIMPORT +# endif +#endif + +/* + * Definitions that allow this header file to be used either with or + * without ANSI C features like function prototypes. */ + +#undef _ANSI_ARGS_ +#undef CONST + +#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE) +# define _USING_PROTOTYPES_ 1 +# define _ANSI_ARGS_(x) x +# define CONST const +#else +# define _ANSI_ARGS_(x) () +# define CONST +#endif + +#ifdef __cplusplus +# define EXTERN extern "C" TCL_STORAGE_CLASS +#else +# define EXTERN extern TCL_STORAGE_CLASS +#endif + +/* + * Macro to use instead of "void" for arguments that must have + * type "void *" in ANSI C; maps them to type "char *" in + * non-ANSI systems. + */ +#ifndef __WIN32__ +#ifndef VOID +# ifdef __STDC__ +# define VOID void +# else +# define VOID char +# endif +#endif +#else /* __WIN32__ */ +/* + * The following code is copied from winnt.h + */ +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +#endif +#endif /* __WIN32__ */ + +/* + * Miscellaneous declarations. + */ + +#ifndef NULL +#define NULL 0 +#endif + +typedef struct Tcl_RegExp_ *Tcl_RegExp; + +/* + * These function have been renamed. The old names are deprecated, but we + * define these macros for backwards compatibilty. + */ + +#define Tcl_Ckalloc Tcl_Alloc +#define Tcl_Ckfree Tcl_Free +#define Tcl_Ckrealloc Tcl_Realloc +#define Tcl_Return Tcl_SetResult +#define Tcl_TildeSubst Tcl_TranslateFileName + +#endif /* RESOURCE_INCLUDED */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TCL */ + +/* + * end of tcl.h definitions + */ + + +/* + * regexp definitions - from tcl8.0/tclRegexp.h + */ + +/* + * Definitions etc. for regexp(3) routines. + * + * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], + * not the System V one. + * + * RCS: @(#) $Id: expect.h,v 5.33 2010/08/31 22:20:27 andreas_kupries Exp $ + */ + +#ifndef _REGEXP +#define _REGEXP 1 + +#ifdef BUILD_tcl +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * NSUBEXP must be at least 10, and no greater than 117 or the parser + * will not work properly. + */ + +#define NSUBEXP 20 + +typedef struct regexp { + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; + char regstart; /* Internal use only. */ + char reganch; /* Internal use only. */ + char *regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + char program[1]; /* Unwarranted chumminess with compiler. */ +} regexp; + +EXTERN regexp *TclRegComp _ANSI_ARGS_((char *exp)); +EXTERN int TclRegExec _ANSI_ARGS_((regexp *prog, char *string, char *start)); +EXTERN void TclRegSub _ANSI_ARGS_((regexp *prog, char *source, char *dest)); +EXTERN void exp_TclRegError _ANSI_ARGS_((char *msg)); +EXTERN char *TclGetRegError _ANSI_ARGS_((void)); + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* REGEXP */ + + +/* + * end of regexp definitions + */ + + +/* + * finally - expect-specific definitions + */ + +#include "expect_comm.h" + +enum exp_type { + exp_end = 0, /* placeholder - no more cases */ + exp_glob, /* glob-style */ + exp_exact, /* exact string */ + exp_regexp, /* regexp-style, uncompiled */ + exp_compiled, /* regexp-style, compiled */ + exp_null, /* matches binary 0 */ + exp_bogus /* aid in reporting compatibility problems */ +}; + +struct exp_case { /* case for expect command */ + char *pattern; + regexp *re; + enum exp_type type; + int value; /* value to be returned upon match */ +}; + +EXTERN char *exp_buffer; /* buffer of matchable chars */ +EXTERN char *exp_buffer_end; /* one beyond end of matchable chars */ +EXTERN char *exp_match; /* start of matched string */ +EXTERN char *exp_match_end; /* one beyond end of matched string */ +EXTERN int exp_match_max; /* bytes */ +EXTERN int exp_timeout; /* seconds */ +EXTERN int exp_full_buffer; /* if true, return on full buffer */ +EXTERN int exp_remove_nulls; /* if true, remove nulls */ + +EXTERN int exp_pty_timeout; /* see Cray hooks in source */ +EXTERN int exp_pid; /* process-id of spawned process */ +EXTERN int exp_autoallocpty; /* if TRUE, we do allocation */ +EXTERN int exp_pty[2]; /* master is [0], slave is [1] */ +EXTERN char *exp_pty_slave_name; /* name of pty slave device if we */ + /* do allocation */ +EXTERN char *exp_stty_init; /* initial stty args */ +EXTERN int exp_ttycopy; /* copy tty parms from /dev/tty */ +EXTERN int exp_ttyinit; /* set tty parms to sane state */ +EXTERN int exp_console; /* redirect console */ + +#ifdef HAVE_SIGLONGJMP +EXTERN sigjmp_buf exp_readenv; /* for interruptable read() */ +#else +EXTERN jmp_buf exp_readenv; /* for interruptable read() */ +#endif /* HAVE_SIGLONGJMP */ + +EXTERN int exp_reading; /* whether we can longjmp or not */ +#define EXP_ABORT 1 /* abort read */ +#define EXP_RESTART 2 /* restart read */ + +EXTERN int exp_is_debugging; +EXTERN int exp_loguser; + +EXTERN void (*exp_close_in_child)(); /* procedure to close files in child */ +EXTERN void exp_slave_control _ANSI_ARGS_((int,int)); +EXTERN int exp_logfile_all; +EXTERN FILE *exp_debugfile; +EXTERN FILE *exp_logfile; +extern void exp_debuglog _ANSI_ARGS_(TCL_VARARGS(char *,fmt)); +extern void exp_errorlog _ANSI_ARGS_(TCL_VARARGS(char *,fmt)); + +EXTERN int exp_disconnect _ANSI_ARGS_((void)); +EXTERN FILE *exp_popen _ANSI_ARGS_((char *command)); +EXTERN void (*exp_child_exec_prelude) _ANSI_ARGS_((void)); + +#ifndef EXP_DEFINE_FNS +EXTERN int exp_spawnl _ANSI_ARGS_(TCL_VARARGS(char *,file)); +EXTERN int exp_expectl _ANSI_ARGS_(TCL_VARARGS(int,fd)); +EXTERN int exp_fexpectl _ANSI_ARGS_(TCL_VARARGS(FILE *,fp)); +#endif + +EXTERN int exp_spawnv _ANSI_ARGS_((char *file, char *argv[])); +EXTERN int exp_expectv _ANSI_ARGS_((int fd, struct exp_case *cases)); +EXTERN int exp_fexpectv _ANSI_ARGS_((FILE *fp, struct exp_case *cases)); + +EXTERN int exp_spawnfd _ANSI_ARGS_((int fd)); + +#endif /* _EXPECT_H */ diff --git a/expect.man b/expect.man new file mode 100644 index 0000000..1ac0c3f --- /dev/null +++ b/expect.man @@ -0,0 +1,2613 @@ +.TH EXPECT 1 "29 December 1994" +.SH NAME +expect \- programmed dialogue with interactive programs, Version 5 +.SH SYNOPSIS +.B expect +[ +.B \-dDinN +] +[ +.B \-c +.I cmds +] +[ +[ +.BR \- [ f | b ] +] +.I cmdfile +] +[ +.I args +] +.SH INTRODUCTION +.B Expect +is a program that "talks" to other interactive programs according to a +script. Following the script, +.B Expect +knows what can be expected from +a program and what the correct response should be. An interpreted +language provides branching and high-level control structures to +direct the dialogue. In addition, the user can take control +and interact directly when desired, afterward returning control to the +script. +.PP +.B Expectk +is a mixture of +.B Expect +and +.BR Tk . +It behaves just like +.B Expect +and +.BR Tk 's +.BR wish . +.B Expect +can also be used directly in C or C++ (that is, without Tcl). +See libexpect(3). +.PP +The name "Expect" comes from the idea of +.I send/expect +sequences popularized +by uucp, kermit and other modem control programs. +However unlike uucp, +.B Expect +is generalized so that it can be run as a user-level command +with any program and task in mind. +.B Expect +can actually talk to several programs at the same time. +.PP +For example, here are some things +.B Expect +can do: +.RS +.TP 4 +\(bu +Cause your computer to dial you back, +so that you can login without paying for the call. +.TP +\(bu +Start a game (e.g., rogue) and if the optimal configuration doesn't appear, +restart it (again and again) until it does, +then hand over control to you. +.TP +\(bu +Run fsck, and in response to its questions, answer "yes", "no" or give control back to you, +based on predetermined criteria. +.TP +\(bu +Connect to another network or BBS (e.g., MCI Mail, CompuServe) and +automatically retrieve your mail so that it appears as if +it was originally sent to your local system. +.TP +\(bu +Carry environment variables, current directory, +or any kind of information across rlogin, telnet, tip, su, chgrp, etc. +.RE +.PP +There are a variety of reasons why the shell cannot perform these tasks. +(Try, you'll see.) +All are possible with +.BR Expect . +.PP +In general, +.B Expect +is useful for running any program which requires +interaction between the program and the user. +All that is necessary is that the interaction can be characterized +programmatically. +.B Expect +can also give the user back control +(without halting the program being controlled) if desired. +Similarly, the user can return control to the script at any time. +.SH USAGE +.B Expect +reads +.I cmdfile +for a list of commands to execute. +.B Expect +may also be invoked implicitly on systems which support the #! notation +by marking the script executable, and making the first line in your script: + + #!/usr/local/bin/expect \-f + +Of course, the path must accurately describe where +.B Expect +lives. /usr/local/bin is just an example. + +The +.B \-c +flag prefaces a command to be executed before any in the script. +The command should be quoted to prevent being broken up by the shell. +This option may be used multiple times. +Multiple commands may be +executed with a single +.B \-c +by separating them with semicolons. +Commands are executed in the order they appear. +(When using Expectk, this option is specified as +.BR \-command .) +.PP +The +.B \-d +flag enables some diagnostic output, which +primarily reports internal activity of commands such as +.B expect +and +.BR interact . +This flag has the same effect as "exp_internal 1" at the beginning of an Expect +script, plus the version of +.B Expect +is printed. +(The +.B strace +command is useful for tracing statements, and the +.B trace +command is useful for tracing variable assignments.) +(When using Expectk, this option is specified as +.BR \-diag .) +.PP +The +.B \-D +flag enables an interactive debugger. An integer value should follow. +The debugger will take control before the next Tcl procedure +if the value is non-zero +or if a ^C is pressed (or a breakpoint is hit, or other appropriate debugger +command appears in the script). See the README file or SEE ALSO (below) +for more information on the debugger. +(When using Expectk, this option is specified as +.BR \-Debug .) +.PP +The +.B \-f +flag prefaces a file from which to read commands from. +The flag itself is optional as it is only useful when using +the #! notation (see above), +so that other arguments may be supplied on the command line. +(When using Expectk, this option is specified as +.BR \-file .) +.PP +By default, the command file is read into memory and executed in its entirety. +It is occasionally desirable to read files one line at a time. For example, +stdin is read this way. In order to force arbitrary files to be handled this +way, use the +.B \-b +flag. +(When using Expectk, this option is specified as +.BR \-buffer .) Note that stdio-buffering may still take place however this shouldn't cause problems when reading from a fifo or stdin. +.PP +If the string "\-" is supplied as a filename, standard input is read instead. +(Use "./\-" to read from a file actually named "\-".) +.PP +The +.B \-i +flag causes +.B Expect +to interactively prompt for commands instead of reading +them from a file. +Prompting is terminated via the +.B exit +command or upon EOF. +See +.B interpreter +(below) for more information. +.B \-i +is assumed if neither a command file nor +.B \-c +is used. +(When using Expectk, this option is specified as +.BR \-interactive .) +.PP +.B \-\- +may be used to delimit the end of the options. This is useful if +you want to pass an option-like argument to your script without it being +interpreted by +.BR Expect . +This can usefully be placed in the #! line to prevent any flag-like +interpretation by Expect. For example, the following will leave the +original arguments (including the script name) in the variable +.IR argv . + + #!/usr/local/bin/expect \-\- + +Note that the usual getopt(3) and execve(2) conventions must be observed +when adding arguments to the #! line. +.PP +The file $exp_library/expect.rc is sourced automatically if present, unless +the +.B \-N +flag is used. +(When using Expectk, this option is specified as +.BR \-NORC .) +Immediately after this, +the file ~/.expect.rc is sourced automatically, unless the +.B \-n +flag is used. If the environment variable DOTDIR is defined, +it is treated as a directory and .expect.rc is read from there. +(When using Expectk, this option is specified as +.BR \-norc .) +This sourcing occurs only after executing any +.B \-c +flags. +.PP +.B \-v +causes Expect to print its version number and exit. (The corresponding flag +in Expectk, which uses long flag names, is \-version.) +.PP +Optional +.I args +are constructed into a list and stored in the variable named +.IR argv . +.I argc +is initialized to the length of argv. +.PP +.I argv0 +is defined to be the name of the script (or binary if no script is used). +For example, +the following prints out the name of the script and the first three arguments: +.nf + + send_user "$argv0 [lrange $argv 0 2]\\n" + +.fi +.SH COMMANDS +.B Expect +uses +.I Tcl +(Tool Command Language). +Tcl provides control flow (e.g., if, for, break), +expression evaluation and several other features such as recursion, +procedure definition, etc. +Commands used here but not defined (e.g., +.BR set , +.BR if , +.BR exec ) +are Tcl commands (see tcl(3)). +.B Expect +supports additional commands, described below. +Unless otherwise specified, commands return the empty string. +.PP +Commands are listed alphabetically so that they can be quickly located. +However, new users may find it easier to start by reading the descriptions +of +.BR spawn , +.BR send , +.BR expect , +and +.BR interact , +in that order. + +Note that the best introduction to the language (both Expect and Tcl) +is provided in the book "Exploring Expect" (see SEE ALSO below). +Examples are included in this man page but they are very limited since +this man page is meant primarily as reference material. + +Note that in the text of this man page, "Expect" with an uppercase "E" +refers to the +.B Expect +program while "expect" with a lower-case "e" refers to the +.B expect +command within the +.B Expect +program.) +.I +.TP 6 +.BI close " [-slave] [\-onexec 0|1] [\-i spawn_id]" +closes the connection to the current process. +Most interactive programs will detect EOF on their stdin and exit; +thus +.B close +usually suffices to kill the process as well. +The +.B \-i +flag declares the process to close corresponding to the named spawn_id. + +Both +.B expect +and +.B interact +will detect when the current process exits and implicitly do a +.BR close . +But if you kill the process by, say, "exec kill $pid", +you will need to explicitly call +.BR close . + +The +.BR \-onexec +flag determines whether the spawn id will be closed in any new spawned +processes or if the process is overlayed. To leave a spawn id open, +use the value 0. A non-zero integer value will force the spawn closed +(the default) in any new processes. + +The +.B \-slave +flag closes the slave associated with the spawn id. (See "spawn -pty".) +When the connection is closed, the slave is automatically closed as +well if still open. + +No matter whether the connection is closed implicitly or explicitly, +you should call +.B wait +to clear up the corresponding kernel process slot. +.B close +does not call +.B wait +since there is no guarantee that closing a process connection will cause +it to exit. +See +.B wait +below for more info. +.TP +.BI debug " [[-now] 0|1]" +controls a Tcl debugger allowing you to step through statements, set +breakpoints, etc. + +With no arguments, a 1 is returned if the debugger is not running, otherwise +a 0 is returned. + +With a 1 argument, the debugger is started. With a 0 argument, the +debugger is stopped. If a 1 argument is preceded by the +.B \-now +flag, the debugger is started immediately (i.e., in the middle of the +.B debug +command itself). Otherwise, the debugger is started with the next +Tcl statement. + +The +.B debug +command does not change any traps. Compare this to starting Expect with the +.B -D +flag (see above). + +See the README file or SEE ALSO (below) +for more information on the debugger. +.TP +.B disconnect +disconnects a forked process from the terminal. It continues running in the +background. The process is given its own process group (if possible). +Standard I/O is redirected to /dev/null. +.IP +The following fragment uses +.B disconnect +to continue running the script in the background. +.nf + + if {[fork]!=0} exit + disconnect + . . . + +.fi +The following script reads a password, and then runs a program +every hour that demands a password each time it is run. The script supplies +the password so that you only have to type it once. +(See the +.B stty +command which demonstrates how to turn off password echoing.) +.nf + + send_user "password?\\ " + expect_user -re "(.*)\\n" + for {} 1 {} { + if {[fork]!=0} {sleep 3600;continue} + disconnect + spawn priv_prog + expect Password: + send "$expect_out(1,string)\\r" + . . . + exit + } + +.fi +An advantage to using +.B disconnect +over the shell asynchronous process feature (&) is that +.B Expect +can +save the terminal parameters prior to disconnection, and then later +apply them to new ptys. With &, +.B Expect +does not have a chance +to read the terminal's parameters since the terminal is already +disconnected by the time +.B Expect +receives control. +.TP +.BI exit " [\-opts] [status]" +causes +.B Expect +to exit or otherwise prepare to do so. + +The +.B \-onexit +flag causes the next argument to be used as an exit handler. +Without an argument, the current exit handler is returned. + +The +.B \-noexit +flag causes +.B Expect +to prepare to exit but stop short of actually returning control to the +operating system. The user-defined exit handler is run as well as Expect's +own internal handlers. +No further Expect commands should be executed. +This is useful if you are running Expect with other Tcl extensions. +The current interpreter (and main window if in the Tk environment) remain +so that other Tcl extensions can clean up. If Expect's +.B exit +is called again (however this might occur), the handlers are not rerun. + +Upon exiting, +all connections to spawned processes are closed. Closure will be detected +as an EOF by spawned processes. +.B exit +takes no other actions beyond what the normal _exit(2) procedure does. +Thus, spawned processes that do not check for EOF may continue to run. +(A variety of conditions are important to determining, for example, what +signals a spawned process will be sent, but these are system-dependent, +typically documented under exit(3).) +Spawned processes that continue to run will be inherited by init. + +.I status +(or 0 if not specified) is returned as the exit status of +.BR Expect . +.B exit +is implicitly executed if the end of the script is reached. +.TP +\fBexp_continue\fR [-continue_timer] +The command +.B exp_continue +allows +.B expect +itself to continue +executing rather than returning as it normally would. By +default +.B exp_continue +resets the timeout timer. The +.I -continue_timer +flag prevents timer from being restarted. (See +.B expect +for more information.) +.TP +.BI exp_internal " [\-f file] value" +causes further commands to send diagnostic information internal to +.B Expect +to stderr if +.I value +is non-zero. This output is disabled if +.I value +is 0. The diagnostic information includes every character received, +and every attempt made to match the current output against the patterns. +.IP +If the optional +.I file +is supplied, all normal and debugging output is written to that file +(regardless of the value of +.IR value ). +Any previous diagnostic output file is closed. + +The +.B \-info +flag causes exp_internal to return a description of the +most recent non-info arguments given. +.TP +.BI exp_open " [args] [\-i spawn_id]" +returns a Tcl file identifier that corresponds to the original spawn id. +The file identifier can then be used as if it were opened by Tcl's +.B open +command. (The spawn id should no longer be used. A +.B wait +should not be executed. + +The +.B \-leaveopen +flag leaves the spawn id open for access through +Expect commands. A +.B wait +must be executed on the spawn id. +.TP +.BI exp_pid " [\-i spawn_id]" +returns the process id corresponding to the currently spawned process. +If the +.B \-i +flag is used, the pid returned corresponds to that of the given spawn id. +.TP +.B exp_send +is an alias for +.BR send . +.TP +.B exp_send_error +is an alias for +.BR send_error . +.TP +.B exp_send_log +is an alias for +.BR send_log . +.TP +.B exp_send_tty +is an alias for +.BR send_tty . +.TP +.B exp_send_user +is an alias for +.BR send_user . +.TP +.BI exp_version " [[\-exit] version]" +is useful for assuring that the script is compatible with the current +version of Expect. +.IP +With no arguments, the current version of +.B Expect +is returned. This version +may then be encoded in your script. If you actually know that you are not +using features of recent versions, you can specify an earlier version. +.IP +Versions consist of three numbers separated by dots. First +is the major number. Scripts written for versions of +.B Expect +with a +different major number will almost certainly not work. +.B exp_version +returns an error if the major numbers do not match. +.IP +Second is the minor number. Scripts written for a version with a +greater minor number than the current version +may depend upon some new feature and might not run. +.B exp_version +returns an error if the major numbers match, but the script minor number +is greater than that of the running +.BR Expect . +.IP +Third is a number that plays no part in the version comparison. +However, it is incremented when the +.B Expect +software +distribution is changed in any way, such as by additional documentation +or optimization. It is reset to 0 upon each new minor version. +.IP +With the +.B \-exit +flag, +.B Expect +prints an error and exits if the version is out of date. +.TP +.BI expect " [[\-opts] pat1 body1] ... [\-opts] patn [bodyn]" +waits until one of the patterns matches the output of a spawned process, +a specified time period has passed, or an end-of-file is seen. +If the final body is empty, it may be omitted. +.IP +Patterns from the most recent +.B expect_before +command are implicitly used before any other patterns. +Patterns from the most recent +.B expect_after +command are implicitly used after any other patterns. +.IP +If the arguments to the entire +.B expect +statement require more than one line, +all the arguments may be "braced" into one so as to avoid terminating each +line with a backslash. In this one case, the usual Tcl substitutions will +occur despite the braces. +.IP +If a pattern is the keyword +.BR eof , +the corresponding body is executed upon end-of-file. +If a pattern is the keyword +.BR timeout , +the corresponding body is executed upon timeout. If no timeout keyword +is used, an implicit null action is executed upon timeout. +The default timeout period is 10 seconds but may be set, for example to 30, +by the command "set timeout 30". An infinite timeout may be designated +by the value \-1. +If a pattern is the keyword +.BR default , +the corresponding body is executed upon either timeout or end-of-file. +.IP +If a pattern matches, then the corresponding body is executed. +.B expect +returns the result of the body (or the empty string if no pattern matched). +In the event that multiple patterns match, the one appearing first is +used to select a body. +.IP +Each time new output arrives, it is compared to each pattern in the order +they are listed. Thus, you may test for absence of a match by making +the last pattern something guaranteed to appear, such as a prompt. +In situations where there is no prompt, you must use +.B timeout +(just like you would if you were interacting manually). +.IP +Patterns are specified in three ways. By default, +patterns are specified as with Tcl's +.B string match +command. (Such patterns are also similar to C-shell regular expressions +usually referred to as "glob" patterns). The +.B \-gl +flag may may +be used to protect patterns that might otherwise match +.B expect +flags from doing so. +Any pattern beginning with a "-" should be protected this way. (All strings +starting with "-" are reserved for future options.) + +.IP +For example, the following fragment looks for a successful login. +(Note that +.B abort +is presumed to be a procedure defined elsewhere in the script.) +.nf + +.ta \w' expect 'u +\w'invalid password 'u + expect { + busy {puts busy\\n ; exp_continue} + failed abort + "invalid password" abort + timeout abort + connected + } + +.fi +Quotes are necessary on the fourth pattern since it contains a space, which +would otherwise separate the pattern from the action. +Patterns with the same action (such as the 3rd and 4th) require listing the +actions again. This can be avoid by using regexp-style patterns (see below). +More information on forming glob-style patterns can be found in the Tcl manual. +.IP +Regexp-style patterns follow the syntax defined by Tcl's +.B regexp +(short for "regular expression") command. +regexp patterns are introduced with the flag +.BR \-re . +The previous example can be rewritten using a regexp as: +.nf + +.ta \w' expect 'u +\w'connected 'u + expect { + busy {puts busy\\n ; exp_continue} + \-re "failed|invalid password" abort + timeout abort + connected + } + +.fi +Both types of patterns are "unanchored". This means that patterns +do not have to match the entire string, but can begin and end the +match anywhere in the string (as long as everything else matches). +Use ^ to match the beginning of a string, and $ to match the end. +Note that if you do not wait for the end of a string, your responses +can easily end up in the middle of the string as they are echoed from +the spawned process. While still producing correct results, the output +can look unnatural. Thus, use of $ is encouraged if you can exactly +describe the characters at the end of a string. + +Note that in many editors, the ^ and $ match the beginning and end of +lines respectively. However, because expect is not line oriented, +these characters match the beginning and end of the data (as opposed +to lines) currently in the expect matching buffer. (Also, see the +note below on "system indigestion.") + +The +.B \-ex +flag causes the pattern to be matched as an "exact" string. No +interpretation of *, ^, etc is made (although the usual Tcl +conventions must still be observed). +Exact patterns are always unanchored. + +.IP +The +.B \-nocase +flag causes uppercase characters of the output to compare as if they were +lowercase characters. The pattern is not affected. +.IP +While reading output, +more than 2000 bytes can force earlier bytes to be "forgotten". +This may be changed with the function +.BR match_max . +(Note that excessively large values can slow down the pattern matcher.) +If +.I patlist +is +.BR full_buffer , +the corresponding body is executed if +.I match_max +bytes have been received and no other patterns have matched. +Whether or not the +.B full_buffer +keyword is used, the forgotten characters are written to +expect_out(buffer). + +If +.I patlist +is the keyword +.BR null , +and nulls are allowed (via the +.B remove_nulls +command), the corresponding body is executed if a single ASCII +0 is matched. +It is not possible to +match 0 bytes via glob or regexp patterns. + +Upon matching a pattern (or eof or full_buffer), +any matching and previously unmatched output is saved in the variable +.IR expect_out(buffer) . +Up to 9 regexp substring matches are saved in the variables +.I expect_out(1,string) +through +.IR expect_out(9,string) . +If the +.B -indices +flag is used before a pattern, +the starting and ending indices (in a form suitable for +.BR lrange ) +of the +10 strings are stored in the variables +.I expect_out(X,start) +and +.I expect_out(X,end) +where X is a digit, corresponds to the substring position in the buffer. +0 refers to strings which matched the entire pattern +and is generated for glob patterns as well as regexp patterns. +For example, if a process has produced output of "abcdefgh\\n", the result of: +.nf + + expect "cd" + +.fi +is as if the following statements had executed: +.nf + + set expect_out(0,string) cd + set expect_out(buffer) abcd + +.fi +and "efgh\\n" is left in the output buffer. +If a process produced the output "abbbcabkkkka\\n", the result of: +.nf + + expect \-indices \-re "b(b*).*(k+)" + +.fi +is as if the following statements had executed: +.nf + + set expect_out(0,start) 1 + set expect_out(0,end) 10 + set expect_out(0,string) bbbcabkkkk + set expect_out(1,start) 2 + set expect_out(1,end) 3 + set expect_out(1,string) bb + set expect_out(2,start) 10 + set expect_out(2,end) 10 + set expect_out(2,string) k + set expect_out(buffer) abbbcabkkkk + +.fi +and "a\\n" is left in the output buffer. The pattern "*" (and -re ".*") will +flush the output buffer without reading any more output from the +process. +.IP +Normally, the matched output is discarded from Expect's internal buffers. +This may be prevented by prefixing a pattern with the +.B \-notransfer +flag. This flag is especially useful in experimenting (and can be +abbreviated to "-not" for convenience while experimenting). + +The spawn id associated with the matching output (or eof or +full_buffer) is stored in +.IR expect_out(spawn_id) . + +The +.B \-timeout +flag causes the current expect command to use the following value +as a timeout instead of using the value of the timeout variable. + +By default, +patterns are matched against output from the current process, however the +.B \-i +flag declares the output from the named spawn_id list be matched against +any following patterns (up to the next +.BR \-i ). +The spawn_id list should either be a whitespace separated list of spawn_ids +or a variable referring to such a list of spawn_ids. + +For example, the following example waits for +"connected" from the current process, or "busy", "failed" or "invalid +password" from the spawn_id named by $proc2. +.nf + + expect { + \-i $proc2 busy {puts busy\\n ; exp_continue} + \-re "failed|invalid password" abort + timeout abort + connected + } + +.fi +The value of the global variable +.I any_spawn_id +may be used to match patterns to any spawn_ids that are named +with all other +.B \-i +flags in the current +.B expect +command. +The spawn_id from a +.B \-i +flag with no associated pattern (i.e., followed immediately +by another +.BR \-i ) +is made available to any other patterns +in the same +.B expect +command associated with +.I any_spawn_id. + +The +.B \-i +flag may also name a global variable in which case the variable is read +for a list of spawn ids. The variable is reread whenever it changes. +This provides a way of changing the I/O source while the command is in +execution. Spawn ids provided this way are called "indirect" spawn ids. + +Actions such as +.B break +and +.B continue +cause control structures (i.e., +.BR for , +.BR proc ) +to behave in the usual way. +The command +.B exp_continue +allows +.B expect +itself to continue +executing rather than returning as it normally would. +.IP +This is useful for avoiding explicit loops or repeated expect statements. +The following example is part of a fragment to automate rlogin. The +.B exp_continue +avoids having to write a second +.B expect +statement (to look for the prompt again) if the rlogin prompts for a password. +.nf + + expect { + Password: { + stty -echo + send_user "password (for $user) on $host: " + expect_user -re "(.*)\\n" + send_user "\\n" + send "$expect_out(1,string)\\r" + stty echo + exp_continue + } incorrect { + send_user "invalid password or account\\n" + exit + } timeout { + send_user "connection to $host timed out\\n" + exit + } eof { + send_user \\ + "connection to host failed: $expect_out(buffer)" + exit + } -re $prompt + } + +.fi +For example, the following fragment might help a user guide +an interaction that is already totally automated. In this case, the terminal +is put into raw mode. If the user presses "+", a variable is incremented. +If "p" is pressed, several returns are sent to the process, +perhaps to poke it in some way, and "i" lets the user interact with the +process, effectively stealing away control from the script. +In each case, the +.B exp_continue +allows the current +.B expect +to continue pattern matching after executing the +current action. +.nf + + stty raw \-echo + expect_after { + \-i $user_spawn_id + "p" {send "\\r\\r\\r"; exp_continue} + "+" {incr foo; exp_continue} + "i" {interact; exp_continue} + "quit" exit + } + +.fi +.IP +By default, +.B exp_continue +resets the timeout timer. The timer is not restarted, if +.B exp_continue +is called with the +.B \-continue_timer +flag. +.TP +.BI expect_after " [expect_args]" +works identically to the +.B expect_before +except that if patterns from both +.B expect +and +.B expect_after +can match, the +.B expect +pattern is used. See the +.B expect_before +command for more information. +.TP +.BI expect_background " [expect_args]" +takes the same arguments as +.BR expect , +however it returns immediately. +Patterns are tested whenever new input arrives. +The pattern +.B timeout +and +.B default +are meaningless to +.BR expect_background +and are silently discarded. +Otherwise, the +.B expect_background +command uses +.B expect_before +and +.B expect_after +patterns just like +.B expect +does. + +When +.B expect_background +actions are being evaluated, background processing for the same +spawn id is blocked. Background processing is unblocked when +the action completes. While background processing is blocked, +it is possible to do a (foreground) +.B expect +on the same spawn id. + +It is not possible to execute an +.B expect +while an +.B expect_background +is unblocked. +.B expect_background +for a particular spawn id is deleted by +declaring a new expect_background with the same spawn id. Declaring +.B expect_background +with no pattern removes the given spawn id +from the ability to match patterns in the background. +.TP +.BI expect_before " [expect_args]" +takes the same arguments as +.BR expect , +however it returns immediately. +Pattern-action pairs from the most recent +.B expect_before +with the same spawn id are implicitly added to any following +.B expect +commands. If a pattern matches, it is treated as if it had been +specified in the +.B expect +command itself, and the associated body is executed in the context +of the +.B expect +command. +If patterns from both +.B expect_before +and +.B expect +can match, the +.B expect_before +pattern is used. + +If no pattern is specified, the spawn id is not checked for any patterns. + +Unless overridden by a +.B \-i +flag, +.B expect_before +patterns match against the spawn id defined at the time that the +.B expect_before +command was executed (not when its pattern is matched). + +The \-info flag causes +.B expect_before +to return the current specifications of what patterns it will match. +By default, it reports on the current spawn id. An optional spawn id specification may be given for information on that spawn id. For example +.nf + + expect_before -info -i $proc + +.fi +At most one spawn id specification may be given. The flag \-indirect +suppresses direct spawn ids that come only from indirect specifications. + +Instead of a spawn id specification, the flag "-all" will cause +"-info" to report on all spawn ids. + +The output of the \-info flag can be reused as the argument to expect_before. +.TP +.BI expect_tty " [expect_args]" +is like +.B expect +but it reads characters from /dev/tty (i.e. keystrokes from the user). +By default, reading is performed in cooked mode. +Thus, lines must end with a return in order for +.B expect +to see them. +This may be changed via +.B stty +(see the +.B stty +command below). +.TP +.BI expect_user " [expect_args]" +is like +.B expect +but it reads characters from stdin (i.e. keystrokes from the user). +By default, reading is performed in cooked mode. +Thus, lines must end with a return in order for +.B expect +to see them. +This may be changed via +.B stty +(see the +.B stty +command below). +.TP +.B fork +creates a new process. The new process is an exact copy of the current +.B Expect +process. On success, +.B fork +returns 0 to the new (child) process and returns the process ID of the child +process to the parent process. +On failure (invariably due to lack of resources, e.g., swap space, memory), +.B fork +returns \-1 to the parent process, and no child process is created. +.IP +Forked processes exit via the +.B exit +command, just like the original process. +Forked processes are allowed to write to the log files. If you do not +disable debugging or logging in most of the processes, the result can be +confusing. +.IP +Some pty implementations may be confused by multiple readers and writers, +even momentarily. Thus, it is safest to +.B fork +before spawning processes. +.TP +.BI interact " [string1 body1] ... [stringn [bodyn]]" +gives control of the current process to the user, so that +keystrokes are sent to the current process, +and the stdout and stderr of the current process are returned. +.IP +String-body pairs may be specified as arguments, in which case the +body is executed when the corresponding string is entered. (By default, the +string is not sent to the current process.) The +.B interpreter +command is assumed, if the final body is missing. +.IP +If the arguments to the entire +.B interact +statement require more than one line, +all the arguments may be "braced" into one so as to avoid terminating each +line with a backslash. In this one case, the usual Tcl substitutions will +occur despite the braces. +.IP +For example, the following command runs interact with the following +string-body pairs defined: When ^Z is pressed, +.B Expect +is suspended. +(The +.B \-reset +flag restores the terminal modes.) +When ^A is pressed, the user sees "you typed a control-A" and the +process is sent a ^A. When $ is pressed, the user sees the date. +When ^C is pressed, +.B Expect +exits. If "foo" is entered, the user sees "bar". +When ~~ is pressed, the +.B Expect +interpreter runs interactively. +.nf + +.ta \w' interact 'u +\w'$CTRLZ 'u +\w'{'u + set CTRLZ \\032 + interact { + -reset $CTRLZ {exec kill \-STOP [pid]} + \\001 {send_user "you typed a control\-A\\n"; + send "\\001" + } + $ {send_user "The date is [clock format [clock seconds]]."} + \\003 exit + foo {send_user "bar"} + ~~ + } + +.fi +.IP +In string-body pairs, strings are matched in the order they are listed +as arguments. Strings that partially match are not sent to the +current process in anticipation of the remainder coming. If +characters are then entered such that there can no longer possibly be +a match, only the part of the string will be sent to the process that cannot +possibly begin another match. Thus, strings that are substrings of +partial matches can match later, if the original strings that was attempting +to be match ultimately fails. +.IP +By default, string matching is exact with no wild cards. (In contrast, +the +.B expect +command uses glob-style patterns by default.) The +.B \-ex +flag may be used to protect patterns that might otherwise match +.B interact +flags from doing so. +Any pattern beginning with a "-" should be protected this way. (All strings +starting with "-" are reserved for future options.) + +The +.B \-re +flag forces the string to be interpreted as a regexp-style pattern. In this +case, matching substrings are stored in the variable +.I interact_out +similarly to the way +.B expect +stores its output in the variable +.BR expect_out . +The +.B \-indices +flag is similarly supported. + +The pattern +.B eof +introduces an action that is +executed upon end-of-file. A separate +.B eof +pattern may also follow the +.B \-output +flag in which case it is matched if an eof is detected while writing output. +The default +.B eof +action is "return", so that +.B interact +simply returns upon any EOF. + +The pattern +.B timeout +introduces a timeout (in seconds) and action that is executed +after no characters have been read for a given time. +The +.B timeout +pattern applies to the most recently specified process. +There is no default timeout. +The special variable "timeout" (used by the +.B expect +command) has no affect on this timeout. + +For example, the following statement could be used to autologout users who have +not typed anything for an hour but who still get frequent system +messages: +.nf + + interact -input $user_spawn_id timeout 3600 return -output \\ + $spawn_id + +.fi + +If the pattern is the keyword +.BR null , +and nulls are allowed (via the +.B remove_nulls +command), the corresponding body is executed if a single ASCII +0 is matched. +It is not possible to +match 0 bytes via glob or regexp patterns. + +Prefacing a pattern with the flag +.B \-iwrite +causes the variable +.I interact_out(spawn_id) +to be set to the spawn_id which matched the pattern +(or eof). + +Actions such as +.B break +and +.B continue +cause control structures (i.e., +.BR for , +.BR proc ) +to behave in the usual way. +However +.B return +causes interact to return to its caller, while +.B inter_return +causes +.B interact +to cause a return in its caller. For example, if "proc foo" called +.B interact +which then executed the action +.BR inter_return , +.B proc foo +would return. (This means that if +.B interact +calls +.B interpreter +interactively typing +.B return +will cause the interact to continue, while +.B inter_return +will cause the interact to return to its caller.) +.IP +During +.BR interact , +raw mode is used so that all characters may be passed to the current process. +If the current process does not catch job control signals, +it will stop if sent a stop signal (by default ^Z). +To restart it, send a continue signal (such as by "kill \-CONT <pid>"). +If you really want to send a SIGSTOP to such a process (by ^Z), +consider spawning csh first and then running your program. +On the other hand, if you want to send a SIGSTOP to +.B Expect +itself, first call interpreter (perhaps by using an escape character), and then press ^Z. +.IP +String-body pairs can be used as a shorthand for avoiding having +to enter the interpreter and execute commands interactively. The previous +terminal mode is used while the body of a string-body pair is being executed. +.IP +For speed, actions execute in raw mode by default. The +.B \-reset +flag resets the terminal to the mode it had before +.B interact +was executed (invariably, cooked mode). +Note that characters entered when the mode is being switched may be lost +(an unfortunate feature of the terminal driver on some systems). +The only reason to use +.B \-reset +is if your action +depends on running in cooked mode. +.IP +The +.B \-echo +flag sends characters that match the following pattern back to the process +that generated them as each character is read. This may be useful +when the user needs to see feedback from partially typed patterns. +.IP +If a pattern is being echoed but eventually fails to match, +the characters are sent to the spawned process. If the spawned +process then echoes them, the user will see the characters twice. +.B \-echo +is probably only appropriate in situations where the user is +unlikely to not complete the pattern. For example, the following +excerpt is from rftp, the recursive-ftp script, where the user is +prompted to enter ~g, ~p, or ~l, to get, put, or list the current +directory recursively. These are so far away from the normal ftp +commands, that the user is unlikely to type ~ followed by anything +else, except mistakenly, in which case, they'll probably just ignore +the result anyway. +.nf + + interact { + -echo ~g {getcurdirectory 1} + -echo ~l {getcurdirectory 0} + -echo ~p {putcurdirectory} + } + +.fi +The +.B \-nobuffer +flag sends characters that match the following pattern on to +the output process as characters are read. + +This is useful when you wish to let a program echo back the pattern. +For example, the following might be used to monitor where a person is +dialing (a Hayes-style modem). Each time "atd" is seen the script +logs the rest of the line. +.nf + + proc lognumber {} { + interact -nobuffer -re "(.*)\\r" return + puts $log "[clock format [clock seconds]]: dialed $interact_out(1,string)" + } + + interact -nobuffer "atd" lognumber + +.fi +.IP +During +.BR interact , +previous use of +.B log_user +is ignored. In particular, +.B interact +will force its output to be logged (sent to the standard output) +since it is presumed the user doesn't wish to interact blindly. +.IP +The +.B \-o +flag causes any following key-body pairs to be applied to the output of +the current process. +This can be useful, for example, when dealing with hosts that +send unwanted characters during a telnet session. +.IP +By default, +.B interact +expects the user to be writing stdin and reading stdout of the +.B Expect +process +itself. +The +.B \-u +flag (for "user") makes +.B interact +look for the user as the process named by its argument +(which must be a spawned id). +.IP +This allows two unrelated processes to be joined +together without using an explicit loop. To aid in debugging, Expect +diagnostics always go to stderr (or stdout for certain logging and +debugging information). For the same reason, the +.B interpreter +command will read interactively from stdin. +.IP +For example, the following fragment creates a login process. +Then it dials the user (not shown), and finally connects the two together. +Of course, any process may be substituted for login. +A shell, for example, would allow the user to work without supplying an +account and password. +.nf + + spawn login + set login $spawn_id + spawn tip modem + # dial back out to user + # connect user to login + interact \-u $login + +.fi +To send output to multiple processes, list each spawn id list prefaced by a +.B \-output +flag. Input for a group of output spawn ids may be determined +by a spawn id list prefaced by a +.B \-input +flag. (Both +.B \-input +and +.B \-output +may take lists in the same form as the +.B \-i +flag in the +.B expect +command, except that any_spawn_id is not meaningful in +.BR interact .) +All following flags and +strings (or patterns) apply to this input until another -input flag appears. +If no +.B \-input +appears, +.B \-output +implies "\-input $user_spawn_id \-output". +(Similarly, with patterns that do not have +.BR \-input .) +If one +.B \-input +is specified, it overrides $user_spawn_id. If a second +.B \-input +is specified, +it overrides $spawn_id. Additional +.B \-input +flags may be specified. + +The two implied input processes default to having their outputs specified as +$spawn_id and $user_spawn_id (in reverse). +If a +.B \-input +flag appears +with no +.B \-output +flag, characters from that process are discarded. + +The +.B \-i +flag introduces a replacement for the current spawn_id when no +other +.B \-input +or +.B \-output +flags are used. A \-i flag implies a \-o flag. + +It is possible to change the processes that are being interacted with +by using indirect spawn ids. (Indirect spawn ids are described in the +section on the expect command.) Indirect spawn ids may be specified +with the -i, -u, -input, or -output flags. +.TP +.B interpreter " [args]" +causes the user to be interactively prompted for +.B Expect +and Tcl commands. +The result of each command is printed. +.IP +Actions such as +.B break +and +.B continue +cause control structures (i.e., +.BR for , +.BR proc ) +to behave in the usual way. +However +.B return +causes interpreter to return to its caller, while +.B inter_return +causes +.B interpreter +to cause a return in its caller. For example, if "proc foo" called +.B interpreter +which then executed the action +.BR inter_return , +.B proc foo +would return. +Any other command causes +.B interpreter +to continue prompting for new commands. +.IP +By default, the prompt contains two integers. +The first integer describes the depth of +the evaluation stack (i.e., how many times Tcl_Eval has been called). The +second integer is the Tcl history identifier. The prompt can be set by +defining a procedure called "prompt1" whose return value becomes the next +prompt. If a statement has open quotes, parens, braces, or brackets, a +secondary prompt (by default "+> ") is issued upon newline. The secondary +prompt may be set by defining a procedure called "prompt2". +.IP +During +.BR interpreter , +cooked mode is used, even if the its caller was using raw mode. +.IP +If stdin is closed, +.B interpreter +will return unless the +.B \-eof +flag is used, in which case the subsequent argument is invoked. +.TP +.BI log_file " [args] [[\-a] file]" +If a filename is provided, +.B log_file +will record a transcript of the session (beginning at that point) in the file. +.B log_file +will stop recording if no argument is given. Any previous log file is closed. + +Instead of a filename, a Tcl file identifier may be provided by using the +.B \-open +or +.B \-leaveopen +flags. This is similar to the +.B spawn +command. (See +.B spawn +for more info.) + +The +.B \-a +flag forces output to be logged that was suppressed by the +.B log_user +command. + +By default, the +.B log_file +command +.I appends +to old files rather than truncating them, +for the convenience of being able to turn logging off and on multiple +times in one session. +To truncate files, use the +.B \-noappend +flag. + +The +.B -info +flag causes log_file to return a description of the +most recent non-info arguments given. +.TP +.BI log_user " -info|0|1" +By default, the send/expect dialogue is logged to stdout +(and a logfile if open). +The logging to stdout is disabled by the command "log_user 0" +and reenabled by "log_user 1". Logging to the logfile is unchanged. + +The +.B -info +flag causes log_user to return a description of the +most recent non-info arguments given. +.TP +.BI match_max " [\-d] [\-i spawn_id] [size]" +defines the size of the buffer (in bytes) used internally by +.BR expect . +With no +.I size +argument, the current size is returned. +.IP +With the +.B \-d +flag, the default size is set. (The initial default is 2000.) +With the +.B \-i +flag, the size is set for the named spawn id, otherwise it is set for +the current process. +.TP +.BI overlay " [\-# spawn_id] [\-# spawn_id] [...] program [args]" +executes +.IR "program args" +in place of the current +.B Expect +program, which terminates. +A bare hyphen argument forces a hyphen in front of the command name as if +it was a login shell. +All spawn_ids are closed except for those named as arguments. These +are mapped onto the named file identifiers. +.IP +Spawn_ids are mapped to file identifiers for the new program to inherit. +For example, the following line runs chess and allows it to be +controlled by the current process \- say, a chess master. +.nf + + overlay \-0 $spawn_id \-1 $spawn_id \-2 $spawn_id chess + +.fi +This is more efficient than +"interact \-u", however, it sacrifices the ability to do programmed +interaction since the +.B Expect +process is no longer in control. +.IP +Note that no controlling terminal is provided. Thus, if you +disconnect or remap standard input, programs that do +job control (shells, login, etc) will not function properly. +.TP +.BI parity " [\-d] [\-i spawn_id] [value]" +defines whether parity should be retained or stripped from the output of +spawned processes. If +.I value +is zero, parity is stripped, otherwise it is not stripped. +With no +.I value +argument, the current value is returned. +.IP +With the +.B \-d +flag, the default parity value is set. (The initial default is 1, i.e., +parity is not stripped.) +With the +.B \-i +flag, the parity value is set for the named spawn id, otherwise it is set for +the current process. +.TP +.BI remove_nulls " [\-d] [\-i spawn_id] [value]" +defines whether nulls are retained or removed from the output of +spawned processes before pattern matching +or storing in the variable +.I expect_out +or +.IR interact_out . +If +.I value +is 1, nulls are removed. If +.I value +is 0, nulls are not removed. +With no +.I value +argument, the current value is returned. +.IP +With the +.B \-d +flag, the default value is set. (The initial default is 1, i.e., +nulls are removed.) +With the +.B \-i +flag, the value is set for the named spawn id, otherwise it is set for +the current process. + +Whether or not nulls are removed, +.B Expect +will record null bytes to the log and stdout. +.TP +.BI send " [\-flags] string" +Sends +.IR string +to the current process. +For example, the command +.nf + + send "hello world\\r" + +.fi +sends the characters, h e l l o <blank> w o r l d <return> to the +current process. +(Tcl includes a printf-like command (called +.BR format ) +which can build arbitrarily complex strings.) +.IP +Characters are sent immediately although programs with line-buffered input +will not read the characters until a return character is sent. A return +character is denoted "\\r". + +The +.B \-\- +flag forces the next argument to be interpreted as a string rather than a flag. +Any string can be preceded by "\-\-" whether or not it actually looks +like a flag. This provides a reliable mechanism to specify variable strings +without being tripped up by those that accidentally look like flags. +(All strings starting with "-" are reserved for future options.) + +The +.B \-i +flag declares that the string be sent to the named spawn_id. +If the spawn_id is +.IR user_spawn_id , +and the terminal is in raw mode, newlines in the string are translated +to return-newline +sequences so that they appear as if the terminal was in cooked mode. +The +.B \-raw +flag disables this translation. + +The +.BR \-null +flag sends null characters (0 bytes). By default, one null is sent. +An integer may follow the +.BR \-null +to indicate how many nulls to send. + +The +.B \-break +flag generates a break condition. This only makes sense if the spawn +id refers to a tty device opened via "spawn -open". If you have +spawned a process such as tip, you should use tip's convention for +generating a break. + +The +.B \-s +flag forces output to be sent "slowly", thus avoid the common situation +where a computer outtypes an input buffer that was designed for a +human who would never outtype the same buffer. This output is +controlled by the value of the variable "send_slow" which takes a two +element list. The first element is an integer that describes the +number of bytes to send atomically. The second element is a real +number that describes the number of seconds by which the atomic sends +must be separated. For example, "set send_slow {10 .001}" would force +"send \-s" to send strings with 1 millisecond in between each 10 +characters sent. + +The +.B \-h +flag forces output to be sent (somewhat) like a human actually typing. +Human-like delays appear between the characters. (The algorithm is +based upon a Weibull distribution, with modifications to suit this +particular application.) This output is controlled by the value of +the variable "send_human" which takes a five element list. The first +two elements are average interarrival time of characters in seconds. +The first is used by default. The second is used at word endings, to +simulate the subtle pauses that occasionally occur at such +transitions. The third parameter is a measure of variability where .1 +is quite variable, 1 is reasonably variable, and 10 is quite +invariable. The extremes are 0 to infinity. The last two parameters +are, respectively, a minimum and maximum interarrival time. +The minimum and maximum are used last and "clip" the final time. +The ultimate average can be quite different from the given average +if the minimum and maximum clip enough values. + +As an +example, the following command emulates a fast and +consistent typist: +.nf + + set send_human {.1 .3 1 .05 2} + send \-h "I'm hungry. Let's do lunch." + +.fi +while the following might be more suitable after a hangover: +.nf + + set send_human {.4 .4 .2 .5 100} + send \-h "Goodd party lash night!" + +.fi +Note that errors are not simulated, although you can set up error +correction situations yourself by embedding mistakes and corrections +in a send argument. + +The flags for sending null characters, for sending breaks, for forcing slow +output and for human-style output are mutually exclusive. Only the one +specified last will be used. Furthermore, no +.I string +argument can be specified with the flags for sending null characters or breaks. + +It is a good idea to precede the first +.B send +to a process by an +.BR expect . +.B expect +will wait for the process to start, while +.B send +cannot. +In particular, if the first +.B send +completes before the process starts running, +you run the risk of having your data ignored. +In situations where interactive programs offer no initial prompt, +you can precede +.B send +by a delay as in: +.nf + + # To avoid giving hackers hints on how to break in, + # this system does not prompt for an external password. + # Wait for 5 seconds for exec to complete + spawn telnet very.secure.gov + sleep 5 + send password\\r + +.fi +.B exp_send +is an alias for +.BI send . +If you are using Expectk or some other variant of Expect in the Tk environment, +.B send +is defined by Tk for an entirely different purpose. +.B exp_send +is provided for compatibility between environments. +Similar aliases are provided for other Expect's other send commands. +.TP +.BI send_error " [\-flags] string" +is like +.BR send , +except that the output is sent to stderr rather than the current +process. +.TP +.BI send_log " [\--] string" +is like +.BR send , +except that the string is only sent to the log file (see +.BR log_file .) +The arguments are ignored if no log file is open. +.TP +.BI send_tty " [\-flags] string" +is like +.BR send , +except that the output is sent to /dev/tty rather than the current +process. +.TP +.BI send_user " [\-flags] string" +is like +.BR send , +except that the output is sent to stdout rather than the current +process. +.TP +.BI sleep " seconds" +causes the script to sleep for the given number of seconds. +Seconds may be a decimal number. Interrupts (and Tk events if you +are using Expectk) are processed while Expect sleeps. +.TP +.BI spawn " [args] program [args]" +creates a new process running +.IR "program args" . +Its stdin, stdout and stderr are connected to Expect, +so that they may be read and written by other +.B Expect +commands. +The connection is broken by +.B close +or if the process itself closes any of the file identifiers. +.IP +When a process is started by +.BR spawn , +the variable +.I spawn_id +is set to a descriptor referring to that process. +The process described by +.I spawn_id +is considered the +.IR "current process" . +.I spawn_id +may be read or written, in effect providing job control. +.IP +.I user_spawn_id +is a global variable containing a descriptor which refers to the user. +For example, when +.I spawn_id +is set to this value, +.B expect +behaves like +.BR expect_user . + +.I +.I error_spawn_id +is a global variable containing a descriptor which refers to the standard +error. +For example, when +.I spawn_id +is set to this value, +.B send +behaves like +.BR send_error . +.IP +.I tty_spawn_id +is a global variable containing a descriptor which refers to /dev/tty. +If /dev/tty does not exist (such as in a cron, at, or batch script), then +.I tty_spawn_id +is not defined. This may be tested as: +.nf + + if {[info vars tty_spawn_id]} { + # /dev/tty exists + } else { + # /dev/tty doesn't exist + # probably in cron, batch, or at script + } + +.fi +.IP +.B spawn +returns the UNIX process id. If no process is spawned, 0 is returned. +The variable +.I spawn_out(slave,name) +is set to the name of the pty slave device. +.IP +By default, +.B spawn +echoes the command name and arguments. The +.B \-noecho +flag stops +.B spawn +from doing this. +.IP +The +.B \-console +flag causes console output to be redirected to the spawned process. +This is not supported on all systems. + +Internally, +.B spawn +uses a pty, initialized the same way as the user's tty. This is further +initialized so that all settings are "sane" (according to stty(1)). +If the variable +.I stty_init +is defined, it is interpreted in the style of stty arguments +as further configuration. +For example, "set stty_init raw" will cause further spawned processes's +terminals to start in raw mode. +.B \-nottycopy +skips the initialization based on the user's tty. +.B \-nottyinit +skips the "sane" initialization. +.IP +Normally, +.B spawn +takes little time to execute. If you notice spawn taking a +significant amount of time, it is probably encountering ptys that are +wedged. A number of tests are run on ptys to avoid entanglements with +errant processes. (These take 10 seconds per wedged pty.) Running +Expect with the +.B \-d +option will show if +.B Expect +is encountering many ptys in odd states. If you cannot kill +the processes to which these ptys are attached, your only recourse may +be to reboot. + +If +.I program +cannot be spawned successfully because exec(2) fails (e.g. when +.I program +doesn't exist), an error message will be returned by the next +.B interact +or +.B expect +command as if +.I program +had run and produced the error message as output. +This behavior is a natural consequence of the implementation of +.BR spawn . +Internally, spawn forks, after which the spawned process has no +way to communicate with the original +.B Expect +process except by communication +via the spawn_id. + +The +.B \-open +flag causes the next argument to be interpreted as a Tcl file identifier +(i.e., returned by +.BR open .) +The spawn id can then be used as if it were a spawned process. (The file +identifier should no longer be used.) +This lets you treat raw devices, files, and +pipelines as spawned processes without using a pty. 0 is returned to +indicate there is no associated process. When the connection to +the spawned process is closed, so is the Tcl file identifier. +The +.B \-leaveopen +flag is similar to +.B \-open +except that +.B \-leaveopen +causes the file identifier to be left open even after the spawn id is closed. + +The +.B \-pty +flag causes a pty to be opened but no process spawned. 0 is returned +to indicate there is no associated process. Spawn_id is set as usual. + +The variable +.I spawn_out(slave,fd) +is set to a file identifier corresponding to the pty slave. +It can be closed using "close -slave". + +The +.B \-ignore +flag names a signal to be ignored in the spawned process. +Otherwise, signals get the default behavior. +Signals are named as in the +.B trap +command, except that each signal requires a separate flag. +.TP +.BI strace " level" +causes following statements to be printed before being executed. +(Tcl's trace command traces variables.) +.I level +indicates how far down in the call stack to trace. +For example, +the following command runs +.B Expect +while tracing the first 4 levels of calls, +but none below that. +.nf + + expect \-c "strace 4" script.exp + +.fi + +The +.B -info +flag causes strace to return a description of the +most recent non-info arguments given. +.TP +.BI stty " args" +changes terminal modes similarly to the external stty command. + +By default, the controlling terminal is accessed. Other terminals can +be accessed by appending "< /dev/tty..." to the command. (Note that +the arguments should not be grouped into a single argument.) + +Requests for status return it as the result of the command. If no status +is requested and the controlling terminal is accessed, the previous +status of the raw and echo attributes are returned in a form which can +later be used by the command. + +For example, the arguments +.B raw +or +.B \-cooked +put the terminal into raw mode. +The arguments +.B \-raw +or +.B cooked +put the terminal into cooked mode. +The arguments +.B echo +and +.B \-echo +put the terminal into echo and noecho mode respectively. +.IP +The following example illustrates how to temporarily disable echoing. +This could be used in otherwise-automatic +scripts to avoid embedding passwords in them. +(See more discussion on this under EXPECT HINTS below.) +.nf + + stty \-echo + send_user "Password: " + expect_user -re "(.*)\\n" + set password $expect_out(1,string) + stty echo + +.fi +.TP +.BI system " args" +gives +.I args +to sh(1) as input, +just as if it had been typed as a command from a terminal. +.B Expect +waits until the shell terminates. +The return status from sh is handled the same way that +.B exec +handles its return status. +.IP +In contrast to +.B exec +which redirects stdin and stdout to the script, +.B system +performs no redirection +(other than that indicated by the string itself). +Thus, it is possible to use programs which must talk directly to /dev/tty. +For the same reason, the results of +.B system +are not recorded in the log. +.TP +.BI timestamp " [args]" +returns a timestamp. +With no arguments, the number of +seconds since the epoch is returned. + +The +.B \-format +flag introduces a string which is returned but with +substitutions made according to the +POSIX rules for strftime. For example %a is replaced by an abbreviated +weekday name (i.e., Sat). Others are: +.nf + %a abbreviated weekday name + %A full weekday name + %b abbreviated month name + %B full month name + %c date-time as in: Wed Oct 6 11:45:56 1993 + %d day of the month (01-31) + %H hour (00-23) + %I hour (01-12) + %j day (001-366) + %m month (01-12) + %M minute (00-59) + %p am or pm + %S second (00-61) + %u day (1-7, Monday is first day of week) + %U week (00-53, first Sunday is first day of week one) + %V week (01-53, ISO 8601 style) + %w day (0-6) + %W week (00-53, first Monday is first day of week one) + %x date-time as in: Wed Oct 6 1993 + %X time as in: 23:59:59 + %y year (00-99) + %Y year as in: 1993 + %Z timezone (or nothing if not determinable) + %% a bare percent sign + +.fi +Other % specifications are undefined. Other characters will be passed +through untouched. Only the C locale is supported. + +The +.B \-seconds +flag introduces a number of seconds since the epoch to be used as a source +from which to format. Otherwise, the current time is used. + +The +.B \-gmt +flag forces timestamp output to use the GMT timezone. With no flag, +the local timezone is used. +.TP +.BI trap " [[command] signals]" +causes the given +.I command +to be executed upon future receipt of any of the given signals. +The command is executed in the global scope. +If +.I command +is absent, the signal action is returned. +If +.I command +is the string SIG_IGN, the signals are ignored. +If +.I command +is the string SIG_DFL, the signals are result to the system default. +.I signals +is either a single signal or a list of signals. Signals may be specified +numerically or symbolically as per signal(3). The "SIG" prefix may be omitted. + +With no arguments (or the argument \-number), +.B trap +returns the signal number of the trap command currently being executed. + +The +.B \-code +flag uses the return code of the command in place of whatever code Tcl +was about to return when the command originally started running. + +The +.B \-interp +flag causes the command to be evaluated using the interpreter +active at the time the command started running +rather than when the trap was declared. + +The +.B \-name +flag causes the +.B trap +command to return the signal name of the trap command currently being executed. + +The +.B \-max +flag causes the +.B trap +command to return the largest signal number that can be set. + +For example, the command "trap {send_user "Ouch!"} SIGINT" will print "Ouch!" +each time the user presses ^C. + +By default, SIGINT (which can usually be generated by pressing ^C) and +SIGTERM cause Expect to exit. This is due to the following trap, created +by default when Expect starts. +.nf + + trap exit {SIGINT SIGTERM} + +.fi +If you use the -D flag to start the debugger, SIGINT is redefined +to start the interactive debugger. This is due to the following trap: +.nf + + trap {exp_debug 1} SIGINT + +.fi +The debugger trap can be changed by setting the environment variable +EXPECT_DEBUG_INIT to a new trap command. + +You can, of course, override both of these just by adding trap +commands to your script. In particular, if you have your own "trap +exit SIGINT", this will override the debugger trap. This is useful +if you want to prevent users from getting to the debugger at all. + +If you want to define your own trap on SIGINT but still trap to the +debugger when it is running, use: +.nf + + if {![exp_debug]} {trap mystuff SIGINT} + +.fi +Alternatively, you can trap to the debugger using some other signal. + +.B trap +will not let you override the action for SIGALRM as this is used internally +to +.BR Expect . +The disconnect command sets SIGALRM to SIG_IGN (ignore). You can reenable +this as long as you disable it during subsequent spawn commands. + +See signal(3) for more info. +.TP +.BI wait " [args]" +delays until a spawned process (or +the current process if none is named) terminates. +.IP +.B wait +normally returns a list of four integers. +The first integer is the pid of the process that was waited upon. +The second integer is the corresponding spawn id. +The third integer is -1 if an operating system error occurred, or 0 otherwise. +If the third integer was 0, the fourth integer is the status returned by +the spawned process. If the third integer was -1, the fourth integer is +the value of errno set by the operating system. The global variable +errorCode is also set. + +Additional elements may appear at the end of the return value from +.BR wait . +An optional fifth element identifies a class of information. +Currently, the only possible value for this element is CHILDKILLED in +which case the next two values are the C-style signal name and a short +textual description. +.IP +The +.B \-i +flag declares the process to wait corresponding to the named spawn_id +(NOT the process id). +Inside a SIGCHLD handler, +it is possible to wait for any spawned process by using the spawn id -1. + +The +.B \-nowait +flag causes the wait to return immediately with the indication of a +successful wait. When the process exits (later), it will automatically +disappear without the need for an explicit wait. + +The +.B wait +command may also be used wait for a forked process using the arguments +"-i -1". Unlike its use with spawned processes, this command can be +executed at any time. There is no control over which process is +reaped. However, the return value can be checked for the process id. + +.SH LIBRARIES +Expect automatically knows about two built-in libraries for Expect scripts. +These are defined by the directories named in the variables +exp_library and exp_exec_library. Both are meant to contain utility +files that can be used by other scripts. + +exp_library contains architecture-independent files. exp_exec_library +contains architecture-dependent files. Depending on your system, both +directories may be totally empty. The existence of the file +$exp_exec_library/cat-buffers describes whether your /bin/cat buffers +by default. +.SH PRETTY-PRINTING +A vgrind definition is available for pretty-printing +.B Expect +scripts. +Assuming the vgrind definition supplied with the +.B Expect +distribution is +correctly installed, you can use it as: +.nf + + vgrind \-lexpect file + +.fi +.SH EXAMPLES +It many not be apparent how to put everything together that the man page +describes. I encourage you to read and try out the examples in +the example directory of the +.B Expect +distribution. +Some of them are real programs. Others are simply illustrative +of certain techniques, and of course, a couple are just quick hacks. +The INSTALL file has a quick overview of these programs. +.PP +The +.B Expect +papers (see SEE ALSO) are also useful. While some papers +use syntax corresponding to earlier versions of Expect, the accompanying +rationales are still valid and go into a lot more detail than this +man page. +.SH CAVEATS +Extensions may collide with Expect's command names. For example, +.B send +is defined by Tk for an entirely different purpose. +For this reason, most of the +.B Expect +commands are also available as "exp_XXXX". +Commands and variables beginning with "exp", "inter", "spawn", +and "timeout" do not have aliases. +Use the extended command names if you need this compatibility between environments. + +.B Expect +takes a rather liberal view of scoping. +In particular, variables read by commands specific to the +.B Expect +program will be sought first from the local scope, and if not found, in the +global scope. For example, this +obviates the need to place "global timeout" in every +procedure you write that uses +.BR expect . +On the other hand, variables written are always in the local scope (unless +a "global" command has been issued). The most common problem this causes +is when spawn is executed in a procedure. Outside the procedure, +.I spawn_id +no longer exists, so the spawned process is no longer accessible +simply because of scoping. Add a "global spawn_id" to such a procedure. + +If you cannot enable the multispawning capability +(i.e., your system supports neither select (BSD *.*), poll (SVR>2), +nor something equivalent), +.B Expect +will only be able to control a single process at a time. +In this case, do not attempt to set +.IR spawn_id , +nor should you execute processes via exec while a spawned process +is running. Furthermore, you will not be able to +.B expect +from multiple processes (including the user as one) at the same time. + +Terminal parameters can have a big effect on scripts. For example, if +a script is written to look for echoing, it will misbehave if echoing +is turned off. For this reason, Expect forces sane terminal +parameters by default. Unfortunately, this can make things unpleasant +for other programs. As an example, the emacs shell wants to change +the "usual" mappings: newlines get mapped to newlines instead of +carriage-return newlines, and echoing is disabled. This allows one to +use emacs to edit the input line. Unfortunately, Expect cannot +possibly guess this. + +You can request that Expect not override its default setting of +terminal parameters, but you must then be very careful when writing +scripts for such environments. In the case of emacs, avoid depending +upon things like echoing and end-of-line mappings. + +The commands that accepted arguments braced into a single list (the +.B expect +variants and +.BR interact ) +use a heuristic to decide if the list is actually one argument or +many. The heuristic can fail only in the case when the list actually +does represent a single argument which has multiple embedded \\n's +with non-whitespace characters between them. This seems sufficiently +improbable, however the argument "\-nobrace" can be used to force a +single argument to be handled as a single argument. This could +conceivably be used with machine-generated Expect code. Similarly, +-brace forces a single argument to be handle as multiple patterns/actions. + +.SH BUGS +It was really tempting to name the program "sex" (for either "Smart EXec" +or "Send-EXpect"), but good sense (or perhaps just Puritanism) prevailed. + +On some systems, when a shell is spawned, it complains about not being +able to access the tty but runs anyway. This means your system has a +mechanism for gaining the controlling tty that +.B Expect +doesn't know about. Please find out what it is, and send this information +back to me. + +Ultrix 4.1 (at least the latest versions around here) considers +timeouts of above 1000000 to be equivalent to 0. + +Digital UNIX 4.0A (and probably other versions) refuses to allocate +ptys if you define a SIGCHLD handler. See grantpt page for more info. + +IRIX 6.0 does not handle pty permissions correctly so that if Expect +attempts to allocate a pty previously used by someone else, it fails. +Upgrade to IRIX 6.1. + +Telnet (verified only under SunOS 4.1.2) hangs if TERM is not set. +This is a problem under cron, at and in cgi scripts, which do not +define TERM. Thus, you must set it explicitly - to what type is +usually irrelevant. It just has to be set to something! The +following probably suffices for most cases. +.nf + + set env(TERM) vt100 + +.fi + +Tip (verified only under BSDI BSD/OS 3.1 i386) hangs if SHELL and HOME +are not set. This is a problem under cron, at and in cgi scripts, +which do not define these environment variables. Thus, you must set +them explicitly - to what type is usually irrelevant. It just has to +be set to something! The following probably suffices for most cases. +.nf + + set env(SHELL) /bin/sh + set env(HOME) /usr/local/bin + +.fi + + +Some implementations of ptys are designed so that the kernel throws +away any unread output after 10 to 15 seconds (actual number is +implementation-dependent) after the process has closed the file +descriptor. Thus +.B Expect +programs such as +.nf + + spawn date + sleep 20 + expect + +.fi +will fail. To avoid this, invoke non-interactive programs with +.B exec +rather than +.BR spawn . +While such situations are conceivable, in practice I have never +encountered a situation in which the final output of a truly +interactive program would be lost due to this behavior. + +On the other hand, Cray UNICOS ptys throw away any unread output +immediately after the process has closed the file descriptor. I have +reported this to Cray and they are working on a fix. + +Sometimes a delay is required between a prompt and a response, such as +when a tty interface is changing UART settings or matching baud rates +by looking for start/stop bits. Usually, all this is require is to +sleep for a second or two. A more robust technique is to retry until +the hardware is ready to receive input. The following example uses +both strategies: +.nf + + send "speed 9600\\r"; + sleep 1 + expect { + timeout {send "\\r"; exp_continue} + $prompt + } + +.fi + +trap \-code will not work with any command that sits in Tcl's event +loop, such as sleep. The problem is that in the event loop, Tcl +discards the return codes from async event handlers. A workaround is +to set a flag in the trap code. Then check the flag immediately after +the command (i.e., sleep). + +The expect_background command ignores -timeout arguments and has no +concept of timeouts in general. + +.SH "EXPECT HINTS" +There are a couple of things about +.B Expect +that may be non-intuitive. +This section attempts to address some of these things with a couple of +suggestions. + +A common expect problem is how to recognize shell prompts. Since +these are customized differently by differently people and different +shells, portably automating rlogin can be difficult without knowing +the prompt. A reasonable convention is to have users store a regular +expression describing their prompt (in particular, the end of it) in +the environment variable EXPECT_PROMPT. Code like the following +can be used. If EXPECT_PROMPT doesn't exist, the code still has a good chance of functioning correctly. +.nf + + set prompt "(%|#|\\\\$) $" ;# default prompt + catch {set prompt $env(EXPECT_PROMPT)} + + expect -re $prompt + +.fi +I encourage you to write +.B expect +patterns that include the end of whatever +you expect to see. This avoids the possibility of answering a question +before seeing the entire thing. In addition, while you may well be +able to answer questions before seeing them entirely, if you answer +early, your answer may appear echoed back in the middle of the question. +In other words, the resulting dialogue will be correct but look scrambled. + +Most prompts include a space character at the end. +For example, the prompt from ftp is 'f', 't', 'p', '>' and <blank>. +To match this prompt, you must account for each of these characters. +It is a common mistake not to include the blank. +Put the blank in explicitly. + +If you use a pattern of the form X*, the * will match all the output +received from the end of X to the last thing received. +This sounds intuitive but can be somewhat confusing because the phrase +"last thing received" can vary depending upon the speed of the computer +and the processing of I/O both by the kernel and the device driver. +.PP +In particular, humans tend to see program output arriving in huge chunks +(atomically) when in reality most programs produce output one +line at a time. Assuming this is the case, the * in the pattern of the +previous paragraph may only match the end of the current line even though +there seems to be more, because at the time of the match that was all +the output that had been received. +.PP +.B expect +has no way of knowing that further output is coming unless your +pattern specifically accounts for it. +.PP +Even depending on line-oriented buffering is unwise. Not only do programs +rarely make promises about the type of buffering they do, but system +indigestion can break output lines up so that lines break at seemingly +random places. Thus, if you can express the last few characters +of a prompt when writing patterns, it is wise to do so. + +If you are waiting for a pattern in the last output of a program +and the program emits something else instead, you will not be able to +detect that with the +.B timeout +keyword. The reason is that +.B expect +will not timeout \- instead it will get an +.B eof +indication. +Use that instead. Even better, use both. That way if that line +is ever moved around, you won't have to edit the line itself. + +Newlines are usually converted to carriage return, linefeed sequences +when output by the terminal driver. Thus, if you want a pattern that +explicitly matches the two lines, from, say, printf("foo\\nbar"), +you should use the pattern "foo\\r\\nbar". +.PP +A similar translation occurs when reading from the user, via +.BR expect_user . +In this case, when you press return, it will be +translated to a newline. If +.B Expect +then passes that to a program +which sets its terminal to raw mode (like telnet), there is going to +be a problem, as the program expects a true return. (Some programs +are actually forgiving in that they will automatically translate +newlines to returns, but most don't.) Unfortunately, there is no way to find +out that a program put its terminal into raw mode. +.PP +Rather than manually replacing newlines with returns, the solution is to +use the command "stty raw", which will stop the translation. +Note, however, that this means that you will no longer get the cooked +line-editing features. +.PP +.B interact +implicitly sets your terminal to raw mode so this problem will not arise then. + +It is often useful to store passwords (or other private information) +in +.B Expect +scripts. This is not recommended since anything that is +stored on a computer is susceptible to being accessed by anyone. +Thus, interactively prompting for passwords from a script is a smarter +idea than embedding them literally. Nonetheless, sometimes such embedding +is the only possibility. +.PP +Unfortunately, the UNIX file system has no direct way of creating +scripts which are executable but unreadable. Systems which support +setgid shell scripts may indirectly simulate this as follows: +.PP +Create the +.B Expect +script (that contains the secret data) as usual. +Make its permissions be 750 (\-rwxr\-x\-\-\-) and owned by a trusted group, +i.e., a group which is allowed to read it. If necessary, create a new +group for this purpose. Next, create a /bin/sh script with +permissions 2751 (\-rwxr\-s\-\-x) owned by the same group as before. +.PP +The result is a script which may be executed (and read) by anyone. +When invoked, it runs the +.B Expect +script. +.SH "SEE ALSO" +.BR Tcl (3), +.BR libexpect (3) +.br +.I +"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" +\fRby Don Libes, pp. 602, ISBN 1-56592-090-2, O'Reilly and Associates, 1995. +.br +.I +"expect: Curing Those Uncontrollable Fits of Interactivity" \fRby Don Libes, +Proceedings of the Summer 1990 USENIX Conference, +Anaheim, California, June 11-15, 1990. +.br +.I +"Using +.B expect +to Automate System Administration Tasks" \fRby Don Libes, +Proceedings of the 1990 USENIX Large Installation Systems Administration +Conference, Colorado Springs, Colorado, October 17-19, 1990. +.br +.I +"Tcl: An Embeddable Command Language" \fRby John Ousterhout, +Proceedings of the Winter 1990 USENIX Conference, +Washington, D.C., January 22-26, 1990. +.br +.I +"expect: Scripts for Controlling Interactive Programs" \fRby Don Libes, +Computing Systems, Vol. 4, No. 2, University of California Press Journals, +November 1991. +.br +.I +"Regression Testing and Conformance Testing Interactive Programs", \fRby Don +Libes, Proceedings of the Summer 1992 USENIX Conference, pp. 135-144, +San Antonio, TX, June 12-15, 1992. +.br +.I +"Kibitz \- Connecting Multiple Interactive Programs Together", \fRby Don Libes, +Software \- Practice & Experience, John Wiley & Sons, West Sussex, England, +Vol. 23, No. 5, May, 1993. +.br +.I +"A Debugger for Tcl Applications", \fRby Don Libes, +Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA, June 10-11, 1993. +.SH AUTHOR +Don Libes, National Institute of Standards and Technology +.SH ACKNOWLEDGMENTS +Thanks to John Ousterhout for Tcl, and Scott Paisley for inspiration. +Thanks to Rob Savoye for Expect's autoconfiguration code. +.PP +The HISTORY file documents much of the evolution of +.BR expect . +It makes interesting reading and might give you further insight to this +software. Thanks to the people mentioned in it who sent me bug fixes +and gave other assistance. +.PP +Design and implementation of +.B Expect +was paid for in part by the U.S. government and is therefore in the public +domain. +However the author and NIST would like credit +if this program and documentation or portions of them are used. diff --git a/expect_cf.h.in b/expect_cf.h.in new file mode 100644 index 0000000..f5ddbaa --- /dev/null +++ b/expect_cf.h.in @@ -0,0 +1,127 @@ +/* + * Check for headers + */ +#ifndef __EXPECT_CF_H__ +#define __EXPECT_CF_H__ + +#undef NO_STDLIB_H +#undef NO_UNION_WAIT +#undef HAVE_STDARG_H +#undef HAVE_VARARGS_H +#undef HAVE_STROPTS_H +#undef HAVE_SYSCONF_H +#undef HAVE_SYS_FCNTL_H +#undef HAVE_SYS_WAIT_H +#undef HAVE_SYS_BSDTYPES_H +#undef HAVE_SYS_SELECT_H +#undef HAVE_SYS_TIME_H +#undef HAVE_SYS_PTEM_H +#undef HAVE_STRREDIR_H + +/* old-style Dynix ptys need this */ +#undef HAVE_STRPTY_H + +#undef HAVE_UNISTD_H +#undef HAVE_SYSMACROS_H +#undef HAVE_INTTYPES_H +#undef HAVE_TIOCGWINSZ_IN_TERMIOS_H +#undef HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H + +#undef pid_t +#undef RETSIGTYPE + +/* ok to include both time.h and sys/time.h */ +#undef TIME_WITH_SYS_TIME + +/* if setpgrp takes 0 args */ +#undef SETPGRP_VOID + +/* + * This section is for compile macros needed by + * everything else. + */ + +/* + * Check for functions + */ +#undef HAVE_MEMCPY +#undef HAVE_SYSCONF +#undef SIMPLE_EVENT +#undef HAVE_STRFTIME +#undef HAVE_MEMMOVE + +/* timezone() a la Pyramid */ +#undef HAVE_TIMEZONE + +#undef HAVE_SIGLONGJMP +#undef HAVE_STRCHR + +#ifndef HAVE_STRCHR +#define strchr(s,c) index(s,c) +#endif /* HAVE_STRCHR */ + +/* + * timezone + */ +#undef HAVE_SV_TIMEZONE + +/* + * wait status type + */ +#undef NO_UNION_WAIT + +#undef WNOHANG_REQUIRES_POSIX_SOURCE + +/* + * Signal stuff. Setup the return type + * and if signals need to be re-armed. + */ +/*#ifndef RETSIGTYPE*/ +/*#define RETSIGTYPE void*/ +/*#endif*/ +#undef REARM_SIG + +/* + * Generate correct type for select mask + */ +#ifndef SELECT_MASK_TYPE +#define SELECT_MASK_TYPE fd_set +#endif + +/* + * Check how stty works + */ +#undef STTY_READS_STDOUT + +/* + * Check for tty/pty functions and structures + */ +#undef POSIX +#undef HAVE_TCSETATTR +#undef HAVE_TERMIO +#undef HAVE_TERMIOS +#undef HAVE_SGTTYB +#undef HAVE__GETPTY +#undef HAVE_GETPTY +#undef HAVE_OPENPTY +#undef HAVE_PTC +#undef HAVE_PTC_PTS +#undef HAVE_PTYM +#undef HAVE_PTYTRAP +#undef HAVE_PTMX +#undef HAVE_PTMX_BSD +#undef HAVE_SCO_CLIST_PTYS + +/* + * Special hacks + */ +#undef CONVEX +#undef SOLARIS + +#ifdef SOLARIS +#define __EXTENSIONS__ +#endif /* SOLARIS */ + +#undef WNOHANG_BACKUP_VALUE + +#endif /* __EXPECT_CF_H__ */ diff --git a/expect_comm.h b/expect_comm.h new file mode 100644 index 0000000..c9f5f70 --- /dev/null +++ b/expect_comm.h @@ -0,0 +1,65 @@ +/* expectcomm.h - public symbols common to both expect.h and expect_tcl.h + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. +*/ + +#ifndef _EXPECT_COMM_H +#define _EXPECT_COMM_H + +/* common return codes for Expect functions */ +/* The library actually only uses TIMEOUT and EOF */ +#define EXP_ABEOF -1 /* abnormal eof in Expect */ + /* when in library, this define is not used. */ + /* Instead "-1" is used literally in the */ + /* usual sense to check errors in system */ + /* calls */ +#define EXP_TIMEOUT -2 +#define EXP_TCLERROR -3 +#define EXP_FULLBUFFER -5 +#define EXP_MATCH -6 +#define EXP_NOMATCH -7 +#define EXP_CANTMATCH EXP_NOMATCH +#define EXP_CANMATCH -8 +#define EXP_DATA_NEW -9 /* if select says there is new data */ +#define EXP_DATA_OLD -10 /* if we already read data in another cmd */ +#define EXP_EOF -11 +#define EXP_RECONFIGURE -12 /* changes to indirect spawn id lists */ + /* require us to reconfigure things */ + +/* in the unlikely event that a signal handler forces us to return this */ +/* through expect's read() routine, we temporarily convert it to this. */ +#define EXP_TCLRET -20 +#define EXP_TCLCNT -21 +#define EXP_TCLCNTTIMER -22 +#define EXP_TCLBRK -23 +#define EXP_TCLCNTEXP -24 +#define EXP_TCLRETTCL -25 + +/* yet more TCL return codes */ +/* Tcl does not safely provide a way to define the values of these, so */ +/* use ridiculously different numbers for safety */ +#define EXP_CONTINUE -101 /* continue expect command */ + /* and restart timer */ +#define EXP_CONTINUE_TIMER -102 /* continue expect command */ + /* and continue timer */ +#define EXP_TCL_RETURN -103 /* converted by interact */ + /* and interpeter from */ + /* inter_return into */ + /* TCL_RETURN*/ + +/* + * Everything below here should eventually be moved into expect.h + * and Expect-thread-safe variables. + */ + +EXTERN char *exp_pty_error; /* place to pass a string generated */ + /* deep in the innards of the pty */ + /* code but needed by anyone */ +EXTERN int exp_disconnected; /* proc. disc'd from controlling tty */ + + +#endif /* _EXPECT_COMM_H */ diff --git a/expect_tcl.h b/expect_tcl.h new file mode 100644 index 0000000..0fa5a99 --- /dev/null +++ b/expect_tcl.h @@ -0,0 +1,57 @@ +/* expect_tcl.h - include file for using the expect library, libexpect.a +with Tcl (and optionally Tk) + +Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#ifndef _EXPECT_TCL_H +#define _EXPECT_TCL_H + +#include <stdio.h> +#include "expect_comm.h" + +/* + * This is a convenience macro used to initialize a thread local storage ptr. + * Stolen from tclInt.h + */ +#ifndef TCL_TSD_INIT +#define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) +#endif + +EXTERN int exp_cmdlinecmds; +EXTERN int exp_interactive; +EXTERN FILE *exp_cmdfile; +EXTERN char *exp_cmdfilename; +EXTERN int exp_getpid; /* pid of Expect itself */ +EXTERN int exp_buffer_command_input; + +EXTERN int exp_strict_write; + +EXTERN int exp_tcl_debugger_available; + +EXTERN Tcl_Interp *exp_interp; + +#define Exp_Init Expect_Init +EXTERN int Expect_Init _ANSI_ARGS_((Tcl_Interp *)); /* for Tcl_AppInit apps */ +EXTERN void exp_parse_argv _ANSI_ARGS_((Tcl_Interp *,int argc,char **argv)); +EXTERN int exp_interpreter _ANSI_ARGS_((Tcl_Interp *,Tcl_Obj *)); +EXTERN int exp_interpret_cmdfile _ANSI_ARGS_((Tcl_Interp *,FILE *)); +EXTERN int exp_interpret_cmdfilename _ANSI_ARGS_((Tcl_Interp *,char *)); +EXTERN void exp_interpret_rcfiles _ANSI_ARGS_((Tcl_Interp *,int my_rc,int sys_rc)); + +EXTERN char * exp_cook _ANSI_ARGS_((char *s,int *len)); + +EXTERN void expCloseOnExec _ANSI_ARGS_((int)); + + /* app-specific exit handler */ +EXTERN void (*exp_app_exit)_ANSI_ARGS_((Tcl_Interp *)); +EXTERN void exp_exit_handlers _ANSI_ARGS_((ClientData)); + +EXTERN void exp_error _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); + +#endif /* _EXPECT_TCL_H */ diff --git a/fixline1 b/fixline1 new file mode 100755 index 0000000..113e9bb --- /dev/null +++ b/fixline1 @@ -0,0 +1,25 @@ +#!expect -- +# Synopsis: fixline1 newpath < input > output +# Author: Don Libes + +# Description: change first line of script to reflect new binary +# try to match any of the following first lines +#!expect ... +#!../expect ... +#!expectk ... +#!foo/bar/expectk ... +#!/bin/sh ... (beginning of multiline #! style) +# +set line1 [gets stdin] +if {"$line1" == "\#!/bin/sh"} { + # if multi-line hack already in place, do nothing + set header $line1 +} else { + # if single-line #!, switch to multi-line rewrite + + regexp "^#!(.*/)*(.*)" $line1 X X tail + set header "#!/bin/sh\n" + append header "# \\\n" + append header "exec $tail "; append header {"$0" ${1+"$@"}} +} +puts -nonewline "$header\n[read stdin]" diff --git a/libexpect.man b/libexpect.man new file mode 100644 index 0000000..bbb141e --- /dev/null +++ b/libexpect.man @@ -0,0 +1,690 @@ +.TH LIBEXPECT 3 "12 December 1991" +.SH NAME +libexpect \- programmed dialogue library with interactive programs +.SH DESCRIPTION +This library contains functions that allow Expect to be used as +a Tcl extension or to be used directly from C or C++ (without Tcl). +Adding Expect as a Tcl extension is very short and simple, so that will be +covered first. +.SH SYNOPSIS +.nf + +.B #include "expect_tcl.h" +.B Expect_Init(interp); + +.B cc files... \-lexpect5.20 \-ltcl7.5 \-lm + +.fi +Note: library versions may differ in the actual release. + +The Expect_Init function adds expect commands to the named +interpreter. It avoids overwriting commands that already exist, +however aliases beginning with "exp_" are always created for expect +commands. So for example, "send" can be used as "exp_send". + +Generally, you should only call Expect commands via Tcl_Eval. +Certain auxiliary functions may be called directly. They are summarized +below. They may be useful in constructing your own main. Look +at the file exp_main_exp.c in the Expect distribution as +a prototype main. Another prototype is tclAppInit.c in the +Tcl source distribution. A prototype for working with Tk is in +exp_main_tk.c in the Expect distribution. +.nf + +int exp_cmdlinecmds; +int exp_interactive; +FILE *exp_cmdfile; +char *exp_cmdfilename; +int exp_tcl_debugger_available; + +void exp_parse_argv(Tcl_Interp *,int argc,char **argv); +int exp_interpreter(Tcl_Interp *); +void exp_interpret_cmdfile(Tcl_Interp *,FILE *); +void exp_interpret_cmdfilename(Tcl_Interp *,char *); +void exp_interpret_rcfiles(Tcl_Interp *,int my_rc,int sys_rc); +char * exp_cook(char *s,int *len); +void (*exp_app_exit)EXP_PROTO((Tcl_Interp *); +void exp_exit(Tcl_Interp *,int status); +void exp_exit_handlers(Tcl_Interp *); +void exp_error(Tcl_Interp,char *,...); + +.fi +.B exp_cmdlinecmds +is 1 if Expect has been invoked with commands on the program command-line (using "-c" for example). +.B exp_interactive +is 1 if Expect has been invoked with the -i flag or if no commands or script is being invoked. +.B exp_cmdfile +is a stream from which Expect will read commands. +.B exp_cmdfilename +is the name of a file which Expect will open and read commands from. +.B exp_tcl_debugger_available +is 1 if the debugger has been armed. + +.B exp_parse_argv +reads the representation of the command line. +Based on what is found, any of the other variables listed here +are initialized appropriately. +.B exp_interpreter +interactively prompts the user for commands and evaluates them. +.B exp_interpret_cmdfile +reads the given stream and evaluates any commands found. +.B exp_interpret_cmdfilename +opens the named file and evaluates any commands found. +.B exp_interpret_rcfiles +reads and evalutes the .rc files. If my_rc is zero, +then ~/.expectrc is skipped. If sys_rc is zero, then the system-wide +expectrc file is skipped. +.B exp_cook +returns a static buffer containing the argument reproduced with +newlines replaced by carriage-return linefeed sequences. +The primary purpose of this is to allow messages to be produced +without worrying about whether the terminal is in raw mode or +cooked mode. +If length is zero, it is computed via strlen. +.B exp_error is a printf-like function that writes the result +to interp->result. +.SH SYNOPSIS +.nf +.B #include <expect.h> + +.B int +.B "exp_spawnl(file, arg0 [, arg1, ..., argn] (char *)0);" +.B char *file; +.B char *arg0, *arg1, ... *argn; + +.B int +.B exp_spawnv(file,argv); +.B char *file, *argv[ ]; + +.B int +.B exp_spawnfd(fd); +.B int fd; + +.B FILE * +.B exp_popen(command); +.B char *command; + +.B extern int exp_pid; +.B extern int exp_ttyinit; +.B extern int exp_ttycopy; +.B extern int exp_console; +.B extern char *exp_stty_init; +.B extern void (*exp_close_in_child)(); +.B extern void (*exp_child_exec_prelude)(); +.B extern void exp_close_tcl_files(); + +.B cc files... \-lexpect \-ltcl \-lm +.fi + +.SH DESCRIPTION +.B exp_spawnl +and +.B exp_spawnv +fork a new process so that its stdin, +stdout, and stderr can be written and read by the current process. +.I file +is the name of a file to be executed. The +.I arg +pointers are +null-terminated strings. Following the style of execve(), +.I arg0 +(or +.IR argv[0] ) +is customarily a duplicate of the name of the file. +.PP +Four interfaces are available, +.B exp_spawnl +is useful when the number of +arguments is known at compile time. +.B exp_spawnv +is useful when the number of arguments is not known at compile time. +.B exp_spawnfd +is useful when an open file descriptor is already available as a source. +.B exp_popen +is explained later on. +.PP +If the process is successfully created, a file descriptor is returned +which corresponds to the process's stdin, stdout and stderr. +A stream may be associated with the file descriptor by using fdopen(). +(This should almost certainly be followed by setbuf() to unbuffer the I/O.) +.PP +Closing the file descriptor will typically be detected by the +process as an EOF. Once such a process exits, it should be waited +upon (via wait) in order to free up the kernel process slot. (Some systems +allow you to avoid this if you ignore the SIGCHLD signal). +.PP +.B exp_popen +is yet another interface, styled after popen(). It takes a Bourne +shell command line, and returns a stream that corresponds to the process's +stdin, stdout and stderr. The actual implementation of +.B exp_popen +below demonstrates +.BR exp_spawnl . +.nf + +FILE * +exp_popen(program) +char *program; +{ + FILE *fp; + int ec; + + if (0 > (ec = exp_spawnl("sh","sh","-c",program,(char *)0))) + return(0); + if (NULL == (fp = fdopen(ec,"r+")) return(0); + setbuf(fp,(char *)0); + return(fp); +} +.fi + +After a process is started, the variable +.B exp_pid +is set to the process-id of the new process. The variable +.B exp_pty_slave_name +is set to the name of the slave side of the pty. + +The spawn functions uses a pty to communicate with the process. By +default, the pty is initialized the same way as the user's tty (if +possible, i.e., if the environment has a controlling terminal.) This +initialization can be skipped by setting exp_ttycopy to 0. + +The pty is further initialized to some system wide defaults if +exp_ttyinit is non-zero. The default is generally comparable to "stty sane". + +The tty setting can be further modified by setting the variable +.BR exp_stty_init . +This variable is interpreted in the style of stty arguments. For +example, exp_stty_init = "sane"; repeats the default initialization. + +On some systems, it is possible to redirect console output to ptys. +If this is supported, you can force the next spawn to obtain the +console output by setting the variable +.B exp_console +to 1. + +Between the time a process is started and the new program is given +control, the spawn functions can clean up the environment by closing +file descriptors. By default, the only file descriptors closed are +ones internal to Expect and any marked "close-on-exec". + +If needed, you can close additional file descriptors by creating +an appropriate function and assigning it to exp_close_in_child. +The function will be called after the fork and before the exec. +(This also modifies the behavior of the spawn command in Expect.) + +If you are also using Tcl, it may be convenient to use the function +exp_close_tcl_files which closes all files between the default +standard file descriptors and the highest descriptor known to Tcl. +(Expect does this.) + +The function exp_child_exec_prelude is the last function called prior +to the actual exec in the child. You can redefine this for effects +such as manipulating the uid or the signals. + +.SH "IF YOU WANT TO ALLOCATE YOUR OWN PTY" +.nf + +.B extern int exp_autoallocpty; +.B extern int exp_pty[2]; +.fi + +The spawn functions use a pty to communicate with the process. By +default, a pty is automatically allocated each time a process is spawned. +If you want to allocate ptys yourself, before calling one of the spawn +functions, set +.B exp_autoallocpty +to 0, +.B exp_pty[0] +to the master pty file descriptor and +.B exp_pty[1] +to the slave pty file descriptor. +The expect library will not do any pty initializations (e.g., exp_stty_init will not be used). +The slave pty file descriptor will be +automatically closed when the process is spawned. After the process is +started, all further communication takes place with the master pty file +descriptor. +.PP +.B exp_spawnl +and +.B exp_spawnv +duplicate the shell's actions +in searching for an executable file in a list of directories. The +directory list is obtained from the environment. +.SH EXPECT PROCESSING +While it is possible to use read() to read information from a process +spawned by +.B exp_spawnl +or +.BR exp_spawnv , +more convenient functions are provided. They are as +follows: +.nf + +.B int +.B exp_expectl(fd,type1,pattern1,[re1,],value1,type2,...,exp_end); +.B int fd; +.B enum exp_type type; +.B char *pattern1, *pattern2, ...; +.B regexp *re1, *re2, ...; +.B int value1, value2, ...; +.B + +.B int +.B exp_fexpectl(fp,type1,pattern1,[re1,]value1,type2,...,exp_end); +.B FILE *fp; +.B enum exp_type type; +.B char *pattern1, *pattern2, ...; +.B regexp *re1, *re2, ...; +.B int value1, value2, ...; + +.B enum exp_type { +.B exp_end, +.B exp_glob, +.B exp_exact, +.B exp_regexp, +.B exp_compiled, +.B exp_null, +.B }; + +.B struct exp_case { +.B char *pattern; +.B regexp *re; +.B enum exp_type type; +.B int value; +.B }; + +.B int +.B exp_expectv(fd,cases); +.B int fd; +.B struct exp_case *cases; + +.B int +.B exp_fexpectv(fp,cases); +.B FILE *fp; +.B struct exp_case *cases; + +.B extern int exp_timeout; +.B extern char *exp_match; +.B extern char *exp_match_end; +.B extern char *exp_buffer; +.B extern char *exp_buffer_end; +.B extern int exp_match_max; +.B extern int exp_full_buffer; +.B extern int exp_remove_nulls; +.fi + +The functions wait until the output from a process matches one of the +patterns, a specified time period has passed, or an EOF is seen. +.PP +The first argument to each function is either a file descriptor or a stream. +Successive sets of arguments describe patterns and associated integer values +to return when the pattern matches. +.PP +The type argument is one of four values. exp_end indicates that no more +patterns appear. +exp_glob indicates that the pattern is a glob-style string pattern. +exp_exact indicates that the pattern is an exact string. +exp_regexp indicates that the pattern is a regexp-style string pattern. +exp_compiled indicates that the pattern is a regexp-style string pattern, +and that its compiled form is also provided. +exp_null indicates that the pattern is a null (for debugging purposes, +a string pattern must also follow). +.PP +If the compiled form is not provided with the functions +.B exp_expectl +and +.BR exp_fexpectl , +any pattern compilation done internally is +thrown away after the function returns. The functions +.B exp_expectv +and +.B exp_fexpectv +will automatically compile patterns and will not throw them away. +Instead, they must be discarded by the user, by calling free on each +pattern. It is only necessary to discard them, the last time the +cases are used. +.PP +Regexp subpatterns matched are stored in the compiled regexp. +Assuming "re" contains a compiled regexp, the matched string can be +found in re->startp[0]. The match substrings (according to the parentheses) +in the original pattern can be found in re->startp[1], re->startp[2], and +so on, up to re->startp[9]. The corresponding strings ends are re->endp[x] +where x is that same index as for the string start. + +The type exp_null matches if a null appears in the input. The +variable exp_remove_nulls must be set to 0 to prevent nulls from +being automatically stripped. By default, exp_remove_nulls is set +to 1 and nulls are automatically stripped. + +.B exp_expectv +and +.B exp_fexpectv +are useful when the number of patterns is +not known in advance. In this case, the sets are provided in an array. +The end of the array is denoted by a struct exp_case with type exp_end. +For the rest +of this discussion, these functions will be referred to generically as +.IR expect. +.PP +If a pattern matches, then the corresponding integer value is returned. +Values need not be unique, however they should be positive to avoid +being mistaken for EXP_EOF, EXP_TIMEOUT, or EXP_FULLBUFFER. +Upon EOF or timeout, the value +.B EXP_EOF +or +.B EXP_TIMEOUT +is returned. The +default timeout period is 10 seconds but may be changed by setting the +variable +.BR exp_timeout . +A value of -1 +disables a timeout from occurring. +A value of 0 causes the expect function to return immediately (i.e., poll) +after one read(). +However it must be preceded by a function such as select, poll, or +an event manager callback to guarantee that there is data to be read. + +If the variable exp_full_buffer is 1, then EXP_FULLBUFFER is returned +if exp_buffer fills with no pattern having matched. + +When the expect function returns, +.B exp_buffer +points to the buffer +of characters that was being considered for matching. +.B exp_buffer_end +points to one past the last character in exp_buffer. +If a match occurred, +.B exp_match +points into +.B exp_buffer +where the match began. +.B exp_match_end +points to one character past where the match ended. +.PP +Each time new input arrives, it is compared to each pattern in the +order they are listed. Thus, you may test for absence of a match by +making the last pattern something guaranteed to appear, such as a +prompt. In situations where there is no prompt, you must check for +.B EXP_TIMEOUT +(just like you would if you were interacting manually). More philosophy +and strategies on specifying +.B expect +patterns can be found in the +documentation on the +.B expect +program itself. See SEE ALSO below. +.PP +Patterns are the usual C-shell-style regular expressions. For +example, the following fragment looks for a successful login, such +as from a telnet dialogue. +.nf + + switch (exp_expectl( + exp_glob,"connected",CONN, + exp_glob,"busy",BUSY, + exp_glob,"failed",ABORT, + exp_glob,"invalid password",ABORT, + exp_end)) { + case CONN: /* logged in successfully */ + break; + case BUSY: /* couldn't log in at the moment */ + break; + case EXP_TIMEOUT: + case ABORT: /* can't log in at any moment! */ + break; + default: /* problem with expect */ + } +.fi + +Asterisks (as in the +example above) are a useful shorthand for omitting line-termination +characters and other detail. +Patterns must match the entire output of the current process (since +the previous read on the descriptor or stream). +More than 2000 bytes of output can +force earlier bytes to be "forgotten". This may be changed by setting +the variable +.BR exp_match_max . +Note that excessively large values can slow down the pattern matcher. +.SH RUNNING IN THE BACKGROUND +.nf + +.B extern int exp_disconnected; +.B int exp_disconnect(); + +.fi +It is possible to move a process into the background after it has +begun running. A typical use for this is to read passwords and then +go into the background to sleep before using the passwords to do real +work. +.PP +To move a process into the background, fork, call exp_disconnect() in the +child process and exit() in the parent process. This disassociates +your process from the controlling terminal. If you wish to move a +process into the background in a different way, you must set the +variable exp_disconnected to 1. This allows processes spawned after +this point to be started correctly. +.SH MULTIPLEXING +By default, the expect functions block inside of a read on a single file +descriptor. If you want to wait on patterns from multiple file +descriptors, +use select, poll, or an event manager. +They will tell you what file descriptor is ready to read. + +When a file descriptor is ready to read, you can use the expect +functions to do one and only read by setting timeout to 0. +.SH SLAVE CONTROL + +.nf + +.B void +.B exp_slave_control(fd,enable) +.B int fd; +.B int enable; + +.fi + +Pty trapping is normally done automatically by the expect functions. +However, if you want to issue an ioctl, for example, directly on the +slave device, you should temporary disable trapping. + +Pty trapping can be controlled with exp_slave_control. The first +argument is the file descriptor corresponding to the spawned process. +The second argument is a 0 if trapping is to be disabled and 1 if it +is to be enabled. + +.SH ERRORS +All functions indicate errors by returning \-1 and setting errno. +.PP +Errors that occur after the spawn functions fork (e.g., attempting to +spawn a non-existent program) are written to the process's stderr, +and will be read by the first +.BR expect . +.SH SIGNALS +.nf +.B extern int exp_reading; +.B extern jmp_buf exp_readenv; +.fi + +.B expect +uses alarm() to timeout, thus if you generate alarms during +.BR expect , +it will timeout prematurely. +.PP +Internally, +.B expect +calls read() which can be interrupted by signals. If +you define signal handlers, you can choose to restart or abort +.BR expect 's +internal read. The variable, +.BR exp_reading , +is true if (and only if) +.BR expect 's +read has been interrupted. longjmp(exp_readenv,EXP_ABORT) will abort +the read. longjmp(exp_readenv,EXP_RESTART) will restart the read. +.SH LOGGING +.nf + +.B extern int exp_loguser; +.B extern int exp_logfile_all +.B extern FILE *exp_logfile; +.fi + +If +.B exp_loguser +is nonzero, +.B expect +sends any output from the spawned process to +stdout. Since interactive programs typically echo their input, this +usually suffices to show both sides of the conversation. If +.B exp_logfile +is also nonzero, this same output is written to the stream defined by +.BR exp_logfile . +If +.B exp_logfile_all +is non-zero, +.B exp_logfile +is written regardless of the value of +.BR exp_loguser . + +.SH DEBUGGING +While I consider the library to be easy to use, I think that the +standalone expect program is much, much, easier to use than working +with the C compiler and its usual edit, compile, debug cycle. Unlike +typical C programs, most of the debugging isn't getting the C compiler +to accept your programs - rather, it is getting the dialogue correct. +Also, translating scripts from expect to C is usually not necessary. +For example, the speed of interactive dialogues is virtually never an +issue. So please try the standalone 'expect' program first. I +suspect it is a more appropriate solution for most people than the +library. +.PP +Nonetheless, if you feel compelled to debug in C, +here are some tools to help you. +.nf + +.B extern int exp_is_debugging; +.B extern FILE *exp_debugfile; +.fi + +While expect dialogues seem very intuitive, trying to codify them in a +program can reveal many surprises in a program's interface. Therefore +a variety of debugging aids are available. They are controlled by the +above variables, all 0 by default. + +Debugging information internal to +.B expect +is sent to stderr when +.B exp_is_debugging +is non-zero. The debugging information includes +every character received, and every attempt made to match the current +input against the patterns. In addition, non-printable characters are +translated to a printable form. For example, a control-C appears as a +caret followed by a C. If +.B exp_logfile +is non-zero, this information +is also written to that stream. +.PP +If +.B exp_debugfile +is non-zero, all normal and debugging information is +written to that stream, regardless of the value of +.BR exp_is_debugging . +.SH CAVEATS +The stream versions of the +.B expect +functions are much slower than the +file descriptor versions because there is no way to portably read +an unknown number of bytes without the potential of timing out. +Thus, characters are read one at a time. You are therefore strongly +encouraged to use the file descriptor versions of +.B expect +(although, +automated versions of interactive programs don't usually demand high speed +anyway). +.PP +You can actually get the best of both worlds, writing with the usual +stream functions and reading with the file descriptor versions of +.B expect +as long as you don't attempt to intermix other stream input +functions (e.g., fgetc). +To do this, pass fileno(stream) as the file descriptor each time. +Fortunately, there is little reason to use anything but the +.B expect +functions when reading from interactive programs. +.PP +There is no matching exp_pclose to exp_popen (unlike popen and pclose). +It only takes two functions to close down a connection (fclose() followed +by waiting on the pid), but it is not uncommon to separate these two +actions by large time intervals, so the function seems of little value. +.PP +If you are running on a Cray running Unicos (all I know for sure from +experience), you must run your compiled program as root or setuid. The +problem is that the Cray only allows root processes to open ptys. +You should observe as much precautions as possible: If you don't need +permissions, setuid(0) only immediately before calling one of the spawn +functions and immediately set it back afterwards. +.PP +Normally, +.B spawn +takes little time to execute. If you notice spawn taking a +significant amount of time, it is probably encountering ptys that are +wedged. A number of tests are run on ptys to avoid entanglements with +errant processes. (These take 10 seconds per wedged pty.) Running +expect with the \-d option will show if +.B expect +is encountering many ptys in odd states. If you cannot kill +the processes to which these ptys are attached, your only recourse may +be to reboot. +.SH BUGS +The +.B exp_fexpect +functions don't work at all under HP-UX - it appears to be a bug in getc. +Follow the +advice (above) about using the +.B exp_expect +functions (which doesn't need to call getc). If you fix the problem (before +I do - please check the latest release) let me know. +.SH SEE ALSO +An alternative to this library is the +.B expect +program. +.B expect +interprets scripts written in a high-level language +which direct the dialogue. +In addition, the user can take control and interact directly when desired. +If it is not absolutely necessary to write your own C program, it is much +easier to use +.B expect +to perform the entire interaction. +It is described further in the following references: +.PP +.I +"expect: Curing Those Uncontrollable Fits of Interactivity" \fRby Don Libes, +Proceedings of the Summer 1990 USENIX Conference, +Anaheim, California, June 11-15, 1990. +.PP +.I +"Using expect to Automate System Administration Tasks" \fRby Don Libes, +Proceedings of the 1990 USENIX Large Installation Systems Administration +Conference, Colorado Springs, Colorado, October 17-19, 1990. +.PP +expect(1), alarm(3), read(2), write(2), fdopen(3), execve(2), execvp(3), +longjmp(3), pty(4). +.PP +There are several examples C programs in the test directory of +.BR expect 's +source distribution which use the expect library. +.PP +.SH AUTHOR +Don Libes, libes@nist.gov, National Institute of Standards and Technology +.SH ACKNOWLEDGEMENTS +Thanks to John Ousterhout (UCBerkeley) for supplying the pattern +matcher. +.PP +Design and implementation of the +.B expect +library was paid for by the U.S. government and is therefore in the public +domain. +However the author and NIST would like credit +if this program and documentation or portions of them are used. diff --git a/license.terms b/license.terms new file mode 100644 index 0000000..4d5b707 --- /dev/null +++ b/license.terms @@ -0,0 +1,7 @@ +Expect
+
+Written by: Don Libes, libes at nist.gov, NIST
+
+Design and implementation of this program was paid for by U.S. tax
+dollars. Therefore it is public domain. However, the author and NIST
+would appreciate credit if this program or parts of it are used.
diff --git a/pty_sgttyb.c b/pty_sgttyb.c new file mode 100644 index 0000000..8389eef --- /dev/null +++ b/pty_sgttyb.c @@ -0,0 +1,249 @@ +/* pty_bsd.c - routines to allocate ptys - BSD version + +Written by: Don Libes, NIST, 2/6/90 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include <stdio.h> /* tmp for debugging */ +#include <signal.h> + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#include <sys/types.h> +#include <sys/stat.h> +/*** #include <sys/ioctl.h> ***/ +#include <sys/file.h> +#include <signal.h> +#include <setjmp.h> +#include "expect_cf.h" +#include "exp_rename.h" +#include "exp_tty_in.h" +#include "exp_pty.h" + +void expDiagLog(); +void expDiagLogU(); + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +static char master_name[] = "/dev/ptyXX"; /* master */ +static char slave_name[] = "/dev/ttyXX"; /* slave */ +static char *tty_type; /* ptr to char [pt] denoting + whether it is a pty or tty */ +static char *tty_bank; /* ptr to char [p-z] denoting + which bank it is */ +static char *tty_num; /* ptr to char [0-f] denoting + which number it is */ +char *exp_pty_slave_name; +char *exp_pty_error; + +static void +pty_stty(s,name) +char *s; /* args to stty */ +char *name; /* name of pty */ +{ +#define MAX_ARGLIST 10240 + char buf[MAX_ARGLIST]; /* overkill is easier */ + RETSIGTYPE (*old)(); /* save old sigalarm handler */ + +#ifdef STTY_READS_STDOUT + sprintf(buf,"%s %s > %s",STTY_BIN,s,name); +#else + sprintf(buf,"%s %s < %s",STTY_BIN,s,name); +#endif + old = signal(SIGCHLD, SIG_DFL); + system(buf); + signal(SIGCHLD, old); /* restore signal handler */ +} + +int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */ +static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */ + +#ifdef TIOCGWINSZ +static struct winsize winsize = {0, 0}; +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) +static struct ttysize winsize = {0, 0}; +#endif + +exp_tty exp_tty_original; + +#define GET_TTYTYPE 0 +#define SET_TTYTYPE 1 +static void +ttytype(request,fd,ttycopy,ttyinit,s) +int request; +int fd; + /* following are used only if request == SET_TTYTYPE */ +int ttycopy; /* if true, copy from /dev/tty */ +int ttyinit; /* if true, initialize to sane state */ +char *s; /* stty args */ +{ + static struct tchars tc; /* special characters */ + static struct ltchars lc; /* local special characters */ + static struct winsize win; /* window size */ + static int lb; /* local modes */ + static int l; /* line discipline */ + + if (request == GET_TTYTYPE) { + if (-1 == ioctl(fd, TIOCGETP, (char *)&exp_tty_original) + || -1 == ioctl(fd, TIOCGETC, (char *)&tc) + || -1 == ioctl(fd, TIOCGETD, (char *)&l) + || -1 == ioctl(fd, TIOCGLTC, (char *)&lc) + || -1 == ioctl(fd, TIOCLGET, (char *)&lb) + || -1 == ioctl(fd, TIOCGWINSZ, (char *)&win)) { + knew_dev_tty = FALSE; + exp_dev_tty = -1; + } +#ifdef TIOCGWINSZ + ioctl(fd,TIOCGWINSZ,&winsize); +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) + ioctl(fd,TIOCGSIZE,&winsize); +#endif + } else { /* type == SET_TTYTYPE */ + if (ttycopy && knew_dev_tty) { + (void) ioctl(fd, TIOCSETP, (char *)&exp_tty_current); + (void) ioctl(fd, TIOCSETC, (char *)&tc); + (void) ioctl(fd, TIOCSLTC, (char *)&lc); + (void) ioctl(fd, TIOCLSET, (char *)&lb); + (void) ioctl(fd, TIOCSETD, (char *)&l); + (void) ioctl(fd, TIOCSWINSZ, (char *)&win); +#ifdef TIOCSWINSZ + ioctl(fd,TIOCSWINSZ,&winsize); +#endif +#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ) + ioctl(fd,TIOCGSIZE,&winsize); +#endif + } + +#ifdef __CENTERLINE__ +#undef DFLT_STTY +#define DFLT_STTY "sane" +#endif + +/* Apollo Domain doesn't need this */ +#ifdef DFLT_STTY + if (ttyinit) { + /* overlay parms originally supplied by Makefile */ + pty_stty(DFLT_STTY,slave_name); + } +#endif + + /* lastly, give user chance to override any terminal parms */ + if (s) { + pty_stty(s,slave_name); + } + } +} + +void +exp_init_pty() +{ + tty_type = & slave_name[strlen("/dev/")]; + tty_bank = &master_name[strlen("/dev/pty")]; + tty_num = &master_name[strlen("/dev/ptyp")]; + + exp_dev_tty = open("/dev/tty",O_RDWR); + +#if experimental + /* code to allocate force expect to get a controlling tty */ + /* even if it doesn't start with one (i.e., under cron). */ + /* This code is not necessary, but helpful for testing odd things. */ + if (exp_dev_tty == -1) { + /* give ourselves a controlling tty */ + int master = exp_getptymaster(); + fcntl(master,F_SETFD,1); /* close-on-exec */ + setpgrp(0,0); + close(0); + close(1); + exp_getptyslave(exp_get_var(exp_interp,"stty_init")); + close(2); + fcntl(0,F_DUPFD,2); /* dup 0 onto 2 */ + } +#endif + + knew_dev_tty = (exp_dev_tty != -1); + if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0); +} + +/* returns fd of master end of pseudotty */ +int +exp_getptymaster() +{ + int master = -1; + char *hex, *bank; + struct stat statbuf; + + exp_pty_error = 0; + + if (exp_pty_test_start() == -1) return -1; + + for (bank = "pqrstuvwxyzPQRSTUVWXYZ";*bank;bank++) { + *tty_bank = *bank; + *tty_num = '0'; + if (stat(master_name, &statbuf) < 0) break; + for (hex = "0123456789abcdef";*hex;hex++) { + *tty_num = *hex; + + /* generate slave name from master */ + strcpy(slave_name,master_name); + *tty_type = 't'; + + master = exp_pty_test(master_name,slave_name, + *tty_bank,tty_num); + if (master >= 0) goto done; + } + } + done: + exp_pty_test_end(); + exp_pty_slave_name = slave_name; + return(master); +} + +/* see comment in pty_termios.c */ +/*ARGSUSED*/ +void +exp_slave_control(master,control) +int master; +int control; +{ +} + +int +exp_getptyslave(ttycopy,ttyinit,stty_args) +int ttycopy; +int ttyinit; +char *stty_args; +{ + int slave; + + if (0 > (slave = open(slave_name, O_RDWR))) return(-1); + + if (0 == slave) { + /* if opened in a new process, slave will be 0 (and */ + /* ultimately, 1 and 2 as well) */ + + /* duplicate 0 onto 1 and 2 to prepare for stty */ + fcntl(0,F_DUPFD,1); + fcntl(0,F_DUPFD,2); + } + + ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args); + (void) exp_pty_unlock(); + return(slave); +} + +void +exp_pty_exit() +{ + /* a stub so we can do weird things on the cray */ +} diff --git a/pty_termios.c b/pty_termios.c new file mode 100644 index 0000000..c605b23 --- /dev/null +++ b/pty_termios.c @@ -0,0 +1,781 @@ +/* pty_termios.c - routines to allocate ptys - termios version + +Written by: Don Libes, NIST, 2/6/90 + +This file is in the public domain. However, the author and NIST +would appreciate credit if you use this file or parts of it. + +*/ + +#include <stdio.h> +#include <signal.h> + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#include "expect_cf.h" + +/* + The following functions are linked from the Tcl library. They + don't cause anything else in the library to be dragged in, so it + shouldn't cause any problems (e.g., bloat). + + The functions are relatively small but painful enough that I don't care + to recode them. You may, if you absolutely want to get rid of any + vestiges of Tcl. +*/ +extern char *TclGetRegError(); + +#if defined(HAVE_PTMX_BSD) && defined(HAVE_PTMX) +/* + * Some systems have both PTMX and PTMX_BSD. + * In fact, alphaev56-dec-osf4.0e has /dev/pts, /dev/pty, /dev/ptym, + * /dev/ptm, /dev/ptmx, and /dev/ptmx_bsd + * Suggestion from Martin Buchholz <martin@xemacs.org> is that BSD + * is usually deprecated and so should be here. + */ +#undef HAVE_PTMX_BSD +#endif + +/* Linux and Digital systems can be configured to have both. +According to Ashley Pittman <ashley@ilo.dec.com>, Digital works better +with openpty which supports 4000 while ptmx supports 60. */ +#if defined(HAVE_OPENPTY) && defined(HAVE_PTMX) +#undef HAVE_PTMX +#endif + +#if defined(HAVE_PTYM) && defined(HAVE_PTMX) +/* + * HP-UX 10.0 with streams (optional) have both PTMX and PTYM. I don't + * know which is preferred but seeing as how the HP trap stuff is so + * unusual, it is probably safer to stick with the native HP pty support, + * too. + */ +#undef HAVE_PTMX +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef NO_STDLIB_H +#include "../compat/stdlib.h" +#else +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_SYSMACROS_H +#include <sys/sysmacros.h> +#endif + +#ifdef HAVE_PTYTRAP +#include <sys/ptyio.h> +#endif + +#include <sys/file.h> + +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif + +#if defined(_SEQUENT_) +# include <sys/strpty.h> +#endif + +#if defined(HAVE_PTMX) && defined(HAVE_STROPTS_H) +# include <sys/stropts.h> +#endif + +#include "exp_win.h" + +#include "exp_tty_in.h" +#include "exp_rename.h" +#include "exp_pty.h" + +void expDiagLog(); +void expDiagLogPtr(); + +#include <errno.h> +/*extern char *sys_errlist[];*/ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* Convex getpty is different than older-style getpty */ +/* Convex getpty is really just a cover function that does the traversal */ +/* across the domain of pty names. It makes no attempt to verify that */ +/* they can actually be used. Indded, the logic in the man page is */ +/* wrong because it will allow you to allocate ptys that your own account */ +/* already has in use. */ +#if defined(HAVE_GETPTY) && defined(CONVEX) +#undef HAVE_GETPTY +#define HAVE_CONVEX_GETPTY +extern char *getpty(); +static char *master_name; +static char slave_name[] = "/dev/ptyXX"; +static char *tty_bank; /* ptr to char [p-z] denoting + which bank it is */ +static char *tty_num; /* ptr to char [0-f] denoting + which number it is */ +#endif + +#if defined(_SEQUENT_) && !defined(HAVE_PTMX) +/* old-style SEQUENT, new-style uses ptmx */ +static char *master_name, *slave_name; +#endif /* _SEQUENT */ + +/* very old SGIs prefer _getpty over ptc */ +#if defined(HAVE__GETPTY) && defined(HAVE_PTC) && !defined(HAVE_GETPTY) +#undef HAVE_PTC +#endif + +#if defined(HAVE_PTC) +static char slave_name[] = "/dev/ttyqXXX"; +/* some machines (e.g., SVR4.0 StarServer) have all of these and */ +/* HAVE_PTC works best */ +#undef HAVE_GETPTY +#undef HAVE__GETPTY +#endif + +#if defined(HAVE__GETPTY) || defined(HAVE_PTC_PTS) || defined(HAVE_PTMX) +static char *slave_name; +#endif + +#if defined(HAVE_GETPTY) +#include <sys/vty.h> +static char master_name[MAXPTYNAMELEN]; +static char slave_name[MAXPTYNAMELEN]; +#endif + +#if !defined(HAVE_GETPTY) && !defined(HAVE__GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX) && !defined(HAVE_CONVEX_GETPTY) && !defined(_SEQUENT_) && !defined(HAVE_SCO_CLIST_PTYS) && !defined(HAVE_OPENPTY) +#ifdef HAVE_PTYM + /* strange order and missing d is intentional */ +static char banks[] = "pqrstuvwxyzabcefghijklo"; +static char master_name[] = "/dev/ptym/ptyXXXX"; +static char slave_name[] = "/dev/pty/ttyXXXX"; +static char *slave_bank; +static char *slave_num; +#else +static char banks[] = "pqrstuvwxyzPQRSTUVWXYZ"; +static char master_name[] = "/dev/ptyXX"; +static char slave_name [] = "/dev/ttyXX"; +#endif /* HAVE_PTYM */ + +static char *tty_type; /* ptr to char [pt] denoting + whether it is a pty or tty */ +static char *tty_bank; /* ptr to char [p-z] denoting + which bank it is */ +static char *tty_num; /* ptr to char [0-f] denoting + which number it is */ +#endif + +#if defined(HAVE_SCO_CLIST_PTYS) +# define MAXPTYNAMELEN 64 +static char master_name[MAXPTYNAMELEN]; +static char slave_name[MAXPTYNAMELEN]; +#endif /* HAVE_SCO_CLIST_PTYS */ + +#ifdef HAVE_OPENPTY +static char master_name[64]; +static char slave_name[64]; +#endif + +char *exp_pty_slave_name; +char *exp_pty_error; + +#if 0 +static void +pty_stty(s,name) +char *s; /* args to stty */ +char *name; /* name of pty */ +{ +#define MAX_ARGLIST 10240 + char buf[MAX_ARGLIST]; /* overkill is easier */ + RETSIGTYPE (*old)(); /* save old sigalarm handler */ + int pid; + + old = signal(SIGCHLD, SIG_DFL); + switch (pid = fork()) { + case 0: /* child */ + exec_stty(STTY_BIN,STTY_BIN,s); + break; + case -1: /* fail */ + default: /* parent */ + waitpid(pid); + break; + } + + signal(SIGCHLD, old); /* restore signal handler */ +} + +exec_stty(s) +char *s; +{ + char *args[50]; + char *cp; + int argi = 0; + int quoting = FALSE; + int in_token = FALSE; /* TRUE if we are reading a token */ + + args[0] = cp = s; + while (*s) { + if (quoting) { + if (*s == '\\' && *(s+1) == '"') { /* quoted quote */ + s++; /* get past " */ + *cp++ = *s++; + } else if (*s == '\"') { /* close quote */ + end_token + quoting = FALSE; + } else *cp++ = *s++; /* suck up anything */ + } else if (*s == '\"') { /* open quote */ + in_token = TRUE; + quoting = TRUE; + s++; + } else if (isspace(*s)) { + end_token + } else { + *cp++ = *s++; + in_token = TRUE; + } + } + end_token + args[argi] = (char *) 0; /* terminate argv */ + execvp(args[0],args); +} +#endif /*0*/ + +static void +pty_stty(s,name) +char *s; /* args to stty */ +char *name; /* name of pty */ +{ +#define MAX_ARGLIST 10240 + char buf[MAX_ARGLIST]; /* overkill is easier */ + RETSIGTYPE (*old)(); /* save old sigalarm handler */ + +#ifdef STTY_READS_STDOUT + sprintf(buf,"%s %s > %s",STTY_BIN,s,name); +#else + sprintf(buf,"%s %s < %s",STTY_BIN,s,name); +#endif + old = signal(SIGCHLD, SIG_DFL); + system(buf); + signal(SIGCHLD, old); /* restore signal handler */ +} + +int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */ +static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */ + +exp_tty exp_tty_original; + +#define GET_TTYTYPE 0 +#define SET_TTYTYPE 1 +static void +ttytype(request,fd,ttycopy,ttyinit,s) +int request; +int fd; + /* following are used only if request == SET_TTYTYPE */ +int ttycopy; /* true/false, copy from /dev/tty */ +int ttyinit; /* if true, initialize to sane state */ +char *s; /* stty args */ +{ + if (request == GET_TTYTYPE) { +#ifdef HAVE_TCSETATTR + if (-1 == tcgetattr(fd, &exp_tty_original)) { +#else + if (-1 == ioctl(fd, TCGETS, (char *)&exp_tty_original)) { +#endif + knew_dev_tty = FALSE; + exp_dev_tty = -1; + } + exp_window_size_get(fd); + } else { /* type == SET_TTYTYPE */ + if (ttycopy && knew_dev_tty) { +#ifdef HAVE_TCSETATTR + (void) tcsetattr(fd, TCSADRAIN, &exp_tty_current); +#else + (void) ioctl(fd, TCSETS, (char *)&exp_tty_current); +#endif + + exp_window_size_set(fd); + } + +#ifdef __CENTERLINE__ +#undef DFLT_STTY +#define DFLT_STTY "sane" +#endif + +/* Apollo Domain doesn't need this */ +#ifdef DFLT_STTY + if (ttyinit) { + /* overlay parms originally supplied by Makefile */ +/* As long as BSD stty insists on stdout == stderr, we can no longer write */ +/* diagnostics to parent stderr, since stderr has is now child's */ +/* Maybe someday they will fix stty? */ +/* expDiagLogPtrStr("exp_getptyslave: (default) stty %s\n",DFLT_STTY);*/ + pty_stty(DFLT_STTY,slave_name); + } +#endif + + /* lastly, give user chance to override any terminal parms */ + if (s) { + /* give user a chance to override any terminal parms */ +/* expDiagLogPtrStr("exp_getptyslave: (user-requested) stty %s\n",s);*/ + pty_stty(s,slave_name); + } + } +} + +void +exp_init_pty() +{ +#if !defined(HAVE_GETPTY) && !defined(HAVE__GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX) && !defined(HAVE_CONVEX_GETPTY) && !defined(_SEQUENT_) && !defined(HAVE_SCO_CLIST_PTYS) && !defined(HAVE_OPENPTY) +#ifdef HAVE_PTYM + static char dummy; + tty_bank = &master_name[strlen("/dev/ptym/pty")]; + tty_num = &master_name[strlen("/dev/ptym/ptyX")]; + slave_bank = &slave_name[strlen("/dev/pty/tty")]; + slave_num = &slave_name[strlen("/dev/pty/ttyX")]; +#else + tty_bank = &master_name[strlen("/dev/pty")]; + tty_num = &master_name[strlen("/dev/ptyp")]; + tty_type = &slave_name[strlen("/dev/")]; +#endif + +#endif /* HAVE_PTYM */ + + + exp_dev_tty = open("/dev/tty",O_RDWR); + knew_dev_tty = (exp_dev_tty != -1); + if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0); +} + +#ifndef R_OK +/* 3b2 doesn't define these according to jthomas@nmsu.edu. */ +#define R_OK 04 +#define W_OK 02 +#endif + +int +exp_getptymaster() +{ + char *hex, *bank; + struct stat stat_buf; + int master = -1; + int slave = -1; + int num; + + exp_pty_error = 0; + +#define TEST_PTY 1 + +#if defined(HAVE_PTMX) || defined(HAVE_PTMX_BSD) +#undef TEST_PTY +#if defined(HAVE_PTMX_BSD) + if ((master = open("/dev/ptmx_bsd", O_RDWR)) == -1) return(-1); +#else + if ((master = open("/dev/ptmx", O_RDWR)) == -1) return(-1); +#endif + if ((slave_name = (char *)ptsname(master)) == NULL) { + close(master); + return(-1); + } + if (grantpt(master)) { + static char buf[500]; + exp_pty_error = buf; + sprintf(exp_pty_error,"grantpt(%s) failed - likely reason is that your system administrator (in a rage of blind passion to rid the system of security holes) removed setuid from the utility used internally by grantpt to change pty permissions. Tell your system admin to reestablish setuid on the utility. Get the utility name by running Expect under truss or trace.", expErrnoMsg(errno)); + close(master); + return(-1); + } + if (-1 == (int)unlockpt(master)) { + static char buf[500]; + exp_pty_error = buf; + sprintf(exp_pty_error,"unlockpt(%s) failed.", expErrnoMsg(errno)); + close(master); + return(-1); + } +#ifdef TIOCFLUSH + (void) ioctl(master,TIOCFLUSH,(char *)0); +#endif /* TIOCFLUSH */ + + exp_pty_slave_name = slave_name; + return(master); +#endif + +#if defined(HAVE__GETPTY) /* SGI needs it this way */ +#undef TEST_PTY + slave_name = _getpty(&master, O_RDWR, 0600, 0); + if (slave_name == NULL) + return (-1); + exp_pty_slave_name = slave_name; + return(master); +#endif + +#if defined(HAVE_PTC) && !defined(HAVE__GETPTY) /* old SGI, version 3 */ +#undef TEST_PTY + master = open("/dev/ptc", O_RDWR); + if (master >= 0) { + int ptynum; + + if (fstat(master, &stat_buf) < 0) { + close(master); + return(-1); + } + ptynum = minor(stat_buf.st_rdev); + sprintf(slave_name,"/dev/ttyq%d",ptynum); + } + exp_pty_slave_name = slave_name; + return(master); +#endif + +#if defined(HAVE_GETPTY) && !defined(HAVE__GETPTY) +#undef TEST_PTY + master = getpty(master_name, slave_name, O_RDWR); + /* is it really necessary to verify slave side is usable? */ + exp_pty_slave_name = slave_name; + return master; +#endif + +#if defined(HAVE_PTC_PTS) +#undef TEST_PTY + master = open("/dev/ptc",O_RDWR); + if (master >= 0) { + /* never fails */ + slave_name = ttyname(master); + } + exp_pty_slave_name = slave_name; + return(master); +#endif + +#if defined(_SEQUENT_) && !defined(HAVE_PTMX) +#undef TEST_PTY + /* old-style SEQUENT, new-style uses ptmx */ + master = getpseudotty(&slave_name, &master_name); + exp_pty_slave_name = slave_name; + return(master); +#endif /* _SEQUENT_ */ + +#if defined(HAVE_OPENPTY) +#undef TEST_PTY + if (openpty(&master, &slave, master_name, 0, 0) != 0) { + close(master); + close(slave); + return -1; + } + strcpy(slave_name, ttyname(slave)); + exp_pty_slave_name = slave_name; + close(slave); + return master; +#endif /* HAVE_OPENPTY */ + +#if defined(TEST_PTY) + /* + * all pty allocation mechanisms after this require testing + */ + if (exp_pty_test_start() == -1) return -1; + +#if !defined(HAVE_CONVEX_GETPTY) && !defined(HAVE_PTYM) && !defined(HAVE_SCO_CLIST_PTYS) + for (bank = banks;*bank;bank++) { + *tty_bank = *bank; + *tty_num = '0'; + if (stat(master_name, &stat_buf) < 0) break; + for (hex = "0123456789abcdef";*hex;hex++) { + *tty_num = *hex; + strcpy(slave_name,master_name); + *tty_type = 't'; + master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num); + if (master >= 0) goto done; + } + } +#endif + +#ifdef HAVE_SCO_CLIST_PTYS + for (num = 0; ; num++) { + char num_str [16]; + + sprintf (num_str, "%d", num); + sprintf (master_name, "%s%s", "/dev/ptyp", num_str); + if (stat (master_name, &stat_buf) < 0) + break; + sprintf (slave_name, "%s%s", "/dev/ttyp", num_str); + + master = exp_pty_test(master_name,slave_name,'0',num_str); + if (master >= 0) + goto done; + } +#endif + +#ifdef HAVE_PTYM + /* systems with PTYM follow this idea: + + /dev/ptym/pty[a-ce-z][0-9a-f] master pseudo terminals + /dev/pty/tty[a-ce-z][0-9a-f] slave pseudo terminals + /dev/ptym/pty[a-ce-z][0-9][0-9] master pseudo terminals + /dev/pty/tty[a-ce-z][0-9][0-9] slave pseudo terminals + + SPPUX (Convex's HPUX compatible) follows the PTYM convention but + extends it: + + /dev/ptym/pty[a-ce-z][0-9][0-9][0-9] master pseudo terminals + /dev/pty/tty[a-ce-z][0-9][0-9][0-9] slave pseudo terminals + + The code does not distinguish between HPUX and SPPUX because there + is no reason to. HPUX will merely fail the extended SPPUX tests. + In fact, most SPPUX systems will fail simply because few systems + will actually have the extended ptys. However, the tests are + fast so it is no big deal. + */ + + /* + * pty[a-ce-z][0-9a-f] + */ + + for (bank = banks;*bank;bank++) { + *tty_bank = *bank; + sprintf(tty_num,"0"); + if (stat(master_name, &stat_buf) < 0) break; + *(slave_num+1) = '\0'; + for (hex = "0123456789abcdef";*hex;hex++) { + *tty_num = *hex; + *slave_bank = *tty_bank; + *slave_num = *tty_num; + master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num); + if (master >= 0) goto done; + } + } + + /* + * tty[p-za-ce-o][0-9][0-9] + */ + + for (bank = banks;*bank;bank++) { + *tty_bank = *bank; + sprintf(tty_num,"00"); + if (stat(master_name, &stat_buf) < 0) break; + for (num = 0; num<100; num++) { + *slave_bank = *tty_bank; + sprintf(tty_num,"%02d",num); + strcpy(slave_num,tty_num); + master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num); + if (master >= 0) goto done; + } + } + + /* + * tty[p-za-ce-o][0-9][0-9][0-9] + */ + for (bank = banks;*bank;bank++) { + *tty_bank = *bank; + sprintf(tty_num,"000"); + if (stat(master_name, &stat_buf) < 0) break; + for (num = 0; num<1000; num++) { + *slave_bank = *tty_bank; + sprintf(tty_num,"%03d",num); + strcpy(slave_num,tty_num); + master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num); + if (master >= 0) goto done; + } + } + +#endif /* HAVE_PTYM */ + +#if defined(HAVE_CONVEX_GETPTY) + for (;;) { + if ((master_name = getpty()) == NULL) return -1; + + strcpy(slave_name,master_name); + slave_name[5] = 't';/* /dev/ptyXY ==> /dev/ttyXY */ + + tty_bank = &slave_name[8]; + tty_num = &slave_name[9]; + master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num); + if (master >= 0) goto done; + } +#endif + + done: + exp_pty_test_end(); + exp_pty_slave_name = slave_name; + return(master); + +#endif /* defined(TEST_PTY) */ +} + +/* if slave is opened in a child, slave_control(1) must be executed after */ +/* master is opened (when child is opened is irrelevent) */ +/* if slave is opened in same proc as master, slave_control(1) must executed */ +/* after slave is opened */ +/*ARGSUSED*/ +void +exp_slave_control(master,control) +int master; +int control; /* if 1, enable pty trapping of close/open/ioctl */ +{ +#ifdef HAVE_PTYTRAP + ioctl(master, TIOCTRAP, &control); +#endif /* HAVE_PTYTRAP */ +} + +int +exp_getptyslave( + int ttycopy, + int ttyinit, + CONST char *stty_args) +{ + int slave, slave2; + char buf[10240]; + + if (0 > (slave = open(slave_name, O_RDWR))) { + static char buf[500]; + exp_pty_error = buf; + sprintf(exp_pty_error,"open(%s,rw) = %d (%s)",slave_name,slave,expErrnoMsg(errno)); + return(-1); + } + +#if defined(HAVE_PTMX_BSD) + if (ioctl (slave, I_LOOK, buf) != 0) + if (ioctl (slave, I_PUSH, "ldterm")) { + expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ldterm\") = %s\n",slave,expErrnoMsg(errno)); + } +#else +#if defined(HAVE_PTMX) + if (ioctl(slave, I_PUSH, "ptem")) { + expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ptem\") = %s\n",slave,expErrnoMsg(errno)); + } + if (ioctl(slave, I_PUSH, "ldterm")) { + expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ldterm\") = %s\n",slave,expErrnoMsg(errno)); + } + if (ioctl(slave, I_PUSH, "ttcompat")) { + expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ttcompat\") = %s\n",slave,expErrnoMsg(errno)); + } +#endif +#endif + + if (0 == slave) { + /* if opened in a new process, slave will be 0 (and */ + /* ultimately, 1 and 2 as well) */ + + /* duplicate 0 onto 1 and 2 to prepare for stty */ + fcntl(0,F_DUPFD,1); + fcntl(0,F_DUPFD,2); + } + + ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args); + +#if 0 +#ifdef HAVE_PTYTRAP + /* do another open, to tell master that slave is done fiddling */ + /* with pty and master does not have to wait to do further acks */ + if (0 > (slave2 = open(slave_name, O_RDWR))) return(-1); + close(slave2); +#endif /* HAVE_PTYTRAP */ +#endif + + (void) exp_pty_unlock(); + return(slave); +} + +#ifdef HAVE_PTYTRAP +#include <sys/ptyio.h> +#include <sys/time.h> + +/* This function attempts to deal with HP's pty interface. This +function simply returns an indication of what was trapped (or -1 for +failure), the parent deals with the details. + +Originally, I tried to just trap open's but that is not enough. When +the pty is initialized, ioctl's are generated and if not trapped will +hang the child if no further trapping is done. (This could occur if +parent spawns a process and then immediatley does a close.) So +instead, the parent must trap the ioctl's. It probably suffices to +trap the write ioctl's (and tiocsctty which some hp's need) - +conceivably, stty could be smart enough not to do write's if the tty +settings are already correct. In that case, we'll have to rethink +this. + +Suggestions from HP engineers encouraged. I cannot imagine how this +interface was intended to be used! + +*/ + +int +exp_wait_for_slave_open(fd) +int fd; +{ + fd_set excep; + struct timeval t; + struct request_info ioctl_info; + int rc; + int found = 0; + + int maxfds = sysconf(_SC_OPEN_MAX); + + t.tv_sec = 30; /* 30 seconds */ + t.tv_usec = 0; + + FD_ZERO(&excep); + FD_SET(fd,&excep); + + rc = select(maxfds, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)0, + (SELECT_MASK_TYPE *)&excep, + &t); + if (rc != 1) { + expDiagLogPtrStr("spawned process never started: %s\r\n",expErrnoMsg(errno)); + return(-1); + } + if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) { + expDiagLogPtrStr("ioctl(TIOCREQCHECK) failed: %s\r\n",expErrnoMsg(errno)); + return(-1); + } + + found = ioctl_info.request; + + expDiagLogPtrX("trapped pty op = %x",found); + if (found == TIOCOPEN) { + expDiagLogPtr(" TIOCOPEN"); + } else if (found == TIOCCLOSE) { + expDiagLogPtr(" TIOCCLOSE"); + } + +#ifdef TIOCSCTTY + if (found == TIOCSCTTY) { + expDiagLogPtr(" TIOCSCTTY"); + } +#endif + + if (found & IOC_IN) { + expDiagLogPtr(" IOC_IN (set)"); + } else if (found & IOC_OUT) { + expDiagLogPtr(" IOC_OUT (get)"); + } + + expDiagLogPtr("\n"); + + if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) { + expDiagLogPtrStr("ioctl(TIOCREQSET) failed: %s\r\n",expErrnoMsg(errno)); + return(-1); + } + return(found); +} +#endif + +void +exp_pty_exit() +{ + /* a stub so we can do weird things on the cray */ +} diff --git a/pty_unicos.c b/pty_unicos.c new file mode 100644 index 0000000..2791918 --- /dev/null +++ b/pty_unicos.c @@ -0,0 +1,419 @@ +/* pty_unicos.c - routines to allocate ptys - for CRAY UNICOS 5.1 and 6.0 */ + +/* + +Original by: Don Libes, NIST, 2/6/90 +Hacked for Unicos 5.1 by: Frank Terhaar-Yonkers, US EPA, 1/10/91 +Hacked for Unicos 6.0 by: Pete TerMaat, pete@willow.cray.com, 3/27/91 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +#include "expect_cf.h" +#include <stdio.h> +#include <signal.h> + +#if defined(SIGCLD) && !defined(SIGCHLD) +#define SIGCHLD SIGCLD +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#else +extern int fork(), execl(), wait(); +#endif +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/file.h> +#ifdef HAVE_SYS_FCNTL_H +# include <sys/fcntl.h> +#else +# include <fcntl.h> +#endif +/*#if CRAY>=60*/ +#if defined(HAVE_TERMIOS) +# include <sys/termios.h> +#else +# include <sys/termio.h> +/*#endif /* 60 */*/ +#endif /* defined(HAVE_TERMIOS) */ +#if CRAY>=70 && defined(_CRAY2) +#include <sys/session.h> +#endif /* 70 */ +#include <sys/pty.h> +#include <pwd.h> +#include <utmp.h> +#include <signal.h> +#include "exp_tty_in.h" +#include "exp_rename.h" + +#ifdef HAVE_SYSCONF_H +#include <sys/sysconfig.h> +#endif + +void expDiagLog(); + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif /* MAXHOSTNAMELEN */ + +static char linep[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +static char linet[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +static int lowpty; +static int highpty; +static int realuid; +static int realgid; +static int *ptys; +static char myname[32]; +static char hostname[MAXHOSTNAMELEN]; +char *exp_pty_slave_name; +char *exp_pty_error; + +static void +pty_stty(s,name) +char *s; /* args to stty */ +char *name; /* name of pty */ +{ +#define MAX_ARGLIST 10240 + char buf[MAX_ARGLIST]; /* overkill is easier */ + RETSIGTYPE (*old)(); /* save old sigalarm handler */ + +#ifdef STTY_READS_STDOUT + sprintf(buf,"%s %s > %s",STTY_BIN,s,name); +#else + sprintf(buf,"%s %s < %s",STTY_BIN,s,name); +#endif + old = signal(SIGCHLD, SIG_DFL); + system(buf); + signal(SIGCHLD, old); /* restore signal handler */ +} + +int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */ +static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */ + +#ifdef TIOCGWINSZ +static struct winsize winsize = {0, 0}; +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) +static struct ttysize winsize = {0, 0}; +#endif + +/*struct termio exp_tty_original;*/ +exp_tty exp_tty_original; + +#define GET_TTYTYPE 0 +#define SET_TTYTYPE 1 +static void +ttytype(request,fd,ttycopy,ttyinit,s) +int request; +int fd; + /* following are used only if request == SET_TTYTYPE */ +int ttycopy; /* true/false, copy from /dev/tty */ +int ttyinit; /* if true, initialize to sane state */ +char *s; /* stty args, used only if request == SET_TTYTYPE */ +{ + if (request == GET_TTYTYPE) { + if (-1 == ioctl(fd, TCGETA, (char *)&exp_tty_original)) { + knew_dev_tty = FALSE; + exp_dev_tty = -1; + } +#ifdef TIOCGWINSZ + ioctl(fd,TIOCGWINSZ,&winsize); +#endif +#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) + ioctl(fd,TIOCGSIZE,&winsize); +#endif + } else { /* type == SET_TTYTYPE */ + if (ttycopy && knew_dev_tty) { + (void) ioctl(fd, TCSETA, (char *)&exp_tty_current); +#ifdef TIOCSWINSZ + ioctl(fd,TIOCSWINSZ,&winsize); +#endif +#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ) + ioctl(fd,TIOCGSIZE,&winsize); +#endif + } + + if (ttyinit) { + /* overlay parms originally supplied by Makefile */ + pty_stty(DFLT_STTY,linet); + } + + /* lastly, give user chance to override any terminal parms */ + if (s) { + pty_stty(s,linet); + } + } +} + +void +exp_init_pty() +{ + int npty; + char *myline; + + lowpty=0; +#ifdef _SC_CRAY_NPTY + highpty=sysconf(_SC_CRAY_NPTY); +#else + highpty=128; +#endif /* _SC_CRAY_NPTY */ + + ptys = (int *) malloc(sizeof(int)*(highpty+1)); + if (ptys == NULL) { + fprintf(stderr,"exp_init_pty: couldn't allocate pty array\n"); + exit(1); + } + for (npty = lowpty;npty <= highpty;npty++) + ptys[npty] = 0; + + realuid=getuid(); /* get REAL uid */ + realgid=getgid(); /* get REAL uid */ + + exp_dev_tty = open("/dev/tty",O_RDWR); + knew_dev_tty = (exp_dev_tty != -1); + if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0); + + /* + * Acquire (as root) current user name and host. + */ + (void) cuserid(myname); + (void) gethostname(hostname,sizeof(hostname)); + + /* + * Set the real and effective userids to root using 'setuid'. Then + * set the real and effective userids to the actual user using + * 'setreuid'. This allows using 'seteuid' to go back and forth from + * root and the actual userid. Don't ask me why it works. + */ + setuid(0); + setreuid(realuid,realuid); +} + +/* returns fd of master end of pseudotty */ +int +exp_getptymaster() +{ + struct stat sb; + int master; + int npty; + + exp_pty_error = 0; + + expDiagLog("exp_getptymaster: lowpty=%d highpty=%d\n",lowpty,highpty); + for (npty = lowpty; npty <= highpty; npty++) { + if (seteuid(0) == -1) { /* we need to be root! */ + expDiagLog("exp_getptymaster: seteuid root errno=%d\n", + errno); + } + (void) sprintf(linep, "/dev/pty/%03d", npty); + master = open(linep, O_RDWR); + + if (master < 0) { + expDiagLog("exp_getptymaster: open linep=%s errno=%d\n", + linep,errno); + continue; + } + + (void) sprintf(linet, "/dev/ttyp%03d", npty); + if(stat(linet, &sb) < 0) { + expDiagLog("exp_getptymaster: stat linet=%s errno=%d\n", + linet,errno); + (void) close(master); + continue; + } + if (sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + if (chown(linet, realuid, realgid) == -1) { + expDiagLog("exp_getptymaster: chown linet=%s errno=%d\n", + linet,errno); + } + if (chmod(linet, 0600) == -1) { + expDiagLog("exp_getptymaster: chmod linet=%s errno=%d\n", + linet,errno); + } + (void)close(master); + master = open(linep, 2); + if (master < 0) { + expDiagLog("exp_getptymaster: reopen linep=%s errno=%d\n", + linep,errno); + continue; + } + } + if (seteuid(realuid) == -1) { /* back to who we are! */ + expDiagLog("exp_getptymaster: seteuid user errno=%d\n", + errno); + } + if (access(linet, R_OK|W_OK) != 0) { + expDiagLog("exp_getptymaster: access linet=%s errno=%d\n", + linet,errno); + (void) close(master); + continue; + } + expDiagLog("exp_getptymaster: allocated %s\n",linet); + ptys[npty] = -1; + exp_pty_slave_name = linet; + return(master); + } + if (seteuid(realuid) == -1) { /* back to who we are! */ + expDiagLog("exp_getptymaster: seteuid user errno=%d\n",errno); + } + return(-1); +} + +/* see comment in pty_termios.c */ +/*ARGSUSED*/ +void +exp_slave_control(master,control) +int master; +int control; +{ +} + +int +exp_getptyslave(ttycopy,ttyinit,stty_args) +int ttycopy; +int ttyinit; +char *stty_args; +{ + int slave; + + if (0 > (slave = open(linet, O_RDWR))) { + expDiagLog("exp_getptyslave: open linet=%s errno=%d\n",linet,errno); + return(-1); + } + + /* sanity check - if slave not 0, skip rest of this and return */ + /* to what will later be detected as an error in caller */ + if (0 != slave) { + expDiagLog("exp_getptyslave: slave fd not 0\n"); + return(slave); + } + + if (0 == slave) { + /* if opened in a new process, slave will be 0 (and */ + /* ultimately, 1 and 2 as well) */ + + /* duplicate 0 onto 1 and 2 to prepare for stty */ + fcntl(0,F_DUPFD,1); + fcntl(0,F_DUPFD,2); + } + + ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args); + return(slave); +} + +setptyutmp() +{ + struct utmp utmp; + + if (seteuid(0) == -1) { /* Need to be root */ + expDiagLog("setptyutmp: setuid root errno=%d\n",errno); + return(-1); + } + (void) time(&utmp.ut_time); + utmp.ut_type = USER_PROCESS; + utmp.ut_pid = getpid(); + strncpy(utmp.ut_user,myname,sizeof(utmp.ut_user)); + strncpy(utmp.ut_host,hostname,sizeof(utmp.ut_host)); + strncpy(utmp.ut_line,linet+5,sizeof(utmp.ut_line)); + strncpy(utmp.ut_id,linet+8,sizeof(utmp.ut_id)); + if (pututline(&utmp) == NULL) { + expDiagLog("setptyutmp: pututline failed\n"); + } + endutent(); + if (seteuid(realuid) == -1) + expDiagLog("setptyutmp: seteuid user errno=%d\n",errno); + return(0); +} + +setptypid(pid) +int pid; +{ + int npty; + + for (npty = lowpty; npty <= highpty; npty++) { + if (ptys[npty] < 0) { + expDiagLog("setptypid: ttyp%03d pid=%d\n",npty,pid); + ptys[npty] = pid; + break; + } + } +} + +ttyp_reset() +{ + int npty; + + if (seteuid(0) == -1) { /* we need to be root! */ + expDiagLog("ttyp_reset: seteuid root errno=%d\n",errno); + } + for (npty = lowpty; npty <= highpty; npty++) { + if (ptys[npty] <= 0) + continue; + + (void) sprintf(linet, "/dev/ttyp%03d", npty); + expDiagLog("ttyp_reset: resetting %s, killing %d\n", + linet,ptys[npty]); + if (chown(linet,0,0) == -1) { + expDiagLog("ttyp_reset: chown %s errno=%d\n",linet,errno); + } + if (chmod(linet, 0666) == -1) { + expDiagLog("ttyp_reset: chmod %s errno=%d\n",linet,errno); + } + resetptyutmp(); + if (kill(ptys[npty],SIGKILL) == -1) { + expDiagLog("ttyp_reset: kill pid=%d errno=%d\n", + ptys[npty],errno); + } + } + if (seteuid(realuid) == -1) { /* Back to who we really are */ + expDiagLog("ttyp_reset: seteuid user errno=%d\n",errno); + } +} + +void +exp_pty_exit() +{ + ttyp_reset(); +} + +resetptyutmp() +{ + struct utmp utmp; + + (void) setutent (); + /* set up entry to search for */ + (void) strncpy(utmp.ut_id, linet + strlen(linet) - 4, + sizeof (utmp.ut_id)); + utmp.ut_type = USER_PROCESS; + + /* position to entry in utmp file */ + if(getutid(&utmp) == NULL) { + expDiagLog("resetptyutmp: no utmp entry for %s\n",linet); + return(-1); /* no utmp entry for this line ??? */ + } + + /* set up the new entry */ + strncpy(utmp.ut_name,"",sizeof(utmp.ut_name)); + strncpy(utmp.ut_host,"",sizeof(utmp.ut_host)); + time(&utmp.ut_time); + utmp.ut_type = DEAD_PROCESS; + utmp.ut_exit.e_exit = 0; + + /* write out the entry */ + pututline(&utmp); + + /* close the file */ + (void) endutent(); + return(0); +} diff --git a/retoglob.c b/retoglob.c new file mode 100644 index 0000000..521d0ae --- /dev/null +++ b/retoglob.c @@ -0,0 +1,767 @@ +/* + * re2glob - C implementation + * (c) 2007 ActiveState Software Inc. + */ + +#include <tcl.h> + +#define DEBUG 0 + +static void +ExpChopNested _ANSI_ARGS_ ((Tcl_UniChar** xstr, + int* xstrlen, + Tcl_UniChar open, + Tcl_UniChar close)); + +static Tcl_UniChar* +ExpLiteral _ANSI_ARGS_ ((Tcl_UniChar* nexto, + Tcl_UniChar* str, + int strlen)); + +static Tcl_UniChar* +ExpCollapseStar _ANSI_ARGS_ ((Tcl_UniChar* src, + Tcl_UniChar* last)); +static Tcl_UniChar* +ExpCollapseQForward _ANSI_ARGS_ ((Tcl_UniChar* src, + Tcl_UniChar* last)); + +static Tcl_UniChar* +ExpCollapseQBack _ANSI_ARGS_ ((Tcl_UniChar* src, + Tcl_UniChar* last)); + +static Tcl_UniChar +ExpBackslash _ANSI_ARGS_ ((char prefix, + Tcl_UniChar* str, + int strlen)); + +static int +ExpCountStar _ANSI_ARGS_ ((Tcl_UniChar* src, Tcl_UniChar* last)); + + +static char* +xxx (Tcl_UniChar* x, int xl) +{ + static Tcl_DString ds; + Tcl_DStringInit (&ds); + return Tcl_UniCharToUtfDString (x,xl,&ds); +} + + +Tcl_Obj* +exp_retoglob ( + Tcl_UniChar* str, + int strlen) +{ + /* + * Output: x2 size of input (literal where every character has to be + * quoted. + * Location: For next translated unit, in output. + * Size of last generated unit, in characters. + * Stack of output locations at opening parens. x1 size of input. + * Location for next location on stack. + */ + + static Tcl_UniChar litprefix [] = {'*','*','*','='}; + static Tcl_UniChar areprefix [] = {'*','*','*',':'}; + static Tcl_UniChar areopts [] = {'(','?'}; + static Tcl_UniChar nocapture [] = {'?',':'}; + static Tcl_UniChar lookhas [] = {'?','='}; + static Tcl_UniChar looknot [] = {'?','!'}; + static Tcl_UniChar xcomment [] = {'?','#'}; + + static Tcl_UniChar classa [] = {'[','.'}; + static Tcl_UniChar classb [] = {'[','='}; + static Tcl_UniChar classc [] = {'[',':'}; + + + int lastsz, expanded; + Tcl_UniChar* out; + Tcl_UniChar* nexto; + Tcl_UniChar** paren; + Tcl_UniChar** nextp; + Tcl_Obj* glob = NULL; + Tcl_UniChar* mark; + Tcl_UniChar ch; + + /* + * Set things up. + */ + + out = nexto = (Tcl_UniChar*) Tcl_Alloc (strlen*2*sizeof (Tcl_UniChar)); + paren = nextp = (Tcl_UniChar**) Tcl_Alloc (strlen* sizeof (Tcl_UniChar*)); + lastsz = -1; + expanded = 0; + + /* + * Start processing ... + */ + +#define CHOP(n) {str += (n); strlen -= (n);} +#define CHOPC(c) {while (*str != (c) && strlen) CHOP(1) ;} +#define EMIT(c) {lastsz = 1; *nexto++ = (c);} +#define EMITX(c) {lastsz++; *nexto++ = (c);} +#define MATCH(lit) ((strlen >= (sizeof (lit)/sizeof (Tcl_UniChar))) && (0 == Tcl_UniCharNcmp (str,(lit),sizeof(lit)/sizeof (Tcl_UniChar)))) +#define MATCHC(c) (strlen && (*str == (c))) +#define PUSHPAREN {*nextp++ = nexto;} +#define UNEMIT {nexto -= lastsz; lastsz = -1;} + /* Tcl_UniCharIsDigit ? */ +#define MATCH_DIGIT (MATCHC ('0') || MATCHC ('1') || \ + MATCHC ('2') || MATCHC ('3') || \ + MATCHC ('4') || MATCHC ('5') || \ + MATCHC ('6') || MATCHC ('7') || \ + MATCHC ('8') || MATCHC ('9')) +#define MATCH_HEXDIGIT (MATCH_DIGIT || \ + MATCHC ('a') || MATCHC ('A') || \ + MATCHC ('b') || MATCHC ('B') || \ + MATCHC ('c') || MATCHC ('C') || \ + MATCHC ('d') || MATCHC ('D') || \ + MATCHC ('e') || MATCHC ('E') || \ + MATCHC ('f') || MATCHC ('F')) +#define EMITC(c) {if (((c) == '\\') || \ + ((c) == '*') || \ + ((c) == '?') || \ + ((c) == '$') || \ + ((c) == '^') || \ + ((c) == '[')) { \ + EMIT ('\\'); EMITX ((c)); \ + } else { \ + EMIT ((c));}} +#define MATCH_AREOPTS(c) (c == 'b' || c == 'c' || \ + c == 'e' || c == 'i' || c == 'm' || c == 'n' || \ + c == 'p' || c == 'q' || c == 's' || c == 't' || \ + c == 'w' || c == 'x') + +#if DEBUG +#define LOG if (1) fprintf +#define FF fflush (stderr) +#define MARK(s) LOG (stderr,#s "\n"); FF; +#else +#define LOG if (0) fprintf +#define FF +#define MARK(s) +#endif + + /* ***= -> literal string follows */ + + LOG (stderr,"RE-2-GLOB '%s'\n", xxx(str,strlen)); FF; + + if (MATCH (litprefix)) { + CHOP (4); + nexto = ExpLiteral (nexto, str, strlen); + goto done; + } + + /* ***: -> RE is ARE. Always for Expect. Therefore ignore */ + + if (MATCH (areprefix)) { + CHOP (4); + LOG (stderr,"ARE '%s'\n", xxx(str,strlen)); FF; + } + + /* (?xyz) ARE options, in {bceimnpqstwx}. Not validating that the + * options are legal. We assume that the RE is valid. + */ + + if (MATCH (areopts)) { /* "(?" */ + Tcl_UniChar* save = str; + Tcl_UniChar* stop; + int stoplen; + int save_strlen = strlen; + int all_ARE_opts = 1; + + /* First, ensure that this is actually an ARE opts string. + * It could be something else (e.g., a non-capturing block). + */ + CHOP (2); + mark = str; CHOPC (')'); + stop = str; /* Remember closing parens location, allows */ + stoplen = strlen; /* us to avoid a second CHOPC run later */ + + while (mark < str) { + if (MATCH_AREOPTS(*mark)) { + mark++; + } else { + all_ARE_opts = 0; + break; + } + } + + /* Reset back to our entry point. */ + str = save; + strlen = save_strlen; + + if (all_ARE_opts) { + /* Now actually perform the ARE option processing */ + LOG (stderr, "%s\n", "Processing AREOPTS"); FF; + + CHOP (2); + mark = str; + /* Equivalent to CHOPC (')') */ + str = stop; + strlen = stoplen; + + while (mark < str) { + if (*mark == 'q') { + CHOP (1); + nexto = ExpLiteral (nexto, str, strlen); + goto done; + } else if (*mark == 'x') { + expanded = 1; + LOG (stderr,"EXPANDED\n"); FF; + } + mark++; + } + CHOP (1); + } + } + + while (strlen) { + + LOG (stderr,"'%s' <-- ",xxx(out,nexto-out)); FF; + LOG (stderr,"'%s'\n", xxx(str,strlen)); FF; + + if (expanded) { + /* Expanded syntax, whitespace and comments, ignore. */ + while (MATCHC (' ') || + MATCHC (0x9) || + MATCHC (0xa)) CHOP (1); + if (MATCHC ('#')) { + CHOPC (0xa); + if (strlen) CHOP (1); + continue; + } + } + + if (MATCHC ('|')) { + /* branching is too complex */ + goto error; + } else if (MATCHC ('(')) { + /* open parens */ + CHOP (1); + if (MATCH (nocapture)) { /* "?:" */ + /* non capturing -save location */ + PUSHPAREN; + CHOP (2); + } else if (MATCH (lookhas) || /* "?=" */ + MATCH (looknot)) { /* "?!" */ + /* lookahead - ignore */ + CHOP (2); + ExpChopNested (&str, &strlen, '(', ')'); + } else if (MATCH (xcomment)) { /* "?#" */ + /* comment - ignore */ + CHOPC (')'); CHOP (1); + } else { + /* plain capturing */ + PUSHPAREN; + } + } else if (MATCHC (')')) { + /* Closing parens. */ + CHOP (1); + /* Everything coming after the saved result is new, and + * collapsed into a single entry for a possible coming operator + * to handle. + */ + nextp --; /* Back to last save */ + mark = *nextp; /* Location where generation for this parens started */ + lastsz = (nexto - mark); /* This many chars generated */ + /* Now lastsz has the correct value for a possibly following + * UNEMIT + */ + } else if (MATCHC ('$') || MATCHC ('^')) { + /* anchor constraints - ignore */ + CHOP (1); + } else if (MATCHC ('[')) { + /* Classes - reduce to any char [[=chars=]] [[.chars.]] + * [[:name:]] [chars] Count brackets to find end. + + * These are a bit complicated ... [= =], [. .], [: {] sequences + * always have to be complete. '[' does NOT nest otherwise. And + * a ']' after the opening '[' (with only '^' allowed to + * intervene is a character, not the closing bracket. We have to + * process the class in pieces to handle all this. The Tcl level + * implementations (0-2 all have bugs one way or other, all + * different. + */ + + int first = 1; + int allowed = 1; + CHOP (1); + while (strlen) { + if (first && MATCHC ('^')) { + /* ^ as first keeps allowed ok for one more cycle */ + CHOP (1); + first = 0; + continue; + } else if (allowed && MATCHC (']')) { + /* Not a closing bracket! */ + CHOP (1); + } else if (MATCHC (']')) { + /* Closing bracket found */ + CHOP (1); + break; + } else if (MATCH (classa) || + MATCH (classb) || + MATCH (classc)) { + Tcl_UniChar delim[2]; + delim[0] = str [1]; + delim[1] = ']'; + CHOP (2); + while (!MATCH (delim)) CHOP (1); + CHOP (2); + } else { + /* Any char in class */ + CHOP (1); + } + /* Reset flags handling start of class */ + allowed = first = 0; + } + + EMIT ('?'); + } else if (MATCHC ('\\')) { + /* Escapes */ + CHOP (1); + if (MATCHC ('d') || MATCHC ('D') || + MATCHC ('s') || MATCHC ('S') || + MATCHC ('w') || MATCHC ('W')) { + /* Class shorthands - reduce to any char */ + EMIT ('?'); + CHOP (1); + } else if (MATCHC ('m') || MATCHC ('M') || + MATCHC ('y') || MATCHC ('Y') || + MATCHC ('A') || MATCHC ('Z')) { + /* constraint escapes - ignore */ + CHOP (1); + } else if (MATCHC ('B')) { + /* Backslash */ + EMIT ('\\'); + EMITX ('\\'); + CHOP (1); + } else if (MATCHC ('0')) { + /* Escape NULL */ + EMIT ('\0'); + CHOP (1); + } else if (MATCHC ('e')) { + /* Escape ESC */ + EMIT ('\033'); + CHOP (1); + } else if (MATCHC ('a')) { + /* Escape \a */ + EMIT (0x7); + CHOP (1); + } else if (MATCHC ('b')) { + /* Escape \b */ + EMIT (0x8); + CHOP (1); + } else if (MATCHC ('f')) { + /* Escape \f */ + EMIT (0xc); + CHOP (1); + } else if (MATCHC ('n')) { + /* Escape \n */ + EMIT (0xa); + CHOP (1); + } else if (MATCHC ('r')) { + /* Escape \r */ + EMIT (0xd); + CHOP (1); + } else if (MATCHC ('t')) { + /* Escape \t */ + EMIT (0x9); + CHOP (1); + } else if (MATCHC ('v')) { + /* Escape \v */ + EMIT (0xb); + CHOP (1); + } else if (MATCHC ('c') && (strlen >= 2)) { + /* Escape \cX - reduce to (.) */ + EMIT ('?'); + CHOP (2); + } else if (MATCHC ('x')) { + CHOP (1); + if (MATCH_HEXDIGIT) { + /* Escape hex character */ + mark = str; + while (MATCH_HEXDIGIT) CHOP (1); + if ((str - mark) > 2) { mark = str - 2; } + ch = ExpBackslash ('x',mark,str-mark); + EMITC (ch); + } else { + /* Without hex digits following this is a plain char */ + EMIT ('x'); + } + } else if (MATCHC ('u')) { + /* Escapes unicode short. */ + CHOP (1); + mark = str; + CHOP (4); + ch = ExpBackslash ('u',mark,str-mark); + EMITC (ch); + } else if (MATCHC ('U')) { + /* Escapes unicode long. */ + CHOP (1); + mark = str; + CHOP (8); + ch = ExpBackslash ('U',mark,str-mark); + EMITC (ch); + } else if (MATCH_DIGIT) { + /* Escapes, octal, and backreferences - reduce (.*) */ + CHOP (1); + while (MATCH_DIGIT) CHOP (1); + EMIT ('*'); + } else { + /* Plain escaped characters - copy over, requote */ + EMITC (*str); + CHOP (1); + } + } else if (MATCHC ('{')) { + /* Non-greedy and greedy bounds - reduce to (*) */ + CHOP (1); + if (MATCH_DIGIT) { + /* Locate closing brace and remove operator */ + CHOPC ('}'); CHOP (1); + /* Remove optional greedy quantifier */ + if (MATCHC ('?')) { CHOP (1);} + UNEMIT; + EMIT ('*'); + } else { + /* Brace is plain character, copy over */ + EMIT ('{'); + /* CHOP already done */ + } + } else if (MATCHC ('*') || + MATCHC ('+') || + MATCHC ('?')) { + /* (Non-)greedy operators - reduce to (*) */ + CHOP (1); + /* Remove optional greedy quantifier */ + if (MATCHC ('?')) { CHOP (1);} + UNEMIT; + EMIT ('*'); + } else if (MATCHC ('.')) { + /* anychar - copy over */ + EMIT ('?'); + CHOP (1); + } else { + /* Plain char, copy over. */ + EMIT (*str); + CHOP (1); + } + } + + LOG (stderr,"'%s' <-- ",xxx(out,nexto-out)); FF; + LOG (stderr,"'%s'\n", xxx(str,strlen)); FF; + + /* + * Clean up the output a bit (collapse *-sequences and absorb ?'s + * into adjacent *'s. + */ + + MARK (QF) + nexto = ExpCollapseQForward (out,nexto); + LOG (stderr,"QF '%s'\n",xxx(out,nexto-out)); FF; + + MARK (QB) + nexto = ExpCollapseQBack (out,nexto); + LOG (stderr,"QB '%s'\n",xxx(out,nexto-out)); FF; + + MARK (QS) + nexto = ExpCollapseStar (out,nexto); + LOG (stderr,"ST '%s'\n",xxx(out,nexto-out)); FF; + + /* + * Heuristic: if there are more than two *s, the risk is far too + * large that the result actually is slower than the normal re + * matching. So bail out. + */ + if (ExpCountStar (out,nexto) > 2) { + goto error; + } + + /* + * Check if the result is actually useful. + * Empty or just a *, or ? are not. A series + * of ?'s is borderline, as they semi-count + * the buffer. + */ + + if ((nexto == out) || + (((nexto-out) == 1) && + ((*out == '*') || + (*out == '?')))) { + goto error; + } + + /* + * Result generation and cleanup. + */ + done: + LOG (stderr,"RESULT_ '%s'\n", xxx(out,nexto-out)); FF; + glob = Tcl_NewUnicodeObj (out,(nexto-out)); + goto cleanup; + + error: + LOG (stderr,"RESULT_ ERROR\n"); FF; + + cleanup: + Tcl_Free ((char*)out); + Tcl_Free ((char*)paren); + + return glob; +} + +static void +#ifdef _AIX +ExpChopNested (Tcl_UniChar** xstr, + int* xstrlen, + Tcl_UniChar open, + Tcl_UniChar close) +#else +ExpChopNested (xstr,xstrlen, open, close) + Tcl_UniChar** xstr; + int* xstrlen; + Tcl_UniChar open; + Tcl_UniChar close; +#endif +{ + Tcl_UniChar* str = *xstr; + int strlen = *xstrlen; + int level = 0; + + while (strlen) { + if (MATCHC (open)) { + level ++; + } else if (MATCHC (close)) { + level --; + if (level < 0) { + CHOP (1); + break; + } + } + CHOP (1); + } + + *xstr = str; + *xstrlen = strlen; +} + +static Tcl_UniChar* +ExpLiteral (nexto, str, strlen) + Tcl_UniChar* nexto; + Tcl_UniChar* str; + int strlen; +{ + int lastsz; + + LOG (stderr,"LITERAL '%s'\n", xxx(str,strlen)); FF; + + while (strlen) { + EMITC (*str); + CHOP (1); + } + return nexto; +} + +static Tcl_UniChar +#ifdef _AIX +ExpBackslash (char prefix, + Tcl_UniChar* str, + int strlen) +#else +ExpBackslash (prefix, str, strlen) + char prefix; + Tcl_UniChar* str; + int strlen; +#endif +{ + /* strlen <= 8 */ + char buf[20]; + char dst[TCL_UTF_MAX+1]; + Tcl_UniChar ch; + int at = 0; + + /* Construct an utf backslash sequence we can throw to Tcl */ + + buf [at++] = '\\'; + buf [at++] = prefix; + while (strlen) { + buf [at++] = *str++; + strlen --; + } + + Tcl_UtfBackslash (buf, NULL, dst); + TclUtfToUniChar (dst, &ch); + return ch; +} + +static Tcl_UniChar* +ExpCollapseStar (src, last) + Tcl_UniChar* src; + Tcl_UniChar* last; +{ + Tcl_UniChar* dst, *base; + int skip = 0; + int star = 0; + + /* Collapses series of *'s into a single *. State machine. The + * complexity is due to the need of handling escaped characters. + */ + + LOG (stderr,"Q-STAR\n"); FF; + + for (dst = base = src; src < last;) { + + LOG (stderr,"@%1d /%1d '%s' <-- ", star,skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + + if (skip) { + skip = 0; + star = 0; + } else if (*src == '\\') { + skip = 1; /* Copy next char, whatever its value */ + star = 0; + } else if (*src == '*') { + if (star) { + /* Previous char was *, do not copy the current * to collapse + * the sequence + */ + src++; + continue; + } + star = 1; /* *-series starts here */ + } else { + star = 0; + } + *dst++ = *src++; + } + + LOG (stderr,"@%1d /%1d '%s' <-- ", star,skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + + return dst; +} + +static Tcl_UniChar* +ExpCollapseQForward (src, last) + Tcl_UniChar* src; + Tcl_UniChar* last; +{ + Tcl_UniChar* dst, *base; + int skip = 0; + int quest = 0; + + /* Collapses series of ?'s coming after a *. State machine. The + * complexity is due to the need of handling escaped characters. + */ + + LOG (stderr,"Q-Forward\n"); FF; + + for (dst = base = src; src < last;) { + + LOG (stderr,"?%1d /%1d '%s' <-- ", quest,skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + + if (skip) { + skip = 0; + quest = 0; + } else if (*src == '\\') { + skip = 1; + quest = 0; + /* Copy next char, whatever its value */ + } else if (*src == '?') { + if (quest) { + /* Previous char was *, do not copy the current ? to collapse + * the sequence + */ + src++; + continue; + } + } else if (*src == '*') { + quest = 1; + } else { + quest = 0; + } + *dst++ = *src++; + } + + LOG (stderr,"?%1d /%1d '%s' <-- ", quest,skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + return dst; +} + +static Tcl_UniChar* +ExpCollapseQBack (src, last) + Tcl_UniChar* src; + Tcl_UniChar* last; +{ + Tcl_UniChar* dst, *base; + int skip = 0; + + /* Collapses series of ?'s coming before a *. State machine. The + * complexity is due to the need of handling escaped characters. + */ + + LOG (stderr,"Q-Backward\n"); FF; + + for (dst = base = src; src < last;) { + LOG (stderr,"/%1d '%s' <-- ",skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + + if (skip) { + skip = 0; + } else if (*src == '\\') { + skip = 1; + /* Copy next char, whatever its value */ + } else if (*src == '*') { + /* Move backward in the output while the previous character is + * an unescaped question mark. If there is a previous character, + * or a character before that.. + */ + + while ((((dst-base) > 2) && (dst[-1] == '?') && (dst[-2] != '\\')) || + (((dst-base) == 1) && (dst[-1] == '?'))) { + dst --; + } + } + *dst++ = *src++; + } + + LOG (stderr,"/%1d '%s' <-- \n",skip,xxx(base,dst-base)); FF; + LOG (stderr,"'%s'\n", xxx(src,last-src)); FF; + return dst; +} + +static int +ExpCountStar (src, last) + Tcl_UniChar* src; + Tcl_UniChar* last; +{ + int skip = 0; + int stars = 0; + + /* Count number of *'s. State machine. The complexity is due to the + * need of handling escaped characters. + */ + + for (; src < last; src++) { + if (skip) { + skip = 0; + } else if (*src == '\\') { + skip = 1; + } else if (*src == '*') { + stars++; + } + } + + return stars; +} + +#undef CHOP +#undef CHOPC +#undef EMIT +#undef EMITX +#undef MATCH +#undef MATCHC +#undef MATCH_DIGIT +#undef MATCH_HEXDIGIT +#undef PUSHPAREN +#undef UNEMIT diff --git a/tclconfig/config.guess b/tclconfig/config.guess new file mode 100755 index 0000000..1127162 --- /dev/null +++ b/tclconfig/config.guess @@ -0,0 +1,1415 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2003-10-07' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha*:OpenVMS:*:*) + echo alpha-hp-vms + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + *:UNICOS/mp:*:*) + echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + # GNU/KFreeBSD systems have a "k" prefix to indicate we are using + # FreeBSD's kernel, but not the complete OS. + case ${LIBC} in gnu) kernel_only='k' ;; esac + echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + case `uname -p` in + *86) UNAME_PROCESSOR=i686 ;; + powerpc) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + ftp://ftp.gnu.org/pub/gnu/config/ + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/tclconfig/config.sub b/tclconfig/config.sub new file mode 100755 index 0000000..79657cd --- /dev/null +++ b/tclconfig/config.sub @@ -0,0 +1,1510 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2003-10-07' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/tclconfig/install-sh b/tclconfig/install-sh new file mode 100755 index 0000000..0ff4b6a --- /dev/null +++ b/tclconfig/install-sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 diff --git a/tclconfig/tcl.m4 b/tclconfig/tcl.m4 new file mode 100644 index 0000000..396d920 --- /dev/null +++ b/tclconfig/tcl.m4 @@ -0,0 +1,4033 @@ +# tcl.m4 -- +# +# This file provides a set of autoconf macros to help TEA-enable +# a Tcl extension. +# +# Copyright (c) 1999-2000 Ajuba Solutions. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: tcl.m4,v 1.6 2010/09/16 20:46:47 hobbs Exp $ + +AC_PREREQ(2.57) + +dnl TEA extensions pass us the version of TEA they think they +dnl are compatible with (must be set in TEA_INIT below) +dnl TEA_VERSION="3.9" + +# Possible values for key variables defined: +# +# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') +# TEA_PLATFORM - windows unix +# + +#------------------------------------------------------------------------ +# TEA_PATH_TCLCONFIG -- +# +# Locate the tclConfig.sh file and perform a sanity check on +# the Tcl compile flags +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tcl=... +# +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TCLCONFIG], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + AC_ARG_WITH(tcl, + AC_HELP_STRING([--with-tcl], + [directory containing tcl configuration (tclConfig.sh)]), + with_tclconfig="${withval}") + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_ERROR([Can't find Tcl configuration definitions]) + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_TKCONFIG -- +# +# Locate the tkConfig.sh file +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tk=... +# +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TKCONFIG], [ + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + AC_ARG_WITH(tk, + AC_HELP_STRING([--with-tk], + [directory containing tk configuration (tkConfig.sh)]), + with_tkconfig="${withval}") + AC_MSG_CHECKING([for Tk configuration]) + AC_CACHE_VAL(ac_cv_c_tkconfig,[ + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_ERROR([Can't find Tk configuration definitions]) + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TCLCONFIG -- +# +# Load the tclConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TCL_BIN_DIR +# +# Results: +# +# Subst the following vars: +# TCL_BIN_DIR +# TCL_SRC_DIR +# TCL_LIB_FILE +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TCLCONFIG], [ + AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TCL_BIN_DIR}/tclConfig.sh" + else + AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + AC_SUBST(TCL_VERSION) + AC_SUBST(TCL_PATCH_LEVEL) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIB_FLAG) + AC_SUBST(TCL_LIB_SPEC) + + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FLAG) + AC_SUBST(TCL_STUB_LIB_SPEC) + + case "`uname -s`" in + *CYGWIN_*) + AC_MSG_CHECKING([for cygwin variant]) + case ${TCL_EXTRA_CFLAGS} in + *-mwin32*|*-mno-cygwin*) + TEA_PLATFORM="windows" + CFLAGS="$CFLAGS -mwin32" + AC_MSG_RESULT([win32]) + ;; + *) + TEA_PLATFORM="unix" + AC_MSG_RESULT([unix]) + ;; + esac + EXEEXT=".exe" + ;; + *) + ;; + esac + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], + [Building extension source?]) + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + AC_SUBST(CLEANFILES) + AC_SUBST(TCL_LIBS) + AC_SUBST(TCL_DEFS) + AC_SUBST(TCL_EXTRA_CFLAGS) + AC_SUBST(TCL_LD_FLAGS) + AC_SUBST(TCL_SHLIB_LD_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TKCONFIG -- +# +# Load the tkConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TK_BIN_DIR +# +# Results: +# +# Sets the following vars that should be in tkConfig.sh: +# TK_BIN_DIR +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TKCONFIG], [ + AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TK_BIN_DIR}/tkConfig.sh" + else + AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + # TEA specific: Ensure windowingsystem is defined + if test "${TEA_PLATFORM}" = "unix" ; then + case ${TK_DEFS} in + *MAC_OSX_TK*) + AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) + TEA_WINDOWINGSYSTEM="aqua" + ;; + *) + TEA_WINDOWINGSYSTEM="x11" + ;; + esac + elif test "${TEA_PLATFORM}" = "windows" ; then + TEA_WINDOWINGSYSTEM="win32" + fi + + AC_SUBST(TK_VERSION) + AC_SUBST(TK_BIN_DIR) + AC_SUBST(TK_SRC_DIR) + + AC_SUBST(TK_LIB_FILE) + AC_SUBST(TK_LIB_FLAG) + AC_SUBST(TK_LIB_SPEC) + + AC_SUBST(TK_STUB_LIB_FILE) + AC_SUBST(TK_STUB_LIB_FLAG) + AC_SUBST(TK_STUB_LIB_SPEC) + + # TEA specific: + AC_SUBST(TK_LIBS) + AC_SUBST(TK_XINCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_TCLSH +# Determine the fully qualified path name of the tclsh executable +# in the Tcl build directory or the tclsh installed in a bin +# directory. This macro will correctly determine the name +# of the tclsh executable even if tclsh has not yet been +# built in the build directory. The tclsh found is always +# associated with a tclConfig.sh file. This tclsh should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments +# none +# +# Results +# Subst's the following values: +# TCLSH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_TCLSH], [ + AC_MSG_CHECKING([for tclsh]) + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + AC_MSG_RESULT([${TCLSH_PROG}]) + AC_SUBST(TCLSH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_WISH +# Determine the fully qualified path name of the wish executable +# in the Tk build directory or the wish installed in a bin +# directory. This macro will correctly determine the name +# of the wish executable even if wish has not yet been +# built in the build directory. The wish found is always +# associated with a tkConfig.sh file. This wish should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments +# none +# +# Results +# Subst's the following values: +# WISH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_WISH], [ + AC_MSG_CHECKING([for wish]) + if test -f "${TK_BIN_DIR}/Makefile" ; then + # tkConfig.sh is in Tk build directory + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="${TK_BIN_DIR}/wish" + fi + else + # tkConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" + fi + list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TK_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${WISH_PROG}" ; then + REAL_TK_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" + fi + AC_MSG_RESULT([${WISH_PROG}]) + AC_SUBST(WISH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SHARED -- +# +# Allows the building of shared libraries +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-shared=yes|no +# +# Defines the following vars: +# STATIC_BUILD Used for building import/export libraries +# on Windows. +# +# Sets the following vars: +# SHARED_BUILD Value of 1 or 0 +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_SHARED], [ + AC_MSG_CHECKING([how to build libraries]) + AC_ARG_ENABLE(shared, + AC_HELP_STRING([--enable-shared], + [build and link with shared libraries (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + AC_MSG_RESULT([shared]) + SHARED_BUILD=1 + else + AC_MSG_RESULT([static]) + SHARED_BUILD=0 + AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) + fi + AC_SUBST(SHARED_BUILD) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_THREADS -- +# +# Specify if thread support should be enabled. If "yes" is specified +# as an arg (optional), threads are enabled by default, "no" means +# threads are disabled. "yes" is the default. +# +# TCL_THREADS is checked so that if you are compiling an extension +# against a threaded core, your extension must be compiled threaded +# as well. +# +# Note that it is legal to have a thread enabled extension run in a +# threaded or non-threaded Tcl core, but a non-threaded extension may +# only run in a non-threaded Tcl core. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-threads +# +# Sets the following vars: +# THREADS_LIBS Thread library(s) +# +# Defines the following vars: +# TCL_THREADS +# _REENTRANT +# _THREAD_SAFE +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_THREADS], [ + AC_ARG_ENABLE(threads, + AC_HELP_STRING([--enable-threads], + [build with threads]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + AC_DEFINE(USE_THREAD_ALLOC, 1, + [Do we want to use the threaded memory allocator?]) + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + if test "`uname -s`" = "SunOS" ; then + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + fi + AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) + AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + AC_CHECK_LIB(pthread, __pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + AC_CHECK_LIB(pthreads, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + AC_CHECK_LIB(c, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "no"; then + AC_CHECK_LIB(c_r, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + AC_MSG_CHECKING([for building with threads]) + if test "${TCL_THREADS}" = 1; then + AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) + AC_MSG_RESULT([yes (default)]) + else + AC_MSG_RESULT([no]) + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + AC_MSG_WARN([ + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads.]) + fi + ;; + *) + if test "${TCL_THREADS}" = "1"; then + AC_MSG_WARN([ + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core.]) + fi + ;; + esac + AC_SUBST(TCL_THREADS) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SYMBOLS -- +# +# Specify if debugging symbols should be used. +# Memory (TCL_MEM_DEBUG) debugging can also be enabled. +# +# Arguments: +# none +# +# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives +# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. +# Requires the following vars to be set in the Makefile: +# CFLAGS_DEFAULT +# LDFLAGS_DEFAULT +# +# Results: +# +# Adds the following arguments to configure: +# --enable-symbols +# +# Defines the following vars: +# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true +# Sets to $(CFLAGS_OPTIMIZE) if false +# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true +# Sets to $(LDFLAGS_OPTIMIZE) if false +# DBGX Formerly used as debug library extension; +# always blank now. +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_SYMBOLS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_CONFIG_CFLAGS]) + AC_MSG_CHECKING([for build with symbols]) + AC_ARG_ENABLE(symbols, + AC_HELP_STRING([--enable-symbols], + [build with debugging symbols (default: off)]), + [tcl_ok=$enableval], [tcl_ok=no]) + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE}" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + AC_MSG_RESULT([no]) + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + AC_MSG_RESULT([yes (standard debugging)]) + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + AC_SUBST(CFLAGS_DEFAULT) + AC_SUBST(LDFLAGS_DEFAULT) + AC_SUBST(TCL_DBGX) + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + AC_MSG_RESULT([enabled symbols mem debugging]) + else + AC_MSG_RESULT([enabled $tcl_ok debugging]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_LANGINFO -- +# +# Allows use of modern nl_langinfo check for better l10n. +# This is only relevant for Unix. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-langinfo=yes|no (default is yes) +# +# Defines the following vars: +# HAVE_LANGINFO Triggers use of nl_langinfo if defined. +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_LANGINFO], [ + AC_ARG_ENABLE(langinfo, + AC_HELP_STRING([--enable-langinfo], + [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), + [langinfo_ok=$enableval], [langinfo_ok=yes]) + + HAVE_LANGINFO=0 + if test "$langinfo_ok" = "yes"; then + AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) + fi + AC_MSG_CHECKING([whether to use nl_langinfo]) + if test "$langinfo_ok" = "yes"; then + AC_CACHE_VAL(tcl_cv_langinfo_h, [ + AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);], + [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) + AC_MSG_RESULT([$tcl_cv_langinfo_h]) + if test $tcl_cv_langinfo_h = yes; then + AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) + fi + else + AC_MSG_RESULT([$langinfo_ok]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_SYSTEM +# +# Determine what the system is (some things cannot be easily checked +# on a feature-driven basis, alas). This can usually be done via the +# "uname" command. +# +# Arguments: +# none +# +# Results: +# Defines the following var: +# +# system - System/platform/version identification code. +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_SYSTEM], [ + AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + AC_MSG_WARN([can't find uname command]) + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + ]) + system=$tcl_cv_sys_version +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_CFLAGS +# +# Try to determine the proper flags to pass to the compiler +# for building shared libraries and other such nonsense. +# +# Arguments: +# none +# +# Results: +# +# Defines and substitutes the following vars: +# +# DL_OBJS, DL_LIBS - removed for TEA, only needed by core. +# LDFLAGS - Flags to pass to the compiler when linking object +# files into an executable application binary such +# as tclsh. +# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. Could +# be the same as CC_SEARCH_FLAGS if ${CC} is used to link. +# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. +# SHLIB_CFLAGS - Flags to pass to cc when compiling the components +# of a shared library (may request position-independent +# code, among other things). +# SHLIB_LD - Base command to use for combining object files +# into a shared library. +# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when +# creating shared libraries. This symbol typically +# goes at the end of the "ld" commands that build +# shared libraries. The value of the symbol defaults to +# "${LIBS}" if all of the dependent libraries should +# be specified when creating a shared library. If +# dependent libraries should not be specified (as on +# SunOS 4.x, where they cause the link to fail, or in +# general if Tcl and Tk aren't themselves shared +# libraries), then this symbol has an empty string +# as its value. +# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable +# extensions. An empty string means we don't know how +# to use shared libraries on this platform. +# LIB_SUFFIX - Specifies everything that comes after the "libfoo" +# in a static or shared library name, using the $VERSION variable +# to put the version in the right place. This is used +# by platforms that need non-standard library names. +# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${VERSION}.a +# on AIX, since a shared library needs to have +# a .a extension whereas shared objects for loadable +# extensions have a .so extension. Defaults to +# ${VERSION}${SHLIB_SUFFIX}. +# CFLAGS_DEBUG - +# Flags used when running the compiler in debug mode +# CFLAGS_OPTIMIZE - +# Flags used when running the compiler in optimize mode +# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_CFLAGS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + + # Step 0.a: Enable 64 bit support? + + AC_MSG_CHECKING([if 64bit support is requested]) + AC_ARG_ENABLE(64bit, + AC_HELP_STRING([--enable-64bit], + [enable 64bit support (default: off)]), + [do64bit=$enableval], [do64bit=no]) + AC_MSG_RESULT([$do64bit]) + + # Step 0.b: Enable Solaris 64 bit VIS support? + + AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) + AC_ARG_ENABLE(64bit-vis, + AC_HELP_STRING([--enable-64bit-vis], + [enable 64bit Sparc VIS support (default: off)]), + [do64bitVIS=$enableval], [do64bitVIS=no]) + AC_MSG_RESULT([$do64bitVIS]) + # Force 64bit on with VIS + AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + AC_CACHE_CHECK([if compiler supports visibility "hidden"], + tcl_cv_cc_visibility_hidden, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes, + tcl_cv_cc_visibility_hidden=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ + AC_DEFINE(MODULE_SCOPE, + [extern __attribute__((__visibility__("hidden")))], + [Compiler support for module scope symbols]) + ]) + + # Step 0.d: Disable -rpath support? + + AC_MSG_CHECKING([if rpath support is requested]) + AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath], + [disable rpath support (default: on)]), + [doRpath=$enableval], [doRpath=yes]) + AC_MSG_RESULT([$doRpath]) + + # TEA specific: Cross-compiling options for Windows/CE builds? + + AS_IF([test "${TEA_PLATFORM}" = windows], [ + AC_MSG_CHECKING([if Windows/CE build is requested]) + AC_ARG_ENABLE(wince, + AC_HELP_STRING([--enable-wince], + [enable Win/CE support (where applicable)]), + [doWince=$enableval], [doWince=no]) + AC_MSG_RESULT([$doWince]) + ]) + + # Set the variable "system" to hold the name and version number + # for the system. + + TEA_CONFIG_SYSTEM + + # Require ranlib early so we can override it in special cases below. + + AC_REQUIRE([AC_PROG_RANLIB]) + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + CFLAGS_OPTIMIZE=-O + AS_IF([test "$GCC" = yes], [ + # TEA specific: + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + ], [CFLAGS_WARNING=""]) +dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed. +dnl AC_CHECK_TOOL(AR, ar) + AC_CHECK_PROG(AR, ar, ar) + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"]) + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test ! -d "${PATH64}" ; then + AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) + AC_MSG_WARN([Ensure latest Platform SDK is installed]) + do64bit="no" + else + AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible]) + fi + if test "$GCC" = "yes" ; then + AC_MSG_ERROR([Windows/CE and GCC builds incompatible]) + fi + TEA_PATH_CELIB + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \ + if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \ + if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \ + if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]]) + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + TEA_ADD_LIBS([bufferoverflowU.lib]) + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower([$]0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i) + done + AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version]) + AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version]) + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + AC_SUBST(CELIB_DIR) + else + RC="rc" + lflags="-nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + RC="windres" + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD="$CC -shared" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` + ;; + esac + AC_MSG_RESULT([Using $CC for compiling with threads]) + ]) + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + ]) + ]) + + AS_IF([test "`uname -m`" = ia64], [ + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + AS_IF([test "$GCC" = yes], [ + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + ], [ + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + ]) + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ], [ + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared -Wl,-bexpall' + ], [ + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + ]) + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + EXE_SUFFIX=".exe" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' + AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + AS_IF([test "`uname -m`" = ia64], [ + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + ], [ + SHLIB_SUFFIX=".sl" + ]) + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + AS_IF([test "$tcl_ok" = yes], [ + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + ]) + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + ]) + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = "yes"], [ + AS_IF([test "$GCC" = yes], [ + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ;; + esac + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + ]) + ]) ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [ + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + ], [ + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + ]) + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + + # Check to enable 64-bit flags for compiler/linker + + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported by gcc]) + ], [ + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + ]) + ]) + ;; + Linux*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) + AS_IF([test $do64bit = yes], [ + AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_m64 = yes], [ + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + ]) + ]) + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) + + ;; + GNU*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + SHLIB_LD='${CC} -shared' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + ;; + OpenBSD-*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' + AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ + AC_EGREP_CPP(yes, [ +#ifdef __ELF__ + yes +#endif + ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) + AS_IF([test $tcl_cv_ld_elf = yes], [ + LDFLAGS=-Wl,-export-dynamic + ], [LDFLAGS=""]) + AS_IF([test "${TCL_THREADS}" = "1"], [ + # OpenBSD builds and links with -pthread, never -lpthread. + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + SHLIB_CFLAGS="$SHLIB_CFLAGS -pthread" + ]) + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*|FreeBSD-[[3-4]].*) + # FreeBSD 3.* and greater have ELF. + # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + case $system in + FreeBSD-3.*) + # FreeBSD-3 doesn't handle version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + TCL_SHLIB_LD_EXTRAS="-soname \$[@]" + SHLIB_SUFFIX=".so" + LDFLAGS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" + AS_IF([test $do64bit = yes], [ + case `arch` in + ppc) + AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], + tcl_cv_cc_arch_ppc64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes, + tcl_cv_cc_arch_ppc64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + ]);; + i386) + AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], + tcl_cv_cc_arch_x86_64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes, + tcl_cv_cc_arch_x86_64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + ]);; + *) + AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; + esac + ], [ + # Check for combined 32-bit and 64-bit fat build + AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ + fat_32_64=yes]) + ]) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_single_module = yes], [ + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + ]) + # TEA specific: link shlib with current and compatiblity version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [ + LDFLAGS="$LDFLAGS -prebind"]) + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + AC_CACHE_CHECK([if ld accepts -search_paths_first flag], + tcl_cv_ld_search_paths_first, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, + tcl_cv_ld_search_paths_first=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + ]) + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [__private_extern__], + [Compiler support for module scope symbols]) + tcl_cv_cc_visibility_hidden=yes + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ + AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();], + tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ + AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);], + tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ + AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done]) + ]) + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h + [Should OS/390 do the right thing with sockets?]) + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + AS_IF([test "$SHARED_BUILD" = 1], [ + SHLIB_LD='ld -shared -expect_unresolved "*"' + ], [ + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + ]) + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) + # see pthread_intro(3) for pthread support on osf1, k.furukawa + AS_IF([test "${TCL_THREADS}" = 1], [ + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + AS_IF([test "$GCC" = yes], [ + LIBS="$LIBS -lpthread -lmach -lexc" + ], [ + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ]) + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + AS_IF([test "$GCC" = yes], [ + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + ], [ + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + ]) + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[[0-6]]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + arch=`isainfo` + AS_IF([test "$arch" = "sparcv9 sparc"], [ + AS_IF([test "$GCC" = yes], [ + AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ + AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + ]) + ], [ + do64bit_ok=yes + AS_IF([test "$do64bitVIS" = yes], [ + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + ], [ + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + ]) + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + ]) + ], [AS_IF([test "$arch" = "amd64 i386"], [ + AS_IF([test "$GCC" = yes], [ + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]);; + esac + ], [ + do64bit_ok=yes + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + ]) + ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) + ]) + + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "$do64bit_ok" = yes], [ + AS_IF([test "$arch" = "sparcv9 sparc"], [ + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + ], [AS_IF([test "$arch" = "amd64 i386"], [ + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + ])]) + ]) + ], [ + case $system in + SunOS-5.[[1-9]][[0-9]]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ]) + ;; + esac + + AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ + AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) + ]) + +dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so +dnl # until the end of configure, as configure's compile and link tests use +dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's +dnl # preprocessing tests use only CPPFLAGS. + AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + AS_IF([test "$GCC" = yes], [ + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*) ;; + IRIX*) ;; + NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac]) + + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [extern], + [No Compiler support for module scope symbols]) + AC_DEFINE(NO_VIZ, [], [No visibility hidden passed to zlib?]) + ]) + + AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) + AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) + + AC_SUBST(CFLAGS_DEBUG) + AC_SUBST(CFLAGS_OPTIMIZE) + AC_SUBST(CFLAGS_WARNING) + + AC_SUBST(STLIB_LD) + AC_SUBST(SHLIB_LD) + + AC_SUBST(SHLIB_LD_LIBS) + AC_SUBST(SHLIB_CFLAGS) + + AC_SUBST(LD_LIBRARY_PATH_VAR) + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + TEA_TCL_EARLY_FLAGS + TEA_TCL_64BIT_FLAGS +]) + +#-------------------------------------------------------------------- +# TEA_SERIAL_PORT +# +# Determine which interface to use to talk to the serial port. +# Note that #include lines must begin in leftmost column for +# some compilers to recognize them as preprocessor directives, +# and some build environments have stdin not pointing at a +# pseudo-terminal (usually /dev/null instead.) +# +# Arguments: +# none +# +# Results: +# +# Defines only one of the following vars: +# HAVE_SYS_MODEM_H +# USE_TERMIOS +# USE_TERMIO +# USE_SGTTY +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_SERIAL_PORT], [ + AC_CHECK_HEADERS(sys/modem.h) + AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ + AC_TRY_RUN([ +#include <termios.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termio.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <sgtty.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termios.h> +#include <errno.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <termio.h> +#include <errno.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; + }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <sgtty.h> +#include <errno.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none) + fi]) + case $tcl_cv_api_serial in + termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; + termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; + sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; + esac +]) + +#-------------------------------------------------------------------- +# TEA_MISSING_POSIX_HEADERS +# +# Supply substitutes for missing POSIX header files. Special +# notes: +# - stdlib.h doesn't define strtol, strtoul, or +# strtod in some versions of SunOS +# - some versions of string.h don't declare procedures such +# as strstr +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# NO_DIRENT_H +# NO_ERRNO_H +# NO_VALUES_H +# HAVE_LIMITS_H or NO_LIMITS_H +# NO_STDLIB_H +# NO_STRING_H +# NO_SYS_WAIT_H +# NO_DLFCN_H +# HAVE_SYS_PARAM_H +# +# HAVE_STRING_H ? +# +# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and +# CHECK on limits.h +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [ + AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [ + AC_TRY_LINK([#include <sys/types.h> +#include <dirent.h>], [ +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); +], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)]) + + if test $tcl_cv_dirent_h = no; then + AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?]) + fi + + # TEA specific: + AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])]) + AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])]) + AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])]) + AC_CHECK_HEADER(limits.h, + [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])], + [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])]) + AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) + if test $tcl_ok = 0; then + AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?]) + fi + AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) + AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) + fi + + AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])]) + AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])]) + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + AC_HAVE_HEADERS(sys/param.h) +]) + +#-------------------------------------------------------------------- +# TEA_PATH_X +# +# Locate the X11 header files and the X11 library archive. Try +# the ac_path_x macro first, but if it doesn't find the X stuff +# (e.g. because there's no xmkmf program) then check through +# a list of possible directories. Under some conditions the +# autoconf macro will return an include directory that contains +# no include files, so double-check its result just to be safe. +# +# This should be called after TEA_CONFIG_CFLAGS as setting the +# LIBS line can confuse some configure macro magic. +# +# Arguments: +# none +# +# Results: +# +# Sets the following vars: +# XINCLUDES +# XLIBSW +# PKG_LIBS (appends to) +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_PATH_X], [ + if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then + TEA_PATH_UNIX_X + fi +]) + +AC_DEFUN([TEA_PATH_UNIX_X], [ + AC_PATH_X + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + AC_TRY_CPP([#include <X11/XIntrinsic.h>], , not_really_there="yes") + else + if test ! -r $x_includes/X11/Intrinsic.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + AC_MSG_CHECKING([for X11 header files]) + found_xincludes="no" + AC_TRY_CPP([#include <X11/Intrinsic.h>], found_xincludes="yes", found_xincludes="no") + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Intrinsic.h; then + AC_MSG_RESULT([$i]) + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + AC_MSG_RESULT([couldn't find any!]) + fi + + if test "$no_x" = yes; then + AC_MSG_CHECKING([for X11 libraries]) + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + AC_MSG_RESULT([$i]) + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) + fi + if test "$XLIBSW" = nope ; then + AC_MSG_RESULT([could not find any! Using -lX11.]) + XLIBSW=-lX11 + fi + # TEA specific: + if test x"${XLIBSW}" != x ; then + PKG_LIBS="${PKG_LIBS} ${XLIBSW}" + fi +]) + +#-------------------------------------------------------------------- +# TEA_BLOCKING_STYLE +# +# The statements below check for systems where POSIX-style +# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. +# On these systems (mostly older ones), use the old BSD-style +# FIONBIO approach instead. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# HAVE_SYS_IOCTL_H +# HAVE_SYS_FILIO_H +# USE_FIONBIO +# O_NONBLOCK +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BLOCKING_STYLE], [ + AC_CHECK_HEADERS(sys/ioctl.h) + AC_CHECK_HEADERS(sys/filio.h) + TEA_CONFIG_SYSTEM + AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) + case $system in + OSF*) + AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) + AC_MSG_RESULT([FIONBIO]) + ;; + *) + AC_MSG_RESULT([O_NONBLOCK]) + ;; + esac +]) + +#-------------------------------------------------------------------- +# TEA_TIME_HANDLER +# +# Checks how the system deals with time.h, what time structures +# are used on the system, and what fields the structures have. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# USE_DELTA_FOR_TZ +# HAVE_TM_GMTOFF +# HAVE_TM_TZADJ +# HAVE_TIMEZONE_VAR +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TIME_HANDLER], [ + AC_CHECK_HEADERS(sys/time.h) + AC_HEADER_TIME + AC_STRUCT_TIMEZONE + + AC_CHECK_FUNCS(gmtime_r localtime_r) + + AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;], + tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)]) + if test $tcl_cv_member_tm_tzadj = yes ; then + AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) + fi + + AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;], + tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)]) + if test $tcl_cv_member_tm_gmtoff = yes ; then + AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) + fi + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ + AC_TRY_COMPILE([#include <time.h>], + [extern long timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)]) + if test $tcl_cv_timezone_long = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + else + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ + AC_TRY_COMPILE([#include <time.h>], + [extern time_t timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)]) + if test $tcl_cv_timezone_time = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_BUGGY_STRTOD +# +# Under Solaris 2.4, strtod returns the wrong value for the +# terminating character under some conditions. Check for this +# and if the problem exists use a substitute procedure +# "fixstrtod" (provided by Tcl) that corrects the error. +# Also, on Compaq's Tru64 Unix 5.0, +# strtod(" ") returns 0.0 instead of a failure to convert. +# +# Arguments: +# none +# +# Results: +# +# Might defines some of the following vars: +# strtod (=fixstrtod) +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BUGGY_STRTOD], [ + AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) + if test "$tcl_strtod" = 1; then + AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ + AC_TRY_RUN([ + extern double strtod(); + int main() { + char *infString="Inf", *nanString="NaN", *spaceString=" "; + char *term; + double value; + value = strtod(infString, &term); + if ((term != infString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(nanString, &term); + if ((term != nanString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(spaceString, &term); + if (term == (spaceString+1)) { + exit(1); + } + exit(0); + }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy, + tcl_cv_strtod_buggy=buggy)]) + if test "$tcl_cv_strtod_buggy" = buggy; then + AC_LIBOBJ([fixstrtod]) + USE_COMPAT=1 + AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_LINK_LIBS +# +# Search for the libraries needed to link the Tcl shell. +# Things like the math library (-lm) and socket stuff (-lsocket vs. +# -lnsl) are dealt with here. +# +# Arguments: +# Requires the following vars to be set in the Makefile: +# DL_LIBS (not in TEA, only needed in core) +# LIBS +# MATH_LIBS +# +# Results: +# +# Subst's the following var: +# TCL_LIBS +# MATH_LIBS +# +# Might append to the following vars: +# LIBS +# +# Might define the following vars: +# HAVE_NET_ERRNO_H +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_LINK_LIBS], [ + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") + AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) + AC_CHECK_HEADER(net/errno.h, [ + AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])]) + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) + if test "$tcl_checkSocket" = 1; then + AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, + LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) + fi + AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, + [LIBS="$LIBS -lnsl"])]) + + # TEA specific: Don't perform the eval of the libraries here because + # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + AC_SUBST(TCL_LIBS) + AC_SUBST(MATH_LIBS) +]) + +#-------------------------------------------------------------------- +# TEA_TCL_EARLY_FLAGS +# +# Check for what flags are needed to be passed so the correct OS +# features are available. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# _ISOC99_SOURCE +# _LARGEFILE64_SOURCE +# _LARGEFILE_SOURCE64 +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_EARLY_FLAG],[ + AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), + AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no, + AC_TRY_COMPILE([[#define ]$1[ 1 +]$2], $3, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no))) + if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then + AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) + tcl_flags="$tcl_flags $1" + fi +]) + +AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ + AC_MSG_CHECKING([for required early compiler flags]) + tcl_flags="" + TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], + [char *p = (char *)strtoll; char *q = (char *)strtoull;]) + TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], + [struct stat64 buf; int i = stat64("/", &buf);]) + TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>], + [char *p = (char *)open64;]) + if test "x${tcl_flags}" = "x" ; then + AC_MSG_RESULT([none]) + else + AC_MSG_RESULT([${tcl_flags}]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_64BIT_FLAGS +# +# Check for what is defined in the way of 64-bit features. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# TCL_WIDE_INT_IS_LONG +# TCL_WIDE_INT_TYPE +# HAVE_STRUCT_DIRENT64 +# HAVE_STRUCT_STAT64 +# HAVE_TYPE_OFF64_T +# +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ + AC_MSG_CHECKING([for 64-bit integer type]) + AC_CACHE_VAL(tcl_cv_type_64bit,[ + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + AC_TRY_COMPILE(,[__int64 value = (__int64) 0;], + tcl_type_64bit=__int64, tcl_type_64bit="long long") + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + AC_TRY_COMPILE(,[switch (0) { + case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; + }],tcl_cv_type_64bit=${tcl_type_64bit})]) + if test "${tcl_cv_type_64bit}" = none ; then + AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) + AC_MSG_RESULT([using long]) + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + AC_MSG_RESULT([using Tcl header defaults]) + else + AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, + [What type should be used to define wide integers?]) + AC_MSG_RESULT([${tcl_cv_type_64bit}]) + + # Now check for auxiliary declarations + AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ + AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/dirent.h>],[struct dirent64 p;], + tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?]) + fi + + AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ + AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p; +], + tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)]) + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) + fi + + AC_CHECK_FUNCS(open64 lseek64) + AC_MSG_CHECKING([for off64_t]) + AC_CACHE_VAL(tcl_cv_type_off64_t,[ + AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset; +], + tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)]) + dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the + dnl functions lseek64 and open64 are defined. + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + fi +]) + +## +## Here ends the standard Tcl configuration bits and starts the +## TEA specific functions +## + +#------------------------------------------------------------------------ +# TEA_INIT -- +# +# Init various Tcl Extension Architecture (TEA) variables. +# This should be the first called TEA_* macro. +# +# Arguments: +# none +# +# Results: +# +# Defines and substs the following vars: +# CYGPATH +# EXEEXT +# Defines only: +# TEA_VERSION +# TEA_INITED +# TEA_PLATFORM (windows or unix) +# +# "cygpath" is used on windows to generate native path names for include +# files. These variables should only be used with the compiler and linker +# since they generate native path names. +# +# EXEEXT +# Select the executable extension based on the host type. This +# is a lightweight replacement for AC_EXEEXT that doesn't require +# a compiler. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_INIT], [ + # TEA extensions pass this us the version of TEA they think they + # are compatible with. + TEA_VERSION="3.9" + + AC_MSG_CHECKING([for correct TEA configuration]) + if test x"${PACKAGE_NAME}" = x ; then + AC_MSG_ERROR([ +The PACKAGE_NAME variable must be defined by your TEA configure.in]) + fi + if test x"$1" = x ; then + AC_MSG_ERROR([ +TEA version not specified.]) + elif test "$1" != "${TEA_VERSION}" ; then + AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"]) + else + AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) + fi + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*) + AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + CYGPATH=echo + EXEEXT=".exe" + # TEA_PLATFORM is determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) + + AC_SUBST(EXEEXT) + AC_SUBST(CYGPATH) + + # This package name must be replaced statically for AC_SUBST to work + AC_SUBST(PKG_LIB_FILE) + # Substitute STUB_LIB_FILE in case package creates a stub library too. + AC_SUBST(PKG_STUB_LIB_FILE) + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) + AC_SUBST(PKG_TCL_SOURCES) + AC_SUBST(PKG_HEADERS) + AC_SUBST(PKG_INCLUDES) + AC_SUBST(PKG_LIBS) + AC_SUBST(PKG_CFLAGS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_SOURCES +# PKG_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_SOURCES], [ + vars="$@" + for i in $vars; do + case $i in + [\$]*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find source file '$i']) + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + AC_SUBST(PKG_SOURCES) + AC_SUBST(PKG_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_STUB_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_STUB_SOURCES +# PKG_STUB_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_STUB_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find stub source file '$i']) + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_TCL_SOURCES -- +# +# Specify one or more Tcl source files. These should be platform +# independent runtime files. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_TCL_SOURCES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_TCL_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + AC_SUBST(PKG_TCL_SOURCES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_HEADERS -- +# +# Specify one or more source headers. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_HEADERS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_HEADERS], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find header file '${srcdir}/$i']) + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + AC_SUBST(PKG_HEADERS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_INCLUDES -- +# +# Specify one or more include dirs. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_INCLUDES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_INCLUDES], [ + vars="$@" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + AC_SUBST(PKG_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_LIBS -- +# +# Specify one or more libraries. Users should check for +# the right platform before adding to their list. For Windows, +# libraries provided in "foo.lib" format will be converted to +# "-lfoo" when using GCC (mingw). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_LIBS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_LIBS], [ + vars="$@" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + AC_SUBST(PKG_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CFLAGS -- +# +# Specify one or more CFLAGS. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_CFLAGS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CFLAGS], [ + PKG_CFLAGS="$PKG_CFLAGS $@" + AC_SUBST(PKG_CFLAGS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CLEANFILES -- +# +# Specify one or more CLEANFILES. +# +# Arguments: +# one or more file names to clean target +# +# Results: +# +# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CLEANFILES], [ + CLEANFILES="$CLEANFILES $@" +]) + +#------------------------------------------------------------------------ +# TEA_PREFIX -- +# +# Handle the --prefix=... option by defaulting to what Tcl gave +# +# Arguments: +# none +# +# Results: +# +# If --prefix or --exec-prefix was not specified, $prefix and +# $exec_prefix will be set to the values given to Tcl when it was +# configured. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_PREFIX], [ + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) + prefix=${TCL_PREFIX} + else + AC_MSG_NOTICE([--prefix defaulting to /usr/local]) + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) + exec_prefix=${TCL_EXEC_PREFIX} + else + AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) + exec_prefix=$prefix + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER_CC -- +# +# Do compiler checks the way we want. This is just a replacement +# for AC_PROG_CC in TEA configure.in files to make them cleaner. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER_CC], [ + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + # If the user did not set CFLAGS, set it now to keep + # the AC_PROG_CC macro from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + AC_PROG_CC + AC_PROG_CPP + + AC_PROG_INSTALL + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + AC_PROG_MAKE_SET + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + AC_PROG_RANLIB + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + AC_OBJEXT + AC_EXEEXT +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER -- +# +# Do compiler checks that use the compiler. This must go after +# TEA_SETUP_COMPILER_CC, which does the actual compiler check. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER], [ + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + AC_REQUIRE([TEA_SETUP_COMPILER_CC]) + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + AC_CACHE_CHECK([if the compiler understands -pipe], + tcl_cv_cc_pipe, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + AC_C_BIGENDIAN + if test "${TEA_PLATFORM}" = "unix" ; then + TEA_TCL_LINK_LIBS + TEA_MISSING_POSIX_HEADERS + # Let the user call this, because if it triggers, they will + # need a compat/strtod.c that is correct. Users can also + # use Tcl_GetDouble(FromObj) instead. + #TEA_BUGGY_STRTOD + fi +]) + +#------------------------------------------------------------------------ +# TEA_MAKE_LIB -- +# +# Generate a line that can be used to build a shared/unshared library +# in a platform independent manner. +# +# Arguments: +# none +# +# Requires: +# +# Results: +# +# Defines the following vars: +# CFLAGS - Done late here to note disturb other AC macros +# MAKE_LIB - Command to execute to build the Tcl library; +# differs depending on whether or not Tcl is being +# compiled as a shared library. +# MAKE_SHARED_LIB Makefile rule for building a shared library +# MAKE_STATIC_LIB Makefile rule for building a static library +# MAKE_STUB_LIB Makefile rule for building a stub library +# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL +# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_MAKE_LIB], [ + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)" + AC_EGREP_CPP([manifest needed], [ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + ], [ + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + TEA_ADD_CLEANFILES([*.manifest]) + ]) + MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + AC_SUBST(MAKE_LIB) + AC_SUBST(MAKE_SHARED_LIB) + AC_SUBST(MAKE_STATIC_LIB) + AC_SUBST(MAKE_STUB_LIB) + AC_SUBST(RANLIB_STUB) + AC_SUBST(VC_MANIFEST_EMBED_DLL) + AC_SUBST(VC_MANIFEST_EMBED_EXE) +]) + +#------------------------------------------------------------------------ +# TEA_LIB_SPEC -- +# +# Compute the name of an existing object library located in libdir +# from the given base name and produce the appropriate linker flags. +# +# Arguments: +# basename The base name of the library without version +# numbers, extensions, or "lib" prefixes. +# extra_dir Extra directory in which to search for the +# library. This location is used first, then +# $prefix/$exec-prefix, then some defaults. +# +# Requires: +# TEA_INIT and TEA_PREFIX must be called first. +# +# Results: +# +# Defines the following vars: +# ${basename}_LIB_NAME The computed library name. +# ${basename}_LIB_SPEC The computed linker flags. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LIB_SPEC], [ + AC_MSG_CHECKING([for $1 library]) + + # Look in exec-prefix for the library (defined by TEA_PREFIX). + + tea_lib_name_dir="${exec_prefix}/lib" + + # Or in a user-specified location. + + if test x"$2" != x ; then + tea_extra_lib_dir=$2 + else + tea_extra_lib_dir=NONE + fi + + for i in \ + `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do + if test -f "$i" ; then + tea_lib_name_dir=`dirname $i` + $1_LIB_NAME=`basename $i` + $1_LIB_PATH_NAME=$i + break + fi + done + + if test "${TEA_PLATFORM}" = "windows"; then + $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" + else + # Strip off the leading "lib" and trailing ".a" or ".so" + + tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` + $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" + fi + + if test "x${$1_LIB_NAME}" = x ; then + AC_MSG_ERROR([not found]) + else + AC_MSG_RESULT([${$1_LIB_SPEC}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TCL_HEADERS -- +# +# Locate the private Tcl include files +# +# Arguments: +# +# Requires: +# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has +# already been called. +# +# Results: +# +# Substs the following vars: +# TCL_TOP_DIR_NATIVE +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ + # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} + AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) + AC_MSG_CHECKING([for Tcl private include files]) + + TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` + TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" + + # Check to see if tcl<Plat>Port.h isn't already with the public headers + # Don't look for tclInt.h because that resides with tcl.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tclh}/tclWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tclh}/tclUnixPort.h"; then + result="private headers found with public headers" + else + TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" + if test "${TEA_PLATFORM}" = "windows"; then + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" + else + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TCL_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -d "${TCL_BIN_DIR}/Headers" -a \ + -d "${TCL_BIN_DIR}/PrivateHeaders"; then + TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" + else + TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TCL_INCLUDES}" + else + if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then + AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) + fi + result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" + fi + fi + + AC_SUBST(TCL_TOP_DIR_NATIVE) + + AC_SUBST(TCL_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TCL_HEADERS -- +# +# Locate the installed public Tcl header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tclinclude switch to configure. +# Result is cached. +# +# Substs the following vars: +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ + AC_MSG_CHECKING([for Tcl public headers]) + + AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tclh, [ + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tclh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TCL_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TK_HEADERS -- +# +# Locate the private Tk include files +# +# Arguments: +# +# Requires: +# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has +# already been called. +# +# Results: +# +# Substs the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ + # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} + AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) + AC_MSG_CHECKING([for Tk private include files]) + + TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` + TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" + + # Check to see if tk<Plat>Port.h isn't already with the public headers + # Don't look for tkInt.h because that resides with tk.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tkh}/tkWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tkh}/tkUnixPort.h"; then + result="private headers found with public headers" + else + TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" + TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" + if test "${TEA_PLATFORM}" = "windows"; then + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" + else + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TK_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" + # Detect and add ttk subdir + if test -d "${TK_SRC_DIR}/generic/ttk"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" + fi + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -d "${TK_BIN_DIR}/Headers" -a \ + -d "${TK_BIN_DIR}/PrivateHeaders"; then + TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" + else + TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TK_INCLUDES}" + else + if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then + AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) + fi + result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" + fi + fi + + AC_SUBST(TK_TOP_DIR_NATIVE) + AC_SUBST(TK_XLIB_DIR_NATIVE) + + AC_SUBST(TK_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TK_HEADERS -- +# +# Locate the installed public Tk header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tkinclude switch to configure. +# Result is cached. +# +# Substs the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ + AC_MSG_CHECKING([for Tk public headers]) + + AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tkh, [ + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers directory. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tk is not installed, + # and in that situation, look there before installed locations. + if test -f "${TK_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tk's --prefix location, + # relative to directory of tkConfig.sh, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TK_PREFIX}/include 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TK_INCLUDE_SPEC}" != x ; then + d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tkh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TK_INCLUDES) + + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + # On Windows and Aqua, we need the X compat headers + AC_MSG_CHECKING([for X11 header files]) + if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then + INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" + TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + AC_SUBST(TK_XINCLUDES) + fi + AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_CONFIG -- +# +# Locate the ${1}Config.sh file and perform a sanity check on +# the ${1} compile flags. These are used by packages like +# [incr Tk] that load *Config.sh files from more than Tcl and Tk. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-$1=... +# +# Defines the following vars: +# $1_BIN_DIR Full path to the directory containing +# the $1Config.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CONFIG], [ + # + # Ok, lets find the $1 configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-$1 + # + + if test x"${no_$1}" = x ; then + # we reset no_$1 in case something fails here + no_$1=true + AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) + AC_MSG_CHECKING([for $1 configuration]) + AC_CACHE_VAL(ac_cv_c_$1config,[ + + # First check to see if --with-$1 was specified. + if test x"${with_$1config}" != x ; then + case ${with_$1config} in + */$1Config.sh ) + if test -f ${with_$1config}; then + AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) + with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` + fi;; + esac + if test -f "${with_$1config}/$1Config.sh" ; then + ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` + else + AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) + fi + fi + + # then check for a private $1 installation + if test x"${ac_cv_c_$1config}" = x ; then + for i in \ + ../$1 \ + `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../$1 \ + `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../../$1 \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ${srcdir}/../$1 \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + if test -f "$i/unix/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_$1config}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + done + fi + ]) + + if test x"${ac_cv_c_$1config}" = x ; then + $1_BIN_DIR="# no $1 configs found" + AC_MSG_WARN([Cannot find $1 configuration definitions]) + exit 0 + else + no_$1= + $1_BIN_DIR=${ac_cv_c_$1config} + AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG -- +# +# Load the $1Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1_BIN_DIR +# +# Results: +# +# Subst the following vars: +# $1_SRC_DIR +# $1_LIB_FILE +# $1_LIB_SPEC +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_CONFIG], [ + AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) + + if test -f "${$1_BIN_DIR}/$1Config.sh" ; then + AC_MSG_RESULT([loading]) + . "${$1_BIN_DIR}/$1Config.sh" + else + AC_MSG_RESULT([file not found]) + fi + + # + # If the $1_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable $1_LIB_SPEC will be set to the value + # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC + # instead of $1_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + # + + if test -f "${$1_BIN_DIR}/Makefile" ; then + AC_MSG_WARN([Found Makefile - using build library specs for $1]) + $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} + $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} + $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} + $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} + $1_LIBRARY_PATH=${$1_LIBRARY_PATH} + fi + + AC_SUBST($1_VERSION) + AC_SUBST($1_BIN_DIR) + AC_SUBST($1_SRC_DIR) + + AC_SUBST($1_LIB_FILE) + AC_SUBST($1_LIB_SPEC) + + AC_SUBST($1_STUB_LIB_FILE) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_PATH) + + # Allow the caller to prevent this auto-check by specifying any 2nd arg + AS_IF([test "x$2" = x], [ + # Check both upper and lower-case variants + # If a dev wanted non-stubs libs, this function could take an option + # to not use _STUB in the paths below + AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], + [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], + [TEA_LOAD_CONFIG_LIB($1_STUB)]) + ]) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG_LIB -- +# +# Helper function to load correct library from another extension's +# ${PACKAGE}Config.sh. +# +# Results: +# Adds to LIBS the appropriate extension library +# +#------------------------------------------------------------------------ +AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ + AC_MSG_CHECKING([For $1 library for LIBS]) + # This simplifies the use of stub libraries by automatically adding + # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, + # but this is called before CONFIG_CFLAGS. More importantly, this adds + # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. + if test "x${$1_LIB_SPEC}" != "x" ; then + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then + TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) + AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) + else + TEA_ADD_LIBS([${$1_LIB_SPEC}]) + AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) + fi + else + AC_MSG_RESULT([file not found]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_EXPORT_CONFIG -- +# +# Define the data to insert into the ${PACKAGE}Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1 +# +# Results: +# Subst the following vars: +# +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_EXPORT_CONFIG], [ + #-------------------------------------------------------------------- + # These are for $1Config.sh + #-------------------------------------------------------------------- + + # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) + eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}" + else + eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + fi + $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}" + $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}" + $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}" + $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}" + $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}" + $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}" + + AC_SUBST($1_BUILD_LIB_SPEC) + AC_SUBST($1_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_PATH) + AC_SUBST($1_STUB_LIB_PATH) + + AC_SUBST(MAJOR_VERSION) + AC_SUBST(MINOR_VERSION) + AC_SUBST(PATCHLEVEL) +]) + + +#------------------------------------------------------------------------ +# TEA_PATH_CELIB -- +# +# Locate Keuchel's celib emulation layer for targeting Win/CE +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-celib=... +# +# Defines the following vars: +# CELIB_DIR Full path to the directory containing +# the include and platform lib files +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CELIB], [ + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval}) + AC_MSG_CHECKING([for Windows/CE celib directory]) + AC_CACHE_VAL(ac_cv_c_celibconfig,[ + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory]) + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + ]) + if test x"${ac_cv_c_celibconfig}" = x ; then + AC_MSG_ERROR([Cannot find celib support library directory]) + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + AC_MSG_RESULT([found $CELIB_DIR]) + fi + fi +]) + + +# Local Variables: +# mode: autoconf +# End: diff --git a/tcldbg.h b/tcldbg.h new file mode 100644 index 0000000..8f9cb9a --- /dev/null +++ b/tcldbg.h @@ -0,0 +1,62 @@ +/* Dbg.h - Tcl Debugger include file + +Written by: Don Libes, NIST, 3/23/93 + +Design and implementation of this program was paid for by U.S. tax +dollars. Therefore it is public domain. However, the author and NIST +would appreciate credit if this program or parts of it are used. + +*/ + +/* _DEBUG or _DBG is just too likely, use something more unique */ +#ifndef _NIST_DBG +#define _NIST_DBG + +#include "tcl.h" + +typedef int (Dbg_InterProc) _ANSI_ARGS_((Tcl_Interp *interp, ClientData data)); +typedef int (Dbg_IgnoreFuncsProc) _ANSI_ARGS_(( + Tcl_Interp *interp, + char *funcname)); +typedef void (Dbg_OutputProc) _ANSI_ARGS_(( + Tcl_Interp *interp, + char *output, + ClientData data)); + +typedef struct { + Dbg_InterProc *func; + ClientData data; +} Dbg_InterStruct; + +typedef struct { + Dbg_OutputProc *func; + ClientData data; +} Dbg_OutputStruct; + +EXTERN char *Dbg_VarName; +EXTERN char *Dbg_DefaultCmdName; + +/* trivial interface, creates a "debug" command in your interp */ +EXTERN int Tcldbg_Init _ANSI_ARGS_((Tcl_Interp *)); + +EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp *interp, + int immediate)); +EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc,char *argv[], + int copy)); +EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN Dbg_InterStruct Dbg_Interactor _ANSI_ARGS_(( + Tcl_Interp *interp, + Dbg_InterProc *interactor, + ClientData data)); +EXTERN Dbg_IgnoreFuncsProc *Dbg_IgnoreFuncs _ANSI_ARGS_(( + Tcl_Interp *interp, + Dbg_IgnoreFuncsProc *)); +EXTERN Dbg_OutputStruct Dbg_Output _ANSI_ARGS_(( + Tcl_Interp *interp, + Dbg_OutputProc *, + ClientData data)); + +EXTERN void Dbg_StdinMode _ANSI_ARGS_((int mode)); + +#endif /* _NIST_DBG */ diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..e204c6b --- /dev/null +++ b/tests/README @@ -0,0 +1,120 @@ +Expect Test Suite +----------------- + +This directory contains a set of validation tests for the Expect +commands. Each of the files whose name ends in ".test" is intended to +fully exercise one or a few Expect commands. The commands tested by a +given file are listed in the first line of the file. + +You can run the tests in three ways: + + (a) type "make test" in the parent directory to this one; this + will run all of the tests. + + (b) type "expect <testFile> ?<option> <value>? + Command line options include: + + -help display usage information + + -verbose <level> set the level of verbosity to a substring + of "bps". See the "Test output" section + of the tcltest man page for an + explanation of this option. + + -match <matchList> only run tests that match one or more of + the glob patterns in <matchList> + + -skip <skipList> do not run tests that match one or more + of the glob patterns in <skipList> + + -file <globPatternList> + only source test files that match one or + more of the glob patterns in + <globPatternList> (relative to the + "tests" directory). This option only + applies when you run the test suite with + the "all.tcl" file. + + -notfile <globPatternList> + do not source test files that match one + or more of the patterns in + <globPatternList> (relative to the + "tests" directory). This option only + applies when you run the test suite with + the "all.tcl" file. + + -constraints <list> tests with any constraints in <list> will + not be skipped. Not that elements of + <list> must exactly match the existing + constraints. + + -limitconstraints <bool> + If 1, limit test runs to those tests that + match the constraints listed using the + -constraints flag. Use of this flag + requires use of the -constraints flag. + The default value is 0. + + -tmpdir <dirname> put temporary files created by + ::tcltest::makeFile and + ::tcltest::makeDirectory in the named + directory. The default location is + ::tcltest::workingDirectory. + + -preservecore <level> + check for core files. If level is 0, + check for core files only when + cleanupTests is called from an all.tcl + file. If 1, also check at the end of + every test command. If 2, also save core + files in ::tcltest::temporaryDirectory. + The default level is 0. + + (c) start up expect in this directory, then "source" the test + file (for example, type "source parse.test"). To run all + of the tests, type "source all.tcl". To use the options in + interactive mode, you can set their corresponding tcltest + namespace variables after loading the tcltest package. + For example, some of the tcltest variables are: + ::tcltest::match + ::tcltest::skip + ::tcltest::testConstraints(nonPortable) + ::tcltest::testConstraints(knownBug) + ::tcltest::testConstraints(userInteractive) + +Please see the man page for the 'tcltest' package for more detailed +information on the features of the testing environment. + +This approach to testing was copied from the Tcl distribution. + +Incompatibilities with prior versions +------------------------------------- + +1) Global variables such as VERBOSE, TESTS, and testConfig are now + renamed to use the new "tcltest" namespace. + + old name new name + -------- -------- + VERBOSE ::tcltest::verbose + TESTS ::tcltest::match + testConfig ::tcltest::testConstraints + +2) VERBOSE values are no longer numeric. + +3) When you run "make test", the working dir for the test suite is now + the one from which you called "make test", rather than the "tests" + directory. This change allows for both unix and windows test + suites to be run simultaneously without interference with each + other or with existing files. All tests must now run independently + of their working directory. + +4) The "all" file is now called all.tcl. + +5) The "defs" file no longer exists. + +6) Instead of creating a doAllTests file in the tests directory, to + run all nonPortable tests, just use the "-constraints nonPortable" + command line flag. If you are running interactively, you can set + the ::tcltest::testConstraints(nonPortable) variable to 1 (after + loading the tcltest package). + diff --git a/tests/all.tcl b/tests/all.tcl new file mode 100644 index 0000000..4b5c208 --- /dev/null +++ b/tests/all.tcl @@ -0,0 +1,24 @@ +# all.tcl -- +# +# This file contains a top-level script to run all of the Tcl +# tests. Execute it by invoking "source all" when running tclTest +# in this directory. + +package require tcltest +# do this in a way that is backward compatible for Tcl 8.3 +namespace import ::tcltest::test ::tcltest::cleanupTests +package require Expect + +set ::tcltest::testSingleFile false +set ::tcltest::testsDirectory [file dirname [info script]] + +foreach file [lsort [::tcltest::getMatchingFiles]] { + set tail [file tail $file] + puts stdout $tail + if {[catch {source $file} msg]} { + puts stdout $msg + } +} + +::tcltest::cleanupTests 1 +return diff --git a/tests/cat.test b/tests/cat.test new file mode 100644 index 0000000..e7735f0 --- /dev/null +++ b/tests/cat.test @@ -0,0 +1,33 @@ +# Commands covered: cat (UNIX) +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +#exp_internal -f /dev/ttyp5 0 + +catch {unset x} + +log_user 0 + +test cat-1.1 {basic cat operation} { + exp_spawn cat -u + exp_send "\r" + set timeout 10 + expect \r {set x 1} timeout {set x 0} + exp_close + exp_wait + set x +} {1} + +#exp_internal 0 + +cleanupTests +return diff --git a/tests/expect.test b/tests/expect.test new file mode 100644 index 0000000..e91cb15 --- /dev/null +++ b/tests/expect.test @@ -0,0 +1,195 @@ +# -*- tcl -*- Commands covered: cat (UNIX), expect +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +catch {unset x} + +log_user 0 + +exp_spawn cat -u +exp_stty -echo < $spawn_out(slave,name) + +test expect-1.1 {exact pattern} { + expect "*" + exp_send "a\r" + + set timeout 10 + set x 0 + expect -ex a {set x 1} + set x +} {1} + +test expect-1.2 {exact pattern buffering} { + expect "*" + exp_send "hiahi\r" + + set timeout 10 + set x 0 + expect -ex hi + expect -ex hi {set x 1} + set x +} {1} + +# if only this test fails, then configure has guessed incorrectly and +# stty accesses the control terminal from stdout. The quick fix is +# to edit expect_cf.h and define STTY_READS_STDOUT to 1. (It should +# be commented out.) If you figure out a way to fix the configure test, +# let me know. Else, let me know a way to test for your particular +# machine and os version so it can be hardwired. +test expect-1.3 {exact pattern failure} { + expect "*" + exp_send "hiahi\r" + + set timeout 10 + set x 0 + expect -ex hi {set x 1} + expect -ex hi {set x 2} + expect -ex hi {set x 3} + set x +} {2} + +test expect-1.4 {glob pattern} { + expect "*" + exp_send "a\r" + + set timeout 10 + set x 0 + expect "a" {set x 1} + set x +} {1} + +test expect-1.5 {glob pattern buffering} { + expect "*" + exp_send "a\r" + + set timeout 10 + set x 0 + expect "*" {set x 1} + set x +} {1} + +test expect-1.6 {glob buffer} { + expect "*" + exp_send "philosophic\r" + + set timeout 10 + set x 0 + expect "hi" + set x [string match *phi $expect_out(buffer)] +} {1} + +test expect-1.7 {glob string} { + expect "*" + exp_send "philosophic\r" + + set timeout 10 + set x 0 + expect "hi" + set expect_out(0,string) +} {hi} + +test expect-1.10 {re pattern, gate keeping} { + expect "*" + exp_stty raw < $spawn_out(slave,name) + exp_send "\rats-sw-8>show clock" + + #exp_internal 1 + set timeout 10 + set x 0 + expect -re {(.*)show clock$} {set x 1} + #exp_internal 0 + exp_stty -raw < $spawn_out(slave,name) + set x +} {1} + +test expect-1.11 {re pattern, gate keeping} { + exp_stty raw < $spawn_out(slave,name) + expect "*" + exp_send "enable" + + #exp_internal 1 + set timeout 10 + set x 0 + expect -re {(.*)enable$} {set x 1} + exp_stty -raw < $spawn_out(slave,name) + #exp_internal 0 + set x +} {1} + +test expect-1.12 {re pattern, gate keeping} { + exp_stty raw < $spawn_out(slave,name) + expect "*" + exp_send "sh clock" + + #exp_internal 1 + set timeout 10 + set x 0 + expect -re {(.*)sh clock$} {set x 1} + exp_stty -raw < $spawn_out(slave,name) + #exp_internal 0 + set x +} {1} + +test expect-1.13 {re pattern, gate keeping} { + exp_stty raw < $spawn_out(slave,name) + expect "*" + exp_send "Password: " + + #exp_internal 1 + set timeout 10 + set x 0 + expect -re {^.*Password: ?$} {set x 1} + exp_stty -raw < $spawn_out(slave,name) + #exp_internal 0 + set x +} {1} + + +close +wait + +set filename /tmp/null.[pid] +set fid [open $filename w] +fconfigure $fid -encoding iso8859-1 +puts $fid "a\u0000b" +close $fid + +test expect-1.8 {default remove null behavior} { + spawn cat $filename + expect a\u0000b + set rc [regexp $expect_out(buffer) "ab"] + wait + set rc +} {0} + +test expect-1.8b {default remove null behavior} { + spawn cat $filename + expect ab + set rc [regexp $expect_out(buffer) "ab"] + wait + set rc +} {1} + +test expect-1.9 {match null inline} { + spawn cat $filename + remove_nulls 0 + expect a\u0000b + set rc [regexp $expect_out(buffer) "a\u0000b"] + close + wait + set rc +} {1} + +file delete -force $filename + +cleanupTests +return diff --git a/tests/logfile.test b/tests/logfile.test new file mode 100644 index 0000000..d0a5242 --- /dev/null +++ b/tests/logfile.test @@ -0,0 +1,37 @@ +# Commands covered: log_file +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +test logfile-1.1 {basic logfile} { + set filename /tmp/logfile.[pid] + file delete -force $filename + log_file $filename + unset spawn_id ;# clean up results of previous test + send "via send" + send_user "via send_user" + send_error "via send_stdout" + if {[info exists ::tty_spawn_id]} { + send_tty "via send_tty" + } + send_log "via send_log" + log_file + set fid [open $filename] + gets $fid buffer + close $fid + file delete -force $filename + # verify everything but "send" is logged + + regexp "via send_uservia send_stdout.*via send_log" $buffer +} {1} + +cleanupTests +return diff --git a/tests/pid.test b/tests/pid.test new file mode 100644 index 0000000..211c893 --- /dev/null +++ b/tests/pid.test @@ -0,0 +1,43 @@ +# Commands covered: pid +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +catch {unset x} + +#exp_internal -f /dev/ttyp5 0 + +test pid-1.2 {basic pid operation} { + set cat [exp_spawn -noecho cat] + set x [expr 0!=$cat] + set y [expr 0==[string compare $cat [exp_pid -i $spawn_id]]] + exp_close;exp_wait + list $x $y +} {1 1} + +test pid-1.3 {basic pid operation} { + exp_spawn -noecho cat; set cat $spawn_id + exp_spawn -noecho cat; set cat2 $spawn_id + set x [expr {0!=[string compare [exp_pid -i $cat2] [exp_pid -i $cat]]}] + exp_close -i $cat;exp_wait -i $cat;exp_close -i $cat2;exp_wait -i $cat2 + set x +} {1} + +test pid-1.4 {basic pid operation} { + list [catch {exp_pid -i 100} msg] $msg +} {1 {can not find channel named "100"}} + +test pid-1.5 {basic pid operation} { + list [catch {exp_pid -j} msg] $msg +} {1 {usage: -i spawn_id}} + +cleanupTests +return diff --git a/tests/send.test b/tests/send.test new file mode 100644 index 0000000..f43a294 --- /dev/null +++ b/tests/send.test @@ -0,0 +1,39 @@ +# Commands covered: send +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +log_user 0 + +#exp_internal -f /dev/ttyp5 0 + +test send-1.1 {basic send operation} { + spawn cat + after 1000 + send "foo\r" + expect foo + after 1000 + send "\u0004" + expect eof + regexp "\r\nfoo\r\n" $expect_out(buffer) +} {1} + +test send-1.2 {send null} { + spawn od -c + send "a\u0000b\r" + after 1000 + send \u0004 + expect eof + regexp "a \\\\0 b" $expect_out(buffer) +} {1} + +cleanupTests +return diff --git a/tests/spawn.test b/tests/spawn.test new file mode 100644 index 0000000..8f86d95 --- /dev/null +++ b/tests/spawn.test @@ -0,0 +1,73 @@ +# Commands covered: spawn +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +log_user 0 + +#exp_internal -f /dev/ttyp5 0 + +test spawn-1.1 {basic spawn operation} { + set x [catch {exp_spawn cat}] + set first_spawn_id $spawn_id; # save for later test + exp_close;exp_wait + set x +} {0} + +test spawn-1.2 {spawn cat, then simple send/expect sequence} { + set cat [exp_spawn -noecho cat -u] + exp_send "a\r" + expect "a" {set x 1} timeout {set x 0} + exp_close;exp_wait + set x +} {1} + +test spawn-1.3 {spawn two processes simultaneously} { + exp_spawn -noecho cat; set cat $spawn_id + exp_spawn -noecho cat; set cat2 $spawn_id + set x [expr {0!=[string compare [exp_pid -i $cat2] [exp_pid -i $cat]]}] + exp_close -i $cat;exp_wait -i $cat;exp_close -i $cat2;exp_wait -i $cat2 + set x +} {1} + +test spawn-1.4 {spawn open file} { + set x 0 + set y 0 + + set file [open /tmp/[pid] w] + puts $file "testing expect's spawn -open" + exp_close $file + set pid [exp_spawn -open [open /tmp/[pid]]] + expect "testing expect's spawn -open" {set x 1} + expect eof {set y 1} + exec rm /tmp/[pid] + exp_wait + list $x $y $pid +} {1 1 0} + +test spawn-1.5 {spawn with no fd leak} { + exp_spawn cat + set x [expr {"$first_spawn_id"=="$spawn_id"}] + exp_close; exp_wait + set x +} {1} + +# looks to be some control-char problem +#ftest spawn-1.6 {spawn with echo} { +# exp_spawn cat +#} {spawn cat} + +#ftest spawn-1.7 {spawn with -noecho} { +# exp_spawn -noecho cat +#} {} + +cleanupTests +return diff --git a/tests/stty.test b/tests/stty.test new file mode 100644 index 0000000..64f73b9 --- /dev/null +++ b/tests/stty.test @@ -0,0 +1,33 @@ +# Commands covered: stty +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. + +if {[lsearch [namespace children] ::tcltest] == -1} { + package require tcltest + # do this in a way that is backward compatible for Tcl 8.3 + namespace import ::tcltest::test ::tcltest::cleanupTests +} +package require Expect + +#exp_internal -f /dev/ttyp5 0 + +catch {unset x} + +log_user 0 + +test stty-1.1 {basic stty operation} { + exp_spawn cat -u + catch {exp_stty < $spawn_out(slave,name)} +} {0} + +test stty-1.2 {basic stty operation} { + exp_spawn cat -u + catch {exp_stty -echo < $spawn_out(slave,name)} +} {0} + +#exp_internal 0 + +cleanupTests +return diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog new file mode 100644 index 0000000..d7b8d44 --- /dev/null +++ b/testsuite/ChangeLog @@ -0,0 +1,16 @@ +Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * expect/testsuite: made modifications to testcases, etc., to allow + them to work properly given the reorganization of deja-gnu and the + relocation of the testcases from deja-gnu to a "tool" subdirectory. + +Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * expect/testsuite: Initial creation of expect/testsuite. + Migrated dejagnu testcases and support files for testing nm to + expect/testsuite from deja-gnu. These files were moved "as is" + with no modifications. This migration is part of a major overhaul + of dejagnu. The modifications to these testcases, etc., which + will allow them to work with the new version of dejagnu will be + made in a future update. + diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in new file mode 100644 index 0000000..9823315 --- /dev/null +++ b/testsuite/Makefile.in @@ -0,0 +1,109 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +host = @host@ +bindir = @bindir@ +libdir = @libdir@ +tooldir = $(libdir)/$(target_alias) + +includedir = @includedir@ +gxx_includedir = $(tooldir)/g++-include +targetdir = $(datadir)/$(target_alias) + +SHELL = /bin/sh + +CC = @CC@ +TCL_SRC_DIR = @TCL_SRC_DIR@ + +CC_FOR_TARGET = ` \ + if [ -f $${rootme}../gcc/Makefile ] ; then \ + echo $${rootme}../gcc/xgcc -B$${rootme}../gcc/; \ + else \ + if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ + echo $(CC); \ + else \ + t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \ + fi; \ + fi` + +EXPECT = `if [ -f $${rootme}/expect ] ; \ + then echo $${rootme}/expect ; \ + else echo expect; fi` + +RUNTEST = ` \ + if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \ + echo ${srcdir}/../../dejagnu/runtest ; \ + else echo runtest ; fi` +RUNTESTFLAGS = + +all: + +binaries: + +libraries: + +.PHONY: info install-info check installcheck +info: +install-info: +check: +installcheck: +.NOEXPORT: + +check: exp_test site.exp + rootme=`cd .. && pwd`; export rootme; \ + EXPECT=${EXPECT}; export EXPECT; \ + if [ -f ../expect ] ; then \ + TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` ; \ + export TCL_LIBRARY ; \ + else true ; fi ; \ + $(RUNTEST) $(RUNTESTFLAGS) --tool expect EXPECT=$$EXPECT --srcdir $(srcdir) + +install: +uninstall: force + +exp_test.o: ${srcdir}/exp_test.c + +site.exp: ./config.status + @echo "Making a new config file..." + -@rm -f ./tmp? + @touch site.exp + -@mv site.exp site.bak + @echo "## these variables are automatically generated by make ##" > ./tmp0 + @echo "# Do not edit here. If you wish to override these values" >> ./tmp0 + @echo "# add them to the last section" >> ./tmp0 + @echo "set tool expect" >> ./tmp0 + @echo "set srcdir ${srcdir}" >> ./tmp0 + @echo "set objdir `pwd`" >> ./tmp0 + @echo "set host_triplet ${host}" >> ./tmp0 + @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0 + @cat ./tmp0 > site.exp + @cat site.bak | sed \ + -e '1,/^## All variables above are.*##/ d' >> site.exp + @rm -f ./tmp1 ./tmp0 + +clean mostlyclean: + -rm -f *~ core *.o a.out *.x + +distclean realclean: clean + -rm -f *~ core + -rm -f Makefile config.status + -rm -fr *.log summary detail + +Makefile : $(srcdir)/Makefile.in $(host_makefile_frag) + $(SHELL) ./config.status + +# Original aclocal.m4 comes from DejaGnu +# CYGNUS LOCAL: this hack lets "make -f Makefile.in" produce a configure file +configure: force + @echo "Rebuilding configure..." + if [ x"${srcdir}" = x"@srcdir@" ] ; then \ + srcdir=. ; export srcdir ; \ + else true ; fi ; \ + (cd $${srcdir}; autoconf --localdir=$${srcdir}/..) + +config.status: $(srcdir)/configure + @echo "Rebuilding config.status..." + $(SHELL) ./config.status --recheck + +force: diff --git a/testsuite/aclocal.m4 b/testsuite/aclocal.m4 new file mode 100644 index 0000000..bfd8a17 --- /dev/null +++ b/testsuite/aclocal.m4 @@ -0,0 +1,9 @@ +# +# Include the TEA standard macro set +# + +builtin(include,../tclconfig/tcl.m4) + +# +# Add here whatever m4 macros you want to define for your package +# diff --git a/testsuite/configure b/testsuite/configure new file mode 100755 index 0000000..f5f0e4b --- /dev/null +++ b/testsuite/configure @@ -0,0 +1,7059 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for exp_test 0.43. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='exp_test' +PACKAGE_TARNAME='exp_test' +PACKAGE_VERSION='0.43' +PACKAGE_STRING='exp_test 0.43' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CYGPATH EXEEXT PKG_LIB_FILE PKG_STUB_LIB_FILE PKG_STUB_SOURCES PKG_STUB_OBJECTS PKG_TCL_SOURCES PKG_HEADERS PKG_INCLUDES PKG_LIBS PKG_CFLAGS TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC CLEANFILES TCL_LIBS TCL_DEFS TCL_EXTRA_CFLAGS TCL_LD_FLAGS TCL_SHLIB_LD_LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE RANLIB ac_ct_RANLIB EGREP MATH_LIBS host LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures exp_test 0.43 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of exp_test 0.43:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-tcl directory containing tcl configuration + (tclConfig.sh) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +exp_test configure 0.43 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by exp_test $as_me 0.43, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # TEA extensions pass this us the version of TEA they think they + # are compatible with. + TEA_VERSION="3.9" + + echo "$as_me:$LINENO: checking for correct TEA configuration" >&5 +echo $ECHO_N "checking for correct TEA configuration... $ECHO_C" >&6 + if test x"${PACKAGE_NAME}" = x ; then + { { echo "$as_me:$LINENO: error: +The PACKAGE_NAME variable must be defined by your TEA configure.in" >&5 +echo "$as_me: error: +The PACKAGE_NAME variable must be defined by your TEA configure.in" >&2;} + { (exit 1); exit 1; }; } + fi + if test x"3.9" = x ; then + { { echo "$as_me:$LINENO: error: +TEA version not specified." >&5 +echo "$as_me: error: +TEA version not specified." >&2;} + { (exit 1); exit 1; }; } + elif test "3.9" != "${TEA_VERSION}" ; then + echo "$as_me:$LINENO: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5 +echo "${ECHO_T}warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6 + else + echo "$as_me:$LINENO: result: ok (TEA ${TEA_VERSION})" >&5 +echo "${ECHO_T}ok (TEA ${TEA_VERSION})" >&6 + fi + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*) + # Extract the first word of "cygpath", so it can be a program name with args. +set dummy cygpath; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CYGPATH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CYGPATH"; then + ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYGPATH="cygpath -w" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" +fi +fi +CYGPATH=$ac_cv_prog_CYGPATH +if test -n "$CYGPATH"; then + echo "$as_me:$LINENO: result: $CYGPATH" >&5 +echo "${ECHO_T}$CYGPATH" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + CYGPATH=echo + EXEEXT=".exe" + # TEA_PLATFORM is determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + { echo "$as_me:$LINENO: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 +echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} + + + + + # This package name must be replaced statically for AC_SUBST to work + + # Substitute STUB_LIB_FILE in case package creates a stub library too. + + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + + + + + + + + + +ac_aux_dir= +for ac_dir in ../tclconfig $srcdir/../tclconfig; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in ../tclconfig $srcdir/../tclconfig" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in ../tclconfig $srcdir/../tclconfig" >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + + + + + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + with_tclconfig="${withval}" +fi; + echo "$as_me:$LINENO: checking for Tcl configuration" >&5 +echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6 + if test "${ac_cv_c_tclconfig+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 +echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 +echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} + { (exit 1); exit 1; }; } + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + { { echo "$as_me:$LINENO: error: Can't find Tcl configuration definitions" >&5 +echo "$as_me: error: Can't find Tcl configuration definitions" >&2;} + { (exit 1); exit 1; }; } + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + fi + + + echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6 + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + echo "$as_me:$LINENO: result: loading" >&5 +echo "${ECHO_T}loading" >&6 + . "${TCL_BIN_DIR}/tclConfig.sh" + else + echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + case "`uname -s`" in + *CYGWIN_*) + echo "$as_me:$LINENO: checking for cygwin variant" >&5 +echo $ECHO_N "checking for cygwin variant... $ECHO_C" >&6 + case ${TCL_EXTRA_CFLAGS} in + *-mwin32*|*-mno-cygwin*) + TEA_PLATFORM="windows" + CFLAGS="$CFLAGS -mwin32" + echo "$as_me:$LINENO: result: win32" >&5 +echo "${ECHO_T}win32" >&6 + ;; + *) + TEA_PLATFORM="unix" + echo "$as_me:$LINENO: result: unix" >&5 +echo "${ECHO_T}unix" >&6 + ;; + esac + EXEEXT=".exe" + ;; + *) + ;; + esac + + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + +cat >>confdefs.h <<_ACEOF +#define BUILD_${PACKAGE_NAME} +_ACEOF + + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + + + + + + + + + + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + # If the user did not set CFLAGS, set it now to keep + # the AC_PROG_CC macro from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + + + + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5 +echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6 +if test "${tcl_cv_cc_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_pipe=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_pipe=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_pipe" >&5 +echo "${ECHO_T}$tcl_cv_cc_pipe" >&6 + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + if test "${TEA_PLATFORM}" = "unix" ; then + + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking for sin" >&5 +echo $ECHO_N "checking for sin... $ECHO_C" >&6 +if test "${ac_cv_func_sin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define sin to an innocuous variant, in case <limits.h> declares sin. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define sin innocuous_sin + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char sin (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef sin + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sin (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sin) || defined (__stub___sin) +choke me +#else +char (*f) () = sin; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != sin; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_sin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_sin=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5 +echo "${ECHO_T}$ac_cv_func_sin" >&6 +if test $ac_cv_func_sin = yes; then + MATH_LIBS="" +else + MATH_LIBS="-lm" +fi + + echo "$as_me:$LINENO: checking for main in -lieee" >&5 +echo $ECHO_N "checking for main in -lieee... $ECHO_C" >&6 +if test "${ac_cv_lib_ieee_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lieee $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ieee_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ieee_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ieee_main" >&5 +echo "${ECHO_T}$ac_cv_lib_ieee_main" >&6 +if test $ac_cv_lib_ieee_main = yes; then + MATH_LIBS="-lieee $MATH_LIBS" +fi + + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + echo "$as_me:$LINENO: checking for main in -linet" >&5 +echo $ECHO_N "checking for main in -linet... $ECHO_C" >&6 +if test "${ac_cv_lib_inet_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_inet_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_inet_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_inet_main" >&5 +echo "${ECHO_T}$ac_cv_lib_inet_main" >&6 +if test $ac_cv_lib_inet_main = yes; then + LIBS="$LIBS -linet" +fi + + if test "${ac_cv_header_net_errno_h+set}" = set; then + echo "$as_me:$LINENO: checking for net/errno.h" >&5 +echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_net_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking net/errno.h usability" >&5 +echo $ECHO_N "checking net/errno.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <net/errno.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking net/errno.h presence" >&5 +echo $ECHO_N "checking net/errno.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <net/errno.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: net/errno.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: net/errno.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: net/errno.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: net/errno.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: net/errno.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: net/errno.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: net/errno.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: net/errno.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for net/errno.h" >&5 +echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_net_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_net_errno_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6 + +fi +if test $ac_cv_header_net_errno_h = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NET_ERRNO_H 1 +_ACEOF + +fi + + + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case <limits.h> declares connect. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 +if test $ac_cv_func_connect = yes; then + tcl_checkSocket=0 +else + tcl_checkSocket=1 +fi + + if test "$tcl_checkSocket" = 1; then + echo "$as_me:$LINENO: checking for setsockopt" >&5 +echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6 +if test "${ac_cv_func_setsockopt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define setsockopt to an innocuous variant, in case <limits.h> declares setsockopt. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define setsockopt innocuous_setsockopt + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char setsockopt (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef setsockopt + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setsockopt (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setsockopt) || defined (__stub___setsockopt) +choke me +#else +char (*f) () = setsockopt; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != setsockopt; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_setsockopt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_setsockopt=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5 +echo "${ECHO_T}$ac_cv_func_setsockopt" >&6 +if test $ac_cv_func_setsockopt = yes; then + : +else + echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5 +echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_setsockopt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setsockopt (); +int +main () +{ +setsockopt (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_setsockopt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_setsockopt=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6 +if test $ac_cv_lib_socket_setsockopt = yes; then + LIBS="$LIBS -lsocket" +else + tcl_checkBoth=1 +fi + +fi + + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + echo "$as_me:$LINENO: checking for accept" >&5 +echo $ECHO_N "checking for accept... $ECHO_C" >&6 +if test "${ac_cv_func_accept+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define accept to an innocuous variant, in case <limits.h> declares accept. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define accept innocuous_accept + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char accept (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef accept + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char accept (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_accept) || defined (__stub___accept) +choke me +#else +char (*f) () = accept; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != accept; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_accept=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_accept=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_accept" >&5 +echo "${ECHO_T}$ac_cv_func_accept" >&6 +if test $ac_cv_func_accept = yes; then + tcl_checkNsl=0 +else + LIBS=$tk_oldLibs +fi + + fi + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 +if test $ac_cv_func_gethostbyname = yes; then + : +else + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + LIBS="$LIBS -lnsl" +fi + +fi + + + # TEA specific: Don't perform the eval of the libraries here because + # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + + + + + echo "$as_me:$LINENO: checking dirent.h" >&5 +echo $ECHO_N "checking dirent.h... $ECHO_C" >&6 +if test "${tcl_cv_dirent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ + +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_dirent_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_dirent_h=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_dirent_h" >&5 +echo "${ECHO_T}$tcl_cv_dirent_h" >&6 + + if test $tcl_cv_dirent_h = no; then + +cat >>confdefs.h <<\_ACEOF +#define NO_DIRENT_H 1 +_ACEOF + + fi + + # TEA specific: + if test "${ac_cv_header_errno_h+set}" = set; then + echo "$as_me:$LINENO: checking for errno.h" >&5 +echo $ECHO_N "checking for errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_errno_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking errno.h usability" >&5 +echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <errno.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking errno.h presence" >&5 +echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <errno.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for errno.h" >&5 +echo $ECHO_N "checking for errno.h... $ECHO_C" >&6 +if test "${ac_cv_header_errno_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_errno_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 +echo "${ECHO_T}$ac_cv_header_errno_h" >&6 + +fi +if test $ac_cv_header_errno_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_ERRNO_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_float_h+set}" = set; then + echo "$as_me:$LINENO: checking for float.h" >&5 +echo $ECHO_N "checking for float.h... $ECHO_C" >&6 +if test "${ac_cv_header_float_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 +echo "${ECHO_T}$ac_cv_header_float_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking float.h usability" >&5 +echo $ECHO_N "checking float.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <float.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking float.h presence" >&5 +echo $ECHO_N "checking float.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <float.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: float.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for float.h" >&5 +echo $ECHO_N "checking for float.h... $ECHO_C" >&6 +if test "${ac_cv_header_float_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_float_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 +echo "${ECHO_T}$ac_cv_header_float_h" >&6 + +fi +if test $ac_cv_header_float_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_FLOAT_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_values_h+set}" = set; then + echo "$as_me:$LINENO: checking for values.h" >&5 +echo $ECHO_N "checking for values.h... $ECHO_C" >&6 +if test "${ac_cv_header_values_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 +echo "${ECHO_T}$ac_cv_header_values_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking values.h usability" >&5 +echo $ECHO_N "checking values.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <values.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking values.h presence" >&5 +echo $ECHO_N "checking values.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <values.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: values.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: values.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: values.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: values.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: values.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: values.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: values.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: values.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for values.h" >&5 +echo $ECHO_N "checking for values.h... $ECHO_C" >&6 +if test "${ac_cv_header_values_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_values_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 +echo "${ECHO_T}$ac_cv_header_values_h" >&6 + +fi +if test $ac_cv_header_values_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_VALUES_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_limits_h+set}" = set; then + echo "$as_me:$LINENO: checking for limits.h" >&5 +echo $ECHO_N "checking for limits.h... $ECHO_C" >&6 +if test "${ac_cv_header_limits_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 +echo "${ECHO_T}$ac_cv_header_limits_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking limits.h usability" >&5 +echo $ECHO_N "checking limits.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <limits.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking limits.h presence" >&5 +echo $ECHO_N "checking limits.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <limits.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for limits.h" >&5 +echo $ECHO_N "checking for limits.h... $ECHO_C" >&6 +if test "${ac_cv_header_limits_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_limits_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 +echo "${ECHO_T}$ac_cv_header_limits_h" >&6 + +fi +if test $ac_cv_header_limits_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIMITS_H 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define NO_LIMITS_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_stdlib_h+set}" = set; then + echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking stdlib.h usability" >&5 +echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <stdlib.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking stdlib.h presence" >&5 +echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_stdlib_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 + +fi +if test $ac_cv_header_stdlib_h = yes; then + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtol" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtoul" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtod" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + if test $tcl_ok = 0; then + +cat >>confdefs.h <<\_ACEOF +#define NO_STDLIB_H 1 +_ACEOF + + fi + if test "${ac_cv_header_string_h+set}" = set; then + echo "$as_me:$LINENO: checking for string.h" >&5 +echo $ECHO_N "checking for string.h... $ECHO_C" >&6 +if test "${ac_cv_header_string_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 +echo "${ECHO_T}$ac_cv_header_string_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking string.h usability" >&5 +echo $ECHO_N "checking string.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <string.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking string.h presence" >&5 +echo $ECHO_N "checking string.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for string.h" >&5 +echo $ECHO_N "checking for string.h... $ECHO_C" >&6 +if test "${ac_cv_header_string_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_string_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 +echo "${ECHO_T}$ac_cv_header_string_h" >&6 + +fi +if test $ac_cv_header_string_h = yes; then + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strstr" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strerror" >/dev/null 2>&1; then + : +else + tcl_ok=0 +fi +rm -f conftest* + + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + +cat >>confdefs.h <<\_ACEOF +#define NO_STRING_H 1 +_ACEOF + + fi + + if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/wait.h" >&5 +echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/wait.h usability" >&5 +echo $ECHO_N "checking sys/wait.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/wait.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/wait.h presence" >&5 +echo $ECHO_N "checking sys/wait.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/wait.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/wait.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/wait.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/wait.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/wait.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/wait.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/wait.h" >&5 +echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_wait_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 + +fi +if test $ac_cv_header_sys_wait_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_SYS_WAIT_H 1 +_ACEOF + +fi + + + if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo "$as_me:$LINENO: checking for dlfcn.h" >&5 +echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 +if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 +echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking dlfcn.h usability" >&5 +echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <dlfcn.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking dlfcn.h presence" >&5 +echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <dlfcn.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for dlfcn.h" >&5 +echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 +if test "${ac_cv_header_dlfcn_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_dlfcn_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 +echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 + +fi +if test $ac_cv_header_dlfcn_h = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define NO_DLFCN_H 1 +_ACEOF + +fi + + + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + +for ac_header in sys/param.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------------- ## +## Report this to the exp_test lists. ## +## ----------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + # Let the user call this, because if it triggers, they will + # need a compat/strtod.c that is correct. Users can also + # use Tcl_GetDouble(FromObj) instead. + #TEA_BUGGY_STRTOD + fi + + + + ac_config_files="$ac_config_files Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by exp_test $as_me 0.43, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +exp_test config.status 0.43 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CYGPATH@,$CYGPATH,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@PKG_LIB_FILE@,$PKG_LIB_FILE,;t t +s,@PKG_STUB_LIB_FILE@,$PKG_STUB_LIB_FILE,;t t +s,@PKG_STUB_SOURCES@,$PKG_STUB_SOURCES,;t t +s,@PKG_STUB_OBJECTS@,$PKG_STUB_OBJECTS,;t t +s,@PKG_TCL_SOURCES@,$PKG_TCL_SOURCES,;t t +s,@PKG_HEADERS@,$PKG_HEADERS,;t t +s,@PKG_INCLUDES@,$PKG_INCLUDES,;t t +s,@PKG_LIBS@,$PKG_LIBS,;t t +s,@PKG_CFLAGS@,$PKG_CFLAGS,;t t +s,@TCL_VERSION@,$TCL_VERSION,;t t +s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t +s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t +s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t +s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t +s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t +s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t +s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t +s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t +s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t +s,@CLEANFILES@,$CLEANFILES,;t t +s,@TCL_LIBS@,$TCL_LIBS,;t t +s,@TCL_DEFS@,$TCL_DEFS,;t t +s,@TCL_EXTRA_CFLAGS@,$TCL_EXTRA_CFLAGS,;t t +s,@TCL_LD_FLAGS@,$TCL_LD_FLAGS,;t t +s,@TCL_SHLIB_LD_LIBS@,$TCL_SHLIB_LD_LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@EGREP@,$EGREP,;t t +s,@MATH_LIBS@,$MATH_LIBS,;t t +s,@host@,$host,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/testsuite/configure.in b/testsuite/configure.in new file mode 100644 index 0000000..cac7cec --- /dev/null +++ b/testsuite/configure.in @@ -0,0 +1,14 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT([exp_test],[0.43]) + +TEA_INIT([3.9]) + +AC_CONFIG_AUX_DIR(../tclconfig) + +TEA_PATH_TCLCONFIG +TEA_LOAD_TCLCONFIG + +TEA_SETUP_COMPILER + +AC_SUBST(host) +AC_OUTPUT(Makefile) diff --git a/testsuite/exp_test.c b/testsuite/exp_test.c new file mode 100644 index 0000000..29f8d1c --- /dev/null +++ b/testsuite/exp_test.c @@ -0,0 +1,33 @@ +/* + * exp-test -- this is a simple C program to test the interactive functions of expect. + */ + +#include <stdio.h> +#include <string.h> + +#define ARRAYSIZE 128 + +main (argc, argv) +int argc; +char *argv[]; +{ + char line[ARRAYSIZE]; + + do { + memset (line, 0, ARRAYSIZE); + fgets (line, ARRAYSIZE, stdin); + *(line + strlen(line)-1) = '\0'; /* get rid of the newline */ + + /* look for a few simple commands */ + if (strncmp (line,"prompt ", 6) == 0) { + printf ("%s (y or n) ?", line + 6); + if (getchar() == 'y') + puts ("YES"); + else + puts ("NO"); + } + if (strncmp (line, "print ", 6) == 0) { + puts (line + 6); + } + } while (strncmp (line, "quit", 4)); +} diff --git a/vgrindefs b/vgrindefs new file mode 100644 index 0000000..414057c --- /dev/null +++ b/vgrindefs @@ -0,0 +1,30 @@ +# vgrindefs for Expect +# Author: Brian Fitzgerald <fitz@mml0.meche.rpi.edu> +# Department of Mechanical Engineering +# Rensselaer Polytechnic Institute +# Date: Sat, 12 Oct 91 13:41:36 EDT +# +# To install this file, append it to /usr/lib/vgrindefs +# +# vgrind is a troff pretty-printer. For example, to use it on a Sun with the +# Adobe Transcript package, install this file and do: +# +# setenv TROFF ptroff +# vgrind -lexpect file +# +expect|tcl:\ + :pb=(^|;)\d?proc\d\p\d:\ + :id=!$%&'()*+,-./\:<=>?@^_`|}~:\ + :bb={:be=}:\ + :cb=#:ce=$:\ + :sb=":se=\e":\ + :kw=debug disconnect exit\ + expect expect_user expect_before expect_after expect_version\ + fork\ + interact log_file log_user overlay\ + send send_spawn send_user send_log send_error\ + spawn system trace trap wait\ + break case catch concat continue error eval exec expr file for foreach\ + format glob global history if then else index info length list print\ + proc range rename return scan set source string time uplevel upvar: + |