Hi Alexander,
I was able to reproduce the problem based on your description and test case,
and your change does resolve it for me.
On Tue, Mar 20, 2012 at 11:50:14PM +0400, Alexander LAW wrote:
> Thanks, I've understood your point.
> Please look at the patch. It implements the first way and it makes psql
> work too.
> 20.03.2012 00:05, Alvaro Herrera ??????????:
>> Excerpts from Alexander LAW's message of dom mar 18 06:04:51 -0300 2012:
>>> I see two ways to resolve the issue.
>>> First is to use CharToOemBuff when writing a string to the "con" and
>>> OemToCharBuff when reading an input from it.
>>> The other is to always use stderr/stdin for Win32 as it was done for
>>> msys before. I think it's more straightforward.
>> Using console directly instead of stdin/out/err is more appropriate when
>> asking for passwords and reading them back, because you can redirect the
>> rest of the output to/from files or pipes, without the prompt
>> interfering with that. This also explains why stderr is used instead of
>> stdout.
The console output code page will usually match the OEM code page, but this is
not guaranteed. For example, one can change it with chcp.exe before starting
psql. The conversion should be to the actual console output code page. After
"chcp 869", notice how printing to stdout yields question marks while your
code yields unrelated characters.
It would be nicer still to find a way to make the output routines treat this
explicitly-opened console like stdout to a console. I could not find any
documentation around this. Digging into the CRT source code, I see that the
automatic code page conversion happens in write(). One of tests write() uses
to determine whether the destination is a console is to call GetConsoleMode()
on the HANDLE underlying the CRT file descriptor. If that call fails, write()
assumes the target is not a console. GetConsoleMode() requires GENERIC_READ
access on its subject HANDLE, but the HANDLE resulting from our fopen("con",
"w") has only GENERIC_WRITE. Therefore, write() wrongly concludes that it's
writing to a non-console. fopen("con", "w+") fails, but fopen("CONOUT$",
"w+") seems to give the outcome we need. write() recognizes that it's writing
to a console and applies the code page conversion. Let's use that.
This gave me occasion to look at the special case for MSYS that you mentioned.
I observe the same behavior when running a native psql in a Cygwin xterm;
writes to the console succeed but do not appear anywhere. Instead of guessing
at console visibility based on an environment variable witnessing a particular
platform, let's check IsWindowVisible(GetConsoleWindow()).
What do you think of taking that approach?
Thanks,
nm