summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2001-06-18 13:13:23 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2001-06-18 13:13:23 (GMT)
commit298f69f947759d7c1fabe350452fcf9303c89376 (patch)
tree279599b17d03c4a70c0a714893b007ab1855c605
parenta7bfb25cf558c4f2ba054227660dfe3a31523219 (diff)
downloadtcl-298f69f947759d7c1fabe350452fcf9303c89376.zip
tcl-298f69f947759d7c1fabe350452fcf9303c89376.tar.gz
tcl-298f69f947759d7c1fabe350452fcf9303c89376.tar.bz2
Unix channels now have the right type associated with them [bug #219137]
A couple of nasty faults/assumptions in unixInit.test are fixed too.
-rw-r--r--ChangeLog17
-rw-r--r--tests/unixInit.test29
-rw-r--r--unix/tclUnixChan.c87
3 files changed, 96 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 7cf1714..ea31e4a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2001-06-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/unixInit.test (unixInit-1.2,unixInit-2.8): Added test for
+ code described below, and fixed a couple of errors that caused
+ problems during testing; the code to determine the installedTcl
+ constraint was wrong, and test unixInit-2.8 assumed that /tmp/lib
+ was free for use and could be deleted, which clashed nastily with
+ my installation and made other tests fail unnecessarily!
+
+ * unix/tclUnixChan.c (TtyInit,TclpOpenFileChannel,
+ Tcl_MakeFileChannel,TclpGetDefaultStdChannel): Alterations so that
+ the standard channels - stdin, stdout and stderr - have the
+ correct type and fconfigure options. This required making the
+ initialisation of serial lines a little more sophisticated to
+ make the console behave correctly in interactive mode... [Bug
+ #219137 and duplicates]
+
2001-06-16 Don Porter <dgp@users.sourceforge.net>
* generic/tclInt.decls:
diff --git a/tests/unixInit.test b/tests/unixInit.test
index 3017587..4c11741 100644
--- a/tests/unixInit.test
+++ b/tests/unixInit.test
@@ -10,7 +10,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: unixInit.test,v 1.14 2001/01/04 21:30:49 dgp Exp $
+# RCS: @(#) $Id: unixInit.test,v 1.15 2001/06/18 13:13:23 dkf Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
@@ -27,10 +27,10 @@ set env(LANG) C
# Some tests will fail if they are run on a machine that doesn't have
# this Tcl version installed (as opposed to built) on it.
if {[catch {
- set f [open "|[list $::tcltest::tcltest exit]" w+]
+ set f [open "|[list $::tcltest::tcltest]" w+]
exec kill -PIPE [pid $f]
close $f
-}]} {
+} msg]} {
set ::tcltest::testConstraints(installedTcl) 0
} else {
set ::tcltest::testConstraints(installedTcl) 1
@@ -59,6 +59,19 @@ test unixInit-1.1 {TclpInitPlatform: ignore SIGPIPE} {unixOnly installedTcl} {
set x
} {0 1}
+# This test is really a test of code in tclUnixChan.c, but the
+# channels are set up as part of initialisation of the interpreter so
+# the test seems to me to fit here as well as anywhere else.
+test unixInit-1.2 {initialisation: channel type deduction} {unixOnly installedTcl} {
+ set sock [socket localhost echo]
+ set pipe [open |[list $::tcltest::tcltest >@$sock] w]
+ puts $pipe {puts [fconfigure stdout -peername]; exit}
+ close $pipe
+ gets $sock channeltype
+ close $sock
+ set channeltype
+} {127.0.0.1 localhost 7}
+
proc getlibpath "{program [list $::tcltest::tcltest]}" {
set f [open "|$program" w+]
fconfigure $f -buffering none
@@ -152,12 +165,12 @@ test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} \
} {}
test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unixOnly} {
file delete -force /tmp/sparkly
- file delete -force /tmp/lib
+ file delete -force /tmp/library
file mkdir /tmp/sparkly
file copy $::tcltest::tcltest /tmp/sparkly/tcltest
- file mkdir /tmp/lib/tcl[info tclversion]
- close [open /tmp/lib/tcl[info tclversion]/init.tcl w]
+ file mkdir /tmp/library/tcl[info tclversion]
+ close [open /tmp/library/tcl[info tclversion]/init.tcl w]
set allAbsolute 1
foreach dir [getlibpath /tmp/sparkly/tcltest] {
@@ -165,7 +178,7 @@ test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unixOnly} {
&& [string equal absolute [file pathtype $dir]]}]
}
file delete -force /tmp/sparkly
- file delete -force /tmp/lib
+ file delete -force /tmp/library
set allAbsolute
} 1
test unixInit-3.1 {TclpSetInitialEncodings} {unixOnly installedTcl} {
@@ -215,7 +228,7 @@ test unixInit-5.1 {Tcl_Init} {emptyTest unixOnly} {
test unixInit-6.1 {Tcl_SourceRCFile} {emptyTest unixOnly} {
} {}
-
+
# cleanup
if {[info exists oldlibrary]} {
set env(TCL_LIBRARY) $oldlibrary
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 1bf9d54..d31cc6c 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -10,7 +10,7 @@
* 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.19 2000/10/28 00:29:58 hobbs Exp $
+ * RCS: @(#) $Id: tclUnixChan.c,v 1.20 2001/06/18 13:13:23 dkf Exp $
*/
#include "tclInt.h" /* Internal definitions for Tcl. */
@@ -217,7 +217,7 @@ static void TtyGetAttributes _ANSI_ARGS_((int fd,
static int TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,
Tcl_Interp *interp, char *optionName,
Tcl_DString *dsPtr));
-static FileState * TtyInit _ANSI_ARGS_((int fd));
+static FileState * TtyInit _ANSI_ARGS_((int fd, int initialize));
static int TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *mode, int *speedPtr, int *parityPtr,
int *dataPtr, int *stopPtr));
@@ -1201,54 +1201,61 @@ TtyParseMode(interp, mode, speedPtr, parityPtr, dataPtr, stopPtr)
* Given file descriptor that refers to a serial port,
* initialize the serial port to a set of sane values so that
* Tcl can talk to a device located on the serial port.
+ * Note that no initialization happens if the initialize flag
+ * is not set; this is necessary for the correct handling of
+ * UNIX console TTYs at startup.
*
* Results:
- * None.
+ * A pointer to a FileState suitable for use with Tcl_CreateChannel
+ * and the ttyChannelType structure.
*
* Side effects:
* Serial device initialized to non-blocking raw mode, similar to
- * sockets. All other modes can be simulated on top of this in Tcl.
+ * sockets (if initialize flag is non-zero.) All other modes can
+ * be simulated on top of this in Tcl.
*
*---------------------------------------------------------------------------
*/
static FileState *
-TtyInit(fd)
+TtyInit(fd, initialize)
int fd; /* Open file descriptor for serial port to
* be initialized. */
+ int initialize;
{
- IOSTATE iostate;
TtyState *ttyPtr;
ttyPtr = (TtyState *) ckalloc((unsigned) sizeof(TtyState));
GETIOSTATE(fd, &ttyPtr->savedState);
- iostate = ttyPtr->savedState;
+ if (initialize) {
+ IOSTATE iostate = ttyPtr->savedState;
#ifdef USE_TERMIOS
- iostate.c_iflag = IGNBRK;
- iostate.c_oflag = 0;
- iostate.c_lflag = 0;
- iostate.c_cflag |= CREAD;
- iostate.c_cc[VMIN] = 1;
- iostate.c_cc[VTIME] = 0;
+ iostate.c_iflag = IGNBRK;
+ iostate.c_oflag = 0;
+ iostate.c_lflag = 0;
+ iostate.c_cflag |= CREAD;
+ iostate.c_cc[VMIN] = 1;
+ iostate.c_cc[VTIME] = 0;
#endif /* USE_TERMIOS */
#ifdef USE_TERMIO
- iostate.c_iflag = IGNBRK;
- iostate.c_oflag = 0;
- iostate.c_lflag = 0;
- iostate.c_cflag |= CREAD;
- iostate.c_cc[VMIN] = 1;
- iostate.c_cc[VTIME] = 0;
+ iostate.c_iflag = IGNBRK;
+ iostate.c_oflag = 0;
+ iostate.c_lflag = 0;
+ iostate.c_cflag |= CREAD;
+ iostate.c_cc[VMIN] = 1;
+ iostate.c_cc[VTIME] = 0;
#endif /* USE_TERMIO */
#ifdef USE_SGTTY
- iostate.sg_flags &= (EVENP | ODDP);
- iostate.sg_flags |= RAW;
+ iostate.sg_flags &= (EVENP | ODDP);
+ iostate.sg_flags |= RAW;
#endif /* USE_SGTTY */
- SETIOSTATE(fd, &iostate);
+ SETIOSTATE(fd, &iostate);
+ }
return &ttyPtr->fs;
}
@@ -1354,7 +1361,7 @@ TclpOpenFileChannel(interp, fileName, modeString, permissions)
translation = "auto crlf";
channelTypePtr = &ttyChannelType;
- fsPtr = TtyInit(fd);
+ fsPtr = TtyInit(fd, 1);
} else
#endif /* SUPPORTS_TTY */
{
@@ -1428,16 +1435,17 @@ Tcl_MakeFileChannel(handle, mode)
FileState *fsPtr;
char channelName[16 + TCL_INTEGER_SPACE];
int fd = (int) handle;
+ Tcl_ChannelType *channelTypePtr;
#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#endif
+ int socketType = 0;
+ int argLength = sizeof(int);
if (mode == 0) {
return NULL;
}
- sprintf(channelName, "file%d", fd);
-
/*
* Look to see if a channel with this fd and the same mode already exists.
@@ -1453,7 +1461,24 @@ Tcl_MakeFileChannel(handle, mode)
}
#endif
- fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
+#ifdef SUPPORTS_TTY
+ if (isatty(fd)) {
+ fsPtr = TtyInit(fd, 0);
+ channelTypePtr = &ttyChannelType;
+ sprintf(channelName, "serial%d", fd);
+ } else
+#endif
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (VOID *)&socketType,
+ &argLength) == 0 && socketType == SOCK_STREAM) {
+ /*
+ * The mode parameter gets lost here, unfortunately.
+ */
+ return Tcl_MakeTcpClientChannel((ClientData) fd);
+ } else {
+ channelTypePtr = &fileChannelType;
+ fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
+ sprintf(channelName, "file%d", fd);
+ }
#ifdef DEPRECATED
fsPtr->nextPtr = tsdPtr->firstFilePtr;
@@ -1461,9 +1486,9 @@ Tcl_MakeFileChannel(handle, mode)
#endif
fsPtr->fd = fd;
fsPtr->validMask = mode | TCL_EXCEPTION;
- fsPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName,
+ fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName,
(ClientData) fsPtr, mode);
-
+
return fsPtr->channel;
}
@@ -2515,7 +2540,11 @@ TclpGetDefaultStdChannel(type)
* Set up the normal channel options for stdio handles.
*/
- Tcl_SetChannelOption(NULL, channel, "-translation", "auto");
+ if (Tcl_GetChannelType(channel) == &fileChannelType) {
+ Tcl_SetChannelOption(NULL, channel, "-translation", "auto");
+ } else {
+ Tcl_SetChannelOption(NULL, channel, "-translation", "auto crlf");
+ }
Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode);
return channel;
}