cfgetsfeofferror

How to use feof and ferror for fgets (minishell in C)


I've written this minishell but I'm not sure I'm making a correct control of the errors. I know fgets can return feof and ferror (http://www.manpagez.com/man/3/fgets/) but I don't know how to use them.

I've checked if fgets returns a null pointer (which indicates the content of the buffer is inditerminate) but i would like to know how to use feof and ferror.

    #include <stdio.h>
    #include <stdlib.h> 
    #include <string.h> 
    #include <stdbool.h>    
    #define LINE_LEN  50
    #define MAX_PARTS  50 
    int main ()
    {
    char* token;
    char str[LINE_LEN];
    char* arr[MAX_PARTS];
    int i,j;
    bool go_on = true;

    while (go_on == true){
        printf("Write a line:('quit' to end) \n $:");
        fgets(str, LINE_LEN, stdin);

        if (str==NULL) {
            goto errorfgets;
        } else {
            size_t l=strlen(str);
            if(l && str[l-1]=='\n')
                str[l-1]=0;

            i=0;
            /* split string into words*/
            token = strtok(str, " \t\r\n");
            while( token != NULL ) 
            {
                arr[i] = token;
                i++;
                token = strtok(NULL," \t\r\n");
            }

            fflush(stdin);

            /* check if the first word is quit*/
            if (strcmp(arr[0],"quit")==0)
            {
                printf("Goodbye\n");
                go_on = false;
            } else {

                for (j=0; j < i; j++){
                printf("'%s'\n", arr[j]);       
                }   
            }
        }
    }

    return 0;
    errorfgets:
        printf("fgets didn't work correctly");
        return -1;
}

Solution

  • First of all, your test:

    fgets(str, LINE_LEN, stdin);
    
    [...]
    
    if (str==NULL) {
        goto errorfgets;
    }
    

    is wrong. The str parameter is passed by value and cannot be modified by fgets(). Instead, you should be checking the value returned by fgets() (returns NULL on EOF or error).

    Regarding your specific question: fgets() does not "return" feof or ferror. Both feof() and ferror() are actually functions (see the man pages). You would use this as follows:

    if (!fgets(str, LINE_LEN, stdin)) {
        /* fgets returns NULL on EOF and error; let's see what happened */
        if (ferror(stdin)) {
            /* handle error */
        } else {
            /* handle EOF */
        }
    }