1 /*
2   File autogenerated by gengetopt version 2.23
3   generated with the following command:
4   /usr/bin/gengetopt --file-name=goid-tool-cmdline --output-dir=.
5 
6   The developers of gengetopt consider the fixed text that goes in all
7   gengetopt output files to be in the public domain:
8   we make no copyright claims on it.
9 */
10 
11 /* If we use autoconf.  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #ifndef FIX_UNUSED
21 #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
22 #endif
23 
24 #include <getopt.h>
25 
26 #include "goid-tool-cmdline.h"
27 
28 const char *gengetopt_args_info_purpose = "";
29 
30 const char *gengetopt_args_info_usage = "Usage: goid-tool [OPTION]...";
31 
32 const char *gengetopt_args_info_versiontext = "";
33 
34 const char *gengetopt_args_info_description = "";
35 
36 const char *gengetopt_args_info_help[] = {
37   "  -h, --help                    Print help and exit",
38   "  -V, --version                 Print version and exit",
39   "  -r, --reader=STRING           Number of the reader to use. By default, the\n                                  first reader with a present card is used. If\n                                  the argument is an ATR, the reader with a\n                                  matching card will be chosen.",
40   "  -v, --verbose                 Use (several times) to be more verbose",
41   "  -p, --verify-pin              Verify PIN",
42   "  -b, --verify-bio              Verify finger print",
43   "      --verify-pin-or-bio       Verify PIN or finger print (user's choice)",
44   "\nReport bugs to https://github.com/OpenSC/OpenSC/issues\n\nWritten by Frank Morgner <frankmorgner@gmail.com>",
45   "\n Mode: soc\n  Options for SoCManager Applet",
46   "      --new-pin                 Change PIN",
47   "      --new-bio                 Use (several times) to change one or more\n                                  biometric templates",
48   "      --info                    Dump Information about the SoCManager's\n                                  configuration",
49   "\n Mode: pxs\n  Options for PAccess Applet",
50   "  -c, --certificate=FILENAME    Use (several times) to pass CV certificates",
51   "  -k, --key=FILENAME            Private key for the CV certificate",
52   "      --print-cardid            Print the card ID",
53   "      --write-cardid=CARDID     Write the specified card ID",
54   "      --print-paccessid         Print the PAccess ID",
55   "      --write-paccessid=PACCESSID\n                                Write the specified PAccess ID",
56   "      --read-dg=ID              Read the specified data group; use several\n                                  times to read out multiple files",
57   "      --out-file=FILENAME       Write output to a file instead of printing it;\n                                  use once for each use of `--read-dg'",
58   "      --write-dg=ID             Write the specified data group; use several\n                                  times to write multiple files",
59   "      --in-file=FILENAME        Read input from a file; use once for each use\n                                  of `--write-dg'",
60   "      --delete-dg=ID            Delete the specified data group; use several\n                                  times to delete multiple files",
61   "      --create-dg=ID            Create the specified data group; use several\n                                  times to create multiple files",
62   "      --new-size=SIZE           File size of newly created DGs  (default=`256')",
63   "      --new-read-ac=STRING      Access condition for reading newly created DGs\n                                  (possible values=\"always\", \"never\",\n                                  \"ta\", \"sm\" default=`sm')",
64   "      --new-read-ac-chatbit=INDEX\n                                Required access bits in certificate's CHAT for\n                                  reading newly created DGs",
65   "      --new-write-ac=STRING     Access condition for writing newly created DGs\n                                  (possible values=\"always\", \"never\",\n                                  \"ta\", \"sm\" default=`sm')",
66   "      --new-write-ac-chatbit=INDEX\n                                Required access bits in certificate's CHAT for\n                                  reading newly created DGs",
67     0
68 };
69 
70 typedef enum {ARG_NO
71   , ARG_STRING
72   , ARG_INT
73 } cmdline_parser_arg_type;
74 
75 static
76 void clear_given (struct gengetopt_args_info *args_info);
77 static
78 void clear_args (struct gengetopt_args_info *args_info);
79 
80 static int
81 cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
82                         struct cmdline_parser_params *params, const char *additional_error);
83 
84 static int
85 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
86 
87 const char *cmdline_parser_new_read_ac_values[] = {"always", "never", "ta", "sm", 0}; /*< Possible values for new-read-ac. */
88 const char *cmdline_parser_new_write_ac_values[] = {"always", "never", "ta", "sm", 0}; /*< Possible values for new-write-ac. */
89 
90 static char *
91 gengetopt_strdup (const char *s);
92 
93 static
clear_given(struct gengetopt_args_info * args_info)94 void clear_given (struct gengetopt_args_info *args_info)
95 {
96   args_info->help_given = 0 ;
97   args_info->version_given = 0 ;
98   args_info->reader_given = 0 ;
99   args_info->verbose_given = 0 ;
100   args_info->verify_pin_given = 0 ;
101   args_info->verify_bio_given = 0 ;
102   args_info->verify_pin_or_bio_given = 0 ;
103   args_info->new_pin_given = 0 ;
104   args_info->new_bio_given = 0 ;
105   args_info->info_given = 0 ;
106   args_info->certificate_given = 0 ;
107   args_info->key_given = 0 ;
108   args_info->print_cardid_given = 0 ;
109   args_info->write_cardid_given = 0 ;
110   args_info->print_paccessid_given = 0 ;
111   args_info->write_paccessid_given = 0 ;
112   args_info->read_dg_given = 0 ;
113   args_info->out_file_given = 0 ;
114   args_info->write_dg_given = 0 ;
115   args_info->in_file_given = 0 ;
116   args_info->delete_dg_given = 0 ;
117   args_info->create_dg_given = 0 ;
118   args_info->new_size_given = 0 ;
119   args_info->new_read_ac_given = 0 ;
120   args_info->new_read_ac_chatbit_given = 0 ;
121   args_info->new_write_ac_given = 0 ;
122   args_info->new_write_ac_chatbit_given = 0 ;
123   args_info->pxs_mode_counter = 0 ;
124   args_info->soc_mode_counter = 0 ;
125 }
126 
127 static
clear_args(struct gengetopt_args_info * args_info)128 void clear_args (struct gengetopt_args_info *args_info)
129 {
130   FIX_UNUSED (args_info);
131   args_info->reader_arg = NULL;
132   args_info->reader_orig = NULL;
133   args_info->certificate_arg = NULL;
134   args_info->certificate_orig = NULL;
135   args_info->key_arg = NULL;
136   args_info->key_orig = NULL;
137   args_info->write_cardid_arg = NULL;
138   args_info->write_cardid_orig = NULL;
139   args_info->write_paccessid_arg = NULL;
140   args_info->write_paccessid_orig = NULL;
141   args_info->read_dg_arg = NULL;
142   args_info->read_dg_orig = NULL;
143   args_info->out_file_arg = NULL;
144   args_info->out_file_orig = NULL;
145   args_info->write_dg_arg = NULL;
146   args_info->write_dg_orig = NULL;
147   args_info->in_file_arg = NULL;
148   args_info->in_file_orig = NULL;
149   args_info->delete_dg_arg = NULL;
150   args_info->delete_dg_orig = NULL;
151   args_info->create_dg_arg = NULL;
152   args_info->create_dg_orig = NULL;
153   args_info->new_size_arg = 256;
154   args_info->new_size_orig = NULL;
155   args_info->new_read_ac_arg = gengetopt_strdup ("sm");
156   args_info->new_read_ac_orig = NULL;
157   args_info->new_read_ac_chatbit_arg = NULL;
158   args_info->new_read_ac_chatbit_orig = NULL;
159   args_info->new_write_ac_arg = gengetopt_strdup ("sm");
160   args_info->new_write_ac_orig = NULL;
161   args_info->new_write_ac_chatbit_arg = NULL;
162   args_info->new_write_ac_chatbit_orig = NULL;
163 
164 }
165 
166 static
init_args_info(struct gengetopt_args_info * args_info)167 void init_args_info(struct gengetopt_args_info *args_info)
168 {
169 
170 
171   args_info->help_help = gengetopt_args_info_help[0] ;
172   args_info->version_help = gengetopt_args_info_help[1] ;
173   args_info->reader_help = gengetopt_args_info_help[2] ;
174   args_info->verbose_help = gengetopt_args_info_help[3] ;
175   args_info->verbose_min = 0;
176   args_info->verbose_max = 0;
177   args_info->verify_pin_help = gengetopt_args_info_help[4] ;
178   args_info->verify_bio_help = gengetopt_args_info_help[5] ;
179   args_info->verify_pin_or_bio_help = gengetopt_args_info_help[6] ;
180   args_info->new_pin_help = gengetopt_args_info_help[9] ;
181   args_info->new_bio_help = gengetopt_args_info_help[10] ;
182   args_info->new_bio_min = 0;
183   args_info->new_bio_max = 0;
184   args_info->info_help = gengetopt_args_info_help[11] ;
185   args_info->certificate_help = gengetopt_args_info_help[13] ;
186   args_info->certificate_min = 0;
187   args_info->certificate_max = 0;
188   args_info->key_help = gengetopt_args_info_help[14] ;
189   args_info->print_cardid_help = gengetopt_args_info_help[15] ;
190   args_info->write_cardid_help = gengetopt_args_info_help[16] ;
191   args_info->print_paccessid_help = gengetopt_args_info_help[17] ;
192   args_info->write_paccessid_help = gengetopt_args_info_help[18] ;
193   args_info->read_dg_help = gengetopt_args_info_help[19] ;
194   args_info->read_dg_min = 0;
195   args_info->read_dg_max = 0;
196   args_info->out_file_help = gengetopt_args_info_help[20] ;
197   args_info->out_file_min = 0;
198   args_info->out_file_max = 0;
199   args_info->write_dg_help = gengetopt_args_info_help[21] ;
200   args_info->write_dg_min = 0;
201   args_info->write_dg_max = 0;
202   args_info->in_file_help = gengetopt_args_info_help[22] ;
203   args_info->in_file_min = 0;
204   args_info->in_file_max = 0;
205   args_info->delete_dg_help = gengetopt_args_info_help[23] ;
206   args_info->delete_dg_min = 0;
207   args_info->delete_dg_max = 0;
208   args_info->create_dg_help = gengetopt_args_info_help[24] ;
209   args_info->create_dg_min = 0;
210   args_info->create_dg_max = 0;
211   args_info->new_size_help = gengetopt_args_info_help[25] ;
212   args_info->new_read_ac_help = gengetopt_args_info_help[26] ;
213   args_info->new_read_ac_chatbit_help = gengetopt_args_info_help[27] ;
214   args_info->new_read_ac_chatbit_min = 0;
215   args_info->new_read_ac_chatbit_max = 0;
216   args_info->new_write_ac_help = gengetopt_args_info_help[28] ;
217   args_info->new_write_ac_chatbit_help = gengetopt_args_info_help[29] ;
218   args_info->new_write_ac_chatbit_min = 0;
219   args_info->new_write_ac_chatbit_max = 0;
220 
221 }
222 
223 void
cmdline_parser_print_version(void)224 cmdline_parser_print_version (void)
225 {
226   printf ("%s %s\n",
227      (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
228      CMDLINE_PARSER_VERSION);
229 
230   if (strlen(gengetopt_args_info_versiontext) > 0)
231     printf("\n%s\n", gengetopt_args_info_versiontext);
232 }
233 
print_help_common(void)234 static void print_help_common(void)
235 {
236 	size_t len_purpose = strlen(gengetopt_args_info_purpose);
237 	size_t len_usage = strlen(gengetopt_args_info_usage);
238 
239 	if (len_usage > 0) {
240 		printf("%s\n", gengetopt_args_info_usage);
241 	}
242 	if (len_purpose > 0) {
243 		printf("%s\n", gengetopt_args_info_purpose);
244 	}
245 
246 	if (len_usage || len_purpose) {
247 		printf("\n");
248 	}
249 
250 	if (strlen(gengetopt_args_info_description) > 0) {
251 		printf("%s\n\n", gengetopt_args_info_description);
252 	}
253 }
254 
255 void
cmdline_parser_print_help(void)256 cmdline_parser_print_help (void)
257 {
258   int i = 0;
259   print_help_common();
260   while (gengetopt_args_info_help[i])
261     printf("%s\n", gengetopt_args_info_help[i++]);
262 }
263 
264 void
cmdline_parser_init(struct gengetopt_args_info * args_info)265 cmdline_parser_init (struct gengetopt_args_info *args_info)
266 {
267   clear_given (args_info);
268   clear_args (args_info);
269   init_args_info (args_info);
270 }
271 
272 void
cmdline_parser_params_init(struct cmdline_parser_params * params)273 cmdline_parser_params_init(struct cmdline_parser_params *params)
274 {
275   if (params)
276     {
277       params->override = 0;
278       params->initialize = 1;
279       params->check_required = 1;
280       params->check_ambiguity = 0;
281       params->print_errors = 1;
282     }
283 }
284 
285 struct cmdline_parser_params *
cmdline_parser_params_create(void)286 cmdline_parser_params_create(void)
287 {
288   struct cmdline_parser_params *params =
289     (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
290   cmdline_parser_params_init(params);
291   return params;
292 }
293 
294 static void
free_string_field(char ** s)295 free_string_field (char **s)
296 {
297   if (*s)
298     {
299       free (*s);
300       *s = 0;
301     }
302 }
303 
304 /** @brief generic value variable */
305 union generic_value {
306     int int_arg;
307     char *string_arg;
308     const char *default_string_arg;
309 };
310 
311 /** @brief holds temporary values for multiple options */
312 struct generic_list
313 {
314   union generic_value arg;
315   char *orig;
316   struct generic_list *next;
317 };
318 
319 /**
320  * @brief add a node at the head of the list
321  */
add_node(struct generic_list ** list)322 static void add_node(struct generic_list **list) {
323   struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));
324   new_node->next = *list;
325   *list = new_node;
326   new_node->arg.string_arg = 0;
327   new_node->orig = 0;
328 }
329 
330 /**
331  * The passed arg parameter is NOT set to 0 from this function
332  */
333 static void
free_multiple_field(unsigned int len,void * arg,char *** orig)334 free_multiple_field(unsigned int len, void *arg, char ***orig)
335 {
336   unsigned int i;
337   if (arg) {
338     for (i = 0; i < len; ++i)
339       {
340         free_string_field(&((*orig)[i]));
341       }
342 
343     free (arg);
344     free (*orig);
345     *orig = 0;
346   }
347 }
348 
349 static void
free_multiple_string_field(unsigned int len,char *** arg,char *** orig)350 free_multiple_string_field(unsigned int len, char ***arg, char ***orig)
351 {
352   unsigned int i;
353   if (*arg) {
354     for (i = 0; i < len; ++i)
355       {
356         free_string_field(&((*arg)[i]));
357         free_string_field(&((*orig)[i]));
358       }
359     free_string_field(&((*arg)[0])); /* free default string */
360 
361     free (*arg);
362     *arg = 0;
363     free (*orig);
364     *orig = 0;
365   }
366 }
367 
368 static void
cmdline_parser_release(struct gengetopt_args_info * args_info)369 cmdline_parser_release (struct gengetopt_args_info *args_info)
370 {
371 
372   free_string_field (&(args_info->reader_arg));
373   free_string_field (&(args_info->reader_orig));
374   free_multiple_string_field (args_info->certificate_given, &(args_info->certificate_arg), &(args_info->certificate_orig));
375   free_string_field (&(args_info->key_arg));
376   free_string_field (&(args_info->key_orig));
377   free_string_field (&(args_info->write_cardid_arg));
378   free_string_field (&(args_info->write_cardid_orig));
379   free_string_field (&(args_info->write_paccessid_arg));
380   free_string_field (&(args_info->write_paccessid_orig));
381   free_multiple_field (args_info->read_dg_given, (void *)(args_info->read_dg_arg), &(args_info->read_dg_orig));
382   args_info->read_dg_arg = 0;
383   free_multiple_string_field (args_info->out_file_given, &(args_info->out_file_arg), &(args_info->out_file_orig));
384   free_multiple_field (args_info->write_dg_given, (void *)(args_info->write_dg_arg), &(args_info->write_dg_orig));
385   args_info->write_dg_arg = 0;
386   free_multiple_string_field (args_info->in_file_given, &(args_info->in_file_arg), &(args_info->in_file_orig));
387   free_multiple_field (args_info->delete_dg_given, (void *)(args_info->delete_dg_arg), &(args_info->delete_dg_orig));
388   args_info->delete_dg_arg = 0;
389   free_multiple_field (args_info->create_dg_given, (void *)(args_info->create_dg_arg), &(args_info->create_dg_orig));
390   args_info->create_dg_arg = 0;
391   free_string_field (&(args_info->new_size_orig));
392   free_string_field (&(args_info->new_read_ac_arg));
393   free_string_field (&(args_info->new_read_ac_orig));
394   free_multiple_field (args_info->new_read_ac_chatbit_given, (void *)(args_info->new_read_ac_chatbit_arg), &(args_info->new_read_ac_chatbit_orig));
395   args_info->new_read_ac_chatbit_arg = 0;
396   free_string_field (&(args_info->new_write_ac_arg));
397   free_string_field (&(args_info->new_write_ac_orig));
398   free_multiple_field (args_info->new_write_ac_chatbit_given, (void *)(args_info->new_write_ac_chatbit_arg), &(args_info->new_write_ac_chatbit_orig));
399   args_info->new_write_ac_chatbit_arg = 0;
400 
401 
402 
403   clear_given (args_info);
404 }
405 
406 /**
407  * @param val the value to check
408  * @param values the possible values
409  * @return the index of the matched value:
410  * -1 if no value matched,
411  * -2 if more than one value has matched
412  */
413 static int
check_possible_values(const char * val,const char * values[])414 check_possible_values(const char *val, const char *values[])
415 {
416   int i, found, last;
417   size_t len;
418 
419   if (!val)   /* otherwise strlen() crashes below */
420     return -1; /* -1 means no argument for the option */
421 
422   found = last = 0;
423 
424   for (i = 0, len = strlen(val); values[i]; ++i)
425     {
426       if (strncmp(val, values[i], len) == 0)
427         {
428           ++found;
429           last = i;
430           if (strlen(values[i]) == len)
431             return i; /* exact macth no need to check more */
432         }
433     }
434 
435   if (found == 1) /* one match: OK */
436     return last;
437 
438   return (found ? -2 : -1); /* return many values or none matched */
439 }
440 
441 
442 static void
write_into_file(FILE * outfile,const char * opt,const char * arg,const char * values[])443 write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
444 {
445   int found = -1;
446   if (arg) {
447     if (values) {
448       found = check_possible_values(arg, values);
449     }
450     if (found >= 0)
451       fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]);
452     else
453       fprintf(outfile, "%s=\"%s\"\n", opt, arg);
454   } else {
455     fprintf(outfile, "%s\n", opt);
456   }
457 }
458 
459 static void
write_multiple_into_file(FILE * outfile,int len,const char * opt,char ** arg,const char * values[])460 write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[])
461 {
462   int i;
463 
464   for (i = 0; i < len; ++i)
465     write_into_file(outfile, opt, (arg ? arg[i] : 0), values);
466 }
467 
468 int
cmdline_parser_dump(FILE * outfile,struct gengetopt_args_info * args_info)469 cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
470 {
471   int i = 0;
472 
473   if (!outfile)
474     {
475       fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
476       return EXIT_FAILURE;
477     }
478 
479   if (args_info->help_given)
480     write_into_file(outfile, "help", 0, 0 );
481   if (args_info->version_given)
482     write_into_file(outfile, "version", 0, 0 );
483   if (args_info->reader_given)
484     write_into_file(outfile, "reader", args_info->reader_orig, 0);
485   write_multiple_into_file(outfile, args_info->verbose_given, "verbose", 0, 0);
486   if (args_info->verify_pin_given)
487     write_into_file(outfile, "verify-pin", 0, 0 );
488   if (args_info->verify_bio_given)
489     write_into_file(outfile, "verify-bio", 0, 0 );
490   if (args_info->verify_pin_or_bio_given)
491     write_into_file(outfile, "verify-pin-or-bio", 0, 0 );
492   if (args_info->new_pin_given)
493     write_into_file(outfile, "new-pin", 0, 0 );
494   write_multiple_into_file(outfile, args_info->new_bio_given, "new-bio", 0, 0);
495   if (args_info->info_given)
496     write_into_file(outfile, "info", 0, 0 );
497   write_multiple_into_file(outfile, args_info->certificate_given, "certificate", args_info->certificate_orig, 0);
498   if (args_info->key_given)
499     write_into_file(outfile, "key", args_info->key_orig, 0);
500   if (args_info->print_cardid_given)
501     write_into_file(outfile, "print-cardid", 0, 0 );
502   if (args_info->write_cardid_given)
503     write_into_file(outfile, "write-cardid", args_info->write_cardid_orig, 0);
504   if (args_info->print_paccessid_given)
505     write_into_file(outfile, "print-paccessid", 0, 0 );
506   if (args_info->write_paccessid_given)
507     write_into_file(outfile, "write-paccessid", args_info->write_paccessid_orig, 0);
508   write_multiple_into_file(outfile, args_info->read_dg_given, "read-dg", args_info->read_dg_orig, 0);
509   write_multiple_into_file(outfile, args_info->out_file_given, "out-file", args_info->out_file_orig, 0);
510   write_multiple_into_file(outfile, args_info->write_dg_given, "write-dg", args_info->write_dg_orig, 0);
511   write_multiple_into_file(outfile, args_info->in_file_given, "in-file", args_info->in_file_orig, 0);
512   write_multiple_into_file(outfile, args_info->delete_dg_given, "delete-dg", args_info->delete_dg_orig, 0);
513   write_multiple_into_file(outfile, args_info->create_dg_given, "create-dg", args_info->create_dg_orig, 0);
514   if (args_info->new_size_given)
515     write_into_file(outfile, "new-size", args_info->new_size_orig, 0);
516   if (args_info->new_read_ac_given)
517     write_into_file(outfile, "new-read-ac", args_info->new_read_ac_orig, cmdline_parser_new_read_ac_values);
518   write_multiple_into_file(outfile, args_info->new_read_ac_chatbit_given, "new-read-ac-chatbit", args_info->new_read_ac_chatbit_orig, 0);
519   if (args_info->new_write_ac_given)
520     write_into_file(outfile, "new-write-ac", args_info->new_write_ac_orig, cmdline_parser_new_write_ac_values);
521   write_multiple_into_file(outfile, args_info->new_write_ac_chatbit_given, "new-write-ac-chatbit", args_info->new_write_ac_chatbit_orig, 0);
522 
523 
524   i = EXIT_SUCCESS;
525   return i;
526 }
527 
528 int
cmdline_parser_file_save(const char * filename,struct gengetopt_args_info * args_info)529 cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
530 {
531   FILE *outfile;
532   int i = 0;
533 
534   outfile = fopen(filename, "w");
535 
536   if (!outfile)
537     {
538       fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
539       return EXIT_FAILURE;
540     }
541 
542   i = cmdline_parser_dump(outfile, args_info);
543   fclose (outfile);
544 
545   return i;
546 }
547 
548 void
cmdline_parser_free(struct gengetopt_args_info * args_info)549 cmdline_parser_free (struct gengetopt_args_info *args_info)
550 {
551   cmdline_parser_release (args_info);
552 }
553 
554 /** @brief replacement of strdup, which is not standard */
555 char *
gengetopt_strdup(const char * s)556 gengetopt_strdup (const char *s)
557 {
558   char *result = 0;
559   if (!s)
560     return result;
561 
562   result = (char*)malloc(strlen(s) + 1);
563   if (result == (char*)0)
564     return (char*)0;
565   strcpy(result, s);
566   return result;
567 }
568 
569 static char *
get_multiple_arg_token(const char * arg)570 get_multiple_arg_token(const char *arg)
571 {
572   const char *tok;
573   char *ret;
574   size_t len, num_of_escape, i, j;
575 
576   if (!arg)
577     return 0;
578 
579   tok = strchr (arg, ',');
580   num_of_escape = 0;
581 
582   /* make sure it is not escaped */
583   while (tok)
584     {
585       if (*(tok-1) == '\\')
586         {
587           /* find the next one */
588           tok = strchr (tok+1, ',');
589           ++num_of_escape;
590         }
591       else
592         break;
593     }
594 
595   if (tok)
596     len = (size_t)(tok - arg + 1);
597   else
598     len = strlen (arg) + 1;
599 
600   len -= num_of_escape;
601 
602   ret = (char *) malloc (len);
603 
604   i = 0;
605   j = 0;
606   while (arg[i] && (j < len-1))
607     {
608       if (arg[i] == '\\' &&
609 	  arg[ i + 1 ] &&
610 	  arg[ i + 1 ] == ',')
611         ++i;
612 
613       ret[j++] = arg[i++];
614     }
615 
616   ret[len-1] = '\0';
617 
618   return ret;
619 }
620 
621 static const char *
get_multiple_arg_token_next(const char * arg)622 get_multiple_arg_token_next(const char *arg)
623 {
624   const char *tok;
625 
626   if (!arg)
627     return 0;
628 
629   tok = strchr (arg, ',');
630 
631   /* make sure it is not escaped */
632   while (tok)
633     {
634       if (*(tok-1) == '\\')
635         {
636           /* find the next one */
637           tok = strchr (tok+1, ',');
638         }
639       else
640         break;
641     }
642 
643   if (! tok || strlen(tok) == 1)
644     return 0;
645 
646   return tok+1;
647 }
648 
649 static int
650 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc);
651 
652 int
check_multiple_option_occurrences(const char * prog_name,unsigned int option_given,unsigned int min,unsigned int max,const char * option_desc)653 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc)
654 {
655   int error_occurred = 0;
656 
657   if (option_given && (min > 0 || max > 0))
658     {
659       if (min > 0 && max > 0)
660         {
661           if (min == max)
662             {
663               /* specific occurrences */
664               if (option_given != (unsigned int) min)
665                 {
666                   fprintf (stderr, "%s: %s option occurrences must be %d\n",
667                     prog_name, option_desc, min);
668                   error_occurred = 1;
669                 }
670             }
671           else if (option_given < (unsigned int) min
672                 || option_given > (unsigned int) max)
673             {
674               /* range occurrences */
675               fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n",
676                 prog_name, option_desc, min, max);
677               error_occurred = 1;
678             }
679         }
680       else if (min > 0)
681         {
682           /* at least check */
683           if (option_given < min)
684             {
685               fprintf (stderr, "%s: %s option occurrences must be at least %d\n",
686                 prog_name, option_desc, min);
687               error_occurred = 1;
688             }
689         }
690       else if (max > 0)
691         {
692           /* at most check */
693           if (option_given > max)
694             {
695               fprintf (stderr, "%s: %s option occurrences must be at most %d\n",
696                 prog_name, option_desc, max);
697               error_occurred = 1;
698             }
699         }
700     }
701 
702   return error_occurred;
703 }
704 int
cmdline_parser(int argc,char ** argv,struct gengetopt_args_info * args_info)705 cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
706 {
707   return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
708 }
709 
710 int
cmdline_parser_ext(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params)711 cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
712                    struct cmdline_parser_params *params)
713 {
714   int result;
715   result = cmdline_parser_internal (argc, argv, args_info, params, 0);
716 
717   if (result == EXIT_FAILURE)
718     {
719       cmdline_parser_free (args_info);
720       exit (EXIT_FAILURE);
721     }
722 
723   return result;
724 }
725 
726 int
cmdline_parser2(int argc,char ** argv,struct gengetopt_args_info * args_info,int override,int initialize,int check_required)727 cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
728 {
729   int result;
730   struct cmdline_parser_params params;
731 
732   params.override = override;
733   params.initialize = initialize;
734   params.check_required = check_required;
735   params.check_ambiguity = 0;
736   params.print_errors = 1;
737 
738   result = cmdline_parser_internal (argc, argv, args_info, &params, 0);
739 
740   if (result == EXIT_FAILURE)
741     {
742       cmdline_parser_free (args_info);
743       exit (EXIT_FAILURE);
744     }
745 
746   return result;
747 }
748 
749 int
cmdline_parser_required(struct gengetopt_args_info * args_info,const char * prog_name)750 cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
751 {
752   int result = EXIT_SUCCESS;
753 
754   if (cmdline_parser_required2(args_info, prog_name, 0) > 0)
755     result = EXIT_FAILURE;
756 
757   if (result == EXIT_FAILURE)
758     {
759       cmdline_parser_free (args_info);
760       exit (EXIT_FAILURE);
761     }
762 
763   return result;
764 }
765 
766 int
cmdline_parser_required2(struct gengetopt_args_info * args_info,const char * prog_name,const char * additional_error)767 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
768 {
769   int error_occurred = 0;
770   FIX_UNUSED (additional_error);
771 
772   /* checks for required options */
773   if (check_multiple_option_occurrences(prog_name, args_info->verbose_given, args_info->verbose_min, args_info->verbose_max, "'--verbose' ('-v')"))
774      error_occurred = 1;
775 
776   if (args_info->soc_mode_counter && check_multiple_option_occurrences(prog_name, args_info->new_bio_given, args_info->new_bio_min, args_info->new_bio_max, "'--new-bio'"))
777      error_occurred = 1;
778 
779   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->certificate_given, args_info->certificate_min, args_info->certificate_max, "'--certificate' ('-c')"))
780      error_occurred = 1;
781 
782   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->read_dg_given, args_info->read_dg_min, args_info->read_dg_max, "'--read-dg'"))
783      error_occurred = 1;
784 
785   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->out_file_given, args_info->out_file_min, args_info->out_file_max, "'--out-file'"))
786      error_occurred = 1;
787 
788   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->write_dg_given, args_info->write_dg_min, args_info->write_dg_max, "'--write-dg'"))
789      error_occurred = 1;
790 
791   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->in_file_given, args_info->in_file_min, args_info->in_file_max, "'--in-file'"))
792      error_occurred = 1;
793 
794   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->delete_dg_given, args_info->delete_dg_min, args_info->delete_dg_max, "'--delete-dg'"))
795      error_occurred = 1;
796 
797   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->create_dg_given, args_info->create_dg_min, args_info->create_dg_max, "'--create-dg'"))
798      error_occurred = 1;
799 
800   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->new_read_ac_chatbit_given, args_info->new_read_ac_chatbit_min, args_info->new_read_ac_chatbit_max, "'--new-read-ac-chatbit'"))
801      error_occurred = 1;
802 
803   if (args_info->pxs_mode_counter && check_multiple_option_occurrences(prog_name, args_info->new_write_ac_chatbit_given, args_info->new_write_ac_chatbit_min, args_info->new_write_ac_chatbit_max, "'--new-write-ac-chatbit'"))
804      error_occurred = 1;
805 
806 
807   /* checks for dependences among options */
808   if (args_info->certificate_given && ! args_info->key_given)
809     {
810       fprintf (stderr, "%s: '--certificate' ('-c') option depends on option 'key'%s\n", prog_name, (additional_error ? additional_error : ""));
811       error_occurred = 1;
812     }
813   if (args_info->key_given && ! args_info->certificate_given)
814     {
815       fprintf (stderr, "%s: '--key' ('-k') option depends on option 'certificate'%s\n", prog_name, (additional_error ? additional_error : ""));
816       error_occurred = 1;
817     }
818   if (args_info->new_size_given && ! args_info->create_dg_given)
819     {
820       fprintf (stderr, "%s: '--new-size' option depends on option 'create-dg'%s\n", prog_name, (additional_error ? additional_error : ""));
821       error_occurred = 1;
822     }
823   if (args_info->new_read_ac_given && ! args_info->create_dg_given)
824     {
825       fprintf (stderr, "%s: '--new-read-ac' option depends on option 'create-dg'%s\n", prog_name, (additional_error ? additional_error : ""));
826       error_occurred = 1;
827     }
828   if (args_info->new_read_ac_chatbit_given && ! args_info->create_dg_given)
829     {
830       fprintf (stderr, "%s: '--new-read-ac-chatbit' option depends on option 'create-dg'%s\n", prog_name, (additional_error ? additional_error : ""));
831       error_occurred = 1;
832     }
833   if (args_info->new_write_ac_given && ! args_info->create_dg_given)
834     {
835       fprintf (stderr, "%s: '--new-write-ac' option depends on option 'create-dg'%s\n", prog_name, (additional_error ? additional_error : ""));
836       error_occurred = 1;
837     }
838   if (args_info->new_write_ac_chatbit_given && ! args_info->create_dg_given)
839     {
840       fprintf (stderr, "%s: '--new-write-ac-chatbit' option depends on option 'create-dg'%s\n", prog_name, (additional_error ? additional_error : ""));
841       error_occurred = 1;
842     }
843 
844   return error_occurred;
845 }
846 
847 
848 static char *package_name = 0;
849 
850 /**
851  * @brief updates an option
852  * @param field the generic pointer to the field to update
853  * @param orig_field the pointer to the orig field
854  * @param field_given the pointer to the number of occurrence of this option
855  * @param prev_given the pointer to the number of occurrence already seen
856  * @param value the argument for this option (if null no arg was specified)
857  * @param possible_values the possible values for this option (if specified)
858  * @param default_value the default value (in case the option only accepts fixed values)
859  * @param arg_type the type of this option
860  * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
861  * @param override @see cmdline_parser_params.override
862  * @param no_free whether to free a possible previous value
863  * @param multiple_option whether this is a multiple option
864  * @param long_opt the corresponding long option
865  * @param short_opt the corresponding short option (or '-' if none)
866  * @param additional_error possible further error specification
867  */
868 static
update_arg(void * field,char ** orig_field,unsigned int * field_given,unsigned int * prev_given,char * value,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,int check_ambiguity,int override,int no_free,int multiple_option,const char * long_opt,char short_opt,const char * additional_error)869 int update_arg(void *field, char **orig_field,
870                unsigned int *field_given, unsigned int *prev_given,
871                char *value, const char *possible_values[],
872                const char *default_value,
873                cmdline_parser_arg_type arg_type,
874                int check_ambiguity, int override,
875                int no_free, int multiple_option,
876                const char *long_opt, char short_opt,
877                const char *additional_error)
878 {
879   char *stop_char = 0;
880   const char *val = value;
881   int found;
882   char **string_field;
883   FIX_UNUSED (field);
884 
885   stop_char = 0;
886   found = 0;
887 
888   if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
889     {
890       if (short_opt != '-')
891         fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
892                package_name, long_opt, short_opt,
893                (additional_error ? additional_error : ""));
894       else
895         fprintf (stderr, "%s: `--%s' option given more than once%s\n",
896                package_name, long_opt,
897                (additional_error ? additional_error : ""));
898       return 1; /* failure */
899     }
900 
901   if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0)
902     {
903       if (short_opt != '-')
904         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n",
905           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt,
906           (additional_error ? additional_error : ""));
907       else
908         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n",
909           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt,
910           (additional_error ? additional_error : ""));
911       return 1; /* failure */
912     }
913 
914   if (field_given && *field_given && ! override)
915     return 0;
916   if (prev_given)
917     (*prev_given)++;
918   if (field_given)
919     (*field_given)++;
920   if (possible_values)
921     val = possible_values[found];
922 
923   switch(arg_type) {
924   case ARG_INT:
925     if (val) *((int *)field) = strtol (val, &stop_char, 0);
926     break;
927   case ARG_STRING:
928     if (val) {
929       string_field = (char **)field;
930       if (!no_free && *string_field)
931         free (*string_field); /* free previous string */
932       *string_field = gengetopt_strdup (val);
933     }
934     break;
935   default:
936     break;
937   };
938 
939   /* check numeric conversion */
940   switch(arg_type) {
941   case ARG_INT:
942     if (val && !(stop_char && *stop_char == '\0')) {
943       fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
944       return 1; /* failure */
945     }
946     break;
947   default:
948     ;
949   };
950 
951   /* store the original value */
952   switch(arg_type) {
953   case ARG_NO:
954     break;
955   default:
956     if (value && orig_field) {
957       if (no_free) {
958         *orig_field = value;
959       } else {
960         if (*orig_field)
961           free (*orig_field); /* free previous string */
962         *orig_field = gengetopt_strdup (value);
963       }
964     }
965   };
966 
967   return 0; /* OK */
968 }
969 
970 /**
971  * @brief store information about a multiple option in a temporary list
972  * @param list where to (temporarily) store multiple options
973  */
974 static
update_multiple_arg_temp(struct generic_list ** list,unsigned int * prev_given,const char * val,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,const char * long_opt,char short_opt,const char * additional_error)975 int update_multiple_arg_temp(struct generic_list **list,
976                unsigned int *prev_given, const char *val,
977                const char *possible_values[], const char *default_value,
978                cmdline_parser_arg_type arg_type,
979                const char *long_opt, char short_opt,
980                const char *additional_error)
981 {
982   /* store single arguments */
983   char *multi_token;
984   const char *multi_next;
985 
986   if (arg_type == ARG_NO) {
987     (*prev_given)++;
988     return 0; /* OK */
989   }
990 
991   multi_token = get_multiple_arg_token(val);
992   multi_next = get_multiple_arg_token_next (val);
993 
994   while (1)
995     {
996       add_node (list);
997       if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,
998           prev_given, multi_token, possible_values, default_value,
999           arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {
1000         if (multi_token) free(multi_token);
1001         return 1; /* failure */
1002       }
1003 
1004       if (multi_next)
1005         {
1006           multi_token = get_multiple_arg_token(multi_next);
1007           multi_next = get_multiple_arg_token_next (multi_next);
1008         }
1009       else
1010         break;
1011     }
1012 
1013   return 0; /* OK */
1014 }
1015 
1016 /**
1017  * @brief free the passed list (including possible string argument)
1018  */
1019 static
free_list(struct generic_list * list,short string_arg)1020 void free_list(struct generic_list *list, short string_arg)
1021 {
1022   if (list) {
1023     struct generic_list *tmp;
1024     while (list)
1025       {
1026         tmp = list;
1027         if (string_arg && list->arg.string_arg)
1028           free (list->arg.string_arg);
1029         if (list->orig)
1030           free (list->orig);
1031         list = list->next;
1032         free (tmp);
1033       }
1034   }
1035 }
1036 
1037 /**
1038  * @brief updates a multiple option starting from the passed list
1039  */
1040 static
update_multiple_arg(void * field,char *** orig_field,unsigned int field_given,unsigned int prev_given,union generic_value * default_value,cmdline_parser_arg_type arg_type,struct generic_list * list)1041 void update_multiple_arg(void *field, char ***orig_field,
1042                unsigned int field_given, unsigned int prev_given, union generic_value *default_value,
1043                cmdline_parser_arg_type arg_type,
1044                struct generic_list *list)
1045 {
1046   int i;
1047   struct generic_list *tmp;
1048 
1049   if (prev_given && list) {
1050     *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));
1051 
1052     switch(arg_type) {
1053     case ARG_INT:
1054       *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break;
1055     case ARG_STRING:
1056       *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;
1057     default:
1058       break;
1059     };
1060 
1061     for (i = (prev_given - 1); i >= 0; --i)
1062       {
1063         tmp = list;
1064 
1065         switch(arg_type) {
1066         case ARG_INT:
1067           (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;
1068         case ARG_STRING:
1069           (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;
1070         default:
1071           break;
1072         }
1073         (*orig_field) [i + field_given] = list->orig;
1074         list = list->next;
1075         free (tmp);
1076       }
1077   } else { /* set the default value */
1078     if (default_value && ! field_given) {
1079       switch(arg_type) {
1080       case ARG_INT:
1081         if (! *((int **)field)) {
1082           *((int **)field) = (int *)malloc (sizeof (int));
1083           (*((int **)field))[0] = default_value->int_arg;
1084         }
1085         break;
1086       case ARG_STRING:
1087         if (! *((char ***)field)) {
1088           *((char ***)field) = (char **)malloc (sizeof (char *));
1089           (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);
1090         }
1091         break;
1092       default: break;
1093       }
1094       if (!(*orig_field)) {
1095         *orig_field = (char **) malloc (sizeof (char *));
1096         (*orig_field)[0] = 0;
1097       }
1098     }
1099   }
1100 }
1101 
check_modes(int given1[],const char * options1[],int given2[],const char * options2[])1102 static int check_modes(
1103   int given1[], const char *options1[],
1104                        int given2[], const char *options2[])
1105 {
1106   int i = 0, j = 0, errors = 0;
1107 
1108   while (given1[i] >= 0) {
1109     if (given1[i]) {
1110       while (given2[j] >= 0) {
1111         if (given2[j]) {
1112           ++errors;
1113           fprintf(stderr, "%s: option %s conflicts with option %s\n",
1114                   package_name, options1[i], options2[j]);
1115         }
1116         ++j;
1117       }
1118     }
1119     ++i;
1120   }
1121 
1122   return errors;
1123 }
1124 
1125 int
cmdline_parser_internal(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params,const char * additional_error)1126 cmdline_parser_internal (
1127   int argc, char **argv, struct gengetopt_args_info *args_info,
1128                         struct cmdline_parser_params *params, const char *additional_error)
1129 {
1130   int c;	/* Character of the parsed option.  */
1131 
1132   struct generic_list * certificate_list = NULL;
1133   struct generic_list * read_dg_list = NULL;
1134   struct generic_list * out_file_list = NULL;
1135   struct generic_list * write_dg_list = NULL;
1136   struct generic_list * in_file_list = NULL;
1137   struct generic_list * delete_dg_list = NULL;
1138   struct generic_list * create_dg_list = NULL;
1139   struct generic_list * new_read_ac_chatbit_list = NULL;
1140   struct generic_list * new_write_ac_chatbit_list = NULL;
1141   int error_occurred = 0;
1142   struct gengetopt_args_info local_args_info;
1143 
1144   int override;
1145   int initialize;
1146   int check_required;
1147   int check_ambiguity;
1148 
1149   package_name = argv[0];
1150 
1151   /* TODO: Why is this here? It is not used anywhere. */
1152   override = params->override;
1153   FIX_UNUSED(override);
1154 
1155   initialize = params->initialize;
1156   check_required = params->check_required;
1157 
1158   /* TODO: Why is this here? It is not used anywhere. */
1159   check_ambiguity = params->check_ambiguity;
1160   FIX_UNUSED(check_ambiguity);
1161 
1162   if (initialize)
1163     cmdline_parser_init (args_info);
1164 
1165   cmdline_parser_init (&local_args_info);
1166 
1167   optarg = 0;
1168   optind = 0;
1169   opterr = params->print_errors;
1170   optopt = '?';
1171 
1172   while (1)
1173     {
1174       int option_index = 0;
1175 
1176       static struct option long_options[] = {
1177         { "help",	0, NULL, 'h' },
1178         { "version",	0, NULL, 'V' },
1179         { "reader",	1, NULL, 'r' },
1180         { "verbose",	0, NULL, 'v' },
1181         { "verify-pin",	0, NULL, 'p' },
1182         { "verify-bio",	0, NULL, 'b' },
1183         { "verify-pin-or-bio",	0, NULL, 0 },
1184         { "new-pin",	0, NULL, 0 },
1185         { "new-bio",	0, NULL, 0 },
1186         { "info",	0, NULL, 0 },
1187         { "certificate",	1, NULL, 'c' },
1188         { "key",	1, NULL, 'k' },
1189         { "print-cardid",	0, NULL, 0 },
1190         { "write-cardid",	1, NULL, 0 },
1191         { "print-paccessid",	0, NULL, 0 },
1192         { "write-paccessid",	1, NULL, 0 },
1193         { "read-dg",	1, NULL, 0 },
1194         { "out-file",	1, NULL, 0 },
1195         { "write-dg",	1, NULL, 0 },
1196         { "in-file",	1, NULL, 0 },
1197         { "delete-dg",	1, NULL, 0 },
1198         { "create-dg",	1, NULL, 0 },
1199         { "new-size",	1, NULL, 0 },
1200         { "new-read-ac",	1, NULL, 0 },
1201         { "new-read-ac-chatbit",	1, NULL, 0 },
1202         { "new-write-ac",	1, NULL, 0 },
1203         { "new-write-ac-chatbit",	1, NULL, 0 },
1204         { 0,  0, 0, 0 }
1205       };
1206 
1207       c = getopt_long (argc, argv, "hVr:vpbc:k:", long_options, &option_index);
1208 
1209       if (c == -1) break;	/* Exit from `while (1)' loop.  */
1210 
1211       switch (c)
1212         {
1213         case 'h':	/* Print help and exit.  */
1214           cmdline_parser_print_help ();
1215           cmdline_parser_free (&local_args_info);
1216           exit (EXIT_SUCCESS);
1217 
1218         case 'V':	/* Print version and exit.  */
1219           cmdline_parser_print_version ();
1220           cmdline_parser_free (&local_args_info);
1221           exit (EXIT_SUCCESS);
1222 
1223         case 'r':	/* Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen..  */
1224 
1225 
1226           if (update_arg( (void *)&(args_info->reader_arg),
1227                &(args_info->reader_orig), &(args_info->reader_given),
1228               &(local_args_info.reader_given), optarg, 0, 0, ARG_STRING,
1229               check_ambiguity, override, 0, 0,
1230               "reader", 'r',
1231               additional_error))
1232             goto failure;
1233 
1234           break;
1235         case 'v':	/* Use (several times) to be more verbose.  */
1236 
1237           local_args_info.verbose_given++;
1238 
1239           break;
1240         case 'p':	/* Verify PIN.  */
1241 
1242 
1243           if (update_arg( 0 ,
1244                0 , &(args_info->verify_pin_given),
1245               &(local_args_info.verify_pin_given), optarg, 0, 0, ARG_NO,
1246               check_ambiguity, override, 0, 0,
1247               "verify-pin", 'p',
1248               additional_error))
1249             goto failure;
1250 
1251           break;
1252         case 'b':	/* Verify finger print.  */
1253 
1254 
1255           if (update_arg( 0 ,
1256                0 , &(args_info->verify_bio_given),
1257               &(local_args_info.verify_bio_given), optarg, 0, 0, ARG_NO,
1258               check_ambiguity, override, 0, 0,
1259               "verify-bio", 'b',
1260               additional_error))
1261             goto failure;
1262 
1263           break;
1264         case 'c':	/* Use (several times) to pass CV certificates.  */
1265           args_info->pxs_mode_counter += 1;
1266 
1267           if (update_multiple_arg_temp(&certificate_list,
1268               &(local_args_info.certificate_given), optarg, 0, 0, ARG_STRING,
1269               "certificate", 'c',
1270               additional_error))
1271             goto failure;
1272 
1273           break;
1274         case 'k':	/* Private key for the CV certificate.  */
1275           args_info->pxs_mode_counter += 1;
1276 
1277 
1278           if (update_arg( (void *)&(args_info->key_arg),
1279                &(args_info->key_orig), &(args_info->key_given),
1280               &(local_args_info.key_given), optarg, 0, 0, ARG_STRING,
1281               check_ambiguity, override, 0, 0,
1282               "key", 'k',
1283               additional_error))
1284             goto failure;
1285 
1286           break;
1287 
1288         case 0:	/* Long option with no short option */
1289           /* Verify PIN or finger print (user's choice).  */
1290           if (strcmp (long_options[option_index].name, "verify-pin-or-bio") == 0)
1291           {
1292 
1293 
1294             if (update_arg( 0 ,
1295                  0 , &(args_info->verify_pin_or_bio_given),
1296                 &(local_args_info.verify_pin_or_bio_given), optarg, 0, 0, ARG_NO,
1297                 check_ambiguity, override, 0, 0,
1298                 "verify-pin-or-bio", '-',
1299                 additional_error))
1300               goto failure;
1301 
1302           }
1303           /* Change PIN.  */
1304           else if (strcmp (long_options[option_index].name, "new-pin") == 0)
1305           {
1306             args_info->soc_mode_counter += 1;
1307 
1308 
1309             if (update_arg( 0 ,
1310                  0 , &(args_info->new_pin_given),
1311                 &(local_args_info.new_pin_given), optarg, 0, 0, ARG_NO,
1312                 check_ambiguity, override, 0, 0,
1313                 "new-pin", '-',
1314                 additional_error))
1315               goto failure;
1316 
1317           }
1318           /* Use (several times) to change one or more biometric templates.  */
1319           else if (strcmp (long_options[option_index].name, "new-bio") == 0)
1320           {
1321             args_info->soc_mode_counter += 1;
1322 
1323             local_args_info.new_bio_given++;
1324 
1325           }
1326           /* Dump Information about the SoCManager's configuration.  */
1327           else if (strcmp (long_options[option_index].name, "info") == 0)
1328           {
1329             args_info->soc_mode_counter += 1;
1330 
1331 
1332             if (update_arg( 0 ,
1333                  0 , &(args_info->info_given),
1334                 &(local_args_info.info_given), optarg, 0, 0, ARG_NO,
1335                 check_ambiguity, override, 0, 0,
1336                 "info", '-',
1337                 additional_error))
1338               goto failure;
1339 
1340           }
1341           /* Print the card ID.  */
1342           else if (strcmp (long_options[option_index].name, "print-cardid") == 0)
1343           {
1344             args_info->pxs_mode_counter += 1;
1345 
1346 
1347             if (update_arg( 0 ,
1348                  0 , &(args_info->print_cardid_given),
1349                 &(local_args_info.print_cardid_given), optarg, 0, 0, ARG_NO,
1350                 check_ambiguity, override, 0, 0,
1351                 "print-cardid", '-',
1352                 additional_error))
1353               goto failure;
1354 
1355           }
1356           /* Write the specified card ID.  */
1357           else if (strcmp (long_options[option_index].name, "write-cardid") == 0)
1358           {
1359             args_info->pxs_mode_counter += 1;
1360 
1361 
1362             if (update_arg( (void *)&(args_info->write_cardid_arg),
1363                  &(args_info->write_cardid_orig), &(args_info->write_cardid_given),
1364                 &(local_args_info.write_cardid_given), optarg, 0, 0, ARG_STRING,
1365                 check_ambiguity, override, 0, 0,
1366                 "write-cardid", '-',
1367                 additional_error))
1368               goto failure;
1369 
1370           }
1371           /* Print the PAccess ID.  */
1372           else if (strcmp (long_options[option_index].name, "print-paccessid") == 0)
1373           {
1374             args_info->pxs_mode_counter += 1;
1375 
1376 
1377             if (update_arg( 0 ,
1378                  0 , &(args_info->print_paccessid_given),
1379                 &(local_args_info.print_paccessid_given), optarg, 0, 0, ARG_NO,
1380                 check_ambiguity, override, 0, 0,
1381                 "print-paccessid", '-',
1382                 additional_error))
1383               goto failure;
1384 
1385           }
1386           /* Write the specified PAccess ID.  */
1387           else if (strcmp (long_options[option_index].name, "write-paccessid") == 0)
1388           {
1389             args_info->pxs_mode_counter += 1;
1390 
1391 
1392             if (update_arg( (void *)&(args_info->write_paccessid_arg),
1393                  &(args_info->write_paccessid_orig), &(args_info->write_paccessid_given),
1394                 &(local_args_info.write_paccessid_given), optarg, 0, 0, ARG_STRING,
1395                 check_ambiguity, override, 0, 0,
1396                 "write-paccessid", '-',
1397                 additional_error))
1398               goto failure;
1399 
1400           }
1401           /* Read the specified data group; use several times to read out multiple files.  */
1402           else if (strcmp (long_options[option_index].name, "read-dg") == 0)
1403           {
1404             args_info->pxs_mode_counter += 1;
1405 
1406             if (update_multiple_arg_temp(&read_dg_list,
1407                 &(local_args_info.read_dg_given), optarg, 0, 0, ARG_INT,
1408                 "read-dg", '-',
1409                 additional_error))
1410               goto failure;
1411 
1412           }
1413           /* Write output to a file instead of printing it; use once for each use of `--read-dg'.  */
1414           else if (strcmp (long_options[option_index].name, "out-file") == 0)
1415           {
1416             args_info->pxs_mode_counter += 1;
1417 
1418             if (update_multiple_arg_temp(&out_file_list,
1419                 &(local_args_info.out_file_given), optarg, 0, 0, ARG_STRING,
1420                 "out-file", '-',
1421                 additional_error))
1422               goto failure;
1423 
1424           }
1425           /* Write the specified data group; use several times to write multiple files.  */
1426           else if (strcmp (long_options[option_index].name, "write-dg") == 0)
1427           {
1428             args_info->pxs_mode_counter += 1;
1429 
1430             if (update_multiple_arg_temp(&write_dg_list,
1431                 &(local_args_info.write_dg_given), optarg, 0, 0, ARG_INT,
1432                 "write-dg", '-',
1433                 additional_error))
1434               goto failure;
1435 
1436           }
1437           /* Read input from a file; use once for each use of `--write-dg'.  */
1438           else if (strcmp (long_options[option_index].name, "in-file") == 0)
1439           {
1440             args_info->pxs_mode_counter += 1;
1441 
1442             if (update_multiple_arg_temp(&in_file_list,
1443                 &(local_args_info.in_file_given), optarg, 0, 0, ARG_STRING,
1444                 "in-file", '-',
1445                 additional_error))
1446               goto failure;
1447 
1448           }
1449           /* Delete the specified data group; use several times to delete multiple files.  */
1450           else if (strcmp (long_options[option_index].name, "delete-dg") == 0)
1451           {
1452             args_info->pxs_mode_counter += 1;
1453 
1454             if (update_multiple_arg_temp(&delete_dg_list,
1455                 &(local_args_info.delete_dg_given), optarg, 0, 0, ARG_INT,
1456                 "delete-dg", '-',
1457                 additional_error))
1458               goto failure;
1459 
1460           }
1461           /* Create the specified data group; use several times to create multiple files.  */
1462           else if (strcmp (long_options[option_index].name, "create-dg") == 0)
1463           {
1464             args_info->pxs_mode_counter += 1;
1465 
1466             if (update_multiple_arg_temp(&create_dg_list,
1467                 &(local_args_info.create_dg_given), optarg, 0, 0, ARG_INT,
1468                 "create-dg", '-',
1469                 additional_error))
1470               goto failure;
1471 
1472           }
1473           /* File size of newly created DGs.  */
1474           else if (strcmp (long_options[option_index].name, "new-size") == 0)
1475           {
1476             args_info->pxs_mode_counter += 1;
1477 
1478 
1479             if (update_arg( (void *)&(args_info->new_size_arg),
1480                  &(args_info->new_size_orig), &(args_info->new_size_given),
1481                 &(local_args_info.new_size_given), optarg, 0, "256", ARG_INT,
1482                 check_ambiguity, override, 0, 0,
1483                 "new-size", '-',
1484                 additional_error))
1485               goto failure;
1486 
1487           }
1488           /* Access condition for reading newly created DGs.  */
1489           else if (strcmp (long_options[option_index].name, "new-read-ac") == 0)
1490           {
1491             args_info->pxs_mode_counter += 1;
1492 
1493 
1494             if (update_arg( (void *)&(args_info->new_read_ac_arg),
1495                  &(args_info->new_read_ac_orig), &(args_info->new_read_ac_given),
1496                 &(local_args_info.new_read_ac_given), optarg, cmdline_parser_new_read_ac_values, "sm", ARG_STRING,
1497                 check_ambiguity, override, 0, 0,
1498                 "new-read-ac", '-',
1499                 additional_error))
1500               goto failure;
1501 
1502           }
1503           /* Required access bits in certificate's CHAT for reading newly created DGs.  */
1504           else if (strcmp (long_options[option_index].name, "new-read-ac-chatbit") == 0)
1505           {
1506             args_info->pxs_mode_counter += 1;
1507 
1508             if (update_multiple_arg_temp(&new_read_ac_chatbit_list,
1509                 &(local_args_info.new_read_ac_chatbit_given), optarg, 0, 0, ARG_INT,
1510                 "new-read-ac-chatbit", '-',
1511                 additional_error))
1512               goto failure;
1513 
1514           }
1515           /* Access condition for writing newly created DGs.  */
1516           else if (strcmp (long_options[option_index].name, "new-write-ac") == 0)
1517           {
1518             args_info->pxs_mode_counter += 1;
1519 
1520 
1521             if (update_arg( (void *)&(args_info->new_write_ac_arg),
1522                  &(args_info->new_write_ac_orig), &(args_info->new_write_ac_given),
1523                 &(local_args_info.new_write_ac_given), optarg, cmdline_parser_new_write_ac_values, "sm", ARG_STRING,
1524                 check_ambiguity, override, 0, 0,
1525                 "new-write-ac", '-',
1526                 additional_error))
1527               goto failure;
1528 
1529           }
1530           /* Required access bits in certificate's CHAT for reading newly created DGs.  */
1531           else if (strcmp (long_options[option_index].name, "new-write-ac-chatbit") == 0)
1532           {
1533             args_info->pxs_mode_counter += 1;
1534 
1535             if (update_multiple_arg_temp(&new_write_ac_chatbit_list,
1536                 &(local_args_info.new_write_ac_chatbit_given), optarg, 0, 0, ARG_INT,
1537                 "new-write-ac-chatbit", '-',
1538                 additional_error))
1539               goto failure;
1540 
1541           }
1542 
1543           break;
1544         case '?':	/* Invalid option.  */
1545           /* `getopt_long' already printed an error message.  */
1546           goto failure;
1547 
1548         default:	/* bug: option not considered.  */
1549           fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
1550           abort ();
1551         } /* switch */
1552     } /* while */
1553 
1554 
1555   update_multiple_arg((void *)&(args_info->certificate_arg),
1556     &(args_info->certificate_orig), args_info->certificate_given,
1557     local_args_info.certificate_given, 0,
1558     ARG_STRING, certificate_list);
1559   update_multiple_arg((void *)&(args_info->read_dg_arg),
1560     &(args_info->read_dg_orig), args_info->read_dg_given,
1561     local_args_info.read_dg_given, 0,
1562     ARG_INT, read_dg_list);
1563   update_multiple_arg((void *)&(args_info->out_file_arg),
1564     &(args_info->out_file_orig), args_info->out_file_given,
1565     local_args_info.out_file_given, 0,
1566     ARG_STRING, out_file_list);
1567   update_multiple_arg((void *)&(args_info->write_dg_arg),
1568     &(args_info->write_dg_orig), args_info->write_dg_given,
1569     local_args_info.write_dg_given, 0,
1570     ARG_INT, write_dg_list);
1571   update_multiple_arg((void *)&(args_info->in_file_arg),
1572     &(args_info->in_file_orig), args_info->in_file_given,
1573     local_args_info.in_file_given, 0,
1574     ARG_STRING, in_file_list);
1575   update_multiple_arg((void *)&(args_info->delete_dg_arg),
1576     &(args_info->delete_dg_orig), args_info->delete_dg_given,
1577     local_args_info.delete_dg_given, 0,
1578     ARG_INT, delete_dg_list);
1579   update_multiple_arg((void *)&(args_info->create_dg_arg),
1580     &(args_info->create_dg_orig), args_info->create_dg_given,
1581     local_args_info.create_dg_given, 0,
1582     ARG_INT, create_dg_list);
1583   update_multiple_arg((void *)&(args_info->new_read_ac_chatbit_arg),
1584     &(args_info->new_read_ac_chatbit_orig), args_info->new_read_ac_chatbit_given,
1585     local_args_info.new_read_ac_chatbit_given, 0,
1586     ARG_INT, new_read_ac_chatbit_list);
1587   update_multiple_arg((void *)&(args_info->new_write_ac_chatbit_arg),
1588     &(args_info->new_write_ac_chatbit_orig), args_info->new_write_ac_chatbit_given,
1589     local_args_info.new_write_ac_chatbit_given, 0,
1590     ARG_INT, new_write_ac_chatbit_list);
1591 
1592   args_info->verbose_given += local_args_info.verbose_given;
1593   local_args_info.verbose_given = 0;
1594   args_info->new_bio_given += local_args_info.new_bio_given;
1595   local_args_info.new_bio_given = 0;
1596   args_info->certificate_given += local_args_info.certificate_given;
1597   local_args_info.certificate_given = 0;
1598   args_info->read_dg_given += local_args_info.read_dg_given;
1599   local_args_info.read_dg_given = 0;
1600   args_info->out_file_given += local_args_info.out_file_given;
1601   local_args_info.out_file_given = 0;
1602   args_info->write_dg_given += local_args_info.write_dg_given;
1603   local_args_info.write_dg_given = 0;
1604   args_info->in_file_given += local_args_info.in_file_given;
1605   local_args_info.in_file_given = 0;
1606   args_info->delete_dg_given += local_args_info.delete_dg_given;
1607   local_args_info.delete_dg_given = 0;
1608   args_info->create_dg_given += local_args_info.create_dg_given;
1609   local_args_info.create_dg_given = 0;
1610   args_info->new_read_ac_chatbit_given += local_args_info.new_read_ac_chatbit_given;
1611   local_args_info.new_read_ac_chatbit_given = 0;
1612   args_info->new_write_ac_chatbit_given += local_args_info.new_write_ac_chatbit_given;
1613   local_args_info.new_write_ac_chatbit_given = 0;
1614 
1615   if (args_info->pxs_mode_counter && args_info->soc_mode_counter) {
1616     int pxs_given[] = {args_info->certificate_given, args_info->key_given, args_info->print_cardid_given, args_info->write_cardid_given, args_info->print_paccessid_given, args_info->write_paccessid_given, args_info->read_dg_given, args_info->out_file_given, args_info->write_dg_given, args_info->in_file_given, args_info->delete_dg_given, args_info->create_dg_given, args_info->new_size_given, args_info->new_read_ac_given, args_info->new_read_ac_chatbit_given, args_info->new_write_ac_given, args_info->new_write_ac_chatbit_given,  -1};
1617     const char *pxs_desc[] = {"--certificate", "--key", "--print-cardid", "--write-cardid", "--print-paccessid", "--write-paccessid", "--read-dg", "--out-file", "--write-dg", "--in-file", "--delete-dg", "--create-dg", "--new-size", "--new-read-ac", "--new-read-ac-chatbit", "--new-write-ac", "--new-write-ac-chatbit",  0};
1618     int soc_given[] = {args_info->new_pin_given, args_info->new_bio_given, args_info->info_given,  -1};
1619     const char *soc_desc[] = {"--new-pin", "--new-bio", "--info",  0};
1620     error_occurred += check_modes(pxs_given, pxs_desc, soc_given, soc_desc);
1621   }
1622 
1623   if (check_required)
1624     {
1625       error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error);
1626     }
1627 
1628   cmdline_parser_release (&local_args_info);
1629 
1630   if ( error_occurred )
1631     return (EXIT_FAILURE);
1632 
1633   return 0;
1634 
1635 failure:
1636   free_list (certificate_list, 1 );
1637   free_list (read_dg_list, 0 );
1638   free_list (out_file_list, 1 );
1639   free_list (write_dg_list, 0 );
1640   free_list (in_file_list, 1 );
1641   free_list (delete_dg_list, 0 );
1642   free_list (create_dg_list, 0 );
1643   free_list (new_read_ac_chatbit_list, 0 );
1644   free_list (new_write_ac_chatbit_list, 0 );
1645 
1646   cmdline_parser_release (&local_args_info);
1647   return (EXIT_FAILURE);
1648 }
1649 /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */
1650