popen.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include <sys/wait.h>
  6. #define MAXFORKS 20
  7. #define NSYSFILE 3
  8. #define tst(a,b) (*mode == 'r'? (b) : (a))
  9. #define RDR 0
  10. #define WTR 1
  11. struct a_fork {
  12. short done;
  13. short fd;
  14. int pid;
  15. int status;
  16. };
  17. static struct a_fork the_fork[MAXFORKS];
  18. FILE *
  19. popen(char *cmd, char *mode)
  20. {
  21. int p[2];
  22. int myside, hisside, pid;
  23. int i, ind;
  24. for (ind = 0; ind < MAXFORKS; ind++)
  25. if (the_fork[ind].pid == 0)
  26. break;
  27. if (ind == MAXFORKS)
  28. return NULL;
  29. if(pipe(p) < 0)
  30. return NULL;
  31. myside = tst(p[WTR], p[RDR]);
  32. hisside = tst(p[RDR], p[WTR]);
  33. switch (pid = fork()) {
  34. case -1:
  35. return NULL;
  36. case 0:
  37. /* myside and hisside reverse roles in child */
  38. close(myside);
  39. dup2(hisside, tst(0, 1));
  40. for (i=NSYSFILE; i<FOPEN_MAX; i++)
  41. close(i);
  42. execl("/bin/ape/sh", "sh", "-c", cmd, NULL);
  43. _exit(1);
  44. default:
  45. the_fork[ind].pid = pid;
  46. the_fork[ind].fd = myside;
  47. the_fork[ind].done = 0;
  48. close(hisside);
  49. return(fdopen(myside, mode));
  50. }
  51. }
  52. int
  53. pclose(FILE *ptr)
  54. {
  55. int f, r, ind;
  56. int status;
  57. f = fileno(ptr);
  58. fclose(ptr);
  59. for (ind = 0; ind < MAXFORKS; ind++)
  60. if (the_fork[ind].fd == f && the_fork[ind].pid != 0)
  61. break;
  62. if (ind == MAXFORKS)
  63. return 0;
  64. if (!the_fork[ind].done) {
  65. do {
  66. r = wait(&status);
  67. for (f = 0; f < MAXFORKS; f++)
  68. if (the_fork[f].pid == r) {
  69. the_fork[f].done = 1;
  70. the_fork[f].status = status;
  71. break;
  72. }
  73. } while(r != the_fork[ind].pid && r != -1);
  74. the_fork[ind].status = r == -1 ? -1 : status;
  75. }
  76. the_fork[ind].pid = 0;
  77. return (the_fork[ind].status);
  78. }