Redericting stdout and stdin - c

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;
}

Related

setbuf() - printf(), and write()

this is my first step on Stackoverflow !
So, I'm trying to use setbuf() to redirect stdout into a char buffer[BUFSIZ]. It works perfectly when I use printf(), but not at all when I use the system call write().
Here is an example of code :
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buffer[BUFSIZ];
freopen("/dev/null", "a", stdout);
setbuf(stdout, buffer);
printf("This works\n");
write(stdout->_file, "This doesn't.\n", 14);
fflush(stdout);
freopen("/dev/tty", "a", stdout);
printf("Buffer content :\n%s", buffer);
return 0;
}
And the output is
Buffer content :
This works
Do you have any idea why ?
Because for now I don't see how this work, I'll pipe stdout to stdin and then read the result - not the cleanest way of doing this I think.
Thank you, and have a nice day !
The write function is a low-level POSIX function that operates at a lower-level than the C standard output functions.
By using write directly you bypass the stdio buffering. If you want to use the buffer use the standard C fwrite function instead.
Also note that stdout is a FILE*, and FILE is an opaque data structure. You should never attempt to use members of it directly.

mkfifo make 2 processes talk to each other

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().

How to write redirected output to file inside loop in C?

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 */
}

freopen stdout and console

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;
}

How to redirect the output back to the screen after freopen("out.txt", "a", stdout)

#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!");

Resources