clish_script_callback.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. int so; /* saved stdout */
  63. close(pipefd[0]); /* Close unused read end */
  64. so = dup(STDOUT_FILENO);
  65. dup2(pipefd[1], STDOUT_FILENO);
  66. close(pipefd[1]); /* Close write end */
  67. wpipe = popen(shebang, "w");
  68. dup2(so, STDOUT_FILENO);
  69. close(so);
  70. if (!wpipe)
  71. _exit(-1);
  72. fwrite(script, strlen(script) + 1, 1, wpipe);
  73. retval = pclose(wpipe);
  74. _exit(WEXITSTATUS(retval));
  75. }
  76. /* Parent */
  77. /* Read the result of script execution */
  78. close(pipefd[1]); /* Close unused write end */
  79. while (read(pipefd[0], &buf, 1) > 0)
  80. write(fileno(clish_shell__get_ostream(this)), &buf, 1);
  81. close(pipefd[0]);
  82. waitpid(cpid, &res, 0);
  83. /* Restore SIGINT and SIGQUIT */
  84. sigaction(SIGINT, &sig_old_int, NULL);
  85. sigaction(SIGQUIT, &sig_old_quit, NULL);
  86. #ifdef DEBUG
  87. fprintf(stderr, "RETCODE: %d\n", WEXITSTATUS(res));
  88. #endif /* DEBUG */
  89. return (0 == res) ? BOOL_TRUE : BOOL_FALSE;
  90. }
  91. /*--------------------------------------------------------- */
  92. bool_t clish_dryrun_callback(const clish_shell_t * this,
  93. const clish_command_t * cmd, const char *script)
  94. {
  95. #ifdef DEBUG
  96. fprintf(stderr, "DRY-RUN: %s\n", script);
  97. #endif /* DEBUG */
  98. return BOOL_TRUE;
  99. }
  100. /*--------------------------------------------------------- */