cgetopt

getopt() in C doesn't read option arguments


I am typing up a program and it takes three command-line options: s, f and c
Since I was told to use getopt() as a function to get them, I looked into it.

The three options do the following:
s - this is just a "no logs" option, all I need to do is check if it's there or not
f - this is a file path option, followed by its argument (I decided it best to take it as a char array and then use fopen with it)
c - this is another char array that takes an argument after itself

I'm reaching out to you after 2 hours of trying to get these options properly through the function and being unable to.

There is surprisingly little documentation for getopt(), I couldn't find a good example where the code is explained line by line, but nevertheless, this is what I came up with after reading the geeksforgeeks page and the several pages of the GNU documentation regarding it:

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

int main(int argc, char **argv)
{
    int opt;
    char *cli_input_s = NULL;
    char *cli_input_f = NULL;
    char *cli_input_c = NULL;

    while ((opt = getopt(argc, argv, "fc:s")) != -1)
    {
        switch (opt)
        {
            case 's':
                printf("Program is executing without logs.\n");
                break;
            case 'f':
                strcpy(cli_input_f, argv[optind]);
                break;
            case 'c':
                strcpy(cli_input_c, argv[optind]);
                break;
            case '?':
                printf("The program has encountered an unknown argument, aborting.");
                break;
            default:
                printf("I don't know what exactly is going on but...");
                break;
        }
    }

    printf("%d \n", argc);
    printf("%s \n", cli_input_s);
    printf("%s \n", cli_input_f);
    printf("%s \n", cli_input_c);
}

I am using argv[optind] instead of optarg because it wouldn't record the correct thing to the arguments. So far, I've been trying to run the following CLI input:
filename -s -f abc -c abc

The result I'm getting is "Program is executing without logs." and that's it.
At some point I was actually managing to get all the printf's at the end to... print.
But now this is the only thing that prints and I'm completely out of ideas.
It also takes a surprisingly long time to compile (several seconds). I'm using the CLion IDE and its bundled MinGW compiler.

What exactly am I doing wrong and why can I not get the CLI arguments properly?


Solution

  • The option string "fc:s" say that only -c can have an argument. You need the argument character : for each option that can take an argument.

    So your string should be "f:c:s" if you want the -f option to also have an argument.


    That option argument string is the least of your problem. A much worse problem is that you have undefined behavior due to your usage of null pointers...

    Take for example

    strcpy(cli_input_f, argv[optind]);
    

    The pointer cli_input_f is a null pointer. It doesn't point anywhere. And yet you use it as a destination for a string. That's not possible.

    You must have a pointer to a string long enough to hold the sources string, including the null-terminator at the end.

    I recommend you simply change your variables from pointers to arrays of sufficient size:

    char cli_input_f[256] = { 0 };  // Initialize all elements to the string null-terminator