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?