0
votes

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;
}
1
In the for loop i should either start from 1 or the condition should be changed to i < number_of_lines .Knight71
its C, the start from 1 is ridiculousV-X
as long as it is logical I don't mind :)Knight71
It is not educational at all.V-X
it is not an array iteration. It is just a counter. what harm it does ?Knight71

1 Answers

1
votes

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)