/* Demonstration of sub-command options in popt * * This program was written for demonstrational purposes * 2005-05-24 by Henrik Nordstrom and is placed in the public * domain. No righs reserved. You may use this program in any * way you may seem fit. * * The program is delivered as-is and comes with absolutely no * warranty of any kind. The author can not be held responsible * for any problems caused by using whole or parts of this * program for any purpose. */ #include #include #include #include const char *program_name; void usage(poptContext optCon, int exitcode, char *error, char *addl) { poptPrintUsage(optCon, stderr, 0); if (error) fprintf(stderr, "%s: %s\n", error, addl); exit(exitcode); } int argv_count(const char **argv) { int i; if (!argv) return 0; for (i = 0; *argv++; i++); return i; } /**** Global *****/ const char *global_1 = "default global 1"; const char *global_2 = "default global 2"; struct poptOption global_options[] = { {"opt1", 0, POPT_ARG_STRING, &global_1, 0, "Global option 1", "String used for global option 2"}, {"opt2", 0, POPT_ARG_STRING, &global_2, 0, "Global option 2", "String used for global option 2"}, {NULL, 0, 0, NULL, 0, NULL, NULL} }; #define GLOBAL_POPT_TABLE {NULL, 0, POPT_ARG_INCLUDE_TABLE, global_options, 0, "Global options:", NULL}, void module_global(void) { printf("global1: %s\n", global_1); printf("global2: %s\n", global_2); } /**** Module 1 *****/ const char *og1_1 = "default 1 1"; struct poptOption module1_options[] = { {"og1_1", 0, POPT_ARG_STRING, &og1_1, 0, "Common option 1 1", "String used for option 1 1"}, {NULL, 0, 0, NULL, 0, NULL, NULL} }; #define MODULE1_POPT_TABLE {NULL, 0, POPT_ARG_INCLUDE_TABLE, module1_options, 0, "Module 1 options:", NULL}, void module1(void) { printf("og1_1: %s\n", og1_1); } /***** Module 2 ******/ const char *og2_1 = "default 2 1"; const char *module2_login = NULL; const char *module2_password = NULL; void module2_parse_password(const struct poptOption *opt, const char *arg, void *data) { char *login = strdup(arg); char *password = strchr(login, ':'); if (!password) { fprintf(stderr, "ERROR: --%s requires a login:password\n", opt->longName); exit(1); } *password++ = '\0'; module2_login = login; module2_password = password; } void module2_parse(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, void *data) { switch (opt->val) { case 2: /* og2_2 */ module2_parse_password(opt, arg, data); break; default: fprintf(stderr, "Unexpected callbal for %s\n", opt->longName); break; } } struct poptOption module2_options[] = { {NULL, 0, POPT_ARG_CALLBACK, module2_parse, 0, NULL, NULL}, MODULE1_POPT_TABLE {"og2_1", 0, POPT_ARG_STRING, &og2_1, 0, "Common option 2 1", "String used for option 2 1"}, {"og2_2", 0, POPT_ARG_STRING, NULL, 2, "Common option 2 2", "login:password"}, {NULL, 0, 0, NULL, 0, NULL, NULL} }; #define MODULE2_POPT_TABLE {NULL, 0, POPT_ARG_INCLUDE_TABLE, module2_options, 0, "Module 2 options:", NULL}, void module2(void) { printf("og2_1: %s\n", og2_1); printf("login: %s\n", module2_login); printf("password: %s\n", module2_password); } /* Sub command 1. Uses Module 1 */ int sub_command1(int argc, char *argv[]) { const char *test = "default"; const char *recipient; int opt; struct poptOption options[] = { {"test", 0, POPT_ARG_STRING, &test, 0, "Test", "Message text"}, GLOBAL_POPT_TABLE MODULE1_POPT_TABLE POPT_AUTOHELP {NULL, 0, 0, NULL, 0, NULL, NULL} }; poptContext optCon = poptGetContext(NULL, argc, (const char **)argv, options, 0); poptSetOtherOptionHelp(optCon,"command1 [OPTION...] recipient..."); while ((opt = poptGetNextOpt(optCon)) >= 0) { switch (opt) { default: fprintf(stderr, "Unexpected option %d\n", opt); exit(1); } } if (opt != -1) { fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(opt)); poptPrintUsage(optCon, stderr, 0); exit(1); } if (poptPeekArg(optCon) == NULL) { poptPrintUsage(optCon, stderr, 0); exit(1); } module_global(); module1(); printf("Message: %s\n", test); while ((recipient = poptGetArg(optCon)) != NULL) { printf("Recipient: %s\n", recipient); } return 1; } /* Sub command 2. Uses Module 1 & 2 */ int sub_command2(int argc, char *argv[]) { const char *test = "default"; int opt; struct poptOption options[] = { {"test", 0, POPT_ARG_STRING, &test, 0, "Testing", "String"}, GLOBAL_POPT_TABLE MODULE2_POPT_TABLE POPT_AUTOHELP {NULL, 0, 0, NULL, 0, NULL, NULL} }; poptContext optCon = poptGetContext(NULL, argc, (const char **)argv, options, 0); poptSetOtherOptionHelp(optCon, "command2 [OPTION...]"); while ((opt = poptGetNextOpt(optCon)) >= 0) { switch (opt) { default: fprintf(stderr, "Unexpected option %d\n", opt); exit(1); } } if (opt != -1) { fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(opt)); poptPrintUsage(optCon, stderr, 0); exit(1); } if (poptPeekArg(optCon) != NULL) { poptPrintUsage(optCon, stderr, 0); exit(1); } module_global(); module1(); module2(); return 1; } /* Main */ int main(int argc, char *argv[]) { const char *command; const char **sub_argv; int sub_argc; int opt; int ret; struct poptOption options[] = { GLOBAL_POPT_TABLE {"help", '?', POPT_ARG_NONE, NULL, 1, "Show this help message", NULL}, {"usage", 0, POPT_ARG_NONE, NULL, 2, "Display brief usage message", NULL}, {NULL, 0, 0, NULL, 0, NULL, NULL} }; poptContext optCon = poptGetContext(NULL, argc, (const char **)argv, options, POPT_CONTEXT_POSIXMEHARDER); poptSetOtherOptionHelp(optCon, " [OPTION...]"); program_name = argv[0]; while ((opt = poptGetNextOpt(optCon)) >= 0) { switch (opt) { case 1: poptPrintHelp(optCon, stderr, 0); fprintf(stderr, "\n"); fprintf(stderr, "Available commands:\n"); fprintf(stderr, " %-42s %s\n", "command1", "Silly example command"); fprintf(stderr, " %-42s %s\n", "command2", "Another silly example command"); exit(0); case 2: poptPrintUsage(optCon, stderr, 0); exit(0); default: fprintf(stderr, "Unexpected option %d\n", opt); exit(1); } } if (opt != -1) { fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(opt)); poptPrintUsage(optCon, stderr, 0); exit(1); } command = poptGetArg(optCon); if (!command) { poptPrintUsage(optCon, stderr, 0); exit(1); } argc = poptStrippedArgv(optCon, argc, argv); if (strcmp(command, "command1") == 0) ret = sub_command1(argc, argv); else if (strcmp(command, "command2") == 0) ret = sub_command2(argc, argv); else { fprintf(stderr, "Unknown command '%s'\n", command); poptPrintUsage(optCon, stderr, 0); exit(1); } poptFreeContext(optCon); return ret; }