[GPS] - Thu May 9, 2002: I wrote this little extension for my file server. My file server is a console application that prompts the user for a password. Being the pedantic programmer that I am I decided I didn't want someone to be able to see the password while the user enters it. I also wanted to receive a character at a time, so that I could display * for each entered char. This extension provides four commands. Please feel free to add to this. I place the code in the public domain. [KBK] - 10 May 2002 - George, would you consider writing a TIP on this? This code could slide very easily into tclUnixChan.c (in the functions TtyGetOptionProc and TtySetOptionProc) as additional 'fconfigure' options that apply to ttys. Perhaps one could spell them something like: fconfigure stdin -echo false -canonicalize false It's slightly messy that configuring these flags might apply to several channels at once, but that's no worse than the bucket of options we already have on ttys: -mode / -handshake / -xchar / -timeout / -ttycontrol all potentially have the same cross-channel effects. ---- #include #include #include #include #include /*For MAX_CANON */ #include #define CMD_ARGS (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) int TerminalEchoOff CMD_ARGS { struct termios terminal; int fid = fileno (stdout); if (objc != 1) { Tcl_WrongNumArgs (interp, 0, NULL, "terminal:echoOff"); return TCL_ERROR; } tcgetattr (fid, &terminal); terminal.c_lflag &= (~ECHO); tcsetattr (fid, TCSANOW, &terminal); return TCL_OK; } int TerminalEchoOn CMD_ARGS { struct termios terminal; int fid = fileno (stdout); if (objc != 1) { Tcl_WrongNumArgs (interp, 0, NULL, "terminal:echoOn"); return TCL_ERROR; } tcgetattr (fid, &terminal); terminal.c_lflag |= (ECHO); tcsetattr (fid, TCSANOW, &terminal); return TCL_OK; } int TerminalCanonicalOff CMD_ARGS { struct termios terminal; int fid = fileno (stdin); if (objc != 1) { Tcl_WrongNumArgs (interp, 0, NULL, "terminal:canonicalOff"); return TCL_ERROR; } tcgetattr (fid, &terminal); terminal.c_lflag &= (~ICANON); terminal.c_cc[VTIME] = 0; terminal.c_cc[VMIN] = 1; tcsetattr (fid, TCSANOW, &terminal); return TCL_OK; } int TerminalCanonicalOn CMD_ARGS { struct termios terminal; int fid = fileno (stdin); if (objc != 1) { Tcl_WrongNumArgs (interp, 0, NULL, "terminal:canonicalOn"); return TCL_ERROR; } tcgetattr (fid, &terminal); terminal.c_lflag |= (ICANON); terminal.c_cc[VTIME] = 0; terminal.c_cc[VMIN] = MAX_CANON; tcsetattr (fid, TCSANOW, &terminal); return TCL_OK; } int Terminal_Init (Tcl_Interp *interp) { #define OBJ_CMD(name,func) Tcl_CreateObjCommand(interp, name, func, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL) OBJ_CMD ("terminal:echoOff", TerminalEchoOff); OBJ_CMD ("terminal:echoOn", TerminalEchoOn); OBJ_CMD ("terminal:canonicalOff", TerminalCanonicalOff); OBJ_CMD ("terminal:canonicalOn", TerminalCanonicalOn); #undef OBJ_CMD return TCL_OK; } ----