Usage of stderr in C - c

I am trying to use stderr but i am totally confused with respect to its usage.I was about to reply to a question asked here but when i think to try it first , i find myself stucked.
I read about stderr in this link,and as per the information i tried to use it like this
FILE *stderr;
stderr = fopen("<path to file>","w");
.....//some code and conditions
fprintf(stderr,"found a error here");
using this gives me a seg fault, which i wasn't able to figure out why?
then i used freopen(), then also i get the seg fault.Is stderr byitself send the standard err if any to some default file instead of stdout.
Here is my code in which i am only trying to use stderr as any other FILE * pointer.May i am totlly takingit as wrong way to execute.Or it only write standard compiler errors to some default file.Need help.
#include<stdio.h>
#include<string.h>
#include<time.h>
FILE *stderr;
int main()
{
time_t start,end;
volatile long unsigned counter;
start = time(NULL);
for(counter = 0; counter < 500000000; counter++)
{}
int i;
char str1[]="XXXXXXX-XXXXXXXXX-YYYYYYYY-TTTTTT";
char str2[]="pro1_0.0";
char str3[]="CC";
char str4[]="ZZ";
char str5[]="QQ";
char serialstring[100];
stderr = fopen("path to file","w");
//freopen("llog.out","w",stderr);
printf("enter a serial string:");
scanf("%s",serialstring);
if((strstr(serialstring,str1)))
{
printf("String1 matched\n");
if((strstr(serialstring,str2)))
{
fprintf(stderr,"str2 matched\n"); //it is where i tried using fprintf and stderr, rest of code is working pretty file
if((strstr(serialstring,str3)))
{
printf("str3 matched\n");
}
else if((strstr(serialstring,str4)))
{printf("str4 matched\n");}
else if((strstr(serialstring,str5)))
{printf("str5 matched\n");
for(i=232;i<290;i++)
{
printf("Sending some values: %d\n",i);}}
}
else{printf("str2 not matched\n");}
}
else{printf("str1 not matched\n");}
end = time(NULL);
printf("The loop used %f seconds.\n", difftime(end, start));
return 0;
}

You are not supposed to try to override stderr yourself. Just use it. It's provided to you by the program that's running your program. If your program is being run interactively from a shell on a terminal, then both stdout and stderr normally go to the terminal, but there are plenty of ways that could be overridden. The most common way it's overridden is that the caller has redirected stdout to a file, to save the output, but left stderr connected to the terminal so that the user can see status/error messages.

Use dup2():
int fd = open("mylog.txt", O_RDWR | O_APPEND | O_CREAT);
if (fd < 0) {
printf("Cannot open mylog.txt!\n");
exit(1);
}
if (dup2(fd, STDERR_FILENO) < 0) {
printf("Cannot redirect stderr!\n");
exit(1);
}
From this point on, any writes to stderr will go to "mylog.txt".
You can use similar approach to redirect stdout as well - just use STDOUT_FILENO.

Related

Segmentation fault while system() in C

I want to use the "base64" script of linux to encode the data and get it in C.
When I try to compile
char a[200];
strcpy(a, "Hello");
printf("%s", a);
I get the output
Hello
Now whenever I try the code
char a[200];
strcpy(a, system("echo Hello | base64"));
printf("%s", a);
I get the output
aGVsbG8K
Segmentation fault
Even when I remove the "printf" statement, I get the same
aGVsbG8K
Segmentation fault
I want to save the value of the output of
system("echo Hello | base64")
in 'a' and not display it. Please help
If you read the documentation for system you'll discover that it doesn't return a string - it's defined as:
int system(const char *command);
The return value is the return status of the command or -1 if there's an error. You can't get the output using system - the output of the command(s) you run will go straight to stdout.
To get the output from another command you could use something like popen.
FILE *myfile;
char buffer[1024];
myfile=popen("echo Hello | base64","r");
if(myfile)
{
while(fgets(buffer,1024,myfile))
{
printf("%s",buffer);
}
pclose(myfile);
}
Here
strcpy(a, system("echo Hello | base64"));
system() doesn't stores it's result into array a as system() job is to execute the command provided in the argument & print it on console i.e stdout buffer. From the manual page of system
system() executes a command specified in command by calling
/bin/sh -c
command, and returns after the command has been completed.
There is one way to solve the problem i.e instead of printing system() output on stdout you can redirect its output to a file & then read that from file & print. For example
int main(void) {
close(1); /* stdout file descriptor is avilable now */
/* create the file if doesn't exist, if exist truncate the content to 0 length */
int fd = open("data.txt",O_CREAT|O_TRUNC|O_RDWR,0664); /* fd gets assigned with lowest
available fd i.e 1 i.e nowonwards stdout output
gets rediredcted to file */
if(fd == -1) {
/* #TODO error handling */
return 0;
}
system("echo Hello | base64"); /* system output gets stored in file */
int max_char = lseek(fd,0,2);/* make fd to point to end, get the max no of char */
char *a = malloc(max_char + 1); /* to avoid buffer overflow or
underflow, allocate memory only equal to the max no of char in file */
if(a == NULL) {
/* #TODO error handling if malloc fails */
return 0;
}
lseek(fd,0,0);/* from beginning of file */
int ret = read(fd,a,max_char);/* now read out put of system() from
file as array and print it */
if(ret == -1) {
/* #TODO error handling */
return 0;
}
a[ret] = '\0';/* \0 terminated array */
dup2(0,fd);/*fd 0 duplicated to file descriptor where fd points i.e */
printf("output : %s \n", a);
/* to avoid memory leak, free the dynamic memory */
free(a);
return 0;
}
My above suggestion is a temporary fix & I won't recommend this, instead use [popen] as suggested by #chris Turner (http://man7.org/linux/man-pages/man3/popen.3.html) which says
The popen() function opens a process by creating a pipe, forking,
and
invoking the shell. Since a pipe is by definition unidirectional, the
type argument may specify only reading or writing, not both; the
resulting stream is correspondingly read-only or write-only.
For example
int main(void) {
char buf[1024];
FILE *fp = popen("echo Hello | base64","r");
printf("%s\n",fgets(buf,sizeof(buf),fp));
return 0;
}

Segmentation core error c

I am little bit ruggy with C coding, but I need this script working to test serial communication with a microcontroller. I have the following code written as:
int main() {
char *portname = "/dev/ttyACM0";
FILE *csv = fopen("~/Desktop/my.csv", "wb");
int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
//error_message ("error %d opening %s: %s", errno, portname, strerror (errno));
return 1;
}
set_interface_attribs (fd, B9600, 0); // set speed to 9600 bps, 8n1 (no parity)
set_blocking (fd, 1); // set no blocking
char a = 255;
int i = 0;
write(fd, &a, 1);
do {
char c;
read(fd, &c, 1); // wait for next value
fprintf(csv, "%d\n", c);
i ++;
} while(i < 10000); //keep running this loop for a while
write(fd, &a, 1);
fclose(csv);
close(fd);
return 0;
This scripts should connect successfully for serial communication, send a start bit (255) to the receiver which operates some actions, and then start writing received data on csv file until the while loop ends up. Have compiled that source with the instruction:
g++ -o serial c-serial.c
where c-serial.c is the name of the source code. Just skip the two "set" function, they are visible in this scope so the error comes not out of this. In fact, when executing I receive:
Segmentation fault (core dumped)
How do I fix it?
Function call fopen is not able to resolve ~ as your home directory. Please take a look at how to open a file in user's home folder.
In your fprintf statement you tell the programm to print an integer (usually two bytes) but provide a char variable (one byte) to print from. fprintf relies on the supplied format string to decide how many bytes to read from the source. In this case fprintf tries to read (at least) two bytes from a one-byte-memory block. Therefore fprintf will try to access memory which might not even be allocated to the program, producing a segmentation fault.
Correct the format string to print a character only.
For more information on fprintf and format strings see here.

Call a C Program within Another and Get the Child's Output in macOS

I have two C programs and am trying to call some child program "child.c" inside of some parent program "parent.c", and capturing the output to stdout from child.c. How would I go about doing this?
I am using macOS.
Here's an example of what parent.c and child.c might look like
parent.c
while (1)
{
// call the child program
// capture the output from the child
if (child_output == some_condition)
{
break;
}
}
child.c
printf("Hello world!")
Thanks for the help.
Simply use popen() and create a stream object of type FILE * which you can use with fread()/fgets() to get the output from the child program. Reading the manual page should be enough to get you started.
But here is an example
#include <stdio.h>
int
main(void)
{
FILE *pipe;
char line[256];
pipe = popen("ls", "r");
if (pipe != NULL) {
while (fgets(line, sizeof line, pipe) != NULL) {
fprintf(stdout, "%s", line);
}
pclose(pipe);
}
return 0;
}
Also, read the manual to get an idea of how this actually works.

Why do the strings output using fprintf end up not being written to the output file if my program is terminated via CTRL-C?

Why does fprintf give different results in the following example programs?
Example 1:
int main(){
FILE *f;
char buf[512];
char name[128] = {"filename"};
f = fopen(name, "w");
fprintf(f, "asdas\n");
fprintf(f, "asdas\n");
while(1){}
return 0;
}
If I terminate this program using CTRL+C, I get an empty file named filename.
However, using
Example 2:
int main(){
FILE *f;
char buf[512];
char name[128] = {"wpa_supplicant.conf"};
f = fopen(name,"w");
while(1){
fprintf(f, "asdas\n");
}
return 0;
}
If I terminate this program using CTRL+C, I get file named filename, and it contains many lines with the string asdas.
Why are the strings not written to the file in the first example, but they are written to the file in the second example?
In the second case, there are enough fprintf calls for the internal buffers to be flushed to disk.
With the first program, if you put a fflush(f) before the while loop, the strings will be written to the file.
#include <stdio.h>
int main(void) {
FILE *f = fopen("filename", "w");
if (!f) {
perror("Failed to open 'filename' for writing");
exit(EXIT_FAILURE);
}
fprintf(f, "asdas\n");
fprintf(f, "asdas\n");
if ( fflush(f) != 0 ) {
perror("Flushing output failed");
exit(EXIT_FAILURE);
}
while(1){}
return 0;
}
Output:
C:\...\Temp> cl file.c
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
...
/out:file.exe
C:\...\Temp> file
^C
C:\...\Temp> type filename
asdas
asdas
Keep in mind:
Upon successful completion, fflush() shall return 0; otherwise, it shall set the error indicator for the stream, return EOF, and set errno to indicate the error.
As mentioned in the answer by #SinanÜnür this is indeed an issue with the buffering of data in internal buffers. You need to flush manually in the first case to get that data actually written into the file.
However, FWIW, I just want to add here, you see this behavior because of the abnormal termination of the program by a signal (generated by CTRL+C).
If your program would have ended normally, (for example, by calling exit(), after a large-enough but controlled while() loop), then both the cases would have shown the same behavior, as in that scenario, all the open streams would have been flushed automatically.
The exit() function shall then flush all open streams with unwritten buffered data and close all open streams. Finally, the process shall be terminated ...

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