简体   繁体   中英

Segmentation fault error using strtok() and strcmp()

I am trying to make simple C program which checks a Linux password file line-by-line searching for the line beginning with a username supplied by a command line argument. Each line consists of several tokens delimited by a colon. The first token is the username, the 2nd is irrelevant, the 3rd is a user id (UID) number which needs to be printed, and the 4th token is the group id number (GID) which also needs to be printed.

Using a few print tests and searching online for solutions, I think my token variable remains NULL after assigning it to my first strtok call (printf of the token at this point prints nothing). Then, the NULL token is compared, using strcmp, to the username which produces the segmentation fault error. If my analysis thus far is correct (which it may very well not be since I am new to C), how can I avoid/fix this problem and why is this happening?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    FILE *pwfile;
    char *userName;
    char buf[1024];
    const char s[2] = ":";
    char *token;
    int ch, number_of_lines = 0;
    int i;

    if(argc != 2)
    {
            perror("must supply a user name");

            return -1;
    }

    pwfile = fopen("/home/c2467/passwd", "r");

    if( pwfile == NULL)
    {
        perror( "error opening password file" );

        return -1;
     }

     userName = argv[1];

     do//loop to determine number of lines in the file
     {
         ch = fgetc(pwfile);
         if(ch == '\n')
         number_of_lines++;
     } while (ch != EOF);

     if(ch != '\n' && number_of_lines != 0)
     {
         number_of_lines++;
     }

     for (i = 0; i <= number_of_lines; i++)//iterates through lines of file
     {

         fgets(buf, 1024, pwfile);//stores line into buf

         if (ferror(pwfile) != 0)//tests error indicator for given stream
         {
             perror("fgets error");
             return 1;
         }

         if (feof(pwfile) == 0)//checks if at end of file
         {
             break;
         }

         token = strtok( buf, s);//stores first token of current line in file

         if( strcmp(token, userName) == 0 )//compares token to user name entered
         {
             token = strtok( NULL, s);//Jumps to 2nd token in line, which is irrelevant so do nothing
             token = strtok( NULL, s);//Jumps to 3rd token which is UID number
             printf( "UID: %s\n", token );
             token = strtok( NULL, s);//Jumps to 4th token which is GID number
             printf( "GID: %s\n", token );
             break;
          }

     }
     fclose(pwfile);

     return 0;
}

You read the file from the beginning to the end to get the count of new lines.

However, you start reading again without seeking back to the beginning. This causes your fgets to fail (read after EOF).

you have to call this:

fseek(pwfile, 0 , SEEK_SET);

you also break from the for on (feof(pwfile) == 0) , which is true in case that the file is not at teh end of file, which means, even after the rewind, you'll stop before processing of the first line.

you should change that to:

if (feof(pwfile))

otherwise it seem to work nice and correctly. (However, I personally hate strtok)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM