Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reaching EOF with fgets

Tags:

c

unix

eof

fgets

I'm writing a function that perform some authentications actions. I have a file with all the user_id:password:flag couples structured like this:

Users.txt

user_123:a1b2:0 user_124:a2b1:1 user_125:a2b2:2

This is the code:

int main(){
    /*...*/

    /*user_id, password retrieving*/
    USRPSW* p = malloc(sizeof(USRPSW));
    if(p == NULL){
        fprintf(stderr, "Dynamic alloc error\n");
        exit(EXIT_FAILURE);
    }
    memset((void*)p, 0, sizeof(USRPSW));

    if(usr_psw_read(acc_sock_ds, p->user_id, USR_SIZE) <= 0){
        printf("Failed read: connection with %s aborted.\n",
                 inet_ntoa(client_addr.sin_addr));
        close(acc_sock_ds);
        continue;
    }

    if(usr_psw_read(acc_sock_ds, p->password, PSW_SIZE) <= 0){
        printf("Failed read: connection with %s aborted.\n",
                 inet_ntoa(client_addr.sin_addr));
        close(acc_sock_ds);
        continue;
    }

    /*Authentication through user_id, password*/
    FILE *fd;
    fd = fopen(USERSFILE, "r");
    if(fd == NULL){
        fprintf(stderr, "Users file opening error\n");
        exit(EXIT_FAILURE);
    }

    char *usr_psw_line = malloc(USR_SIZE+PSW_SIZE+3+1);
    if(usr_psw_line == NULL){
        fprintf(stderr, "Dynamic alloc error\n");
        exit(EXIT_FAILURE);
    }

    while(1){

        memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1));
        fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd);
        printf("%s\n", usr_psw_line);
        fseek(fd, 1, SEEK_CUR);


        /*EOF management*/
        /*usr_id - password matching checking */

    }   
/*...*/    
}

How can I manage the EOF reaching? I saw that when EOF is reached fgets doesn't edits anymore the usr_psw_line but neither returns a NULL pointer. If EOF is reached it mean that no match are found in the users file and the loop breaks.

Can someone give me some tips or suggests?

like image 343
Fabio Carello Avatar asked Mar 18 '13 18:03

Fabio Carello


2 Answers

fgets() return a null pointer when it reaches end-of-file or an error condition.

(EOF is a macro that specifies the value returned by certain other functions in similar conditions; it's not just an abbreviation for the phrase "end of file".)

You're ignoring the result returned by fgets(). Don't do that.

Note that just checking feof(fd) won't do what you want. feof() returns a true result if you've reached the end of the file. If you encounter an error instead, feof() still returns false, and you've got yourself an infinite loop if you're using feof() to decide when you're done. And it doesn't return true until after you've failed to read input.

Most C input functions return some special value to indicate that there's nothing more to read. For fgets() it's NULL, for fgetc() it's EOF, and so forth. If you like, you can call feof() and/or ferror() afterwards to determine why there's nothing more to read.

like image 141
Keith Thompson Avatar answered Sep 19 '22 16:09

Keith Thompson


You might want to try something like this in your loop:

while(1)
{
    memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1));
    if( !fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd)
     || ferror( fd ) || feof( fd ) )
    {
        break;
    }
    printf("%s\n", usr_psw_line);
    fseek(fd, 1, SEEK_CUR);

    /*EOF management*/
    /*usr_id - password matching checking */

}

With the extra code, the loop will terminate if fgets returns NULL (no more data to read) or if you're read the EOF mark or had any error on the file. I'm sure it is overkill, but those tests have always worked for me.

like image 28
Steve Valliere Avatar answered Sep 17 '22 16:09

Steve Valliere