0

When i pass any argument i get this error: Segmentation fault (core dumped) only -h option works properly.

Here option -d and -a takes string value.
option -s and -e takes integer value.

how can i save the values of options passed to a different variable for later usage ?

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

void usage() {
    printf("Usage: help\n----------\n------");
}

int main(int argc, char *argv[]) {
    int opt= 0;
    int start = -1, end = -1;
    char *alg,*dir;

    static struct option long_options[] = {
        {"start",no_argument,0,'s' },
        {"end",no_argument,0,'e' },
        {"algorithm",no_argument, 0,'a' },
        {"directory",required_argument, 0,'d' },
        {0,0,0,0}
    };

    int long_index =0;
    while ((opt = getopt_long(argc, argv,"seadh:",
               long_options, &long_index )) != -1) {
        switch (opt) {
          case 'a' :
            printf("you entered \"%s\"\n", optarg); // error while printing this
            break;
          case 'd' :
            printf("you entered \"%s\"\n", optarg);
            break;
          case 's' : start = atoi(optarg);
            break;
          case 'e' : end = atoi(optarg);
            break;
          case 'h' : usage();
            break;
          default: usage();
            exit(EXIT_FAILURE);
        }
    }
    printf("%d",start);

    return 0;
}

I want to use the options passed along with their values to call a python script inside this C program using system Call .

eg : system(python alg.py -alr -s3 -e45 -d/path)

mch
  • 9,424
  • 2
  • 28
  • 42
programmer
  • 71
  • 1
  • 12
  • 1
    `{"algorithm",no_argument, 0,'a' }` --> `{"algorithm",required_argument, 0,'a' }` (same as `s`, `e` ) and `"seadh:"` --> `"s:e:a:d:h"` – BLUEPIXY Apr 11 '17 at 07:20
  • Wait...you actually need argument for "help", not the other way round? – Sourav Ghosh Apr 11 '17 at 07:25
  • @BLUEPIXY "s:e:a:d:h" this is working , but how do i save this options values to different variable ? My main requirement is to send this to options to python script called with in c program . Read the end part of question after the code , how can i do that ? – programmer Apr 11 '17 at 07:36
  • @BLUEPIXY {"algorithm",no_argument, 0,'a' } --> {"algorithm",required_argument, 0,'a' } , option a, s and e are optional , only -d option is a must , so do i need to still make all others as required_argument ? – programmer Apr 11 '17 at 07:40
  • @programmer `required_argument` means that the option needs an argument, not that the option is mandatory. – Klas Lindbäck Apr 11 '17 at 08:07
  • @KlasLindbäck but this code is working fine , and accepting arguments even if i have specified no_arguments . – programmer Apr 11 '17 at 08:24
  • 1
    @programmer I choose to believe the documentation. – Klas Lindbäck Apr 11 '17 at 08:47

1 Answers1

0

The signature of getopt_long() is

int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

The characters in optstring are short options. If a short option name is followed by colon (:), that option always needs an argument. As in the case of short option e in an optstring like "ae:d".

If there are two colons as the case of y in "ae:y::f", the short option's argument is optional.

If there is no colon after a short option character in optstring, it means that the option never takes an argument.

So, in your case, the optstring should be a:d:e:s:h

optarg points to the argument of the option only if the option has one. Otherwise it will be (null).

And dereferencing a NULL invokes undefined behaviour. See here.

The short options you need are a, d, e and s all of which can take argument. I'm assuming that they always take an argument. Change it to optional argument if that's what you want.

We obtain the argument via optarg which will point to the argument string. If you need the argument as a number, you must convert the string to number. See this post for conversion to integer.

Since all your options need arguments, the has_arg field of the struct option should be required_argument instead of no_argument. If the argument is optional, make it `optional_argument'.

static struct option long_options[] = {
    {"start", required_argument,0,'s' },
    {"end", required_argument,0,'e' },
    {"algorithm", required_argument, 0,'a' },
    {"directory",required_argument, 0,'d' },
};

So the loop could be like

int c, longindex=0, n;
while( (c=getopt_long(argc, argv, "a:e:d:s:h", long_options, &longindex ))!=-1 )
{
    switch(c)
    {
    case 'a':
        fprintf(stdout, "\na value: %s", optarg);
        break;
    case 'e':
        n=strtol(optarg, NULL, 10);
        fprintf(stdout, "\ne value: %d", n);
        break;
    case 'd':
        fprintf(stdout, "\nd value: %s", optarg);
        break;
    case 's':
        n=strtol(optarg, NULL, 10);
        fprintf(stdout, "\ns value: %d", n);
        break;
    case 'h':
        printf("\nh found.");
        break;
    }
}

I have not done the error checking after strtol() for brevity, you should handle that.

You should take care of problems like unknown flags, duplicate flags, extra arguments, etc as well. Check the man page of getopt.

J...S
  • 5,079
  • 1
  • 20
  • 35