Net-NIS-0.44/0000755000175000001440000000000012302201072011306 5ustar esmusersNet-NIS-0.44/Changes0000644000175000001440000000215612302201056012607 0ustar esmusersRevision history for Net::NIS 0.44 2014-02-22 - require perl 5.6 - typo fix; modernize encoding 0.43 2007-11-17 - NIS.xs: missed one whitespace change needed for 5.005 0.42 2007-11-16 - test suite: remove the 'table' test; the Table interface is deprecated anyway. - NIS.xs: whitespace change for amd64 freebsd, perl 5.005 0.41 2007-11-16 - test suite: handle another problem situation 0.40 2007-11-16 - New feature: magic '__YPMASTER' map serves as interface to yp_master() function and, if available, yp_maplist(). Thanks to John L. Allen at ngc.com for feature request. - test suite: handle several unusual situations. - test suite: disable ypcat test. It fails in too many places. 0.34 2003-03-19 - NIS.xs: compile and work properly on perl 5.8.0 configured for threads and 64bit integers - t/ypcat.t: rewrite to use arrays instead of hashes. Fixes https://rt.cpan.org/NoAuth/Bug.html?id=1865 0.33 2002-08-31 - test suite: pass even if build host isn't running NIS - NIS::Table - allow more than one concurrent object. Bug fix provided by Andy Walker . Net-NIS-0.44/MANIFEST0000644000175000001440000000053312302201073012441 0ustar esmusersREADME Changes MANIFEST Makefile.PL NIS.pm NIS.pod NISTable.pod NIS.xs NIS/Table.pm t/01domainname.t t/10yperr_string.t t/15yperr_num.t t/20wantarray.t t/40ypmaster.t t/90ypcat.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Net-NIS-0.44/META.json0000664000175000001440000000157112302201072012735 0ustar esmusers{ "abstract" : "Interface to Sun's Network Information Service", "author" : [ "Eduardo Santiago " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Net-NIS", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Test::More" : "0" } } }, "release_status" : "stable", "version" : "0.44" } Net-NIS-0.44/META.yml0000664000175000001440000000076712302201072012573 0ustar esmusers--- abstract: "Interface to Sun's Network Information Service" author: - 'Eduardo Santiago ' build_requires: ExtUtils::MakeMaker: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120921' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Net-NIS no_index: directory: - t - inc requires: Test::More: 0 version: 0.44 Net-NIS-0.44/Makefile.PL0000644000175000000510000000105310720345634012211 0ustar esm# $Id$ use ExtUtils::MakeMaker; # It's 2007. Time to forget about 5.005. use 5.006; WriteMakefile( NAME => 'Net::NIS', AUTHOR => 'Eduardo Santiago ', VERSION_FROM => 'NIS.pm', ABSTRACT_FROM => 'NIS.pod', LIBS => '-lnsl', PREREQ_PM => { 'Test::More' => 0 }, # The PREOP condition prevents me from doing incomplete releases :-) dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', PREOP => 'fgrep \?\? Changes && exit 1 || true', }, ); Net-NIS-0.44/NIS/0000755000175000001440000000000012302201072011737 5ustar esmusersNet-NIS-0.44/NIS/Table.pm0000644000175000001440000000154512302176760013350 0ustar esmusers# $Id: 100 $ require Net::NIS; package Net::NIS::Table; sub new { my($pkg, $map, $domain) = @_; my ($self) = {}; $domain = Net::NIS::yp_get_default_domain() if ! $domain; $self->{'map'} = $map; $self->{'domain'} = $domain; bless $self; } sub list { my ($me) = shift; my ($value); ($me->{'status'}, $value) = Net::NIS::yp_all($me->{'domain'}, $me->{'map'}); return $value; } sub match { my ($me, $key) = @_; my ($value); ($me->{'status'}, $value) = Net::NIS::yp_match($me->{'domain'}, $me->{'map'}, $key); return $value; } sub search { my ($me, $srch) = @_; my ($value, %ret); ($me->{'status'}, $value) = Net::NIS::yp_all($me->{'domain'}, $me->{'map'}); foreach (grep(/$srch/, keys %{$value})) { $ret{$_} = $value->{$_}; }; return \%ret; } sub status { my ($me) = shift; $me->{'status'}; } 1; __END__ Net-NIS-0.44/NIS.pm0000644000175000001440000002037412302200751012306 0ustar esmusers# -*- perl -*- # # Net::NIS::Tied - interface to YP^H^HNIS # # $Id: 104 $ # package Net::NIS; use strict; use 5.006; use warnings; # Sigh, only available in 5.6 and above use Carp; ############################################################################### # BEGIN user-configurable section # Linux and Solaris seem to have this file. It contains a number of # lines, each with a key/value pair (separated by spaces). my $Nicknames_File = '/var/yp/nicknames'; # For those systems who don't have a nicknames file, here are some # reasonable defaults. my %Nicknames_Default = ( passwd => 'passwd.byname', group => 'group.byname', networks => 'networks.byaddr', hosts => 'hosts.byname', protocols => 'protocols.bynumber', services => 'services.byname', aliases => 'mail.aliases', ethers => 'ethers.byname', ); # Special case: this magic map acts as a front end to yp_master() our $Magic_ypmaster_map = '__YPMASTER'; # Ouch. It really hurts to enumerate these here, manually, instead of # somehow relying on the autogenerated list made by h2xs. But at least # we have a test (t/15yperr_num.t) that should catch inconsistencies. # # Please be sure to keep these in numerical order, starting with 0. If # There are ever gaps in the YPERR_xxx sequence, or duplicates, we will # have to rethink this approach. But until then, let's not worry. use vars qw(@YPERRS); @YPERRS = map { "YPERR_$_" } qw( SUCCESS BADARGS RPC DOMAIN MAP KEY YPERR RESRC NOMORE PMAP YPBIND YPSERV NODOM BADDB VERS ACCESS BUSY ); # Magic! This variable is magically tied to a global in our .xs which # keeps track of the status returned from the last yp_xxx() function. # # This variable is exported by default. I'm not too happy with its # name, but it seems like the best out of all the possibilities I # considered. The primary benefit is that, given the fixed nature # of the YPERR_xxx constant names, '$yperr' will be easier for someone # to remember than $yp_status, $ypstatus, $yp_err, or anything like that. # # Any other suggestions, before it's too late to change it? use vars qw($yperr); # END user-configurable section ############################################################################### use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $PKG); require Exporter; require DynaLoader; require AutoLoader; @ISA = qw(Exporter DynaLoader); %EXPORT_TAGS = ( all => [ '$yperr', @YPERRS ] ); @EXPORT_OK = ( '$yperr', @YPERRS ); @EXPORT = ( '$yperr' ); $VERSION = '0.44'; $PKG = __PACKAGE__; # For interpolating into error messages ############# # DESTROY # Not really used, but needed so AUTOLOAD doesn't trap it ############# sub DESTROY {} ############## # AUTOLOAD # from h2xs ############## sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; use vars qw($AUTOLOAD); ($constname = $AUTOLOAD) =~ s/.*:://; croak "& not defined" if $constname eq 'constant'; my $val = constant($constname, @_ ? $_[0] : 0); if ($! != 0) { if ($! =~ /Invalid/) { if ($constname =~ /^YP/) { croak "No such constant, ${PKG}::$constname"; } else { croak "No such function, ${PKG}::$constname()"; } } else { croak "Your vendor has not defined Net::NIS macro $constname"; } } { no strict 'refs'; *$AUTOLOAD = sub { $val }; } goto &$AUTOLOAD; } bootstrap Net::NIS $VERSION; # Magic: The $yperr variable will now have the YP status, int & string form _yp_tie_status ($yperr); ###################### # _expand_nickname # Look for a string in the /var/yp/nicknames file ###################### sub _expand_nickname($) { my $map = shift; use vars '%nickname'; # First time through? Read the nicknames file, or initialize to a # reasonable default (hardcoded above). if (keys %nickname == 0) { if (open NICKNAMES, '<', $Nicknames_File) { while (defined (my $line = )) { $line =~ /^\s*(\S+)\s+(\S+)$/ or next; $nickname{$1} = $2; } close NICKNAMES; } else { # No nicknames file %nickname = %Nicknames_Default; } } # If there's a nickname defined for this map, return it... otherwise, # the map name itself. $nickname{$map} || $map; } ############# # TIEHASH # establish the relationship between a hash and a YP map. ############# sub TIEHASH { my $class = shift; # Second argument must be a map name (passwd, mail.aliases, etc) my $map = shift or croak "Usage: tie \%hash, $PKG, 'MAP NAME' [, 'DOMAIN' ]\n"; # Third argument (optional) is the NIS domain. If unset, bail out # now, setting error to NODOM ("Local domain name not set"). Otherwise, # if we try the yp_match, it fails with the less-than-helpful BADARGS. my $domain = shift || yp_get_default_domain() or do { $yperr = YPERR_NODOM(); return undef; }; # Check validity of map name. # As a special case, use '__YPMASTER' to act as a front end to yp_master() $map = _expand_nickname($map); unless ($map eq $Magic_ypmaster_map) { if (! Net::NIS::yp_master( $domain, $map )) { $yperr = YPERR_MAP(); return undef; } } # All OK. Force $yperr to OK, and return a blessed object $yperr = YPERR_SUCCESS(); bless { map => $map, domain => $domain }, $class; } ########### # FETCH # read-only access to a key. ########### sub FETCH { my $self = shift; my $key = shift; # Special case for magic yp_master map if ($self->{map} eq $Magic_ypmaster_map) { return Net::NIS::yp_master($self->{domain}, $key); } # Have we slurped in all keys using yp_all() ? Look up our key therein. if (exists $self->{_alldata} && exists $self->{_alldata}->{$key}) { return $self->{_alldata}->{$key}; } # Haven't called yp_all(), or key not found there. Do a real YP lookup. if (defined (my $val = yp_match($self->{domain}, $self->{map}, $key))) { return $val; } # Error... is it 'no such key in map'? That's OK if ($yperr == YPERR_KEY()) { return undef; } # Any other error: fatal croak sprintf("Unable to find '%s' in %s. Reason: %s", $key, $self->{map}, $yperr); } ############ # EXISTS # Does a key exist? This isn't cheap, it still incurs a yp_match ############ sub EXISTS { my $self = shift; defined $self->FETCH (@_); } ############## # FIRSTKEY # For iterating with each() or keys() ############## # # Important note: this uses the yp_all() mechanism to slurp in a complete # hash containing all the key/value pairs. It is delayed until here, # because our caller could simply want to perform lookups (via FETCH) # without iterating over all keys. # sub FIRSTKEY { my $self = shift; # Special case when called with magic yp_master key if ($self->{map} eq $Magic_ypmaster_map) { my %master; for my $map (Net::NIS::yp_maplist( $self->{domain} )) { $master{$map} = Net::NIS::yp_master( $self->{domain},$map ); } $self->{_alldata} = \%master; } else { # Each time we get called, slurp across again... just in case any # values have changed. This is suboptimal: in effect, we're keeping # a cache around for who-knows-how-long. Suggestions welcome for # improving it (perhaps keeping a {_last_updated} time??) $self->{_alldata} = yp_all ($self->{domain}, $self->{map}); # Returned value must be a hash. If it isn't, something bad happened. if (ref $self->{_alldata} ne 'HASH') { croak sprintf("No such map '%s'. Reason: %s", $self->{map}, $yperr); } } # Reset the each() operator, and let it do the rest. my $trashme = keys %{ $self->{_alldata} }; return scalar each %{ $self->{_alldata} }; } ############# # NEXTKEY # no-brainer, just lets each() do the work on our internal hash ############# sub NEXTKEY { my $self = shift; return each %{ $self->{_alldata} }; } # ------NO WRITE ACCESS ALLOWED------ sub _read_only(@) { croak "$PKG provides read-only access"; } sub STORE { _read_only(@_); } sub DELETE { _read_only(@_); } ############################################################################### 1; __END__ Net-NIS-0.44/NIS.pod0000644000175000001440000001756112302200015012451 0ustar esmusers=head1 NAME Net::NIS - Interface to Sun's Network Information Service =head1 SYNOPSIS use Net::NIS; tie %hash, 'Net::NIS', $mapname [, $domainname]; $value = $hash{$key}; or ($status, $value) = Net::NIS::yp_match (Net::NIS::yp_get_default_domain(), $mapname, $key); =head1 DESCRIPTION The Net::NIS interface comes in three parts: =over 4 =item 1. raw The first part is the raw implementation of the NIS API. =item 2. OO The second is the object interface, described in L. =item 3. Tie The third is a new 'Tied' interface, allowing simple access to NIS maps using Perl hashes. =back This document describes the NIS API implementation and the 'Tied' mechanism. =head2 Tied Implementation NIS maps are simple key/value pairs, perfectly suited for Perl hashes. B allows any given NIS map to be treated as a hash (read-only). Usage is: tie %hash, 'Net::NIS', $mapname [, $domainname]; I<$mapname> must be specified, and be a valid map in the given domain. If the file F exists, it is used to obtain a list of acceptable shortcut names, such as C for C. Otherwise, a hardcoded set of the "usual suspects" is consulted. If I<$domainname> is not given, the C function is used to determine the current NIS domain. This is usually the same as will be displayed by the C command. If B cannot tie to a given I, it returns C, with an appropriate error value in the variable B<$yperr>. See L. To look up an entry in a YP map, simply use the entry name as a key in the tied hash. B returns a string if the key exists in the map, or C if it is not found. For any errors other than YPERR_KEY, B raises a fatal exception through C. B tie %alias, 'Net::NIS', 'mail.aliases' or die "Cannot tie to mail.aliases YP map: $yperr\n"; print "postmaster is ", $alias{postmaster} || "", "\n"; As a special case, the magic map B<__YPMASTER> can be used as an equivalent to 'ypwhich -m': tie %ypmaster, 'Net::NIS', '__YPMASTER' or die ...; printf "ypmaster(passwd) = %s\n", $ypmaster{'passwd.byname'}; print $_, "\n" for sort keys %ypmaster; # Only works on Linux! Note that keys() only works on Linux, because Linux includes a helpful yp_maplist() function. On Linux, you can get a list of existing YP maps. On other OSes, you can't -- but given the name of an existing map, $ypmaster{$map} will work as expected. =head2 NIS API Implementation The NIS package implements all functions described in the L manual page. The following commands have been implemented: =over 5 =item yp_bind($domain) Bind the process to a NIS server for the domain $domain. This function is rarely needed. See L. =item yp_unbind($domain) Unbind the process from the specified $domain. This function is also rarely required. See L. =item $domain = yp_get_default_domain() Return the host's local domain. (The same as the L program). See L. =item ($status, $value) = yp_match($domain, $map, $key) Return the $value for the given $key in the $map for the domain $domain. The $key must be an exact match for an item in the map (I yp_match does no partial matching. The $value is only valid if $status is equal to YPERR_SUCCESS. If called in scalar context, yp_match returns only $value, and it is up to the user to check $yperr. =item ($status, $key, $value) = yp_first($domain, $map) Return the first key-value pair from $map in $domain. As the NIS maps are stored in a DBM table, the order of the returned values is not obvious. =item ($status, $key, $value) = yp_next($domain, $map, $key) Return the next key-value pair from $map in $domain. The $key must be provided from the previous L or L. The L/L method is not recommended, as under some circumstances, entries can be skipped or returned twice. L is a better interface to use. =item ($status, \%values) = yp_all($domain, $map) The L call returns an entire map in the %values associative array. =item ($status, $order) = yp_order($domain, $map) This function returns the order number for $domain. Whatever that is. It mustn't be very important, since it's not implemented on NIS+ servers running in "YP-compatibility mode". I put it in for completeness. =item ($status, $name) = yp_master($domain, $map) Returns the machine name of the master server for a map. =item $error = yperr_string($status) B<[DEPRECATED, use $yperr]> Returns a string representation of the error code passed in $status. =item $status = ypprot_err($code) B<[DEPRECATED]> Translates a NIS name service protocol error code to a ypclnt layer error code. Only used for the C version of L, and it is only implemented here for completeness. =back =head1 EXPORT The magic variable B<$yperr> is exported by default (see L). =head2 Exportable constants The following error status constants can be imported individually, or by using the ':all' symbol: YPERR_SUCCESS There is no error YPERR_BADARGS Args to function are bad YPERR_RPC RPC failure YPERR_DOMAIN Can't bind to a server with this domain YPERR_MAP No such map in server's domain YPERR_KEY No such key in map YPERR_YPERR Internal yp server or client error YPERR_RESRC Local resource allocation failure YPERR_NOMORE No more records in map database YPERR_PMAP Can't communicate with portmapper YPERR_YPBIND Can't communicate with ypbind YPERR_YPSERV Can't communicate with ypserv YPERR_NODOM Local domain name not set YPERR_BADDB yp data base is bad YPERR_VERS YP version mismatch YPERR_ACCESS Access violation YPERR_BUSY Database is busy =head1 ERRORS Instead of having 'tie' succeed and the first access fail, TIEHASH() (the function executed when performing a B) performs some sanity checks: it ensures the validity of the domain and map names. On failure, 'tie' returns C, with an appropriate error value in B<$yperr> : tie %myhash, 'Net::NIS', 'foo-bar' or die "Unable to access foo-bar map: $yperr\n" Note that the B<$yperr> variable is magic, like Perl's B<$!>. If accessed in a string context, it returns a human-friendly string obtained from the C library function. In a numeric context, B<$yperr> returns the numeric status code returned from the last YP function. This can be compared against the error constants above, if you so desire. =head2 Other Errors Your vendor has not defined Net::NIS macro YPERR_xxxx This indicates that one of the standard YPERR_xxx constants is not defined in your host's Erpcsct/ypclnt.hE file. You might see this during S on an old system, perhaps. Unable to find 'KEY' in 'MAP'. Reason: ... If an attempt to access a tied variable fails for any reason other than 'no such key in map', FETCH() raises this fatal exception. It probably indicates that YP has gone down, or there is some other fatal error. This can be caught with eval{}, but I'm not sure what you can do about it... =head1 AUTHOR Copyright (c) 1995, 2002 Rik Harris (B), 2002-2014 Ed Santiago. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Net::NIS is currently maintained by Ed Santiago . The Network Information Service (NIS) was formerly known as Sun Yellow Pages (YP). The functionality of the two remains the same; only the name has changed. The name Yellow Pages is a registered trademark in the United Kingdom of British Telecommunications plc, and may not be used without permission. Net-NIS-0.44/NIS.xs0000644000175000000510000002450210717571622011254 0ustar esm/* -*- c -*- ** ** Filename: NIS.xs - back end for the Net::NIS package ** ** $Id$ */ #include /* Needed on FreeBSD */ #include #include #include #include "EXTERN.h" #include "perl.h" #include "XSUB.h" /* ** The *THX_ macros seem to be 5.6 and above. ** ** Nobody should be running 5.005 any more, but still, it's not my place ** to judge. If someone wants to, let's try to let them. */ #ifndef pTHX_ # define pTHX_ #endif /* pTHX */ /* ** FIXME: if we ever support new YPERR_xxx values, this must be updated! */ #define YPERR_MAX YPERR_BUSY /* Solaris doesn't define YPERR_SUCCESS */ #ifndef YPERR_SUCCESS #define YPERR_SUCCESS 0 #endif /* YPERR_SUCCESS */ /* ** Slight interface change: NIS-a2 would always return ($status, $value). ** We use the GIMME_V macro to determine if our caller wants array or ** scalar. If array, return the same as before. If scalar, just return ** the desired value. Error status will always be available through the ** magic "tied" variable. */ #define YP_RETURN(val) \ do { \ if (GIMME_V == G_ARRAY) \ XPUSHs(sv_2mortal(newSViv(yp_status))); \ if (yp_status == YPERR_SUCCESS) \ XPUSHs(sv_2mortal(val)); \ else \ XPUSHs(&PL_sv_undef); \ } while (0) struct callbackdata { SV *results; int status; }; /* ESM: What's this? It doesn't seem to be used, nor part of the API?? */ static int not_here(s) char *s; { croak("%s not implemented on this architecture", s); return -1; } /* Invoked by AUTOLOAD, returns int values of the YPERR_ constants */ static double constant(name, arg) char *name; int arg; { errno = 0; if (strEQ(name, "YPERR_ACCESS")) #ifdef YPERR_ACCESS return YPERR_ACCESS; #else goto not_there; #endif if (strEQ(name, "YPERR_BADARGS")) #ifdef YPERR_BADARGS return YPERR_BADARGS; #else goto not_there; #endif if (strEQ(name, "YPERR_BADDB")) #ifdef YPERR_BADDB return YPERR_BADDB; #else goto not_there; #endif if (strEQ(name, "YPERR_BUSY")) #ifdef YPERR_BUSY return YPERR_BUSY; #else goto not_there; #endif if (strEQ(name, "YPERR_DOMAIN")) #ifdef YPERR_DOMAIN return YPERR_DOMAIN; #else goto not_there; #endif if (strEQ(name, "YPERR_KEY")) #ifdef YPERR_KEY return YPERR_KEY; #else goto not_there; #endif if (strEQ(name, "YPERR_MAP")) #ifdef YPERR_MAP return YPERR_MAP; #else goto not_there; #endif if (strEQ(name, "YPERR_NODOM")) #ifdef YPERR_NODOM return YPERR_NODOM; #else goto not_there; #endif if (strEQ(name, "YPERR_NOMORE")) #ifdef YPERR_NOMORE return YPERR_NOMORE; #else goto not_there; #endif if (strEQ(name, "YPERR_PMAP")) #ifdef YPERR_PMAP return YPERR_PMAP; #else goto not_there; #endif if (strEQ(name, "YPERR_RESRC")) #ifdef YPERR_RESRC return YPERR_RESRC; #else goto not_there; #endif if (strEQ(name, "YPERR_RPC")) #ifdef YPERR_RPC return YPERR_RPC; #else goto not_there; #endif if (strEQ(name, "YPERR_SUCCESS")) #ifdef YPERR_SUCCESS return YPERR_SUCCESS; #else goto not_there; #endif if (strEQ(name, "YPERR_VERS")) #ifdef YPERR_VERS return YPERR_VERS; #else goto not_there; #endif if (strEQ(name, "YPERR_YPBIND")) #ifdef YPERR_YPBIND return YPERR_YPBIND; #else goto not_there; #endif if (strEQ(name, "YPERR_YPERR")) #ifdef YPERR_YPERR return YPERR_YPERR; #else goto not_there; #endif if (strEQ(name, "YPERR_YPSERV")) #ifdef YPERR_YPSERV return YPERR_YPSERV; #else goto not_there; #endif errno = EINVAL; return 0; not_there: errno = ENOENT; return 0; } /*****************************************************************************\ ** Whee! Magic yp_status variable! *| \*****************************************************************************/ static int yp_status; /* ** When perl scripts read its value, e.g.: ** ** tie %map, 'Net::NIS', $mapname ** or die "Could not tie $mapname: $yp_status\n" ** */ static int yp_status_get(pTHX_ SV *sv, MAGIC *m) { /* ** First set the numeric value (double -- int doesn't do the right thing), ** then set the string value. The SvNOK_on() is copied unaltered from ** perl-5.6.1/mg.c, including the wonderful comment. It makes "sv" ** work both as a string and as a number. ** ** Note that if yp_status is 0 we use an emtpy string, so script can do: ** ** $yp_status_varname and die "blah blah: $yp_..." ** ** ...without worrying about "0" status being translated as "Success" */ sv_setnv (sv, yp_status); sv_setpv (sv, yp_status == YPERR_SUCCESS ? "" : yperr_string (yp_status)); SvNOK_on(sv); /* what a wonderful hack! */ return 1; } /* ** This seems useful only for testing: $yperr = 0 (or something else) */ static int yp_status_set(pTHX_ SV *sv, MAGIC *m) { int new_val = SvIV(sv); /* Only allow setting this var to one of our supported YPERR_xxx vals */ if (new_val < YPERR_SUCCESS || YPERR_MAX < new_val) croak("Value out of range"); yp_status = new_val; return 1; } MGVTBL yp_status_accessors = { yp_status_get, yp_status_set, }; /*****************************************************************************\ |* Callback used by yp_all() *| \*****************************************************************************/ int ypallcallback(instatus, inkey, inkeylen, inval, invallen, indata) int instatus; char *inkey; int inkeylen; char *inval; int invallen; char *indata; { if (instatus == YP_TRUE) { /* Ugh. Sometimes we get back keys (or values) with a trailing NUL. */ if (0 < inkeylen && inkey[inkeylen - 1] == '\0') --inkeylen; if (0 < invallen && inval[invallen - 1] == '\0') --invallen; /* Don't allow a zero-length key -- but zero-length value ("") is OK */ if (0 < inkeylen) { hv_store((HV*)SvRV(((struct callbackdata *)indata)->results), inkey, inkeylen, newSVpv(inval, invallen), (U32)0); } } ((struct callbackdata *)indata)->status = ypprot_err(instatus); if (instatus < 0) return instatus; return 0; } MODULE = Net::NIS PACKAGE = Net::NIS # # YPERR_xxx constants, enumerated above # double constant(name,arg) char * name int arg int yp_bind(domain) char * domain void yp_unbind(domain) char * domain void yp_get_default_domain() PPCODE: { char *domain; yp_status = yp_get_default_domain(&domain); YP_RETURN(newSVpv(domain, strlen(domain))); } # # Looks up a key in a given map (this implements the FETCH part) # void yp_match(domain, map, key) char * domain char * map SV * key PPCODE: { char *inkey; STRLEN inkeylen; char *outval; int outvallen = 0; if (SvPOK(key)) { inkey = SvPV(key, inkeylen); yp_status = yp_match(domain, map, inkey, (int)inkeylen, &outval, &outvallen); /* Sigh. Sometimes we have to include the trailing NUL */ if (yp_status == YPERR_KEY) yp_status = yp_match(domain, map, inkey, (int)inkeylen+1, &outval, &outvallen); /* Like above, sometimes we get an extra trailing NUL char */ if (yp_status == YPERR_SUCCESS) if (0 < outvallen && outval[outvallen-1] == '\0') --outvallen; } else { yp_status = YPERR_BADARGS; } YP_RETURN(newSVpv(outval, outvallen)); } void yp_first(domain, map) char * domain char * map PPCODE: { char *outkey; int outkeylen; char *outval; int outvallen; yp_status = yp_first(domain, map, &outkey, &outkeylen, &outval, &outvallen); XPUSHs(sv_2mortal(newSViv(yp_status))); if (yp_status == 0) { XPUSHs(sv_2mortal(newSVpv(outkey, outkeylen))); XPUSHs(sv_2mortal(newSVpv(outval, outvallen))); } } void yp_next(domain, map, key) char * domain char * map SV * key PPCODE: { char *inkey; STRLEN inkeylen; char *outkey; int outkeylen; char *outval; int outvallen; if (SvPOK(key)) { inkey = SvPV(key, inkeylen); yp_status = yp_next(domain, map, inkey, (int)inkeylen, &outkey, &outkeylen, &outval, &outvallen); XPUSHs(sv_2mortal(newSViv(yp_status))); if (yp_status == 0) { XPUSHs(sv_2mortal(newSVpv(outkey, outkeylen))); XPUSHs(sv_2mortal(newSVpv(outval, outvallen))); } } else { XPUSHs(sv_2mortal(newSViv(YPERR_BADARGS))); } } void yp_all(domain, map) char * domain char * map PPCODE: { struct ypall_callback callback; struct callbackdata data; data.results = newRV((SV *) newHV()); data.status = 0; callback.foreach = ypallcallback; callback.data = (char *)&data; yp_status = yp_all(domain, map, &callback); if (yp_status == YPERR_SUCCESS) { # Linux & Solaris see NOMORE, FreeBSD gets a plain 0 if (data.status == YPERR_NOMORE || data.status == YPERR_SUCCESS) { yp_status = YPERR_SUCCESS; } else { /* Unexpected value in callback status block */ yp_status = data.status; } } YP_RETURN((SV*)data.results); } void yp_order(domain, map) char * domain char * map PPCODE: { unsigned long order; yp_status = yp_order(domain, map, &order); YP_RETURN(newSViv(order)); } void yp_master(domain, map) char * domain char * map PPCODE: { char *name; yp_status = yp_master(domain, map, &name); YP_RETURN(newSVpv(name, strlen(name))); } char * yperr_string(code) int code int ypprot_err(code) int code # # Tie the magic yp_status variable. This should be called from our .pm # void _yp_tie_status(sv) SV* sv PREINIT: MAGIC *m; CODE: sv_magic(sv, NULL, '~', "Net::NIS::yp_status_variable", strlen("Net::NIS::yp_status_variable")); m = mg_find(sv, '~'); m->mg_virtual = &yp_status_accessors; SvMAGICAL_on(sv); #ifdef __linux # # Returns an array of all the YP map names # void yp_maplist(domain) char * domain PREINIT: int ret; struct ypmaplist *ypmap = NULL; AV *retval; PPCODE: { ret = yp_maplist( domain, &ypmap ); if (ret == YPERR_SUCCESS) { struct ypmaplist *y, *old; for (y=ypmap; y;) { // FIXME: check that y->map is not NULL? XPUSHs(newSVpv(y->ypml_name,strlen(y->ypml_name))); old = y; y = y->ypml_next; free(old); } } } #else /* Linux */ void yp_maplist(domain) char * domain PPCODE: { warn("Net::NIS::yp_maplist() -- not implemented on this OS"); XSRETURN_EMPTY; } #endif Net-NIS-0.44/NISTable.pod0000644000175000001440000001004612302177241013426 0ustar esmusers=head1 NAME Net::NIS::Table - Object Interface to Sun's Network Information Service =head1 DESCRIPTION The NIS interface comes in two parts. The first part is the raw implementation of the NIS API, described in L. The second is the object interface. This document describes the object interface implementation. The Table object represents an individual NIS map. A NIS map is bound to a Table object with the new method: $obj = Net::NIS::Table->new($map, [ $domain ]); For example, $hostsmap = Net::NIS::Table->new("hosts.byname"); This will create a Table object bound to the C NIS map in the default NIS domain. All operations on the $hostsmap object will relate to the C map. You can also specify a non-default domain: $hostsmap = Net::NIS::Table->new("hosts.byname", "my.domain.com.au"); Once a Table object has been bound to a NIS map, the following methods are available: =over 5 =item $value = $obj->match($key) Returns the value for a given key. If you only wish to look up one or two values, this function is more efficient, as it retrieves the items one at a time. If you wish to retrieve many items (where many is dependent on the size of the map, and probably what sort of machine you are on), it is better to use the L interface, which uses just one RPC call to retrieve the entire map. =item \%data = $obj->list() Return a reference to an associative array which contains the entire NIS map. The keys in the %data array correspond to the keys in the NIS map. If any error occurs that prevents the retrieval of the map, then the undefined value is returned. In this case, your program can use the status method to determine the cause of the error. =item \%data = $obj->search($srchkey) Return a reference to an associative array which contains all entries that have keys that contain the $srchkey. If any error occurs that prevents the retrieval of the map, then the undefined value is returned. In this case, your program can use the status method to determine the cause of the error. =item $status = $obj->status() Returns the status code for the last operation. If the last operation succeeded, then the status code is 0. The status codes returned by this method are described below in the ERROR CODES section. =item $status = $obj->status_string() Returns the character representation of the status code for the last operation. If the last operation succeeded, then the status code is something like "operation succeeded". The exact strings returned by this function are implementation dependent, and should not be used for comparison purposes. Use the status call, as described above. =back =head1 ERROR CODES The status method described above can return one of the following values: $Net::NIS::ERR_ACCESS Access violation $Net::NIS::ERR_BADARGS Args to function are bad $Net::NIS::ERR_BADDB yp data base is bad $Net::NIS::ERR_BUSY Database is busy $Net::NIS::ERR_DOMAIN Can't bind to a server which serves this domain $Net::NIS::ERR_KEY No such key in map $Net::NIS::ERR_MAP No such map in server's domain $Net::NIS::ERR_NODOM Local domain name not set $Net::NIS::ERR_PMAP Can't communicate with portmapper $Net::NIS::ERR_NOMORE No more records in map database $Net::NIS::ERR_RESRC Local resource allocation failure $Net::NIS::ERR_RPC RPC failure $Net::NIS::ERR_YPBIND Can't communicate with ypbind $Net::NIS::ERR_YPERR Internal yp server or client interface error $Net::NIS::ERR_YPSERV Can't communicate with ypserv $Net::NIS::ERR_VERS YP version mismatch =head1 AUTHOR Copyright (c) 1995 Rik Harris (B). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The Network Information Service (NIS) was formerly known as Sun Yellow Pages (YP). The functionality of the two remains the same; only the name has changed. The name Yellow Pages is a registered trademark in the United Kingdom of British Telecommunications plc, and may not be used without permission. Net-NIS-0.44/README0000644000175000001440000000451212302200277012176 0ustar esmusersThis is a snapshot release of the NIS interface to Perl 5. There are three parts to the interface: the raw component (Net::NIS), the object- oriented component (Net::NIS::Table), and the tied interface (Net::NIS). Unless someone provides strong reason to support the raw or OO components, they will be marked as deprecated and not documented or enhanced (but still supported for backward compatibility). The tied interface provides simple, Perl-like access to NIS databases: use Net::NIS; tie %ip, 'Net::NIS', 'hosts.byname' or die "Cannot tie to hosts.byname YP map: $yperr\n"; $hostname = "test"; print "$hostname's IP address is ", $ip{$hostname} || "", "\n"; # Look for any hosts named "test-XXX" @test_hosts = sort grep(/^test-/, keys %ip); INSTALLATION: ------------ The usual: perl Makefile.PL make make test make install You may see some (different) compiler warnings on Linux, FreeBSD, and Solaris. Suggestions welcome on portable ways to clean those up. DEPENDENCIES: ------------- Net::NIS is being developed under Perl 5.6.1. It has been tested with 5.005_03, and seems to work. Sorry, Net::NIS will not compile under Perl 5.004 or anything earlier. The tests require that the "ypcat" and "domainname" executables be found somewhere in your $PATH, and that the compile system be bound to a YP server containing some of the "usual suspects" maps. If you build on a system not running NIS, the tests will fail. BUGS: ----- Net::NIS has not changed much (read "at all") in many years, so I (Ed) am not about to go changing interfaces. I have made some bug fixes: * trailing-NUL bugs fixed: calling code no longer needs to trim NULs from returned keys, or append them in lookups. * YPERR_xxx constants are now properly defined ...and added some new features: * when called in scalar context, yp_match() returns * New magic variable "$yperr" for determining error status * New tied interface There have been a lot of changes, and that means there will be bugs. Please report any bugs you encounter to . have fun, rik. (1995-11-10) Ed (2014-02-22) COPYRIGHT AND LICENSE: --------------------- Copyright © 1995,2002 Rik Harris; 2002-2014 Ed Santiago This package is free software; you may redistribute it and/or modify it under the same terms as Perl itself. Net-NIS-0.44/t/0000755000175000001440000000000012302201072011551 5ustar esmusersNet-NIS-0.44/t/01domainname.t0000644000175000000510000000140710717352325013144 0ustar esm# -*- perl -*- # # Our yp_get_default_domain() call must return the same as "domainname" # # NOTE: This uses an unpublished interface to Net::NIS # use strict; use Test::More tests => 1; use Net::NIS; # See what the 'domainname' command returns. If there's an error, # assume that NIS just isn't installed and skip the test. chomp(my $domainname_per_cmdline = `domainname` || ''); if ($?) { ok 1, "Skip: 'domainname' command failed"; exit 0; } # Some versions return '(none)' (left-paren, none, right-paren). if ($domainname_per_cmdline eq '(none)') { $domainname_per_cmdline = ''; } # Now see what our library returns. my $domainname_per_Net_NIS = Net::NIS::yp_get_default_domain() || ''; is $domainname_per_Net_NIS, $domainname_per_cmdline, 'domainname'; Net-NIS-0.44/t/10yperr_string.t0000644000175000000510000000265310717110532013557 0ustar esm# -*- perl -*- # # verify the error string names returned by yperr_string() # # NOTE: This uses an unpublished interface to Net::NIS # use Test; my $loaded = 0; use strict; use vars qw(@msgs); # Make sure we get English error messages, no matter the current locale use POSIX qw(locale_h); setlocale(LC_ALL, 'C'); BEGIN { # These regular expressions have been tested under: # # Solaris (2.5.1, 2.6, 8) (both SPARC and x86) # Linux (RH 5.0, 7.0, Debian Woody) (yp-tools 2.4) # FreeBSD 4.2 # # If you encounter a system on which they don't work, please let # me know , and include the platform name and full # output of 'make test TEST_VERBOSE=1' @msgs = ( '', '\barg.* bad', 'RPC failure', 'Can\'t bind to( a)? server .* domain', 'No such map in server\'s domain', 'No such key in map', '(Internal )?(YP|NIS) .*error', 'Local resource allocation failure', 'No more records in map database', ); plan tests => (2 * scalar @msgs) + 2; } END { $loaded or print "not ok 1\n" } use Net::NIS; $loaded = 1; for (my $i=0; $i < @msgs; $i++) { eval '$yperr = $i'; ok $@, "", "Setting \$yperr = $i"; ok "$yperr", "/(?i)$msgs[$i]/", "yperr_string ($i)"; } # Now try for "out of range" foreach my $badval (-1, scalar @Net::NIS::YPERRS) { eval '$yperr = $badval'; ok $@, '/^Value out of range at \(eval/', "Setting \$yperr = $badval"; } Net-NIS-0.44/t/15yperr_num.t0000644000175000000510000000153410717110533013053 0ustar esm# -*- perl -*- # # Test that we have access to the YPERR_xxx constants, and their values # are what we expect. # # NOTE: This uses an unpublished interface to Net::NIS # use strict; use Test; my $loaded = 0; # NOTE: this depends heavily on the fact that @Net::NIS::YPERRS # currently (2002-02-14) consists of exactly 17 values. If you # ever add or remove any from that array, you must change the "34" # below to (2 * @YPERRS), and also change this comment. BEGIN { plan tests => 34; } END { $loaded or print "not ok 1\n" } use Net::NIS qw(:all); $loaded = 1; # For each constant 'YPERR_XXX' defined in @YPERRS, make sure the # function returns the value we expect to see. for (my $i=0; $i < @Net::NIS::YPERRS; $i++) { my $const = $Net::NIS::YPERRS[$i]; my $val = eval "$const()"; ok $@, "", "Evaluation of $const"; ok eval $val, $i, $const; } Net-NIS-0.44/t/20wantarray.t0000644000175000000510000000161710717110533013041 0ustar esm# -*- perl -*- # # test the Net::NIS interface when called as scalars or arrays # use Test; my $loaded = 0; use strict; BEGIN { plan tests => 6; } END { $loaded or print "not ok 1\n" } use Net::NIS; $loaded = 1; my ($status, $value_array, $value_scalar); eval '($status, $value_array) = Net::NIS::yp_get_default_domain()'; ok $@, '', 'eval yp_get_default_domain [array]'; ok $status, 0+$yperr, 'status of yp_get_default_domain [array]'; eval '$value_scalar = Net::NIS::yp_get_default_domain()'; ok $@, '', 'eval yp_get_default_domain [scalar]'; ok $value_array, $value_scalar, 'yp_get_default_domain [array,scalar] mismatch'; my @ret; eval '@ret = Net::NIS::yp_get_default_domain()'; ok scalar @ret, 2, 'scalar return of yp_get_default_domain[array]'; eval '@ret = scalar Net::NIS::yp_get_default_domain()'; ok scalar @ret, 1, 'scalar return of yp_get_default_domain[array]'; Net-NIS-0.44/t/40ypmaster.t0000644000175000000510000000263110717326430012701 0ustar esm#!perl # # Tests for magic __YPMASTER functionality # use strict; use Test::More tests => 1; eval 'use Test::Differences'; # If available, provides better diagnostics use Net::NIS qw(:all); tie my %ypmaster, 'Net::NIS', '__YPMASTER'; if ($yperr != YPERR_SUCCESS()) { diag "Skipping: $yperr"; ok 1, "Skipping test"; exit 0; } # Assemble a hash from the output of 'ypwhich -m' my $ypwhich_m = qx{ ypwhich -m }; if ($?) { diag "Skipping: error running 'ypwhich -m'"; ok 1, "Skipping test"; exit 0; } my %ypwhich_m; for my $line (split "\n", $ypwhich_m) { if ($line =~ m!^(\S+) \s+ (\S+)$!x) { $ypwhich_m{$1} = $2; } else { diag "Aborting test: Cannot grok '$line' from output of ypwhich -m"; ok 1, "Skipping test"; exit 0; } } # # Pay attention: black magic in action here. # # On Linux, which correctly implements yp_maplist(), this test works # just as you expect: it's a simple hash comparison. # # On other OSes, yp_maplist() is unavailable. That means that %ypmaster # is an empty hash, because there's no way to get its keys(). *BUT*, # fortunately, Test::More doesn't seem to compare keys() of its inputs. # It does seem to iterate over the keys, and *that* works well because # for a given key $k, $ypmaster{$k} works: it invokes yp_master(), # which is implemented in Solaris and possibly other OSes. # is_deeply \%ypmaster, \%ypwhich_m, "ypwhich -m .vs. our internal code"; Net-NIS-0.44/t/90ypcat.t0000644000175000000510000000534610717123247012171 0ustar esm# -*- perl -*- # # compare our results against what "ypcat -k " finds # # This test is DISABLED BY DEFAULT. That's because there are a few # sites out there whose YP maps have keys with spaces in them. So # if I run ypcat -k passwd.byname and see 'joe bob joe bob:*:123:45:...', # how do I parse that as a key/value pair? # # To enable this test, you can set $NET_NIS_YPCAT_TEST to any nonzero value # use Test::More; use strict; use vars qw(@maps); BEGIN { my $envar = 'NET_NIS_YPCAT_TEST'; if ($ENV{$envar}) { @maps = qw(passwd.byname passwd.byuid group.byname hosts.byname); plan tests => 2 * @maps; } else { plan tests => 1; diag("This test is disabled by default. To run, set $envar=1"); ok 1, "All tests skipped"; } } use Net::NIS qw($yperr YPERR_DOMAIN YPERR_NODOM YPERR_MAP); foreach my $map (@maps) { my $ok = 1; SKIP: { my %tied; tie %tied, 'Net::NIS', $map; # Build machine could be YP-less. We should still allow tests to pass. if (grep { $yperr == $_ } (YPERR_DOMAIN, YPERR_NODOM, YPERR_MAP)) { skip "$map: $yperr", 2; } is $yperr, "", "tie '$map'"; next if $yperr; # See what "ypcat -k" has to say. Remember each key/value pair seen. # # We can't keep them in a hash, because some bozo sysadmins have # maps whose keys have spaces in them. In parsing the output of # ypcat, we cannot detect those. my @cmdline; open CMDLINE, "ypcat -k $map |" or die "open ypcat $map: $!\n"; while () { chomp; /^\s*$/ and next; # skip blank lines # Allow leading whitespace, for the FreeBSD ypcat implementation /^\s*(\S+)\s+(.*)/ or die "$map: cannot grok '$_'\n"; push @cmdline, "$1 $2"; } close CMDLINE or die "close ypcat $map: $!\n"; # Step 1: see what our package found, and make sure each of those was # also listed by ypcat. This is not likely to fail. while (my ($key, $val) = each %tied) { my $pair = "$key $val"; my @cmdline_match = grep { $pair eq $cmdline[$_] } (0..$#cmdline); if (@cmdline_match == 0) { warn "Pair seen in \%tied, but not ypcat: '$pair'\n"; $ok = 0; } elsif (@cmdline_match > 1) { warn "WEIRD! Too many matches for '$pair'!\n"; $ok = 0; } else { # Exactly one match, as expected. # # Forget about it, we shan't be seeing it again. splice @cmdline, $cmdline_match[0], 1; } } # Step 2: Is there anything left of what ypcat found? There shouldn't # be, because we delete each ypcat key/value pair as soon as we # find it in our own list. if (@cmdline) { warn "Some key/value pairs listed by ypcat, but not found by me:\n"; warn " : $_\n" for @cmdline; } is $ok, 1, "\$ok"; } }