shell_file.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include <stdlib.h>
  2. #include <assert.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include "lub/string.h"
  6. #include "private.h"
  7. /*----------------------------------------------------------- */
  8. static int clish_shell_push(clish_shell_t * this, FILE * file,
  9. const char *fname, bool_t stop_on_error)
  10. {
  11. /* Allocate a control node */
  12. clish_shell_file_t *node = malloc(sizeof(clish_shell_file_t));
  13. assert(this);
  14. assert(node);
  15. /* intialise the node */
  16. node->file = file;
  17. if (fname)
  18. node->fname = lub_string_dup(fname);
  19. else
  20. node->fname = NULL;
  21. node->line = 0;
  22. node->stop_on_error = stop_on_error;
  23. node->next = this->current_file;
  24. /* put the node at the top of the file stack */
  25. this->current_file = node;
  26. /* now switch the terminal's input stream */
  27. tinyrl__set_istream(this->tinyrl, file);
  28. return 0;
  29. }
  30. /*----------------------------------------------------------- */
  31. int clish_shell_push_file(clish_shell_t * this, const char * fname,
  32. bool_t stop_on_error)
  33. {
  34. FILE *file;
  35. int res;
  36. assert(this);
  37. if (!fname)
  38. return -1;
  39. file = fopen(fname, "r");
  40. if (!file)
  41. return -1;
  42. #ifdef FD_CLOEXEC
  43. fcntl(fileno(file), F_SETFD, fcntl(fileno(file), F_GETFD) | FD_CLOEXEC);
  44. #endif
  45. res = clish_shell_push(this, file, fname, stop_on_error);
  46. if (res)
  47. fclose(file);
  48. return res;
  49. }
  50. /*----------------------------------------------------------- */
  51. int clish_shell_push_fd(clish_shell_t *this, FILE *file,
  52. bool_t stop_on_error)
  53. {
  54. return clish_shell_push(this, file, NULL, stop_on_error);
  55. }
  56. /*----------------------------------------------------------- */
  57. int clish_shell_pop_file(clish_shell_t *this)
  58. {
  59. int result = -1;
  60. clish_shell_file_t *node = this->current_file;
  61. if (!node)
  62. return -1;
  63. /* remove the current file from the stack... */
  64. this->current_file = node->next;
  65. /* and close the current file... */
  66. fclose(node->file);
  67. if (node->next) {
  68. /* now switch the terminal's input stream */
  69. tinyrl__set_istream(this->tinyrl, node->next->file);
  70. result = 0;
  71. }
  72. /* and free up the memory */
  73. if (node->fname)
  74. lub_string_free(node->fname);
  75. free(node);
  76. return result;
  77. }
  78. /*----------------------------------------------------------- */