Thread: The program does not work as I need it

  1. #1
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42

    The program does not work as I need it

    My code:
    Code:
    #include <stdio.h>
    
    int main()
    {
    	FILE *popen_result;
            char buff[512];
            popen_result = popen("Err", "r");
            if(!popen_result){
                    printf("Error!!!\n");
                    return 0;
            }
            while(fgets(buff, sizeof(buff), popen_result)!=NULL){
                    printf("%s", buff);
            }
            pclose(popen_result);
    }
    After running this program, I do not see the error message, but I just see this inscription:
    Code:
    sh: 1: Err: not found
    Why do I have such strange program behavior? The message "Error !!!" should be displayed.
    Code: system("Err") It turns out the same comma, but in it I also can not get rid of this annoying message, so I use popen

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Could it possibly be that the program "Err" doesn't exist?
    Try "ls" instead.

    EDIT:
    I think I see what you mean now. If the shell couldn't find the program "Err", why does it terminate the program instead of just returning NULL and allowing your program to continue?

    That is strange. I don't know why it does that.
    Last edited by algorism; 07-15-2017 at 02:47 PM.

  3. #3
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42
    Quote Originally Posted by algorism View Post
    Could it possibly be that the program "Err" doesn't exist?
    Try "ls" instead.

    EDIT:
    I think I see what you mean now. If the shell couldn't find the program "Err", why does it terminate the program instead of just returning NULL and allowing your program to continue?

    That is strange. I don't know why it does that.
    I specifically use a non-existent command to call and process the error, but as you can see I can not do it and I really need it.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    It seems it works like this.

    A FILE* stream is successfully associated with a child process 'sh', but that shell fails to find the program "Err" (hence the error message which is written to stderr).

    Whilst you end up with a valid FILE*, the child shell won't have written anything to it, and it's probably already closed the other end. The result of which is the first call to any file reading function will return EOF.

    I cooked up this hackery.
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    int main()
    {
      FILE *popen_result;
      char buff[512];
      int temperr = dup(2);               // copy where stderr is at the moment
      freopen("/dev/null", "w", stderr);  // trash stderr reports from popen shell
      popen_result = popen("Err", "r");
      stderr = fdopen(temperr,"w");       // get back stderr
      perror("fopen err=");               // just something that writes to stderr
      if(!popen_result){
            printf("Error!!!\n");
            return 0;
      }
      printf("Reading %p...\n",(void*)popen_result);
      if ( feof(popen_result) ) {
        printf("Already at EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Already at error!\n");
      }
      while(fgets(buff, sizeof(buff), popen_result)!=NULL){
            printf(">>> %s", buff);
      }
      if ( feof(popen_result) ) {
        printf("Got EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Got error!\n");
      }
      printf("Closing...\n");
      pclose(popen_result);
    }
    
    
    $ gcc -Wall bar.c
    $ ./a.out 
    fopen err=: Success
    Reading 0x1c03010...
    Got EOF!
    Closing...
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42
    Quote Originally Posted by algorism View Post
    Could it possibly be that the program "Err" doesn't exist?
    Try "ls" instead.

    EDIT:
    I think I see what you mean now. If the shell couldn't find the program "Err", why does it terminate the program instead of just returning NULL and allowing your program to continue?

    That is strange. I don't know why it does that.
    Quote Originally Posted by Salem View Post
    It seems it works like this.

    A FILE* stream is successfully associated with a child process 'sh', but that shell fails to find the program "Err" (hence the error message which is written to stderr).

    Whilst you end up with a valid FILE*, the child shell won't have written anything to it, and it's probably already closed the other end. The result of which is the first call to any file reading function will return EOF.

    I cooked up this hackery.
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    int main()
    {
      FILE *popen_result;
      char buff[512];
      int temperr = dup(2);               // copy where stderr is at the moment
      freopen("/dev/null", "w", stderr);  // trash stderr reports from popen shell
      popen_result = popen("Err", "r");
      stderr = fdopen(temperr,"w");       // get back stderr
      perror("fopen err=");               // just something that writes to stderr
      if(!popen_result){
            printf("Error!!!\n");
            return 0;
      }
      printf("Reading %p...\n",(void*)popen_result);
      if ( feof(popen_result) ) {
        printf("Already at EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Already at error!\n");
      }
      while(fgets(buff, sizeof(buff), popen_result)!=NULL){
            printf(">>> %s", buff);
      }
      if ( feof(popen_result) ) {
        printf("Got EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Got error!\n");
      }
      printf("Closing...\n");
      pclose(popen_result);
    }
    
    
    $ gcc -Wall bar.c
    $ ./a.out 
    fopen err=: Success
    Reading 0x1c03010...
    Got EOF!
    Closing...
    This code works, but it can not understand whether the file was executed or not.
    I tried to print the return value: printf("%d\n", popen_result), but each time the program simply outputs a random number regardless of whether the command is executed or not.

  6. #6
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42
    made this decision:
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    int main()
    {
      FILE *popen_result;
      char buff[512];
      char *cmd = "ls";
      int temperr = dup(2);               // copy where stderr is at the moment
      freopen("/dev/null", "w", stderr);  // trash stderr reports from popen shell
      popen_result = popen(cmd, "r");
      stderr = fdopen(temperr,"w");       // get back stderr
      perror(cmd);
      if(!popen_result){
            printf("Error!!!\n");
            return 0;
      }
      if ( feof(popen_result) ) {
        printf("Already at EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Already at error!\n");
      }
      int err=1;
      while(fgets(buff, sizeof(buff), popen_result)!=NULL){
            printf(">>> %s", buff);
            err=0;
      }
      if( err==1 )
          printf("Error! Command %s not found\n", cmd);
      if( feof(popen_result) && err==0)
          printf("EOF cmd\n");
      pclose(popen_result);
    }
    This code is good for catching an error if the command is not found, but its drawback is that if the command does not print anything in stdout then an error will appear even if the command does not exist.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Like I said, popen_result is valid because popen() created a shell successfully.

    That the shell failed to do anything useful with the command is a separate problem.

    This is getting increasingly ugly
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/select.h>
    
    int main(int argc, char *argv[])
    {
      FILE *popen_result;
      char *cmd = argc > 1 ? argv[1] : "Oops";
      char buff[512] = { 0 };
      int p[2];
      int temperr = dup(2);               // copy where stderr is at the moment
    
      pipe(p);                            // create a pipe
      fcntl(p[0],F_SETFL,O_NONBLOCK);
      dup2(p[1],2);                       // make stderr use one end of the pipe
      popen_result = popen(cmd, "r");
    
      // check if an error message line was printed by the sub-shell
      struct timeval  tmo = { .tv_sec = 0, .tv_usec = 1000 };
      fd_set  rdset;
      FD_ZERO(&rdset);
      FD_SET(p[0],&rdset);
      if ( select(p[0]+1,&rdset,NULL,NULL,&tmo) > 0 ) {
        char emsg[500];
        ssize_t n = read(p[0],emsg,sizeof(emsg)-1);
        if ( n > 0 ) {
          emsg[n] = '\0';
          printf("StdErrMsgFromPopen=>>>%s<<<\n",emsg);
        }
      }
      close(p[0]);
      close(p[1]);  // All done with the pipe
    
      stderr = fdopen(temperr,"w");       // get back stderr
      if(!popen_result){
            printf("Error!!!\n");
            return 0;
      }
      printf("Reading %p...\n",(void*)popen_result);
      if ( feof(popen_result) ) {
        printf("Already at EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Already at error!\n");
      }
      while(fgets(buff, sizeof(buff), popen_result)!=NULL){
            printf(">>> %s", buff);
      }
      if ( feof(popen_result) ) {
        printf("Got EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Got error!\n");
      }
      printf("Closing...\n");
      pclose(popen_result);
    }
    
    
    
    $ gcc -Wall foo.c
    $ ./a.out 
    StdErrMsgFromPopen=>>>sh: 1: Oops: not found
    <<<
    Reading 0x21db010...
    Got EOF!
    Closing...
    $ ./a.out 'Err'
    StdErrMsgFromPopen=>>>sh: 1: Err: not found
    <<<
    Reading 0x20c9010...
    Got EOF!
    Closing...
    $ ./a.out 'ls *.c'
    Reading 0x1d02010...
    >>> bar.c
    >>> foo.c
    >>> locale_wide_char.c
    >>> main.c
    Got EOF!
    Closing...
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    It's getting complicated enough that maybe forgoing the popen and doing the pipe/fork stuff manually is better. That way the parent can wait for the status and use that.

  9. #9
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42
    Quote Originally Posted by Salem View Post
    Like I said, popen_result is valid because popen() created a shell successfully.

    That the shell failed to do anything useful with the command is a separate problem.

    This is getting increasingly ugly
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/select.h>
    
    int main(int argc, char *argv[])
    {
      FILE *popen_result;
      char *cmd = argc > 1 ? argv[1] : "Oops";
      char buff[512] = { 0 };
      int p[2];
      int temperr = dup(2);               // copy where stderr is at the moment
    
      pipe(p);                            // create a pipe
      fcntl(p[0],F_SETFL,O_NONBLOCK);
      dup2(p[1],2);                       // make stderr use one end of the pipe
      popen_result = popen(cmd, "r");
    
      // check if an error message line was printed by the sub-shell
      struct timeval  tmo = { .tv_sec = 0, .tv_usec = 1000 };
      fd_set  rdset;
      FD_ZERO(&rdset);
      FD_SET(p[0],&rdset);
      if ( select(p[0]+1,&rdset,NULL,NULL,&tmo) > 0 ) {
        char emsg[500];
        ssize_t n = read(p[0],emsg,sizeof(emsg)-1);
        if ( n > 0 ) {
          emsg[n] = '\0';
          printf("StdErrMsgFromPopen=>>>%s<<<\n",emsg);
        }
      }
      close(p[0]);
      close(p[1]);  // All done with the pipe
    
      stderr = fdopen(temperr,"w");       // get back stderr
      if(!popen_result){
            printf("Error!!!\n");
            return 0;
      }
      printf("Reading %p...\n",(void*)popen_result);
      if ( feof(popen_result) ) {
        printf("Already at EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Already at error!\n");
      }
      while(fgets(buff, sizeof(buff), popen_result)!=NULL){
            printf(">>> %s", buff);
      }
      if ( feof(popen_result) ) {
        printf("Got EOF!\n");
      }
      if ( ferror(popen_result) ) {
        printf("Got error!\n");
      }
      printf("Closing...\n");
      pclose(popen_result);
    }
    
    
    
    $ gcc -Wall foo.c
    $ ./a.out 
    StdErrMsgFromPopen=>>>sh: 1: Oops: not found
    <<<
    Reading 0x21db010...
    Got EOF!
    Closing...
    $ ./a.out 'Err'
    StdErrMsgFromPopen=>>>sh: 1: Err: not found
    <<<
    Reading 0x20c9010...
    Got EOF!
    Closing...
    $ ./a.out 'ls *.c'
    Reading 0x1d02010...
    >>> bar.c
    >>> foo.c
    >>> locale_wide_char.c
    >>> main.c
    Got EOF!
    Closing...
    This code is very buggy, although I did not change anything in it, here's the log:
    Code:
    Script started on Sun 16 Jul 2017 04:40:52 PM MSK
    root programs $  /a./a.out 
    Reading 0x557008...
    Got EOF!
    Closing...
    root programs $ 
    root programs $ ./a.out 
    Reading 0x16ce008...
    Got EOF!
    Closing...
    root programs $ ./a.out 
    Reading 0x6f4008...
    Got EOF!
    Closing...
    root programs $ ./a.out gcc
    Reading 0x1adf008...
    Got EOF!
    Closing...
    root programs $ ./a.out gcc
    Reading 0xf80008...
    Got EOF!
    Closing...
    root programs $ ./a.out gcc
    Reading 0x1311008...
    Got EOF!
    Closing...
    root programs $ ./a.out gcc
    Reading 0x25a008...
    Got EOF!
    Closing...
    root programs $ ./a.out gctest
    Reading 0x2d008...
    Got EOF!
    Closing...
    root programs $ ./a.out testno no
    Reading 0x1393008...
    Got EOF!
    Closing...
    root programs $ ./a.out no no
    Reading 0x1b26008...
    Got EOF!
    Closing...
    root programs $ ./a.out no no
    Reading 0x2dd008...
    Got EOF!
    Closing...
    root programs $ ./a.out ne
    Reading 0xaa008...
    Got EOF!
    Closing...
    root programs $ ./a.out eg
    Reading 0xbc4008...
    Got EOF!
    Closing...
    root programs $ ./a.out eg
    Reading 0x1060008...
    Got EOF!
    Closing...
    root programs $ ./a.out 
    Reading 0x1a4d008...
    Got EOF!
    Closing...
    root programs $ ./a.out 
    Reading 0xc93008...
    Got EOF!
    Closing...
    root programs $ ./a.out 
    Reading 0x189008...
    Got EOF!
    Closing...
    root programs $ exit
    
    Script done on Sun 16 Jul 2017 04:41:41 PM MSK
    A campaign in the compiler or in the system.
    I read the manual here: popen
    It is written there: "Upon successful completion, popen() shall return a pointer to an open stream that can be used to read or write to the pipe. Otherwise, it shall return a null pointer and may set errno to indicate the error."
    I wrote the code according to the instructions:
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    
    #define PATH_MAX 100
    
    int main(int argc, char *argv[])
    {
    	FILE *fp;
    int status;
    char path[PATH_MAX];
    
    fp = popen(argv[1], "r");
    if (fp == NULL)
        printf("Command not found\n");
    
    while (fgets(path, PATH_MAX, fp) != NULL)
        printf("%s", path);
    
    status = pclose(fp);
    if (status == -1) {
        printf("Error close\n");
    } else {
        printf("Command exit\n");
    }
    }
    I run ./a.out true:
    Command exit
    I run ./a.out k:
    sh: 1: k: not found
    Command exit
    Can it be easier just to check the existence of the file before it is released? My platform arm and gcc 4.9.2

  10. #10
    programmer hacker DevZero's Avatar
    Join Date
    Jul 2017
    Posts
    42
    I read many manuals and finally understood how to solve this problem:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
    	int x = execvp(argv[1], argv);
    	if(x==-1)
    	    printf("Error\n");
    }
    The problem is solved!

  11. #11
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by DevZero View Post
    This code is very buggy, although I did not change anything in it
    Are you retarded?
    Do you really think Salem would post code that was "very buggy"?
    It could certainly have a bug in it since he's presumably writing it quickly and not taking much time to test it.
    But it's not going to be "very buggy".
    That's an incredibly braindead thing to say.

    @Salem, This guy may be too stupid to help. He doesn't seem to have understood a single word you wrote. (Look at his popen comment. Clueless.)

  12. #12
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by DevZero View Post
    I read many manuals and finally understood how to solve this problem:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        int x = execvp(argv[1], argv);
        if(x==-1)
            printf("Error\n");
    }
    The problem is solved!
    Wow.
    I'm speechless.
    You really are retarded.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. program won't work
    By juice in forum C++ Programming
    Replies: 8
    Last Post: 02-15-2012, 01:42 PM
  2. Can not get this program to work?
    By BLG in forum C Programming
    Replies: 9
    Last Post: 09-09-2009, 09:28 AM
  3. help getting program to work
    By jlmac2001 in forum C Programming
    Replies: 2
    Last Post: 11-13-2002, 11:04 PM
  4. How does this program work??
    By Paninaro in forum C Programming
    Replies: 4
    Last Post: 06-20-2002, 06:50 AM
  5. Why won't my program work?
    By Unregistered in forum C Programming
    Replies: 15
    Last Post: 01-11-2002, 12:57 PM

Tags for this Thread