Search code examples
cbashstdingetopt

How do you use getopt() with non option arguments


I am trying to use getopt() for a program that requires either an "e" or "d" option to select encrypt or decrypt then takes a key to be used for either on. My problem is im not sure how to handle the key with getopt(). I have read much of of the man getopt() stuff and numerous other article at this point. I currently get a floating point error and core dump and am recieveing the warning message:

cypher.c: In function ‘main’: cypher.c:14:3: warning: passing argument 2 of ‘getopt’ from incompatible pointer type [enabled by default] /usr/include/getopt.h:152:12: note: expected ‘char * const*’ but argument is of type ‘char *’ cypher.c:28:13: warning: assignment makes integer from pointer without a cast [enabled by default]

Below is the actual code any help is appreciated.

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

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

  int e,x; 
  int i=0;      
  int c=fgetc(stdin);
  //  int n=strlen(key);
  int encrypt;

  while((x = getopt (argc, argv, "ed")) != -1){
    switch (x){
    case 'e':
      encrypt=1;
      break;
    case 'd':
      encrypt=0;
      break;
    default:
      fputs("you broke it\n",stderr);
      exit(1);
    }
  }
    char key[100];
    key[100]= argv[optind++];
    int n = strlen(key);

    if(encrypt == 1){
      while(c != EOF){
         c= fgetc(stdin);
         e=(c - 32 + key[i % n]) % 95 +32;
         fputc( e, stdout);
         i++;
      }
    }
    else{
      while( e != EOF){
         c = fgetc(stdin);
         c=(e - 32 -key[i % n] +3 * 95) % 95 +32;
         fputc(c, stdout);
         i++;
      }
    }
  exit (0);
 }

Solution

  • Typically you want to separate option handling into two steps:

    1. Collect all options and do any preprocessing on them (such as checking their validity) and storing them as necessary in variables or structures.
    2. Actually taking action based on the full set of options encountered.

    So basically you will probably want to set a global variable (such as opt_mode = ENCRYPT or opt_mode = DECRYPT or something similar), and store the key as necessary. Then after all option processing is done, actually do the encryption or decryption based on the opt_mode variable.