[comp.unix.wizards] more BSD strangeness -- syslogd.c

jik@athena.mit.edu (Jonathan I. Kamens) (06/08/90)

  Here's another little gem of code from BSD4.3 that I don't quite
understand.  Pulled from etc/syslogd.c:

	if (!Debug) {
		if (fork())
			exit(0);
		for (i = 0; i < 10; i++)
			(void) close(i);
		(void) open("/", 0);
		(void) dup2(0, 1);
		(void) dup2(0, 2);
		untty();
	}

OK, so why is it opening "/"?  Is this a poor man's equivalent to
/dev/null, and if so, why doesn't it just open /dev/null?

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

rpw3@rigden.wpd.sgi.com (Rob Warnock) (06/08/90)

In article <1990Jun8.070904.7466@athena.mit.edu> jik@athena.mit.edu
(Jonathan I. Kamens) writes:
+---------------
|   Here's another little gem of code from BSD4.3 that I don't quite
| understand.  Pulled from etc/syslogd.c:
| 	if (!Debug) {
| 		if (fork())
| 			exit(0);
| 		for (i = 0; i < 10; i++)
| 			(void) close(i);
| 		(void) open("/", 0);
| 		(void) dup2(0, 1);
| 		(void) dup2(0, 2);
| 		untty();
| 	}
| OK, so why is it opening "/"?  Is this a poor man's equivalent to
| /dev/null, and if so, why doesn't it just open /dev/null?
+---------------

Just guessing, but...

Because /dev/null might not be there. Or might have been removed and
now /dev/null is a *plain* file, not a special. [Oh, boy, that can
make things weird!] Or somebody may have mounted a funny file system
on /dev. Or the kernel may have been reconfigured and recompiled and
the major i-node numbers changed and nobody has run MAKEDEVS to fix 'em
all up yet so the device under "/dev/null" isn't /dev/null. [Yup! Seen
*that* one, too!]

But if the system booted at all, "/etc/init" was there, so "/" is there.
And the i-node number for "/" is stored in memory.

-Rob

-----
Rob Warnock, MS-9U/510          rpw3@sgi.com            rpw3@pei.com
Silicon Graphics, Inc.          (415)335-1673           Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311

keany@sequent.UUCP (Bernard Keany) (06/09/90)

In article <1990Jun8.070904.7466@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>
>  Here's another little gem of code from BSD4.3 that I don't quite
>understand.  Pulled from etc/syslogd.c:
>
>	if (!Debug) {
>		if (fork())
>			exit(0);
>		for (i = 0; i < 10; i++)
>			(void) close(i);
>		(void) open("/", 0);
>		(void) dup2(0, 1);
>		(void) dup2(0, 2);
>		untty();
>	}
>
>OK, so why is it opening "/"?  Is this a poor man's equivalent to
>/dev/null, and if so, why doesn't it just open /dev/null?
>
>Jonathan Kamens			              USnail:
>MIT Project Athena				11 Ashford Terrace
>jik@Athena.MIT.EDU				Allston, MA  02134
>Office: 617-253-8495			      Home: 617-782-0710


The answer as printed in a 12/88 UNIXWORLD article by Dave Lennert
titled "How to Write Unix Daemons" appears below ... Dave gave me a
copy when I started working on such things here and it's been invaluable.

"Change the working directory to /. Each process has a current working
directory, and the kernel holds this directory file open during the life
of the process. If a process has a current directory in a mounted file
system, the file system is "in use" and cannot be dismounted by the
administrator without first finding and killing the offending process.
(The hard part is finding the process!) Unless a process explicitly
alters its current directory via a chdir(2) call, it inherits the current
directory of its parent. When launched from an interactive shell, the
current directory (of the shell and thus the daemon) will be whatever
the user has most recently selected via the cd(1) command.
 Thus daemons should adopt a current directory that is not located on a
mounted file system (assuming that the daemon's purpose allows this). The
most reliable choice is the root directory."
-- 
Bernie Keany		"That's my story and I'm sticking to it"
..sequent!keany

djm@eng.umd.edu (David J. MacKenzie) (06/09/90)

In article <36447@sequent.UUCP> keany@sequent.UUCP (Bernard Keany) writes:

>>		(void) open("/", 0);
>>		(void) dup2(0, 1);
>>		(void) dup2(0, 2);

>>OK, so why is it opening "/"?  Is this a poor man's equivalent to
>>/dev/null, and if so, why doesn't it just open /dev/null?

> "Change the working directory to /. Each process has a current working
> directory, and the kernel holds this directory file open during the life
> of the process. If a process has a current directory in a mounted file
> system, the file system is "in use" and cannot be dismounted by the
> administrator without first finding and killing the offending process.

Almost.  That's an *open*, not a *chdir*!  But the principle is the
same: syslog wants to make sure that it doesn't hold open any files on
stdin, stdout, or stderr that would tie up a filesystem.  I presume
that after that it makes no references to stdin, stdout, and stderr.

Not that /dev/null is going to be on a different filesystem, but "/"
is guaranteed to exist, so why not use it?
--
David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>

hitz@auspex.auspex.com (Dave Hitz) (06/10/90)

 djm@eng.umd.edu (David J. MacKenzie) writes:
 >>>               for (i = 0; i < 10; i++)
 >>>                       (void) close(i);
 >>>               (void) open("/", 0);
 >>>               (void) dup2(0, 1);
 >>>               (void) dup2(0, 2);
 >>>               untty();
 >>>OK, so why is it opening "/"?  Is this a poor man's equivalent to
 >>>/dev/null, and if so, why doesn't it just open /dev/null?

 ...

 > syslog wants to make sure that it doesn't hold open any files on
 > stdin, stdout, or stderr that would tie up a filesystem.  I presume
 > that after that it makes no references to stdin, stdout, and stderr.

This answers the question "why close all open files", but it doesn't
answer the question, "why open anything at all for descriptors 0, 1 and
2."  If it makes no reference to stdin, stdout, stderr, why must there
be something open for them?

I can (and have) made up several answers for this.  Anyone know the real
one?  What happens if you just leave the descriptors closed?

-- 
Dave Hitz					home: 408-739-7116
UUCP: {uunet,mips,sun,bridge2}!auspex!hitz 	work: 408-492-0900

seindal@skinfaxe.diku.dk (Rene' Seindal) (06/11/90)

hitz@auspex.auspex.com (Dave Hitz) writes:

> This answers the question "why close all open files", but it doesn't
> answer the question, "why open anything at all for descriptors 0, 1 and
> 2."  If it makes no reference to stdin, stdout, stderr, why must there
> be something open for them?

Because otherwise those file descriptors will be used for something
else, such as log files or sockets, contrary to the usual conventions
abount what the file descriptors 0, 1 and 2 means.

> I can (and have) made up several answers for this.  Anyone know the real
> one?  What happens if you just leave the descriptors closed?

By Murphys Law, some braindead library routine will inevitably write
stupid error messages in your log files or screw up the protocols you
implement on top of a socket, that just happens to be file descriptor 2!
Not an easy one to track down, and a lot of wasted time doing just that.

Rene' Seindal (seindal@diku.dk)

smb@ulysses.att.com (Steven Bellovin) (06/11/90)

In article <3446@auspex.auspex.com>, hitz@auspex.auspex.com (Dave Hitz) writes:
} This answers the question "why close all open files", but it doesn't
} answer the question, "why open anything at all for descriptors 0, 1 and
} 2."  If it makes no reference to stdin, stdout, stderr, why must there
} be something open for them?
} 
} I can (and have) made up several answers for this.  Anyone know the real
} one?  What happens if you just leave the descriptors closed?

It probably doesn't apply to syslogd, but in general if 0,1,2 are
closed you confuse a lot of programs that you fork/open/dup/exec to.

Yes, I've seen it happen.  Many times.