popen.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * popen - open a pipe
  3. */
  4. /* $Id$ */
  5. #include <errno.h>
  6. #include <stdio.h>
  7. #include <signal.h>
  8. #if defined(__BSD4_2)
  9. union wait {
  10. int w_status;
  11. };
  12. typedef union wait wait_arg;
  13. #else
  14. typedef int wait_arg;
  15. #endif /* __BSD4_2 */
  16. #include "../stdio/loc_incl.h"
  17. int _close(int d);
  18. #if defined(__USG)
  19. static
  20. #endif
  21. int _dup2(int oldd, int newd); /* not present in System 5 */
  22. int _execl(const char *name, ... );
  23. int _fork(void);
  24. int _pipe(int fildes[2]);
  25. int _wait(wait_arg *status);
  26. void _exit(int status);
  27. static int pids[FOPEN_MAX];
  28. FILE *
  29. popen(const char *command, const char *type)
  30. {
  31. int piped[2];
  32. int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
  33. int pid;
  34. if (Xtype == 2 ||
  35. _pipe(piped) < 0 ||
  36. (pid = _fork()) < 0) return 0;
  37. if (pid == 0) {
  38. /* child */
  39. register int *p;
  40. for (p = pids; p < &pids[ FOPEN_MAX]; p++) {
  41. if (*p) _close(p - pids);
  42. }
  43. _close(piped[Xtype]);
  44. _dup2(piped[!Xtype], !Xtype);
  45. _close(piped[!Xtype]);
  46. _execl("/bin/sh", "sh", "-c", command, (char *) 0);
  47. _exit(127); /* like system() ??? */
  48. }
  49. pids[piped[Xtype]] = pid;
  50. _close(piped[!Xtype]);
  51. return fdopen(piped[Xtype], type);
  52. }
  53. #if defined(__BSD4_2)
  54. #define ret_val status.w_status
  55. #else
  56. #define ret_val status
  57. #endif
  58. int
  59. pclose(FILE *stream)
  60. {
  61. int fd = fileno(stream);
  62. wait_arg status;
  63. int wret;
  64. void (*intsave)(int) = signal(SIGINT, SIG_IGN);
  65. void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
  66. fclose(stream);
  67. while ((wret = _wait(&status)) != -1) {
  68. if (wret == pids[fd]) break;
  69. }
  70. if (wret == -1) ret_val = -1;
  71. signal(SIGINT, intsave);
  72. signal(SIGQUIT, quitsave);
  73. pids[fd] = 0;
  74. return ret_val;
  75. }
  76. #if defined(__USG)
  77. int _dup(int fildes);
  78. static int
  79. _dup2(int oldd, int newd)
  80. {
  81. int i = 0, fd, tmp;
  82. int fdbuf[FOPEN_MAX];
  83. /* ignore the error on the close() */
  84. tmp = errno; (void) _close(newd); errno = tmp;
  85. while ((fd = _dup(oldd)) != newd) {
  86. if (fd == -1) break;
  87. fdbuf[i++] = fd;
  88. }
  89. tmp = errno;
  90. while (--i >= 0) {
  91. _close(fdbuf[i]);
  92. }
  93. errno = tmp;
  94. return -(fd == -1);
  95. }
  96. #endif /* __USG */