Is there a API (like dup) to duplicate fstream so it can - c

I want to write a stream into one FILE *fp at the same time the stream should be copied onto another fp too is there a better way to write my debug function by eliminating one fprintf?
const int logflag=1;
#define debug(args ...) if (logflag) { FILE *flog = fopen("test.log", "a+"); fprintf( flog, args); fclose(flog); } fprintf(stderr, args);
int main()
{
debug("test"); // writes test into both stderr and flog
debug("test2");
}

The short answer is no, it's two different file pointers and you can only write to one at a time. Actually, dup still doesn't help you because it closes the duplicated file descriptor:
"dup2() makes newfd be the copy of oldfd, closing newfd first if necessary"
from the dup2 man-pages
However, if your goal is to have both a log to the screen and to a file, you are better served by using the tools Linux already provides you. A generally good practice (I don't remember the source for this) is to have a program print its output and debugging to a stdout/stderr and let the calling user determine how to handle the output.
Following this, if all of your output goes to stderr, you can do the following when executing the program:
$ ./program 2>&1 | tee file.log

Related

Redirecting pipe from file to screen linux c

I have the following code (found it on internet)
FILE *fp;
fp=fopen("text.txt","w");
int fd=open("text.txt",O_WRONLY,S_IWUSR);
dup2(fd,1);
This code redirect the pipe from screen to a file named text.txt.
Now i need to do the opposite. I want to change the pipe writing from this file to the screen.
Does anyone have an idea? Thank you
That code only works because something is pushing data into the pipe. That would not be the case if you simply reversed the wiring of guzintas and comzoutas. You'll need to open the text file for reading and then read the file into memory and write it to the screen. There's lots of examples of source code out there for clones of cat.exe, go look on GitHub for the code.
Here's a very simple example:
#include <stdio.h>
void spewfile(FILE *fp)
{
char buf[BUFSIZ];
while(fgets(buf, sizeof(buf), fp))
fputs(buf, stdout);
}
On Linux, you can write to /dev/tty, but this is not equivalent to restoring writing to stdout, since you probably won't be able to redirect output from the calling program (Not sure - to be tested), and by the way, I'm not sure this is portable to other Unix based systems.
int fd=open("/dev/tty",O_WRONLY);
dup2(fd,1);
Otherwise, you should dup your file descriptor 1 to another one before the first redirection, so that you would be able to restore it later.
/* save fd 1 */
int sav=dup(1);
/* redirect to file */
int fd=open("text.txt",O_WRONLY,S_IWUSR);
dup2(fd,1);
/* done anything you wanted here (redirected to text.txt) */
/* ... */
/* revert redirection */
dup2(sav,1);
/* do anything you want here (having reverted the redirection back to stdout) */
/* ... */
By the way, one should probably avoid using both buffered (fopen) and unbuffered (open) I/O at the same time. This will cause problems since the buffered I/O are not informed of what you do at the same time with the unbuffered I/O.

How to read the cmd output as Input in C using System() [duplicate]

I've got a utility that outputs a list of files required by a game. How can I run that utility within a C program and grab its output so I can act on it within the same program?
UPDATE: Good call on the lack of information. The utility spits out a series of strings, and this is supposed to be portable across Mac/Windows/Linux. Please note, I'm looking for a programmatic way to execute the utility and retain its output (which goes to stdout).
As others have pointed out, popen() is the most standard way. And since no answer provided an example using this method, here it goes:
#include <stdio.h>
#define BUFSIZE 128
int parse_output(void) {
char *cmd = "ls -l";
char buf[BUFSIZE];
FILE *fp;
if ((fp = popen(cmd, "r")) == NULL) {
printf("Error opening pipe!\n");
return -1;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Do whatever you want here...
printf("OUTPUT: %s", buf);
}
if (pclose(fp)) {
printf("Command not found or exited with error status\n");
return -1;
}
return 0;
}
Sample output:
OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c
For simple problems in Unix-ish environments try popen().
From the man page:
The popen() function opens a process by creating a pipe, forking and invoking the shell.
If you use the read mode this is exactly what you asked for. I don't know if it is implemented in Windows.
For more complicated problems you want to look up inter-process communication.
popen is supported on Windows, see here:
http://msdn.microsoft.com/en-us/library/96ayss4b.aspx
If you want it to be cross-platform, popen is the way to go.
Well, assuming you're on a command line in a windows environment, you can use pipes or command line redirects. For instance,
commandThatOutputs.exe > someFileToStoreResults.txt
or
commandThatOutputs.exe | yourProgramToProcessInput.exe
Within your program, you could use the C standard input functions to read the other programs output (scanf, etc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp . You could also use the file example and use fscanf. This should also work in Unix/Linux.
This is a very generic question, you may want to include more details, like what type of output it is (just text, or a binary file?) and how you want to process it.
Edit: Hooray clarification!
Redirecting STDOUT looks to be troublesome, I've had to do it in .NET, and it gave me all sorts of headaches. It looks like the proper C way is to spawn a child process, get a file pointer, and all of a sudden my head hurts.
So heres a hack that uses temporary files. It's simple, but it should work. This will work well if speed isn't an issue (hitting the disk is slow), or if it's throw-away. If you're building an enterprise program, looking into the STDOUT redirection is probably best, using what other people recommended.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE * fptr; // file holder
char c; // char buffer
system("dir >> temp.txt"); // call dir and put it's contents in a temp using redirects.
fptr = fopen("temp.txt", "r"); // open said file for reading.
// oh, and check for fptr being NULL.
while(1){
c = fgetc(fptr);
if(c!= EOF)
printf("%c", c); // do what you need to.
else
break; // exit when you hit the end of the file.
}
fclose(fptr); // don't call this is fptr is NULL.
remove("temp.txt"); // clean up
getchar(); // stop so I can see if it worked.
}
Make sure to check your file permissions: right now this will simply throw the file in the same directory as an exe. You might want to look into using /tmp in nix, or C:\Users\username\Local Settings\Temp in Vista, or C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. I think the /tmp will work in OSX, but I've never used one.
In Linux and OS X, popen() really is your best bet, as dmckee pointed out, since both OSs support that call. In Windows, this should help: http://msdn.microsoft.com/en-us/library/ms682499.aspx
MSDN documentation says
If used in a Windows program, the _popen function returns an invalid file pointer that causes the program to stop responding indefinitely. _popen works properly in a console application. To create a Windows application that redirects input and output, see Creating a Child Process with Redirected Input and Output in the Windows SDK.
You can use system() as in:
system("ls song > song.txt");
where ls is the command name for listing the contents of the folder song and song is a folder in the current directory. Resulting file song.txt will be created in the current directory.
//execute external process and read exactly binary or text output
//can read image from Zip file for example
string run(const char* cmd){
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[262144];
string data;
string result;
int dist=0;
int size;
//TIME_START
while(!feof(pipe)) {
size=(int)fread(buffer,1,262144, pipe); //cout<<buffer<<" size="<<size<<endl;
data.resize(data.size()+size);
memcpy(&data[dist],buffer,size);
dist+=size;
}
//TIME_PRINT_
pclose(pipe);
return data;
}

How to change stdout via program

Program:
#include<stdio.h>
void main()
{
printf("Hello world\n");
}
The above program print the output as "Hello world" in stdout(Terminal). But, I need the output of the program in some other
file like "output.txt". So, is there any way to change the standard output of the process to some other file via programatically.
You don't need all this stdout changing business. Everything you have to do is to open a file and then write to it. Use fopen and fprintf to do it.
You might want to use freopen(3) on stdout but it would close stdout.
You could use dup2(2) like:
int newfd = open("/tmp/someoutput.txt", O_WRONLY|O_CREAT, 0640);
if (newfd<0) {
perror("/tmp/someoutput.txt"); exit(EXIT_FAILURE); };
if (dup2(STDOUT_FILENO, newfd)) {
perror("dup2"); exit(EXIT_FAILURE); }
But as commented by David Heffernan you really want to use redirections in your shell.
IMHO redirecting STDOUT_FILENO like above smells bad.
A possible way might be to declare a global
FILE* myout = stdout;
and use always fprintf(myout, instead of printf( and perhaps sometimes doing myout = fopen("/tmp/someoutput.txt"); with a test!
At least inform the user that you are redirecting his stdout (perhaps by some message to stderr etc...) !
You can make use of fprintf to write in a file .Open file in w or a mode and then use fprintf to write in it .

Why is my popen failing

My c code is
size_t n=0;
char *str = (char *)malloc(sizeof(char)* 1000)
FILE *fp = popen(" cat /conf/a.txt" ,"r" );
// my program comes in this function only if /conf/a.txt exists
getline(&str, &n, fp); <== crash if fp is null
My debugger shows that sometimes i get fp as null and hence my program crashes at line 6 . Sometimes i get valid pointere and it passes .
What is it , that controls this behaviour . I can't find problem in above code . Some help is appreciated .
I know I can have a check of fp==null but that is not my question . I just want to know , knowing that file is definitely present why is fp coming as null in some scenarios .
man of popen says The popen() function returns NULL if the fork(2) or pipe(2) calls fail, or if it cannot allocate memory.
i checked after crash and system is having enough memory ..
strerror and errno are your friends.
Example from the C++ references linked:
/* strerror example : error list */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("Error opening file unexist.ent: %s\n",strerror(errno));
return 0;
}
Example output:
Error opening file unexist.ent: No such file or directory
Using this method of checking errno after a failure will allow you to better diagnose your issue as it will print a more specific error message. There are many reasons a file can't be opened: no permission, bad path, file is locked from another process, IO errors during reading, etc. Ultimately your question seems to be asking why the open failed. Using these tools will answer that for you.
Update For Tag Change:
I've referenced and linked to C++ resources, but sterror and errno are both available in C as well by including errno.h.
popen() also fails if too many file handles are open in one process. I had one case in a server app, that was scanning one directory periodically for files.There was one scenario were no fclose call was made. So after some hours we reached the limit of 1024 open file handles on from that moment consecutive popen() calls would fail.
You can use ps -aux | grep {PROC_NAME} to retrieve the process id.
Then use sudo ls -l /proc/{PROC_ID}/fd to see the list of open file descriptors.

Multiple processes accessing the same file

Is it alright for multiple processes to access (write) to the same file at the same time? Using the following code, it seems to work, but I have my doubts.
Use case in the instance is an executable that gets called every time an email is received and logs it's output to a central file.
if (freopen(console_logfile, "a+", stdout) == NULL || freopen(error_logfile, "a+", stderr) == NULL) {
perror("freopen");
}
printf("Hello World!");
This is running on CentOS and compiled as C.
Using the C standard IO facility introduces a new layer of complexity; the file is modified solely via write(2)-family of system calls (or memory mappings, but that's not used in this case) -- the C standard IO wrappers may postpone writing to the file for a while and may not submit complete requests in one system call.
The write(2) call itself should behave well:
[...] If the file was
open(2)ed with O_APPEND, the file offset is first set to the
end of the file before writing. The adjustment of the file
offset and the write operation are performed as an atomic
step.
POSIX requires that a read(2) which can be proved to occur
after a write() has returned returns the new data. Note that
not all file systems are POSIX conforming.
Thus your underlying write(2) calls will behave properly.
For the higher-level C standard IO streams, you'll also need to take care of the buffering. The setvbuf(3) function can be used to request unbuffered output, line-buffered output, or block-buffered output. The default behavior changes from stream to stream -- if standard output and standard error are writing to the terminal, then they are line-buffered and unbuffered by default. Otherwise, block-buffering is the default.
You might wish to manually select line-buffered if your data is naturally line-oriented, to prevent interleaved data. If your data is not line-oriented, you might wish to use un-buffered or leave it block-buffered but manually flush the data whenever you've accumulated a single "unit" of output.
If you are writing more than BUFSIZ bytes at a time, your writes might become interleaved. The setvbuf(3) function can help prevent the interleaving.
It might be premature to talk about performance, but line-buffering is going to be slower than block buffering. If you're logging near the speed of the disk, you might wish to take another approach entirely to ensure your writes aren't interleaved.
This answer was incorrect. It does work:
So the race condition would be:
process 1 opens it for append, then
later process 2 opens it for append, then
later still 1 writes and closes, then
finally 2 writes and closes.
I'd be impressed if that 'worked' because it isn't clear to me what
working should mean. I assume 'working' means all of the bytes written
by the two processes are inthe log file? I'd expect that they both
write starting at the same byte offset, so one will replace the others
bytes. It will all be okay upto and including step 3. and only show up
as a problem at step 4, Seems like an easy test to write: open getchar
... write close.
Is it critical that they can have the file open simultaneously? A
more obvious solution if the write is quick, is to open exclusive.
For a quick check on your system, try:
/* write the first command line argument to a file called foo
* stackoverflow topic 9880935
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main (int argc, const char * argv[]) {
if (argc <2) {
fprintf(stderr, "Error: need some text to write to the file Foo\n");
exit(1);
}
FILE* fp = freopen("foo", "a+", stdout);
if (fp == NULL) {
perror("Error failed to open file\n");
exit(1);
}
fprintf(stderr, "Press a key to continue\n");
(void) getchar(); /* Yes, I really mean to ignore the character */
if (printf("%s\n", argv[1]) < 0) {
perror("Error failed to write to file: ");
exit(1);
}
fclose(fp);
return 0;
}

Resources