shell_internal.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * shell_internal.c
  3. */
  4. #include "private.h"
  5. #include "lub/string.h"
  6. #include "lub/argv.h"
  7. #include <assert.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <errno.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/file.h>
  16. #include <signal.h>
  17. #include <fcntl.h>
  18. /*----------------------------------------------------------- */
  19. /* Terminate the current shell session */
  20. CLISH_PLUGIN_SYM(clish_close)
  21. {
  22. clish_context_t *context = (clish_context_t *)clish_context;
  23. clish_shell_t *this = (clish_shell_t *)context->shell;
  24. this->state = SHELL_STATE_CLOSING;
  25. return 0;
  26. }
  27. /*----------------------------------------------------------- */
  28. /*
  29. Open a file and interpret it as a script in the context of a new
  30. thread. Whether the script continues after command, but not script,
  31. errors depends on the value of the stop_on_error flag.
  32. */
  33. static int clish_source_internal(clish_context_t *context,
  34. const char *fn, bool_t stop_on_error)
  35. {
  36. int result = -1;
  37. const char *filename = fn;
  38. struct stat fileStat;
  39. /* the exception proves the rule... */
  40. clish_shell_t *this = (clish_shell_t *)context->shell;
  41. /*
  42. * Check file specified is not a directory
  43. */
  44. if ((0 == stat((char *)filename, &fileStat)) &&
  45. (!S_ISDIR(fileStat.st_mode))) {
  46. /*
  47. * push this file onto the file stack associated with this
  48. * session. This will be closed by clish_shell_pop_file()
  49. * when it is finished with.
  50. */
  51. result = clish_shell_push_file(this, filename,
  52. stop_on_error);
  53. }
  54. return result ? -1 : 0;
  55. }
  56. /*----------------------------------------------------------- */
  57. /*
  58. Open a file and interpret it as a script in the context of a new
  59. thread. Invoking a script in this way will cause the script to
  60. stop on the first error
  61. */
  62. CLISH_PLUGIN_SYM(clish_source)
  63. {
  64. clish_context_t *context = (clish_context_t *)clish_context;
  65. return (clish_source_internal(context, script, BOOL_TRUE));
  66. }
  67. /*----------------------------------------------------------- */
  68. /*
  69. Open a file and interpret it as a script in the context of a new
  70. thread. Invoking a script in this way will cause the script to
  71. continue after command, but not script, errors.
  72. */
  73. CLISH_PLUGIN_SYM(clish_source_nostop)
  74. {
  75. clish_context_t *context = (clish_context_t *)clish_context;
  76. return (clish_source_internal(context, script, BOOL_FALSE));
  77. }
  78. /*----------------------------------------------------------- */
  79. /*
  80. Show the shell overview
  81. */
  82. CLISH_PLUGIN_SYM(clish_overview)
  83. {
  84. clish_context_t *context = (clish_context_t *)clish_context;
  85. clish_shell_t *this = context->shell;
  86. tinyrl_printf(this->tinyrl, "%s\n", context->shell->overview);
  87. return 0;
  88. }
  89. /*----------------------------------------------------------- */
  90. CLISH_PLUGIN_SYM(clish_history)
  91. {
  92. clish_context_t *context = (clish_context_t *)clish_context;
  93. clish_shell_t *this = context->shell;
  94. tinyrl_history_t *history = tinyrl__get_history(this->tinyrl);
  95. tinyrl_history_iterator_t iter;
  96. const tinyrl_history_entry_t *entry;
  97. unsigned limit = 0;
  98. const char *arg = script;
  99. if (arg && ('\0' != *arg)) {
  100. limit = (unsigned)atoi(arg);
  101. if (0 == limit) {
  102. /* unlimit the history list */
  103. (void)tinyrl_history_unstifle(history);
  104. } else {
  105. /* limit the scope of the history list */
  106. tinyrl_history_stifle(history, limit);
  107. }
  108. }
  109. for (entry = tinyrl_history_getfirst(history, &iter);
  110. entry; entry = tinyrl_history_getnext(&iter)) {
  111. /* dump the details of this entry */
  112. tinyrl_printf(this->tinyrl,
  113. "%5d %s\n",
  114. tinyrl_history_entry__get_index(entry),
  115. tinyrl_history_entry__get_line(entry));
  116. }
  117. return 0;
  118. }
  119. /*----------------------------------------------------------- */
  120. /*
  121. * Find out the previous view in the stack and go to it
  122. */
  123. CLISH_PLUGIN_SYM(clish_nested_up)
  124. {
  125. clish_context_t *context = (clish_context_t *)clish_context;
  126. clish_shell_t *this = context->shell;
  127. if (!this)
  128. return -1;
  129. /* If depth=0 than exit */
  130. if (0 == this->depth) {
  131. this->state = SHELL_STATE_CLOSING;
  132. return 0;
  133. }
  134. this->depth--;
  135. return 0;
  136. }
  137. /*----------------------------------------------------------- */
  138. /*
  139. * Builtin: NOP function
  140. */
  141. CLISH_PLUGIN_SYM(clish_nop)
  142. {
  143. return 0;
  144. }
  145. /*----------------------------------------------------------- */
  146. /*
  147. * Builtin: Set watchdog timeout. The "0" to turn watchdog off.
  148. */
  149. CLISH_PLUGIN_SYM(clish_wdog)
  150. {
  151. clish_context_t *context = (clish_context_t *)clish_context;
  152. const char *arg = script;
  153. clish_shell_t *this = context->shell;
  154. /* Turn off watchdog if no args */
  155. if (!arg || ('\0' == *arg)) {
  156. this->wdog_timeout = 0;
  157. return 0;
  158. }
  159. this->wdog_timeout = (unsigned int)atoi(arg);
  160. return 0;
  161. }
  162. /*----------------------------------------------------------- */
  163. /* Initialize internal pseudo-plugin */
  164. CLISH_PLUGIN_INIT
  165. {
  166. clish_plugin_add_psym(plugin, clish_close, "clish_close");
  167. clish_plugin_add_psym(plugin, clish_overview, "clish_overview");
  168. clish_plugin_add_psym(plugin, clish_source, "clish_source");
  169. clish_plugin_add_psym(plugin, clish_source_nostop, "clish_source_nostop");
  170. clish_plugin_add_psym(plugin, clish_history, "clish_history");
  171. clish_plugin_add_psym(plugin, clish_nested_up, "clish_nested_up");
  172. clish_plugin_add_psym(plugin, clish_nop, "clish_nop");
  173. clish_plugin_add_psym(plugin, clish_wdog, "clish_wdog");
  174. clish_plugin_add_sym(plugin, clish_script, "clish_script");
  175. return 0;
  176. }
  177. /*----------------------------------------------------------- */