clish.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //-------------------------------------
  2. // clish.cpp
  3. //
  4. // A simple client for libclish
  5. //-------------------------------------
  6. #ifdef HAVE_CONFIG_H
  7. #include "config.h"
  8. #endif /* HAVE_CONFIG_H */
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #ifdef HAVE_GETOPT_H
  14. #include <getopt.h>
  15. #endif
  16. #include <signal.h>
  17. #include "clish/shell.h"
  18. #include "clish/internal.h"
  19. #ifndef VERSION
  20. #define VERSION 1.2.2
  21. #endif
  22. #define QUOTE(t) #t
  23. /* #define version(v) printf("%s\n", QUOTE(v)) */
  24. #define version(v) printf("%s\n", v)
  25. /* Hooks */
  26. static clish_shell_hooks_t my_hooks = {
  27. NULL, /* don't worry about init callback */
  28. clish_access_callback,
  29. NULL, /* don't worry about cmd_line callback */
  30. clish_script_callback,
  31. NULL, /* don't worry about fini callback */
  32. clish_config_callback,
  33. NULL /* don't register any builtin functions */
  34. };
  35. static void help(int status, const char *argv0);
  36. /*--------------------------------------------------------- */
  37. int main(int argc, char **argv)
  38. {
  39. bool_t running;
  40. int result = -1;
  41. clish_shell_t * shell;
  42. /* Command line options */
  43. const char *socket_path = KONFD_SOCKET_PATH;
  44. bool_t lockless = BOOL_FALSE;
  45. bool_t stop_on_error = BOOL_FALSE;
  46. bool_t interactive = BOOL_TRUE;
  47. bool_t quiet = BOOL_FALSE;
  48. bool_t utf8 = BOOL_FALSE;
  49. const char *xml_path = getenv("CLISH_PATH");
  50. const char *view = getenv("CLISH_VIEW");
  51. const char *viewid = getenv("CLISH_VIEWID");
  52. FILE *outfd = stdout;
  53. /* Signal vars */
  54. struct sigaction sigpipe_act;
  55. sigset_t sigpipe_set;
  56. static const char *shortopts = "hvs:ledx:w:i:bqu";
  57. #ifdef HAVE_GETOPT_H
  58. static const struct option longopts[] = {
  59. {"help", 0, NULL, 'h'},
  60. {"version", 0, NULL, 'v'},
  61. {"socket", 1, NULL, 's'},
  62. {"lockless", 0, NULL, 'l'},
  63. {"stop-on-error", 0, NULL, 'e'},
  64. {"dry-run", 0, NULL, 'd'},
  65. {"xml-path", 1, NULL, 'x'},
  66. {"view", 1, NULL, 'w'},
  67. {"viewid", 1, NULL, 'i'},
  68. {"background", 0, NULL, 'b'},
  69. {"quiet", 0, NULL, 'q'},
  70. {"utf8", 0, NULL, 'u'},
  71. {NULL, 0, NULL, 0}
  72. };
  73. #endif
  74. /* Ignore SIGPIPE */
  75. sigemptyset(&sigpipe_set);
  76. sigaddset(&sigpipe_set, SIGPIPE);
  77. sigpipe_act.sa_flags = 0;
  78. sigpipe_act.sa_mask = sigpipe_set;
  79. sigpipe_act.sa_handler = SIG_IGN;
  80. sigaction(SIGPIPE, &sigpipe_act, NULL);
  81. /* Parse command line options */
  82. optind = 0;
  83. while(1) {
  84. int opt;
  85. #ifdef HAVE_GETOPT_H
  86. opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  87. #else
  88. opt = getopt(argc, argv, shortopts);
  89. #endif
  90. if (-1 == opt)
  91. break;
  92. switch (opt) {
  93. case 's':
  94. socket_path = optarg;
  95. break;
  96. case 'l':
  97. lockless = BOOL_TRUE;
  98. break;
  99. case 'e':
  100. stop_on_error = BOOL_TRUE;
  101. break;
  102. case 'b':
  103. interactive = BOOL_FALSE;
  104. break;
  105. case 'q':
  106. quiet = BOOL_TRUE;
  107. break;
  108. case 'u':
  109. utf8 = BOOL_TRUE;
  110. break;
  111. case 'd':
  112. my_hooks.script_fn = clish_dryrun_callback;
  113. break;
  114. case 'x':
  115. xml_path = optarg;
  116. break;
  117. case 'w':
  118. view = optarg;
  119. break;
  120. case 'i':
  121. viewid = optarg;
  122. break;
  123. case 'h':
  124. help(0, argv[0]);
  125. exit(0);
  126. break;
  127. case 'v':
  128. version(VERSION);
  129. exit(0);
  130. break;
  131. default:
  132. help(-1, argv[0]);
  133. exit(-1);
  134. break;
  135. }
  136. }
  137. /* Create shell instance */
  138. if (quiet)
  139. outfd = fopen("/dev/null", "w");
  140. shell = clish_shell_new(&my_hooks, NULL, NULL, outfd, stop_on_error);
  141. if (!shell) {
  142. fprintf(stderr, "Cannot run clish.\n");
  143. return -1;
  144. }
  145. /* Load the XML files */
  146. clish_shell_load_scheme(shell, xml_path);
  147. /* Set communication to the konfd */
  148. clish_shell__set_socket(shell, socket_path);
  149. /* Set lockless mode */
  150. if (lockless)
  151. clish_shell__set_lockfile(shell, NULL);
  152. /* Set interactive mode */
  153. if (!interactive)
  154. clish_shell__set_interactive(shell, interactive);
  155. /* Set startup view */
  156. if (view)
  157. clish_shell__set_startup_view(shell, view);
  158. /* Set startup viewid */
  159. if (viewid)
  160. clish_shell__set_startup_viewid(shell, viewid);
  161. /* Set UTF-8 mode if needed */
  162. clish_shell__set_utf8(shell, utf8);
  163. /* Execute startup */
  164. running = clish_shell_startup(shell);
  165. if (!running) {
  166. fprintf(stderr, "Cannot startup clish.\n");
  167. clish_shell_delete(shell);
  168. return -1;
  169. }
  170. if(optind < argc) {
  171. int i;
  172. /* Run the commands from the files */
  173. for (i = argc - 1; i >= optind; i--)
  174. clish_shell_push_file(shell, argv[i], stop_on_error);
  175. } else {
  176. /* The interactive shell */
  177. clish_shell_push_fd(shell, fdopen(dup(fileno(stdin)), "r"), stop_on_error);
  178. }
  179. result = clish_shell_loop(shell);
  180. /* Cleanup */
  181. clish_shell_delete(shell);
  182. if (quiet)
  183. fclose(outfd);
  184. return result ? 0 : -1;
  185. }
  186. /*--------------------------------------------------------- */
  187. /* Print help message */
  188. static void help(int status, const char *argv0)
  189. {
  190. const char *name = NULL;
  191. if (!argv0)
  192. return;
  193. /* Find the basename */
  194. name = strrchr(argv0, '/');
  195. if (name)
  196. name++;
  197. else
  198. name = argv0;
  199. if (status != 0) {
  200. fprintf(stderr, "Try `%s -h' for more information.\n",
  201. name);
  202. } else {
  203. printf("Usage: %s [options]\n", name);
  204. printf("CLI utility. "
  205. "The part of the klish project.\n");
  206. printf("Options:\n");
  207. printf("\t-v, --version\tPrint version.\n");
  208. printf("\t-h, --help\tPrint this help.\n");
  209. printf("\t-s <path>, --socket=<path>\tSpecify listen socket "
  210. "of the konfd daemon.\n");
  211. printf("\t-l, --lockless\tDon't use locking mechanism.\n");
  212. printf("\t-e, --stop-on-error\tStop programm execution on error.\n");
  213. printf("\t-b, --background\tStart shell using non-interactive mode.\n");
  214. printf("\t-q, --quiet\tDisable echo while executing commands from the file stream.\n");
  215. printf("\t-d, --dry-run\tDon't actually execute ACTION scripts.\n");
  216. printf("\t-x, --xml-path\tPath to XML scheme files.\n");
  217. printf("\t-w, --view\tSet the startup view.\n");
  218. printf("\t-i, --viewid\tSet the startup viewid.\n");
  219. printf("\t-u, --utf8\tSuppose the console mode is UTF-8.\n");
  220. }
  221. }