clish_script_callback.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * clish_script_callback.c
  3. *
  4. *
  5. * Callback hook to action a shell script.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #include <signal.h>
  13. #include <sys/types.h>
  14. #include <sys/wait.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include "private.h"
  19. #define KLISH_FIFO "/tmp/klish.fifo"
  20. /*--------------------------------------------------------- */
  21. bool_t clish_script_callback(const clish_shell_t * this,
  22. const clish_command_t * cmd, const char *script)
  23. {
  24. const char * shebang = NULL;
  25. pid_t cpid;
  26. char buf;
  27. int res;
  28. const char *fifo_name = KLISH_FIFO;
  29. FILE *rpipe;
  30. char *command = NULL;
  31. /* Signal vars */
  32. struct sigaction sig_old_int;
  33. struct sigaction sig_old_quit;
  34. struct sigaction sig_new;
  35. sigset_t sig_set;
  36. assert(this);
  37. assert(cmd);
  38. if (!script) /* Nothing to do */
  39. return BOOL_TRUE;
  40. shebang = clish_command__get_shebang(cmd);
  41. if (!shebang)
  42. shebang = clish_shell__get_default_shebang(this);
  43. assert(shebang);
  44. #ifdef DEBUG
  45. fprintf(stderr, "SHEBANG: #!%s\n", shebang);
  46. fprintf(stderr, "SCRIPT: %s\n", script);
  47. #endif /* DEBUG */
  48. mkfifo(fifo_name, 0600);
  49. /* Ignore SIGINT and SIGQUIT */
  50. sigemptyset(&sig_set);
  51. sig_new.sa_flags = 0;
  52. sig_new.sa_mask = sig_set;
  53. sig_new.sa_handler = SIG_IGN;
  54. sigaction(SIGINT, &sig_new, &sig_old_int);
  55. sigaction(SIGQUIT, &sig_new, &sig_old_quit);
  56. /* Create process to execute script */
  57. cpid = fork();
  58. if (cpid == -1) {
  59. return BOOL_FALSE;
  60. }
  61. /* Child */
  62. if (cpid == 0) {
  63. int retval;
  64. FILE *wpipe;
  65. wpipe = fopen(fifo_name, "w");
  66. if (!wpipe)
  67. _exit(-1);
  68. fwrite(script, strlen(script) + 1, 1, wpipe);
  69. fclose(wpipe);
  70. _exit(0);
  71. }
  72. /* Parent */
  73. lub_string_cat(&command, shebang);
  74. lub_string_cat(&command, " ");
  75. lub_string_cat(&command, fifo_name);
  76. rpipe = popen(command, "r");
  77. lub_string_free(command);
  78. /* Read the result of script execution */
  79. while (read(fileno(rpipe), &buf, 1) > 0)
  80. write(fileno(clish_shell__get_ostream(this)), &buf, 1);
  81. /* Wait for script */
  82. res = pclose(rpipe);
  83. /* Wait for the writing process */
  84. waitpid(cpid, NULL, 0);
  85. /* Restore SIGINT and SIGQUIT */
  86. sigaction(SIGINT, &sig_old_int, NULL);
  87. sigaction(SIGQUIT, &sig_old_quit, NULL);
  88. #ifdef DEBUG
  89. fprintf(stderr, "RETCODE: %d\n", WEXITSTATUS(res));
  90. #endif /* DEBUG */
  91. return (0 == res) ? BOOL_TRUE : BOOL_FALSE;
  92. }
  93. /*--------------------------------------------------------- */
  94. bool_t clish_dryrun_callback(const clish_shell_t * this,
  95. const clish_command_t * cmd, const char *script)
  96. {
  97. #ifdef DEBUG
  98. fprintf(stderr, "DRY-RUN: %s\n", script);
  99. #endif /* DEBUG */
  100. return BOOL_TRUE;
  101. }
  102. /*--------------------------------------------------------- */