-1

I am trying to make my own cat command in C by the name of "lolcat". It will read the command line arguments such as file name, open that file and print its contents in reverse order. The program is working fine when I run such commands as :

./lolcat file1.txt It prints the file content in reversed order.

But when I try to implement the -n functionality to count the total number of lines. such as ./lolcat -n file1.txt It displays segmentation fault(core dumped).

I have the attached the code below:

#include <stdio.h>

int main(int argc , char *argv[])
{

    printf("%s" , argv[1]);

    int command = 0;
    if(argv[1] == "-n")
    {
        command = 2;
    }
    else{
        command = 1;
    }





    for(int i = command ; i < argc ; i++)

    {

        FILE *myFile = NULL;
        myFile = fopen(argv[i] , "r");
        char word[255];
        char c;
        int  c_count = 0;
        int w_count = 0;
        int l_count = 0;
        int prev_c_count = 0;
        int x = 0;
        int out = 0;


        while((c = fgetc(myFile)) != EOF)
        {
            word[x] = c;
            c_count++;
            if(c == '\n' || c == '\0')
            {
                l_count++;

                    if(command == 1)
                    {
                        for(int j = c_count - 1 ; j>=prev_c_count ; j--)
                        {
                            printf("%c" , word[j]);
                        }

                    }

                prev_c_count = c_count;
            }

            x++;

        }

        printf("\n");

            l_count++;

                    if(command == 1)
                    {
                        for(int j = c_count - 1 ; j>=prev_c_count ; j--)
                        {
                            printf("%c" , word[j]);
                        }
                    }


            

            prev_c_count = c_count;

        printf("\n");



    }

    return 0;
}

4
  • if(argv[1] == "-n") is NOT how you compare C strings... Try strcmp()... So, the program tries to open a file named "-n", fails, and the code continues to suck on that dry pipe... What do you expect the system to do when you don't check return codes from system calls like fopen()? Commented Oct 9, 2022 at 11:33
  • argv[1] == "-n" is not a defined way to do string comparison in c. Your compiler should be warning you about that. Commented Oct 9, 2022 at 11:36
  • @possum : syntactically argv[1] and "-n" are both pointers to char so I guess the compiler is happy with that. (of course they always point to different memory areas so they are always different) Commented Oct 18, 2022 at 17:58
  • fgetc returns an int , 'c' needs to be int not char Commented Oct 18, 2022 at 21:12

1 Answer 1

0

The cause for your segmentation fault is that your code is trying to run fgetc() on a null FILE stream pointer in the line:

while((c = fgetc(myFile)) != EOF)

This causes the libc to try to dereference a null pointer when it tries to read the file contents.

The root cause is, as mentioned in the comments, because you are doing a comparison between two char pointers (char *):

if(argv[1] == "-n")

And then setting the command variable based on that comparison and subsequentely setting i to this command value. Since the code will always enter the else block, command will start at 1.

Then you have the lines:

FILE *myFile = NULL;
myFile = fopen(argv[i], "r");

If command is 1, and therefore i starts as 1, the first argument to the fopen() call will be argv[1], which is, if you run $ ./lolcat -n file1.txt, the "-n" string. Since there's (probably) no '-n' file. (fun fact: I put some effort to create a file named '-n', and your code reads the files fine if this file is present)

How to fix it

The simplest (and quickiest) fix for your code would be replacing your if line (the one I mentioned as the root cause) by:

if(strcmp(argv[1], "-n") == 0)

Remember that, while C supports strings, it has no string type. Your compiler builts binaries having a string on a certain region of your memory, and it has functions to handle strings. However, a char * is NOT a string, it is rather a pointer to a char (the first char of the string. Since strings are null-terminated, functions like strcmp() iterate into the memory region started at the character pointed by the pointer until it finds a null character; there the string functions know the string ended.

Therefore, while it would work for a 'learning project', it's not safe to use in production since an attacker might easily make your program get stuck in an (almost) infinite loop.

Other issues

I could see some other possible problems in your code:

  1. Since you're statically allocating word as a 255-character array, if you get a line with more than 255 characters your code will have a buffer overflow.
  2. If no argument is passed, argv[1] will be a null pointer when you check it to define the value of command. Therefore, strcmp() will dereference a null pointer and you'll have a segmentation fault. You must check the value of a pointer every time you dereference it or run a function that does so (check the function docs/specs; but if a function receives a pointer argument, it likely does.

Hint: To make your life easier, you might want to take a look at getopt library to parse command-line arguments.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.