[comp.sys.ibm.pc] MS-DOS call to read without echo

lhv@spocm2.UUCP (Leo Vermeulen) (02/06/90)

I have the following problem: I'm trying to write a C-program, using
Microsoft-C 5.1, that reads a character string from the keyboard and
assigns it to an character array. Since this string is supposed to be
a password, I do not want it echoed to the display.

Does anybody have any advice on how to write this bit of code? I am 
accustomed to a Un*x environment, and have not too much experience
coding in C for MS-DOS, so please keep it simple.

Any responses, by e-mail, would be greatly appreciated.

Leo Vermeulen  (UUCP: ..!uunet!mcsun!sunic!spocm2!lhv)
--------------------------------------------------------------------------
Stockholm -- where the banks are on strike, and public transport will
             follow suit next week. Nobody will be able to pay for a taxi!
--------------------------------------------------------------------------

mcintyre@turing.cs.rpi.edu (David McIntyre) (02/06/90)

In article <1036@spocm2.UUCP> lhv@spocm2.UUCP (Leo Vermeulen) writes:
>
>I have the following problem: I'm trying to write a C-program, using
>Microsoft-C 5.1, that reads a character string from the keyboard and
>assigns it to an character array. Since this string is supposed to be
>a password, I do not want it echoed to the display.
>
>Any responses, by e-mail, would be greatly appreciated.
>

I sent Leo a response by email, but in case anyone else is wondering
about this:  MSC5.1 has a function called getch(), which gets a
character from the console without echo.  

					-Dave


Dave "mr question" McIntyre     |      "....say you're thinking about a plate
mcintyre@turing.cs.rpi.edu      |       of shrimp.....and someone says to
office : 518-276-8633		|	you 'plate,' or 'shrimp'......"

elund@pro-graphics.cts.com (Eric Lund) (02/08/90)

In-Reply-To: message from lhv@spocm2.UUCP

You can create your own INPUT routine using getch() and getche().  The former
DOES NOT ECHO.  I don't know if MSC has a getpass() function.  This is
available on some C compilers, and allows you to input a (ta da) password.

Eric

 ProLine: elund@pro-graphics
    UUCP: ...crash!pro-graphics!elund
ARPA/DDN: pro-graphics!elund@nosc.mil
Internet: elund@pro-graphics.cts.com

pipkins@qmsseq.imagen.com (Jeff Pipkins) (02/09/90)

In article <1036@spocm2.UUCP> lhv@spocm2.UUCP (Leo Vermeulen) writes:
>
>I have the following problem: I'm trying to write a C-program, using
>Microsoft-C 5.1, that reads a character string from the keyboard and
>assigns it to an character array. Since this string is supposed to be
>a password, I do not want it echoed to the display.

As others have mentioned in reply, the getch() function provided with
both MSC and Turdo C is probably the easiest solution.  MSC provides
a library of console routines when you include conio.h.  I was not
happy with these for two reasons.  First, if a user redirects stdin
and/or stdout when invoking your program, some of the MSC conio
routines are affected and others are not.  For example, the cprintf()
function writes to stdout just like printf() does!  This has to be
considered a bug -- why else would there be two different functions?!
The other problem is that the output of the kbhit() function is not
completely defined in the documentation and could be more useful if
it were more complete.  Yes, kbhit() is inherently PC-specific and
nonportable.

I few years ago, circa MSC 3.x, I rewrote the conio library to solve
these problems.  It is now in the public domain and works for both
MSC and Turdo C.  I submitted it to the C User's Group, and someone
seems to have uploaded it to SIMTEL as PD1:<MSDOS.C>CONIO.ARC.  It
is written in ASM and includes source.

Standard disclaimers and all that.

darcy@druid.uucp (D'Arcy J.M. Cain) (02/09/90)

In article <1262@srhqla.SR.COM> tcm@srhqla.SR.COM (Tim Meighan) writes:
>/*
> *  GET_KEY() checks for IBM-PC keyboard input, returning a -1 if no character
> *  is available, 0 to 255 for regular keypresses, and values above 255 for
> *  function keypresses.  Note that the function kbhit() is not from the
> *  standard library but is part of MSC.  Use this function ONLY when
> *  standard input will be the PC keyboard.
> */
>
>int get_key()
>{
>	int c;
>
>	if(kbhit())
>	{
>		if((c = getch()) == 0)
>		{
>			c = (getch() + 197);
>			return(c);
>		}
>	}
>	return(-1);
>}
>
>Tim Meighan
>Silent Radio

Hmmm.  Seems to only allow for function keys to be entered.  Regular
keys will return -1.  Also 197 isn't the best choice.  Here is how
I did the same thing:

int get_key()
{
	int c;

	if(kbhit())
	{
		if ((c = getch()) == 0)
			c = (getch() << 8);

		return(c);
	}
	return(0);
}

By doing the shift you get two advantages.  First, the return value can
be anded with 0xff00 and tested for special characters.  Second, the
return value winds up looking like the scan code return and it is easier
to enter a table of function keys into a #define list from standard texts.

I also used 0 to signify no character since it is an impossible return.
It is slightly more intuitive and can save a memory fetch and a byte
when comparing the return such as:

	if (c = get_key)
		process_key();

instead of 
	if ((c = get_key()) != -1)
		process_key();


-- 
D'Arcy J.M. Cain (darcy@druid)     |   Thank goodness we don't get all 
D'Arcy Cain Consulting             |   the government we pay for.
West Hill, Ontario, Canada         |
(416) 281-6094                     |

bmarsh@cod.NOSC.MIL (William C. Marsh) (02/13/90)

In article <1990Feb9.000950.11693@druid.uucp> darcy@druid.UUCP (D'Arcy J.M. Cain) writes:
>In article <1262@srhqla.SR.COM> tcm@srhqla.SR.COM (Tim Meighan) writes:
>
>I also used 0 to signify no character since it is an impossible return.
>It is slightly more intuitive and can save a memory fetch and a byte
>when comparing the return such as:
>
>	if (c = get_key)
>		process_key();
>
Unfortunatly, (and the Microsoft C library functions _bios_keybd use the
same assumption), a scan code of 0x0000 *IS* possible on a standard
keyboard.  It is Ctrl-Break.  If you use the above idea for reading
keys, if the user hits Ctrl-Break, you program will hang, since 
the function get_key() will return zero when there is no key ready,
or if the user hit Ctrl-Break.  -1 would be a much better return code,
since 0xFFFF *is not* possible.

--

Bill Marsh, Naval Ocean Systems Center, San Diego, CA
{arpa,mil}net: bmarsh@cod.nosc.mil
uucp: {ihnp4,akgua,decvax,dcdwest,ucbvax}!sdcsvax!nosc!bmarsh

"If everything seems to be coming your way, you're probably in the wrong lane."

tcm@srhqla.SR.COM (Tim Meighan) (02/13/90)

In article <1990Feb9.000950.11693@druid.uucp> darcy@druid.UUCP
 (D'Arcy J.M. Cain) writes:

> In article <1262@srhqla.SR.COM> tcm@srhqla.SR.COM (Tim Meighan) writes:
>>
>> [My sample code with mistake]
>>

> Hmmm.  Seems to only allow for function keys to be entered.  Regular
> keys will return -1.  Also 197 isn't the best choice.

Arg!  He's absolutely right, there is a misplaced closing brace.
It should have been:

	if(kbhit())
	{
		if((c = getch()) == 0)
		{
			c = (getch() + 197);
		}
		return(c);
	}
	return(-1);

I chose 197 because it makes F1 return a value of 256, F2 return 257, etc.
D'Arcy's method (shifting) is better at producing faster machine code.

Most keyboards produce an ASCII NUL (0) value when the user types CTRL-@.
This normally causes a BREAK to occur, but is something that can be
intercepted.  This raises a really interesting side point: if you redirect
the BIOS break handler vector to your own code, then it is possible to pass
the single 0 keycode back into get_key() via the initial getch() function.
Therefore, your program will hang at the second getch() call, since we're
assuming here that an initial 0 MUST indicate that a second key is waiting
in the buffer, which in this case is not so.

There are different ways to avoid this, such as having your application  
"fake" the extra keycode in its break handler.  It seemed "correct" to me
to use a NUL (0) since that is what the original ASCII control code was
anyway.   Which means that, for me, get_key() CAN return a 0 code, which
tells my application that the user attempted to break out of the program.

This is why I return a -1 to mean "no key pressed."  However, D'Arcy is quite
right that in many cases (where break traps aren't set up by the application)
a 0 code is never going to make it to the get_key() function, so it is
the faster and more intuitive way to indicate "no key pressed."

Tim Meighan