⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclunixchan.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclUnixChan.c * *	Common channel driver for Unix channels based on files, command *	pipes and TCP sockets. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by 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: tclUnixChan.c,v 1.42 2003/02/21 02:36:27 hobbs Exp $ */#include "tclInt.h"	/* Internal definitions for Tcl. */#include "tclPort.h"	/* Portability features for Tcl. */#include "tclIO.h"	/* To get Channel type declaration. *//* * 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#define SUPPORTS_TTY#ifdef USE_TERMIOS#   include <termios.h>#   ifdef HAVE_SYS_IOCTL_H#	include <sys/ioctl.h>#   endif /* HAVE_SYS_IOCTL_H */#   ifdef HAVE_SYS_MODEM_H#	include <sys/modem.h>#   endif /* HAVE_SYS_MODEM_H */#   define IOSTATE			struct termios#   define GETIOSTATE(fd, statePtr)	tcgetattr((fd), (statePtr))#   define SETIOSTATE(fd, statePtr)	tcsetattr((fd), TCSADRAIN, (statePtr))#   define GETCONTROL(fd, intPtr)	ioctl((fd), TIOCMGET, (intPtr))#   define SETCONTROL(fd, intPtr)	ioctl((fd), TIOCMSET, (intPtr))    /*     * TIP #35 introduced a different on exit flush/close behavior that     * doesn't work correctly with standard channels on all systems.     * The problem is tcflush throws away waiting channel data.	 This may     * be necessary for true serial channels that may block, but isn't     * correct in the standard case.  This might be replaced with tcdrain     * instead, but that can block.  For now, we revert to making this do     * nothing, and TtyOutputProc being the same old FileOutputProc.     * -- hobbs [Bug #525783]     */#   define BAD_TIP35_FLUSH 0#   if BAD_TIP35_FLUSH#	define TTYFLUSH(fd)		tcflush((fd), TCIOFLUSH);#   else#	define TTYFLUSH(fd)#   endif /* BAD_TIP35_FLUSH */#   ifdef FIONREAD#	define GETREADQUEUE(fd, int)	ioctl((fd), FIONREAD, &(int))#   elif defined(FIORDCHK)#	define GETREADQUEUE(fd, int)	int = ioctl((fd), FIORDCHK, NULL)#   endif /* FIONREAD */#   ifdef TIOCOUTQ#	define GETWRITEQUEUE(fd, int)	ioctl((fd), TIOCOUTQ, &(int))#   endif /* TIOCOUTQ */#   if defined(TIOCSBRK) && defined(TIOCCBRK)/* * Can't use ?: operator below because that messes up types on either * Linux or Solaris (the two are mutually exclusive!) */#	define SETBREAK(fd, flag) \		if (flag) {				\		    ioctl((fd), TIOCSBRK, NULL);	\		} else {				\		    ioctl((fd), TIOCCBRK, NULL);	\		}#   endif /* TIOCSBRK&TIOCCBRK */#   if !defined(CRTSCTS) && defined(CNEW_RTSCTS)#	define CRTSCTS CNEW_RTSCTS#   endif /* !CRTSCTS&CNEW_RTSCTS */#else	/* !USE_TERMIOS */#ifdef USE_TERMIO#   include <termio.h>#   define IOSTATE			struct termio#   define GETIOSTATE(fd, statePtr)	ioctl((fd), TCGETA, (statePtr))#   define SETIOSTATE(fd, statePtr)	ioctl((fd), TCSETAW, (statePtr))#else	/* !USE_TERMIO */#ifdef USE_SGTTY#   include <sgtty.h>#   define IOSTATE			struct sgttyb#   define GETIOSTATE(fd, statePtr)	ioctl((fd), TIOCGETP, (statePtr))#   define SETIOSTATE(fd, statePtr)	ioctl((fd), TIOCSETP, (statePtr))#else	/* !USE_SGTTY */#   undef SUPPORTS_TTY#endif	/* !USE_SGTTY */#endif	/* !USE_TERMIO */#endif	/* !USE_TERMIOS *//* * 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. */#ifdef DEPRECATED    struct FileState *nextPtr;	/* Pointer to next file in list of all				 * file channels. */#endif /* DEPRECATED */} FileState;#ifdef SUPPORTS_TTY/* * The following structure describes per-instance state of a tty-based * channel. */typedef struct TtyState {    FileState fs;		/* Per-instance state of the file				 * descriptor.	Must be the first field. */    int stateUpdated;		/* Flag to say if the state has been				 * modified and needs resetting. */    IOSTATE savedState;		/* Initial state of device.  Used to reset				 * state when device closed. */} TtyState;/* * 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;#endif	/* !SUPPORTS_TTY */#define UNSUPPORTED_OPTION(detail) \	if (interp) {							\	    Tcl_AppendResult(interp, (detail),				\		    " not supported for this platform", (char *) NULL); \	}#ifdef DEPRECATEDtypedef struct ThreadSpecificData {    /*     * List of all file channels currently open.  This is per thread and is     * used to match up fd's to channels, which rarely occurs.     */    FileState *firstFilePtr;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;#endif /* DEPRECATED *//* * 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 /* SOMAXCONN */#if (SOMAXCONN < 100)#   undef  SOMAXCONN#   define SOMAXCONN	100#endif /* SOMAXCONN < 100 *//* * 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, CONST char *host, int server,			    CONST char *myaddr, int myport, int async));static int		CreateSocketAddress _ANSI_ARGS_(			    (struct sockaddr_in *sockaddrPtr,			    CONST 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, CONST char *buf,			    int toWrite, int *errorCode));static int		FileSeekProc _ANSI_ARGS_((ClientData instanceData,			    long offset, int mode, int *errorCode));static Tcl_WideInt	FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,			    Tcl_WideInt 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, CONST 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,			    CONST char *buf, int toWrite, int *errorCode));static void		TcpWatchProc _ANSI_ARGS_((ClientData instanceData,			    int mask));#ifdef SUPPORTS_TTYstatic int		TtyCloseProc _ANSI_ARGS_((ClientData instanceData,			    Tcl_Interp *interp));static void		TtyGetAttributes _ANSI_ARGS_((int fd,			    TtyAttrs *ttyPtr));static int		TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,			    Tcl_Interp *interp, CONST char *optionName,			    Tcl_DString *dsPtr));static FileState *	TtyInit _ANSI_ARGS_((int fd, int initialize));#if BAD_TIP35_FLUSHstatic int		TtyOutputProc _ANSI_ARGS_((ClientData instanceData,			    CONST char *buf, int toWrite, int *errorCode));#endif /* BAD_TIP35_FLUSH */static int		TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp,			    CONST char *mode, int *speedPtr, int *parityPtr,			    int *dataPtr, int *stopPtr));static void		TtySetAttributes _ANSI_ARGS_((int fd,			    TtyAttrs *ttyPtr));static int		TtySetOptionProc _ANSI_ARGS_((ClientData instanceData,			    Tcl_Interp *interp, CONST char *optionName, 			    CONST char *value));#endif	/* SUPPORTS_TTY */static int		WaitForConnect _ANSI_ARGS_((TcpState *statePtr,			    int *errorCodePtr));static Tcl_Channel	MakeTcpClientChannelMode _ANSI_ARGS_(			    (ClientData tcpSocket,			    int mode));/* * This structure describes the channel type structure for file based IO: */static Tcl_ChannelType fileChannelType = {    "file",			/* Type name. */    TCL_CHANNEL_VERSION_3,	/* v3 channel */    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. */    NULL,			/* close2proc. */    FileBlockModeProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */    FileWideSeekProc,		/* wide seek proc. */};#ifdef SUPPORTS_TTY/* * 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. */    TCL_CHANNEL_VERSION_2,	/* v2 channel */    TtyCloseProc,		/* Close proc. */    FileInputProc,		/* Input proc. */#if BAD_TIP35_FLUSH    TtyOutputProc,		/* Output proc. */#else /* !BAD_TIP35_FLUSH */    FileOutputProc,		/* Output proc. */#endif /* BAD_TIP35_FLUSH */    NULL,			/* Seek proc. */    TtySetOptionProc,		/* Set option proc. */    TtyGetOptionProc,		/* Get option proc. */    FileWatchProc,		/* Initialize notifier. */    FileGetHandleProc,		/* Get OS handles out of channel. */    NULL,			/* close2proc. */    FileBlockModeProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */};#endif	/* SUPPORTS_TTY *//* * This structure describes the channel type structure for TCP socket * based IO: */static Tcl_ChannelType tcpChannelType = {    "tcp",			/* Type name. */    TCL_CHANNEL_VERSION_2,	/* v2 channel */    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. */    NULL,			/* close2proc. */    TcpBlockModeProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */};/* *---------------------------------------------------------------------- * * 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 /* USE_FIONBIO */    if (mode == TCL_MODE_BLOCKING) {	curStatus = 0;    } else {	curStatus = 1;    }    if (ioctl(fsPtr->fd, (int) FIONBIO, &curStatus) < 0) {	return errno;    }#endif /* !USE_FIONBIO */    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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -