popen.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /* Copyright (c) 20XX 9front
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in all
  11. * copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. * SOFTWARE.
  20. */
  21. #include <u.h>
  22. #include <lib9.h>
  23. #include <bio.h>
  24. #include "awk.h"
  25. #define MAXFORKS 20
  26. #define NSYSFILE 3
  27. #define tst(a,b) (mode == OREAD? (b) : (a))
  28. #define RDR 0
  29. #define WTR 1
  30. struct a_fork {
  31. short done;
  32. short fd;
  33. int pid;
  34. char status[128];
  35. };
  36. static struct a_fork the_fork[MAXFORKS];
  37. Biobuf*
  38. popen(char *cmd, int mode)
  39. {
  40. int p[2];
  41. int myside, hisside, pid;
  42. int i, ind;
  43. for (ind = 0; ind < MAXFORKS; ind++)
  44. if (the_fork[ind].pid == 0)
  45. break;
  46. if (ind == MAXFORKS)
  47. return nil;
  48. if(pipe(p) < 0)
  49. return nil;
  50. myside = tst(p[WTR], p[RDR]);
  51. hisside = tst(p[RDR], p[WTR]);
  52. switch (pid = fork()) {
  53. case -1:
  54. return nil;
  55. case 0:
  56. /* myside and hisside reverse roles in child */
  57. sys_close(myside);
  58. dup(hisside, tst(0, 1));
  59. for (i=NSYSFILE; i<FOPEN_MAX; i++)
  60. sys_close(i);
  61. execl("/bin/rc", "rc", "-c", cmd, nil);
  62. exits("exec failed");
  63. default:
  64. the_fork[ind].pid = pid;
  65. the_fork[ind].fd = myside;
  66. the_fork[ind].done = 0;
  67. sys_close(hisside);
  68. return(Bfdopen(myside, mode));
  69. }
  70. }
  71. int
  72. pclose(Biobuf *ptr)
  73. {
  74. int f, r, ind;
  75. Waitmsg *status;
  76. f = Bfildes(ptr);
  77. Bterm(ptr);
  78. for (ind = 0; ind < MAXFORKS; ind++)
  79. if (the_fork[ind].fd == f && the_fork[ind].pid != 0)
  80. break;
  81. if (ind == MAXFORKS)
  82. return -1;
  83. if (!the_fork[ind].done) {
  84. do {
  85. if((status = wait()) == nil)
  86. r = -1;
  87. else
  88. r = status->pid;
  89. for (f = 0; f < MAXFORKS; f++) {
  90. if (r == the_fork[f].pid) {
  91. the_fork[f].done = 1;
  92. strecpy(the_fork[f].status, the_fork[f].status+512, status->msg);
  93. break;
  94. }
  95. }
  96. free(status);
  97. } while(r != the_fork[ind].pid && r != -1);
  98. if(r == -1)
  99. strcpy(the_fork[ind].status, "No loved ones to wait for");
  100. }
  101. the_fork[ind].pid = 0;
  102. if(the_fork[ind].status[0] != '\0')
  103. return 1;
  104. return 0;
  105. }