opts.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <getopt.h>
  12. #include <faux/faux.h>
  13. #include <faux/str.h>
  14. #include <faux/list.h>
  15. #include <faux/ini.h>
  16. #include <klish/ktp_session.h>
  17. #include "private.h"
  18. /** @brief Initialize option structure by defaults
  19. */
  20. struct options *opts_init(void)
  21. {
  22. struct options *opts = NULL;
  23. opts = faux_zmalloc(sizeof(*opts));
  24. assert(opts);
  25. // Initialize
  26. opts->verbose = BOOL_FALSE;
  27. opts->stop_on_error = BOOL_FALSE;
  28. opts->dry_run = BOOL_FALSE;
  29. opts->quiet = BOOL_FALSE;
  30. opts->cfgfile = faux_str_dup(DEFAULT_CFGFILE);
  31. opts->cfgfile_userdefined = BOOL_FALSE;
  32. opts->unix_socket_path = faux_str_dup(KLISH_DEFAULT_UNIX_SOCKET_PATH);
  33. opts->pager = faux_str_dup(DEFAULT_PAGER);
  34. // Don't free command list because elements are the pointers to
  35. // command line options and don't need to be freed().
  36. opts->commands = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  37. NULL, NULL, NULL);
  38. opts->files = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  39. NULL, NULL, NULL);
  40. return opts;
  41. }
  42. /** @brief Free options structure
  43. */
  44. void opts_free(struct options *opts)
  45. {
  46. if (!opts)
  47. return;
  48. faux_str_free(opts->cfgfile);
  49. faux_str_free(opts->unix_socket_path);
  50. faux_str_free(opts->pager);
  51. faux_list_free(opts->commands);
  52. faux_list_free(opts->files);
  53. faux_free(opts);
  54. }
  55. /** @brief Parse command line options
  56. */
  57. int opts_parse(int argc, char *argv[], struct options *opts)
  58. {
  59. static const char *shortopts = "hvf:c:erq";
  60. static const struct option longopts[] = {
  61. {"conf", 1, NULL, 'f'},
  62. {"help", 0, NULL, 'h'},
  63. {"verbose", 0, NULL, 'v'},
  64. {"command", 1, NULL, 'c'},
  65. {"stop-on-error", 0, NULL, 'e'},
  66. {"dry-run", 0, NULL, 'r'},
  67. {"quiet", 0, NULL, 'q'},
  68. {NULL, 0, NULL, 0}
  69. };
  70. optind = 1;
  71. while(1) {
  72. int opt = 0;
  73. opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  74. if (-1 == opt)
  75. break;
  76. switch (opt) {
  77. case 'v':
  78. opts->verbose = BOOL_TRUE;
  79. break;
  80. case 'e':
  81. opts->stop_on_error = BOOL_TRUE;
  82. break;
  83. case 'r':
  84. opts->dry_run = BOOL_TRUE;
  85. break;
  86. case 'q':
  87. opts->quiet = BOOL_TRUE;
  88. break;
  89. case 'h':
  90. help(0, argv[0]);
  91. _exit(0);
  92. break;
  93. case 'c':
  94. faux_list_add(opts->commands, optarg);
  95. break;
  96. case 'f':
  97. faux_str_free(opts->cfgfile);
  98. opts->cfgfile = faux_str_dup(optarg);
  99. opts->cfgfile_userdefined = BOOL_TRUE;
  100. break;
  101. default:
  102. help(-1, argv[0]);
  103. _exit(-1);
  104. break;
  105. }
  106. }
  107. // Input files
  108. if(optind < argc) {
  109. int i;
  110. for (i = argc - 1; i >= optind; i--)
  111. faux_list_add(opts->files, argv[i]);
  112. }
  113. // Validate options
  114. // Commands specified by '-c' option can't coexist with input files
  115. if (!faux_list_is_empty(opts->commands) &&
  116. !faux_list_is_empty(opts->files)) {
  117. fprintf(stderr, "Error: Commands specified by '-c' can't coexist "
  118. "with input files\n");
  119. _exit(-1);
  120. }
  121. return 0;
  122. }
  123. /** @brief Print help message
  124. */
  125. void help(int status, const char *argv0)
  126. {
  127. const char *name = NULL;
  128. if (!argv0)
  129. return;
  130. // Find the basename
  131. name = strrchr(argv0, '/');
  132. if (name)
  133. name++;
  134. else
  135. name = argv0;
  136. if (status != 0) {
  137. fprintf(stderr, "Try `%s -h' for more information.\n",
  138. name);
  139. } else {
  140. printf("Version : %s\n", VERSION);
  141. printf("Usage : %s [options] [filename] ... [filename]\n", name);
  142. printf("Klish client\n");
  143. printf("Options :\n");
  144. printf("\t-h, --help Print this help.\n");
  145. printf("\t-v, --verbose Be verbose.\n");
  146. printf("\t-c <line>, --command=<line> Command to execute.\n"
  147. "\t\tMultiple options are allowed.\n");
  148. printf("\t-e, --stop-on-error Stop script execution on error.\n");
  149. printf("\t-q, --quiet Disable echo while executing commands\n\t\tfrom the file stream.\n");
  150. printf("\t-r, --dry-run Don't actually execute ACTION scripts.\n");
  151. printf("\t-f <path>, --conf=<path> Config file ("
  152. DEFAULT_CFGFILE ").\n");
  153. }
  154. }
  155. /** @brief Parse config file
  156. *
  157. */
  158. bool_t config_parse(const char *cfgfile, struct options *opts)
  159. {
  160. faux_ini_t *ini = NULL;
  161. const char *tmp = NULL;
  162. ini = faux_ini_new();
  163. assert(ini);
  164. if (!ini)
  165. NULL;
  166. if (!faux_ini_parse_file(ini, cfgfile)) {
  167. fprintf(stderr, "Error: Can't parse config file \"%s\"\n", cfgfile);
  168. faux_ini_free(ini);
  169. return BOOL_FALSE;
  170. }
  171. // UnixSocketPath
  172. if ((tmp = faux_ini_find(ini, "UnixSocketPath"))) {
  173. faux_str_free(opts->unix_socket_path);
  174. opts->unix_socket_path = faux_str_dup(tmp);
  175. }
  176. // DBs
  177. if ((tmp = faux_ini_find(ini, "Pager"))) {
  178. faux_str_free(opts->pager);
  179. opts->pager = faux_str_dup(tmp);
  180. }
  181. faux_ini_free(ini);
  182. return BOOL_TRUE;
  183. }