Search code examples
cargumentsargp

C argp : Handle option require


I started recently to use argp but i can't find a way to make my option required. I want to see the help when -u (--url) and -w (--wordlist) is not given. Both of them need to be required in order for my programme to work. I look on the internet but can't find the same problem anywhere else. Thanks for the help

argp.c

#include "../header/argp.h"

#include <argp.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

const char *argp_program_version = "WiBreak 0.0.1";
static char doc[] = "Program used to brute force URL.";
static char args_doc[] = "[-u URL] [-w WORDLIST]";
static struct argp_option options[] = {
    {"url", 'u', "URL_TO_QUERY", 0, "Compare lines instead of characters."},
    {"wordlist", 'w', "WORDLIST", 0, "Compare words instead of characters."},
    {"verbose", 'v', 0, OPTION_ARG_OPTIONAL, "Show more info"},
    {0}};


// TODO: Need to handle when no argument are given.
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
    struct arguments *arguments = state->input;
    int *arg_cout = state->input;
    switch (key) {
        case 'u':
            arguments->url_to_query = arg;
            // printf("arg : %s\n", arg);
            break;
        case 'w':
            arguments->wordlist = arg;
            break;
        case 'v':
            arguments->verbose = 1;
            break;
        default:
            // argp_usage(state);
            return ARGP_ERR_UNKNOWN;
    }
    // Code never reach even when i initialyze arguments in the main.
    if (arguments->wordlist == "" || arguments->url_to_query == ""){
        argp_failure(state, 1, 0, "too few arguments");
        exit(ARGP_ERR_UNKNOWN);
    }
    
    return 0;
}

struct argp argp = {options, parse_opt, args_doc, doc};

argp.h

#ifndef __ARGP__H
#define __ARGP__H
#include <argp.h>
#include <stdbool.h>

// static error_t parse_opt(int key, char *arg, struct argp_state *state)
extern struct argp argp;

struct arguments {
    // enum { CHARACTER_MODE, WORD_MODE, LINE_MODE } mode;
    char *wordlist;
    char *url_to_query;
    bool verbose;
    // bool isCaseInsensitive;
};


#endif

main.c

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

    // arguments.mode = CHARACTER_MODE;
    // arguments.isCaseInsensitive = false;
    arguments.wordlist = "";
    arguments.url_to_query = "";

    argp_parse(&argp, argc, argv, 0, 0, &arguments);

    // printf("Wordlist : %s, Url : %s\n", arguments.wordlist,
    // arguments.url_to_query);
    // ...
}

EDIT

Turn out i manage to answer my question by changing the parse_opt as follow

case ARGP_KEY_END:
            // printf("arguments->wordlist : %s, arguments->url_to_query : %s\n", arguments->wordlist, arguments->url_to_query);
            if (arguments->wordlist == NULL || arguments->url_to_query == NULL){
                argp_failure(state, 1, 0, "required -u and -w. See --help for more information");
                exit(ARGP_ERR_UNKNOWN);
            }

Solution

  • I change the argp file and init my struct to null in the main.

    See code under argp.c

    #include "../header/argp.h"
    
    #include <argp.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdlib.h>
    
    const char *argp_program_version = "WiBreak 0.0.1";
    const char *argp_program_bug_address = "arthur.guyotpremel@gmail.com";
    static char doc[] = "Program used to brute force URL.";
    static char args_doc[] = "[-u URL] [-w WORDLIST]";
    static struct argp_option options[] = {
        {"url", 'u', "URL_TO_QUERY", 0, "Compare lines instead of characters [REQUIRED]."},
        {"wordlist", 'w', "WORDLIST", 0, "Compare words instead of characters [REQUIRED]."},
        {"verbose", 'v', 0, OPTION_ARG_OPTIONAL, "Show more info"},
        {0}};
    
    
    // TODO: Need to handle when no argument are given.
    static error_t parse_opt(int key, char *arg, struct argp_state *state) {
        struct arguments *arguments = state->input;
        int *arg_cout = state->input;
        switch (key) {
            case 'u':
                arguments->url_to_query = arg;
                // printf("arg : %s\n", arg);
                break;
            case 'w':
                arguments->wordlist = arg;
                break;
            case 'v':
                arguments->verbose = 1;
                break;
            
            case ARGP_KEY_END:
                // printf("arguments->wordlist : %s, arguments->url_to_query : %s\n", arguments->wordlist, arguments->url_to_query);
                if (arguments->wordlist == NULL || arguments->url_to_query == NULL){
                    argp_failure(state, 1, 0, "required -u and -w. See --help for more information");
                    exit(ARGP_ERR_UNKNOWN);
                }
    
            default:
                // argp_usage(state);
                return ARGP_ERR_UNKNOWN;
        }
        
        return 0;
    }
    
    struct argp argp = {options, parse_opt, args_doc, doc};
    

    main.c

    int main(int argc, char *argv[]) {
        struct arguments arguments;
    
        // arguments.mode = CHARACTER_MODE;
        // arguments.isCaseInsensitive = false;
        arguments.wordlist = NULL;
        arguments.url_to_query = NULL;
    
        argp_parse(&argp, argc, argv, 0, 0, &arguments);
    
        // printf("Wordlist : %s, Url : %s\n", arguments.wordlist,arguments.url_to_query);
        // arguments.url_to_query);
        // ...
    }