Nevertheless, there may be cases where interfacing with NIS services at programming level is a great and useful complement, easily incorporating some non-standard and centralized information into distributed and/or replicated applications.
Let's demonstrate with a couple of examples.
That should suffice to convey the main ideas.
Example 1:
This example mimics the functionality of ypmatch built-in command.
#include <cstdlib>
#include <iostream>
#include <rpcsvc/ypclnt.h>
void error_msg( char const * context, int code )
{
std::cout
<< "Context: "
<< context
<< std::endl;
std::cout
<< "Message: "
<< ::yperr_string( code )
<< "."
<< std::endl;
}
inline void std_c_free( void * p ) throw()
{
::free( p );
}
int main()
{
int code = 0;
char * domain = "";
if ( ( code = ::yp_get_default_domain( & domain ) ) == 0 )
{
char map[] = "phonebook";
char key[] = "user1";
char * value = "";
int length = 0;
(
domain,
map,
key,
sizeof(key) - 1, // '\0' trim.
& value,
& length
);
{
pointer< char, std_c_free > v_ptr( value );
v_ptr[ length ] = '.';
<< ", map " << map
<< ", key " << key
<< ", value " << v_ptr
<<
}
else
error_msg( "yp_match()", code );
}
else
error_msg( "yp_get_default_domain()", code );
return EXIT_SUCCESS;
}
Example 2:
This example mimics the functionality of the ypcat built-in command.
As depicted on the man pages, this calls are using the UPD protocol.
This implies that the results may not be always accurate.
#include <cstdlib>
#include <iostream>
#include <rpcsvc/ypclnt.h>
#include "pointer.hxx"
// Omitted stuff common to example 1...
int main()
{
int code = 0;
char * domain = "";
if ( ( code = ::yp_get_default_domain( & domain ) ) == 0 )
{
// Consider the previous custom NIS map example.
char map[] = "phonebook";
char * key = "";
int k_length = 0;
char * value = "";
int v_length = 0;
// This call is decoupled from the following if
// just for the readability of this example.
code = ::yp_first
(
domain,
map,
& key,
& k_length,
& value,
& v_length
);
if ( code == 0 )
{
do
{
// Use a simple smart pointer
// for automatic custom destruction.
pointer< char, std_c_free > k_ptr( key );
pointer< char, std_c_free > v_ptr( value );
// Trim standard '\n' "garbage".
k_ptr[ k_length ] = '\0';
v_ptr[ v_length ] = '\0';
std::cout
<< k_ptr
<< ": "
<< v_ptr
<< std::endl;
// This call is decoupled from the following if
// just for the readability of this example.
code = ::yp_next
(
domain,
map,
key,
k_length,
& key,
& k_length,
& value,
& v_length
);
if ( code != 0 )
{
if ( code != YPERR_NOMORE )
message( "yp_next()", code );
break;
}
}
while ( true );
}
else
error_msg( "yp_first()", code );
}
else
error_msg( "yp_get_default_domain()", code );
return EXIT_SUCCESS;
}
Example 3:
This example also mimics the functionality of the ypcat built-in command.
As depicted on the man pages, this calls are using the TCP protocol.
This implies that the results should be always accurate.
#include <cstdlib>
#include <iostream>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/yp_prot.h>
#include "pointer.hxx"
// Omitted stuff common to example 1...
// NIS callback support
extern "C" typedef int ( *callback ) ();
extern "C"
int pair
(
int status,
char const * const k, int k_length,
char const * const v, int v_length,
void *
)
{
if ( status == YP_TRUE )
{
//
// k and v are private to yp_all().
// Copy as needed, for instance, with:
//
// std::string key( k, k_length );
// std::string value( v, v_length );
//
std::cout.write( k, k_length );
std::cout << ' ';
std::cout.write( v, v_length );
std::cout << std::endl;
return 0;
}
int code = 0;
if ( ( code = ::ypprot_err( status ) ) != YPERR_NOMORE )
error_msg( "ypall_callback()", code );
return EXIT_FAILURE;
}
int main()
{
int code = 0;
char * domain = "";
if ( ( code = ::yp_get_default_domain( & domain ) ) == 0 )
{
// Consider the previous custom NIS map example.
char map[] = "phonebook";
::ypall_callback dumper = { (callback) pair, 0 };
if ( ( code = ::yp_all( domain, map, & dumper ) ) != 0 )
error_msg( "yp_all()", code );
}
else
error_msg( "yp_get_default_domain()", code );
return EXIT_SUCCESS;
}