[uClibc]popen bug?
Joseph Chiu
josephc at idealab.com
Mon Jul 22 22:53:31 UTC 2002
Hi,
I have a patch for popen().
Under uclibc, the popen call fails when stdout is already closed (uncomment
the close(1)); but this works fine under gcc.
The affected section reads:
close(reading);
if (pr != reading) {
dup2(pr, reading);
close(pr);
}
If pr == reading, then youve closed pr before you dup2()d it. And dup2()
is responsible for closing reading if necessary, anyways.
Joseph
*** popen.c.orig Mon Jul 22 14:47:20 2002
--- popen.c Mon Jul 22 14:47:30 2002
*************** FILE *popen (const char *command, const
*** 34,40 ****
if ((fp = fdopen(pnr, mode)) != NULL) {
if ((pid = vfork()) == 0) { /* vfork -- child */
close(pnr);
- close(reading);
if (pr != reading) {
dup2(pr, reading);
close(pr);
--- 34,39 ----
test case program:
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
int main () {
FILE *f;
char line[256];
int ret;
close(0);
// close(1);
close(2);
openlog("ptest", LOG_PID|LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "starting, version is " );
f = popen("ls -r /", "r");
syslog(LOG_INFO,"Error %s\n",strerror(errno));
syslog(LOG_INFO,"pipe called %s got %d", "cmd",(int)f);
while (fgets(line, 255, f)) {
line[strlen(line)-1] = '\0';
syslog(LOG_INFO,"+ %s", line);
}
ret = pclose(f);
syslog(LOG_INFO,"Got %d\n",ret);
closelog();
return 0;
}
FILE *popen (const char *command, const char *mode)
{
FILE *fp;
int pipe_fd[2];
int pid, reading;
int pr, pnr;
reading = (mode[0] == 'r');
if ((!reading && (mode[0] != 'w')) || mode[1]) {
__set_errno(EINVAL); /* Invalid mode arg. */
} else if (pipe(pipe_fd) == 0) {
pr = pipe_fd[reading];
pnr = pipe_fd[1-reading];
if ((fp = fdopen(pnr, mode)) != NULL) {
if ((pid = vfork()) == 0) { /* vfork -- child */
close(pnr);
close(reading);
if (pr != reading) {
dup2(pr, reading);
close(pr);
}
execl("/bin/sh", "sh", "-c", command, (char *) 0);
_exit(255); /* execl failed! */
} else { /* vfork -- parent or failed */
close(pr);
if (pid > 0) { /* vfork -- parent */
return fp;
} else { /* vfork -- failed! */
fclose(fp);
}
}
} else { /* fdopen failed */
close(pr);
close(pnr);
}
}
return NULL;
}
More information about the uClibc
mailing list