Hi,
I will try to not be long winded, but I do want you to have a proper understanding...
I have an `info-box` on my desktop, which is nothing more than a `xterm` window which displays the output from a FIFO file. It's a way I can have the output of my programs in one place, instead of always having windows open until a command completes (to check if there were errors).
The first thing I tried was to just redirect the output from whichever command I wanted, to the `info-box` with a redirect:
Code:
command_to_run > $INFOBOX
And it worked, but not the way I wanted it. It's simple for commands where the output IS the end of the program. But for programs that have output throughout the life of it, the output doesn't get displayed until the entire program is finished, and then it gets dumped.
So I created a function for all my programs, to fork a child process and print the output to the FIFO file in the child process. This way I get current updates during the program. But it's done via a `system` command:
Code:
system("echo 'Text to display!' > $INFOBOX");
Now, things are working the way I want them, but I feel the way I was able to accomplish it was horribly hacky. After doing some more searching, I came across someone saying I could use `dup2` to change the `STDOUT_FILENO` to the FIFO file and print the info directly. This sounds good to me, but when I try it, I get no output in the `info-box`.
Could someone please shed some light on this (if they were able to follow my description)? Is this the way I should be doing it? What am I doing wrong with `dup2`? Any and all comments are welcome.
Here is the working code (hacky):
Code:
#define PRINT_PREFIX "echo \"YD: "
#define PRINT_SUFFIX "\" > " INFO_BOX_PATH
void print_output (char *text)
{
// Declare variables.
int fd = {0};
char *text_working = NULL;
// Allocate enough memory for a copy of 'text'.
if((text_working = malloc(sizeof(char) * (strlen(text) + 1))) == NULL)
{
fprintf(stderr, "%s: %s error: malloc failed\n", program_invocation_short_name, __func__);
exit(EXIT_FAILURE);
}
// Make working copy of text.
strcpy(text_working, text);
// Remove trailing newline '\n', if any.
if(text_working[strlen(text_working) - 1] == '\n')
text_working[strlen(text_working) - 1] = '\0';
// Evaluate the fork.
switch(fork())
{
case -1: // Error.
fprintf(stderr, "%s: %s error: fork failed (%s)\n", program_invocation_short_name, __func__, strerror(errno));
exit(EXIT_FAILURE);
break;
case 0: // Child.
// Open output fifo file.
if((fd = open(INFO_BOX_PATH, O_WRONLY)) == -1)
{
fprintf(stderr, "%s: %s error: open failed (%s) (%s)\n", program_invocation_short_name, __func__, strerror(errno), INFO_BOX_PATH);
exit(EXIT_FAILURE);
}
// Duplicate stdout stream.
if(dup2(fd, STDOUT_FILENO) == -1)
{
fprintf(stderr, "%s: %s error: dup2 failed (%s)\n", program_invocation_short_name, __func__, strerror(errno));
exit(EXIT_FAILURE);
}
// Print out to fifo file.
puts(text_working);
// Close the output file and exit child process cleanly.
close(fd);
_exit(EXIT_SUCCESS);
default:
wait(0);
}
// Free allocated memory.
free(text_working);
}
Here is the code using `dup2` which doesn't work:
Code:
void print_output (char *text)
{
// Declare variables.
int fd = {0};
char *text_working = NULL;
// Allocate enough memory for a copy of 'text'.
if((text_working = malloc(sizeof(char) * (strlen(text) + 1))) == NULL)
{
fprintf(stderr, "%s: %s error: malloc failed\n", program_invocation_short_name, __func__);
exit(EXIT_FAILURE);
}
// Make working copy of text.
strcpy(text_working, text);
// Remove trailing newline '\n', if any.
if(text_working[strlen(text_working) - 1] == '\n')
text_working[strlen(text_working) - 1] = '\0';
// Evaluate the fork.
switch(fork())
{
case -1: // Error.
fprintf(stderr, "%s: %s error: fork failed (%s)\n", program_invocation_short_name, __func__, strerror(errno));
exit(EXIT_FAILURE);
break;
case 0: // Child.
// Open output fifo file.
if((fd = open(INFO_BOX_PATH, O_WRONLY)) == -1)
{
fprintf(stderr, "%s: %s error: open failed (%s) (%s)\n", program_invocation_short_name, __func__, strerror(errno), INFO_BOX_PATH);
exit(EXIT_FAILURE);
}
// Duplicate stdout stream.
if(dup2(fd, STDOUT_FILENO) == -1)
{
fprintf(stderr, "%s: %s error: dup2 failed (%s)\n", program_invocation_short_name, __func__, strerror(errno));
exit(EXIT_FAILURE);
}
// Print out to fifo file.
puts(text_working);
// Close the output file and exit child process cleanly.
close(fd);
_exit(EXIT_SUCCESS);
default:
wait(0);
}
// Free allocated memory.
free(text_working);
}