clish_script_callback.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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 "private.h"
  16. /*--------------------------------------------------------- */
  17. bool_t clish_script_callback(const clish_shell_t * this,
  18. const clish_command_t * cmd, const char *script)
  19. {
  20. const char * shebang = NULL;
  21. int pipefd[2];
  22. pid_t cpid;
  23. char buf;
  24. int res;
  25. /* Signal vars */
  26. struct sigaction sig_old_int;
  27. struct sigaction sig_old_quit;
  28. struct sigaction sig_new;
  29. sigset_t sig_set;
  30. assert(this);
  31. assert(cmd);
  32. if (!script) /* Nothing to do */
  33. return BOOL_TRUE;
  34. shebang = clish_command__get_shebang(cmd);
  35. if (!shebang)
  36. shebang = clish_shell__get_default_shebang(this);
  37. assert(shebang);
  38. #ifdef DEBUG
  39. fprintf(stderr, "SHEBANG: #!%s\n", shebang);
  40. fprintf(stderr, "SCRIPT: %s\n", script);
  41. #endif /* DEBUG */
  42. if (pipe(pipefd) < 0)
  43. return BOOL_FALSE;
  44. /* Ignore SIGINT and SIGQUIT */
  45. sigemptyset(&sig_set);
  46. sig_new.sa_flags = 0;
  47. sig_new.sa_mask = sig_set;
  48. sig_new.sa_handler = SIG_IGN;
  49. sigaction(SIGINT, &sig_new, &sig_old_int);
  50. sigaction(SIGQUIT, &sig_new, &sig_old_quit);
  51. /* Create process to execute script */
  52. cpid = fork();
  53. if (cpid == -1) {
  54. close(pipefd[0]);
  55. close(pipefd[1]);
  56. return BOOL_FALSE;
  57. }
  58. /* Child */
  59. if (cpid == 0) {
  60. FILE *wpipe;
  61. int retval;
  62. close(pipefd[0]); /* Close unused read end */
  63. dup2(pipefd[1], STDOUT_FILENO);
  64. wpipe = popen(shebang, "w");
  65. close(pipefd[1]); /* Close write end */
  66. if (!wpipe)
  67. _exit(-1);
  68. fwrite(script, strlen(script) + 1, 1, wpipe);
  69. retval = pclose(wpipe);
  70. _exit(WEXITSTATUS(retval));
  71. }
  72. /* Parent */
  73. /* Read the result of script execution */
  74. close(pipefd[1]); /* Close unused write end */
  75. while (read(pipefd[0], &buf, 1) > 0)
  76. write(fileno(clish_shell__get_ostream(this)), &buf, 1);
  77. close(pipefd[0]);
  78. waitpid(cpid, &res, 0);
  79. /* Restore SIGINT and SIGQUIT */
  80. sigaction(SIGINT, &sig_old_int, NULL);
  81. sigaction(SIGQUIT, &sig_old_quit, NULL);
  82. #ifdef DEBUG
  83. fprintf(stderr, "RETCODE: %d\n", WEXITSTATUS(res));
  84. #endif /* DEBUG */
  85. return (0 == res) ? BOOL_TRUE : BOOL_FALSE;
  86. }
  87. /*--------------------------------------------------------- */
  88. bool_t clish_dryrun_callback(const clish_shell_t * this,
  89. const clish_command_t * cmd, const char *script)
  90. {
  91. #ifdef DEBUG
  92. fprintf(stderr, "DRY-RUN: %s\n", script);
  93. #endif /* DEBUG */
  94. return BOOL_TRUE;
  95. }
  96. /*--------------------------------------------------------- */