diff options
author | Ilya Zakharevich <ilya@math.berkeley.edu> | 1999-05-06 14:17:28 -0400 |
---|---|---|
committer | Gurusamy Sarathy <gsar@cpan.org> | 1999-05-10 11:22:10 +0000 |
commit | e446cec8f170ecc3eabea80092ef64589855e167 (patch) | |
tree | b6105f3368055fb094ec8ed34e797a1128a497b0 /util.c | |
parent | 9b155405e1006cdd8b8d8ffbf82a0cdd100aa3a4 (diff) | |
download | perl-e446cec8f170ecc3eabea80092ef64589855e167.tar.gz |
Re: [PATCH 5.005_56] Make open(F,"command |") return correct err(no)
Message-ID: <19990506181728.A12433@monk.mps.ohio-state.edu>
p4raw-id: //depot/perl@3373
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 43 |
1 files changed, 41 insertions, 2 deletions
@@ -1910,6 +1910,8 @@ my_popen(char *cmd, char *mode) register I32 pid; SV *sv; I32 doexec = strNE(cmd,"-"); + I32 did_pipes = 0; + int pp[2]; PERL_FLUSHALL_FOR_CHILD; #ifdef OS2 @@ -1925,9 +1927,15 @@ my_popen(char *cmd, char *mode) } if (PerlProc_pipe(p) < 0) return Nullfp; + if (doexec && PerlProc_pipe(pp) >= 0) + did_pipes = 1; while ((pid = (doexec?vfork():fork())) < 0) { if (errno != EAGAIN) { PerlLIO_close(p[This]); + if (did_pipes) { + PerlLIO_close(pp[0]); + PerlLIO_close(pp[1]); + } if (!doexec) croak("Can't fork"); return Nullfp; @@ -1942,6 +1950,12 @@ my_popen(char *cmd, char *mode) #define THIS that #define THAT This PerlLIO_close(p[THAT]); + if (did_pipes) { + PerlLIO_close(pp[0]); +#if defined(HAS_FCNTL) && defined(F_SETFD) + fcntl(pp[1], F_SETFD, FD_CLOEXEC); +#endif + } if (p[THIS] != (*mode == 'r')) { PerlLIO_dup2(p[THIS], *mode == 'r'); PerlLIO_close(p[THIS]); @@ -1954,9 +1968,10 @@ my_popen(char *cmd, char *mode) #define NOFILE 20 #endif for (fd = PL_maxsysfd + 1; fd < NOFILE; fd++) - PerlLIO_close(fd); + if (fd != pp[1]) + PerlLIO_close(fd); #endif - do_exec(cmd); /* may or may not use the shell */ + do_exec3(cmd,pp[1],did_pipes); /* may or may not use the shell */ PerlProc__exit(1); } /*SUPPRESS 560*/ @@ -1970,6 +1985,8 @@ my_popen(char *cmd, char *mode) } do_execfree(); /* free any memory malloced by child on vfork */ PerlLIO_close(p[that]); + if (did_pipes) + PerlLIO_close(pp[1]); if (p[that] < p[This]) { PerlLIO_dup2(p[This], p[that]); PerlLIO_close(p[This]); @@ -1979,6 +1996,28 @@ my_popen(char *cmd, char *mode) (void)SvUPGRADE(sv,SVt_IV); SvIVX(sv) = pid; PL_forkprocess = pid; + if (did_pipes && pid > 0) { + int errkid; + int n = 0, n1; + + while (n < sizeof(int)) { + n1 = PerlLIO_read(pp[0], + (void*)(((char*)&errkid)+n), + (sizeof(int)) - n); + if (n1 <= 0) + break; + n += n1; + } + if (n) { /* Error */ + if (n != sizeof(int)) + croak("panic: kid popen errno read"); + PerlLIO_close(pp[0]); + errno = errkid; /* Propagate errno from kid */ + return Nullfp; + } + } + if (did_pipes) + PerlLIO_close(pp[0]); return PerlIO_fdopen(p[This], mode); } #else |