shell.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. *
  3. */
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. #include <sys/wait.h>
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14. #include <limits.h>
  15. #include <faux/str.h>
  16. #include <faux/list.h>
  17. #include <klish/kcontext.h>
  18. #include <klish/ksession.h>
  19. static char *shell_mkfifo(void)
  20. {
  21. int res = 0;
  22. char *name = NULL;
  23. name = faux_str_sprintf("/tmp/klish.fifo.%u.XXXXXX", getpid());
  24. mktemp(name);
  25. if (mkfifo(name, 0600) < 0) {
  26. faux_str_free(name);
  27. return NULL;
  28. }
  29. return name;
  30. }
  31. // Execute shell script
  32. int shell_shell(kcontext_t *context)
  33. {
  34. const char *script = NULL;
  35. pid_t cpid = -1;
  36. int res = -1;
  37. char *fifo_name = NULL;
  38. FILE *wpipe = NULL;
  39. char *command = NULL;
  40. script = kcontext_script(context);
  41. if (faux_str_is_empty(script))
  42. return 0;
  43. // Create FIFO
  44. if (!(fifo_name = shell_mkfifo())) {
  45. fprintf(stderr, "Error: Can't create temporary FIFO.\n"
  46. "Error: The ACTION will be not executed.\n");
  47. return -1;
  48. }
  49. // Create process to write to FIFO
  50. cpid = fork();
  51. if (cpid == -1) {
  52. fprintf(stderr, "Error: Can't fork the write process.\n"
  53. "Error: The ACTION will be not executed.\n");
  54. unlink(fifo_name);
  55. faux_str_free(fifo_name);
  56. return -1;
  57. }
  58. // Child: write to FIFO
  59. if (cpid == 0) {
  60. wpipe = fopen(fifo_name, "w");
  61. if (!wpipe)
  62. _exit(-1);
  63. fwrite(script, strlen(script), 1, wpipe);
  64. fflush(wpipe);
  65. fclose(wpipe);
  66. _exit(0);
  67. }
  68. // Parent
  69. // Populate environment. Put command parameters to env vars.
  70. // Prepare command
  71. command = faux_str_sprintf("/bin/sh %s", fifo_name);
  72. res = system(command);
  73. // Wait for the writing process
  74. kill(cpid, SIGTERM);
  75. while (waitpid(cpid, NULL, 0) != cpid);
  76. // Clean up
  77. faux_str_free(command);
  78. unlink(fifo_name);
  79. faux_str_free(fifo_name);
  80. return WEXITSTATUS(res);
  81. }