Test for standard streams piping failed - c

After creating a function to grab stdin, stdout & stderr, I wanted to test it ..
Here is the test code:
int fd[3];
char *buf = calloc(200, sizeof(char));
FILE *stream;
pid_t pid;
pid = opencmd(fd, "/bin/echo", (char *[]){"/bin/echo", "hello!"});
stream = fdopen(fd[2], "r");
while (fgets(buf, 200, stream) != NULL)
printf("stderr: %s\n", buf);
fclose(stream);
stream = fdopen(fd[1], "r");
while (fgets(buf, 200, stream) != NULL)
printf("stdout: %s\n", buf);
fclose(stream);
free(buf);
closecmd(pid, fd);
This does not manage to work as intended. I spent an hour debugging and could not manage to trace the problem, but as far as I managed to go, I realized that using fdopen to start using the descriptors' streams does not work (for some reason), but using functions that work directly with file descriptors (such as write(2) & read(2)) works fine.
What might be the possible reason for this ?

this excerpt: (char *[]){"/bin/echo", "hello!"}); is missing the final NULL parameter – user3629249

Related

correct way to use fwrite and fread

I wrote a program
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
int r;
char arr[] = "this is the string";
char str[20] = {'\0'};
fp = fopen("fwrite.txt", "w");
fwrite(arr, 1, sizeof(arr), fp);
fseek(fp, SEEK_SET, 0);
r = fread(str, 1, sizeof(arr), fp);
if(r == sizeof(arr))
printf("read successfully\n");
else
{
printf("read unsuccessfull\n");
exit(1);
}
printf("read = %d\n", r);
printf("%s\n", str);
fclose(fp);
return 0;
}
I am trying to read in this way but I am not able to do it. What is the problem here, is it that I should put &str[i] and run a loop for fread or will fread be able to put data in the str?
I am getting junk and I don't understand why?
The primary problem is that you have the arguments to fseek() backwards — you need the offset (0) before the whence (SEEK_SET). A secondary problem is that you attempt to read from a file open only for writing. A more minor issue in this context, but one that is generally very important, is that you don't error check the fopen() call. (It is relatively unlikely that this fopen() will fail, but funnier things have been known.) You should also check the fwrite() call (you already check the fread(), of course).
Fixing all these might lead to:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int rc = EXIT_SUCCESS;
int r;
const char file[] = "fwrite.txt";
char arr[] = "this is the string";
char str[20] = {'\0'};
FILE *fp = fopen(file, "w+b");
if (fp == 0)
{
fprintf(stderr, "Failed to open file %s for reading and writing\n", file);
rc = EXIT_FAILURE;
}
else
{
if (fwrite(arr, 1, sizeof(arr), fp) != sizeof(arr))
{
fprintf(stderr, "Failed to write to file %s\n", file);
rc = EXIT_FAILURE;
}
else
{
fseek(fp, 0, SEEK_SET);
r = fread(str, 1, sizeof(arr), fp);
if (r == sizeof(arr))
{
printf("read successful\n");
printf("read = %d bytes\n", r);
printf("read data [%s]\n", str);
}
else
{
printf("read unsuccessful\n");
rc = EXIT_FAILURE;
}
}
fclose(fp);
}
return rc;
}
Example run:
$ ./fi37
read successful
read = 19 bytes
read data [this is the string]
$
Note that this works in part because you write the null byte at the end of the output string to the file, and then read that back in. The file isn't really a text file if it contains null bytes. The b in "w+b" mode isn't really needed on Unix systems where there's no distinction between a binary and a text file. If you're writing null bytes to a file on Windows, you should use the b to indicate binary mode.
If you chose to, you could reduce the 'bushiness' (or depth of nesting) by not having a single return in the main() function. You could use return EXIT_FAILURE; and avoid an else and another set of braces. The code shown is careful to close the file if it was opened. In a general-purpose function, that's important. In main(), it is less critical since the exiting process will flush and close open files anyway.
You can't read in a file with the "w" mode for fopen, use "w+" instead.
"r" - Opens a file for reading. The file must exist.
"w" - Creates an empty file for writing. If a file with the same name already
exists, its content is erased and the file is considered as a new empty file.
"a" - Appends to a file. Writing operations, append data at the end of the
file. The file is created if it does not exist.
"r+" - Opens a file to update both reading and writing. The file must exist.
"w+" - Creates an empty file for both reading and writing.
"a+" - Opens a file for reading and appending.

How to read some specific lines in a file, and print them in console in Linux C programming

I write two new lines in a file. The new lines are appended to this file. How can print these two new lines to the console.
Could you please give me some examples about this?
The process is below:
fd = open(file , O_WRONLY | O_APPEND, 0666);
ret = read(0, buf, 100);
write(file, buf, strlen(buf));
The problem is 4th process. How can I read the new line which is written in file just now, rather than old contents in this file. Below is my code to print the whole contents.
FILE *fptr;
char chr;
fptr = fopen(file, "r");
if (fptr == NULL)
{
perror("open");
exit(1);
}
chr = fgetc(fptr);
while(chr != EOF) {
printf("%c", chr);
chr = fgetc(fptr);
}
clearerr (fptr);
fclose(fptr);
if you want to read back the data you just wrote then you can use ftell to get your position in the file then write, then fseek to reposition to the same point and read

Writing to an output file in C

I am writing a program in C that takes a a command line argument that represents the name of an output file. I then opened the file to write to it. The problem is that when I write something in the command line, it never shows up in the file I was writing to and any text in the file is erased. Here is the code I have for writing to the file from stdin.
(fdOut is the FILE * stream that was specified)
while(fread(buf, 1, 1024, stdin))
{
fwrite(buf, 1, 1024, fdOut);
}
try this code.
#include "stdio.h"
int main()
{
char buf[1024];
FILE *fdOut;
if((fdOut = fopen("out.txt","w")) ==NULL)
{ printf("fopen error!\n");return -1;}
while (fgets(buf, 1024, stdin) != NULL)
{
// int i ;
// for(i = 0;buf[i]!=NULL; ++i)
// fputc(buf[i],fdOut);
fputs(buf,fdOut);
// printf("write error\n");
}
fclose(fdOut);
return 0;
}
Note : use Ctrl+'D' to stop input.
let's assume that there is data coming in at stdin, d.g. you are using your program like:
cat infile.txt | ./myprog /tmp/outfile.txt
then data written with fwrite() will be buffered, so it won't appear immediately in the output file, but only when your OS decides that it's time to flush the buffer.
you can manually force writing to disk by using
fflush(fdOut);
(probably you don't want to do this all the time, as buffering allows for great speedups, esp when writing to slow media)
size_t nbytes;
while ((nbytes = fread(buf, 1, 1024, stdin)) > 0)
{
if (fwrite(buf, 1, nbytes, fdOut) != nbytes)
...handle short write...out of space?...
}
As you wrote it, you mishandle a short read, writing garbage that was not read to the output.

pppd popen hanging in C

I am launching pppd using popen in my program to make obtaining the IP address and interface name a little bit easier. My code runs fine independently and is a pretty typical implementation. The problem begins when it runs in the full program (too large to post)... the loop seems to hang for quite a while at the fgets() line. The popen is launched in its own thread that is then managed based on the output.
The popen/pppd code is essentially the following.
int main(void){
pthread_create(&thread, NULL, pppd, (char *)NULL);
pthread_join(thread, NULL);
return 0;
}
void *pppd(char *args){
char* command = malloc(32);
sprintf(command, "pppd %s call %s", dev, provider);
pppd_stream = popen(command, "r");
if(pppd_stream == NULL){
pppd_terminated = TRUE;
return;
}
free(command);
while(fgets(buffer, 128, d->pppd_stream) != NULL){
//handle_output
}
}
CPU usage isnt a problem, the system and the other parts of the program are still responsive and running as expected.
Any thoughts on what could be causing this slow down?
Ensure that your command is null terminated string:
#define COMMAND_BUFFER_SIZE 256 /* Modify this if you need */
snprintf(command, COMMAND_BUFFER_SIZE, "pppd %s call %s", dev, provider);
command[COMMAND_BUFFER_SIZE - 1] = '\0';
pppd_stream = popen(command, "r");
EDIT:
Check your fgets:
while(fgets(buffer, 128, d->pppd_stream) != NULL){
You may want this:
while(fgets(buffer, 128, pppd_stream) != NULL){

How to catch error in FILE IO using C?

I am using following code snippet in C to copy a file:
#define CHUNK 4096
char buf[CHUNK];
FILE *file , *out;
size_t nread;
file = fopen("test", "rb");
out = fopen("out", "wb");
if (file) {
while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
fwrite(buf, 1, nread, out);
if (ferror(file)) {
/* Not getting error here */
}
fclose(file);
fclose(out);
}
My file is very large (200 MB), I have to handle errors if file is moved or removed while reading, writing is in progress. How can I do that?
Let me clear it tad more, Any how I will get access to path by some wifi means. So if wifi will be disconnected then how I'll get the error..
If the count bytes written is different from the nread parameter this would indicate an error, so:
if(fwrite(buf, 1, nread, out) != nread) {
// error handling
}
Under windows you could lock the file using _lock_file(); to prevent other processes from deleting the file:
#include <stdio.h>
if (file) {
// lock file
_lock_file(file);
while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
fwrite(buf, 1, nread, out);
// unlock the file
_unlock_file(file);
fclose(file);
fclose(out);
}
You should probably open your output file in write mode, i.e. "wb".
How to handle errors: check return values of the I/O functions, and try to deal with the errors. You can use feof() and ferror() to analyze what went wrong. Make sure to always do some I/O before calling either of them (don't try to detemine EOF before reading).

Resources