opts.c 4.8 KB

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