expect5.45/0000775002342100234200000000000011466322022013462 5ustar andreaskDomainUsersexpect5.45/exp_glob.c0000664002342100234200000002467411412763435015452 0ustar andreaskDomainUsers/* 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: */ expect5.45/INSTALL0000664002342100234200000002467506733503545014545 0ustar andreaskDomainUsersThis 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. expect5.45/NEWS0000664002342100234200000007115307141641156014177 0ustar andreaskDomainUsersThis 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. expect5.45/exp_clib.c0000664002342100234200000021565211437300053015424 0ustar andreaskDomainUsers/* 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 #include #ifdef HAVE_INTTYPES_H # include #endif #include #include #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef CRAY # ifndef TCSETCTTY # if defined(HAVE_TERMIOS) # include # else # include # endif # endif #endif #ifdef HAVE_SYS_FCNTL_H # include #else # include #endif #ifdef HAVE_STRREDIR_H #include # ifdef SRIOCSREDIR # undef TIOCCONS # endif #endif #include /*#include - deprecated - ANSI C moves them into string.h */ #include "string.h" #include #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 /* for malloc */ #endif #include #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 */ # include 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 , 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 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,"<>",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 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;pre,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 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(""); /* 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); } expect5.45/exp_noevent.c0000664002342100234200000001007011412763435016166 0ustar andreaskDomainUsers/* 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 #include #include #ifdef HAVE_SYS_WAIT_H #include #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; } expect5.45/exp_tty.c0000664002342100234200000004422711412763435015343 0ustar andreaskDomainUsers/* exp_tty.c - tty support routines */ #include "expect_cf.h" #include #include #include "string.h" #ifdef HAVE_SYS_FCNTL_H # include #else # include #endif #include #ifdef HAVE_INTTYPES_H # include #endif #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_WAIT_H #include #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(""); 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/dev/tty", #else " " */ 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 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: */ expect5.45/exp_trap.c0000664002342100234200000003226511436031571015463 0ustar andreaskDomainUsers/* 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 #include #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_STRING_H #include #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 0 && sig < NSIG) return sig; } else { /* try interpreting as a string */ for (sig=1;sig 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;iaction); 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); } expect5.45/exp_main_exp.c0000664002342100234200000000271511412763435016317 0ustar andreaskDomainUsers/* 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 #include "tcl.h" #include "expect_tcl.h" #include 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. */ } expect5.45/tclconfig/0000775002342100234200000000000011466322022015432 5ustar andreaskDomainUsersexpect5.45/tclconfig/tcl.m40000664002342100234200000037602211466322022016470 0ustar andreaskDomainUsers# 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 ], [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 ], [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_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 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 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 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 #include 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 #include 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 #include 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 #include ], [ #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 ?]) fi # TEA specific: AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have ?])]) AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have ?])]) AC_CHECK_HEADER(limits.h, [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have ?])], [AC_DEFINE(NO_LIMITS_H, 1, [Do we have ?])]) 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 ?]) 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 ?]) fi AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have ?])]) # 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 ], , 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 ], 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 ], [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 ], [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 ], [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 ], [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 ?])]) #-------------------------------------------------------------------- # 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 ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include ], [struct stat64 buf; int i = stat64("/", &buf);]) TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include ], [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 #include ],[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 ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_TRY_COMPILE([#include ],[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 ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_TRY_COMPILE([#include ],[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 ?]) 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 tclPort.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 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 tkPort.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 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: expect5.45/tclconfig/config.guess0000775002342100234200000012247111466322022017761 0ustar andreaskDomainUsers#! /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 . # Please send patches to . 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 ." 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 /* 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 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 #include 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 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 #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 #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' /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 echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 < # include #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 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 # 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 < 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: expect5.45/tclconfig/config.sub0000775002342100234200000007344211466322022017427 0ustar andreaskDomainUsers#! /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 . 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 ." 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: expect5.45/tclconfig/install-sh0000775002342100234200000000421211466322022017435 0ustar andreaskDomainUsers#!/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 expect5.45/expect.h0000664002342100234200000002631411437300053015127 0ustar andreaskDomainUsers/* 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 #include /* * 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 #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 # 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 # 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 */ expect5.45/exp_inter.c0000664002342100234200000016666011437300053015640 0ustar andreaskDomainUsers/* 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 #ifdef HAVE_INTTYPES_H # include #endif #include #ifdef HAVE_UNISTD_H # include #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_WAIT_H #include #endif #include #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 #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 #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: */ expect5.45/exp_int.h0000664002342100234200000000213711412763435015314 0ustar andreaskDomainUsers/* 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 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 /* for malloc */ #endif /*NO_STDLIB_H*/ #endif /* _EXPECT_INT_H */ expect5.45/fixline10000774002342100234200000000130407726156645015150 0ustar andreaskDomainUsers#!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]" expect5.45/expect.c0000664002342100234200000024463711461650640015143 0ustar andreaskDomainUsers/* 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 #include #include #include #include /* for isspace */ #include /* for time(3) */ #include "expect_cf.h" #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_UNISTD_H # include #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;iecd.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) { 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;iecd.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;iecd.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;iecd.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;jecd.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;iecd.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) { 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;iecd.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;iecd.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) 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) { 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;icount;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: */ expect5.45/tcldbg.h0000664002342100234200000000330510222357741015100 0ustar andreaskDomainUsers/* 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 */ expect5.45/ChangeLog0000664002342100234200000015530311461650640015250 0ustar andreaskDomainUsers2010-10-26 Andreas Kupries * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 * 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 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 * exp_clib.c (TclRegComp): Fixed memory leak reported by in [Expect SF Bug 2814263]. 2009-06-22 Andreas Kupries * pty_unicos.c (pty_stty): Fixed missing double-quotes for sprint formatting strings. Thanks to for the report, i.e. [Expect SF Bug 2809496]. 2009-06-18 Andreas Kupries * 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 . 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 * 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 * retoglob.c: Accepted the patch by Mike Cumings 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 * 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 , 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 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 * 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 . * configure.in: Bumped version to 5.44.1.10. * configure: Regen'd, autoconf 2.59. 2008-08-18 Jeff Hobbs * exp_main_sub.c (exp_interpreter): cleaner handling of commandPtr to prevent crash. (das) 2008-06-03 Andreas Kupries * 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 * 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 * 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 . * 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 * 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 . * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * Merged changes from the official version 5.44.1 of expect into the SF sources. See the details below. -------------------- Marius Schamsula 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 noted the home page should note that Wikipedia has a very readable entry for Expect. Andre Alves 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 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 * 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 * 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 * tclconfig/tcl.m4: Updated to TEA 3.5 * configure.in: Ditto. * configure: Regenerated. 2006-01-10 Jeff Hobbs * tests/expect.test: ensure iso8859-1 for /tmp/null (steffen). 2005-09-19 Andreas Kupries * 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 * exp_chan.c (ExpBlockModeProc): No, stdin is not ok (See last entry). Fixed. 2005-07-07 Andreas Kupries * 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 * 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 * 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 * 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 * 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 * 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 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 noted that expect_background ignores timeouts. Added to documentation. Jens Peterson provided patch for "mkpasswd -vo". Gary Bliesener 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 provided patch for MacOS to avoid panic-redefinition. -------------------- 2005-01-21 Andreas Kupries * 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 * exp_chan.c (ExpOutputProc): Added code posted by Don on c.l.t. to handle interrupted system calls (EAGAIN). 2004-07-15 Andreas Kupries * Merged changes from the official version 5.42b0 of expect into the SF sources. See details below. -------------------- Alexander Doktorovich 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 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 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 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 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 * 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 * aclocal.m4 (TCLHDIRDASHI): Extended with path to unix headers as well. * expect_tcl.h: Added inclusion of . Both changes required for Expect to compile against Tcl 8.5 after the header reform. * configure: Regenerated. 2004-05-19 Andreas Kupries * Merged changes from the official version 5.41 of expect into the SF sources. See details below. -------------------- Simon Taylor 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 encountered interact diagnostics incorrectly pointing to expect_background. Also, found multiple -o flags behaving unexpectedly. Added diag. Kristoffer Eriksson noted typo in SIMPLE code in exp_inter.c. However, this is extremely unlikely to affect any machines. Reinhard Max 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 * 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 provided troff-related fixes for the expect, lib, and dislocate man pages. Rich Kennedy 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 provided patch for leak in spawn error handling. Pete Lancashire noted autopasswd example broke on Solaris which capitalized prompts. -------------------- 2003-10-20 Andreas Kupries * 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 . 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 > 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 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 * Merged changes from the official version 5.39 of expect into the SF sources. See details below. Partially already done. -------------------- Poorva Gupta noted that grantpt/unlockpt order was backward. Strange that this was never a prob before! Eric Raymond provided a troff-related fix for the multixterm man page. Nicolas Roeser 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 and Igor Sobrado noted that fixline1 rewrote scripts to be expect scripts even if they were expectk scripts. Dirk Petera 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 noted that ncurses ignores 2-char term names because of, well, poor assumptions and coding. Changed tkterm to use longer names. Heath Moore noted that exp_clib could lock up if remtime happened to be precisely 0. Recoded to avoid. At request of Per Otterholm , 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 pointed out that by default, SIGINT/TERM should cause expect's return status to be 1, not 0. Paul Reithmuller noted that unbuffer shouldn't postprocess its output. Added stty_init. Mordechai T. Abzug noted that log_file wasn't recording -append status. James Kelly noted weather example needed new source. Dimitar Haralanov noted that interact dumped core with interact { timeout 1 } -------------------- 2003-06-16 Andreas Kupries * exp_command.c: Applied patch provided on c.l.t., by Don Libes in response to a bug report by Dirk Petera in same place. See thread reference below: http://groups.google.ca/groups?threadm=4791f5a6.0305250619.1a660299%40posting.google.com 2003-05-08 Andreas Kupries * exp_clib.c (expectv): Applied patch provided on c.l.t., by Don Libes in response to a bug report by "Heath Moore" 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 * 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 * configure.in: Made expect aware of tcl stubs. Derived from the * exp_command.h: patches to expect done by Steve Landers * exp_command.c: . 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 * 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 * exp_log.c (expLogChannelOpen): Fixed the bug reported on comp.lang.tcl by Mordechai T. Abzug . The bugfix itself was provided by Don Libes. 2002-10-09 Andreas Kupries * 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 * 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 * 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 * 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 * 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 * 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 * Andreas Kupries mods to provide CONST support per TIP 27 (Fixed SF Patch #525074). 2002-02-25 Andreas Kupries * expect.c: Applied patch by Don Libes fixing improper internationalization. 2002-02-21 Andreas Kupries * 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 * 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 * 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 * Resynchronization of SourceForge with Don's sources to Expect version 5.34. The changes are Don Porter provided package-related fixes for test suite. Brian Theado 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 * 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 * 'telco-tec-win32-branch' branch created. 2001-08-01 Jeff Hobbs * Dbg.c (Dbg_On): fixed handling of stepping. [Bug: #446412] 2000-04-26 Rob Savoye * 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 * 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 * 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 * 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 * Makefile.in (install_shared_lib): Put else clause onto each if. Fri Nov 15 11:23:43 1996 Tom Tromey * 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 * configure: Regenerated. * configure.in (stty_reads_stdout): /bin/stty on DG/UX fails. Fri Sep 27 10:15:48 1996 Tom Tromey * 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 * 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 * 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 * configure.in (i[345]86-*-*): Recognize i686 for pentium pro. * configure: Regenerate. Mon Aug 5 12:55:06 1996 Tom Tromey * 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 * 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 * 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 * exp_regexp.c (regmatch, regrepeat): Only declare strchr if it is not a macro. Mon Jan 22 11:17:06 1996 Tom Tromey * 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 * Makefile.in (install, ${SCRIPT_LIST}, test): Find new Tcl libraries. Thu Jan 18 13:43:13 1996 Tom Tromey * Most files: Update to expect 5.19. Fri Jan 12 16:22:12 1996 Tom Tromey * 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 * 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 . * 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 * 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 * 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 * Most files: Update to expect 5.18.1. Fri Nov 17 17:31:55 1995 Rob Savoye * configure.in: Add support for SCO OpenServer. It doesn't like the trap either. Thu Nov 16 09:28:53 1995 Rob Savoye * 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 * 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 * 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 * 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 * Makefile.in (configure): Removed rule that automatically rebuilds configure script. Users might not have autoconf. Tue Jul 18 23:15:03 1995 Fred Fish * expect.c (Exp_ExpectGlobalCmd): Cast ckrealloc first arg to char*. Sun Jun 18 13:02:41 1995 Fred Fish * 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 * Makefile.in (exp_clib.o): Add dependencies. Mon May 1 16:50:22 1995 Rob Savoye * configure.in: Also set XINCLUDES in the Makefile. Fri Apr 28 18:56:02 1995 Rob Savoye * 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 * 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 * configure.in: Copy Dbg_cf.h to objdir, not srcdir. Tue Apr 11 18:52:24 1995 Rob Savoye * 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 * configure.in: Add a trap so the configure runs in the background. Thu Mar 16 16:56:08 1995 Rob Savoye * 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 * Makefile.in (check): Pass EXPECT correctly to runtest. Thu Oct 20 18:04:06 1994 Rob Savoye * 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 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. expect5.45/README0000664002342100234200000003455310641005271014352 0ustar andreaskDomainUsersNOTE: 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 , 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. expect5.45/configure.in0000775002342100234200000007366211436031571016017 0ustar andreaskDomainUsersdnl 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 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 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 #include ], [ 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 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 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 #include 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 #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 29Mar93 SEDDEFS="${SEDDEFS}CONFEOF cat >> conftest.sed </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 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 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 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 # endif # include 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 #endif #include 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 #endif #include 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) expect5.45/pty_unicos.c0000664002342100234200000002460211217731007016027 0ustar andreaskDomainUsers/* 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 #include #if defined(SIGCLD) && !defined(SIGCHLD) #define SIGCHLD SIGCLD #endif #ifdef HAVE_UNISTD_H #include #else extern int fork(), execl(), wait(); #endif #include #include #include #include #include #ifdef HAVE_SYS_FCNTL_H # include #else # include #endif /*#if CRAY>=60*/ #if defined(HAVE_TERMIOS) # include #else # include /*#endif /* 60 */*/ #endif /* defined(HAVE_TERMIOS) */ #if CRAY>=70 && defined(_CRAY2) #include #endif /* 70 */ #include #include #include #include #include "exp_tty_in.h" #include "exp_rename.h" #ifdef HAVE_SYSCONF_H #include #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); } expect5.45/exp_pty.h0000664002342100234200000000120110775226715015333 0ustar andreaskDomainUsers/* 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; expect5.45/FAQ0000664002342100234200000022237711413406723014034 0ustar andreaskDomainUsersExpect 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 ? #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 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 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 ? 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 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 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 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 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) 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 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 together? From: libes (Don Libes) To: Frank Winkler 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 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 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 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 , Kirby Hughes 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: atdt ... But instead I see: 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) 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 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 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 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 | B. Kramer Home Page 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" 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 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 expect5.45/exp_tty.h0000664002342100234200000000151410775226715015346 0ustar andreaskDomainUsers/* 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__ */ expect5.45/exp_win.c0000664002342100234200000001004511412763435015307 0ustar andreaskDomainUsers/* 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 #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 #else # include #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 #endif /* SCO defines window size structure in PTEM and TIOCGWINSZ in termio.h */ /* Sigh... */ #if defined(HAVE_SYS_PTEM_H) # include /* for stream.h's caddr_t */ # include /* for ptem.h's mblk_t */ # include #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: */ expect5.45/testsuite/0000775002342100234200000000000011466322022015513 5ustar andreaskDomainUsersexpect5.45/testsuite/ChangeLog0000664002342100234200000000140511413406723017270 0ustar andreaskDomainUsersMon 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. expect5.45/testsuite/configure.in0000664002342100234200000000035711436031571020034 0ustar andreaskDomainUsersdnl 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) expect5.45/testsuite/Makefile.in0000664002342100234200000000533411436031571017570 0ustar andreaskDomainUsersVPATH = @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: expect5.45/testsuite/aclocal.m40000664002342100234200000000022611436031571017356 0ustar andreaskDomainUsers# # Include the TEA standard macro set # builtin(include,../tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # expect5.45/testsuite/exp_test.c0000664002342100234200000000125511413406723017520 0ustar andreaskDomainUsers/* * exp-test -- this is a simple C program to test the interactive functions of expect. */ #include #include #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)); } expect5.45/testsuite/configure0000774002342100234200000063723611436031571017445 0ustar andreaskDomainUsers#! /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 #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #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 if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory 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 &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &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 #include #include #include /* 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 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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 #include #include #include 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 _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 _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 #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 #include 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 #include 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 declares sin. For example, HP-UX 11i declares gettimeofday. */ #define sin innocuous_sin /* System header to define __stub macros and hopefully few prototypes, which can conflict with char sin (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 _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 _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 declares connect. For example, HP-UX 11i declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 declares setsockopt. For example, HP-UX 11i declares gettimeofday. */ #define setsockopt innocuous_setsockopt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char setsockopt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 declares accept. For example, HP-UX 11i declares gettimeofday. */ #define accept innocuous_accept /* System header to define __stub macros and hopefully few prototypes, which can conflict with char accept (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 declares gethostbyname. For example, HP-UX 11i declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 #include 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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 _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 ." _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 expect5.45/exp_tty_comm.c0000664002342100234200000000150311412763435016344 0ustar andreaskDomainUsers/* exp_tty_comm.c - tty support routines common to both Expect program and library */ #include "expect_cf.h" #include #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; } expect5.45/Makefile.in0000664002342100234200000005425211451142537015544 0ustar andreaskDomainUsers# 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: expect5.45/exp_log.h0000664002342100234200000000426411412763435015306 0ustar andreaskDomainUsers/* 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)); expect5.45/expect_cf.h.in0000664002342100234200000000406110641005272016200 0ustar andreaskDomainUsers/* * 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__ */ expect5.45/exp_event.h0000664002342100234200000000165311412763435015645 0ustar andreaskDomainUsers/* 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)); expect5.45/example/0000775002342100234200000000000011466322022015115 5ustar andreaskDomainUsersexpect5.45/example/beer.exp0000774002342100234200000000561410365771353016574 0ustar andreaskDomainUsers#!/depot/path/expect -f # 99 bottles of beer on the wall, Expect-style # Author: Don Libes # 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]}] } } expect5.45/example/passwdprompt0000775002342100234200000000135707726156647017642 0ustar andreaskDomainUsers#!/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: "]" expect5.45/example/xpstat0000774002342100234200000001471611451204656016404 0ustar andreaskDomainUsers#!/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 { 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 { 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 } expect5.45/example/Makefile0000664002342100234200000000270407035221636016566 0ustar andreaskDomainUsersEXPVERSION = 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) expect5.45/example/virterm0000774002342100234200000003512711451204656016550 0ustar andreaskDomainUsers#!/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 # # 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 } } } } expect5.45/example/dislocate.man0000664002342100234200000000520310017242664017565 0ustar andreaskDomainUsers.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 expect5.45/example/lpunlock0000774002342100234200000000507311451204656016704 0ustar andreaskDomainUsers#!/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 \[\]\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 expect5.45/example/tkpasswd0000774002342100234200000004027211436031571016712 0ustar andreaskDomainUsers#!/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 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 to move to the next entry.\ Press or click the 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 \$parm_tabList" bind $w.$name.entry "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 {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 {select %W %x,%y} bind Text {select %W %x,%y} bind Text <2> {select %W %x,%y} bind Text <3> {select %W %x,%y} bind Text {} bind Text {} bind Text {} bind Text {} bind .password {incr selection_line 1; make_selection} bind .password {incr selection_line -1;make_selection} bind .password {select_next_nopassword 1} bind .password {select_next_nopassword -1} bind .password {password_generate} bind .password {adjust_parameters} bind .password {set password ""} bind Entry {exit} expect5.45/example/decryptdir0000774002342100234200000000252511451204656017225 0ustar andreaskDomainUsers#!/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" expect5.45/example/unbuffer.c0000664002342100234200000000026011413406723017076 0ustar andreaskDomainUsers/* unbuffer.c */ #include #include "expect.h" main(argc,argv) int argc; char *argv[]; { argv++; exp_timeout = -1; exp_expectl(exp_spawnv(*argv,argv),exp_end); } expect5.45/example/passmass.man0000664002342100234200000000637510641005274017460 0ustar andreaskDomainUsers.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 expect5.45/example/read1char0000664002342100234200000000034611451204656016703 0ustar andreaskDomainUsers#!/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) expect5.45/example/autopasswd0000774002342100234200000000056711451204656017252 0ustar andreaskDomainUsers#!/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 expect5.45/example/xkibitz0000774002342100234200000001137611451204656016544 0ustar andreaskDomainUsers#!/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 "+ add" puts "- drop" puts "where is an X display name such as nist.gov or nist.gov:0.0" puts "and 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 } expect5.45/example/chesslib.c0000664002342100234200000000253207035221636017065 0ustar andreaskDomainUsers/* chesslib.c - test expectlib */ #include #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); } } expect5.45/example/chesslib++.c0000664002342100234200000000264307035221636017216 0ustar andreaskDomainUsers/* testlib.c for c++ - test expectlib */ #include #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); } } expect5.45/example/ftp-rfc0000774002342100234200000000125311451204656016412 0ustar andreaskDomainUsers#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} package require Expect # ftp-rfc # 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 expect5.45/example/timed-run0000774002342100234200000000042511451204656016755 0ustar andreaskDomainUsers#!/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 expect5.45/example/beer.exp.out0000664002342100234200000000532711413406723017370 0ustar andreaskDomainUsers99 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. expect5.45/example/timed-read0000774002342100234200000000045711451204656017071 0ustar andreaskDomainUsers#!/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)} expect5.45/example/xrlogin0000664002342100234200000000105107035221640016520 0ustar andreaskDomainUsers#!/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 expect5.45/example/rogue.exp0000774002342100234200000000065511451204656016772 0ustar andreaskDomainUsers#!/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 expect5.45/example/autoexpect0000774002342100234200000001703211436031571017231 0ustar andreaskDomainUsers#!/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" expect5.45/example/README0000664002342100234200000001534110641005273016001 0ustar andreaskDomainUsersThis 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. expect5.45/example/autoexpect.man0000664002342100234200000001503511413406723020002 0ustar andreaskDomainUsers.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. expect5.45/example/passwd.cgi0000664002342100234200000000540507035221637017115 0ustar andreaskDomainUsers#!/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 " Passwd Change Acknowledgment

Passwd Change Acknowledgment

" 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 "

Error: $s

"} proc successmsg {s} {puts "

$s

"} # 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." } expect5.45/example/kibitz0000774002342100234200000002520611451204656016351 0ustar andreaskDomainUsers#!/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 expect5.45/example/carpal0000664002342100234200000000143007035221636016306 0ustar andreaskDomainUsers# 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] } expect5.45/example/unbuffer.man0000664002342100234200000000434010641005275017431 0ustar andreaskDomainUsers.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 expect5.45/example/chess.exp0000774002342100234200000000260011451204656016746 0ustar andreaskDomainUsers#!/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) } } } expect5.45/example/rlogin-cwd0000774002342100234200000000076511451204656017125 0ustar andreaskDomainUsers#!/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 expect5.45/example/dislocate0000774002342100234200000001740211451204656017023 0ustar andreaskDomainUsers#!/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 } expect5.45/example/decryptdir.man0000664002342100234200000000226311413406723017771 0ustar andreaskDomainUsers.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 expect5.45/example/expectd.proto0000664002342100234200000000326611413406723017650 0ustar andreaskDomainUsers#!/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} expect5.45/example/unbuffer0000774002342100234200000000120011451204656016655 0ustar andreaskDomainUsers#!/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] } expect5.45/example/telnet-in-bg0000664002342100234200000000104407035221640017325 0ustar andreaskDomainUsers# 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 } expect5.45/example/term_expect0000774002342100234200000003456410204435523017375 0ustar andreaskDomainUsers#!/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 { focus %W } bind $term { if {"%A" != ""} { exp_send -i $term_spawn_id "\033%A" } } bind $term { exp_send -i $term_spawn_id -- %A break } bind $term {exp_send -null} bind $term {exp_send -null} bind $term {exp_send -i $term_spawn_id "\033OP"} bind $term {exp_send -i $term_spawn_id "\033OQ"} bind $term {exp_send -i $term_spawn_id "\033OR"} bind $term {exp_send -i $term_spawn_id "\033OS"} bind $term {exp_send -i $term_spawn_id "\033OT"} bind $term {exp_send -i $term_spawn_id "\033OU"} bind $term {exp_send -i $term_spawn_id "\033OV"} bind $term {exp_send -i $term_spawn_id "\033OW"} bind $term {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... expect5.45/example/cryptdir.man0000664002342100234200000000227011413406723017456 0ustar andreaskDomainUsers.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 expect5.45/example/xkibitz.man0000664002342100234200000001174611413406723017312 0ustar andreaskDomainUsers.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 expect5.45/example/vrfy0000774002342100234200000000077311413406723016042 0ustar andreaskDomainUsers#!/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"} expect5.45/example/robohunt0000774002342100234200000000416511451204656016716 0ustar andreaskDomainUsers#!/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)} } expect5.45/example/reprompt0000664002342100234200000000056007035221637016720 0ustar andreaskDomainUsers#!/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) } } expect5.45/example/passmass0000774002342100234200000001070711451204656016707 0ustar andreaskDomainUsers#!/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" } expect5.45/example/chesslib2.c0000664002342100234200000000247707035221636017157 0ustar andreaskDomainUsers/* testlib.c - test expectlib */ #include #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); } } expect5.45/example/tknewsbiff.man0000664002342100234200000003457511413406723017775 0ustar andreaskDomainUsers.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 { 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 { 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 expect5.45/example/archie0000774002342100234200000000165611436031571016310 0ustar andreaskDomainUsers#!/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} } expect5.45/example/mkpasswd0000774002342100234200000001241411451204656016703 0ustar andreaskDomainUsers#!/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" expect5.45/example/multixterm0000775002342100234200000007342711451204656017300 0ustar andreaskDomainUsers#!/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 # # 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 {xtermStart $xtermCmd $xtermCmd} # send all keypresses to xterm bind .input {xtermSend %A ; break} bind .input {xtermSend \033%A; break} bind .input {xtermSend \033%A; break} bind .input <> {xtermPaste ; break} bind .input <> {xtermPaste ; break} # arrow keys - note that if they've been rebound through .Xdefaults # you'll have to change these definitions. bind .input {xtermSend \033OA; break} bind .input {xtermSend \033OB; break} bind .input {xtermSend \033OC; break} bind .input {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 colorFocusOut bind .input 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 {focus .input; break} # ignore all other mouse events that might make selection visible bind .input break bind .input break bind .input break bind .input 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 " 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 {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 {scrollPage 1} ;#more bind $W {scrollPage -1} ;#more bind $W {scrollPage -1} ;#more bind $W {scrollPage 1} ;#emacs bind $W {scrollPage -1} ;#emacs bind $W {scrollPage 1} ;#vi bind $W {scrollPage -1} ;#vi bind $W {scrollPage 1} ;#sun bind $W {scrollPage -1} ;#sun bind $W {scrollLine 1} bind $W {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 } expect5.45/example/mkpasswd.man0000664002342100234200000000427107142602424017452 0ustar andreaskDomainUsers.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. expect5.45/example/cryptdir0000774002342100234200000000252511451204656016714 0ustar andreaskDomainUsers#!/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" expect5.45/example/gethostbyaddr0000774002342100234200000002000011451204656017703 0ustar andreaskDomainUsers#!/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]} expect5.45/example/irsh0000774002342100234200000000050511413406723016012 0ustar andreaskDomainUsers#!/depot/path/expect -- # Do rsh interactively. For example, consider the following command: # rsh 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 expect5.45/example/tkterm0000774002342100234200000003224311436031571016357 0ustar andreaskDomainUsers#!/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 { 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 { focus %W } bind $term { if {"%A" != ""} { exp_send -i $term_spawn_id "\033%A" } } bind $term { exp_send -i $term_spawn_id -- %A break } bind $term {exp_send -null} bind $term {exp_send -null} bind $term {exp_send -i $term_spawn_id "\033OP"} bind $term {exp_send -i $term_spawn_id "\033OQ"} bind $term {exp_send -i $term_spawn_id "\033OR"} bind $term {exp_send -i $term_spawn_id "\033OS"} bind $term {exp_send -i $term_spawn_id "\033OT"} bind $term {exp_send -i $term_spawn_id "\033OU"} bind $term {exp_send -i $term_spawn_id "\033OV"} bind $term {exp_send -i $term_spawn_id "\033OW"} bind $term {exp_send -i $term_spawn_id "\033OX"} expect5.45/example/multixterm.man0000664002342100234200000002243710641005274020035 0ustar andreaskDomainUsers.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 .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. expect5.45/example/getpassck0000664002342100234200000000220410641005274017023 0ustar andreaskDomainUsers#!/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 # 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." expect5.45/example/kibitz.man0000664002342100234200000001511711413406723017116 0ustar andreaskDomainUsers.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. expect5.45/example/tknewsbiff0000774002342100234200000002616511436031571017221 0ustar andreaskDomainUsers#!/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 { 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 } expect5.45/example/passwd.html0000664002342100234200000000146311413406723017313 0ustar andreaskDomainUsers Change your login password 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

Change your login password


Username:
Old password:
New password:
New password:
New password must be entered twice to avoid typos.
expect5.45/example/ftp-inband0000774002342100234200000001526111451204656017077 0ustar andreaskDomainUsers#!/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 expect5.45/example/telnet-cwd0000774002342100234200000000071211451204656017116 0ustar andreaskDomainUsers#!/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 expect5.45/example/rftp0000774002342100234200000002127011451204656016025 0ustar andreaskDomainUsers#!/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 } expect5.45/example/weather0000774002342100234200000000403311451204656016507 0ustar andreaskDomainUsers#!/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 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 expect5.45/example/dvorak0000774002342100234200000000210611451204656016335 0ustar andreaskDomainUsers#!/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} expect5.45/exp_regexp.c0000664002342100234200000007066607035221635016020 0ustar andreaskDomainUsers#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 */ expect5.45/exp_event.c0000664002342100234200000002027311412763435015637 0ustar andreaskDomainUsers/* 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 #include #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_PTYTRAP # include #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;irr++; 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;iname);*/ 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; } expect5.45/retoglob.c0000664002342100234200000004350411436035441015454 0ustar andreaskDomainUsers/* * re2glob - C implementation * (c) 2007 ActiveState Software Inc. */ #include #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 expect5.45/exp_select.c0000664002342100234200000001461511412763435016000 0ustar andreaskDomainUsers/* 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 #include #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYSSELECT_H # include /* Intel needs this for timeval */ #endif #ifdef HAVE_PTYTRAP # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef _AIX /* AIX has some unusual definition of FD_SET */ #include #endif #if !defined( FD_SET ) && defined( HAVE_SYS_BSDTYPES_H ) /* like AIX, ISC has it's own definition of FD_SET */ # include #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 #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) 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) 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 !!!! */ expect5.45/pty_sgttyb.c0000664002342100234200000001364610075564010016050 0ustar andreaskDomainUsers/* 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 /* tmp for debugging */ #include #if defined(SIGCLD) && !defined(SIGCHLD) #define SIGCHLD SIGCLD #endif #include #include /*** #include ***/ #include #include #include #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 */ } expect5.45/exp_console.c0000664002342100234200000000335211412763435016157 0ustar andreaskDomainUsers/* 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 #include #include /* Solaris needs this for console redir */ #ifdef HAVE_STRREDIR_H #include # ifdef SRIOCSREDIR # undef TIOCCONS # endif #endif #ifdef HAVE_SYS_FCNTL_H #include #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*/ } expect5.45/exp_poll.c0000664002342100234200000003316711412763435015472 0ustar andreaskDomainUsers/* 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 #include #include #ifdef HAVE_UNISTD_H # include #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; } expect5.45/exp_command.h0000664002342100234200000003233411412763435016142 0ustar andreaskDomainUsers/* 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 # ifdef WNOHANG_REQUIRES_POSIX_SOURCE # undef _POSIX_SOURCE # endif #endif #ifdef __APPLE__ /* From: "Daniel A. Steffen" */ # undef panic #endif #include #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: */ expect5.45/expect.man0000664002342100234200000023255410365771340015472 0ustar andreaskDomainUsers.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 "). 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 w o r l d 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 . 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. expect5.45/exp_memmove.c0000664002342100234200000000062411412763435016161 0ustar andreaskDomainUsers/* 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 /* 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)); expect5.45/exp_main_sub.c0000664002342100234200000006163311436032653016315 0ustar andreaskDomainUsers/* exp_main_sub.c - miscellaneous subroutines for Expect or Tk main() */ #include "expect_cf.h" #include #include #ifdef HAVE_INTTYPES_H # include #endif #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_WAIT_H #include #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 * 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 #include #include "string.h" /* according to Karl Vogel, time.h is insufficient on Pyramid */ /* following is recommended by autoconf */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #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; } expect5.45/expect_comm.h0000664002342100234200000000434307035221636016150 0ustar andreaskDomainUsers/* 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 */ expect5.45/exp_prog.h0000664002342100234200000000116610645235762015476 0ustar andreaskDomainUsers/* 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 */ expect5.45/exp_pty.c0000664002342100234200000002024411412763435015330 0ustar andreaskDomainUsers/* 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 #endif #ifdef HAVE_SYS_FCNTL_H # include #else # include #endif #include #include #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include #include "tcl.h" #include "exp_int.h" #include "expect_comm.h" #include "exp_rename.h" #include "exp_pty.h" #include #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 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; } expect5.45/exp_closetcl.c0000664002342100234200000000057711412763435016333 0ustar andreaskDomainUsers#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 */ expect5.45/expTcl.c0000664002342100234200000000000007035221632015055 0ustar andreaskDomainUsersexpect5.45/vgrindefs0000664002342100234200000000172211413406723015401 0ustar andreaskDomainUsers# vgrindefs for Expect # Author: Brian Fitzgerald # 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: expect5.45/exp_simple.c0000664002342100234200000002704411412763435016012 0ustar andreaskDomainUsers/* * 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 /* * 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 #include #include #ifdef HAVE_SYS_WAIT_H #include #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! */ expect5.45/exp_tty_in.h0000664002342100234200000000520211413406723016017 0ustar andreaskDomainUsers/* 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 . 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 # 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 # else # include # endif # include # include #endif #if defined(HAVE_TERMIOS) # undef HAVE_TERMIO # undef HAVE_SGTTYB # include # 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__ */ expect5.45/expect_tcl.h0000664002342100234200000000345311412763435016002 0ustar andreaskDomainUsers/* 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 #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 */ expect5.45/Dbg.c0000664002342100234200000010257311437245105014336 0ustar andreaskDomainUsers/* 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 #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 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(""); /* 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 ; argccallerVarPtr,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) { 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: */ expect5.45/exp_regexp.h0000664002342100234200000000034507035221635016010 0ustar andreaskDomainUsers#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 */ expect5.45/tests/0000775002342100234200000000000011466322022014624 5ustar andreaskDomainUsersexpect5.45/tests/logfile.test0000664002342100234200000000210510645234552017154 0ustar andreaskDomainUsers# 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 expect5.45/tests/cat.test0000664002342100234200000000133510645234552016306 0ustar andreaskDomainUsers# 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 expect5.45/tests/README0000664002342100234200000001137507035221641015515 0ustar andreaskDomainUsersExpect 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 ?