Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!tektronix!teklds!copper!stevesu From: stevesu@copper.UUCP (Steve Summit) Newsgroups: net.unix-wizards Subject: Re: Conventional daemons Message-ID: <335@copper.UUCP> Date: Wed, 7-May-86 00:25:57 EDT Article-I.D.: copper.335 Posted: Wed May 7 00:25:57 1986 Date-Received: Sat, 10-May-86 19:49:05 EDT References: <2177@brl-smoke.ARPA> <6636@utzoo.UUCP> Organization: Tektronix, Inc., Beaverton, OR Lines: 87 > [Why do daemons open / as stdin/stdout/stderr?] > The real question was, why open anything? Surely there's > nothing functionally useful about opening stdin/stdout on > "/" and it could be a potential hazard if ported... Another reason for keeping file descriptors 0, 1, and 2 open is that it's remarkably easy to write code that depends on it. Consider the following fragment, which intends to determine the load average by inspecting the output of "uptime": int fdpair[2], pid; pipe(fdpair); pid = fork(); if(pid == 0) { close(1); dup(fdpair[1]); /* intends to become 1 */ execl("/usr/ucb/uptime", "uptime", 0); } close(fdpair[1]); read(fdpair[0], buf, BUFSIZ); while(wait(0) != pid); . . . (Please don't nit-pick this program; I am aware of at least eight things wrong with it, but I didn't want to obscure the example with all of the error-checking that a production program would require.) The problem with this program is that the sequence close(1); dup(fdpair[1]); will fail miserably if fdpair[1] happens to be 1, as in fact would be the case if this program were run with no file descriptors initially open. Using dup2() might help this example, and of course the best thing to do would be to use popen(), which is written so as to avoid this problem. When writing code that forks and execs other programs with my own attached input and output, I frequently find myself writing extremely strange code, such as the following: fd = open("/dev/littleredridinghood", 2); if(fd != 0) { close(0); dup(fd); } if(fd != 1) { close(1); dup(fd); } if(fd != 2) { close(2); dup(fd); } if(fd > 2) close(fd); execl("/big/bad", "wolf", 0); The big bad wolf program is given little red riding hood as standard input, output, and error. The checks of fd against 0, 1, and 2 are in case it is already 0, 1, or 2, which would happen if this program were invoked under some daemon which didn't leave 0, 1, and 2 open on something. I think that one of the main reasons that well-written daemons do leave 0, 1, and 2 open on something is there are probably a lot of programs out there that weren't written by somebody paranoid enough to check other file descriptors against 0 before closing 0. ("But 0 is always standard input, right?") Steve Summit tektronix!copper!stevesu