Ldapsearch.pl
use strict;
use Net::LDAP;
use Net::LDAP::Filter;
use Getopt::Std;
# BEGIN CALLOUT A
BEGIN COMMENT
# Получение и проверка заданных параметров.
END COMMENT
my %opts;
getopt(?bshpDwfa?, \%opts);
my($err_str) = validate_options(\%opts);
if ($err_str) {
	print «ldapsearch.pl: $err_str
»;
	print usage();
	exit;
}
# END CALLOUT A
# BEGIN CALLOUT B
BEGIN COMMENT
# Connect, then bind to host.
# Соединение, затем привязка к хосту
END COMMENT
my $ldap = Net::LDAP->new($opts{h}, port => $opts{p} || 389) or die «$@
»;
my $rc = $ldap->bind( $opts{D}, password => $opts{w});
die $rc->error if $rc->code;
# END CALLOUT B
# BEGIN CALLOUT C
BEGIN COMMENT
# Perform search and display results.
# Выполнение поиска и отображение результатов
END COMMENT
my $search = $ldap->search (
            base => $opts{b}, 
            scope => $opts{s}, 
            filter => $opts{f}, 
            attrs => [split /, /, $opts{a}], 
          );
die $search->error if $search->code;
foreach my $entry ($search->entries) {
	$entry->dump;
}
$ldap->unbind;
exit;
# END CALLOUT C
# BEGIN CALLOUT D
BEGIN COMMENT
# Miscellaneous functions
# Различные функции.
END COMMENT
sub usage {
return qq(
usage: ldapsearch.pl [options]
options (all are required except port):
	-b basedn    base dn for search
	-s scope    one of base, one, or sub (search scope)
	-h host     ldap server
	-D binddn    bind dn
	-w passwd    bind passwd (for authentication)
	-f filter    RFC-2254 compliant LDAP search filter
	-a attributes  comma-separated list of attributes to retrieve
	-p port     port on ldap server
); 
}
sub validate_options {
	my $opts_ref = $_[0];
	foreach (qw(b s h D w f a)) {
		return(«-$_ required») unless $opts_ref->{$_};
	}
	my $filter = Net::LDAP::Filter->new($opts_ref->{f});
	return(«Bad search filter») unless ref $filter;
	return;
}
# END CALLOUT D