home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-19 | 44.5 KB | 1,443 lines |
- Newsgroups: comp.sources.misc
- From: karl@sugar.neosoft.com (Karl Lehenbauer)
- Subject: v26i022: tclx - extensions and on-line help for tcl 6.1, Part22/23
- Message-ID: <1991Nov19.135844.1688@sparky.imd.sterling.com>
- X-Md4-Signature: 7872693e9f39da42eb10b15a1d3182e3
- Date: Tue, 19 Nov 1991 13:58:44 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: karl@sugar.neosoft.com (Karl Lehenbauer)
- Posting-number: Volume 26, Issue 22
- Archive-name: tclx/part22
- Environment: UNIX
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 22 (of 23)."
- # Contents: extended/src/iocmds.c
- # Wrapped by karl@one on Wed Nov 13 21:50:33 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'extended/src/iocmds.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'extended/src/iocmds.c'\"
- else
- echo shar: Extracting \"'extended/src/iocmds.c'\" \(41928 characters\)
- sed "s/^X//" >'extended/src/iocmds.c' <<'END_OF_FILE'
- X/*
- X * iocmds.c
- X *
- X * Extended Tcl file I/O commands.
- X *---------------------------------------------------------------------------
- X * Copyright 1991 Karl Lehenbauer and Mark Diekhans.
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation for any purpose and without fee is hereby granted, provided
- X * that the above copyright notice appear in all copies. Karl Lehenbauer and
- X * Mark Diekhans make no representations about the suitability of this
- X * software for any purpose. It is provided "as is" without express or
- X * implied warranty.
- X */
- X
- X#include "tclExtdInt.h"
- X#include <math.h>
- X
- X#ifdef TCL_USE_BZERO_MACRO
- X# define bzero(to,length) memset(to,'\0',length)
- X#endif
- X
- X/*
- X * Macro to enable line buffering mode on a file.
- X */
- X#ifdef TCL_HAVE_SETLINEBUF
- X# define SET_LINE_BUF(fp) setlinebuf (fp)
- X#else
- X# define SET_LINE_BUF(fp) setvbuf (fp, NULL, _IOLBF, BUFSIZ)
- X#endif
- X
- X
- X/*
- X * Control block used to pass data used by the binary search routines.
- X */
- Xtypedef struct binSearchCB_t {
- X Tcl_Interp *interp; /* Pointer to the interpreter. */
- X char *cmdName; /* Cmd name to include in error msg. */
- X char *fileHandle; /* Handle of file. */
- X char *key; /* The key to search for. */
- X
- X FILE *fileCBPtr; /* Open file structure. */
- X dynamicBuf_t dynBuf; /* Dynamic buffer to hold a line of file. */
- X long lastRecOffset; /* Offset of last record read. */
- X int cmpResult; /* -1, 0 or 1 result of string compare. */
- X char *tclProc; /* Name of Tcl comparsion proc, or NULL. */
- X } binSearchCB_t;
- X
- X/*
- X * Prototypes of internal functions.
- X */
- Xint
- XStandardKeyCompare _ANSI_ARGS_((char *key,
- X char *line));
- X
- Xint
- XTclProcKeyCompare _ANSI_ARGS_((binSearchCB_t *searchCBPtr));
- X
- Xint
- XReadAndCompare _ANSI_ARGS_((long fileOffset,
- X binSearchCB_t *searchCBPtr));
- X
- Xint
- XBinSearch _ANSI_ARGS_((binSearchCB_t *searchCBPtr));
- X
- XFILE *
- XDoNormalDup _ANSI_ARGS_((Interp *iPtr,
- X char *tclCommand,
- X OpenFile *oldFilePtr));
- X
- XFILE *
- XDoSpecialDup _ANSI_ARGS_((Interp *iPtr,
- X char *tclCommand,
- X OpenFile *oldFilePtr,
- X char *newHandleName));
- X
- Xint
- XGetFcntlFlags _ANSI_ARGS_((Tcl_Interp *interp,
- X char *cmdName,
- X OpenFile *filePtr));
- X
- Xint
- XSetFcntlFlag _ANSI_ARGS_((Tcl_Interp *interp,
- X char *cmdName,
- X char *flagName,
- X char *valueStr,
- X OpenFile *filePtr));
- X
- Xint
- XParseSelectFileList _ANSI_ARGS_((Tcl_Interp *interp,
- X char *handleList,
- X fd_set *fileDescSetPtr,
- X int **fileDescListPtr,
- X int *maxFileIdPtr));
- X
- Xstatic char *
- XReturnSelectedFileList _ANSI_ARGS_((fd_set *fileDescSetPtr,
- X int fileDescCnt,
- X int *fileDescList));
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * StandardKeyCompare --
- X * Standard comparison routine for BinSearch, compares the key to the
- X * first white-space seperated field in the line.
- X *
- X * Parameters:
- X * o key (I) - The key to search for.
- X * o line (I) - The line to compare the key to.
- X *
- X * Results:
- X * o < 0 if key < line-key
- X * o = 0 if key == line-key
- X * o > 0 if key > line-key.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XStandardKeyCompare (key, line)
- X char *key;
- X char *line;
- X{
- X int cmpResult, fieldLen;
- X char saveChar;
- X
- X fieldLen = strcspn (line, " \t\r\n\v\f");
- X
- X saveChar = line [fieldLen];
- X line [fieldLen] = 0;
- X cmpResult = strcmp (key, line);
- X line [fieldLen] = saveChar;
- X
- X return cmpResult;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * TclProcKeyCompare --
- X * Comparison routine for BinSearch that runs a Tcl procedure to,
- X * compare the key to a line from the file.
- X *
- X * Parameters:
- X * o searchCBPtr (I/O) - The search control block, the line should be in
- X * dynBuf, the comparsion result is returned in cmpResult.
- X *
- X * Results:
- X * TCL_OK or TCL_ERROR.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XTclProcKeyCompare (searchCBPtr)
- X binSearchCB_t *searchCBPtr;
- X{
- X char *cmdArgv [3];
- X char *command;
- X int result;
- X
- X cmdArgv [0] = searchCBPtr->tclProc;
- X cmdArgv [1] = searchCBPtr->key;
- X cmdArgv [2] = searchCBPtr->dynBuf.ptr;
- X command = Tcl_Merge (3, cmdArgv);
- X
- X result = Tcl_Eval (searchCBPtr->interp, command, 0, (char **) NULL);
- X
- X ckfree (command);
- X if (result == TCL_ERROR)
- X return TCL_ERROR;
- X
- X if (!Tcl_StrToInt (searchCBPtr->interp->result, 0,
- X &searchCBPtr->cmpResult)) {
- X char *oldResult = ckalloc (strlen (searchCBPtr->interp->result + 1));
- X
- X strcpy (oldResult, searchCBPtr->interp->result);
- X Tcl_ResetResult (searchCBPtr->interp);
- X Tcl_AppendResult (searchCBPtr->interp, "invalid integer \"", oldResult,
- X "\" returned from compare proc \"",
- X searchCBPtr->tclProc, "\"", (char *) NULL);
- X ckfree (oldResult);
- X return TCL_ERROR;
- X }
- X Tcl_ResetResult (searchCBPtr->interp);
- X return TCL_OK;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * ReadAndCompare --
- X * Search for the next line in the file starting at the specified
- X * offset. Read the line into the dynamic buffer and compare it to
- X * the key using the specified comparison method. The start of the
- X * last line read is saved in the control block, and if the start of
- X * the same line is found in the search, then it will not be recompared.
- X * This is needed since the search algorithm has to hit the same line
- X * a couple of times before failing, due to the fact that the records are
- X * not fixed length.
- X *
- X * Parameters:
- X * o fileOffset (I) - The offset of the next byte of the search, not
- X * necessarly the start of a record.
- X * o searchCBPtr (I/O) - The search control block, the comparsion result
- X * is returned in cmpResult. If the EOF is hit, a less-than result is
- X * returned.
- X *
- X * Results:
- X * TCL_OK or TCL_ERROR.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XReadAndCompare (fileOffset, searchCBPtr)
- X long fileOffset;
- X binSearchCB_t *searchCBPtr;
- X{
- X int recChar, status;
- X
- X if (fseek (searchCBPtr->fileCBPtr, fileOffset, SEEK_SET) != 0)
- X goto unixError;
- X
- X /*
- X * Go to beginning of next line.
- X */
- X
- X if (fileOffset != 0) {
- X while (((recChar = getc (searchCBPtr->fileCBPtr)) != EOF) &&
- X (recChar != '\n'))
- X fileOffset++;
- X if ((recChar == EOF) && ferror (searchCBPtr->fileCBPtr))
- X goto unixError;
- X }
- X /*
- X * If this is the same line as before, then just leave the comparison
- X * result unchanged.
- X */
- X if (fileOffset == searchCBPtr->lastRecOffset)
- X return TCL_OK;
- X
- X searchCBPtr->lastRecOffset = fileOffset;
- X
- X status = Tcl_DynamicFgets (&searchCBPtr->dynBuf, searchCBPtr->fileCBPtr);
- X if (status < 0)
- X goto unixError;
- X
- X /*
- X * Only compare if EOF was not hit, otherwise, treat as if we went
- X * above the key we are looking for.
- X */
- X if (status == 0) {
- X searchCBPtr->cmpResult = -1;
- X return TCL_OK;
- X }
- X
- X if (searchCBPtr->tclProc == NULL) {
- X searchCBPtr->cmpResult = StandardKeyCompare (searchCBPtr->key,
- X searchCBPtr->dynBuf.ptr);
- X } else {
- X if (TclProcKeyCompare (searchCBPtr) != TCL_OK)
- X return TCL_ERROR;
- X }
- X
- X return TCL_OK;
- X
- XunixError:
- X Tcl_AppendResult (searchCBPtr->interp, searchCBPtr->cmdName,
- X ": ", searchCBPtr->fileHandle, ": ",
- X Tcl_UnixError (searchCBPtr->interp), (char *) NULL);
- X return TCL_ERROR;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * BinSearch --
- X * Binary search a sorted ASCII file.
- X *
- X * Parameters:
- X * o searchCBPtr (I/O) - The search control block, if the line is found,
- X * it is returned in dynBuf.
- X * Results:
- X * TCL_OK - If the key was found.
- X * TCL_BREAK - If it was not found.
- X * TCL_ERROR - If there was an error.
- X *
- X * based on getpath.c from smail 2.5 (9/15/87)
- X *
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XBinSearch (searchCBPtr)
- X binSearchCB_t *searchCBPtr;
- X{
- X OpenFile *filePtr;
- X long middle, high, low;
- X struct stat statBuf;
- X
- X if (TclGetOpenFile (searchCBPtr->interp, searchCBPtr->fileHandle,
- X &filePtr) != TCL_OK)
- X goto unixError;
- X
- X searchCBPtr->fileCBPtr = filePtr->f;
- X searchCBPtr->lastRecOffset = -1;
- X
- X if (fstat (fileno (searchCBPtr->fileCBPtr), &statBuf) < 0)
- X goto unixError;
- X
- X low = 0;
- X high = statBuf.st_size;
- X
- X /*
- X * "Binary search routines are never written right the first time around."
- X * - Robert G. Sheldon.
- X */
- X
- X while (TRUE) {
- X middle = (high + low + 1) / 2;
- X
- X if (ReadAndCompare (middle, searchCBPtr) != TCL_OK)
- X return TCL_ERROR;
- X
- X if (searchCBPtr->cmpResult == 0)
- X return TCL_OK; /* Found */
- X
- X if (low >= middle)
- X return TCL_BREAK; /* Failure */
- X
- X /*
- X * Close window.
- X */
- X if (searchCBPtr->cmpResult > 0) {
- X low = middle;
- X } else {
- X high = middle - 1;
- X }
- X }
- X
- XunixError:
- X Tcl_AppendResult (searchCBPtr->interp, searchCBPtr->cmdName,
- X ": ", searchCBPtr->fileHandle, ": ",
- X Tcl_UnixError (searchCBPtr->interp), (char *) NULL);
- X return TCL_ERROR;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_BsearchCmd --
- X * Implements the TCL bsearch command:
- X * bsearch filehandle key [retvar]
- X *
- X * Results:
- X * Standard TCL results.
- X *
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_BsearchCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X int status;
- X binSearchCB_t searchCB;
- X
- X if ((argc < 3) || (argc > 5)) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv [0],
- X " handle key [retvar] [compare_proc]"
- X , (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X searchCB.interp = interp;
- X searchCB.cmdName = argv [0];
- X searchCB.fileHandle = argv [1];
- X searchCB.key = argv [2];
- X searchCB.tclProc = (argc == 5) ? argv [4] : NULL;
- X Tcl_DynBufInit (&searchCB.dynBuf);
- X
- X status = BinSearch (&searchCB);
- X if (status == TCL_ERROR) {
- X Tcl_DynBufFree (&searchCB.dynBuf);
- X return TCL_ERROR;
- X }
- X
- X if (status == TCL_BREAK) {
- X Tcl_DynBufFree (&searchCB.dynBuf);
- X if ((argc >= 4) && (argv [3][0] != '\0'))
- X interp->result = "0";
- X return TCL_OK;
- X }
- X
- X if ((argc == 3) || (argv [3][0] == '\0')) {
- X Tcl_DynBufReturn (interp, &searchCB.dynBuf);
- X } else {
- X char *varPtr;
- X
- X varPtr = Tcl_SetVar (interp, argv[3], searchCB.dynBuf.ptr,
- X TCL_LEAVE_ERR_MSG);
- X Tcl_DynBufFree (&searchCB.dynBuf);
- X if (varPtr == NULL)
- X return TCL_ERROR;
- X interp->result = "1";
- X }
- X return TCL_OK;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * DoNormalDup --
- X * Process a normal dup command (i.e. the new file is not specified).
- X *
- X * Parameters:
- X * o iPtr (I) - If an error occures, the error message is in result,
- X * otherwise the file handle is in result.
- X * o tclCommand (I) - The command name (argv [0]), for error reporting.
- X * o oldFilePtr (I) - Tcl file control block for the file to dup.
- X * Returns:
- X * A pointer to the FILE structure for the new file, or NULL if an
- X * error occured.
- X *----------------------------------------------------------------------
- X */
- Xstatic FILE *
- XDoNormalDup (iPtr, tclCommand, oldFilePtr)
- X Interp *iPtr;
- X char *tclCommand;
- X OpenFile *oldFilePtr;
- X{
- X int newFileId;
- X FILE *newFileCbPtr;
- X char *mode;
- X
- X newFileId = dup (fileno (oldFilePtr->f));
- X if (newFileId < 0)
- X goto unixError;
- X
- X TclMakeFileTable (iPtr, newFileId);
- X if (iPtr->filePtrArray [newFileId] != NULL) {
- X panic ("Tcl_OpenCmd found file already open");
- X }
- X /*
- X * Set up a stdio FILE control block for the new file.
- X */
- X if (oldFilePtr->readable && oldFilePtr->writable) {
- X mode = "r+";
- X } else if (oldFilePtr->writable) {
- X mode = "w";
- X } else {
- X mode = "r";
- X }
- X if ((newFileCbPtr = fdopen (newFileId, mode)) == NULL)
- X goto unixError;
- X
- X sprintf (iPtr->result, "file%d", newFileId);
- X return newFileCbPtr;
- X
- XunixError:
- X Tcl_AppendResult ((Tcl_Interp *) iPtr, tclCommand, ": ",
- X Tcl_UnixError ((Tcl_Interp *) iPtr), (char *) NULL);
- X return NULL;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * DoSpecialDup --
- X * Process a special dup command. This is the case were the file is
- X * dup-ed to stdin, stdout or stderr. The new file may or be open or
- X * closed
- X * Parameters:
- X * o iPtr (I) - If an error occures, the error message is in result,
- X * otherwise nothing is returned.
- X * o tclCommand (I) - The command name (argv [0]), for error reporting.
- X * o oldFilePtr (I) - Tcl file control block for the file to dup.
- X * o newFileHandle (I) - The handle name for the new file.
- X * Returns:
- X * A pointer to the FILE structure for the new file, or NULL if an
- X * error occured.
- X *----------------------------------------------------------------------
- X */
- Xstatic FILE *
- XDoSpecialDup (iPtr, tclCommand, oldFilePtr, newHandleName)
- X Interp *iPtr;
- X char *tclCommand;
- X OpenFile *oldFilePtr;
- X char *newHandleName;
- X{
- X int newFileId;
- X FILE *newFileCbPtr;
- X
- X /*
- X * Duplicate the old file to the specified file id.
- X */
- X newFileId = Tcl_ConvertFileHandle ((Tcl_Interp *) iPtr, newHandleName);
- X if (newFileId < 0)
- X return NULL;
- X if (newFileId > 2) {
- X Tcl_AppendResult (iPtr, "target handle must be one of stdin, ",
- X "stdout, stderr, file0, file1, or file2: got \"",
- X newHandleName, "\"", (char *) NULL);
- X return NULL;
- X }
- X switch (newFileId) {
- X case 0:
- X newFileCbPtr = stdin;
- X break;
- X case 1:
- X newFileCbPtr = stdout;
- X break;
- X case 2:
- X newFileCbPtr = stderr;
- X break;
- X }
- X
- X /*
- X * If the specified id is not open, set up a stdio file descriptor.
- X */
- X TclMakeFileTable (iPtr, newFileId);
- X if (iPtr->filePtrArray [newFileId] == NULL) {
- X char *mode;
- X
- X /*
- X * Set up a stdio FILE control block for the new file.
- X */
- X if (oldFilePtr->readable && oldFilePtr->writable) {
- X mode = "r+";
- X } else if (oldFilePtr->writable) {
- X mode = "w";
- X } else {
- X mode = "r";
- X }
- X if (freopen ("/dev/null", mode, newFileCbPtr) == NULL)
- X goto unixError;
- X }
- X
- X /*
- X * This functionallity may be obtained with dup2 on most systems. Being
- X * open is optional.
- X */
- X close (newFileId);
- X if (fcntl (fileno (oldFilePtr->f), F_DUPFD, newFileId) < 0)
- X goto unixError;
- X
- X return newFileCbPtr;
- X
- XunixError:
- X Tcl_AppendResult ((Tcl_Interp *) iPtr, tclCommand, ": ",
- X Tcl_UnixError ((Tcl_Interp *) iPtr), (char *) NULL);
- X return NULL;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_DupCmd --
- X * Implements the dup TCL command:
- X * dup filehandle [stdhandle]
- X *
- X * Results:
- X * Returns TCL_OK and interp->result containing a filehandle
- X * if the requested file or pipe was successfully duplicated.
- X *
- X * Return TCL_ERROR and interp->result containing an
- X * explanation of what went wrong if an error occured.
- X *
- X * Side effects:
- X * Locates and creates an entry in the handles table
- X *
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_DupCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X Interp *iPtr = (Interp *) interp;
- X OpenFile *oldFilePtr;
- X FILE *newFileCbPtr;
- X OpenFile *newFilePtr;
- X long seekOffset = -1;
- X
- X if ((argc < 2) || (argc > 3)) {
- X Tcl_AppendResult (interp, "wrong # arg: ", argv[0],
- X " filehandle [stdhandle]", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X if (TclGetOpenFile(interp, argv[1], &oldFilePtr) != TCL_OK)
- X return TCL_ERROR;
- X if (oldFilePtr->numPids > 0) { /*??????*/
- X Tcl_AppendResult (interp, "can not `dup' a pipeline", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X /*
- X * If writable, flush out the buffer. If readable, remember were we are
- X * so the we can set it up for the next stdio read to come from the same
- X * place. The location is only recorded if the file is a reqular file,
- X * since you cann't seek on other types of files.
- X */
- X if (oldFilePtr->writable) {
- X if (fflush (oldFilePtr->f) != 0)
- X goto unixError;
- X }
- X if (oldFilePtr->readable) {
- X struct stat statBuf;
- X
- X if (fstat (fileno (oldFilePtr->f), &statBuf) < 0)
- X goto unixError;
- X if ((statBuf.st_mode & S_IFMT) == S_IFREG) {
- X seekOffset = ftell (oldFilePtr->f);
- X if (seekOffset < 0)
- X goto unixError;
- X }
- X }
- X /*
- X * Process the dup depending on if dup-ing to a new file or a target
- X * file handle.
- X */
- X if (argc == 2)
- X newFileCbPtr = DoNormalDup (iPtr, argv [0], oldFilePtr);
- X else
- X newFileCbPtr = DoSpecialDup (iPtr, argv [0], oldFilePtr, argv [2]);
- X
- X if (newFileCbPtr == NULL)
- X return TCL_ERROR;
- X
- X /*
- X * Set up a Tcl OpenFile structure for the new file handle.
- X */
- X newFilePtr = iPtr->filePtrArray [fileno (newFileCbPtr)];
- X if (newFilePtr == NULL) {
- X newFilePtr = (OpenFile*) ckalloc (sizeof (OpenFile));
- X iPtr->filePtrArray [fileno (newFileCbPtr)] = newFilePtr;
- X }
- X newFilePtr->f = newFileCbPtr;
- X newFilePtr->f2 = NULL;
- X newFilePtr->readable = oldFilePtr->readable;
- X newFilePtr->writable = oldFilePtr->writable;
- X newFilePtr->numPids = 0;
- X newFilePtr->pidPtr = NULL;
- X newFilePtr->errorId = -1;
- X
- X if (seekOffset >= 0) {
- X if (fseek (newFilePtr->f, seekOffset, SEEK_SET) != 0)
- X goto unixError;
- X }
- X return TCL_OK;
- X
- XunixError:
- X Tcl_AppendResult (interp, argv [0], ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_PipeCmd --
- X * Implements the pipe TCL command:
- X * pipe [handle_var_r handle_var_w]
- X *
- X * Results:
- X * Standard TCL result.
- X *
- X * Side effects:
- X * Locates and creates entries in the handles table
- X *
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_PipeCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X Interp *iPtr = (Interp *) interp;
- X FILE *file0CbPtr, *file1CbPtr;
- X OpenFile *file0Ptr, *file1Ptr;
- X int fileIds [2];
- X char fHandle [12];
- X
- X if (!((argc == 1) || (argc == 3))) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv[0],
- X " [handle_var_r handle_var_w]", (char*) NULL);
- X }
- X
- X if (pipe (fileIds) < 0)
- X goto unixError;
- X
- X if (((file0CbPtr = fdopen (fileIds[0], "r")) == NULL) ||
- X ((file1CbPtr = fdopen (fileIds[1], "w")) == NULL)) {
- X close (fileIds [0]);
- X close (fileIds [1]);
- X goto unixError;
- X }
- X
- X TclMakeFileTable (iPtr,
- X (fileIds [0] > fileIds [1]) ? fileIds [0] : fileIds [1]);
- X file0Ptr = (OpenFile*) ckalloc (sizeof (OpenFile));
- X file0Ptr->f = file0CbPtr;
- X file0Ptr->f2 = NULL;
- X file0Ptr->readable = TRUE;
- X file0Ptr->writable = FALSE;
- X file0Ptr->numPids = 0;
- X file0Ptr->pidPtr = NULL;
- X file0Ptr->errorId = -1;
- X iPtr->filePtrArray[fileIds [0]] = file0Ptr;
- X
- X file1Ptr = (OpenFile*) ckalloc (sizeof (OpenFile));
- X file1Ptr->f = file1CbPtr;
- X file1Ptr->f2 = NULL;
- X file1Ptr->readable = FALSE;
- X file1Ptr->writable = TRUE;
- X file1Ptr->numPids = 0;
- X file1Ptr->pidPtr = NULL;
- X file1Ptr->errorId = -1;
- X iPtr->filePtrArray[fileIds [1]] = file1Ptr;
- X
- X
- X if (argc == 1)
- X sprintf (interp->result, "file%d file%d", fileIds [0], fileIds [1]);
- X else {
- X sprintf (fHandle, "file%d", fileIds [0]);
- X if (Tcl_SetVar (interp, argv[1], fHandle, TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (fHandle, "file%d", fileIds [1]);
- X if (Tcl_SetVar (interp, argv[2], fHandle, TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X }
- X
- X return TCL_OK;
- X
- XunixError:
- X Tcl_AppendResult (interp, argv [0], ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_CopyfileCmd --
- X * Implements the copyfile TCL command:
- X * copyfile handle1 handle2 [lines]
- X *
- X * Results:
- X * Nothing if it worked, else an error.
- X *
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_CopyfileCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X OpenFile *fromFilePtr, *toFilePtr;
- X char transferBuffer [2048];
- X int bytesRead;
- X
- X if (argc != 3) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv [0],
- X " fromfilehandle tofilehandle", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X if (TclGetOpenFile (interp, argv[1], &fromFilePtr) != TCL_OK)
- X return TCL_ERROR;
- X if (TclGetOpenFile (interp, argv[2], &toFilePtr) != TCL_OK)
- X return TCL_ERROR;
- X
- X if (!fromFilePtr->readable) {
- X interp->result = "Source file is not open for read access";
- X return TCL_ERROR;
- X }
- X if (!toFilePtr->writable) {
- X interp->result = "Target file is not open for write access";
- X return TCL_ERROR;
- X }
- X
- X while (TRUE) {
- X bytesRead = fread (transferBuffer, sizeof (char),
- X sizeof (transferBuffer), fromFilePtr->f);
- X if (bytesRead <= 0) {
- X if (feof (fromFilePtr->f))
- X break;
- X else
- X goto unixError;
- X }
- X if (fwrite (transferBuffer, sizeof (char), bytesRead, toFilePtr->f) !=
- X bytesRead)
- X goto unixError;
- X }
- X
- X return TCL_OK;
- X
- XunixError:
- X Tcl_AppendResult (interp, argv [0], ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_FstatCmd --
- X * Implements the fstat TCL command:
- X * fstat handle [arrayvar]
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_FstatCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X OpenFile *filePtr;
- X struct stat statBuf;
- X
- X if ((argc < 2) || (argc > 3)) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv [0],
- X " handle [arrayVar]", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X if (TclGetOpenFile (interp, argv[1], &filePtr) != TCL_OK)
- X return TCL_ERROR;
- X
- X if (fstat (fileno (filePtr->f), &statBuf)) {
- X Tcl_AppendResult (interp, argv [0], ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X }
- X /*
- X * Either return the arguments in an array or a list of keyword & value
- X * elements.
- X */
- X if (argc == 2) {
- X char statList [160];
- X
- X sprintf (statList,
- X "{atime %d} {ctime %d} {dev %d} {gid %d} {ino %d} ",
- X statBuf.st_atime, statBuf.st_ctime, statBuf.st_dev,
- X statBuf.st_gid, statBuf.st_ino);
- X Tcl_AppendResult (interp, statList, (char *) NULL);
- X
- X sprintf (statList,
- X "{mode %d} {mtime %d} {nlink %d} {size %d} {uid %d}",
- X statBuf.st_mode, statBuf.st_mtime, statBuf.st_nlink,
- X statBuf.st_size, statBuf.st_uid);
- X Tcl_AppendResult (interp, statList, (char *) NULL);
- X
- X } else {
- X char numBuf [30];
- X
- X sprintf (numBuf, "%d", statBuf.st_dev);
- X if (Tcl_SetVar2 (interp, argv[2], "dev", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_ino);
- X if (Tcl_SetVar2 (interp, argv[2], "ino", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_mode);
- X if (Tcl_SetVar2 (interp, argv[2], "mode", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_nlink);
- X if (Tcl_SetVar2 (interp, argv[2], "nlink", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_uid);
- X if (Tcl_SetVar2 (interp, argv[2], "uid", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_gid);
- X if (Tcl_SetVar2 (interp, argv[2], "gid", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_size);
- X if (Tcl_SetVar2 (interp, argv[2], "size", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_atime);
- X if (Tcl_SetVar2 (interp, argv[2], "atime", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_mtime);
- X if (Tcl_SetVar2 (interp, argv[2], "mtime", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X sprintf (numBuf, "%d", statBuf.st_ctime);
- X if (Tcl_SetVar2 (interp, argv[2], "ctime", numBuf,
- X TCL_LEAVE_ERR_MSG) == NULL)
- X return TCL_ERROR;
- X
- X }
- X return TCL_OK;
- X
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * GetFcntlFlags --
- X * Return the fcntl values as a symbolic list in the result.
- X * Result:
- X * Returns TCL_OK if all is well, TCL_ERROR if fcntl returns an error.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XGetFcntlFlags (interp, cmdName, filePtr)
- X Tcl_Interp *interp;
- X char *cmdName;
- X OpenFile *filePtr;
- X{
- X int flags;
- X int listArgc = 0;
- X char *listArgv [9];
- X
- X flags = fcntl (fileno (filePtr->f), F_GETFL, 0);
- X if (flags == -1)
- X goto unixError;
- X
- X if (flags & O_RDONLY)
- X listArgv [listArgc++] = "RDONLY";
- X if (flags & O_WRONLY)
- X listArgv [listArgc++] = "WRONLY";
- X if (flags & O_RDWR)
- X listArgv [listArgc++] = "RDWR";
- X if (flags & O_NDELAY)
- X listArgv [listArgc++] = "NDELAY";
- X if (flags & O_APPEND)
- X listArgv [listArgc++] = "APPEND";
- X
- X flags = fcntl (fileno (filePtr->f), F_GETFD, 0);
- X if (flags == -1)
- X goto unixError;
- X if (flags & 1)
- X listArgv [listArgc++] = "CLEXEC";
- X
- X /*
- X * Poke the stdio FILE structure to see if its buffered.
- X */
- X
- X#ifdef _IONBF
- X if (filePtr->f->_flag & _IONBF)
- X listArgv [listArgc++] = "NOBUF";
- X if (filePtr->f->_flag & _IOLBF)
- X listArgv [listArgc++] = "LINEBUF";
- X#else
- X if (filePtr->f->_flags & _SNBF)
- X listArgv [listArgc++] = "NOBUF";
- X if (filePtr->f->_flags & _SLBF)
- X listArgv [listArgc++] = "LINEBUF";
- X#endif
- X
- X Tcl_SetResult (interp, Tcl_Merge (listArgc, listArgv), TCL_DYNAMIC);
- X return TCL_OK;
- X
- XunixError:
- X Tcl_AppendResult (interp, cmdName, ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * SetFcntlFlag --
- X * Set the specified fcntl flag to the given boolean value.
- X * Result:
- X * Returns TCL_OK if all is well, TCL_ERROR if there is an error.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XSetFcntlFlag (interp, cmdName, flagName, valueStr, filePtr)
- X Tcl_Interp *interp;
- X char *cmdName;
- X char *flagName;
- X char *valueStr;
- X OpenFile *filePtr;
- X{
- X#define MAX_FLAG_NAME_LEN 12
- X#define CLEXEC_FLAG 1
- X#define NOBUF_FLAG 2
- X#define LINEBUF_FLAG 4
- X
- X int setFlag = 0, otherFlag = 0, setValue;
- X char flagNameUp [MAX_FLAG_NAME_LEN + 1];
- X
- X
- X if (Tcl_GetBoolean (interp, valueStr, &setValue) != TCL_OK)
- X return TCL_ERROR;
- X
- X if (strlen (flagName) > MAX_FLAG_NAME_LEN)
- X goto invalidFlagName;
- X Tcl_UpShift (flagNameUp, flagName);
- X
- X if (STREQU (flagNameUp, "NDELAY"))
- X setFlag = O_NDELAY;
- X else if (STREQU (flagNameUp, "APPEND"))
- X setFlag = O_APPEND;
- X else if (STREQU (flagNameUp, "CLEXEC"))
- X otherFlag = CLEXEC_FLAG;
- X else if (STREQU (flagNameUp, "NOBUF"))
- X otherFlag = NOBUF_FLAG;
- X else if (STREQU (flagNameUp, "LINEBUF"))
- X otherFlag = LINEBUF_FLAG;
- X else {
- X Tcl_AppendResult (interp, "unknown attribute name \"", flagName,
- X "\", expected one of: APPEND, CLEXEC, NDELAY, ",
- X "NOBUF, LINEBUF", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X if (otherFlag == CLEXEC_FLAG) {
- X if (fcntl (fileno (filePtr->f), F_SETFD, setValue) == -1)
- X goto unixError;
- X } else if (otherFlag != 0) {
- X if (setValue != 1) {
- X Tcl_AppendResult (interp, flagNameUp, " flag may not be cleared",
- X (char *) NULL);
- X return TCL_ERROR;
- X }
- X if (otherFlag == NOBUF_FLAG)
- X setbuf (filePtr->f, NULL);
- X else
- X SET_LINE_BUF (filePtr->f);
- X } else {
- X int flags;
- X
- X flags = fcntl (fileno (filePtr->f), F_GETFL, 0);
- X if (flags == -1)
- X goto unixError;
- X flags = flags & ~setFlag;
- X if (setValue)
- X flags = flags | setFlag;
- X if (fcntl (fileno (filePtr->f), F_SETFL, flags) == -1)
- X goto unixError;
- X }
- X return TCL_OK;
- X
- XinvalidFlagName:
- X Tcl_AppendResult (interp, cmdName, ": invalid flag name \"", flagName,
- X "\", expected one of: NDELAY, APPEND, CLEXEC",
- X (char *) NULL);
- X return TCL_ERROR;
- XunixError:
- X Tcl_AppendResult (interp, cmdName, ": ", Tcl_UnixError (interp),
- X (char *) NULL);
- X return TCL_ERROR;
- X
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_FcntlCmd --
- X * Implements the fcntl TCL command:
- X * fcntl handle [attribute value]
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_FcntlCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X OpenFile *filePtr;
- X
- X if (!((argc == 2) || (argc == 4))) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv [0],
- X " handle [attribute value]", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X if (TclGetOpenFile (interp, argv[1], &filePtr) != TCL_OK)
- X return TCL_ERROR;
- X if (argc == 2) {
- X if (GetFcntlFlags (interp, argv [0], filePtr) != TCL_OK)
- X return TCL_ERROR;
- X } else {
- X if (SetFcntlFlag (interp, argv [0], argv [2], argv [3],
- X filePtr) != TCL_OK)
- X return TCL_ERROR;
- X }
- X return TCL_OK;
- X}
- X#ifndef TCL_NO_SELECT
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * ParseSelectFileList --
- X *
- X * Parse a list of file handles for select.
- X *
- X * Parameters:
- X * o interp (O) - Error messages are returned in the result.
- X * o handleList (I) - The list of file handles to parse, may be empty.
- X * o fileDescSetPtr (O) - The select fd_set for the parsed handles is
- X * filled in. Should be cleared before this procedure is called.
- X * o fileDescListPtr (O) - A pointer to a dynamically allocated list of
- X * the integer file ids that are in the set. If the list is empty,
- X * NULL is returned.
- X * o maxFileIdPtr (I/O) - If a file id greater than the current value is
- X * encountered, it will be set to that file id.
- X * Returns:
- X * The number of files in the list, or -1 if an error occured.
- X *----------------------------------------------------------------------
- X */
- Xstatic int
- XParseSelectFileList (interp, handleList, fileDescSetPtr, fileDescListPtr,
- X maxFileIdPtr)
- X Tcl_Interp *interp;
- X char *handleList;
- X fd_set *fileDescSetPtr;
- X int **fileDescListPtr;
- X int *maxFileIdPtr;
- X{
- X int handleCnt, idx;
- X char **handleArgv;
- X int *fileDescList;
- X
- X if (Tcl_SplitList (interp, handleList, &handleCnt, &handleArgv) != TCL_OK)
- X return -1;
- X
- X /*
- X * Handle case of an empty list.
- X */
- X if (handleCnt == 0) {
- X *fileDescListPtr = NULL;
- X ckfree ((char *) handleArgv);
- X return 0;
- X }
- X
- X fileDescList = (int *) ckalloc (sizeof (int) * handleCnt);
- X
- X for (idx = 0; idx < handleCnt; idx++) {
- X OpenFile *filePtr;
- X int fileId;
- X
- X if (TclGetOpenFile (interp, handleArgv [idx], &filePtr) != TCL_OK) {
- X ckfree ((char *) handleArgv);
- X ckfree ((char *) fileDescList);
- X return -1;
- X }
- X fileId = fileno (filePtr->f);
- X fileDescList [idx] = fileId;
- X
- X FD_SET (fileId, fileDescSetPtr);
- X if (fileId > *maxFileIdPtr)
- X *maxFileIdPtr = fileId;
- X }
- X
- X *fileDescListPtr = fileDescList;
- X ckfree ((char *) handleArgv);
- X return handleCnt;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * ReturnSelectedFileList --
- X *
- X * Take the resulting file descriptor sets from a select, and the
- X * list of file descritpors and build up a list of Tcl file handles.
- X *
- X * Parameters:
- X * o fileDescSetPtr (I) - The select fd_set.
- X * o fileDescCnt (I) - Number of descriptors in the list.
- X * o fileDescListPtr (I) - A pointer to a list of the integer file
- X * ids that are in the set. If the list is empty,
- X * NULL is returned.
- X * Returns:
- X * A dynamicly allocated list of file handles. If the handles are empty,
- X * it still returns a NULL list to make clean up easy.
- X *----------------------------------------------------------------------
- X */
- Xstatic char *
- XReturnSelectedFileList (fileDescSetPtr, fileDescCnt, fileDescList)
- X fd_set *fileDescSetPtr;
- X int fileDescCnt;
- X int *fileDescList;
- X{
- X int idx, handleCnt;
- X char *fileHandleList;
- X char **fileHandleArgv;
- X
- X /*
- X * Special case the empty list.
- X */
- X if (fileDescCnt == 0) {
- X fileHandleList = ckalloc (1);
- X fileHandleList [0] = '\0';
- X return fileHandleList;
- X }
- X
- X handleCnt = 0;
- X fileHandleArgv = (char **) ckalloc (sizeof (char *) * fileDescCnt);
- X
- X for (idx = 0; idx < fileDescCnt; idx++) {
- X if (FD_ISSET (fileDescList [idx], fileDescSetPtr)) {
- X fileHandleArgv [handleCnt] = ckalloc (8); /* fileNNN */
- X sprintf (fileHandleArgv [handleCnt], "file%d", fileDescList [idx]);
- X handleCnt++;
- X }
- X }
- X
- X fileHandleList = Tcl_Merge (handleCnt, fileHandleArgv);
- X for (idx = 0; idx < handleCnt; idx++)
- X ckfree ((char *) fileHandleArgv [idx]);
- X ckfree ((char *) fileHandleArgv);
- X
- X return fileHandleList;
- X}
- X
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_SelectCmd --
- X * Implements the select TCL command:
- X * select readhandles [writehandles] [excepthandles] [timeout]
- X *
- X * Results:
- X * A list in the form:
- X * {readhandles writehandles excepthandles}
- X * or {} it the timeout expired.
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_SelectCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X
- X fd_set readFdSet, writeFdSet, exceptFdSet;
- X int readDescCnt = 0, writeDescCnt = 0, exceptDescCnt = 0;
- X int *readDescList = NULL, *writeDescList = NULL, *exceptDescList = NULL;
- X char *retListArgv [3];
- X
- X int numSelected, maxFileId = 0;
- X int result = TCL_ERROR;
- X struct timeval timeoutRec;
- X struct timeval *timeoutRecPtr;
- X
- X
- X if (argc < 2) {
- X Tcl_AppendResult (interp, "wrong # args: ", argv [0],
- X " readhandles [writehandles] [excepthandles]",
- X " [timeout]", (char *) NULL);
- X return TCL_ERROR;
- X }
- X
- X /*
- X * Parse the file handles and set everything up for the select call.
- X */
- X FD_ZERO (&readFdSet);
- X FD_ZERO (&writeFdSet);
- X FD_ZERO (&exceptFdSet);
- X readDescCnt = ParseSelectFileList (interp, argv [1], &readFdSet,
- X &readDescList, &maxFileId);
- X if (readDescCnt < 0)
- X goto exitPoint;
- X if (argc > 2) {
- X writeDescCnt = ParseSelectFileList (interp, argv [2], &writeFdSet,
- X &writeDescList, &maxFileId);
- X if (writeDescCnt < 0)
- X goto exitPoint;
- X }
- X if (argc > 3) {
- X exceptDescCnt = ParseSelectFileList (interp, argv [3], &exceptFdSet,
- X &exceptDescList, &maxFileId);
- X if (exceptDescCnt < 0)
- X goto exitPoint;
- X }
- X
- X /*
- X * Get the time out. Zero is different that not specified.
- X */
- X timeoutRecPtr = NULL;
- X if ((argc > 4) && (argv [4][0] != '\0')) {
- X double timeout, seconds, microseconds;
- X
- X if (Tcl_GetDouble (interp, argv [4], &timeout) != TCL_OK)
- X goto exitPoint;
- X if (timeout < 0) {
- X Tcl_AppendResult (interp, "timeout must be greater than or equal",
- X " to zero", (char *) NULL);
- X goto exitPoint;
- X }
- X seconds = floor (timeout);
- X microseconds = (timeout - seconds) * 1000000.0;
- X timeoutRec.tv_sec = seconds;
- X timeoutRec.tv_usec = microseconds;
- X timeoutRecPtr = &timeoutRec;
- X }
- X
- X /*
- X * All set, do the select.
- X */
- X numSelected = select (maxFileId + 1, &readFdSet, &writeFdSet, &exceptFdSet,
- X timeoutRecPtr);
- X if (numSelected < 0) {
- X Tcl_AppendResult (interp, argv [0], ": system call error:",
- X Tcl_UnixError (interp), (char *) NULL);
- X goto exitPoint;
- X }
- X
- X /*
- X * Return the result, either a 3 element list, or leave the result
- X * empty if the timeout occured.
- X */
- X if (numSelected > 0) {
- X retListArgv [0] = ReturnSelectedFileList (&readFdSet, readDescCnt,
- X readDescList);
- X retListArgv [1] = ReturnSelectedFileList (&writeFdSet, writeDescCnt,
- X writeDescList);
- X retListArgv [2] = ReturnSelectedFileList (&exceptFdSet, exceptDescCnt,
- X exceptDescList);
- X Tcl_SetResult (interp, Tcl_Merge (3, retListArgv), TCL_DYNAMIC);
- X ckfree ((char *) retListArgv [0]);
- X ckfree ((char *) retListArgv [1]);
- X ckfree ((char *) retListArgv [2]);
- X }
- X
- X result = TCL_OK;
- X
- XexitPoint:
- X if (readDescList != NULL)
- X ckfree ((char *) readDescList);
- X if (writeDescList != NULL)
- X ckfree ((char *) writeDescList);
- X if (exceptDescList != NULL)
- X ckfree ((char *) exceptDescList);
- X return result;
- X
- XunixError:
- X return TCL_ERROR;
- X}
- X#else
- X/*
- X *----------------------------------------------------------------------
- X *
- X * Tcl_SelectCmd --
- X * Dummy select command that returns an error for systems that don't
- X * have select.
- X *----------------------------------------------------------------------
- X */
- Xint
- XTcl_SelectCmd (clientData, interp, argc, argv)
- X ClientData clientData;
- X Tcl_Interp *interp;
- X int argc;
- X char **argv;
- X{
- X Tcl_AppendResult (interp,
- X "select is not available on this version of Unix",
- X (char *) NULL);
- X return TCL_ERROR;
- X}
- X#endif
- END_OF_FILE
- if test 41928 -ne `wc -c <'extended/src/iocmds.c'`; then
- echo shar: \"'extended/src/iocmds.c'\" unpacked with wrong size!
- fi
- # end of 'extended/src/iocmds.c'
- fi
- echo shar: End of archive 22 \(of 23\).
- cp /dev/null ark22isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 23 archives.
- echo "Now cd to "extended", edit the makefile, then do a "make""
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-