Search code examples
cswitch-statementargumentsgetopt

Using getopt() and switch statements in C


I'm new to C and trying to use getopt combined with a switch statement. I think my problem is just a syntax one but I can't seem to figure it out. I need to run my program like this : $/webserver -p 8080 -r /my/root/dir. So I need to recognize the -p and get the 8080 and the recognize the -r and get the /my/root/dir. Currently my code finds the -p and then finds the -r and then detects an unknown option and exits. Here is the code. I have the puts() in there for testing.

   #define USAGE_STRING "Usage: webserver -p <port> -r  <rootdir>\n"
char *port;
char *rootdir;
// Process command line arguments. Uses GNU getopt() function.
void processargs(int argc, char **argv) {
  int next_option;
  do {
    next_option = getopt(argc, argv, "pr:");
    if (next_option != -1) {
      switch (next_option)
      {
        case 'p': /* -p -- port option  */
          puts("p");

          port = optarg;
         printf("%s", port);
        case 'r': // -r -- root directory option
          puts("r");
          rootdir = optarg;  
        printf("%s", rootdir);
        default:
             puts("unknown");
          /* Unknown option detected. Print it to standard
                output, and exit with exit code zero (normal termination). */
          fprintf(stderr, USAGE_STRING);
          exit(1);

      }
    }
  } while (next_option != -1);
  printf("%s", port);

  if (port == NULL) {

          fprintf(stderr, USAGE_STRING);
          exit(1);
    }
  if (rootdir == NULL) {
  puts("unknown");
          fprintf(stderr, USAGE_STRING);
          exit(1);
    }


}

Currently when I run the above command I get this output (using the puts for testing).

p
r
unknown
Usage: webserver -p <port> -r  <rootdir>

Thanks for any help!


Solution

  • First you should be using getopt_long() I believe getopt() is depreciated. You are also missing break in your switch statement. With out break each case beneath that one will be executed. While you could use a do-while loop it's simpler to just use a while loop.

    Here's a simple command line parser you can build on.

    static const char *optstring = "p:r:";
    
    static struct option longopts[] =
    {
        { "port", required_argument, NULL, 'p' },
        { "root", required_argument, NULL, 'r' },
        { NULL, 0, NULL, 0 }
    };
    
    int parseInput(int argc, char * const argv[])
    {
        int ch;
    
        /* Main Loop ie the Parser */
        while ((ch = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)
        {
            switch(ch)
            {
                case 'p':
                    printf("arg: %s\n", optarg);
                    break;
    
                case 'r':
                    printf("arg: %s\n", optarg);
                    break;
    
                default:
                    printf("Unsupported option\n");
                    return -1;
            }
       }
       return 0;
    }