Dumping the NIS database programmatically

I recently had to get user information from a NIS domain programmatically. It’s fairly simple to dump the NIS database from the command line using ypcat. e.g.

bash-4.1$ ypcat passwd.byname
user1:crypticpwd:100:100:User One:/homes/user1:/bin/sh
user2:crypticpwd:101:100:User Two:/homes/user2:/bin/csh
....

It’s just as easy to match users or UIDs using ypwhich. e.g.

bash-4.1$ ypwhich 100 passwd.byuid
user1:crypticpwd:100:100:User One:/homes/user1:/bin/sh

Unfortunately, examples of doing this programmatically are few and far between. After some experimentation I figured out how to get the entire NIS database using yp_all.

The yp_all function is defined as follows:

int yp_all(char* indomain,
char* inmap,
struct ypall_callback* incallback
);

where ypall_callback is defined as:

struct ypall_callback {
int(*foreach)();
char *data;
};

And foreach is defined as a function:

int foreach (
int instatus,
char* inkey,
int inkeylen,
char* inval,
int invallen,
char* indata
);

Seems straight forward enough, no? yp_all takes a structure containing some arbitrary data and a callback function. yp_all queries the NIS database and makes a call to the given callback function for each row in the result set. Define your special handling in the foreach implementation for every record and there you have it. Don’t forget to handle error conditions along the way.

You can use the same method to query other NIS databases by specifying a different inmap value. These are fully qualified map names, not aliases. A not so exhaustive list includes:

  • passwd.byname
  • passwd.byuid
  • group.byname
  • group.bygid
  • mail.aliases

You’ll need to know the format of each entry to parse it properly.

There’s an equivalent yp_match API call that can retrieve specific records from a NIS database.

Example:

// define the foreach method called by yp_all
extern "C" int my_foreach(int instatus, char *inkey,
int inkeylen, char *inval,
int invallen, char *indata) {
// This function is call for every record in the database
// note - be sure to use the provide keylens to determine the
// length of the provided data, otherwise you'll pick up garbarge.
// indata at this point is what you provided to the structure. If it's not
// a char * you'll need to cast it properly.

...

// do something with the current record here
}

struct ypall_callback yp_cb;
yp_cb.foreach = myforeach;
yp_cb.data = dataPassedToForEach;

yp_all(myNISDomain, "passwd.byname", &yp_cb);
Tagged with: ,
Posted in Uncategorized
Design a site like this with WordPress.com
Get started