Question

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);
 }
Was it helpful?

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.

OTHER TIPS

Most new comers do Linux don't even know about man, there is no man in windows.
In addition the package might not be installed my the Sysadmin. If you can install packages on your machine, install the package:

sudo apt get install manpages-dev # on debian based systems

It's a usefull resource, you can find a list of all possible man pages doing:

 dpkg -L manpages-dev

And here is where is what you are looking for:

$ dpkg -L manpages-dev| grep getop
/usr/share/man/man3/getopt.3.gz
/usr/share/man/man3/getopt_long_only.3.gz
/usr/share/man/man3/getopt_long.3.gz

Here is a good example with clear text, in addition to man pages (which tend to brevity)...

http://linuxprograms.wordpress.com/2012/06/22/c-getopt-example/

getopt(3) has a very good example:

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

int
main(int argc, char *argv[])
{
    int flags, opt;
    int nsecs, tfnd;

   nsecs = 0;
    tfnd = 0;
    flags = 0;
    while ((opt = getopt(argc, argv, "nt:")) != -1) {
        switch (opt) {
        case 'n':
            flags = 1;
            break;
        case 't':
            nsecs = atoi(optarg);
            tfnd = 1;
            break;
        default: /* '?' */
            fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }
    }

   printf("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind);

   if (optind >= argc) {
        fprintf(stderr, "Expected argument after options\n");
        exit(EXIT_FAILURE);
    }

   printf("name argument = %s\n", argv[optind]);

   /* Other code omitted */

   exit(EXIT_SUCCESS);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top