Where does "printf" write in a Windows Non-console Application? - c++

If I choose to create a Windows Non-console Application, and implement printf/cout in the code, where does the printf/cout write? Does it write to the stdout buffer? If yes, is there any way to read it from stdout and print it to some text file or do a MessageBox with the text (just to verify that I have read it correctly)?
EDIT:: Just to clarify that I do not want to redirect the output anywhere. I would like to know, where does printf/cout write? And if it writes to some default buffer, is there a way to read the output, just to verify that I have read the correct output and from the correct buffer. Please, do not give me solutions to redirect the "stdout".

Under Windows stdout is a wrapper to the low-level functions accessing the handle returned by GetStdHandle(STD_OUTPUT_HANDLE).
When starting a non-console application by double-clicking (I tried under Windows 7, 64 bit) then GetStdHandle(STD_OUTPUT_HANDLE) will return an invalid handle. This means that printf and other commands will write nothing at all but the low-level functions internally called by printf will return an error code.
However as already said even a non-console program can be started the following way:
program_name > output_file.txt
In this case the printf output will be written to the output file.
-- EDIT --
If you wish to "catch" the printf() output and write it to MessageBox() there are two ways to achieve this:
The first one is running the program twice while the input of one instance is the standard output of the other one. The behavior could be explained by the following command line:
program_name | program_name /msgbox
The second possibility works without running two programs and without running the program twice: You may hook file handle #1. This should be at least possible when using msvcrt.dll:
HANDLE hRead,hWrite;
CreatePipe(&hRead,&hWrite,NULL,0);
dup2(_open_osfhandle(hWrite,O_WRONLY),1);
// Now printf() output can be read from handle hRead
printf("Hello world 2!\n");
// In a separate thread do:
ReadFile(hRead,...);

Since your question seems to be just for information, a windows app without a console, has its stdout, stderr handles closed. Any function that tries to output to those handles, simply gets called, checks for an open handle, finds it closed, and returns without doing anything else.
You might say, your output in this case ends up nowhere to be found :)
If you want to read this output, then you need to open the handles either by allocating a console, or use one of the methods described here.

I am developing a visual engine and I use the following two things as a substitution for the standard input/output between pc and user that you get in console application.
1: Use sprintf (int sprintf ( char * str, const char * format, ... )). What it does is print into a string instead of stdout(you don't have to use a temporary file). After this you can use MessageBox with the string where you just printed to.
2: Make an actual console window(while keeping the main one) and redirect the stdin, stdout and stderr from the main window to the console. Here is a class for construction:
ConsoleWindowClass.h:
#pragma once
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
class ConsoleWindowClass
{
public:
ConsoleWindowClass(void);
~ConsoleWindowClass(void);
void Create();
};
ConsoleWindowClass.cpp:
#include "ConsoleWindowClass.h"
using namespace std;
// maximum mumber of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;
ConsoleWindowClass::ConsoleWindowClass(void)
{
Create();
}
ConsoleWindowClass::~ConsoleWindowClass(void)
{
}
void ConsoleWindowClass::Create()
{
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}
After this, calling printf() will print the string into the console. You can also use the console to type strings into it and they will be usable from the main window(use multi-threading so that scanf won't pause your main program).

printf or cout always print to stdout.
You need to start the program from command line and pipe its output to a text file to make it readable.
Otherwise you would need an outputstream to a file in tmp to be generated inside your code.
Piping can be done the following way (if your apps name would be foo):
foo > log.txt
You could then read the file log.txt if you navigate to its directory which can be found with
dir

Related

When redirecting a process' both Input and Output in Windows, input doesn't work

I want to redirect the Input and Output of a program, to another program which uses two threads, one for Input of the process, another for output. Now the 2nd program reads from it's stdin and writes to the 1st program's stdin. Similarly, 2nd program reads from the 1st program's stdout and writes it to it's stdout. And, I do this using anonymous pipes[CreatePipe()]
I've followed the logic from this link: Creating a Child Process with Redirected Input and Output MSDN
But, so far what I've been able to achieve is that I can get the stdout properly redirected, but when it comes to redirecting the stdin, scanf() functions don't wait to get the input, they just simply takes no input!
My questions is: What could be the problem? is it a Win32 API specific problem?
or a common redirected related issue? or is it a buffering related problem?
I've even kept this article in mind: Be careful when redirecting both a process’s stdin and stdout to pipes, for you can easily deadlock MSDN
Note:
In the 2nd Program I've used two threads for the I/O redirection. One for Input and one for Output. And, through a "pretty ugly trick", I've been using PIPE HANDLE as FILE*.
P.S.: This is my first question in stackoverflow. So pardon me if I've violated any rules for making questions.
EDIT:
that program whose I/O I've redirected:
char name[256];
char school[256];
int age = -1;
strcpy(name, "(_null)");
strcpy(school, "(_null)");
printf("What's your name?\n");
int n = scanf("%s", name);
printf("\n\nscanf()=%d\n", n); //this prints -1
printf("What's your age?\n");
scanf("%d", &age);
And the two thread routines that I used to perform I/O redirection:
rdpipe->m_stdout and rdpipe->m_stdin are both of types FILE from stdio.h, but m_stdout is read-only and m_stdin is write-only.
bool fexit = false;
void func_out(RDPIPE *rdpipe) {
char buf[1024];
while(true) {
fgets(buf, 1024, stdin);
if(fexit) break;
fwrite(buf, 1, strlen(buf), rdpipe->m_stdin);
if(fexit) break;
}
}
void func_in(RDPIPE *rdpipe) {
char buf[4096];
while(!feof(rdpipe->m_stdout)) {
int n = fread(buf, 1, 4096, rdpipe->m_stdout);
fwrite(buf, 1, n, stdout);
}
fexit = true;
}

How can I read process output that has not been flushed?

Consider this little programm be compiled as application.exe
#include <stdio.h>
int main()
{
char str[100];
printf ("Hello, please type something\n");
scanf("%[^\n]s", &str);
printf("you typed: %s\n", str);
return 0;
}
Now I use this code to start application.exe and fetch its output.
#include <stdio.h>
#include <iostream>
#include <stdexcept>
int main()
{
char buffer[128];
FILE* pipe = popen("application.exe", "r");
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
printf(buffer);
}
pclose(pipe);
return 0;
}
My problem is that there is no output until I did my input. Then both output lines get fetched.
I can workarround this problem by adding this line after the first printf statement.
fflush(stdout);
Then the first line is fetched before I do my input as expected.
But how can I fetch output of applications that I cannot modify and that do not use fflush() in "realtime" (means before they exit)? .
And how does the windows cmd do it?
You have been bitten by the fact that the buffering for the streams which are automatically opened in a C program changes with the type of device attached.
That's a bit odd — one of the things which make *nixes nice to play with (and which are reflected in the C standard library) is that processes don't care much about where they get data from and where they write it. You just pipe and redirect around at your leisure and it's usually plug and play, and pretty fast.
One obvious place where this rule breaks is interaction; you present a nice example. If the output of the program is block buffered you don't see it before maybe 4k data has accumulated, or the process exits.
A program can detect though whether it writes to a terminal via isatty() (and perhaps through other means as well). A terminal conceptually includes a user, suggesting an interactive program. The library code opening stdin and stdout checks that and changes their buffering policy to line buffered: When a newline is encountered, the stream is flushed. That is perfect for interactive, line oriented applications. (It is less than perfect for line editing, as bash does, which disables buffering completely.)
The open group man page for stdin is fairly vague with respect to buffering in order to give implementations enough leeway to be efficient, but it does say:
the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
That's what happens to your program: The standard library sees that it is running "non-interactively" (writing to a pipe), tries to be smart and efficient and switches on block buffering. Writing a newline does not flush the output any longer. Normally that is a good thing: Imagine writing binary data, writing to disk every 256 bytes, on average! Terrible.
It is noteworthy to realize that there is probably a whole cascade of buffers between you and, say, a disk; after the C standard library comes the operating system's buffers, and then the disk's proper.
Now to your problem: The standard library buffer used to store characters-to-be-written is in the memory space of the program. Despite appearances, the data has not yet left your program and hence is not (officially) accessible by other programs. I think you are out of luck. You are not alone: Most interactive console programs will perform badly when one tries to operate them through pipes.
IMHO, that is one of the less logical parts of IO buffering: it acts differently when directed to a terminal or to a file or pipe. If IO is directed to a file or a pipe, it is normally buffered, that means that output is actually written only when a buffer is full or when an explicit flush occurs => that is what you see when you execute a program through popen.
But when IO is directed to a terminal, a special case occurs: all pending output is automatically flushed before a read from the same terminal. That special case is necessary to allow interactive programs to display prompts before reading.
The bad thing is that if you try to drive an interactive application through pipes, you loose: the prompts can only be read when either the application ends or when enough text was output to fill a buffer. That's the reason why Unix developpers invented the so called pseudo ttys (pty). They are implemented as terminal drivers so that the application uses the interactive buffering, but the IO is in fact manipulated by another program owning the master part of the pty.
Unfortunately, as you write application.exe, I assume that you use Windows, and I do not know an equivalent mechanism in the Windows API. The callee must use unbuffered IO (stderr is by default unbuffered) to allow the prompts to be read by a caller before it sends the answer.
The problems of my question in my original post are already very good explained
in the other answers.Console applications use a function named isatty() to detect
if their stdout handler is connected to a pipe or a real console. In case of a pipe
all output is buffered and flushed in chunks except if you directly call fflush().
In case of a real console the output is unbuffered and gets directly printed to the
console output.
In Linux you can use openpty() to create a pseudoterminal and create your process in it. As a
result the process will think it runs in a real terminal and uses unbuffered output. Windows seems not to have
such an option.
After a lot of digging through winapi documentation I found that this is not true. Actually you can create
your own console screen buffer and use it for stdout of your process that will be unbuffered then.
Sadly this is not a very comfortable solution because there are no event handler and we need to poll for new data.
Also at the moment I'm not sure how to handle scrolling when this screen buffer is full. But even if there are still some problems
left I think I have created a very useful (and interesting) starting point for those of you who ever wanted to fetch unbuffered (and unflushed)
windows console process output.
#include <windows.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
char cmdline[] = "application.exe"; // process command
HANDLE scrBuff; // our virtual screen buffer
CONSOLE_SCREEN_BUFFER_INFO scrBuffInfo; // state of the screen buffer
// like actual cursor position
COORD scrBuffSize = {80, 25}; // size in chars of our screen buffer
SECURITY_ATTRIBUTES sa; // security attributes
PROCESS_INFORMATION procInfo; // process information
STARTUPINFO startInfo; // process start parameters
DWORD procExitCode; // state of process (still alive)
DWORD NumberOfCharsWritten; // output of fill screen buffer func
COORD pos = {0, 0}; // scr buff pos of data we have consumed
bool quit = false; // flag for reading loop
// 1) Create a screen buffer, set size and clear
sa.nLength = sizeof(sa);
scrBuff = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&sa, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleScreenBufferSize(scrBuff, scrBuffSize);
// clear the screen buffer
FillConsoleOutputCharacter(scrBuff, '\0', scrBuffSize.X * scrBuffSize.Y,
pos, &NumberOfCharsWritten);
// 2) Create and start a process
// [using our screen buffer as stdout]
ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&startInfo, sizeof(STARTUPINFO));
startInfo.cb = sizeof(STARTUPINFO);
startInfo.hStdOutput = scrBuff;
startInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startInfo.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
0, NULL, NULL, &startInfo, &procInfo);
CloseHandle(procInfo.hThread);
// 3) Read from our screen buffer while process is alive
while(!quit)
{
// check if process is still alive or we could quit reading
GetExitCodeProcess(procInfo.hProcess, &procExitCode);
if(procExitCode != STILL_ACTIVE) quit = true;
// get actual state of screen buffer
GetConsoleScreenBufferInfo(scrBuff, &scrBuffInfo);
// check if screen buffer cursor moved since
// last time means new output was written
if (pos.X != scrBuffInfo.dwCursorPosition.X ||
pos.Y != scrBuffInfo.dwCursorPosition.Y)
{
// Get new content of screen buffer
// [ calc len from pos to cursor pos:
// (curY - posY) * lineWidth + (curX - posX) ]
DWORD len = (scrBuffInfo.dwCursorPosition.Y - pos.Y)
* scrBuffInfo.dwSize.X
+(scrBuffInfo.dwCursorPosition.X - pos.X);
char buffer[len];
ReadConsoleOutputCharacter(scrBuff, buffer, len, pos, &len);
// Print new content
// [ there is no newline, unused space is filled with '\0'
// so we read char by char and if it is '\0' we do
// new line and forward to next real char ]
for(int i = 0; i < len; i++)
{
if(buffer[i] != '\0') printf("%c",buffer[i]);
else
{
printf("\n");
while((i + 1) < len && buffer[i + 1] == '\0')i++;
}
}
// Save new position of already consumed data
pos = scrBuffInfo.dwCursorPosition;
}
// no new output so sleep a bit before next check
else Sleep(100);
}
// 4) Cleanup and end
CloseHandle(scrBuff);
CloseHandle(procInfo.hProcess);
return 0;
}
You can't.
Because not yet flushed data is owned by the program itself.
I think you can flush data to stderr or encapsulate a function of fgetc and fungetc to not corrupt the stream or use system("application.ext >>log") and then mmap log to memory to do things you want.

how to get back stdout after piping it with dup?

int mypipe[2];
pipe(mypipe);
int dupstdout=dup2(mypipe[1],1);
cout<<"hello";//not printed on terminal
fflush(stdout);
now how to print again on terminal or redirect mypipe[0] to stdout?
Best to save a copy of standard out and restore it later. If dup2 closes your last copy of stdout, you might not be able to get it back (e.g., no controlling terminal, chroot'd and no access to /dev nor /proc, stdout was an anonymous pipe to begin with, etc.).
int mypipe[2];
pipe(mypipe);
int savstdout=dup(1); // save original stdout
dup2(mypipe[1], 1);
printf("hello"); // not printed on terminal
fflush(stdout);
dup2(savstdout, 1); // restore original stdout
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
int mypipe[2];
pipe(mypipe);
int dupstdout=dup2(mypipe[1], 1);
printf("hello");//not printed on terminal
fflush(stdout);
close(dupstdout);
int fd = open("/dev/tty", O_WRONLY);
stdout = fdopen(fd, "w");
printf("hello again\n");
}
Anyway, it's better to not close stdout.
If a descriptor passed as a second argument to dup2() is already opened, dup2() closes it ignoring all errors. It's safer to use close() and dup() explicitly.

How to prevent buffer overflow in C/C++?

I am using the following code to redirect stdout to a pipe, then read all the data from the pipe to a buffer. I have 2 problems:
first problem: when i send a string (after redirection) bigger then the pipe's BUFF_SIZE, the program stops responding (deadlock or something).
second problem: when i try to read from a pipe before something was sent to stdout. I get the same response, the program stops responding - _read command stuck's ...
The issue is that i don't know the amount of data that will be sent to the pipe after the redirection.
The first problem, i don't know how to handle and i'll be glad for help. The second problem i solved by a simple workaround, right after the redirection i print space character to stdout. but i guess that this solution is not the correct one ...
#include <fcntl.h>
#include <io.h>
#include <iostream>
#define READ 0
#define WRITE 1
#define BUFF_SIZE 5
using namespace std;
int main()
{
int stdout_pipe[2];
int saved_stdout;
saved_stdout = _dup(_fileno(stdout)); // save stdout
if(_pipe(stdout_pipe,BUFF_SIZE, O_TEXT) != 0 ) // make a pipe
{
exit(1);
}
fflush( stdout );
if(_dup2(stdout_pipe[1], _fileno(stdout)) != 0 ) //redirect stdout to the pipe
{
exit(1);
}
ios::sync_with_stdio();
setvbuf( stdout, NULL, _IONBF, 0 );
//anything sent to stdout goes now to the pipe
//printf(" ");//workaround for the second problem
printf("123456");//first problem
char buffer[BUFF_SIZE] = {0};
int nOutRead = 0;
nOutRead = _read(stdout_pipe[READ], buffer, BUFF_SIZE); //second problem
buffer[nOutRead] = '\0';
// reconnect stdout
if (_dup2(saved_stdout, _fileno(stdout)) != 0 )
{
exit(1);
}
ios::sync_with_stdio();
printf("buffer: %s\n", buffer);
}
Your problem is that you are using blocking I/O calls, while both ends of the pipe are connected to the same process. If you don't know how much data there will be, this is just a deadlock situation waiting to happen.
printf is a blocking call, which means that it will not return until all data has been written to the output device (the pipe in this case), or until a write error is signalled (for example, the other end of the pipe is closed).
_read works similarly. It only returns when it has a full buffer worth of data or it knows that the end of the input has been reached (which can be signalled by closing the write-end of the pipe).
The only ways around this are
to use non-blocking I/O (which is not feasible if you don't have access to the code that calls printf), or
to ensure the reading and writing happens in different processes or threads, or
to use a temporary file for buffering, instead of the buffer of a pipe.
Pipes are unidirectional. Ie. you can either write to a pipe (x)or you can read from it.
To simulate a pipeline, try the following (the below is C, not C++):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc)
{
int pfds[2];
pipe(pfds);
if (!fork()) {
close(1); /* close stdout, check for errors */
dup(pfds[1]); /* make stdout same as pfds[1], dup reuses lowest fd */
close(pfds[0]); /* not needed */
execlp("ls", "ls", NULL); /* or write() in whatever way you want */
} else {
close(0); /* close stdin, check for errors please! */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* not needed on this end */
execlp("wc", "wc", "-l", NULL); /* or read() */
}
return 0;
}
[edit] By the way, your code does not overflow a buffer. Its only relation to buffer overflow is that you're reading into a statically allocated array...if you read() more than sizeof buffer elements, then you'll run into problems.
You must use non-blocking I/O if you don't want read or write to be blocked in this case.

freopen: reverting back to original stream

I needed to forward stdout to different files to separate some prints produced and the reverting back to normal stdout.
I used freopen to switch to the file in this way:
char name[80];
memset(name, 0, 80);
strcpy(name, "./scripts/asm/");
strcat(name, m_func->m_name->m_value);
strcat(name, ".shasm");
freopen(name, "w", stdout);
And it actually works, but at the end of the process (mind that stdout is redirected many times in the previous same way) I'm not able to revert it to original stdout. I tried the following:
freopen("/dev/stdout", "w", stdout);
but it doesn't seem to work.. just for information I'm developing on macosx.
What should I do?
Thanks in advance
This can be achieved using fileno, dup and dup2 calls. I have tried this on linux not sure whether this will work on mac but I am sure you will get some equivalent functions for your setup. See if this sample code works for you. Sorry for lack of error-handling in the code. :)
#include <stdio.h>
main()
{
int fd;
fpos_t pos;
printf("stdout, ");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen("stdout.out", "w", stdout);
f();
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); /* for C9X */
printf("stdout again\n");
}
f()
{
printf("stdout in f()");
}
This seems like a roundabout way of solving your problem. Why not just open each file with fopen() and then writing to its FILE * with fputs, fprintf, fwrite etc? No need to redirect stdout.