OS2 World Community Forum
OS/2, eCS & ArcaOS - Technical => Programming => Topic started by: Martin Vieregg on April 15, 2020, 05:29:39 pm
-
Meanwhile, I have published a stable beta version of MeShell 0.51 (see Utilities). But there's one problem left where I need your help for brainstorming.
PAUSE is a command which is defined in cmd.exe or 4os2.exe. It does not handle Stdin, but it does also not handle normal VIO keyboard input. I do not understand completely how it works, because a key input into the MeShell original VIO window has no effect. It seems that it is compiled completely internally. And this is a problem for MeShell. In comparison to "MORE", where I programmed an expedient substitute, I have no Idea at the moment how to handle the PAUSE problem. I hope that you have ideas how to handle the problem.
Programming a tiny "pause.exe" does not work because cmd.exe executes "pause" directly without checking the PATH directory list for external programs.
Till now, I found a convenient solution for every problem, and I hope that someone here has an idea how to solve this problem.
-
Hi Martin
Could you not recompile your pause.exe as a DLL file to be imported/called by your app?
Regards
Pete
-
Could you not recompile your pause.exe as a DLL file to be imported/called by your app?
The "PAUSE" command is part of cmd.exe, like "copy" or "dir". In opposite e.g. "xcopy" is an external program "xcopy.exe" and if it would not fit my purpose, I could rewrite and replace it.
The 4os2 source code is available, so I could change it, but I hope that I can handle the problem generally with cmd.exe.
A possible solution would be to ask the user how to handle the cmd file and, as an option, to rewrite it and renaming the original to *.cmd-old and replacing the occurences of "pause" to "pause2" and writing a tiny program "pause2". Or executing a temporary cmd file copy. But I hope that there's a better solution.
It would be already helpful if someone can explain why cmd.exe "Pause" does not accept a VIO keystroke. I don't understand what happens here. You can see the behaviour by typing "PAUSE" in MeShell, then make the VIO window visible, press a key and normally the LED should turn to green and the command "Pause" has finally been executed and a new Prompt appears. But MeShell does not do so. The LED rests red, so the keystroke in the VIO window has not been reached cmd.exe.
-
It seems that the problem is a FALSE ALARM. In a very early version of MeShell (cmdme 0.1) PAUSE did work already. So it seems that it is a newer bug in MeShell. I have also seen that the current MeShell 0.51 does not handle user input in a commandline program anymore. I have only to compare the old code with the current one to find the bug.
-
Meanwhile I have uploaded MeShell 0.52. The PAUSE problem was a new bug. Even 0.50 worked. (See section utilities).
But there's another related problem:
If a program requires user input via stdin in the same line where an output has placed, like
enter the desired directory name and press ENTER:
MeShell does not show the query, because cmd.exe and 4os2.exe only sends output to stdout if the line has been completed with Return. But both programs send an output without ending Return when the old command has been executed and the new prompt is shown.
With the simple attachment stdin/out based program sample, you can test the behaviour in cmd.exe/4os2.exe and MeShell.
[C:\]test1
Enter an expression: hello
You have entered: hello
[C:\]
Do we have access to cmd.exe source code?
I want so send the desire to Netlabs for 4os2.exe. Who is responsible for 4os2.exe Netlabs?
Does anyone has an idea how to force cmd.exe/4os2.exe to spit out the characters which are not shown?
-
While there's no output to stdout until the eol is recieved the cursor position will have changed. Calling VioGetCurPos before issuing a command, check for output on stdout, and if there is no output call VioGetCurPos again and compare the two values. If the values differ then use VioReadCharStr with the two values you have for the cursor position to get the output prompt and display it to the user. It's similar to the logic you used for capturing Vio Output.
-
Laurence,
but the VIO window rests empty. The cursor in the VIO window does not change. I could handle it if it is VIO output and input. But I do not receive redirected stdout in the described case. I thaught that the Vio* calls are completely restricted to the VIO window and not to stdin/stdout ?
-
The standard i/o functions move the Vio cursor. I've attached a simple program, with source, to demonstrate.
-
But I do not receive redirected stdout in the described case
You need to check for the change in the cursor position in the child/helper application, then use VioReadCharStr to get the prompt text and send that text through the pipe to the main application.
-
Thank you for the sample. Sorry, but it does not. You forgot that stdout is piped to the editor.
[H:\cursor]cursorpos
Hello World!
Initial cursor position: Column 0, Row 24
Final cursor position: Column 12, Row 24
[H:\cursor]cursorpos >out.txt
[H:\cursor]type out.txt
Hello World!
Initial cursor position: Column 0, Row 24
Final cursor position: Column 0, Row 24
-
Stdout is read by the child program and piped to the editor. You check for a prompt in the child program.
Parent pipes command to child program
child program checks cursor position
child program writes command to stdout
child program checks for output on stdout
if there is no output on stodut
check cursor position
compare cursor position with original position
-
I do not understand what you mean. I think the explanaition was too short. What is the child program? The helper or the external program which is executed, for example your sample program?
Do you think that the helper should read what happens in the pipe? (How can I do that?) But this provides that the output already happens, and I fear that the pipe is only running after eol / Return and before a line is finished, also the helper will see nothing.
At the moment, the helper program only opens the pipes on the "cmd side" which are created by MeShell and the cmd stdout/err/in is redirected to the pipes. After initializing, the helper doesn't make anything with the pipes. When terminating cmd.exe, the helper closes the pipes and terminates itself. Of course, I could add some functionality, but at the moment I do not understand what to do.
-
Meanwhile, I've updated MeShell to version 0.54.
MeShell.zip (http://www.hypermake.de/archive/meshell.zip) (650 kB)
If the UNZIP utility asks the user, the query is sent via STDERR. In 0.54, this works now perfect. But if a query is sent via STDOUT, it still does not work.
I have got an interesting sample program
#include <stdio.h>
main () {
char Expression[200];
printf ("Enter first expression: "); scanf ("%s", Expression);
printf ("You have entered: %s\n", Expression);
printf ("\n");
printf ("(Now query with Stderr)\n");
fprintf (stderr, "Enter second expression: "); scanf ("%s", Expression);
printf ("You have entered: %s\n", Expression);
}
and in MeShell, the second query comes first. The order comes false through the two pipes.
Perhaps to omit the problem the query in UNZIP is sent via Stderr.
-
Still the stdout problem of a query: Meanwhile, I've tested what happens if the helper sends characters to MeShell. But it does not has an effect, I see the helper output immediately in MeShell, and the line which should be shown from the user program still does not appear.
I found out that in Windows 10 the new written commandline pauses 3 seconds before the query is shown. (e.g. "copy" a file to a destination where a file with the same name exists). So it seems the Windows programmers had to fight with the same problem and also made a "dirty hack" which I am looking for. "UNZIP" query (with the query via stderr) comes immediately.
P. S. The Windows 10 commandline has also limits: 32767 lines.
-
I put the question to stackoverflow forum (https://stackoverflow.com/questions/61359024/redirected-stdout-without-ending-eol-rests-in-a-buffer-and-is-not-shown). Let's see what happens.
-
Now I am very close to a solution. Someone answered that I have to use fflush(). But fflush(mystream) is Standard C and requires a stream, not an OS/2 HFILE which is opened via DosOpen(). Is there a comparible call for OS/2 HFILE to flush the buffer ? The editor can detect the problem and the helper calls a flush call for stdout.
-
DosResetBuf.
Why don't you just read the OS/2 programming doc ?
-
Yes, I did it, but I tried to find something with "flush".... Thank you.
But anyway, exeuting DosResetBuffer in the helper app has no effect. I also tried to DosClose and DosOpen the named pipe. Also no effect. I really wonder how other command-line frontends do the job.
-
I realized now that the "fflush" command has to be placed in the user program. Stdout is always buffered when redirecting, Stderr is not. That is the problem that stderr output can happen before the stdout output. I have got an extreme example, see attachment. I wrote the sample for testing colored output and the stderr output is shown 4 lines before it should be shown.
So that means that all programmers which are writing stdout and stderr or use user queries have to flush stdout before performing a stdin:
char Expression[200];
printf ("Enter an expression: "); fflush (stdout); scanf ("%s", Expression);
printf ("You have entered: %s\n", Expression);
flush (stdout); fprintf (stderr, "An error has occured.");
MeShell has been updated to 0.61. See here (https://www.os2world.com/forum/index.php/topic,2380.msg26326.html#msg26326)