Subject: Re: nsswitch implementation questions...
To: None <thorpej@nas.nasa.gov>
From: Luke Mewburn <lukem@telstra.com.au>
List: current-users
Date: 01/17/1996 12:24:13
Jason Thorpe writes:
> On Tue, 16 Jan 1996 12:26:39 -0500 
>  "Perry E. Metzger" <perry@piermont.com> wrote:

>  > I prefer simplicity myself. Apps should read the file on startup, once
>  > in all likelyhood. If you are worried that you might have edited the
>  > file and that something might read it partially, move the file into
>  > place (though I doubt this is going to be much of aproblem.)

> So, you'd have to keep this state around somewhere ... I certainly 
> wouldn't want to teach every app how to use nsswitch ... it should Just 
> Work.  Given that, maybe the best way is to read it as soon as it's 
> needed, i.e. on the first call to getpwent() (which calls the underlying 
> nsswitch goo), for example.  The "have read nsswitch.conf" state would be 
> kept in the hidden goo.

> Of course, there might also be something to be said for being able to 
> change the contents of the file while the application runs and have those 
> changes reflected in the behavior of the system (like, say, if you fix a 
> configuration error in nsswitch.conf after having run mountd or 
> something).

> So, perhaps:

> 	- "nsswitch.conf has been read" state kept as a
> 	  struct timeval *.

> 	- Call to getpwent()->nsswitch goo...is pointer NULL?  Yes,
> 	  allocate storage for timestamp, stat file, read file.

> 	- next call to getpwent()->nsswitch goo...is pointer NULL?  No,
> 	  stat file.  updated time?  Yes, update timestamp, read file.

> 	- etc, etc, etc.

Well, actually, this is basically what my code does. The nsswitch.db file
gets opened upon the first time the nsswitch dispatcher is used.  Something
like:

	static time_t lastmod;
	struct stat sb; 
	if (lastmod) {
		if (fstat(fd, &sb) == -1)
			return;
		if (lastmod <= sb.st_mtime) {
			(dp->close)(dp);		/* point 1 */
			lastmod = 0;
		}
	}
	if (!lastmod) {
		if (stat(_PATH_NS_DB, &sb) == -1)
			return;
		dp = dbopen(_PATH_NS_DB, O_RDONLY, 0, DB_HASH, NULL);
		if (dp == NULL)				/* point 2 */
			return;
		fd = (dp->fd)(dp);
		if (fstat(fd, &sb) == -1)
			return;
		lastmod = sb.st_mtime;
	}
	/* do rest */


Now, if I rework the code into doing a parse each time, I'd just remove
the line at /* point 1 */, and replace the lines around /* point 2 */
with a call to the parser to build up the state.

Now, the hard part is, how do I support reentrant nsswitch stuff (a
longer term wishlist item of jtc for multithreaded apps)?
Do I make the "open the database/parse the file" section non-reentrant,
but allow the lookups to be reentrant?