Given the following function:
freopen("file.txt","w",stdout);
Redirects stdout into a file, how do I make it so stdout redirects back into the console?
I will note, yes there are other questions similar to this, but they are about linux/posix. I'm using windows.
You can't assigned to stdout, which nullifies one set of solutions that rely on it.
dup and dup2() are not native to windows, nullifying the other set. As said, posix functions don't apply (unless you count fdopen()).
You should be able to use _dup to do this
Something like this should work (or you may prefer the example listed in the _dup documentation):
#include <io.h>
#include <stdio.h>
...
{
int stdout_dupfd;
FILE *temp_out;
/* duplicate stdout */
stdout_dupfd = _dup(1);
temp_out = fopen("file.txt", "w");
/* replace stdout with our output fd */
_dup2(_fileno(temp_out), 1);
/* output something... */
printf("Woot!\n");
/* flush output so it goes to our file */
fflush(stdout);
fclose(temp_out);
/* Now restore stdout */
_dup2(stdout_dupfd, 1);
_close(stdout_dupfd);
}
An alternate solution is:
freopen("CON","w",stdout);
Per wikipedia "CON" is a special keyword which refers to the console.
After posting the answer I have noticed that this is a Windows-specific question. The below still might be useful in the context of the question to other people. Windows also provides _fdopen, so mayble simply changing 0 to a proper HANDLE would modify this Linux solution to Windows.
stdout = fdopen(0, "w")
#include <stdio.h>
#include <stdlib.h>
int main()
{
freopen("file.txt","w",stdout);
printf("dupa1");
fclose(stdout);
stdout = fdopen(0, "w");
printf("dupa2");
return 0;
}
take note that the filedescriptors for stdin, stdout, stderr (0,1,2) are not nessesarily the same as the 'special variables' printf() and the likes use. although in most cases they output to the same devices upon program start. (not if you start changing things in the middle of your program, or tty redirects are in place). stdin stdout stderr are FILE * pointers. both concepts need to be 'redirected' seperately from each other with their own methods... 'dup2' is for duplicating file descriptors. not FILE pointers. for FILE * pointers such as stdin, stdout, stderr... 'freopen()'.. but that will literally only affect printf and derivatives.
This works to me
#include <stdio.h>
int main()
{
FILE* original_stdout = stdout;
stdout = fopen("new_stdout.txt", "w");
printf("ciao\n");
fclose(stdout);
stdout = original_stdout;
printf("a tutti\n");
return 0;
}
Related
I am trying to write 2 programs that will talk to each other using fifo pipe.
I used the example here (section 5.2), but I changed the mknod there to mkfifo and tried to change gets to fgets.
This is the code (of one program which writes into the fifo):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /*mkfifo, open */
#include <sys/wait.h>
#include <sys/stat.h> /* mkfifo, open */
#include <fcntl.h> /*open */
#define FIFO_PATH "/home/hana/Desktop"
#define BUFFER_SIZE 300
int main()
{
char buffer[BUFFER_SIZE];
int fd;
int wStatus;
mkfifo(FIFO_PATH, 666);
printf("waiting for readers\n");
fd = open(FIFO_PATH, O_RDWR);
while (fgets(buffer, BUFFER_SIZE, fd), !feof(stdin))
{
if ((wStatus = write(fd, buffer, strlen(buffer))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", wStatus);
}
return 0;
}
I get a compilation error: passing argument 3 of fgets makes pointer from integer.
So fgets is expecting FILE* and not file descriptor.
What should I do? change something so that fgets works? use another function?
I am compiling with gcc (ansi, pedantic).
Thanks
The answer from whjm is the cause of your error diagnostic, but I think you probably meant
fgets(buffer, BUFFER_SIZE, stdin)
// ^^^^^
It doesn't make sense that you would read from a pipe and then immediately write the same thing back to the pipe. Also, if you never read from stdin, feof(stdin) will never be true.
Also, with fgets just check for a null result and then outside the loop, do the check for eof:
while (fgets(...) != NULL)
{
...
}
if (!feof(stdin))
{
// error handling
}
mkfifo() just creates special node in filesystem. And you are free to open it in any way. Actually there are two alternatives - POSIX "non-buffered" I/O: open()/write()/read() or standard buffered I/O: fopen()/fread()/fwrite(). First family operates on file descriptors while second one uses so called file streams: FILE. You can not mix these APIs freely. Just choose one and stick to it.
Standard I/O library offers some useful extra capabilities comparing to low-level non-buffered I/O. Like fgets() that you're trying to use. In this situation would be reasonable to use standard streams and replace open() with:
FILE* stream = fopen(FIFO_PATH, "r+");
Thus program will use FILE* instead of plain file descriptors. Also write() need to be changed to fwrite() immediately followed by fflush() to guarantee that written data are passed to FIFO.
P.S. In case of necessity it is possible to "wrap" low-level descriptors returned by open()(or something other) with standard FILE*. See fdopen(). But it is much like a workaround to use standard I/O API with special file objects that can not be opened with fopen().
I would like to redericting stdout, stderr to file and stdin from char*. My goal is make it in C.
When i run this code:
int main(){
stdout=fopen("/home/user/file.txt","w");
printf("aaaa");
printf("\nbbbb");
system("/bin/bash");
sprintf("stdin","exit");
return 0;
}
File didn't have for some string and bash take argument from console. Where is bug??
You don't want to assign to stdout. Instead, you (probably) want to use freopen, in your case like: freopen("/home/user/file.txt","w", stdout);
If/when you're doing all the processing internally, you're generally better off writing the code to receive a FILE * as a parameter, and passing the correct value. That doesn't work when you have external code that writes directly to stdout though.
Edit: I should probably also mention one other serious problem with freopen -- no method is provided to restore it to the previous stream. It's up t you to use freopen again, and know the path that will write to the console (or whatever).
stdout should not be used as an lvalue. Try the fprintf() function instead of printf() to get the desired effect.
As for redirecting the stdout from bash, can you not just call it with /usr/bin/bash >> /home/user/file.txt?
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
int main(void){
int ret;
FILE *fp;
int stdout_bk;
stdout_bk = dup(fileno(stdout));
fp=fopen("/home/user/file.txt","w");
dup2(fileno(fp), fileno(stdout));
ret = system("/bin/bash");
//flushall();//for vc
fflush(stdout);//for gcc
fclose(fp);
dup2(stdout_bk, fileno(stdout));//restore
return 0;
}
I am writing a C program on unix which should redirect it's output to the file, and write to it some text every second in infinite loop:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
int outDes = open("./output.txt", O_APPEND | O_WRONLY);
dup2(outDes, 1);
while(1) {
printf("output text\n");
sleep(1);
}
}
But it writes nothing to the output file. I tried to change the 'while' loop for 'for' with 10 loops, and I found that it writes all 10 lines to the file at once after the series ends. It is not very good for me, while I need to have an infinite loop.
When I'm not redirecting output, it is all ok, and new line appears every second on terminal.
I also tried to put one
printf("text\n");
before redirecting output to the file. Then the program wrote the lines to the file in real time, which is good, but wrote there the first (non redirected) line too. I don't want this first line in my output file, I don't understand how it could be written into file when output was not redirected yet (maybe redirect remained there since last run?), and how it could cause that the lines are suddenly written in real time.
Can anyone explain me how does it work?
You are not checking the return value of open() and dup2(). If either open() or dup2() failed, it won't write anything in output.txt.
if (outDes < -1) {
perror("open");
return 1;
}
if (dup2(outDes, 1) == -1) {
perror("dup2");
return 1;
}
stdio streams are buffered, and the writes happen in memory before being done on the real file description.
Try adding a fflush(stdout) after printf().
You're running afoul of a poorly documented DWIMmy feature in many Unix C libraries. The first time you write to stdout or stderr, the library probes the underlying file descriptor (with isatty(3)). If it's a (pseudo-)terminal, the library puts the FILE in "line buffered" mode, meaning that it'll buffer input until a newline is written and then flush it all to the OS. But if the file descriptor is not a terminal, it puts the FILE in "fully buffered" mode, where it'll buffer something like BUFSIZ bytes of output before flushing them, and pays no attention to line breaks.
This is normally the behavior you want, but if you don't want it (as in this case), you can change it with setvbuf(3). This function (although not the behavior I described above) is ISO standard C. Here's how to use it in your case.
#include <stdio.h>
#include <unistd.h>
int
main(void)
{
if (freopen("output.txt", "a", stdout)) {
perror("freopen");
return 1;
}
if (setvbuf(stdout, 0, _IOLBF, 0)) {
perror("setvbuf");
return 1;
}
for (;;) {
puts("output text");
sleep(1);
}
/* not reached */
}
I actually have a solution to this problem, but I'm wondering if there is a slicker one.
I have the need to load in a library to my utility using dlopen and then call one of the functions.
Unfortunately, the function spews a whole bunch of information out onto STDOUT and this I do not want.
I have a solution that is non-portable and I'm wondering if there's a better, more generic solution that I could use.
Here's what I have (NB: This is C) :
/*
* Structure for retaining information about a stream, sufficient to
* recreate that stream later on
*/
struct stream_info {
int fd;
fpos_t pos;
};
#define STDOUT_INFO 0
#define STDERR_INFO 1
struct stream_info s_info[2];
point_stream_to_null(stdout, &s_info[STDOUT_INFO]);
point_stream_to_null(stderr, &s_info[STDERR_INFO]);
void *output = noisy_function();
reset_stream(stderr, &s_info[STDERR_INFO]);
reset_stream(stdout, &s_info[STDOUT_INFO]);
/*
* Redirects a stream to null and retains sufficient information to restore the stream to its original location
*** NB ***
* Not Portable
*/
void point_stream_to_null(FILE *stream, struct stream_info *info) {
fflush(stream);
fgetpos(stream, &(info->pos));
info->fd = dup(fileno(stream));
freopen("/dev/null", "w", stream);
}
/*
* Resets a stream to its original location using the info provided
*/
void reset_stream(FILE *stream, struct stream_info *info) {
fflush(stream);
dup2(info->fd, fileno(stream));
close(info->fd);
clearerr(stream);
fsetpos(stream, &(info->pos));
}
Any suggestions?
I have a suggestion, which lets you use the preprocessor for portability, or perhaps "portability".
If you try something like
#if defined __unix__
#define DEVNULL "/dev/null"
#elif defined _WIN32
#define DEVNULL "nul"
#endif
(ignoring other OSes, else case, error directive, etc.)
and then reopen the file as before
FILE *myfile = freopen(DEVNULL, "w", stream);
then that may give you what you want.
I haven't tried this at home, though. The "nul" file exists; see /dev/null in Windows. And you can get predefined macros at "Pre-defined C/C++ Compiler Macros".
You could try using setvbuf to set stdout to have a very large buffer and be fully buffered. Then, after every call to noisy_function, clear out the buffer before flushing it to the stream. I think this invokes undefined behavior though.
Another way would be to redirect stdout to a temp file, like with this macro function.
#include <stdio.h>
#define QUIET_CALL(noisy) { \
FILE* tmp = stdout;\
stdout = tmpfile();\
(noisy);\
fclose(stdout);\
stdout = tmp;\
}
int main(){
QUIET_CALL(printf("blah blah"));
printf("bloo bloo\n");
return 0;
}
For Windows console applications:
freopen("NUL", "w", stdout); // redirect stdout to the windows version of /dev/null
NoisyDllFunction();
freopen("CON", "w", stdout); // redirect stdout back to the console
Worked for me.
In Windows you can redirect streams too.
See http://support.microsoft.com/kb/110930/en-us
Unfortunately, freopening to a platform-specific null filename is about the closest you can get in standard C. You could also consider modifying the library itself to not spew so much output on stdout.
That said, in practice, the only OSes you need to worry about are either unix-based (including MacOS) or Windows - in the case of Windows, stdout is hidden by default, so you can just skip the redirection step, and for *nix you have the code already.
#include <stdio.h>
int main() {
printf("This goes to screen\n");
freopen("out.txt", "a", stdout);
printf("This goes to out.txt");
freopen("/dev/stdout", "a", stdout);
printf("This should go to screen too, but doesn't\n");
return 0;
}
I call freopen to redirect the stdout to out.txt then I print something on the file, now I want to redirect it back to the screen, but freopen("/dev/stdout", "a", stdout); doesn't work. Is there any way to do that using ANSI C or POSIX system calls?
I can't think of a way to do this in a cross-platform manner, but on GNU/Linux systems (and maybe other POSIX-compliant ones, too) you can freopen ("/dev/tty", "a", stdout). Is this what you were trying to do?
Unfortunately, there doesn't seem to be a good way:
http://c-faq.com/stdio/undofreopen.html
The best recommendation is not to use freopen in this circumstance.
Generally speaking, you can't. You have closed the file, which could've been pipe or whatever. It's not reopenable. You might have saved stdout value, then assign some fopen to it and then close it and copy the old value back. Example:
FILE *o = stdout;
stdout=fopen("/tmp/crap.txt","a");
printf("Oh no!\n");
fclose(stdout);
stdout = o;
Mike Weller suggested below in comments that stdout might not always be writable. In this case something like that might help:
int o = dup(fileno(stdout));
freopen("/tmp/crap.txt","a",stdout);
printf("Oh no!\n");
dup2(o,fileno(stdout));
close(o);
Another edit: if you're using it to redirect output from the child process like your comment elsewhere suggest, you can redirect it after the fork.
Use fdopen() and dup() as well as freopen().
int old_stdout = dup(1); // Preserve original file descriptor for stdout.
FILE *fp1 = freopen("out.txt", "w", stdout); // Open new stdout
...write to stdout... // Use new stdout
FILE *fp2 = fdopen(old_stdout, "w"); // Open old stdout as a stream
...Now, how to get stdout to refer to fp2?
...Under glibc, I believe you can use:
fclose(stdout); // Equivalent to fclose(fp1);
stdout = fp2; // Assign fp2 to stdout
// *stdout = *fp2; // Works on Solaris and MacOS X, might work elsewhere.
close(old_stdout); // Close the file descriptor so pipes work sanely
I'm not sure whether you can do the assignment reliably elsewhere.
Dubious code that does actually work
The code below worked on Solaris 10 and MacOS X 10.6.2 - but I'm not confident that it is reliable. The structure assignment may or may not work with Linux glibc.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("This goes to screen\n");
int old_stdout = dup(1); // Consider dup(STDOUT_FILENO) or dup(fileno(stdout))
FILE *fp1 = freopen("out.txt", "a", stdout);
printf("This goes to out.txt\n");
fclose(stdout);
FILE *fp2 = fdopen(old_stdout, "w");
*stdout = *fp2; // Unreliable!
printf("This should go to screen too, but doesn't\n");
return 0;
}
You can't say you weren't warned — this is playing with fire!
If you're on a system with the /dev/fd file system, you could create the name of the file implied by the file descriptor returned from dup() with sprintf(buffer, "/dev/fd/%d", old_stdout) and then use freopen() with that name. This would be a lot more reliable than the assignment used in this code.
The better solutions either make the code use 'fprintf(fp, ...)' everywhere, or use a cover function that allows you set your own default file pointer:
mprintf.c
#include "mprintf.h"
#include <stdarg.h>
static FILE *default_fp = 0;
void set_default_stream(FILE *fp)
{
default_fp = fp;
}
int mprintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (default_fp == 0)
default_fp = stdout;
int rv = vfprintf(default_fp, fmt, args);
va_end(args);
return(rv);
}
mprintf.h
#ifndef MPRINTF_H_INCLUDED
#define MPRINTF_H_INCLUDED
#include <stdio.h>
extern void set_default_stream(FILE *fp);
extern int mprintf(const char *fmt, ...);
#endif
Clearly, you can create an mvprintf() and other functions as needed.
Example use of mprintf()
Then, in place of the original code, you can use:
#include "mprintf.h"
int main()
{
mprintf("This goes to screen\n");
FILE *fp1 = fopen("out.txt", "w");
set_default_stream(fp1);
mprintf("This goes to out.txt\n");
fclose(fp1);
set_default_stream(stdout);
mprintf("This should go to screen too, but doesn't\n");
return 0;
}
(Warning: untested code - confidence level too high. Also, all code written assuming you use a C99 compiler, primarily because I declare variables when I first need them, not at the beginning of the function.)
Caution:
Note that if the original program is invoked as ./original_program > file or ./original_program | grep something (with redirected output) or is run from a cron job, then opening /dev/tty is not usually appropriate as a way to reopen standard output because the original standard output was not the terminal.
Also, note that if the redirection of standard output is used prior to forking and execing a child program and the original standard output is reinstated in the parent, then the sequence of operations is wrong. You should fork and then adjust the I/O of the child (only), without modifying the parent's I/O at all.
On Windows, you can open "CONOUT$".
freopen("test.txt", "w", stdout);
printf("this goes to test.txt");
freopen("CONOUT$", "w", stdout);
printf("this goes to the console\n");
This probably doesn't work if stdout is redirected to start with.
The following code (SwapIOB) is used in Testbenches that want to store
the stdout stream for comparison to an expected results file.
Background: File streams are managed using an _IOB structure that is stored in an array of 20 _IOB entries. This includes stdout stream. The IOBs are stored in an array. When a file is created the application code gets a ptr to an element in that array. The application code then passes that ptr to the OS for processing I/O calls. Thus, the OS does NOT itself contain or rely on its own pointers to the application's IOB.
Requirement: When running a testbench the stdout messages issued by an application should be re-directed to a file. However, after the module under test has completed then stdout messages should be re-redirected to the console.
This routine was tested and is currently used on Windows XP/Pro system.
void SwapIOB(FILE *A, FILE *B) {
FILE temp;
// make a copy of IOB A (usually this is "stdout")
memcpy(&temp, A, sizeof(struct _iobuf));
// copy IOB B to A's location, now any output
// sent to A is redirected thru B's IOB.
memcpy(A, B, sizeof(struct _iobuf));
// copy A into B, the swap is complete
memcpy(B, &temp, sizeof(struct _iobuf));
} // end SwapIOB;
Application code uses SwapIOB() similar to:
FILE *fp;
fp = fopen("X", "w");
SwapIOB(stdout, fp);
printf("text to file X");
SwapIOB(stdout, fp);
fclose(fp);
printf("text to console works, again!");