opts.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #define _GNU_SOURCE
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <syslog.h>
  8. #include <unistd.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <getopt.h>
  14. #include <time.h>
  15. #include <faux/faux.h>
  16. #include <faux/str.h>
  17. #include <faux/ini.h>
  18. #include <faux/log.h>
  19. #include <faux/conv.h>
  20. #include <klish/ktp_session.h>
  21. #include "private.h"
  22. /** @brief Initialize option structure by defaults
  23. */
  24. struct options *opts_init(void)
  25. {
  26. struct options *opts = NULL;
  27. opts = faux_zmalloc(sizeof(*opts));
  28. assert(opts);
  29. // Initialize
  30. opts->pidfile = faux_str_dup(DEFAULT_PIDFILE);
  31. opts->cfgfile = faux_str_dup(DEFAULT_CFGFILE);
  32. opts->socket_cfg.path = faux_str_dup(KLISH_DEFAULT_UNIX_SOCKET_PATH);
  33. opts->cfgfile_userdefined = BOOL_FALSE;
  34. opts->foreground = BOOL_FALSE; // Daemonize by default
  35. opts->verbose = BOOL_FALSE;
  36. opts->log_facility = LOG_DAEMON;
  37. opts->dbs = faux_str_dup(DEFAULT_DBS);
  38. return opts;
  39. }
  40. /** @brief Free options structure
  41. */
  42. void opts_free(struct options *opts)
  43. {
  44. faux_str_free(opts->pidfile);
  45. faux_str_free(opts->cfgfile);
  46. faux_str_free(opts->socket_cfg.path);
  47. faux_str_free(opts->socket_cfg.user);
  48. faux_str_free(opts->socket_cfg.group);
  49. faux_str_free(opts->socket_cfg.mode);
  50. faux_str_free(opts->dbs);
  51. faux_free(opts);
  52. }
  53. /** @brief Parse command line options
  54. */
  55. int opts_parse(int argc, char *argv[], struct options *opts)
  56. {
  57. static const char *shortopts = "hp:f:dl:v";
  58. static const struct option longopts[] = {
  59. {"help", 0, NULL, 'h'},
  60. {"pid", 1, NULL, 'p'},
  61. {"conf", 1, NULL, 'f'},
  62. {"foreground", 0, NULL, 'd'},
  63. {"verbose", 0, NULL, 'v'},
  64. {"facility", 1, NULL, 'l'},
  65. {NULL, 0, NULL, 0}
  66. };
  67. optind = 1;
  68. while(1) {
  69. int opt = 0;
  70. opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  71. if (-1 == opt)
  72. break;
  73. switch (opt) {
  74. case 'p':
  75. faux_str_free(opts->pidfile);
  76. opts->pidfile = faux_str_dup(optarg);
  77. break;
  78. case 'f':
  79. faux_str_free(opts->cfgfile);
  80. opts->cfgfile = faux_str_dup(optarg);
  81. opts->cfgfile_userdefined = BOOL_TRUE;
  82. break;
  83. case 'd':
  84. opts->foreground = BOOL_TRUE;
  85. break;
  86. case 'v':
  87. opts->verbose = BOOL_TRUE;
  88. break;
  89. case 'l':
  90. if (faux_log_facility_id(optarg, &(opts->log_facility))) {
  91. fprintf(stderr, "Error: Illegal syslog facility %s.\n", optarg);
  92. _exit(-1);
  93. }
  94. break;
  95. case 'h':
  96. help(0, argv[0]);
  97. _exit(0);
  98. break;
  99. default:
  100. help(-1, argv[0]);
  101. _exit(-1);
  102. break;
  103. }
  104. }
  105. return 0;
  106. }
  107. /** @brief Print help message
  108. */
  109. void help(int status, const char *argv0)
  110. {
  111. const char *name = NULL;
  112. if (!argv0)
  113. return;
  114. // Find the basename
  115. name = strrchr(argv0, '/');
  116. if (name)
  117. name++;
  118. else
  119. name = argv0;
  120. if (status != 0) {
  121. fprintf(stderr, "Try `%s -h' for more information.\n",
  122. name);
  123. } else {
  124. printf("Version : %s\n", VERSION);
  125. printf("Usage : %s [options]\n", name);
  126. printf("Klish daemon\n");
  127. printf("Options :\n");
  128. printf("\t-h, --help Print this help.\n");
  129. printf("\t-d, --foreground Don't daemonize.\n");
  130. printf("\t-v, --verbose Be verbose.\n");
  131. printf("\t-p <path>, --pid=<path> File to save daemon's PID to ("
  132. DEFAULT_PIDFILE ").\n");
  133. printf("\t-f <path>, --conf=<path> Config file ("
  134. DEFAULT_CFGFILE ").\n");
  135. printf("\t-l, --facility Syslog facility (DAEMON).\n");
  136. }
  137. }
  138. /** @brief Parse config file
  139. *
  140. * It parses known options and put them to opts arg. But also it returns
  141. * parsed config file. The parts of config file can be unknown to klish
  142. * itself but can be known to third party plugins. For example DBs
  143. * subsystem get settings from config file.
  144. */
  145. faux_ini_t *config_parse(const char *cfgfile, struct options *opts)
  146. {
  147. faux_ini_t *ini = NULL;
  148. const char *tmp = NULL;
  149. ini = faux_ini_new();
  150. assert(ini);
  151. if (!ini)
  152. NULL;
  153. if (!faux_ini_parse_file(ini, cfgfile)) {
  154. syslog(LOG_ERR, "Can't parse config file: %s", cfgfile);
  155. faux_ini_free(ini);
  156. return NULL;
  157. }
  158. // UnixSocketPath
  159. if ((tmp = faux_ini_find(ini, "UnixSocketPath"))) {
  160. faux_str_free(opts->socket_cfg.path);
  161. opts->socket_cfg.path = faux_str_dup(tmp);
  162. }
  163. // UnixSocketUser
  164. if ((tmp = faux_ini_find(ini, "UnixSocketUser"))) {
  165. faux_str_free(opts->socket_cfg.user);
  166. opts->socket_cfg.user = faux_str_dup(tmp);
  167. }
  168. // UnixSocketGroup
  169. if ((tmp = faux_ini_find(ini, "UnixSocketGroup"))) {
  170. faux_str_free(opts->socket_cfg.group);
  171. opts->socket_cfg.group = faux_str_dup(tmp);
  172. }
  173. // UnixSocketMode
  174. if ((tmp = faux_ini_find(ini, "UnixSocketMode"))) {
  175. faux_str_free(opts->socket_cfg.mode);
  176. opts->socket_cfg.mode = faux_str_dup(tmp);
  177. }
  178. // DBs
  179. if ((tmp = faux_ini_find(ini, "DBs"))) {
  180. faux_str_free(opts->dbs);
  181. opts->dbs = faux_str_dup(tmp);
  182. }
  183. return ini;
  184. }
  185. /** @brief Show options. For debug purposes.
  186. */
  187. int opts_show(struct options *opts)
  188. {
  189. assert(opts);
  190. if (!opts)
  191. return -1;
  192. syslog(LOG_DEBUG, "opts: Foreground = %s\n", opts->foreground ? "true" : "false");
  193. syslog(LOG_DEBUG, "opts: Verbose = %s\n", opts->verbose ? "true" : "false");
  194. syslog(LOG_DEBUG, "opts: LogFacility = %s\n", faux_log_facility_str(opts->log_facility));
  195. syslog(LOG_DEBUG, "opts: PIDPath = %s\n", opts->pidfile);
  196. syslog(LOG_DEBUG, "opts: ConfigPath = %s\n", opts->cfgfile);
  197. syslog(LOG_DEBUG, "opts: UnixSocketPath = %s\n", opts->socket_cfg.path);
  198. syslog(LOG_DEBUG, "opts: UnixSocketUser = %s\n", opts->socket_cfg.user ? opts->socket_cfg.user : "None");
  199. syslog(LOG_DEBUG, "opts: UnixSocketGroup = %s\n", opts->socket_cfg.group ? opts->socket_cfg.group : "None");
  200. syslog(LOG_DEBUG, "opts: UnixSocketMode = %s\n", opts->socket_cfg.mode ? opts->socket_cfg.mode : "None");
  201. syslog(LOG_DEBUG, "opts: DBs = %s\n", opts->dbs);
  202. return 0;
  203. }