Popen fails with No file descriptors available - c

Why does the code below fail after a few seconds?
The error outputs No file descriptors available.
The code runs on a MIPS CPU.
I want to execute a shell command every second and get the result.
static char data[1024];
static void * my_thread(void * arg)
{
while (true)
{
FILE * fp;
fp = popen("ls /", "r");
if (fp == NULL)
{
printf("Error: %s", strerror(errno));
exit(1);
}
while (fgets(data, sizeof(data) - 1, fp) != NULL)
{
printf("%s", data);
}
pclose(fp);
sleep(1);
}
return NULL;
}
Linux kernel version: 4.14.81
EDIT: Maybe I have to mention that there is a fork after the thread is created.

Related

How to exit safely from a loop while working on a growing input file?

I am reading a growing input file, and do some work and write the info to the output file. I have some conditions to work on the growing file. But I am failing at exiting from the loop.
FILE *logfile;
int main(int argc, char *argv[])
{
char *filename;
char *logfilename;
FILE *infile;
char line_buf[255];
char *line;
sleep(3);
if (argc < 3) {
fprintf(stderr, "Usage: %s <filename> <logfile>\n",
argv[0]);
return -1;
}
filename = argv[1];
logfilename = argv[2];
infile = fopen(filename, "rb");
if (infile == NULL) {
fprintf(stderr, "Failed to open file\n");
return -1;
}
logfile = fopen(logfilename, "w");
if (logfile == NULL) {
fprintf(stderr, "Failed to open logfile - are permissions correct?\n");
return -1;
}
while(1){
line = fgets(line_buf, sizeof(line_buf), infile);
if (line == NULL){
if(feof(infile))
clearerr(infile);
failedReads++;
usleep(25000); //wait for the data from live file
continue;
}
else{
if(feof(infile))
break;
}
...........
//do some work
...........
}
fclose(infile);
fclose(logfile);
}
My output log file is getting the data only after the input file stops growing(means at the end of execution). I want my output logfile to get the data by time(means output file is not growing). I have a python script for create a growing file(If anyone really wants to work my issue).
#/usr/bin/python
import time
with open("input.txt") as f:
fileoutput = f.readlines()
with open("out.txt", "a+") as f1:
for line in fileoutput:
f1.write(line)
f1.flush()
time.sleep(0.01)
Code is waiting indefinitely for additional data. Code just waits longer and longer with usleep(25000*failedReads).
// Ineffective code
if (line == NULL){
if(feof(infile))
clearerr(infile);
failedReads++;
usleep(25000*failedReads); //wait for the data from live file
continue;
}
else{
if(line == NULL) // this can never be true!
if(feof(infile))
break;
}
"to get the data by time(means output file is not growing" implies there should be an upper bound of time that if the input file fails to provide more data, quit the loop.
Look for 2 successive read failures. If waiting after the first failure does not provide more data, time to leave.
// instead
bool failed_read_flag = false;
while(1){
line = fgets(line_buf, sizeof(line_buf), infile);
if (line == NULL){
if (failed_read_flag) {
break; // 2 successive read fails
}
if(!feof(infile)) {
break; // Rare input error just occurred.
}
clearerr(infile);
failed_read_flag = true;
usleep(25000 /* us */); //wait for the data from live file
continue;
}
failed_read_flag = false;
// Do some work
}
Strange to open a file with infile = fopen(filename, "rb"); and then use it with fgets().
It the file is a text file, use fopen(filename, "r"). If the file is binary, use fread().

How does FILE stream buffer work?

I understand fopen() opens file and creates a buffer for read and write operations on that file. fopen() returns a pointer for that buffer.
So my question is, in the code below, the _copy function body has a temp matrix to transfer between the fread() and fwrite(). why cant I directly transfer from buffer to buffer?
/* example: copyfile.exe xxxxx.txt zzzzzz.txt */
#include <stdio.h>
#include <stdlib.h>
#define BUFF 8192
void _copy(FILE *source, FILE *destination);
int main(int argc, char *argv[])
{
FILE *fp1, *fp2; // fp1 source file pointer// fp2 copied file pointer
if (argc !=3 ) //command line must have 3 arguments
{
fprintf(stderr, "Usage: %s (source file) (copy file)\n", argv[0][0]);
exit(EXIT_FAILURE);
}
if ((fp1 = fopen(argv[1], "rb")) == NULL) //Opening source file
{
fprintf(stderr, "Could not open %s\n",argv[1]);
exit(EXIT_FAILURE);
}
if((fp2 = fopen(argv[2], "ab+")) == NULL) //Opening destination file
{
fprintf(stderr, "could not create %s \n",argv[2]);
exit(EXIT_FAILURE);
}
if( setvbuf(fp1,NULL, _IOFBF, BUFF) != 0) //Setting buffer for source file
{
fputs("Can't create output buffer\n", stderr);
exit(EXIT_FAILURE);
}
if( setvbuf(fp2,NULL, _IOFBF, BUFF) != 0) //Setting buffer for destination file
{
fputs("Can't create input buffer\n", stderr);
exit(EXIT_FAILURE);
}
_copy(fp1, fp2);
if (ferror(fp1)!=0)
fprintf(stderr, "Error reading file %s\n", argv[1]);
if(ferror(fp2)!=0)
fprintf(stderr, "Error writing file %s\n",argv[2]);
printf("Done coping %s (source) to %s (destination) \n",argv[1], argv[2]);
fclose(fp1);
fclose(fp2);
return (0);
}
void _copy(FILE *source, FILE *destination)
{
size_t bytes;
static char temp[BUFF];
while((bytes = fread(temp,sizeof(char),BUFF,source))>0)
fwrite(temp,sizeof(char),bytes,destination);
}
You cannot use the underlying buffer from a FILE * in another FILE *. As you were told in comment, FILE * is an opaque pointer. But you can avoid the overhead of copying data between buffers by forcing both files in non buffered mode:
setbuf(fp, NULL); // cause the stream to be unbuffered

I am trying to print a txt file and it doesn't work in C homework

I'm writing code that's supposed to verify that a .txt file is a certain format.
I wrote my code as I saw in a tutorial and in the website
and for some reason my program doesn't even print my file.
Can you tell me what I'm doing wrong?
The code will do something far more complex, but I'm still trying to work on my basics.
Here's my code so far:
int main(int argc, char *argv[]) {
/* argv[0] = name of my running file
* argv[1] = the first file that i receive
*/
define MAXBUFLEN 4096
char source[MAXBUFLEN + 1];
int badReturnValue = 1;
char *error = "Error! trying to open the file ";
if (argc != 2) {
printf("please supply a file \n");
return badReturnValue;
}
char *fileName = argv[1];
FILE *fp = fopen(argv[1], "r"); /* "r" = open for reading */
if (fp != NULL) {
size_t newLen = fread(&source, sizeof(char), MAXBUFLEN, fp);
if (ferror(fp) != 0) {
printf("%s %s", error, fileName);
return badReturnValue;
}
int symbol;
while ((symbol = getc(fp)) != EOF) {
putchar(symbol);
}
printf("finish");
fclose(fp);
}
else {
printf("%s %s", error, fileName);
return badReturnValue;
}
}
I think you need a bit more explanations:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// there might be a macro BUFLEN defined in stdio
// which size is optimized for reading in chunks.
// Test if avaiable otherwise define it
#ifndef BUFLEN
# define BUFLEN 4096
#endif
int main(int argc, char *argv[])
{
char source[BUFLEN];
char *filename;
FILE *fp;
size_t fpread, written;
char c;
int ret_fclose;
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// work on copy
filename = malloc(strlen(argv[1]) + 1);
if (filename == NULL) {
fprintf(stderr, "Allocating %zu bytes failed\n", strlen(argv[1]) + 1);
exit(EXIT_FAILURE);
}
filename = strcpy(filename, argv[1]);
// try to open the file at 'filename'
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Opening file \"%s\" filename failed\n", filename);
// errno might got set to something usable, check and print
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// You have two options here. One is to read in chunks of MAXBUFLEN
while ((fpread = fread(&source, 1, BUFLEN, fp)) > 0) {
// Do something with the stuff we read into "source"
// we do nothing with it here, we just write to stdout
written = fwrite(&source, 1, fpread, stdout);
// you can use 'written' for error check when writing to an actual file
// but it is unlikely (but not impossible!) with stdout
// test if we wrote what we read
if ((fpread - written) != 0) {
fprintf(stderr, "We did not write what we read. Diff: %d\n",
(int) (fpread - written));
}
}
// fread() does not distinguish between EOF and error, we have to check by hand
if (feof(fp)) {
// we have read all, exit
puts("\n\n\tfinish\n");
// No, wait, we want to do it again in a different way, so: no exit
// exit(EXIT_SUCCESS);
} else {
// some error may have occured, check
if (ferror(fp)) {
fprintf(stderr, "Something bad happend while reading \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
}
// the other way is to read it byte by byte
// reset the filepointers/errors et al.
rewind(fp);
// rewind() should have reseted errno, but better be safe than sorry
errno = 0;
printf("\n\n\tread and print \"%s\" again\n\n\n\n", filename);
// read one byte and print it until end of file
while ((c = fgetc(fp)) != EOF) {
// just print. Gathering them into "source" is left as an exercise
fputc(c, stdout);
}
// clean up
errno = 0;
ret_fclose = fclose(fp);
// even fclose() might fail
if (ret_fclose == EOF) {
fprintf(stderr, "Something bad happend while closing \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// The macros EXIT_FAILURE and EXIT_SUCCESS are set to the correct values for
// the OS to tell it if we had an eror or not.
// Using exit() is noot necessary here but there exits teh function atexit()
// that runs a given function (e.g: clean up, safe content etc.) when called
exit(EXIT_SUCCESS);
}
You read from the file twice but only print once.
If the file is to small the first reading will read all of the contents, and the second reading will not produce anything so you don't print anything.
I believe you have to reset the pointer after using fread.
Try fseek(fp, SEEK_SET, 0) to reset the pointer to the beginning of the file. Then print the file.

how to copy result of the linux command into a string using c code?

I have executed a command "watch grep \"cpu MHz \" /proc/cpuinfo".After executing this command i got following result.
Result of The Command
But when I am trying this command using c code.
#include<stdio.h>
#include<stdlib.h>
int main(){
FILE *fp;
char path[1035];
char command[]="watch grep \"cpu MHz \" /proc/cpuinfo";
fp = popen(command, "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
/* Read the output a line at a time - output it. */
while (fgets(path, sizeof(path)-1, fp) != NULL) {
printf("%s",path);
}
pclose(fp);
return 0;
}
I am getting following result.
Result of The Code
tell me where am I going wrong?
Try something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
FILE *fp;
char path[1035];
char command[]="while grep \"cpu MHz\" /proc/cpuinfo; do sleep 2; done";
fp = popen(command, "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
/* Read the output a line at a time - output it. */
while (fgets(path, sizeof(path), fp) != NULL) {
printf("%s",path);
}
pclose(fp);
return 0;
}
I think this is what you want.
Don't forget to use memset.
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char path[1035];
char command[]="watch grep 'cpu MHz' /proc/cpuinfo";
fp = popen(command, "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
memset(path,'\0',sizeof(path));
/* Read the output a line at a time - output it. */
while (fgets(path, sizeof(path)-1, fp) != NULL) {
printf("%s",path);
}
pclose(fp);
return 0;
}

Read mpq_t from a binary file

I have written mpq_t to a binary file called "data", and now I am trying to read mpq_t from the file one by one, but I kept having segfault at the line: gmp_printf("%Qd\n", buf). I've been debugging for a while but couldn't figure out where went wrong.
int main(){
FILE *fp = fopen("data", "rb");
if (fp == NULL){
perror("FILE open failed");
exit(1);
}
mpq_t buf;
mpq_init(buf);
while (fread(&buf, sizeof(mpq_t), 1, fp) == 1){
gmp_printf("%Qd\n", buf);
}
fclose(fp);
return 0;
}
It seems that I have a memory issue with buf after reading from the file. I have also tried mallocing instead of initiating, but it did not work either.
mpq_t *buf = (mpq_t *)malloc(sizeof(mpq_t));
if (buf == NULL){
perror("malloc failed");
exit(1);
}
while (fread(buf, sizeof(mpq_t), 1, fp) == 1){
gmp_printf("%Qd\n", *buf);
}
Use gmp_fprintf and gmp_fscanf to write and read:
gmp_fprintf (FILE *fp, const char *fmt, ...)
gmp_fscanf (FILE *fp, const char *fmt, ...)

Resources