# HG changeset patch # User Heiko Schlittermann (JUMPER) # Date 1384203695 -3600 # Node ID 3bfbc22cb61c8090f4ad783b4aa82ff1d00b8694 first revision diff -r 000000000000 -r 3bfbc22cb61c schema2ldif --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema2ldif Mon Nov 11 22:01:35 2013 +0100 @@ -0,0 +1,129 @@ +#! /usr/bin/perl +# according +# http://www.zytrax.com/books/ldap/ch6/slapd-config.html#use-schemas +# © 2013 Heiko Schlittermann + +use 5.010; +use strict; +use warnings; +use if $ENV{DEBUG} => 'Smart::Comments'; +use English qw(-no_match_vars); +use File::Temp; +use File::Spec::Functions; +use Getopt::Long; +use Pod::Usage; + +our $VERSION = 0.01; + +my @opt_schema_dirs = qw(/etc/ldap/schema); +my @opt_additional_schemas = (); + +GetOptions( + 'schema_dir=s@' => \@opt_schema_dirs, + 'additional_schema=s@' => \@opt_additional_schemas, +) and @ARGV == 1 or pod2usage(); + +# find the additional schema definitions +my @schemas = do { + my @rc = (); + + open(my $f, '<', $ARGV[0]) or die "$PROGRAM_NAME: $ARGV[0]: $!\n"; + while (<$f>) { + if (/^#schema2ldif:include\s+(\S+)/) { + push @opt_additional_schemas, $1; + } + } + close($f); + foreach my $file (@opt_additional_schemas) { + $file .= '.schema' unless $file =~ /\.schema$/xms; + if (-f $file) { + push @rc, catfile('.', $file); + next; + } + ($_) = grep { -f } map { catfile $_, $file } @opt_schema_dirs; + if ($_) { + push @rc, $_; + next; + } + die "$PROGRAM_NAME: $file: $!\n"; + } + @rc; +}; + +### @opt_schema_dirs +### @opt_additional_schemas +### @schemas + +(my $name = $ARGV[0]) =~ s/\.schema$//xms; +my $cf = File::Temp->new(); +my $cd = File::Temp->newdir(); + +# create a short temp config +$cf->print("include $_\n") foreach @schemas, $ARGV[0]; +close $cf or die "Can't close $cf: $!\n"; +# ... convert it +system slaptest => ( -f => $cf ), + ( -F => $cd ); +die "slaptest failed, exit\n" if $?; + +# slurp the generated file +# FIXME: what, if we had multiple preconditions +open(my $ldif, '<', $_ = "$cd/cn=config/cn=schema/cn={1}$name.ldif") + or die "Can't open $_: $!\n"; +$_ = do { local $RS = undef; <$ldif> }; +close($ldif) or die "Can't close ldif generated ldif file: $!\n"; + +# some modifications +s/\n\s+//xgms; +s/^(?!(?:olc|dn|objectClass|cn)).*?\n//xmsg; +s/(?<=^dn:\scn=){\d+}(\w+)/$1,cn=schema,cn=config/xms; +s/(?<=^cn:\s){\d+}//xmsg; + +print <<"__", $_; +# autogenerated by $PROGRAM_NAME +# do not edit, edit $name.schema instead +# see https://ssl.schlittermann.de/hg/exim-ldap-schema +__ + +__END__ + +=head1 NAME + + schema2ldif - convert an LDAP schema definition into an LDIF for cn=config + +=head1 SYNOPSIS + + schema2ldif [--schema-dir=s]... [--additional-schema=s]... schema + +=head1 DESCRIPTION + +This B converts an LDAP schema definition into an LDIF +file. + +=head2 OPTIONS + +=over 4 + +=item B<--schema-dir> I + +A directory where to search for the additional schema(s). May +be used multiple times. (default: F + +=item B<--additional-schema> I + +Additional schema to be included (preconditions for your self +defind schema). The F<.schema> extension may be omitted. First it's +searched in the local directory, then in the directories given in +B<--schema-dir> option(s). (default: none) + +NOTE: A pseudo comment + + #include core.schema + +may be included in the schema to convert. It works the same way. + +=back + +=head1 EXAMPLES + + schema2ldif exim.schema | sudo ldapadd -Y external -H ldapi:///