📄 tclunixchan.c
字号:
/* * tclUnixChan.c * * Common channel driver for Unix channels based on files, command * pipes and TCP sockets. * * 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: @(#) tclUnixChan.c 1.207 97/11/04 14:45:29 */#include "tclInt.h" /* Internal definitions for Tcl. */#include "tclPort.h" /* Portability features for Tcl. *//* * sys/ioctl.h has already been included by tclPort.h. Including termios.h * or termio.h causes a bunch of warning messages because some duplicate * (but not contradictory) #defines exist in termios.h and/or termio.h */#undef NL0#undef NL1#undef CR0#undef CR1#undef CR2#undef CR3#undef TAB0#undef TAB1#undef TAB2#undef XTABS#undef BS0#undef BS1#undef FF0#undef FF1#undef ECHO#undef NOFLSH#undef TOSTOP#undef FLUSHO#undef PENDIN#ifdef USE_TERMIOS# include <termios.h>#else /* !USE_TERMIOS */#ifdef USE_TERMIO# include <termio.h>#else /* !USE_TERMIO */#ifdef USE_SGTTY# include <sgtty.h>#endif /* USE_SGTTY */#endif /* !USE_TERMIO */#endif /* !USE_TERMIOS *//* * The following structure is used to set or get the serial port * attributes in a platform-independant manner. */ typedef struct TtyAttrs { int baud; int parity; int data; int stop;} TtyAttrs;/* * This structure describes per-instance state of a file based channel. */typedef struct FileState { Tcl_Channel channel; /* Channel associated with this file. */ int fd; /* File handle. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ struct FileState *nextPtr; /* Pointer to next file in list of all * file channels. */} FileState;/* * List of all file channels currently open. */static FileState *firstFilePtr = NULL;/* * This structure describes per-instance state of a tcp based channel. */typedef struct TcpState { Tcl_Channel channel; /* Channel associated with this file. */ int fd; /* The socket itself. */ int flags; /* ORed combination of the bitfields * defined below. */ Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */ ClientData acceptProcData; /* The data for the accept proc. */} TcpState;/* * These bits may be ORed together into the "flags" field of a TcpState * structure. */#define TCP_ASYNC_SOCKET (1<<0) /* Asynchronous socket. */#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. *//* * The following defines the maximum length of the listen queue. This is * the number of outstanding yet-to-be-serviced requests for a connection * on a server socket, more than this number of outstanding requests and * the connection request will fail. */#ifndef SOMAXCONN#define SOMAXCONN 100#endif#if (SOMAXCONN < 100)#undef SOMAXCONN#define SOMAXCONN 100#endif/* * The following defines how much buffer space the kernel should maintain * for a socket. */#define SOCKET_BUFSIZE 4096/* * Static routines for this file: */static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp, int port, char *host, int server, char *myaddr, int myport, int async));static int CreateSocketAddress _ANSI_ARGS_( (struct sockaddr_in *sockaddrPtr, char *host, int port));static int FileBlockModeProc _ANSI_ARGS_(( ClientData instanceData, int mode));static int FileCloseProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp));static int FileGetHandleProc _ANSI_ARGS_((ClientData instanceData, int direction, ClientData *handlePtr));static int FileInputProc _ANSI_ARGS_((ClientData instanceData, char *buf, int toRead, int *errorCode));static int FileOutputProc _ANSI_ARGS_(( ClientData instanceData, char *buf, int toWrite, int *errorCode));static int FileSeekProc _ANSI_ARGS_((ClientData instanceData, long offset, int mode, int *errorCode));static void FileWatchProc _ANSI_ARGS_((ClientData instanceData, int mask));static void TcpAccept _ANSI_ARGS_((ClientData data, int mask));static int TcpBlockModeProc _ANSI_ARGS_((ClientData data, int mode));static int TcpCloseProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp));static int TcpGetHandleProc _ANSI_ARGS_((ClientData instanceData, int direction, ClientData *handlePtr));static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp, char *optionName, Tcl_DString *dsPtr));static int TcpInputProc _ANSI_ARGS_((ClientData instanceData, char *buf, int toRead, int *errorCode));static int TcpOutputProc _ANSI_ARGS_((ClientData instanceData, char *buf, int toWrite, int *errorCode));static void TcpWatchProc _ANSI_ARGS_((ClientData instanceData, int mask));static int TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp, CONST char *mode, int *speedPtr, int *parityPtr, int *dataPtr, int *stopPtr));static void TtyGetAttributes _ANSI_ARGS_((int fd, TtyAttrs *ttyPtr));static int TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp, char *optionName, Tcl_DString *dsPtr));static void TtyInit _ANSI_ARGS_((int fd));static void TtySetAttributes _ANSI_ARGS_((int fd, TtyAttrs *ttyPtr));static int TtySetOptionProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp, char *optionName, char *value));static int WaitForConnect _ANSI_ARGS_((TcpState *statePtr, int *errorCodePtr));/* * This structure describes the channel type structure for file based IO: */static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ FileBlockModeProc, /* Set blocking/nonblocking mode.*/ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ FileSeekProc, /* Seek proc. */ NULL, /* Set option proc. */ NULL, /* Get option proc. */ FileWatchProc, /* Initialize notifier. */ FileGetHandleProc, /* Get OS handles out of channel. */};/* * This structure describes the channel type structure for serial IO. * Note that this type is a subclass of the "file" type. */static Tcl_ChannelType ttyChannelType = { "tty", /* Type name. */ FileBlockModeProc, /* Set blocking/nonblocking mode.*/ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ NULL, /* Seek proc. */ TtySetOptionProc, /* Set option proc. */ TtyGetOptionProc, /* Get option proc. */ FileWatchProc, /* Initialize notifier. */ FileGetHandleProc, /* Get OS handles out of channel. */};/* * This structure describes the channel type structure for TCP socket * based IO: */static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TcpBlockModeProc, /* Set blocking/nonblocking mode.*/ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Initialize notifier. */ TcpGetHandleProc, /* Get OS handles out of channel. */};/* *---------------------------------------------------------------------- * * FileBlockModeProc -- * * Helper procedure to set blocking and nonblocking modes on a * file based channel. Invoked by generic IO level code. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */ /* ARGSUSED */static intFileBlockModeProc(instanceData, mode) ClientData instanceData; /* File state. */ int mode; /* The mode to set. Can be one of * TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */{ FileState *fsPtr = (FileState *) instanceData; int curStatus;#ifndef USE_FIONBIO curStatus = fcntl(fsPtr->fd, F_GETFL); if (mode == TCL_MODE_BLOCKING) { curStatus &= (~(O_NONBLOCK)); } else { curStatus |= O_NONBLOCK; } if (fcntl(fsPtr->fd, F_SETFL, curStatus) < 0) { return errno; } curStatus = fcntl(fsPtr->fd, F_GETFL);#else if (mode == TCL_MODE_BLOCKING) { curStatus = 0; } else { curStatus = 1; } if (ioctl(fsPtr->fd, (int) FIONBIO, &curStatus) < 0) { return errno; }#endif return 0;}/* *---------------------------------------------------------------------- * * FileInputProc -- * * This procedure is invoked from the generic IO level to read * input from a file based channel. * * Results: * The number of bytes read is returned or -1 on error. An output * argument contains a POSIX error code if an error occurs, or zero. * * Side effects: * Reads input from the input device of the channel. * *---------------------------------------------------------------------- */static intFileInputProc(instanceData, buf, toRead, errorCodePtr) ClientData instanceData; /* File state. */ char *buf; /* Where to store data read. */ int toRead; /* How much space is available * in the buffer? */ int *errorCodePtr; /* Where to store error code. */{ FileState *fsPtr = (FileState *) instanceData; int bytesRead; /* How many bytes were actually * read from the input device? */ *errorCodePtr = 0; /* * Assume there is always enough input available. This will block * appropriately, and read will unblock as soon as a short read is * possible, if the channel is in blocking mode. If the channel is * nonblocking, the read will never block. */ bytesRead = read(fsPtr->fd, buf, (size_t) toRead); if (bytesRead > -1) { return bytesRead; } *errorCodePtr = errno; return -1;}/* *---------------------------------------------------------------------- * * FileOutputProc-- * * This procedure is invoked from the generic IO level to write * output to a file channel. * * Results: * The number of bytes written is returned or -1 on error. An * output argument contains a POSIX error code if an error occurred, * or zero. * * Side effects: * Writes output on the output device of the channel. * *---------------------------------------------------------------------- */static intFileOutputProc(instanceData, buf, toWrite, errorCodePtr) ClientData instanceData; /* File state. */ char *buf; /* The data buffer. */ int toWrite; /* How many bytes to write? */ int *errorCodePtr; /* Where to store error code. */{ FileState *fsPtr = (FileState *) instanceData; int written; *errorCodePtr = 0; written = write(fsPtr->fd, buf, (size_t) toWrite); if (written > -1) { return written; } *errorCodePtr = errno; return -1;}/* *---------------------------------------------------------------------- * * FileCloseProc -- * * This procedure is called from the generic IO level to perform * channel-type-specific cleanup when a file based channel is closed. * * Results: * 0 if successful, errno if failed. * * Side effects: * Closes the device of the channel. * *---------------------------------------------------------------------- */static intFileCloseProc(instanceData, interp) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - unused. */{ FileState *fsPtr = (FileState *) instanceData; FileState **nextPtrPtr; int errorCode = 0; Tcl_DeleteFileHandler(fsPtr->fd); if (!TclInExit() || ((fsPtr->fd != 0) && (fsPtr->fd != 1) && (fsPtr->fd != 2))) { if (close(fsPtr->fd) < 0) { errorCode = errno; } } for (nextPtrPtr = &firstFilePtr; (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == fsPtr) { (*nextPtrPtr) = fsPtr->nextPtr; break; } } ckfree((char *) fsPtr); return errorCode;}/* *---------------------------------------------------------------------- * * FileSeekProc -- * * This procedure is called by the generic IO level to move the * access point in a file based channel. * * Results: * -1 if failed, the new position if successful. An output * argument contains the POSIX error code if an error occurred, * or zero. * * Side effects: * Moves the location at which the channel will be accessed in * future operations. * *---------------------------------------------------------------------- */static intFileSeekProc(instanceData, offset, mode, errorCodePtr) ClientData instanceData; /* File state. */ long offset; /* Offset to seek to. */ int mode; /* Relative to where * should we seek? Can be * one of SEEK_START, * SEEK_SET or SEEK_END. */ int *errorCodePtr; /* To store error code. */{ FileState *fsPtr = (FileState *) instanceData; int newLoc; newLoc = lseek(fsPtr->fd, offset, mode); *errorCodePtr = (newLoc == -1) ? errno : 0; return newLoc;}/* *---------------------------------------------------------------------- * * FileWatchProc -- * * Initialize the notifier to watch the fd from this channel. * * Results: * None. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -