[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 you’ve 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