summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorCVS Import User <samba-bugs@samba.org>2004-04-04 09:21:52 +0000
committerCVS Import User <samba-bugs@samba.org>2004-04-04 09:21:52 +0000
commit9f765b7406282904ce56f2535dcd929a9aefc5ca (patch)
treedbdff78b624ac7c1afcb8851f395df3d99eb1f84 /examples
parent111b4e05ab96eafc4212f38dc5977538907187c7 (diff)
downloadsamba-9f765b7406282904ce56f2535dcd929a9aefc5ca.tar.gz
samba-9f765b7406282904ce56f2535dcd929a9aefc5ca.tar.xz
samba-9f765b7406282904ce56f2535dcd929a9aefc5ca.zip
r2: import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
metze
Diffstat (limited to 'examples')
-rw-r--r--examples/LDAP/README74
-rwxr-xr-xexamples/LDAP/convertSambaAccount233
-rw-r--r--examples/LDAP/ldapsync.pl122
-rw-r--r--examples/LDAP/samba-nds.schema151
-rw-r--r--examples/LDAP/samba-schema-netscapeds4.x112
-rw-r--r--examples/LDAP/samba-schema-netscapeds5.x55
-rw-r--r--examples/LDAP/samba-schema.IBMSecureWay43
-rw-r--r--examples/LDAP/samba.schema424
-rw-r--r--examples/LDAP/samba.schema.at.IBM-DS59
-rw-r--r--examples/LDAP/samba.schema.oc.IBM-DS19
-rw-r--r--examples/LDAP/smbldap-tools/CONTRIBUTORS33
-rw-r--r--examples/LDAP/smbldap-tools/COPYING340
-rw-r--r--examples/LDAP/smbldap-tools/ChangeLog89
-rw-r--r--examples/LDAP/smbldap-tools/FILES43
-rw-r--r--examples/LDAP/smbldap-tools/INFRASTRUCTURE93
-rw-r--r--examples/LDAP/smbldap-tools/INSTALL28
-rw-r--r--examples/LDAP/smbldap-tools/Makefile35
-rw-r--r--examples/LDAP/smbldap-tools/README87
-rw-r--r--examples/LDAP/smbldap-tools/TODO28
-rw-r--r--examples/LDAP/smbldap-tools/cgi/README27
-rwxr-xr-xexamples/LDAP/smbldap-tools/cgi/ldappass.cgi202
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/Makefile62
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/getopt.c756
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/getopt.h133
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/md4.c171
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c253
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h17
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/smbdes.c337
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupadd.pl158
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupdel.pl93
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupmod.pl283
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupshow.pl74
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl230
-rw-r--r--examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl225
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-passwd.pl227
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-populate.pl370
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-tools.spec140
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-useradd.pl522
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-userdel.pl125
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-usermod.pl488
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-usershow.pl72
-rw-r--r--examples/LDAP/smbldap-tools/smbldap_conf.pm248
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap_tools.pm771
-rw-r--r--examples/README11
-rw-r--r--examples/VFS/.cvsignore9
-rw-r--r--examples/VFS/Makefile.in43
-rw-r--r--examples/VFS/README20
-rwxr-xr-xexamples/VFS/autogen.sh60
-rw-r--r--examples/VFS/configure.in350
-rw-r--r--examples/VFS/install-sh238
-rw-r--r--examples/VFS/shadow_copy_test.c83
-rw-r--r--examples/VFS/skel_opaque.c581
-rw-r--r--examples/VFS/skel_transparent.c548
-rw-r--r--examples/appliance/Makefile68
-rw-r--r--examples/appliance/README52
-rw-r--r--examples/appliance/appliance.spec389
-rwxr-xr-xexamples/appliance/build.sh4
-rw-r--r--examples/appliance/smb.conf-appliance8
-rw-r--r--examples/auth/Makefile31
-rw-r--r--examples/auth/auth_skel.c59
-rw-r--r--examples/autofs/auto.a15
-rw-r--r--examples/dce-dfs/README4
-rw-r--r--examples/dce-dfs/smb.conf42
-rw-r--r--examples/genlogon/genlogon.pl71
-rw-r--r--examples/libsmbclient/Makefile36
-rw-r--r--examples/libsmbclient/README8
-rw-r--r--examples/libsmbclient/testacl.c280
-rw-r--r--examples/libsmbclient/testbrowse.c91
-rw-r--r--examples/libsmbclient/testsmbc.c335
-rw-r--r--examples/libsmbclient/tree.c813
-rw-r--r--examples/misc/extra_smbstatus50
-rwxr-xr-xexamples/misc/modify_samba_config.pl154
-rw-r--r--examples/misc/swat.pl122
-rw-r--r--examples/misc/wall.perl69
-rw-r--r--examples/nss/nss_winbind.c422
-rw-r--r--examples/nss/nss_winbind.h97
-rw-r--r--examples/nss/wbtest.c111
-rw-r--r--examples/ntlogon/README160
-rw-r--r--examples/ntlogon/ntlogon.conf44
-rwxr-xr-xexamples/ntlogon/ntlogon.py376
-rw-r--r--examples/pdb/Makefile31
-rw-r--r--examples/pdb/README16
-rw-r--r--examples/pdb/mysql/mysql.dump37
-rw-r--r--examples/pdb/mysql/smb.conf11
-rw-r--r--examples/pdb/pdb_test.c145
-rw-r--r--examples/pdb/sambapdb.dtd46
-rw-r--r--examples/printer-accounting/README63
-rw-r--r--examples/printer-accounting/acct-all9
-rw-r--r--examples/printer-accounting/acct-sum29
-rw-r--r--examples/printer-accounting/hp5-redir40
-rw-r--r--examples/printer-accounting/lp-acct35
-rw-r--r--examples/printer-accounting/printcap22
-rw-r--r--examples/printing/prtpub.c238
-rw-r--r--examples/printing/readme.prtpub12
-rwxr-xr-xexamples/printing/smbprint144
-rw-r--r--examples/printing/smbprint-new.sh144
-rwxr-xr-xexamples/printing/smbprint.old95
-rw-r--r--examples/printing/smbprint.sysv52
-rw-r--r--examples/simple/README2
-rw-r--r--examples/simple/smb.conf167
-rw-r--r--examples/smb.conf.default273
-rw-r--r--examples/svr4-startup/README24
-rwxr-xr-xexamples/svr4-startup/samba.server38
-rw-r--r--examples/thoralf/smb.conf152
-rw-r--r--examples/tridge/README8
-rw-r--r--examples/tridge/smb.conf101
-rw-r--r--examples/tridge/smb.conf.WinNT14
-rw-r--r--examples/tridge/smb.conf.fjall21
-rw-r--r--examples/tridge/smb.conf.lapland14
-rw-r--r--examples/tridge/smb.conf.vittjokk14
-rw-r--r--examples/validchars/msdos70.out257
-rw-r--r--examples/validchars/nwdos70.out257
-rw-r--r--examples/validchars/readme101
-rw-r--r--examples/validchars/validchr.c123
-rw-r--r--examples/validchars/validchr.com77
-rw-r--r--examples/wins_hook/README8
-rw-r--r--examples/wins_hook/dns_update94
117 files changed, 16820 insertions, 0 deletions
diff --git a/examples/LDAP/README b/examples/LDAP/README
new file mode 100644
index 00000000000..2f4b4f2a056
--- /dev/null
+++ b/examples/LDAP/README
@@ -0,0 +1,74 @@
+!==
+!== README File for various LDAP examples
+!==
+!== written by Gerald Carter <jerry@samba.org>
+!==
+
+OpenLDAP 2.x
+------------
+
+A sample schema file (samba.schema) has been included for use
+with OpenLDAP 2.0.x. The OIDs used in this file are owned by
+the Samba team and generated from its own Enterprise number
+of 7165 (as issued by IANA).
+
+Copy the samba.schema file into your /etc/openldap/schema directory,
+and add an include for it in the /etc/openldap/slapd.conf file.
+Note that samba.schema relies upon the uid and uidNumber attributes
+from the RFC2307 schema (i.e. nis.schema)
+
+If you choose to import /etc/passwd, nis, or nisplus tables
+into ldap, you can use migration tools provided by PADL Software
+which are located at
+
+ http://www.padl.com/tools.html
+
+It is not a requirement that a user's /etc/passwd account
+is stored in LDAP for the samba.schema file to work (although
+the whole point of storing smbpasswd in LDAP is to have a
+single location for user accounts, right?)
+
+The padl tools will leave you with LDIF files which you can import
+into OpenLDAP. Before you can import them, you need to include
+nis.schema and cosine.schema in your slapd.conf file.
+
+You must restart the LDAP server for these new included schema files
+to become active.
+
+SunOne/Netscape DS
+------------------
+
+The schema file has not been updated for the sambaSamAccount
+objectclass.
+
+
+Novell eDirectory
+-----------------
+
+The schema file has not been updated for the sambaSamAccount
+objectclass.
+
+
+smbldap-tools/
+--------------
+
+This is a collection of perl scripts (wrapped around the standard
+OpenLDAP command line tools) for managing Samba and posix accounts
+in an LDAP directory. See the README file included with the scripts
+for more details.
+
+
+ldapsync.pl
+-----------
+For more information on these scripts, see
+
+ http://www.mami.net/univr/tng-ldap/howto/
+
+
+The ldapsync.pl script requires a small command (smbencrypt)
+for generating LanMan and NT password hashes which
+can be found at ftp://samba.org/pub/samba/contributed/
+
+!==
+!== end of README
+!==
diff --git a/examples/LDAP/convertSambaAccount b/examples/LDAP/convertSambaAccount
new file mode 100755
index 00000000000..4357dbc8f8d
--- /dev/null
+++ b/examples/LDAP/convertSambaAccount
@@ -0,0 +1,233 @@
+#!/usr/bin/perl -w
+##
+## Convert an LDIF file containing sambaAccount entries
+## to the new sambaSamAccount objectclass
+##
+## Copyright Gerald (Jerry) Carter 2003
+##
+## Usage: convertSambaAccount --sid=<Domain SID> \
+## --input=<input ldif> --output=<output ldif> \
+## --changetype=[modify|add]
+##
+## You can generate an input ldif file using:
+## $ ldapsearch -LL -x -h ldapsrv -D cn=root,dc=company,dc=com \
+## -b dc=copmany,dc=com > /tmp/samba3.alpha23.ldif
+##
+## Note the "-LL" so no additional comments are generated
+##
+
+
+use strict;
+use Net::LDAP::LDIF;
+use Getopt::Long;
+
+
+##############################################################################
+## local variables
+
+my ( $domain, $domsid, $changetype );
+my ( $ldif, $ldif2 );
+my ( $entry, @objclasses, $obj );
+my ( $is_samba_account, $is_samba_group );
+my ( %attr_map, %group_attr_map, $key );
+my ( @dels, $deletion, @adds, $addition );
+my ( $result, %options );
+
+
+##############################################################################
+## Print the option usage
+
+sub usage {
+
+ print "convertSambaAccount <options>\n";
+ print "Options:\n";
+ print " --help print this help message\n";
+ print " --input input LDIF filename\n";
+ print " --output output LDIF filename\n";
+ print " --sid domain SID\n";
+ print " --changetype [modify|add] (default is 'add')\n";
+}
+
+
+##############################################################################
+## MAIN DRIVER ##
+##############################################################################
+
+##
+## hashes to map old attribute names to new ones
+##
+
+%attr_map = (
+ lmPassword => 'sambaLMPassword',
+ ntPassword => 'sambaNTPassword',
+ pwdLastSet => 'sambaPwdLastSet',
+ pwdMustChange => 'sambaPwdMustChange',
+ pwdCanChange => 'sambaPwdCanChange',
+ homeDrive => 'sambaHomeDrive',
+ smbHome => 'sambaHomePath',
+ scriptPath => 'sambaLogonScript',
+ profilePath => 'sambaProfilePath',
+ kickoffTime => 'sambaKickoffTime',
+ logonTime => 'sambaLogonTime',
+ logoffTime => 'sambaLogoffTime',
+ userWorkstations => 'sambaUserWorkstations',
+ domain => 'sambaDomainName',
+ acctFlags => 'sambaAcctFlags',
+);
+
+%group_attr_map = (
+ ntSid => 'sambaSID',
+ ntGroupType => 'sambaGroupType',
+);
+
+##
+## process command line args
+##
+
+$result = GetOptions(\%options,
+ "help",
+ "input=s",
+ "output=s",
+ "sid=s",
+ "changetype=s");
+
+if (!$result && ($#ARGV != -1)) {
+ usage();
+ exit 1;
+}
+
+if ( defined($options{'help'}) ) {
+ usage();
+ exit 0;
+}
+
+
+if ( !defined( $options{'sid'} ) ) {
+ print "You must provide a domain sid\n";
+ exit 1;
+}
+
+$domsid = $options{'sid'};
+
+$changetype = 'add';
+if ( defined( $options{'changetype'} ) ) {
+ $changetype = $options{'changetype'};
+}
+
+##
+## open files
+##
+
+$ldif = Net::LDAP::LDIF->new ($options{'input'}, "r") or die $!;
+
+if ( "$changetype" eq "add" ) {
+ $ldif2 = Net::LDAP::LDIF->new ($options{'output'}, "w") or die $!;
+}
+elsif ( "$changetype" eq "modify" ) {
+ open( OUTPUT, ">$options{'output'}" ) or die $!;
+}
+else {
+ print "Bad changetype!\n";
+ exit 1;
+}
+
+##
+## process LDIF
+##
+
+while ( !$ldif->eof ) {
+ undef ( $entry );
+ $entry = $ldif->read_entry();
+
+ ## skip entry if we find an error
+ if ( $ldif->error() ) {
+ print "Error msg: ",$ldif->error(),"\n";
+ print "Error lines:\n",$ldif->error_lines(),"\n";
+ next;
+ }
+
+ ##
+ ## check to see if we have anything to do on this
+ ## entry. If not just write it out
+ ##
+ @objclasses = $entry->get_value( "objectClass" );
+ undef ( $is_samba_account );
+ undef ( $is_samba_group );
+ @adds = ();
+ @dels = ();
+ foreach $obj ( @objclasses ) {
+ if ( "$obj" eq "sambaAccount" ) {
+ $is_samba_account = 1;
+ } elsif ( "$obj" eq "sambaGroupMapping" ) {
+ $is_samba_group = 1;
+ }
+ }
+
+ if ( defined ( $is_samba_account ) ) {
+ ##
+ ## start editing the sambaAccount
+ ##
+
+ @dels = ( 'objectclass: sambaAccount', 'rid' );
+ @adds = ('objectclass: sambaSamAccount', "sambaSID: " . ${domsid} . "-" . ${entry}->get_value( 'rid' ) );
+ $entry->delete( 'objectclass' => [ 'sambaAccount' ] );
+ $entry->add( 'objectclass' => 'sambaSamAccount' );
+
+ $entry->add( 'sambaSID' => $domsid."-".$entry->get_value( "rid" ) );
+ $entry->delete( 'rid' );
+
+ if ( defined($entry->get_value( "primaryGroupID" )) ) {
+ push @adds, "sambaPrimaryGroupSID: " . $domsid."-".$entry->get_value( "primaryGroupID" );
+ push @dels, "primaryGroupID";
+ $entry->add( 'sambaPrimaryGroupSID' => $domsid."-".$entry->get_value( "primaryGroupID" ) );
+ $entry->delete( 'primaryGroupID' );
+ }
+
+
+ foreach $key ( keys %attr_map ) {
+ if ( defined($entry->get_value($key)) ) {
+ push @adds, "$attr_map{$key}: " . $entry->get_value($key);
+ push @dels, "$key";
+ $entry->add( $attr_map{$key} => $entry->get_value($key) );
+ $entry->delete( $key );
+ }
+ }
+ } elsif ( defined ( $is_samba_group ) ) {
+ foreach $key ( keys %group_attr_map ) {
+ if ( defined($entry->get_value($key)) ) {
+ push @adds, "$group_attr_map{$key}: " . $entry->get_value($key);
+ push @dels, "$key";
+ $entry->add( $group_attr_map{$key} => $entry->get_value($key) );
+ $entry->delete( $key );
+ }
+ }
+ }
+
+ ## see if we should write full entries or only the changes
+
+ if ( "$changetype" eq "add" ) {
+ $ldif2->write_entry( $entry );
+ }
+ else {
+ if ( defined ( $is_samba_account ) || defined ( $is_samba_group ) ){
+ if ( @adds + @dels > 0 ) {
+ print OUTPUT "dn: " . $entry->dn . "\n";
+ foreach $addition (@adds) {
+ $addition =~ /(^\w+):/;
+ print OUTPUT "add: " . $1 . "\n";
+ print OUTPUT "$addition\n-\n";
+ }
+ foreach $deletion (@dels) {
+ if ( $deletion =~ /^(\w+):\s(.*)/ ) {
+ print OUTPUT "delete: $1\n$1: $2\n-\n";
+ } else {
+ print OUTPUT "delete: $deletion\n-\n"
+ }
+ }
+ print OUTPUT "\n"
+ }
+ }
+ }
+}
+
+
diff --git a/examples/LDAP/ldapsync.pl b/examples/LDAP/ldapsync.pl
new file mode 100644
index 00000000000..c112bcc34cb
--- /dev/null
+++ b/examples/LDAP/ldapsync.pl
@@ -0,0 +1,122 @@
+#!/usr/bin/perl -w
+
+# LDAP to unix password sync script for samba-tng
+# originally by Jody Haynes <Jody.Haynes@isunnetworks.com>
+# 12/12/2000 milos@interactivesi.com
+# modified for use with MD5 passwords
+# 12/16/2000 mami@arena.sci.univr.it
+# modified to change lmpassword and ntpassword for samba
+# 05/01/2001 mami@arena.sci.univr.it
+# modified for being also a /bin/passwd replacement
+#
+# ACHTUNG!! For servers that support the LDAP Modify password
+# extended op (e.g. OpenLDAP), see the "ldap password
+# sync" option in smb.conf(5).
+#
+
+$basedn = "ou=Students,dc=univr, dc=it";
+$binddn = "uid=root,dc=univr,dc=it";
+$scope = "sub";
+$passwd = "mysecret";
+
+foreach $arg (@ARGV) {
+ if ($< != 0) {
+ die "Only root can specify parameters\n";
+ } else {
+ if ( ($arg eq '-?') || ($arg eq '--help') ) {
+ print "Usage: $0 [-o] [username]\n";
+ print " -o, --without-old-password do not ask for old password (root only)\n";
+ print " -?, --help show this help message\n";
+ exit (-1);
+ } elsif ( ($arg eq '-o') || ($arg eq '--without-old-password') ) {
+ $oldpass = 1;
+ } elsif (substr($arg,0) ne '-') {
+ $user = $arg;
+ if (!defined(getpwnam($user))) {
+ die "$0: Unknown user name '$user'\n"; ;
+ }
+ }
+ }
+}
+
+if (!defined($user)) {
+ $user=$ENV{"USER"};
+}
+
+if (!defined($oldpass)) {
+ system "stty -echo";
+ print "Old password for user $user: ";
+ chomp($oldpass=<STDIN>);
+ print "\n";
+ system "stty echo";
+
+ $ntpwd = `/usr/local/sbin/smbencrypt '$oldpass'`;
+ $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')); chomp $lmpassword;
+ $ntpassword = substr($ntpwd, index($ntpwd, ':')+1); chomp $ntpassword;
+
+ # Find dn for user $user (maybe check unix password too?)
+ $dn=`ldapsearch -b '$basedn' -s '$scope' '(&(uid=$user)(lmpassword=$lmpassword)(ntpassword=$ntpassword))'|head -1`;
+ chomp $dn;
+
+ if ($dn eq '') {
+ print "Wrong password for user $user!\n";
+ exit (-1);
+ }
+} else {
+ # Find dn for user $user
+ $dn=`ldapsearch -b '$basedn' -s '$scope' '(uid=$user)'|head -1`;
+ chomp $dn;
+}
+
+system "stty -echo";
+print "New password for user $user: ";
+chomp($pass=<STDIN>);
+print "\n";
+system "stty echo";
+
+system "stty -echo";
+print "Retype new password for user $user: ";
+chomp($pass2=<STDIN>);
+print "\n";
+system "stty echo";
+
+if ($pass ne $pass2) {
+ die "Wrong password!\n";
+} else {
+# MD5 password
+$random = join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64];
+$bsalt = "\$1\$"; $esalt = "\$";
+$modsalt = $bsalt.$random.$esalt;
+$password = crypt($pass, $modsalt);
+
+# LanManager and NT clear text passwords
+$ntpwd = `/usr/local/sbin/smbencrypt '$pass'`;
+chomp($lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
+chomp($ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
+
+$FILE="|/usr/bin/ldapmodify -D '$binddn' -w $passwd";
+
+open FILE or die;
+
+print FILE <<EOF;
+dn: $dn
+changetype: modify
+replace: userPassword
+userPassword: {crypt}$password
+-
+changetype: modify
+replace: lmpassword
+lmpassword: $lmpassword
+-
+changetype: modify
+replace: ntpassword
+ntpassword: $ntpassword
+-
+
+EOF
+close FILE;
+
+}
+
+exit 0;
+
diff --git a/examples/LDAP/samba-nds.schema b/examples/LDAP/samba-nds.schema
new file mode 100644
index 00000000000..8369c8404ec
--- /dev/null
+++ b/examples/LDAP/samba-nds.schema
@@ -0,0 +1,151 @@
+##
+## Schema file for Novell eDirectory 8.7.x by Uli Iske
+## Schema for storing Samba's smbpasswd file in LDAP
+## OIDs are owned by the Samba Team
+##
+#######################################################################
+## Attributes used by Samba 3.0 schema ##
+#######################################################################
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags' DESC 'Account Flags' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet' DESC 'Timestamp of the last password update' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange' DESC 'Timestamp of when the user is allowed to update the password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange' DESC 'Timestamp of when the password will expire' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime' DESC 'Timestamp of last logon' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime' DESC 'Timestamp of last logoff' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime' DESC 'Timestamp of when the user will be logged off automatically' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive' DESC 'Driver letter of home directory mapping' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript' DESC 'Logon script path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath' DESC 'Roaming profile path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations' DESC 'List of user workstations the user is allowed to logon to' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath' DESC 'Home directory UNC path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName' DESC 'Windows NT domain to which the user belongs' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID' DESC 'Security ID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID' DESC 'Primary Group Security ID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType' DESC 'NT Group Type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid' DESC 'Next NT rid to give our for users' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid' DESC 'Next NT rid to give out for groups' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid to give out for anything' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#######################################################################
+## objectClasses used by Samba 3.0 schema ##
+#######################################################################
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' DESC 'Samba 3.0 Auxilary SAM Account' SUP top AUXILIARY MUST ( uid $ sambaSID ) MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $sambaLogonTime $ sambaLogoffTime $sambaKickoffTime $sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $sambaProfilePath $ description $ sambaUserWorkstations $sambaPrimaryGroupSID $ sambaDomainName ))
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' DESC 'Samba Group Mapping' SUP top AUXILIARY MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY ( displayName $ description ))
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' DESC 'Samba Domain Information' SUP top STRUCTURAL MUST ( sambaDomainName $sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $sambaAlgorithmicRidBase ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' DESC 'Pool for allocating UNIX uids/gids' SUP top AUXILIARY MUST ( uidNumber $ gidNumber ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' DESC 'Mapping from a SID to an ID' SUP top AUXILIARY MUST ( sambaSID ) MAY ( uidNumber $ gidNumber ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' DESC 'Structural Class for a SID' SUP top STRUCTURAL MUST ( sambaSID ) )
diff --git a/examples/LDAP/samba-schema-netscapeds4.x b/examples/LDAP/samba-schema-netscapeds4.x
new file mode 100644
index 00000000000..9f409664187
--- /dev/null
+++ b/examples/LDAP/samba-schema-netscapeds4.x
@@ -0,0 +1,112 @@
+#
+# LDAP Schema file for SAMBA 3.0 attribute storage
+# For Netscape Directory Server 4.1x
+# Prepared by Osman Demirhan
+
+attribute sambaLMPassword 1.3.6.1.4.1.7165.2.1.24 cis single
+attribute sambaNTPassword 1.3.6.1.4.1.7165.2.1.25 cis single
+attribute sambaAcctFlags 1.3.6.1.4.1.7165.2.1.26 cis single
+attribute sambaPwdLastSet 1.3.6.1.4.1.7165.2.1.27 int single
+attribute sambaPwdCanChange 1.3.6.1.4.1.7165.2.1.28 int single
+attribute sambaPwdMustChange 1.3.6.1.4.1.7165.2.1.29 int single
+attribute sambaLogonTime 1.3.6.1.4.1.7165.2.1.30 int single
+attribute sambaLogoffTime 1.3.6.1.4.1.7165.2.1.31 int single
+attribute sambaKickoffTime 1.3.6.1.4.1.7165.2.1.32 int single
+attribute sambaHomeDrive 1.3.6.1.4.1.7165.2.1.33 cis single
+attribute sambaLogonScript 1.3.6.1.4.1.7165.2.1.34 cis single
+attribute sambaProfilePath 1.3.6.1.4.1.7165.2.1.35 cis single
+attribute sambaUserWorkstations 1.3.6.1.4.1.7165.2.1.36 cis single
+attribute sambaHomePath 1.3.6.1.4.1.7165.2.1.37 cis single
+attribute sambaDomainName 1.3.6.1.4.1.7165.2.1.38 cis single
+attribute sambaSID 1.3.6.1.4.1.7165.2.1.20 cis single
+attribute sambaPrimaryGroupSID 1.3.6.1.4.1.7165.2.1.23 cis single
+attribute sambaGroupType 1.3.6.1.4.1.7165.2.1.19 int single
+attribute sambaNextUserRid 1.3.6.1.4.1.7165.2.1.21 int single
+attribute sambaNextGroupRid 1.3.6.1.4.1.7165.2.1.22 int single
+attribute sambaNextRid 1.3.6.1.4.1.7165.2.1.39 int single
+attribute sambaAlgorithmicRidBase 1.3.6.1.4.1.7165.2.1.40 int single
+
+objectclass sambaSamAccount
+ oid
+ 1.3.6.1.4.1.7165.2.2.6
+ superior
+ top
+ requires
+ objectClass,
+ uid,
+ sambaSID
+ allows
+ cn,
+ sambaLMPassword,
+ sambaNTPassword,
+ sambaPwdLastSet,
+ sambaLogonTime,
+ sambaLogoffTime,
+ sambaKickoffTime,
+ sambaPwdCanChange,
+ sambaPwdMustChange,
+ sambaAcctFlags,
+ displayName,
+ sambaHomePath,
+ sambaHomeDrive,
+ sambaLogonScript,
+ sambaProfilePath,
+ description,
+ sambaUserWorkstations,
+ sambaPrimaryGroupSID,
+ sambaDomainName
+
+objectclass sambaGroupMapping
+ oid
+ 1.3.6.1.4.1.7165.2.2.4
+ superior
+ top
+ requires
+ gidNumber,
+ sambaSID,
+ sambaGroupType
+ allows
+ displayName,
+ description
+
+objectclass sambaDomain
+ oid
+ 1.3.6.1.4.1.7165.2.2.5
+ superior
+ top
+ requires
+ sambaDomainName,
+ sambaSID
+ allows
+ sambaNextRid,
+ sambaNextGroupRid,
+ sambaNextUserRid,
+ sambaAlgorithmicRidBase
+
+objectclass sambaUnixIdPool
+ oid
+ 1.3.6.1.4.1.7165.1.2.2.7
+ superior
+ top
+ requires
+ uidNumber,
+ gidNumber
+
+objectclass sambaIdmapEntry
+ oid
+ 1.3.6.1.4.1.7165.1.2.2.8
+ superior
+ top
+ requires
+ sambaSID
+ allows
+ uidNumber,
+ gidNumber
+
+objectclass sambaSidEntry
+ oid
+ 1.3.6.1.4.1.7165.1.2.2.9
+ superior
+ top
+ requires
+ sambaSID
diff --git a/examples/LDAP/samba-schema-netscapeds5.x b/examples/LDAP/samba-schema-netscapeds5.x
new file mode 100644
index 00000000000..e750039acbf
--- /dev/null
+++ b/examples/LDAP/samba-schema-netscapeds5.x
@@ -0,0 +1,55 @@
+##
+## Darren Chew <darren.chew at vicscouts dot asn dot au>
+## Andre Fiebach <andre dot fiebach at stud dot uni-rostock dot de>
+##
+## Samba 3.0 schema file for Netscape DS 5.x
+##
+## INSTALL-DIRECTORY/slapd-your_name/config/schema/samba-schema-netscapeds5.ldif
+####################################################################
+# Sun One DS do not load the schema without this lines
+# André Fiebach <af123@uni-rostock.de>
+dn: cn=schema
+objectClass: top
+objectClass: ldapSubentry
+objectClass: subschema
+cn: schema
+aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymo
+ us, no acis"; allow (read, search, compare) userdn = "ldap:///anyone";)
+aci: (targetattr = "*")(version 3.0; acl "Configuration Administrator"; allow
+ (all) userdn = "ldap:///uid=admin,ou=Administrators, ou=TopologyManagement,
+ o=NetscapeRoot";)
+aci: (targetattr = "*")(version 3.0; acl "Local Directory Administrators Group
+ "; allow (all) groupdn = "ldap:///cn=Directory Administrators, dc=samba,dc=org";)
+aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all)groupdn = "ld
+ ap:///cn=slapd-sambaldap, cn=iPlanet Directory Server, cn=Server Group, cn=iPlanetDirectory.samba.org, ou=samba.org, o=NetscapeRoot";)
+modifiersName: cn=directory manager
+modifyTimestamp: 20020322124844Z
+####################################################################
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY DESC 'Samba 3.0 Auxilary SAM Account' MUST ( uid $ sambaSID ) MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY DESC 'Samba Group Mapping' MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY ( displayName $ description ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL DESC 'Samba Domain Information' MUST ( sambaDomainName $ sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $ sambaAlgorithmicRidBase ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY DESC 'Pool for allocating UNIX uids/gids' MUST ( uidNumber $ gidNumber ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY DESC 'Mapping from a SID to an ID' MUST ( sambaSID ) MAY ( uidNumber $ gidNumber ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL DESC 'Structural Class for a SID' MUST ( sambaSID ) X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet' DESC 'Timestamp of the last password update' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange' DESC 'Timestamp of when the user is allowed to update the password' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange' DESC 'Timestamp of when the password will expire' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime' DESC 'Timestamp of last logon' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime' DESC 'Timestamp of last logoff' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime' DESC 'Timestamp of when the user will be logged off automatically' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive' DESC 'Driver letter of home directory mapping' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript' DESC 'Logon script path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath' DESC 'Roaming profile path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations' DESC 'List of user workstations the user is allowed to logon to' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath' DESC 'Home directory UNC path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName' DESC 'Windows NT domain to which the user belongs' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID' DESC 'Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID' DESC 'Primary Group Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType' DESC 'NT Group Type' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid' DESC 'Next NT rid to give our for users' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid' DESC 'Next NT rid to give out for groups' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid to give out for anything' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
diff --git a/examples/LDAP/samba-schema.IBMSecureWay b/examples/LDAP/samba-schema.IBMSecureWay
new file mode 100644
index 00000000000..1fca4a749a6
--- /dev/null
+++ b/examples/LDAP/samba-schema.IBMSecureWay
@@ -0,0 +1,43 @@
+##
+## Submitted by Dirk Kastens <Dirk.Kastens@Uni-Osnabrueck.de>
+##
+## I translated the samba.schema to be used with IBM
+## SecureWay directoy server 3.2.2. You have to load
+## it in your slapd32.conf with:
+##
+## dn: cn=IBM SecureWay, cn=Schemas, cn=Configuration
+## cn: IBM SecureWay
+## ibm-slapdIncludeSchema: /etc/lapschema/samba.schema
+##
+objectClasses {
+( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' DESC 'Samba Account' SUP top MUST uid $ rid MAY ( acctFlags $ cn $ description $ displayName $ homeDrive $ kickoffTime $ lmPassword $ logoffTime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $ pwdLastSet $ pwdMustChange $ scriptPath $ smbHome $ userWorkstations ) )
+}
+
+attributeTypes {
+( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' DESC 'LanManager Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' DESC 'NT homeDrive' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' DESC 'NT scriptPath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' DESC 'NT profilePath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' DESC 'userWorkstations' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' DESC 'NT rid' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' DESC 'NT Group RID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' DESC 'smbHome' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' DESC 'NT Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet' DESC 'NT pwdLastSet' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' DESC 'NT logonTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.6 NAME 'logoffTime' DESC 'NT logoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' DESC 'NT kickoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' DESC 'NT pwdCanChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' DESC 'NT pwdMustChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+}
+
+IBMattributeTypes {
+}
+
+ldapSyntaxes {
+}
+
+matchingRules {
+}
+
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema
new file mode 100644
index 00000000000..7d7fe346b2b
--- /dev/null
+++ b/examples/LDAP/samba.schema
@@ -0,0 +1,424 @@
+##
+## schema file for OpenLDAP 2.x
+## Schema for storing Samba user accounts and group maps in LDAP
+## OIDs are owned by the Samba Team
+##
+## Prerequisite schemas - uid (cosine.schema)
+## - displayName (inetorgperson.schema)
+## - gidNumber (nis.schema)
+##
+## 1.3.6.1.4.1.7165.2.1.x - attributetypes
+## 1.3.6.1.4.1.7165.2.2.x - objectclasses
+##
+
+########################################################################
+## HISTORICAL ##
+########################################################################
+
+##
+## Password hashes
+##
+#attributetype ( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword'
+# DESC 'LanManager Passwd'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword'
+# DESC 'NT Passwd'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+##
+## Account flags in string format ([UWDX ])
+##
+#attributetype ( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags'
+# DESC 'Account Flags'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
+
+##
+## Password timestamps & policies
+##
+#attributetype ( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet'
+# DESC 'NT pwdLastSet'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime'
+# DESC 'NT logonTime'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.6 NAME 'logoffTime'
+# DESC 'NT logoffTime'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime'
+# DESC 'NT kickoffTime'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange'
+# DESC 'NT pwdCanChange'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange'
+# DESC 'NT pwdMustChange'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+##
+## string settings
+##
+#attributetype ( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive'
+# DESC 'NT homeDrive'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath'
+# DESC 'NT scriptPath'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath'
+# DESC 'NT profilePath'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations'
+# DESC 'userWorkstations'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome'
+# DESC 'smbHome'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.18 NAME 'domain'
+# DESC 'Windows NT domain to which the user belongs'
+# EQUALITY caseIgnoreIA5Match
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+
+##
+## user and group RID
+##
+#attributetype ( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid'
+# DESC 'NT rid'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#attributetype ( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID'
+# DESC 'NT Group RID'
+# EQUALITY integerMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+##
+## The smbPasswordEntry objectclass has been depreciated in favor of the
+## sambaAccount objectclass
+##
+#objectclass ( 1.3.6.1.4.1.7165.2.2.1 NAME 'smbPasswordEntry' SUP top AUXILIARY
+# DESC 'Samba smbpasswd entry'
+# MUST ( uid $ uidNumber )
+# MAY ( lmPassword $ ntPassword $ pwdLastSet $ acctFlags ))
+
+#objectclass ( 1.3.6.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTURAL
+# DESC 'Samba Account'
+# MUST ( uid $ rid )
+# MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
+# logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
+# displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
+# description $ userWorkstations $ primaryGroupID $ domain ))
+
+#objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
+# DESC 'Samba Auxiliary Account'
+# MUST ( uid $ rid )
+# MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
+# logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
+# displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
+# description $ userWorkstations $ primaryGroupID $ domain ))
+
+########################################################################
+## END OF HISTORICAL ##
+########################################################################
+
+#######################################################################
+## Attributes used by Samba 3.0 schema ##
+#######################################################################
+
+##
+## Password hashes
+##
+attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword'
+ DESC 'LanManager Password'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword'
+ DESC 'MD4 hash of the unicode password'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+##
+## Account flags in string format ([UWDX ])
+##
+attributetype ( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags'
+ DESC 'Account Flags'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
+
+##
+## Password timestamps & policies
+##
+attributetype ( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet'
+ DESC 'Timestamp of the last password update'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange'
+ DESC 'Timestamp of when the user is allowed to update the password'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange'
+ DESC 'Timestamp of when the password will expire'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime'
+ DESC 'Timestamp of last logon'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime'
+ DESC 'Timestamp of last logoff'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime'
+ DESC 'Timestamp of when the user will be logged off automatically'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.48 NAME 'sambaBadPasswordCount'
+ DESC 'Bad password attempt count'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.49 NAME 'sambaBadPasswordTime'
+ DESC 'Time of the last bad password attempt'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+
+##
+## string settings
+##
+attributetype ( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive'
+ DESC 'Driver letter of home directory mapping'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript'
+ DESC 'Logon script path'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath'
+ DESC 'Roaming profile path'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations'
+ DESC 'List of user workstations the user is allowed to logon to'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath'
+ DESC 'Home directory UNC path'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName'
+ DESC 'Windows NT domain to which the user belongs'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial'
+ DESC ''
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} )
+
+##
+## SID, of any type
+##
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID'
+ DESC 'Security ID'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE )
+
+
+##
+## Primary group SID, compatible with ntSid
+##
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID'
+ DESC 'Primary Group Security ID'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE )
+
+##
+## group mapping attributes
+##
+attributetype ( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType'
+ DESC 'NT Group Type'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+##
+## Store info on the domain
+##
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid'
+ DESC 'Next NT rid to give our for users'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid'
+ DESC 'Next NT rid to give out for groups'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid'
+ DESC 'Next NT rid to give out for anything'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase'
+ DESC 'Base at which the samba RID generation algorithm should operate'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.41 NAME 'sambaShareName'
+ DESC 'Share Name'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.42 NAME 'sambaOptionName'
+ DESC 'Option Name'
+ EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.43 NAME 'sambaBoolOption'
+ DESC 'A boolean option'
+ EQUALITY booleanMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.44 NAME 'sambaIntegerOption'
+ DESC 'An integer option'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.45 NAME 'sambaStringOption'
+ DESC 'A string option'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption'
+ DESC 'A string list option'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME ( 'sambaPrivName' ) SUP name )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.51 NAME 'sambaSIDList'
+ DESC 'Security ID List'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} )
+
+#######################################################################
+## objectClasses used by Samba 3.0 schema ##
+#######################################################################
+
+## The X.500 data model (and therefore LDAPv3) says that each entry can
+## only have one structural objectclass. OpenLDAP 2.0 does not enforce
+## this currently but will in v2.1
+
+##
+## added new objectclass (and OID) for 3.0 to help us deal with backwards
+## compatibility with 2.2 installations (e.g. ldapsam_compat) --jerry
+##
+objectclass ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY
+ DESC 'Samba 3.0 Auxilary SAM Account'
+ MUST ( uid $ sambaSID )
+ MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $
+ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $
+ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
+ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $
+ sambaProfilePath $ description $ sambaUserWorkstations $
+ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial $
+ sambaBadPasswordCount $ sambaBadPasswordTime))
+
+##
+## Group mapping info
+##
+objectclass ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY
+ DESC 'Samba Group Mapping'
+ MUST ( gidNumber $ sambaSID $ sambaGroupType )
+ MAY ( displayName $ description $ sambaSIDList ))
+
+##
+## Whole-of-domain info
+##
+objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL
+ DESC 'Samba Domain Information'
+ MUST ( sambaDomainName $
+ sambaSID )
+ MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $
+ sambaAlgorithmicRidBase ) )
+
+## used for idmap_ldap module
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY
+ DESC 'Pool for allocating UNIX uids/gids'
+ MUST ( uidNumber $ gidNumber ) )
+
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY
+ DESC 'Mapping from a SID to an ID'
+ MUST ( sambaSID )
+ MAY ( uidNumber $ gidNumber ) )
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL
+ DESC 'Structural Class for a SID'
+ MUST ( sambaSID ) )
+
+
+
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.10 NAME 'sambaConfig' SUP top AUXILIARY
+ DESC 'Samba Configuration Section'
+ MAY ( description ) )
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.11 NAME 'sambaShare' SUP top STRUCTURAL
+ DESC 'Samba Share Section'
+ MUST ( sambaShareName )
+ MAY ( description ) )
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURAL
+ DESC 'Samba Configuration Option'
+ MUST ( sambaOptionName )
+ MAY ( sambaBoolOption $ sambaIntegerOption $ sambaStringOption $ sambaStringListoption $ description ) )
+
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.13 NAME 'sambaPrivilege' SUP top STRUCTURAL
+ DESC 'Samba Privilege'
+ MUST ( sambaPrivName )
+ MAY ( sambaSIDList $ description ) )
+
diff --git a/examples/LDAP/samba.schema.at.IBM-DS b/examples/LDAP/samba.schema.at.IBM-DS
new file mode 100644
index 00000000000..bc39d520fb6
--- /dev/null
+++ b/examples/LDAP/samba.schema.at.IBM-DS
@@ -0,0 +1,59 @@
+## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password'EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet' DESC 'Timestamp of the last password update' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange' DESC 'Timestamp of when the user is allowed to update the password' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange' DESC 'Timestamp of when the password will expire' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime' DESC 'Timestamp of last logon' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime' DESC 'Timestamp of last logoff' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime' DESC 'Timestamp of when the user will be logged off automatically' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive' DESC 'Driver letter of home directory mapping' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript' DESC 'Logon script path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath' DESC 'Roaming profile path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations' DESC 'List of user workstations the user is allowed to logon to' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath' DESC 'Home directory UNC path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName' DESC 'Windows NT domain to which the user belongs' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID' DESC 'Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID' DESC 'Primary Group Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType' DESC 'NT Group Type' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid' DESC 'Next NT rid to give our for users' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid' DESC 'Next NT rid to give out for groups' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid to give out for anything' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.41 NAME 'sambaShareName' DESC 'Share Name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.42 NAME 'sambaOptionName' DESC 'Option Name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.43 NAME 'sambaBoolOption' DESC 'A boolean option' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.44 NAME 'sambaIntegerOption' DESC 'An integer option' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.45 NAME 'sambaStringOption' DESC 'A string option' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption' DESC 'A string list option' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' DESC '' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} )
diff --git a/examples/LDAP/samba.schema.oc.IBM-DS b/examples/LDAP/samba.schema.oc.IBM-DS
new file mode 100644
index 00000000000..8f556520de9
--- /dev/null
+++ b/examples/LDAP/samba.schema.oc.IBM-DS
@@ -0,0 +1,19 @@
+## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY DESC 'Samba 3.0 Auxilary SAM Account' MUST ( uid $ sambaSID ) MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial ))
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY DESC 'Samba Group Mapping' MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY ( displayName $ description ))
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL DESC 'Samba Domain Information' MUST ( sambaDomainName $ sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $ sambaAlgorithmicRidBase ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY DESC 'Pool for allocating UNIX uids/gids' MUST ( uidNumber $ gidNumber ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY DESC 'Mapping from a SID to an ID' MUST ( sambaSID ) MAY ( uidNumber $ gidNumber ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL DESC 'Structural Class for a SID' MUST ( sambaSID ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.10 NAME 'sambaConfig' SUP top AUXILIARY DESC 'Samba Configuration Section' MAY ( description ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.11 NAME 'sambaShare' SUP top STRUCTURAL DESC 'Samba Share Section' MUST ( sambaShareName ) MAY ( description ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.1.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURAL DESC 'Samba Configuration Option' MUST ( sambaOptionName ) MAY ( sambaBoolOption $ sambaIntegerOption $ sambaStringOption $ sambaStringListoption $ description ) )
diff --git a/examples/LDAP/smbldap-tools/CONTRIBUTORS b/examples/LDAP/smbldap-tools/CONTRIBUTORS
new file mode 100644
index 00000000000..697f93b7f49
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/CONTRIBUTORS
@@ -0,0 +1,33 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/CONTRIBUTORS,v $
+#
+## Authors and actives contributors to SMBLDAP-TOOLS
+
+Have contributed directly to this tools, or are always in charge of
+some aspects of it developments:
+ . Jrme Tournier <jerome.tournier@IDEALX.com>
+ . Terry Davis <terry@terryd.net>
+ . David Le Corfec <dlc@freesurf.fr>
+ . Olivier Lemaire <olivier.lemaire@IDEALX.com>
+
+Many thanks to contributors for bug report and patches:
+ . Marc Schoechlin <ms@LF.net>
+ load the perl-modules without setting environment-variables or making symlinks
+ . Alexander Bergolth <leo@strike.wu-wien.ac.at>
+ more Net::LDAP support
+ . Gert-Jan Braas <braas@wyldebeast-wunderliebe.com>
+ bug report for 2.2.3 samba.schema
+ . Jody Haynes <Jody.Haynes@isunnetworks.com>
+ originaly passwd.pl
+ . Brad Langhorst <brad@langhorst.com>
+ package relocatability
+ . Mirko Manea <mami@arena.sci.univr.it>
+ originaly useradd.pl
+ . Alain Richard <alain.richard@equation.fr>
+ bug report and Perl tips
+ . Roland Schulz <mail@r2s2.de>
+ bug report for smbldap-passwd
+ . Xavier Boschian <Xavier.Boschian@rtlgroup.net>
+ bug report for smbldap-populate
+ . Christophe DUBREUIL <christophe.dubreuil@laposte.net>
+ Net::LDAP support in smbldap_tools.pm
+# - The End
diff --git a/examples/LDAP/smbldap-tools/COPYING b/examples/LDAP/smbldap-tools/COPYING
new file mode 100644
index 00000000000..32d0e6014a7
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/examples/LDAP/smbldap-tools/ChangeLog b/examples/LDAP/smbldap-tools/ChangeLog
new file mode 100644
index 00000000000..54ba1aed66f
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/ChangeLog
@@ -0,0 +1,89 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/ChangeLog,v $
+# $id: $
+#
+## ChangeLog for SMBLDAP-TOOLS
+
+2003-11-18:
+ . new option '-a' to smbldap-usermod.pl that allow adding the sambaSamAccount
+ objectclass to an existing posixAccount
+2003-11-07:
+ . patch that allow adding user to a group when the group is in a higher level depth
+ then ou=Groups (for example, ou=grp1,ou=Groups,...)
+ . check the unicity of a group when adding/removing a user to this group
+2003-10-28:
+ . new option '-p' in smbldap-groupadd.pl to 'print' the gidNumber
+ of the group to STDOUT. This is needed by samba (see the man page)
+2003-10-19:
+ . new function does_sid_exist that check if samaSID sttribute is already
+ defined for another use or another group
+2003-10-13:
+ . smbldap-populate.pl now also add the group mapping
+2003-10-01:
+ . one can now comment the two directives '$_userSmbHome' and '$_userProfile'
+ if you want to use the smb.conf directives instead ('logon home' and
+ 'logon path' respectively), or if you want to desable roaming profiles
+ . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>: the sambaPrimaryGroupSID
+ of a user is now set to the sambaSID of his primary group
+2003-09-29:
+ . added new option '$_defaultMaxPasswordAge' in smbldap_conf.pm to specifie
+ how long a password is valid
+ . The '-B' option was not always valid: to force a user to change his password:
+ . the attribut sambaPwdLastSet must be != 0
+ . the attribut sambaAcctFlags must not match the 'X' flag
+ . logon script is set (for every one) to the default '_userScript' value if it is defined
+ . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>:
+ gid-sid group mapping to smbldap-groupadd.pl and smbldap-groupmod.pl
+2003-09-19: Patch from Marc Schoechlin <ms@LF.net>
+ . load the perl-modules without setting environment-variables or making symlinks
+2003-09-18: Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>
+ . options "-u", "-g", "-s" and "-c" are now functionnal
+ . the existence of samba account was made on sambaAccount and
+ not sambaSamAccount as it should be for samba3
+ . new function read_user_entry to smbldap_tools.pm that returns
+ a Net::LDAP:Entry object of the user
+ . Use this object to get the dn and user attributes instead of
+ producing an ldif and searching for attributes within that ldif
+2003-09-15:
+ . change machine account creation to not add the sambaSamAccount objectclass.
+ It is now added directly by samba when joigning the domain
+ . new option in smbldap-usermod.pl: '-e' to set an expire date
+ . Start_tls support activated when ldapSSL is set to 1
+ . Net::LDAP support more scripts
+ . bugs correction
+2003-09-02:
+ . sambaPwdLastSet is updated when smbldap-passwd.pl is used
+ . add a function is_group_member to test the existence of a
+ user in a particular group
+ . add a function is_unix_user to test if a particular user exist
+ . Net::LDAP support more scripts
+2003-08-15:
+ . Samba3.0 support
+2003-08-01:
+ . Final version for samba 2.2.8a (cvs tag SAMBA-2-2-8a-FINAL)
+ . OpenLDAP 2.1 support (only one structural objectclass allowed)
+2002-07-24: top and account objectclasses replaced with inetorgperson
+2002-06-03: notes to webmin.idealx.org (idxldapaccounts)
+2002-06-01: release 0.7. tested with 2.2.4
+2002-05-31: fixed smbldap-populate compliance to smbldap_conf
+ cleaned up smbldap_conf to be more readable
+ some more documentation
+ bugfixes on smbldap-passwd and smbldap-populate
+2002-05-16: modified default mode on homes: now 700
+2002-05-13: fixed spec (relocation and reqs)
+2002-03-02: fixed 2.2.3 sambaAccount bug with smbldap-useradd.pl
+ (rid is now mandatory in the sambaAccount objectClass)
+2002-02-14: just modified default populate for Administrator
+2002-02-05: release 0.6. enable/disable user in usermod
+2002-02-04: release 0.5. added smbldap-migrate-groups to migrate NT groups
+ from a net group dump. added samba parameters to smbldap-useradd
+ and smbldap-usermod.
+2002-01-12: added smbldap-migrate-accounts to migrate users/machines
+ accounts from a PWDUMP dump
+2001-12-13: added smbldap-populate to create the initial base
+2001-12-13: initial release 0.1
+2001-12-12: fixed the SPEC file for RedHat
+2001-12-03: cleaned the code and use strict;
+2001-11-20: initial needs (for testing purpose on Samba-2.2.2 an Samba-TNG)
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/FILES b/examples/LDAP/smbldap-tools/FILES
new file mode 100644
index 00000000000..2d2dabd93e9
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/FILES
@@ -0,0 +1,43 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/FILES,v $
+#
+## File listing for SMBLDAP-TOOLS
+
+CONTRIBUTORS : authors and contributors
+COPYING : licence
+FILES : this file listing
+README : introduction and usage
+TODO : feature request and bug report list
+ChangeLog : changelog
+
+Core:
+=-=-=
+smbldap-groupadd.pl : to add a new group
+ (objectclass: posixGroup)
+smbldap-groupdel.pl : to delete a group
+ (objectclass: posixGroup)
+smbldap-groupmod.pl : to modify a group (mostly used to add user to a group)
+ (objectclass: posixGroup)
+smbldap-groupshow.pl : to view a group
+ (objectclass: posixGroup)
+smbldap_conf.pm : global configuration datas
+smbldap_tools.pm : functions
+smbldap-useradd.pl : to add a new user
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-userdel.pl : to delete a user
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-usermod.pl : to modify an user datas
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-usershow.pl : to view an user datas
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-passwd.pl : to sync passwd (Unix and Samba)
+ (a replacement for the system passwd utility)
+smbldap-populate.pl : to add a builtin ldif to initialize your LDAP master for
+ smbldap use, or to add a specified ldif
+smbldap-tools.spec : SPEC file for RedHat RPM package format
+
+Migration:
+=-=-=-=-=-
+smbldap-migrate-accounts.pl : add NT sam entries from pwdump to ldap
+smbldap-migrate-groups.pl : add any LDAP posixGroups from the output of the 'net group' NT command
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/INFRASTRUCTURE b/examples/LDAP/smbldap-tools/INFRASTRUCTURE
new file mode 100644
index 00000000000..8ea07ead44b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/INFRASTRUCTURE
@@ -0,0 +1,93 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/INFRASTRUCTURE,v $
+#
+## Some notes about the architecture
+
+
+Global Architecture for smbdlap-tools
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-tools help you manage users and groups for Unix and Samba,
+using LDAP. They may be used in any context, and are kept relatively
+simplier enought to let you customize them to you needs.
+
+They need the following objectClasses to work:
+ . sambaAccount: from samba.schema for Samba 2.2 branch
+ . posixAccount and posixGroup : from nis.schema
+ . organizationalUnit and dcObject: from core.schema
+
+They will probably use in a near future some additional objectClasses
+to support :
+ . mail features (sendmail/postfix/qmail/courier).
+ . conform to RFC2307 best practices (and so some maps too like merging
+ Netbios computers (sambaAccounts) with ipHosts
+
+For ease of visualization of the LDAP objects by human standards, we
+used a DIT like this one :
+ . dc=IDEALX,dc=org : the company/organization suffix
+ . ou=Users : to store users accounts
+ . ou=Computers : to store computers accounts
+ . ou=Groups : to store system groups
+Of course, you're free to use a different naming scheme and DIT (see
+smbldap_conf.pm).
+
+
+Built in groups initial population
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-populate.pl populate the LDAP directory with some built in groups
+using gidNumber according to Well Know RID of Windows NT4 Srv. In fact, As
+far a Samba 2.2.x is concerned, only the 'Domain Admins' (gidNumber 512) have
+real inpact on the Samba and Windows population. To activate this group as
+the Domain Administrators Group, use the following smb.conf directive (see
+man smb.conf for more):
+
+ domain admin group = " @"Domain Admins" "
+
+However, to make pdb_ldap accept bind without being uid=0, a quick and
+dirty patch must be applied to 2.2.4 (see samba-2.2.4-ldapbindnotuid0.patch).
+This patch is Q&D because the check is there because Samba store admin
+credentials to establish the LDAP connection. The uid == 0 check was to
+ensure that a normal user could not get write access to the LDAP backend.
+A more logical situation should be done for 2.2.5 by checking if the user
+is a member of the domain admin group (reported to Jerremy and Gerald
+2002-05-28).
+
+Other built in groups are really cosmetic ones with Samba 2.2.x. We did not
+removed them because one of these days, we whish to use Samba 3.0 where
+Windows Group Support should be operational.
+
+Why these specific gidNumbers ?
+It's about unix/windows mapping of numerical ids with Samba. Ids below 1024
+are NT special ids. In fact, 512 is the RID (Windows uid/gid) for the
+"Domain Administrators" NT group. The magic number is found in Samba sources
+and possibly other Samba/Windows documentations.
+
+The goal is to have a set of Unix users who are Domain Administrators and can
+modify Samba datas (eg. LDAP content), with commandline tools or within
+Windows via Samba.
+
+Say you want to add a NT4 ws to an NT domain (controlled by a samba/ldap
+server). You give the domain administrator's login and password in the
+appropriate ws settings, then the ws contacts the samba server, which checks
+the credentials and use them as unix user to run the smbldap-tools (if I
+remember). Giving 512 as a RID to a LDAP entry marks it as a domain admin
+for Samba (thus Windows). Using nss_ldap, you also have an account with
+gid 512.
+
+
+Known BUGS and WORKAROUND used
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The 2.2.2 has at least a bug : rid/primaryGroupID are read as hex in LDAP,
+but written as decimal. Fixed in CVS by reading as decimal. By default
+smbldap-useradd.pl writes decimal to LDAP. Use -x to support the odd
+behaviour.
+
+The samba-2.2.4-ldapbindnotuid0.patch is not a perfect solution however
+as the check is there because Samba store admin credentials to establish the
+LDAP connection. The uid == 0 check was to ensure that a normal user could
+not get write access to the LDAP backend. A more logical situation should be
+done for 2.2.5 by checking if the user is a member of the domain admin group
+(reported to Jerremy and Gerald 2002-05-28).
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/INSTALL b/examples/LDAP/smbldap-tools/INSTALL
new file mode 100644
index 00000000000..38221b12433
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/INSTALL
@@ -0,0 +1,28 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/INSTALL,v $
+#
+## How To Install SMBLDAP-TOOLS
+
+Quick & Dirty:
+=-=-=-=-=-=-=-
+ . Copy all those scripts in /usr/local/sbin/
+ . Modify smbldap_conf.pm to match your configuration
+ . If not already done : "smbpasswd -w secret" to set up
+ the ldap admin password in secrets.tdb
+ . Either add /usr/local/sbin in $PERLLIB or run the scripts
+ from this directory, or make a symlink from /usr/local/sbin/*.pm
+ to /usr/lib/perl5/.
+ . to allow a domain admin to add user using "add user script" in smb.conf :
+ chmod 753 smbldap_conf.pm
+ chmod 750 smbldap-useradd.pl
+ chgrp 512 smbldap_conf.pm smbldap-useradd.pl (512 = 0x200 = Domain Admins)
+ Have your admin belong to this group
+ In smb.conf : domain admin group = " @"Domain Admins" "
+
+RedHat RPM:
+=-=-=-=-=-=
+Install smbldap-tools-0.7-1.i386.rpm
+Modify /usr/local/sbin/smbldap_conf.pm to match you configuration
+If not already done : "smbpasswd -w secret" to set up
+the ldap admin password in secrets.tdb
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/Makefile b/examples/LDAP/smbldap-tools/Makefile
new file mode 100644
index 00000000000..783a3571a99
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/Makefile
@@ -0,0 +1,35 @@
+PACKAGE=smbldap-tools
+RELEASE=0.8.2-1
+DESTDIR = $(PACKAGE)-$(RELEASE)
+
+dist: distclean $(DESTDIR).tgz
+
+$(DESTDIR).tgz: .diststamp
+ rm -rf $(DESTDIR)
+ mkdir $(DESTDIR)
+ # copy files
+ cp CONTRIBUTORS $(DESTDIR)
+ cp COPYING $(DESTDIR)
+ cp ChangeLog $(DESTDIR)
+ cp FILES $(DESTDIR)
+ cp INSTALL $(DESTDIR)
+ cp README $(DESTDIR)
+ cp TODO $(DESTDIR)
+ cp INFRASTRUCTURE $(DESTDIR)
+ tar cf mkntpwd.tar mkntpwd
+ gzip mkntpwd.tar
+ cp mkntpwd.tar.gz $(DESTDIR)
+ cp smbldap-*.pl $(DESTDIR)
+ cp smbldap_*.pm $(DESTDIR)
+ # copy directories
+ tar cvzf $(DESTDIR).tgz $(DESTDIR)
+ rm -rf $(DESTDIR)
+ touch .diststamp
+
+.diststamp:
+
+distclean:
+ rm -f *~
+ rm -f $(DESTDIR).tgz
+ rm -f mkntpwd.tar.gz
+
diff --git a/examples/LDAP/smbldap-tools/README b/examples/LDAP/smbldap-tools/README
new file mode 100644
index 00000000000..c6133e19692
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/README
@@ -0,0 +1,87 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/README,v $
+#
+
+Latest version may be found at http://samba.idealx.org/
+
+
+What those tools are for?
+=-=-=-=-=-=-=-=-=-=-=-=-=
+
+A collection of scripts, over user{add,del,mod} and group{add,del,mod}
+system tools to manipulate users and groups stored in LDAP directory,
+for DEN system like SAMBA-LDAP and pam/nss_ldap systems.
+
+Additionnaly, some scripts are designed to ease your migration from
+a Windows NT 4.0 PDC Server to a Samba-LDAP PDC Server (Killer?;-):
+smbldap-populate, smbldap-migrate-groups, smbldap-migrate-accounts.
+
+They are currently used with Samba 2.2.4, therefore you may (will) have
+to make some fixes for Samba TNG and Samba 3.0. Hint: contribs welcome :)
+
+In the future, some other function may come (like backup and restore,
+Novell migration tools, samba system activity report, dealing with
+mail functions, compliance to RFC2307...): consult TODO.
+
+
+What do SMBLDAP-TOOLS provide?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Those tools provide the following functions :
+ . populate LDAP database with a basic LDIF
+ . add a user or group
+ . delete a user or group
+ . modify all users or groups data (all attributes types stored in
+ posixAccount and sambaAccount object class)
+Taking care of :
+ . staying compatible with all standard system tools options
+ (user/group{add,del,mod})
+ . be extensible for future developments
+ (manipulation of shadow account options, for example)
+ . error management, in the way system tools do
+Constraints :
+ . usage of PERL (portability)
+ . all options must be placed in an external configuration file
+ . english localization
+
+The current release uses the "mkntpwd" program, in mkntpwd.tar.gz
+in the current directory. It comes from
+http://www.demog.berkeley.edu/~aperrin/tips/src/mkntpwd.tar.gz
+It allows to not use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm)
+
+What do SMBLDAP-TOOLS deliver?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+Contents :
+ . scripts (see FILES)
+ . user documentation in pod format, included in the sources
+ (or just use the -? option)
+
+These tools aim at delivering the same functionality as the corresponding
+system tools. However they may not be all implemented yet.
+Current limitations :
+ . no shadow support
+ . cannot change uid with usermod
+ . no UTF-8 support (thus ASCII-7 only)
+
+
+How to generate documentation?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Just issue the following command:
+ perldoc name_of_script.pl (ex: perldoc smbldap-useradd.pl)
+
+Where can I find the latest release of those scripts?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Just fire any web browser to http://samba.IDEALX.org/
+and/or contact samba@IDEALX.org
+
+Additionnaly, you will find an useful Webmin module
+at http://webmin.IDEALX.org/ if interested in a graphical
+user interface to manager user and groups accounts via Webmin
+for your Samba+LDAP PDC.
+
+Let us know if these tools helped you, or if we should enhance
+them with some functions you want them to support.
+
+Sincerly,
+ LEM
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/TODO b/examples/LDAP/smbldap-tools/TODO
new file mode 100644
index 00000000000..8fdc2a55994
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/TODO
@@ -0,0 +1,28 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/TODO,v $
+#
+## TODO list - First In, Last in the list...
+## (BF: Bug Report / FR: Feature Request)
+
+
+FR * add 'LDAP port' for both slave and master LDAP server in smbldap_conf.pm
+FR * use RFC2307 best practices (Luke, next time you visit Paris, have a
+ beer at IDEALX'cantina ;-)
+FR * add mail (sendmail/postfix/qmail/courier) support
+FR * bugfix, really : allow non-root users to change passwd
+ (currently the config must be unreadable because of bindpasswd)
+FR * make smbldap-tools to use system configuration files
+ (/etc/login.defs and /etc/ldap.conf for example)
+FR * rewrite smbldap-tools using perl-ldap. In fact, this 0.x
+ release use ldap system tools (ldapadd,ldapdelete,ldapmodify)
+FR * add shadowAccounts manipulation support
+FR * internationalize the SMBLDAP-TOOLS
+FR * add smbldap-sar : Samba System Activity Report to help
+ supporting Samba/LDAP sysadmin activity
+FR * add smbldap-backup/smbldap-restore to backup and restore
+ a SAM (in LDAP) database. No sorcery, just LDIF, but usefull
+ for non-LDAP gurus
+FR * adding migration tools from migration from W2K and NetWare to Samba-LDAP
+FR * adapt smbldap-tools to use Samba 3.0
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/cgi/README b/examples/LDAP/smbldap-tools/cgi/README
new file mode 100644
index 00000000000..7a4fc0c02b9
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/cgi/README
@@ -0,0 +1,27 @@
+Description:
+ A cgi to allow users to change their passwords via a web browser.
+
+Installation:
+ Drop this into a cgi-enabled directory on your webserver.
+ Edit it and change the CONFIGURATION section to suit your environment.
+ READ THE NOTES SECTION.
+
+Notes: This script will run as the user who runs your web server. So, to invoke the smbpasswd call, you must implement sudo.
+ Example of /etc/sudoers:
+
+ # Host alias specification
+ # User alias specification
+ User_Alias PASSWD = apache
+ # Cmnd alias specification
+ Cmnd_Alias PASSWD = /usr/bin/smbpasswd
+ # User privilege specification
+ root ALL=(ALL) ALL
+ PASSWD ALL= NOPASSWD: PASSWD
+
+ This concept is probably very insecure and broken. That is why this is a 0.1 release. :)
+
+
+Feel free to drop me suggestions. I am a perl learner so I am always open to suggestions.
+
+Terry Davis
+tdavis@approbation.org
diff --git a/examples/LDAP/smbldap-tools/cgi/ldappass.cgi b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi
new file mode 100755
index 00000000000..4a5ecb8f3a9
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi
@@ -0,0 +1,202 @@
+#!/usr/bin/perl
+
+################################################################################
+#
+# changepass.pl - A program to allow users to change their passwords
+# via a web browser.
+# Terry Davis
+#
+# URLs
+# Net::LDAP - http://
+# usermod and this file - http://www.cloudamster.com/cloudmaster/projects
+#
+# Release History:
+# Version 0.1 - initial write
+#
+# ToDo:
+# ... the ToDo section is on the ToDo list...
+#
+# Limitations:
+# The password cannot contain single and double quotes.....welcome to quoting hell....
+#
+# Notes:
+# This code is largely based on work done by Danny Sauer - http://www.cloudamster.com/cloudmaster/projects
+# His work is not licensed and is marked as 'freely distributable'.
+# Thank you to Danny for his hard work on the initial work.
+#
+################################################################################
+
+use CGI qw(:standard);
+use Net::LDAP;
+
+# CONFIGURATION SECTION
+$masterLDAP = "ldap.idealx.org";
+$basedn = "dc=IDEALX,dc=org";
+$masterPw = "";
+$masterDN = "cn=manager,$basedn";
+$ldap_path = "/usr/bin";
+$ldap_opts = "-x";
+$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$usersdn = "ou=Users,$basedn";
+# END CONFIGURATION
+
+
+
+# DONT EDIT ANYTHING BELOW THIS LINE
+$logtag = "Login:";
+$passtag = "Current password:";
+$npasstag1 = "New password:";
+$npasstag2 = "Retype new pasword:";
+$error = "";
+$color = "<FONT color='red'>";
+$stopcolor = "</FONT>";
+
+if(param()){
+ nologin() unless ($username = param('login'));
+ nopass() unless ($oldpass = param('oldpass'));
+ nonewpass(1) unless ($newpass1 = param('newpass'));
+ nonewpass(2) unless ($newpass2 = param('newpass2'));
+ verifyuser($username) or die "bad user";
+ verifypass($username, $oldpass) or die "bad pass";
+ testnewpass($newpass1, $newpass2) or die "bad new pass";
+ changepass($username, $newpass1) or die "couldn't change pass";
+ printsuccess();
+}else{
+ printpage();
+}
+exit(0);
+
+sub verifyuser{
+ local $user = shift;
+ $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+ $ldap->bind();
+ if (0 < $ldap->search(base => $basedn, filter => "(uid=$user)")->count){
+ return 1;
+ }
+ $logtag = $color . $logtag . $color;
+ $error = "No such user";
+ printpage();
+ return 0;
+}
+
+sub verifypass{
+ $uid = shift;
+ $pass = shift;
+ $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+ $binddn = "uid=$uid,ou=People,$basedn";
+ return 1 if($ldap->bind( $binddn, password => $pass)->code == 0);
+ if($ldap->bind()){
+ $passtag = $color . $passtag . $color;
+ $error = "Incorrect password";
+ printpage();
+ return 0;
+ }else{
+ print header, start_html(-title=>"LDAP dead");
+ print h2("<CENTER>The LDAP server is temporarily unavailable."),
+ p,"Please try again later</CENTER>";
+ return 0;
+ }die "Something (or someone) is defective, contact your friendly Systems Administrator";
+}
+
+sub testnewpass{
+ $p1 = shift; $p2 = shift;
+ if ($p1 ne $p2){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords don't match ($p1 vs $p2)";
+ printpage();
+ return 0;
+ }
+ if ($p1 =~ /"/ ){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords cannot contain double quotes. Sorry";
+ printpage();
+ return 0;
+ }
+ if ($p1 =~ /'/ ){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords cannot contain single quotes. Sorry";
+ printpage();
+ return 0;
+ }
+ return 1;
+}
+
+sub changepass{
+ local $user = shift;
+ local $newpass = shift;
+ local $dn = "uid=$user,$usersdn";
+ system "$ldappasswd $dn -s '$newpass' > /dev/null";
+ `/usr/bin/sudo /usr/bin/smbpasswd $user "$newpass"`;
+ exit(1);
+}
+
+sub nologin{
+ $logtag = $color . $logtag . $color;
+ $error = "You need to enter a Login Name";
+ printpage();
+ exit(1);
+}
+
+sub nopass{
+ $passtag = $color . $passtag . $color;
+ $error = "Please enter your old password";
+ printpage();
+ exit(1);
+}
+
+sub nonewpass{
+ $f=shift;
+ $npasstag1 = $color . $npasstag1 . $color if($f==1);
+ $npasstag2 = $color . $npasstag2 . $color if($f==2);
+ $error = "You need to enter your new password";
+ $error .= " twice" if($f==2);
+ printpage();
+ exit(1);
+}
+
+sub printpage{
+ print header,
+ start_html(-title=> "Password Change Page",
+ -author=> 'tdavis@birddog.com',
+ -BGCOLOR=> 'WHITE'),
+ h3('Password Change Page'),
+ startform(-method=>'POST'),
+ "<TABLE BORDER=0 WIDTH=50%>",
+ "<font size=2>",
+ "<TR><TD>",
+ $logtag,
+ "</TD><TD>",
+ textfield(-name=>'login', -default=>$login,
+ -size=>15, -maxlength=>20),
+ "</TD><TR><TD>",
+ $passtag,
+ "</TD><TD>",
+ password_field(-name=>'oldpass', -size=>15, -maxlength=>25),
+ "</TD><TR><TD>",
+ $npasstag1,
+ "</TD><TD>",
+ password_field(-name=>'newpass', -size=>15, -maxlength=>25),
+ "</TD><TR><TD>",
+ $npasstag2,
+ "</TD><TD>",
+ password_field(-name=>'newpass2', -size=>15, -maxlength=>25),
+ "</TD><TR><TD></TD><TD>",
+ submit(-name=>"change"),reset(),
+ "</TD></TR></TABLE>",
+ "</font>",
+ endform(),
+ "<FONT color='red'>$error</FONT>",
+ end_html;
+}
+
+sub printsuccess(){
+ print header,
+ start_html(-title=> "Success",
+ -BGCOLOR=> 'WHITE'),
+ h1("Password Succesfully Changed"),
+ "<br>",
+ end_html;
+}
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/Makefile b/examples/LDAP/smbldap-tools/mkntpwd/Makefile
new file mode 100644
index 00000000000..23c9d471b0a
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/Makefile
@@ -0,0 +1,62 @@
+# Makefile for l0phtcrack - mudge@l0pht.com 11/1/96
+
+# C compiler
+#CC=cc
+CC=gcc
+
+# Uncomment the following to add symbols to the code for debugging
+#DEBUG=-g -Wall -D_DEBUG
+#DEBUG=-D_DEBUG
+
+# Optimization for the compiler
+#OPTIMIZE=
+OPTIMIZE=-O2
+
+# Choose your architecture
+# note that if you are on a big-endian machine like SUN's
+# I haven't tweaked the mem-cmp's and md4 stuff to be in
+# the correct order yet. You're on your own right now.
+#
+# FreeBSD
+ARCH=-DMPU8086
+STATIC=
+XLIBS=
+#
+# SUNOS
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# ULTRA_SPARC w/ native compiler
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-fast -xO4 -xdepend -xchip=ultra -xarch=v8plus
+#XLIBS=
+#
+# SunOS/Solaris w/gcc
+#ARCH=-DBIGENDIAN -DTEST
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# NeXTStep 3.2
+#CC=cc
+#ARCH=-DBIGENDIAN
+#STATIC=-Bstatic
+#OPTIMIZE=
+#XLIBS=
+
+CFLAGS= $(DEBUG) $(OPTIMIZE) $(ARCH) $(VISUAL) $(PERMUTE) $(STATIC)
+
+OBJS = getopt.o md4.o mkntpwd.o smbdes.o
+
+mkntpwd: $(OBJS)
+ $(CC) $(CFLAGS) $(XLIBS) -o mkntpwd $(OBJS)
+
+clean:
+ rm -f core *.o mkntpwd
+
+install: mkntpwd
+ install -m 555 mkntpwd $(PREFIX)/sbin/mkntpwd
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.c b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c
new file mode 100644
index 00000000000..5b2e7a9100b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c
@@ -0,0 +1,756 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+ Free Software Foundation, Inc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <string.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (optstring)
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ optstring = _getopt_initialize (optstring);
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0; /* set to zero by Anton */
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp(p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int)(nameend - nextchar) == (unsigned int)strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+ else
+ fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.h b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h
new file mode 100644
index 00000000000..f3696d955dc
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/md4.c b/examples/LDAP/smbldap-tools/mkntpwd/md4.c
new file mode 100644
index 00000000000..1c9c2e6ecd5
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/md4.c
@@ -0,0 +1,171 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ a implementation of MD4 designed for use in the SMB authentication protocol
+ Copyright (C) Andrew Tridgell 1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTE: This code makes no attempt to be fast!
+
+ It assumes that a int is at least 32 bits long
+*/
+
+typedef unsigned int uint32;
+
+static uint32 A, B, C, D;
+
+static uint32 F(uint32 X, uint32 Y, uint32 Z)
+{
+ return (X&Y) | ((~X)&Z);
+}
+
+static uint32 G(uint32 X, uint32 Y, uint32 Z)
+{
+ return (X&Y) | (X&Z) | (Y&Z);
+}
+
+static uint32 H(uint32 X, uint32 Y, uint32 Z)
+{
+ return X^Y^Z;
+}
+
+static uint32 lshift(uint32 x, int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
+}
+
+#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void mdfour64(uint32 *M)
+{
+ int j;
+ uint32 AA, BB, CC, DD;
+ uint32 X[16];
+
+ for (j=0;j<16;j++)
+ X[j] = M[j];
+
+ AA = A; BB = B; CC = C; DD = D;
+
+ ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
+ ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
+ ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
+ ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
+ ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
+ ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
+ ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
+ ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
+
+ ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
+ ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
+ ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
+ ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
+ ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
+ ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
+ ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
+ ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
+
+ ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
+ ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
+ ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
+ ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
+ ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
+ ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
+ ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
+ ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
+
+ A += AA; B += BB; C += CC; D += DD;
+
+ A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
+ C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
+
+ for (j=0;j<16;j++)
+ X[j] = 0;
+}
+
+static void copy64(uint32 *M, unsigned char *in)
+{
+ int i;
+
+ for (i=0;i<16;i++)
+ M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
+ (in[i*4+1]<<8) | (in[i*4+0]<<0);
+}
+
+static void copy4(unsigned char *out,uint32 x)
+{
+ out[0] = x&0xFF;
+ out[1] = (x>>8)&0xFF;
+ out[2] = (x>>16)&0xFF;
+ out[3] = (x>>24)&0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void mdfour(unsigned char *out, unsigned char *in, int n)
+{
+ unsigned char buf[128];
+ uint32 M[16];
+ uint32 b = n * 8;
+ int i;
+
+ A = 0x67452301;
+ B = 0xefcdab89;
+ C = 0x98badcfe;
+ D = 0x10325476;
+
+ while (n > 64) {
+ copy64(M, in);
+ mdfour64(M);
+ in += 64;
+ n -= 64;
+ }
+
+ for (i=0;i<128;i++)
+ buf[i] = 0;
+ memcpy(buf, in, n);
+ buf[n] = 0x80;
+
+ if (n <= 55) {
+ copy4(buf+56, b);
+ copy64(M, buf);
+ mdfour64(M);
+ } else {
+ copy4(buf+120, b);
+ copy64(M, buf);
+ mdfour64(M);
+ copy64(M, buf+64);
+ mdfour64(M);
+ }
+
+ for (i=0;i<128;i++)
+ buf[i] = 0;
+ copy64(M, buf);
+
+ copy4(out, A);
+ copy4(out+4, B);
+ copy4(out+8, C);
+ copy4(out+12, D);
+
+ A = B = C = D = 0;
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c
new file mode 100644
index 00000000000..0c7d61e1341
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c
@@ -0,0 +1,253 @@
+/*
+ This code is based on work from
+ L0phtcrack 1.5 06.02.97 mudge@l0pht.com
+
+ The code also contains sources from:
+ . routines from the samba code source
+ md4.c smbdes.c
+
+ Anton Roeckseisen (anton@genua.de)
+
+*/
+
+/*
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "mkntpwd.h"
+
+void str_to_key(unsigned char *,unsigned char *);
+void usage(char *);
+int PutUniCode(char *dst,char *src);
+void printlanhash(char *tmp);
+void mdfour(unsigned char *out, unsigned char *in, int n);
+void E_P16(unsigned char *p14,unsigned char *p16);
+
+
+void main(int argc, char **argv) {
+ extern char *optarg;
+ int c;
+
+ int printlan = 0;
+ char lanpwd[LMPASSWDLEN+1];
+ int printnt = 0;
+ char inputfile[FILENAMEBUFFER+1] = "";
+ FILE* InputFilePtr;
+ int just_pwd = 0;
+ int i;
+ char hashout[17];
+
+ char ntpasswd[NTPASSWDLEN+1];
+ char *hold;
+ unsigned char *p16;
+ int uni_len;
+ char passwd[NTPASSWDLEN+1];
+
+ if (argc==1)
+ usage(argv[0]);
+
+ if (argc==2)
+ just_pwd=1;
+ else
+ just_pwd=0;
+
+ lanpwd[0] = '\0';
+ ntpasswd[0] = '\0';
+
+ while ( (c = getopt(argc, argv, "L:N:f:")) != EOF){
+ switch(c) {
+ case 'L':
+ printlan++;
+ strncpy(lanpwd,optarg,LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ break;
+ case 'N':
+ printnt++;
+ strncpy(passwd,optarg,NTPASSWDLEN);
+ passwd[NTPASSWDLEN]='\0';
+ break;
+ case 'f':
+ strncpy(inputfile,optarg,FILENAMEBUFFER);
+ inputfile[FILENAMEBUFFER]='\0';
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ /* Get password from file or STDIN */
+ if (inputfile[0]!='\0') {
+
+ just_pwd=0; /* make sure no shit is happening... */
+
+ /* get NT-password (longer) */
+ if (strcmp(inputfile,"-")==0) {
+ fgets(passwd,NTPASSWDLEN,stdin);
+ } else {
+ if ((InputFilePtr=fopen(inputfile,"r")) == NULL)
+ fprintf(stderr,"Couldn't open passwordfile: %s",inputfile) ;
+ fgets(passwd,NTPASSWDLEN,InputFilePtr);
+ fclose(InputFilePtr);
+ }
+ while (strlen(passwd)>0 && passwd[strlen(passwd)-1]=='\n')
+ passwd[strlen(passwd)-1]='\0';
+
+ /* create LANMAN-password (shorter) */
+ strncpy(lanpwd,passwd,LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ printlan++;
+ printnt++;
+
+ }
+
+
+ /* Assume the one and only Arg is the new password! */
+
+ if (argc>1 && just_pwd==1) {
+ strncpy(lanpwd,argv[1],LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ printlan++;
+
+ strncpy(passwd,argv[1],NTPASSWDLEN);
+ passwd[NTPASSWDLEN]='\0';
+ printnt++;
+ }
+
+ if (printlan >0) {
+ memset(hashout,'\0',17);
+ E_P16((uchar *)lanpwd,hashout);
+ printlanhash(hashout);
+ }
+
+ if (printnt >0) {
+
+ if (printlan>0) printf(":");
+
+ memset(ntpasswd, '\0', sizeof(ntpasswd));
+
+ if (passwd[strlen(passwd)-1] == '\n') /* strip the \n - this
+ is done in LowerString for the case sensitive
+ check */
+ passwd[strlen(passwd)-1] = '\0';
+
+ hold = (char *)malloc(NTPASSWDLEN * 2); /* grab space for
+ unicode */
+ if (hold == NULL){
+ fprintf(stderr, "out of memory...crackntdialog hold\n");
+ exit(1);
+ }
+
+ uni_len = PutUniCode(hold, passwd); /* convert to
+ unicode and return correct
+ unicode length for md4 */
+
+ p16 = (unsigned char*)malloc(17); /* grab space for md4 hash */
+ if (p16 == NULL){
+ fprintf(stderr, "out of memory...crackntdialect p16\n");
+ exit(1);
+ }
+
+ memset(p16,'\0',17);
+ mdfour(p16,hold, uni_len);
+
+ printlanhash(p16);
+
+ free(p16);
+ free(hold);
+ }
+
+ printf("\n");
+
+ exit(0);
+
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+void usage(char *progname){
+ char *p;
+
+ p = strrchr(progname, '\\');
+ if (p == NULL)
+ p = progname;
+ else
+ p++;
+
+ fprintf(stderr, "Usage: %s [-L lanmgrpwd] [-N ntpasswd]\n",p);
+ fprintf(stderr, " %s password\n",p);
+ fprintf(stderr, " %s -f [-] [filename]\n\n",p);
+ fprintf(stderr, " -L lanmgrpasswd LanManager cleartextpwd <= 14 chars\n");
+ fprintf(stderr, " -N ntpasswd NT cleartextpwd <=128 chars (usually <=14)\n\n");
+ fprintf(stderr, " with both options present the encrypted LanManager-Pwd is \n");
+ fprintf(stderr, " printed first, followed by a ':' and the encrypted NT-Pwd.\n\n");
+ fprintf(stderr, " The second usage behaves like %s -L pwd -N pwd\n\n",p);
+ fprintf(stderr, " The third usage reads the password from STDIN or a File. Printout\n");
+ fprintf(stderr, " is the same as second.\n\n");
+ fprintf(stderr, "anton@genua.de\n\n");
+ exit(1);
+}
+
+
+/*******************************************************************
+write a string in unicoode format
+********************************************************************/
+int PutUniCode(char *dst,char *src)
+{
+ int ret = 0;
+ while (*src) {
+ dst[ret++] = src[0];
+ dst[ret++] = 0;
+ src++;
+ }
+ dst[ret++]=0;
+ dst[ret++]=0;
+ return(ret-2); /* the way they do the md4 hash they don't represent
+ the last null. ie 'A' becomes just 0x41 0x00 - not
+ 0x41 0x00 0x00 0x00 */
+}
+
+/*
+ print binary buffer as hex-string
+*/
+void printlanhash(char *tmp) {
+
+ int i;
+ unsigned char c;
+ char outbuffer[33];
+
+
+ /* build string from binary hash */
+ for(i=0;i<16;i++) {
+ c=tmp[i];
+ sprintf(outbuffer+2*i,"%x",(c>>4) & 0x0f);
+ sprintf(outbuffer+2*i+1,"%x",c & 0x0f);
+ }
+
+ /* convert to uppercase */
+ for(i=0;i<32;i++)
+ outbuffer[i] = toupper(outbuffer[i]);
+ outbuffer[32]='\0';
+
+ /* print out hex-string */
+ printf("%s",outbuffer);
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h
new file mode 100644
index 00000000000..9a020b8d286
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h
@@ -0,0 +1,17 @@
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+typedef short int16;
+typedef int int32;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned char uchar;
+
+#define MAX_STRING 255
+#define MAX_WORD 128
+#define LMPASSWDLEN 14
+#define NTPASSWDLEN 128
+#define FILENAMEBUFFER 128
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c
new file mode 100644
index 00000000000..e4f8280f9bc
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c
@@ -0,0 +1,337 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+
+ a partial implementation of DES designed for use in the
+ SMB authentication protocol
+
+ Copyright (C) Andrew Tridgell 1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTES:
+
+ This code makes no attempt to be fast! In fact, it is a very
+ slow implementation
+
+ This code is NOT a complete DES implementation. It implements only
+ the minimum necessary for SMB authentication, as used by all SMB
+ products (including every copy of Microsoft Windows95 ever sold)
+
+ In particular, it can only do a unchained forward DES pass. This
+ means it is not possible to use this code for encryption/decryption
+ of data, instead it is only useful as a "hash" algorithm.
+
+ There is no entry point into this code that allows normal DES operation.
+
+ I believe this means that this code does not come under ITAR
+ regulations but this is NOT a legal opinion. If you are concerned
+ about the applicability of ITAR regulations to this code then you
+ should confirm it for yourself (and maybe let me know if you come
+ up with a different answer to the one above)
+*/
+
+
+
+static int perm1[56] = {57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4};
+
+static int perm2[48] = {14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32};
+
+static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7};
+
+static int perm4[48] = { 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1};
+
+static int perm5[32] = { 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25};
+
+
+static int perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25};
+
+
+static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+
+static int sbox[8][4][16] = {
+ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
+
+ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
+
+ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
+
+ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
+
+ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
+
+ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
+
+ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
+
+ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
+
+static void permute(char *out, char *in, int *p, int n)
+{
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = in[p[i]-1];
+}
+
+static void lshift(char *d, int count, int n)
+{
+ char out[64];
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = d[(i+count)%n];
+ for (i=0;i<n;i++)
+ d[i] = out[i];
+}
+
+static void concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+ while (l1--)
+ *out++ = *in1++;
+ while (l2--)
+ *out++ = *in2++;
+}
+
+static void xor(char *out, char *in1, char *in2, int n)
+{
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = in1[i] ^ in2[i];
+}
+
+static void dohash(char *out, char *in, char *key)
+{
+ int i, j, k;
+ char pk1[56];
+ char c[28];
+ char d[28];
+ char cd[56];
+ char ki[16][48];
+ char pd1[64];
+ char l[32], r[32];
+ char rl[64];
+
+ permute(pk1, key, perm1, 56);
+
+ for (i=0;i<28;i++)
+ c[i] = pk1[i];
+ for (i=0;i<28;i++)
+ d[i] = pk1[i+28];
+
+ for (i=0;i<16;i++) {
+ lshift(c, sc[i], 28);
+ lshift(d, sc[i], 28);
+
+ concat(cd, c, d, 28, 28);
+ permute(ki[i], cd, perm2, 48);
+ }
+
+ permute(pd1, in, perm3, 64);
+
+ for (j=0;j<32;j++) {
+ l[j] = pd1[j];
+ r[j] = pd1[j+32];
+ }
+
+ for (i=0;i<16;i++) {
+ char er[48];
+ char erk[48];
+ char b[8][6];
+ char cb[32];
+ char pcb[32];
+ char r2[32];
+
+ permute(er, r, perm4, 48);
+
+ xor(erk, er, ki[i], 48);
+
+ for (j=0;j<8;j++)
+ for (k=0;k<6;k++)
+ b[j][k] = erk[j*6 + k];
+
+ for (j=0;j<8;j++) {
+ int m, n;
+ m = (b[j][0]<<1) | b[j][5];
+
+ n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
+
+ for (k=0;k<4;k++)
+ b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
+ }
+
+ for (j=0;j<8;j++)
+ for (k=0;k<4;k++)
+ cb[j*4+k] = b[j][k];
+ permute(pcb, cb, perm5, 32);
+
+ xor(r2, l, pcb, 32);
+
+ for (j=0;j<32;j++)
+ l[j] = r[j];
+
+ for (j=0;j<32;j++)
+ r[j] = r2[j];
+ }
+
+ concat(rl, r, l, 32, 32);
+
+ permute(out, rl, perm6, 64);
+}
+
+static void str_to_key(unsigned char *str,unsigned char *key)
+{
+ int i;
+
+ key[0] = str[0]>>1;
+ key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
+ key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
+ key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
+ key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
+ key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
+ key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
+ key[7] = str[6]&0x7F;
+ for (i=0;i<8;i++) {
+ key[i] = (key[i]<<1);
+ }
+}
+
+
+static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+ int i;
+ char outb[64];
+ char inb[64];
+ char keyb[64];
+ unsigned char key2[8];
+
+ str_to_key(key, key2);
+
+ for (i=0;i<64;i++) {
+ inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+ keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+ outb[i] = 0;
+ }
+
+ dohash(outb, inb, keyb);
+
+ for (i=0;i<8;i++) {
+ out[i] = 0;
+ }
+
+ for (i=0;i<64;i++) {
+ if (outb[i])
+ out[i/8] |= (1<<(7-(i%8)));
+ }
+}
+
+void E_P16(unsigned char *p14,unsigned char *p16)
+{
+ unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+ smbhash(p16, sp8, p14);
+ smbhash(p16+8, sp8, p14+7);
+}
+
+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+ smbhash(p24, c8, p21);
+ smbhash(p24+8, c8, p21+7);
+ smbhash(p24+16, c8, p21+14);
+}
+
+void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+ unsigned char buf[8];
+
+ smbhash(buf, in, key);
+ smbhash(out, buf, key+9);
+}
+
+void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+ unsigned char buf[8];
+ static unsigned char key2[8];
+
+ smbhash(buf, in, key);
+ key2[0] = key[7];
+ smbhash(out, buf, key2);
+}
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupadd.pl b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl
new file mode 100755
index 00000000000..e242d6e223f
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-groupadd : group (posix) add
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('ag:or:s:t:p?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-agorst?] groupname\n";
+ print " -a add automatic group mapping entry\n";
+ print " -g gid\n";
+ print " -o gid is not unique\n";
+ print " -r group-rid\n";
+ print " -s group-sid\n";
+ print " -t group-type\n";
+ print " -p print the gidNumber to stdout\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $_groupName = $ARGV[0];
+
+if (defined(get_group_dn($_groupName))) {
+ warn "$0: group $_groupName exists\n";
+ exit (6);
+}
+
+my $_groupGidNumber = $Options{'g'};
+if (! defined ($_groupGidNumber = group_add($_groupName, $_groupGidNumber, $Options{'o'}))) {
+ warn "$0: error adding group $_groupName\n";
+ exit (6);
+}
+
+my $group_sid;
+my $tmp;
+if ($tmp= $Options{'s'}) {
+ if ($tmp =~ /^S-(?:\d+-)+\d+$/) {
+ $group_sid = $tmp;
+ } else {
+ warn "$0: illegal group-rid $tmp\n";
+ exit(7);
+ }
+} elsif ($Options{'r'} || $Options{'a'}) {
+ my $group_rid;
+ if ($tmp= $Options{'r'}) {
+ if ($tmp =~ /^\d+$/) {
+ $group_rid = $tmp;
+ } else {
+ warn "$0: illegal group-rid $tmp\n";
+ exit(7);
+ }
+ } else {
+ # algorithmic mapping
+ $group_rid = 2*$_groupGidNumber+1001;
+ }
+ $group_sid = $SID.'-'.$group_rid;
+}
+
+if ($Options{'r'} || $Options{'a'} || $Options{'s'}) {
+ # let's test if this SID already exist
+ my $test_exist_sid=does_sid_exist($group_sid,$groupsdn);
+ if ($test_exist_sid->count == 1) {
+ warn "Group SID already owned by\n";
+ # there should not exist more than one entry, but ...
+ foreach my $entry ($test_exist_sid->all_entries) {
+ my $dn= $entry->dn;
+ chomp($dn);
+ warn "$dn\n";
+ }
+ exit(7);
+ }
+}
+
+if ($group_sid) {
+ my $group_type;
+ my $tmp;
+ if ($tmp= $Options{'t'}) {
+ unless (defined($group_type = &group_type_by_name($tmp))) {
+ warn "$0: unknown group type $tmp\n";
+ exit(8);
+ }
+ } else {
+ $group_type = group_type_by_name('domain');
+ }
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ( "cn=$_groupName,$groupsdn",
+ add => {
+ 'objectClass' => 'sambaGroupMapping',
+ 'sambaSID' => $group_sid,
+ 'sambaGroupType' => $group_type
+ }
+ );
+ $modify->code && warn "failed to delete entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+}
+
+if ($Options{'p'}) {
+ print STDOUT "$_groupGidNumber";
+}
+exit(0);
+
+########################################
+
+=head1 NAME
+
+ smbldap-groupadd.pl - Create a new group
+
+=head1 SYNOPSIS
+
+ smbldap-groupadd.pl [-g gid [-o]] group
+
+=head1 DESCRIPTION
+ The smbldap-groupadd.pl command creates a new group account using
+ the values specified on the command line and the default values
+ from the system. The new group will be entered into the system
+ files as needed. The options which apply to the groupadd command are
+
+ -g gid The numerical value of the group's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. The default is to use the smallest ID value greater
+ than 1000 and greater than every other group.
+
+=head1 SEE ALSO
+
+ groupadd(1)
+
+=cut
+
+#'
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupdel.pl b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl
new file mode 100755
index 00000000000..4f6839ebe59
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl
@@ -0,0 +1,93 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-groupdel : group (posix) deletion
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 groupname\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $_groupName = $ARGV[0];
+
+my $dn_line;
+if (!defined($dn_line = get_group_dn($_groupName))) {
+ print "$0: group $_groupName doesn't exist\n";
+ exit (6);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+group_del($dn);
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+#if (defined($dn_line = get_group_dn($_groupName))) {
+# print "$0: failed to delete group\n";
+# exit (7);
+#}
+
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-groupdel.pl - Delete a group
+
+=head1 SYNOPSIS
+
+ smbldap-groupdel.pl group
+
+=head1 DESCRIPTION
+
+ The smbldap-groupdel.pl command modifies the system account files,
+ deleting all entries that refer to group. The named group must exist.
+
+ You must manually check all filesystems to insure that no files remain
+ with the named group as the file group ID.
+
+=head1 SEE ALSO
+
+ groupdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupmod.pl b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl
new file mode 100755
index 00000000000..3f9741e0152
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl
@@ -0,0 +1,283 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-groupmod : group (posix) modification
+
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('ag:n:m:or:s:t:x:?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-a] [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] [-r rid] [-s sid] [-t type] groupname\n";
+ print " -a add automatic group mapping entry\n";
+ print " -g new gid\n";
+ print " -o gid is not unique\n";
+ print " -n new group name\n";
+ print " -m add members (comma delimited)\n";
+ print " -r group-rid\n";
+ print " -s group-sid\n";
+ print " -t group-type\n";
+ print " -x delete members (comma delimted)\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $groupName = $ARGV[0];
+my $group_entry;
+
+if (! ($group_entry = read_group_entry($groupName))) {
+ print "$0: group $groupName doesn't exist\n";
+ exit (6);
+}
+
+my $newname = $Options{'n'};
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+my $gid = getgrnam($groupName);
+unless (defined ($gid)) {
+ print "$0: group $groupName not found!\n";
+ exit(6);
+}
+
+my $tmp;
+if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
+ if (!defined($Options{'o'})) {
+ if (defined(getgrgid($tmp))) {
+ print "$0: gid $tmp exists\n";
+ exit (6);
+ }
+ }
+ if (!($gid == $tmp)) {
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+ changes => [
+ replace => [gidNumber => $tmp]
+ ]
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+ }
+}
+
+
+if (defined($newname)) {
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->moddn (
+ "cn=$groupName,$groupsdn",
+ newrdn => "cn=$newname",
+ deleteoldrdn => "1",
+ newsuperior => "$groupsdn"
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+}
+
+# Add members
+if (defined($Options{'m'})) {
+ my $members = $Options{'m'};
+ my @members = split( /,/, $members );
+ my $member;
+ foreach $member ( @members ) {
+ my $group_entry=read_group_entry($groupName);
+ $groupsdn=$group_entry->dn;
+ if (is_unix_user($member)) {
+ if (is_group_member($groupsdn,$member)) {
+ print "User $member already in the group\n";
+ } else {
+ print "adding user $member to group $groupName\n";
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ($groupsdn,
+ changes => [
+ add => [memberUid => $member]
+ ]
+ );
+ $modify->code && warn "failed to add entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+ }
+ } else {
+ print "User $member does not exist: create it first !\n";
+ }
+ }
+}
+
+# Delete members
+if (defined($Options{'x'})) {
+ my $members = $Options{'x'};
+ my @members = split( /,/, $members );
+ my $member;
+ foreach $member ( @members ) {
+ my $group_entry=read_group_entry($groupName);
+ $groupsdn=$group_entry->dn;
+ if (is_group_member("$groupsdn",$member)) {
+ print "deleting user $member from group $groupName\n";
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ($groupsdn,
+ changes => [
+ delete => [memberUid => $member]
+ ]
+ );
+ $modify->code && warn "failed to delete entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+ } else {
+ print "User $member is not in the group $groupName!\n";
+ }
+ }
+}
+
+my $group_sid;
+if ($tmp= $Options{'s'}) {
+ if ($tmp =~ /^S-(?:\d+-)+\d+$/) {
+ $group_sid = $tmp;
+ } else {
+ print "$0: illegal group-rid $tmp\n";
+ exit(7);
+ }
+} elsif ($Options{'r'} || $Options{'a'}) {
+ my $group_rid;
+ if ($tmp= $Options{'r'}) {
+ if ($tmp =~ /^\d+$/) {
+ $group_rid = $tmp;
+ } else {
+ print "$0: illegal group-rid $tmp\n";
+ exit(7);
+ }
+ } else {
+ # algorithmic mapping
+ $group_rid = 2*$gid+1001;
+ }
+ $group_sid = $SID.'-'.$group_rid;
+}
+
+if ($group_sid) {
+ my @adds;
+ my @mods;
+ push(@mods, 'sambaSID' => $group_sid);
+
+ if ($tmp= $Options{'t'}) {
+ my $group_type;
+ if (defined($group_type = &group_type_by_name($tmp))) {
+ push(@mods, 'sambaGroupType' => $group_type);
+ } else {
+ print "$0: unknown group type $tmp\n";
+ exit(8);
+ }
+ } else {
+ if (! defined($group_entry->get_value('sambaGroupType'))) {
+ push(@mods, 'sambaGroupType' => group_type_by_name('domain'));
+ }
+ }
+
+ my @oc = $group_entry->get_value('objectClass');
+ unless (grep($_ =~ /^sambaGroupMapping$/i, @oc)) {
+ push (@adds, 'objectClass' => 'sambaGroupMapping');
+ }
+
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+ changes => [
+ 'add' => [ @adds ],
+ 'replace' => [ @mods ]
+ ]
+ );
+ $modify->code && warn "failed to delete entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind
+}
+
+$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+smbldap-groupmod.pl - Modify a group
+
+=head1 SYNOPSIS
+
+smbldap-groupmod.pl [-g gid [-o]] [-n group_name ] group
+
+=head1 DESCRIPTION
+
+The smbldap-groupmod.pl command modifies the system account files to
+ reflect the changes that are specified on the command line.
+ The options which apply to the smbldap-groupmod command are
+
+ -g gid The numerical value of the group's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. Any files which the old group ID is the file
+ group ID must have the file group ID changed manually.
+
+ -n group_name
+ The name of the group will be changed from group to group_name.
+
+ -m members
+ The members to be added to the group in comma-delimeted form.
+
+ -x members
+ The members to be removed from the group in comma-delimted form.
+
+=head1 EXAMPLES
+
+ smbldap-groupmod.pl -g 253 development
+ This will change the GID of the 'development' group to '253'.
+
+ smbldap-groupmod.pl -n Idiots Managers
+ This will change the name of the 'Managers' group to 'Idiots'.
+
+ smbldap-groupmod.pl -m "jdoe,jsmith" "Domain Admins"
+ This will add 'jdoe' and 'jsmith' to the 'Domain Admins' group.
+
+ smbldap-groupmod.pl -x "jdoe,jsmith" "Domain Admins"
+ This will remove 'jdoe' and 'jsmith' from the 'Domain Admins' group.
+
+=head1 SEE ALSO
+
+ groupmod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupshow.pl b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl
new file mode 100755
index 00000000000..a9d368763ee
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-groupshow : user (posix,shadow,samba) display
+#
+# History :
+# . originally by David Le Corfec <david.le-corfec@IDEALX.com>
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-?] group\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $group = $ARGV[0];
+
+my $lines = read_group($group);
+if (!defined($lines)) {
+ print "$0: group $group doesn't exist\n";
+ exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-groupshow.pl - Display group informations
+
+=head1 SYNOPSIS
+
+ smbldap-groupshow.pl groupname
+
+=head1 DESCRIPTION
+
+ The smbldap-groupshow.pl command displays informations
+ associated with the given group.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
new file mode 100755
index 00000000000..54e4d7f7e3f
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
@@ -0,0 +1,230 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-migrate-accounts : add NT sam entries from pwdump
+# to ldap
+
+use strict;
+use Getopt::Std;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+# smbldap-migrate.pl (-? or -h for help)
+#
+# Read pwdump entries on stdin, and add them to the ldap server.
+# Output uncreated/unmodified entries (see parameters -C -U)
+# in pwdump format to stdout.
+# Errors, debug and stats are output to stderr.
+
+sub modify_account
+ {
+ my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
+ # bind to a directory with dn and password
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ("uid=$login,$basedn",
+ changes => [
+ replace => [sambaLMPassword => "$lmpwd"],
+ replace => [sambaNTpassword => "$ntpwd"],
+ replace => [gecos => "$gecos"],
+ replace => [sambaHomePath => "$homedir"]
+ ]
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+ # take down the session
+ $ldap_master->unbind;
+ }
+
+#####################
+
+
+my %Options;
+
+my $ok = getopts('awA:CUW:?h', \%Options);
+
+if ( (!$ok) || ($Options{'?'}) || ($Options{'h'}) ) {
+ print "Usage: $0 [-awAWCU?]\n";
+ print " -a process only people, ignore computers\n";
+ print " -w process only computers, ignore persons\n";
+ print " -A <opts> option string passed verbatim to smbldap-useradd for persons\n";
+ print " -W <opts> option string passed verbatim to smbldap-useradd for computers\n";
+ print " -C if entry not found, don't create it and log it to stdout (default: create it)\n";
+ print " -U if entry found, don't update it and log it to stdout (default: update it)\n";
+ print " -?|-h show this help message\n";
+ exit (1);
+}
+
+my %processed = ( 'user' => 0, 'machine' => 0);
+my %created = ( 'user' => 0, 'machine' => 0);
+my %updated = ( 'user' => 0, 'machine' => 0);
+my %logged = ( 'user' => 0, 'machine' => 0);
+my %errors = ( 'user' => 0, 'machine' => 0);
+my %existing = ( 'user' => 0, 'machine' => 0);
+my $specialskipped = 0;
+
+while (<>) {
+ my ($login, $rid, $lmpwd, $ntpwd, $gecos, $homedir, $b) = split(/:/, $_);
+ my $usertype;
+ my $userbasedn;
+
+ my $entry_type = 'user';
+
+ if ($login =~ m/.*\$$/ ) { # computer
+ $processed{'machine'}++;
+ $entry_type = 'machine';
+ if (defined($Options{'a'})) {
+ print STDERR "ignoring $login\n";
+ next;
+ }
+
+ $usertype = "-w $Options{'W'}";
+ $userbasedn = $computersdn;
+ } else { # people
+ $processed{'user'}++;
+ if (defined($Options{'w'})) {
+ print STDERR "ignoring $login\n";
+ next;
+ }
+ if ($rid < 1000) {
+ $specialskipped++;
+ print STDERR "$login seems to be a special Win account (rid=$rid), skipping\n";
+ next;
+ }
+
+ $usertype = "-a $Options{'A'}";
+ $userbasedn = $usersdn;
+ }
+
+ # normalize homedir
+ # uncomment to replace configured share with share from pwdump
+ # if ($homedir eq "") {
+ $homedir = $_userSmbHome;
+ # }
+
+ # normalize gecos
+ if (!($gecos eq "")) {
+ $gecos =~ tr//AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
+ } else {
+ $gecos = $_userGecos;
+ }
+
+ my $user_exists = is_samba_user($login);
+
+ if (!$user_exists) {
+ if (!defined($Options{'C'})) {
+ # uid doesn't exist and we want to create it
+ my $addcmd = "/usr/local/sbin/smbldap-useradd.pl $usertype $login > /dev/null";
+ print STDERR "$addcmd\n";
+ my $r = system "$addcmd";
+ if ($r != 0) {
+ print STDERR "error adding $login, skipping\n";
+ next;
+ }
+ # lem modif... a retirer si pb
+ if ($entry_type eq "user") {
+ modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+ }
+
+ $created{$entry_type}++;
+ } else { # uid doesn't exist and no create => log
+ print "$_";
+ $logged{$entry_type}++;
+ }
+ } else { # account exists
+ $existing{$entry_type}++;
+ if (!defined($Options{'U'})) { # exists and modify
+ modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+ $updated{$entry_type}++;
+ } else { # exists and log
+ print "$_";
+ $logged{$entry_type}++;
+ }
+ }
+}
+
+my $sum;
+
+$sum = $processed{'user'} + $processed{'machine'};
+print STDERR "processed: all=$sum user=$processed{'user'} machine=$processed{'machine'}\n";
+
+$sum = $existing{'user'} + $existing{'machine'};
+print STDERR "existing: all=$sum user=$existing{'user'} machine=$existing{'machine'}\n";
+
+$sum = $created{'user'} + $created{'machine'};
+print STDERR "created: all=$sum user=$created{'user'} machine=$created{'machine'}\n";
+
+$sum = $updated{'user'} + $updated{'machine'};
+print STDERR "updated: all=$sum user=$updated{'user'} machine=$updated{'machine'}\n";
+
+$sum = $logged{'user'} + $logged{'machine'};
+print STDERR "logged: all=$sum user=$logged{'user'} machine=$logged{'machine'}\n";
+
+print STDERR "special users skipped: $specialskipped\n";
+
+
+########################################
+
+=head1 NAME
+
+smbldap-migrate.pl - Migrate NT accounts to LDAP
+
+=head1 SYNOPSIS
+
+ smbldap-migrate.pl [-a] [-w] [-A opts] [-W opts] [-C] [-U] [-?]
+
+=head1 DESCRIPTION
+
+ This command reads from stdin account entries as created by pwdump,
+ a tool to dump an user database on NT.
+ Depending of the options, some account entries may be output on
+ stdout. All errors and informations are sent to stderr.
+
+ -a process only people, ignore computers
+
+ -w process only computers, ignore persons
+
+ -A opts
+ a string containing arguments to pass verbatim to
+ smbldap-useradd when adding users, eg "-m -x".
+ You don't have to specify -a in this string.
+
+ -W opts
+ a string containing arguments to pass verbatim to
+ smbldap-useradd when adding computers, eg "-m -x".
+ You don't have to specify -w in this string.
+
+ -C if NT account not found in LDAP, don't create it and log it to stdout
+ (default: create it)
+
+ -U if NT account found in LDAP, don't update it and log it to stdout
+ (default: update it)
+
+ -? show the help message
+
+=cut
+
+#'
+
+# The End
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
new file mode 100644
index 00000000000..a2b07bf817c
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
@@ -0,0 +1,225 @@
+#!/usr/bin/perl
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-migrate-groups : to parse a Windows
+# group dump and populate Unix groups
+# Reads group dump on stdin
+
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+use Getopt::Std;
+
+sub process_rec_group
+ {
+ my ($group, $mb) = @_;
+ my @members;
+
+ if (!(@members = group_get_members($group))) {
+ return 0;
+ }
+
+ foreach my $m (@members) {
+ if ( !($m =~ m/^\*/) ) {
+ push @{$mb}, $m;
+ } else {
+ my $gname = $m;
+ $gname =~ s/^.//;
+ if (!process_rec_group($gname, $mb)) {
+ print "recursive group not added : $gname\n";
+ }
+ }
+ }
+ }
+
+
+# given a group dn and a list of members, update the group
+sub modify_group
+ {
+ my ($group, $dn_line, @members, $recgroup) = @_;
+ my $m;
+ my @new_mb;
+
+ foreach $m (@members) {
+ if ( ($m =~ m/^\*/) ) {
+ my $gname = $m;
+ $gname =~ s/^.//;
+ if (!$recgroup) {
+ print "recursive group not added : $gname\n";
+ } else {
+ if (!process_rec_group($gname, \@new_mb)) {
+ print "recursive group not added : $gname\n";
+ }
+ }
+ } else {
+ push @new_mb, $m;
+ }
+ }
+
+ # new_mb contains flat members from group dump
+ # now append them to existing members
+ push @new_mb, group_get_members($group);
+ # uniq them
+ my %saw;
+ @saw{@new_mb} = ();
+ @new_mb = keys %saw;
+
+ my $nmb = $#new_mb + 1;
+ print STDERR "Group $group now has $nmb member(s)\n";
+
+ my $mbs;
+ foreach $m (@new_mb) {
+ $mbs .= "memberUid: $m\n";
+ }
+
+ my $mods="$dn_line
+changetype: modify
+replace: memberUid
+$mbs
+";
+
+ #print "$mods\n";
+ my $tmpldif =
+ "$mods
+";
+
+ die "$0: error while modifying group $group\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ }
+
+sub display_group
+ {
+ my ($group, @members) = @_;
+
+ print "Group name $group\n";
+ print "Members\n";
+ my $m;
+ my $i = 0;
+ foreach $m (@members) {
+ print "$m ";
+ if ($i % 5 == 0) {
+ print "\n";
+ }
+ $i++;
+ }
+ }
+
+sub process_group
+ {
+ my ($group, @members, $nocreate, $noupdate, $recgroup) = @_;
+
+ my $dn_line;
+ if (!defined($dn_line = get_group_dn($group))) {
+ # group not found, create it ?
+ if (!$nocreate) {
+ system "/usr/local/sbin/smbldap-groupadd.pl \"$group\"; sleep 5";
+ if (!defined($dn_line = get_group_dn($group))) {
+ return 1;
+ }
+ modify_group($group, $dn_line, @members, $recgroup);
+ } else {
+ # don't create
+ print "not created:\n";
+ display_group($group, @members);
+ }
+ } else {
+ # group found, update it ?
+ if (!$noupdate) {
+ modify_group($group, $dn_line, @members, $recgroup);
+ } else {
+ # don't update
+ print "not updated:\n";
+ display_group($group, @members);
+ }
+ }
+ }
+
+###################################################
+
+my %Options;
+
+my $ok = getopts('CUr?', \%Options);
+if ( (!$ok) || ($Options{'?'}) ) {
+ print "Usage: $0 [-CUr?] < group_dump\n";
+ print " -C don't create group if it doesn't exist\n";
+ print " -U don't update group if it exists\n";
+ print " -r recursively process groups\n";
+ exit(1);
+}
+
+my $group_name;
+my $group_desc;
+my $has_members = 0;
+my @members = ();
+
+while (<>) {
+ my $line = $_;
+ chomp($line);
+ next if ( $line =~ m/^\s*$/ );
+
+ if ($group_name eq "") {
+ if ( $line =~ m/^Group name\s+(.+).$/ ) {
+ $group_name = $1;
+ next;
+ }
+ }
+ if ($group_desc eq "") {
+ if ( $line =~ m/^Comment\s+(.*)$/ ) {
+ $group_desc = $1;
+ next;
+ }
+ }
+ next if ( $line =~ m/^-+.$/ );
+ if (!$has_members) {
+ if ( $line =~ m/^Members/ ) {
+ $has_members = 1;
+ next;
+ }
+ } else {
+ if ( $line =~ m/^The command completed successfully/ ) {
+ last;
+ } else {
+ push(@members, split(/\s+/, $line));
+ next;
+ }
+ }
+
+ #print;
+}
+
+if ( $#members > -1) {
+ process_group($group_name, @members, $Options{'C'}, $Options{'U'}, $Options{'r'});
+}
+
+#print "gn=$group_name\n";
+#print "gd=$group_desc\n";
+#my $m;
+#foreach $m (@members)
+#{
+# print "$m ";
+#}
+#print "\n";
diff --git a/examples/LDAP/smbldap-tools/smbldap-passwd.pl b/examples/LDAP/smbldap-tools/smbldap-passwd.pl
new file mode 100755
index 00000000000..afbc87a058d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-passwd.pl
@@ -0,0 +1,227 @@
+#!/usr/bin/perl -w
+
+# LDAP to unix password sync script for samba
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose :
+# . ldap-unix passwd sync for SAMBA>2.2.2 + LDAP
+# . may also replace /bin/passwd
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+my $user;
+my $oldpass;
+my $ret;
+
+my $arg;
+
+foreach $arg (@ARGV) {
+ if ($< != 0) {
+ die "Only root can specify parameters\n";
+ } else {
+ if ( ($arg eq '-?') || ($arg eq '--help') ) {
+ print "Usage: $0 [username]\n";
+ print " -?, --help show this help message\n";
+ exit (6);
+ } elsif (substr($arg,0) ne '-') {
+ $user = $arg;
+ }
+ $oldpass = 1;
+ }
+}
+
+if (!defined($user)) {
+ $user=$ENV{"USER"};
+}
+
+# test existence of user in LDAP
+my $dn_line;
+if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+my $samba = is_samba_user($user);
+
+print "Changing password for $user\n";
+
+# non-root user
+if (!defined($oldpass)) {
+ # prompt for current password
+ system "stty -echo";
+ print "(current) UNIX password: ";
+ chomp($oldpass=<STDIN>);
+ print "\n";
+ system "stty echo";
+
+ if (!is_user_valid($user, $dn, $oldpass)) {
+ print "Authentication failure\n";
+ exit (10);
+ }
+}
+
+# prompt for new password
+
+my $pass;
+my $pass2;
+
+system "stty -echo";
+print "New password : ";
+chomp($pass=<STDIN>);
+print "\n";
+system "stty echo";
+
+system "stty -echo";
+print "Retype new password : ";
+chomp($pass2=<STDIN>);
+print "\n";
+system "stty echo";
+
+if ($pass ne $pass2) {
+ print "New passwords don't match!\n";
+ exit (10);
+}
+
+# First, connecting to the directory
+my $ldap_master=connect_ldap_master();
+
+# only modify smb passwords if smb user
+if ($samba == 1) {
+ if (!$with_smbpasswd) {
+ # generate LanManager and NT clear text passwords
+ if ($mk_ntpasswd eq '') {
+ print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
+ exit(1);
+ }
+ my $ntpwd = `$mk_ntpasswd '$pass'`;
+ chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
+ chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
+ # the sambaPwdLastSet must be updating
+ my $date=time;
+ my @mods;
+ push(@mods, 'sambaLMPassword' => $sambaLMPassword);
+ push(@mods, 'sambaNTPassword' => $sambaNTPassword);
+ push(@mods, 'sambaPwdLastSet' => $date);
+ if (defined $_defaultMaxPasswordAge) {
+ my $new_sambaPwdMustChange=$date+$_defaultMaxPasswordAge*24*60*60;
+ push(@mods, 'sambaPwdMustChange' => $new_sambaPwdMustChange);
+ push(@mods, 'sambaAcctFlags' => '[U]');
+ }
+ # Let's change nt/lm passwords
+ my $modify = $ldap_master->modify ( "$dn",
+ 'replace' => { @mods }
+ );
+ $modify->code && warn "failed to modify entry: ", $modify->error ;
+
+ } else {
+ if ($< != 0) {
+ my $FILE="|$smbpasswd -s >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+'$oldpass'
+'$pass'
+'$pass'
+EOF
+ ;
+ close FILE;
+ } else {
+ my $FILE="|$smbpasswd $user -s >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+'$pass'
+'$pass'
+EOF
+ ;
+ close FILE;
+ }
+ }
+}
+
+# change unix password
+my $hash_password = `slappasswd -h {$hash_encrypt} -s '$pass'`;
+chomp($hash_password);
+my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ replace => [userPassword => "$hash_password"]
+ ]
+ );
+$modify->code && warn "Unable to change password : ", $modify->error ;
+
+# take down session
+$ldap_master->unbind;
+
+exit 0;
+
+
+# - The End
+
+=head1 NAME
+
+smbldap-passwd.pl - change user password
+
+=head1 SYNOPSIS
+
+ smbldap-passwd.pl [name]
+
+=head1 DESCRIPTION
+
+smbldap-passwd.pl changes passwords for user accounts. A normal user
+ may only change the password for their own account, the super user may
+ change the password for any account.
+
+ Password Changes
+ The user is first prompted for their old password, if one is present.
+ This password is then tested against the stored password by binding
+ to the server. The user has only one chance to enter the correct pass-
+ word. The super user is permitted to bypass this step so that forgot-
+ ten passwords may be changed.
+
+ The user is then prompted for a replacement password. As a general
+ guideline, passwords should consist of 6 to 8 characters including
+ one or more from each of following sets:
+
+ Lower case alphabetics
+
+ Upper case alphabetics
+
+ Digits 0 thru 9
+
+ Punctuation marks
+
+ passwd will prompt again and compare the second entry against the first.
+ Both entries are require to match in order for the password to be
+ changed.
+
+=head1 SEE ALSO
+
+ passwd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-populate.pl b/examples/LDAP/smbldap-tools/smbldap-populate.pl
new file mode 100755
index 00000000000..b691a848500
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-populate.pl
@@ -0,0 +1,370 @@
+#!/usr/bin/perl -w
+
+# Populate a LDAP base for Samba-LDAP usage
+#
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose :
+# . Create an initial LDAP database suitable for Samba 2.2
+# . For lazy people, replace ldapadd (with only an ldif parameter)
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+use Getopt::Std;
+use Net::LDAP::LDIF;
+
+use vars qw(%oc);
+
+# objectclass of the suffix
+%oc = (
+ "ou" => "organizationalUnit",
+ "o" => "organization",
+ "dc" => "dcObject",
+ );
+
+
+my %Options;
+
+my $ok = getopts('a:b:?', \%Options);
+if ( (!$ok) || ($Options{'?'}) ) {
+ print "Usage: $0 [-ab?] [ldif]\n";
+ print " -a administrator login name (default: Administrator)\n";
+ print " -b guest login name (default: nobody)\n";
+ print " -? show this help message\n";
+ print " ldif file to add to ldap (default: suffix, Groups,";
+ print " Users, Computers and builtin users )\n";
+ exit (1);
+}
+
+my $_ldifName;
+my $tmp_ldif_file="/tmp/$$.ldif";
+
+if (@ARGV >= 1) {
+ $_ldifName = $ARGV[0];
+}
+
+my $adminName = $Options{'a'};
+if (!defined($adminName)) {
+ $adminName = "Administrator";
+}
+
+my $guestName = $Options{'b'};
+if (!defined($guestName)) {
+ $guestName = "nobody";
+}
+
+if (!defined($_ldifName)) {
+ my $attr;
+ my $val;
+ my $objcl;
+
+ print "Using builtin directory structure\n";
+ if ($suffix =~ m/([^=]+)=([^,]+)/) {
+ $attr = $1;
+ $val = $2;
+ $objcl = $oc{$attr} if (exists $oc{$attr});
+ if (!defined($objcl)) {
+ $objcl = "myhardcodedobjectclass";
+ }
+ } else {
+ die "can't extract first attr and value from suffix $suffix";
+ }
+ #print "$attr=$val\n";
+ my ($organisation,$ext) = ($suffix =~ m/dc=(.*),dc=(.*)$/);
+
+ #my $FILE="|cat";
+ my $FILE=$tmp_ldif_file;
+ open (FILE, ">$FILE") || die "Can't open file $FILE: $!\n";
+
+ print FILE <<EOF;
+dn: $suffix
+objectClass: $objcl
+objectclass: organization
+$attr: $val
+o: $organisation
+
+dn: $usersdn
+objectClass: organizationalUnit
+ou: $usersou
+
+dn: $groupsdn
+objectClass: organizationalUnit
+ou: $groupsou
+
+dn: $computersdn
+objectClass: organizationalUnit
+ou: $computersou
+
+dn: uid=$adminName,$usersdn
+cn: $adminName
+sn: $adminName
+objectClass: inetOrgPerson
+objectClass: sambaSamAccount
+objectClass: posixAccount
+gidNumber: 512
+uid: $adminName
+uidNumber: 998
+homeDirectory: $_userHomePrefix
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: 0
+sambaPwdMustChange: 2147483647
+sambaHomePath: $_userSmbHome
+sambaHomeDrive: $_userHomeDrive
+sambaProfilePath: $_userProfile
+sambaPrimaryGroupSID: $SID-512
+sambaLMPassword: XXX
+sambaNTPassword: XXX
+sambaAcctFlags: [U ]
+sambaSID: $SID-2996
+loginShell: /bin/false
+gecos: Netbios Domain Administrator
+
+dn: uid=$guestName,$usersdn
+cn: $guestName
+sn: $guestName
+objectClass: inetOrgPerson
+objectClass: sambaSamAccount
+objectClass: posixAccount
+gidNumber: 514
+uid: $guestName
+uidNumber: 999
+homeDirectory: /dev/null
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: 0
+sambaPwdMustChange: 2147483647
+sambaHomePath: $_userSmbHome
+sambaHomeDrive: $_userHomeDrive
+sambaProfilePath: $_userProfile
+sambaPrimaryGroupSID: $SID-514
+sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+sambaAcctFlags: [NU ]
+sambaSID: $SID-2998
+loginShell: /bin/false
+
+dn: cn=Domain Admins,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 512
+cn: Domain Admins
+memberUid: $adminName
+description: Netbios Domain Administrators
+sambaSID: $SID-512
+sambaGroupType: 2
+displayName: Domain Admins
+
+dn: cn=Domain Users,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 513
+cn: Domain Users
+description: Netbios Domain Users
+sambaSID: $SID-513
+sambaGroupType: 2
+displayName: Domain Users
+
+dn: cn=Domain Guests,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 514
+cn: Domain Guests
+description: Netbios Domain Guests Users
+sambaSID: $SID-514
+sambaGroupType: 2
+displayName: Domain Guests
+
+dn: cn=Administrators,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 544
+cn: Administrators
+description: Netbios Domain Members can fully administer the computer/sambaDomainName
+sambaSID: $SID-544
+sambaGroupType: 2
+displayName: Administrators
+
+dn: cn=Users,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 545
+cn: Users
+description: Netbios Domain Ordinary users
+sambaSID: $SID-545
+sambaGroupType: 2
+displayName: users
+
+dn: cn=Guests,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 546
+cn: Guests
+memberUid: $guestName
+description: Netbios Domain Users granted guest access to the computer/sambaDomainName
+sambaSID: $SID-546
+sambaGroupType: 2
+displayName: Guests
+
+dn: cn=Power Users,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 547
+cn: Power Users
+description: Netbios Domain Members can share directories and printers
+sambaSID: $SID-547
+sambaGroupType: 2
+displayName: Power Users
+
+dn: cn=Account Operators,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 548
+cn: Account Operators
+description: Netbios Domain Users to manipulate users accounts
+sambaSID: $SID-548
+sambaGroupType: 2
+displayName: Account Operators
+
+dn: cn=Server Operators,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 549
+cn: Server Operators
+description: Netbios Domain Server Operators
+sambaSID: $SID-549
+sambaGroupType: 2
+displayName: Server Operators
+
+dn: cn=Print Operators,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 550
+cn: Print Operators
+description: Netbios Domain Print Operators
+sambaSID: $SID-550
+sambaGroupType: 2
+displayName: Print Operators
+
+dn: cn=Backup Operators,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 551
+cn: Backup Operators
+description: Netbios Domain Members can bypass file security to back up files
+sambaSID: $SID-551
+sambaGroupType: 2
+displayName: Backup Operators
+
+dn: cn=Replicator,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 552
+cn: Replicator
+description: Netbios Domain Supports file replication in a sambaDomainName
+sambaSID: $SID-552
+sambaGroupType: 2
+displayName: Replicator
+
+dn: cn=Domain Computers,$groupsdn
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 553
+cn: Domain Computers
+description: Netbios Domain Computers accounts
+sambaSID: $SID-553
+sambaGroupType: 2
+displayName: Domain Computers
+
+EOF
+ close FILE;
+} else {
+ $tmp_ldif_file=$_ldifName;
+}
+
+my $ldap_master=connect_ldap_master();
+my $ldif = Net::LDAP::LDIF->new($tmp_ldif_file, "r", onerror => 'undef' );
+while( not $ldif->eof() ) {
+ my $entry = $ldif->read_entry();
+ if ( $ldif->error() ) {
+ print "Error msg: ",$ldif->error(),"\n";
+ print "Error lines:\n",$ldif->error_lines(),"\n";
+ } else {
+ my $dn = $entry->dn;
+ print "adding new entry: $dn\n";
+ my $result=$ldap_master->add($entry);
+ $result->code && warn "failed to add entry: ", $result->error ;
+ }
+}
+$ldap_master->unbind;
+system "rm -f $tmp_ldif_file";
+exit(0);
+
+
+########################################
+
+=head1 NAME
+
+smbldap-populate.pl - Populate your LDAP database
+
+=head1 SYNOPSIS
+
+ smbldap-populate.pl [ldif-file]
+
+=head1 DESCRIPTION
+
+ The smbldap-populate.pl command helps to populate an LDAP server
+ by adding the necessary entries : base suffix (doesn't abort
+ if already there), organizational units for users, groups and
+ computers, builtin users : Administrator and guest, builtin
+ groups (though posixAccount only, no SambaTNG support).
+
+ -a name Your local administrator login name (default: Administrator)
+ -b name Your local guest login name (default: nobody)
+
+ If you give an extra parameter, it is assumed to be the ldif
+ file to use instead of the builtin one. Options -a and -b
+ will be ignored.
+
+=head1 FILES
+
+ /usr/lib/perl5/site-perl/smbldap_conf.pm : Global parameters.
+
+=head1 SEE ALSO
+
+ smp(1)
+
+=cut
+
+#'
+
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap-tools.spec b/examples/LDAP/smbldap-tools/smbldap-tools.spec
new file mode 100755
index 00000000000..4bd2968defe
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-tools.spec
@@ -0,0 +1,140 @@
+# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/smbldap-tools.spec,v $
+%define version 0.8.2
+%define release 1
+%define name smbldap-tools
+%define realname smbldap-tools
+
+Summary: User & Group administration tools for Samba-OpenLDAP
+Name: %{name}
+version: %{version}
+Release: %{release}
+Group: System Environment/Base
+License: GPL
+
+Vendor: IDEALX S.A.S.
+URL: http://samba.IDEALX.org/
+Packager: Jerome Tournier <jerome.tournier@IDEALX.com>
+Source0: smbldap-groupadd.pl
+Source1: smbldap-groupdel.pl
+Source2: smbldap-groupmod.pl
+Source3: smbldap-groupshow.pl
+Source4: smbldap-passwd.pl
+Source5: smbldap-useradd.pl
+Source6: smbldap-userdel.pl
+Source7: smbldap-usermod.pl
+Source8: smbldap-usershow.pl
+Source9: smbldap_conf.pm
+Source10: smbldap_tools.pm
+Source11: CONTRIBUTORS
+Source12: COPYING
+Source13: ChangeLog
+Source14: FILES
+Source15: README
+Source16: TODO
+Source17: mkntpwd.tar.gz
+Source18: smbldap-populate.pl
+Source19: smbldap-migrate-accounts.pl
+Source20: smbldap-migrate-groups.pl
+Source21: INFRA
+Source22: smb.conf
+BuildRoot: /%{_tmppath}/%{name}
+Prefix: /usr/local
+BuildRequires: perl >= 5.6
+Requires: perl >= 5.6, openldap, openldap-clients, samba
+
+%description
+In settings with OpenLDAP and Samba-LDAP servers, this collection is
+useful to add, modify and delete users and groups, and to change
+Unix and Samba passwords. In those context they replace the system
+tools to manage users, groups and passwords.
+
+%prep
+
+%setup -c -T
+
+%build
+tar zxvf %{SOURCE17}
+cd mkntpwd
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/share
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools
+
+cd mkntpwd ; make PREFIX=$RPM_BUILD_ROOT/%{prefix} install
+
+install -m 550 %{SOURCE0} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupadd.pl
+install -m 550 %{SOURCE1} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupdel.pl
+install -m 550 %{SOURCE2} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupmod.pl
+install -m 555 %{SOURCE3} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupshow.pl
+install -m 555 %{SOURCE4} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-passwd.pl
+install -m 550 %{SOURCE5} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-useradd.pl
+install -m 550 %{SOURCE6} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-userdel.pl
+install -m 550 %{SOURCE7} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usermod.pl
+install -m 555 %{SOURCE8} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usershow.pl
+install -m 550 %{SOURCE18} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-populate.pl
+install -m 751 %{SOURCE9} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_conf.pm
+install -m 555 %{SOURCE10} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_tools.pm
+install -m 550 %{SOURCE19} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-accounts.pl
+install -m 550 %{SOURCE20} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-groups.pl
+
+install -m 644 %{SOURCE11} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/CONTRIBUTORS
+install -m 644 %{SOURCE12} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/COPYING
+install -m 644 %{SOURCE13} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/ChangeLog
+install -m 644 %{SOURCE14} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/FILES
+install -m 644 %{SOURCE15} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/README
+install -m 644 %{SOURCE16} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/TODO
+install -m 644 %{SOURCE21} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/INFRA
+install -m 644 %{SOURCE22} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/smb.conf
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+# from smbldap-tools-0.8-2, librairies are loaded with the FindBin perl package
+if [ -f /usr/lib/perl5/site_perl/smbldap_tools.pm ];
+then
+ rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm
+fi
+if [ -f /usr/lib/perl5/site_perl/smbldap_conf.pm ];
+then
+ rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm
+fi
+chgrp 512 %{prefix}/sbin/smbldap-useradd.pl %{prefix}/sbin/smbldap_conf.pm || echo "An error occured while changing groups of smbldap-useradd.pl and smbldap_conf.pm in /usr/local/sbin. For proper operations, please ensure that they have the same posix group as the Samba domain administrator if there's a local Samba PDC."
+perl -i -pe 's/_SLAVELDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_MASTERLDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_SUFFIX_/dc=IDEALX,dc=org/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_USERS_/Users/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_COMPUTERS_/Computers/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_GROUPS_/Groups/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_LOGINSHELL_/\/bin\/bash/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_HOMEPREFIX_/\/home/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_BINDDN_/cn=Manager,\$suffix/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_BINDPW_/secret/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_PDCNAME_/PDC-SRV/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_HOMEDRIVE_/H:/' %{prefix}/sbin/smbldap_conf.pm
+
+# FIXME: links should not be removed on upgrade
+#%postun
+#if [ $1 = 0 ] ; then
+# rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm
+# rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm
+#fi
+
+%files
+%defattr(-,root,root)
+%{prefix}/sbin/*.pl
+%{prefix}/sbin/smbldap_tools.pm
+%config(noreplace) %{prefix}/sbin/smbldap_conf.pm
+%{prefix}/sbin/mkntpwd
+%doc /usr/share/doc/%{name}/
+
+
+%changelog
+* Fri Nov 28 2003 Jerome Tournier <jerome.tournier@idealx.com> 0.8.2-1
+- new smb.conf file as example configuration file
+- see Changelog file for updates in scripts
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-useradd.pl b/examples/LDAP/smbldap-tools/smbldap-useradd.pl
new file mode 100755
index 00000000000..918bd4a4f66
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-useradd.pl
@@ -0,0 +1,522 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-useradd : user (posix,shadow,samba) add
+
+use strict;
+
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('anmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:N:S:?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-awmugdsckGPABCDEFH?] username\n";
+ print " -a is a Windows User (otherwise, Posix stuff only)\n";
+ print " -w is a Windows Workstation (otherwise, Posix stuff only)\n";
+ print " -u uid\n";
+ print " -g gid\n";
+ print " -G supplementary comma-separated groups\n";
+ print " -n do not create a group\n";
+ print " -d home\n";
+ print " -s shell\n";
+ print " -c gecos\n";
+ print " -m creates home directory and copies /etc/skel\n";
+ print " -k skeleton dir (with -m)\n";
+ print " -P ends by invoking smbldap-passwd.pl\n";
+ print " -A can change password ? 0 if no, 1 if yes\n";
+ print " -B must change password ? 0 if no, 1 if yes\n";
+ print " -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+ print " -D sambaHomeDrive (letter associated with home share, like 'H:')\n";
+ print " -E sambaLogonScript (DOS script to execute on login)\n";
+ print " -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
+ print " -H sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
+ print " -N canonical name\n";
+ print " -S surname\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+
+# cause problems when dealing with getpwuid because of the
+# negative ttl and ldap modification
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+}
+
+
+# Read options
+my $userUidNumber = $Options{'u'};
+if (!defined($userUidNumber)) {
+ # find first unused uid starting from $UID_START
+ while (defined(getpwuid($UID_START))) {
+ $UID_START++;
+ }
+ $userUidNumber = $UID_START;
+} elsif (getpwuid($userUidNumber)) {
+ die "Uid already exists.\n";
+}
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+}
+
+
+my $createGroup = 0;
+my $userGidNumber = $Options{'g'};
+# gid not specified ?
+if (!defined($userGidNumber)) {
+ # windows machine => $_defaultComputerGid
+ if (defined($Options{'w'})) {
+ $userGidNumber = $_defaultComputerGid;
+ # } elsif (!defined($Options{'n'})) {
+ # create new group (redhat style)
+ # find first unused gid starting from $GID_START
+ # while (defined(getgrgid($GID_START))) {
+ # $GID_START++;
+ # }
+ # $userGidNumber = $GID_START;
+
+ # $createGroup = 1;
+
+ } else {
+ # user will have gid = $_defaultUserGid
+ $userGidNumber = $_defaultUserGid;
+ }
+} else {
+ my $gid;
+ if (($gid = parse_group($userGidNumber)) < 0) {
+ print "$0: unknown group $userGidNumber\n";
+ exit (6);
+ }
+ $userGidNumber = $gid;
+}
+
+# Read only first @ARGV
+my $userName = $ARGV[0];
+
+# untaint $userName (can finish with one or two $)
+if ($userName =~ /^([\w -]+\$?)$/) {
+ $userName = $1;
+} else {
+ print "$0: illegal username\n";
+ exit (1);
+}
+
+# user must not exist in LDAP (should it be nss-wide ?)
+my ($rc, $dn) = get_user_dn2($userName);
+if ($rc and defined($dn)) {
+ print "$0: user $userName exists\n";
+ exit (9);
+} elsif (!$rc) {
+ print "$0: error in get_user_dn2\n";
+ exit(10);
+}
+
+my $group_entry;
+my $userGroupSID;
+my $userRid;
+if ($Options{'a'}) {
+ # as grouprid we use the value of the sambaSID attribute for
+ # group of gidNumber=$userGidNumber
+ $group_entry = read_group_entry_gid($userGidNumber);
+ $userGroupSID = $group_entry->get_value('sambaSID');
+ unless ($userGroupSID) {
+ print "$0: unknown group SID not set for unix group $userGidNumber\n";
+ print "check if your unix group is mapped to an NT group\n";
+ exit (7);
+ }
+
+ # as rid we use 2 * uid + 1000
+ $userRid = 2 * $userUidNumber + 1000;
+ # let's test if this SID already exist
+ my $user_sid="$SID-$userRid";
+ my $test_exist_sid=does_sid_exist($user_sid,$usersdn);
+ if ($test_exist_sid->count == 1) {
+ print "User SID already owned by\n";
+ # there should not exist more than one entry, but ...
+ foreach my $entry ($test_exist_sid->all_entries) {
+ my $dn= $entry->dn;
+ chomp($dn);
+ print "$dn\n";
+ }
+ exit(7);
+ }
+}
+
+my $userHomeDirectory;
+my ($userCN, $userSN);
+my $tmp;
+if (!defined($userHomeDirectory = $Options{'d'})) {
+ $userHomeDirectory = $_userHomePrefix."/".$userName;
+}
+$_userLoginShell = $tmp if (defined($tmp = $Options{'s'}));
+$_userGecos = $tmp if (defined($tmp = $Options{'c'}));
+$_skeletonDir = $tmp if (defined($tmp = $Options{'k'}));
+$userCN = ($Options{'c'} || $userName);
+$userCN = $tmp if (defined($tmp = $Options{'N'}));
+$userSN = $userName;
+$userSN = $tmp if (defined($tmp = $Options{'S'}));
+
+
+########################
+
+my $ldap_master=connect_ldap_master();
+
+# MACHINE ACCOUNT
+if (defined($tmp = $Options{'w'})) {
+
+ # add a trailing dollar if missing
+ if ($userName =~ /[^\$]$/s) {
+ $userName .= "\$";
+ }
+
+ #print "About to create machine $userName:\n";
+
+ if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
+ die "$0: error while adding posix account\n";
+ }
+
+ if (!$with_smbpasswd) {
+ # (jtournier)
+ # Objectclass sambaSamAccount is now added directly by samba when joigning the domain (for samba3)
+ #if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) {
+ # die "$0: error while adding samba account\n";
+ #}
+ } else {
+ if (!add_samba_machine($userName)) {
+ die "$0: error while adding samba account\n";
+ }
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ replace => [sambaAcctFlags => '[W ]']
+ ]
+ );
+ $modify->code && warn "failed to modify entry: ", $modify->error ;
+ }
+
+ exit 0;
+}
+
+# USER ACCOUNT
+# add posix account first
+
+my $add = $ldap_master->add ("uid=$userName,$usersdn",
+ attr => [
+ 'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
+ 'cn' => "$userCN",
+ 'sn' => "$userSN",
+ 'uid' => "$userName",
+ 'uidNumber' => "$userUidNumber",
+ 'gidNumber' => "$userGidNumber",
+ 'homeDirectory' => "$userHomeDirectory",
+ 'loginShell' => "$_userLoginShell",
+ 'gecos' => "$_userGecos",
+ 'description' => "$_userGecos",
+ 'userPassword' => "{crypt}x"
+ ]
+ );
+
+$add->code && warn "failed to add entry: ", $add->error ;
+
+
+#if ($createGroup) {
+# group_add($userName, $userGidNumber);
+#}
+
+group_add_user($userGidNumber, $userName);
+
+my $grouplist;
+# adds to supplementary groups
+if (defined($grouplist = $Options{'G'})) {
+ add_grouplist_user($grouplist, $userName);
+}
+
+# If user was created successfully then we should create his/her home dir
+if (defined($tmp = $Options{'m'})) {
+ unless ( $userName =~ /\$$/ ) {
+ if ( !(-e $userHomeDirectory) ) {
+ system "mkdir $userHomeDirectory 2>/dev/null";
+ system "cp -a $_skeletonDir/.[a-z,A-Z]* $_skeletonDir/* $userHomeDirectory 2>/dev/null";
+ system "chown -R $userUidNumber:$userGidNumber $userHomeDirectory 2>/dev/null";
+ system "chmod 700 $userHomeDirectory 2>/dev/null";
+ }
+ }
+}
+
+
+# Add Samba user infos
+if (defined($Options{'a'})) {
+ if (!$with_smbpasswd) {
+
+ my $winmagic = 2147483647;
+ my $valpwdcanchange = 0;
+ my $valpwdmustchange = $winmagic;
+ my $valpwdlastset = 0;
+ my $valacctflags = "[UX]";
+
+ if (defined($tmp = $Options{'A'})) {
+ if ($tmp != 0) {
+ $valpwdcanchange = "0";
+ } else {
+ $valpwdcanchange = "$winmagic";
+ }
+ }
+
+ if (defined($tmp = $Options{'B'})) {
+ if ($tmp != 0) {
+ $valpwdmustchange = "0";
+ # To force a user to change his password:
+ # . the attribut sambaPwdLastSet must be != 0
+ # . the attribut sambaAcctFlags must not match the 'X' flag
+ $valpwdlastset=$winmagic;
+ $valacctflags = "[U]";
+ } else {
+ $valpwdmustchange = "$winmagic";
+ }
+ }
+
+ if (defined($tmp = $Options{'H'})) {
+ $valacctflags = "$tmp";
+ }
+
+
+ my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+ changes => [
+ add => [objectClass => 'sambaSamAccount'],
+ add => [sambaPwdLastSet => "$valpwdlastset"],
+ add => [sambaLogonTime => '0'],
+ add => [sambaLogoffTime => '2147483647'],
+ add => [sambaKickoffTime => '2147483647'],
+ add => [sambaPwdCanChange => "$valpwdcanchange"],
+ add => [sambaPwdMustChange => "$valpwdmustchange"],
+ add => [displayName => "$_userGecos"],
+ add => [sambaAcctFlags => "$valacctflags"],
+ add => [sambaSID => "$SID-$userRid"]
+ ]
+ );
+
+ $modify->code && die "failed to add entry: ", $modify->error ;
+
+ } else {
+ my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+x
+x
+EOF
+ ;
+ close FILE;
+ if ($?) {
+ print "$0: error adding samba account\n";
+ exit (10);
+ }
+ } # with_smbpasswd
+
+ my @mods;
+ my $valscriptpath;
+ if (defined $_userScript) {
+ $valscriptpath="$_userScript";
+ } else {
+ $valscriptpath = "$userName.cmd";
+ }
+ if (defined($tmp = $Options{'E'})) {
+ $valscriptpath = "$tmp";
+ }
+
+ my $valsmbhome;
+ if (defined $_userSmbHome) {
+ $valsmbhome = "$_userSmbHome";
+ }
+ if (defined($tmp = $Options{'C'})) {
+ $valsmbhome = "$tmp";
+ }
+ if (defined $valsmbhome) {
+ push(@mods, 'sambaHomePath', $valsmbhome);
+ }
+
+ my $valhomedrive = "$_userHomeDrive";
+ if (defined($tmp = $Options{'D'})) {
+ $tmp = $tmp.":" unless ($tmp =~ /:/);
+ $valhomedrive = "$tmp";
+ }
+
+ my $valprofilepath;
+ if (defined $_userProfile) {
+ $valprofilepath = "$_userProfile$userName";
+ }
+
+ if (defined($tmp = $Options{'F'})) {
+ $valprofilepath = "$tmp";
+ }
+ if (defined $valprofilepath) {
+ push(@mods, 'sambaProfilePath', $valprofilepath);
+ }
+
+ my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+ changes => [
+ add => [sambaPrimaryGroupSID => "$userGroupSID"],
+ add => [sambaHomeDrive => "$valhomedrive"],
+ add => [sambaLogonScript => "$valscriptpath"],
+ add => [sambaLMPassword => 'XXX'],
+ add => [sambaNTPassword => 'XXX']
+ ]
+ );
+ $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+ 'replace' => { @mods }
+ );
+
+
+ $modify->code && die "failed to add entry: ", $modify->error ;
+
+}
+$ldap_master->unbind; # take down session
+
+
+if (defined($Options{'P'})) {
+ exec "/usr/local/sbin/smbldap-passwd.pl $userName"
+}
+
+exit 0;
+
+########################################
+
+=head1 NAME
+
+smbldap-useradd.pl - Create a new user or update default new
+ user information
+
+=head1 SYNOPSIS
+
+smbldap-useradd.pl [-c comment] [-d home_dir]
+ [-g initial_group] [-G group[,...]]
+ [-m [-k skeleton_dir]]
+ [-s shell] [-u uid [ -o]] [-P]
+ [-A canchange] [-B mustchange] [-C smbhome]
+ [-D homedrive] [-E scriptpath] [-F profilepath]
+ [-H acctflags] login
+
+=head1 DESCRIPTION
+
+Creating New Users
+ The smbldap-useradd.pl command creates a new user account using
+ the values specified on the command line and the default
+ values from the system.
+ The new user account will be entered into the system
+ files as needed, the home directory will be created, and
+ initial files copied, depending on the command line options.
+
+ You have to use smbldap-passwd to set the user password.
+ For Samba users, rid is 2*uidNumber+1000, and primaryGroupID
+ is 2*gidNumber+1001. Thus you may want to use
+ smbldap-useradd.pl -a -g "Domain Admins" -u 500 Administrator
+ to create a sambaDomainName administrator (admin rid is 0x1F4 = 500 and
+ grouprid is 0x200 = 512)
+
+ Without any option, the account created will be an Unix (Posix)
+ account. The following options may be used to add information:
+
+-a The user will have a Samba account (and Unix).
+
+ -w Creates an account for a Samba machine (Workstation), so that
+ it can join a sambaDomainName.
+
+ -x Creates rid and primaryGroupID in hex (for Samba 2.2.2 bug). Else
+ decimal (2.2.2 patched from cvs or 2.2.x, x > 2)
+
+ -c comment
+ The new user's comment field (gecos).
+
+ -d home_dir
+ The new user will be created using home_dir as the value for the
+ user's login directory. The default is to append the login name
+ to default_home and use that as the login directory name.
+
+ -g initial_group
+ The group name or number of the user's initial login group. The
+ group name must exist. A group number must refer to an already
+ existing group. The default group number is 1.
+
+ -G group,[...]
+ A list of supplementary groups which the user is also a member
+ of. Each group is separated from the next by a comma, with no
+ intervening whitespace. The groups are subject to the same
+ restrictions as the group given with the -g option. The default
+ is for the user to belong only to the initial group.
+
+ -m The user's home directory will be created if it does not exist.
+ The files contained in skeleton_dir will be copied to the home
+ directory if the -k option is used, otherwise the files con
+ tained in /etc/skel will be used instead. Any directories con
+ tained in skeleton_dir or /etc/skel will be created in the
+ user's home directory as well. The -k option is only valid in
+ conjunction with the -m option. The default is to not create
+ the directory and to not copy any files.
+
+ -s shell
+ The name of the user's login shell. The default is to leave
+ this field blank, which causes the system to select the default
+ login shell.
+
+ -u uid The numerical value of the user's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. The default is to use the smallest ID value greater
+ than 1000 and greater than every other user.
+
+ -P ends by invoking smbldap-passwd.pl
+
+ -A can change password ? 0 if no, 1 if yes
+
+ -B must change password ? 0 if no, 1 if yes
+
+ -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')
+
+ -D sambaHomeDrive (letter associated with home share, like 'H:')
+
+ -E sambaLogonScript, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+ -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+ -H sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+ -N canonical name (defaults to gecos or username, if gecos not set)
+
+ -S surname (defaults to username)
+
+
+=head1 SEE ALSO
+
+ useradd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-userdel.pl b/examples/LDAP/smbldap-tools/smbldap-userdel.pl
new file mode 100755
index 00000000000..f1e69e209c5
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-userdel.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-userdel : user (posix,shadow,samba) deletion
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('r?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-r?] username\n";
+ print " -r remove home directory\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+my $dn;
+# user must not exist in LDAP
+if (!defined($dn=get_user_dn($user))) {
+ print "$0: user $user does not exist\n";
+ exit (6);
+}
+
+if ($< != 0) {
+ print "You must be root to delete an user\n";
+ exit (1);
+}
+
+my $homedir;
+if (defined($Options{'r'})) {
+ $homedir=get_homedir($user);
+}
+
+# remove user from groups
+my $groups = find_groups_of $user;
+my @grplines = split(/\n/,$groups);
+
+my $grp;
+foreach $grp (@grplines) {
+ my $gname = "";
+ if ( $grp =~ /dn: cn=([^,]+),/) {
+ $gname = $1;
+ #print "xx $gname\n";
+ }
+ if ($gname ne "") {
+ group_remove_member($gname, $user);
+ }
+}
+
+# XXX
+delete_user($user);
+
+# delete dir -- be sure that homeDir is not a strange value
+if (defined($Options{'r'})) {
+ if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
+ system "rm -rf $homedir";
+ }
+}
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-userdel.pl - Delete a user account and related files
+
+=head1 SYNOPSIS
+
+ smbldap-userdel.pl [-r] login
+
+=head1 DESCRIPTION
+
+ The smbldap-userdel.pl command modifies the system
+ account files, deleting all entries that refer to login.
+ The named user must exist.
+
+ -r Files in the user's home directory will be removed along with
+ the home directory itself. Files located in other file
+ systems will have to be searched for and deleted manually.
+
+=head1 SEE ALSO
+
+ userdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usermod.pl b/examples/LDAP/smbldap-tools/smbldap-usermod.pl
new file mode 100755
index 00000000000..70151b74122
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-usermod.pl
@@ -0,0 +1,488 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-usermod : user (posix,shadow,samba) modification
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+
+use Getopt::Std;
+my %Options;
+my $nscd_status;
+
+my $ok = getopts('A:B:C:D:E:F:H:IJN:S:Pame:f:u:g:G:d:l:s:c:ok:?h', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) || ($Options{'h'}) ) {
+ print "Usage: $0 [-awmugdsckxABCDEFGHI?h] username\n";
+ print "Available options are:\n";
+ print " -c gecos\n";
+ print " -d home directory\n";
+ #print " -m move home directory\n";
+ #print " -f inactive days\n";
+ print " -u uid\n";
+ print " -o uid can be non unique\n";
+ print " -g gid\n";
+ print " -G supplementary groups (comma separated)\n";
+ print " -l login name\n";
+ print " -s shell\n";
+ print " -N canonical name\n";
+ print " -S surname\n";
+ print " -P ends by invoking smbldap-passwd.pl\n";
+ print " For samba users:\n";
+ print " -a add sambaSamAccount objectclass\n";
+ print " -e expire date (\"YYYY-MM-DD HH:MM:SS\")\n";
+ print " -A can change password ? 0 if no, 1 if yes\n";
+ print " -B must change password ? 0 if no, 1 if yes\n";
+ print " -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+ print " -D sambaHomeDrive (letter associated with home share, like 'H:')\n";
+ print " -E sambaLogonScript (DOS script to execute on login)\n";
+ print " -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
+ print " -H sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
+ print " -I disable an user. Can't be used with -H or -J\n";
+ print " -J enable an user. Can't be used with -H or -I\n";
+ print " -?|-h show this help message\n";
+ exit (1);
+}
+
+if ($< != 0) {
+ print "You must be root to modify an user\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+# Read user data
+my $user_entry = read_user_entry($user);
+if (!defined($user_entry)) {
+ print "$0: user $user doesn't exist\n";
+ exit (1);
+}
+
+my $samba = 0;
+if (grep ($_ =~ /^sambaSamAccount$/i, $user_entry->get_value('objectClass'))) {
+ $samba = 1;
+}
+
+# get the dn of the user
+my $dn= $user_entry->dn();
+
+my $tmp;
+my @mods;
+if (defined($tmp = $Options{'a'})) {
+ # Let's connect to the directory first
+ my $ldap_master=connect_ldap_master();
+ my $winmagic = 2147483647;
+ my $valpwdcanchange = 0;
+ my $valpwdmustchange = $winmagic;
+ my $valpwdlastset = 0;
+ my $valacctflags = "[UX]";
+ my $user_entry=read_user_entry($user);
+ my $uidNumber = $user_entry->get_value('uidNumber');
+ my $userRid = 2 * $uidNumber + 1000;
+ # apply changes
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ add => [objectClass => 'sambaSamAccount'],
+ add => [sambaPwdLastSet => "$valpwdlastset"],
+ add => [sambaLogonTime => '0'],
+ add => [sambaLogoffTime => '2147483647'],
+ add => [sambaKickoffTime => '2147483647'],
+ add => [sambaPwdCanChange => "$valpwdcanchange"],
+ add => [sambaPwdMustChange => "$valpwdmustchange"],
+ add => [displayName => "$_userGecos"],
+ add => [sambaSID=> "$SID-$userRid"],
+ add => [sambaAcctFlags => "$valacctflags"],
+ ]
+ );
+ $modify->code && warn "failed to modify entry: ", $modify->error ;
+}
+
+# Process options
+my $changed_uid;
+my $_userUidNumber;
+my $_userRid;
+if (defined($tmp = $Options{'u'})) {
+ if (defined($Options{'o'})) {
+ $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+ }
+
+ if (getpwuid($tmp)) {
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+
+ print "$0: uid number $tmp exists\n";
+ exit (6);
+ }
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+
+ }
+ push(@mods, 'uidNumber', $tmp);
+ $_userUidNumber = $tmp;
+ if ($samba) {
+ # as rid we use 2 * uid + 1000
+ my $_userRid = 2 * $_userUidNumber + 1000;
+ if (defined($Options{'x'})) {
+ $_userRid= sprint("%x", $_userRid);
+ }
+ push(@mods, 'sambaSID', $SID.'-'.$_userRid);
+ }
+ $changed_uid = 1;
+}
+
+my $changed_gid;
+my $_userGidNumber;
+my $_userGroupSID;
+if (defined($tmp = $Options{'g'})) {
+ $_userGidNumber = parse_group($tmp);
+ if ($_userGidNumber < 0) {
+ print "$0: group $tmp doesn't exist\n";
+ exit (6);
+ }
+ push(@mods, 'gidNumber', $_userGidNumber);
+ if ($samba) {
+ # as grouprid we use the sambaSID attribute's value of the group
+ my $group_entry = read_group_entry_gid($_userGidNumber);
+ my $_userGroupSID = $group_entry->get_value('sambaSID');
+ unless ($_userGroupSID) {
+ print "$0: unknown group SID not set for unix group $_userGidNumber\n";
+ exit (7);
+ }
+ push(@mods, 'sambaPrimaryGroupSid', $_userGroupSID);
+ }
+ $changed_gid = 1;
+}
+
+if (defined($tmp = $Options{'s'})) {
+ push(@mods, 'loginShell' => $tmp);
+}
+
+
+if (defined($tmp = $Options{'c'})) {
+ push(@mods, 'gecos' => $tmp,
+ 'description' => $tmp);
+ if ($samba == 1) {
+ push(@mods, 'displayName' => $tmp);
+ }
+}
+
+if (defined($tmp = $Options{'d'})) {
+ push(@mods, 'homeDirectory' => $tmp);
+}
+
+if (defined($tmp = $Options{'N'})) {
+ push(@mods, 'cn' => $tmp);
+}
+
+if (defined($tmp = $Options{'S'})) {
+ push(@mods, 'sn' => $tmp);
+}
+
+if (defined($tmp = $Options{'G'})) {
+
+ # remove user from old groups
+ my $groups = find_groups_of $user;
+ my @grplines = split(/\n/,$groups);
+
+ my $grp;
+ foreach $grp (@grplines) {
+ my $gname = "";
+ if ( $grp =~ /dn: cn=([^,]+),/) {
+ $gname = $1;
+ #print "xx $gname\n";
+ }
+ if ($gname ne "") {
+ group_remove_member($gname, $user);
+ }
+ }
+
+ # add user to new groups
+ add_grouplist_user($tmp, $user);
+}
+
+#
+# A : sambaPwdCanChange
+# B : sambaPwdMustChange
+# C : sambaHomePath
+# D : sambaHomeDrive
+# E : sambaLogonScript
+# F : sambaProfilePath
+# H : sambaAcctFlags
+
+my $attr;
+my $winmagic = 2147483647;
+
+$samba = is_samba_user($user);
+
+if (defined($tmp = $Options{'e'})) {
+ if ($samba == 1) {
+ my $kickoffTime=`date --date='$tmp' +%s`;
+ chomp($kickoffTime);
+ push(@mods, 'sambakickoffTime' => $kickoffTime);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+my $_sambaPwdCanChange;
+if (defined($tmp = $Options{'A'})) {
+ if ($samba == 1) {
+ $attr = "sambaPwdCanChange";
+ if ($tmp != 0) {
+ $_sambaPwdCanChange=0;
+ } else {
+ $_sambaPwdCanChange=$winmagic;
+ }
+ push(@mods, 'sambaPwdCanChange' => $_sambaPwdCanChange);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+my $_sambaPwdMustChange;
+if (defined($tmp = $Options{'B'})) {
+ if ($samba == 1) {
+ if ($tmp != 0) {
+ $_sambaPwdMustChange=0;
+ # To force a user to change his password:
+ # . the attribut sambaPwdLastSet must be != 0
+ # . the attribut sambaAcctFlags must not match the 'X' flag
+ my $_sambaAcctFlags;
+ my $flags = $user_entry->get_value('sambaAcctFlags');
+ if ( $flags =~ /X/ ) {
+ my $letters;
+ if ($flags =~ /(\w+)/) {
+ $letters = $1;
+ }
+ $letters =~ s/X//;
+ $_sambaAcctFlags="\[$letters\]";
+ push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
+ }
+ my $_sambaPwdLastSet = $user_entry->get_value('sambaPwdLastSet');
+ if ($_sambaPwdLastSet == 0) {
+ push(@mods, 'sambaPwdLastSet' => $winmagic);
+ }
+ } else {
+ $_sambaPwdMustChange=$winmagic;
+ }
+ push(@mods, 'sambaPwdMustChange' => $_sambaPwdMustChange);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+if (defined($tmp = $Options{'C'})) {
+ if ($samba == 1) {
+ #$tmp =~ s/\\/\\\\/g;
+ push(@mods, 'sambaHomePath' => $tmp);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+my $_sambaHomeDrive;
+if (defined($tmp = $Options{'D'})) {
+ if ($samba == 1) {
+ $tmp = $tmp.":" unless ($tmp =~ /:/);
+ push(@mods, 'sambaHomeDrive' => $tmp);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+if (defined($tmp = $Options{'E'})) {
+ if ($samba == 1) {
+ #$tmp =~ s/\\/\\\\/g;
+ push(@mods, 'sambaLogonScript' => $tmp);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+if (defined($tmp = $Options{'F'})) {
+ if ($samba == 1) {
+ #$tmp =~ s/\\/\\\\/g;
+ push(@mods, 'sambaProfilePath' => $tmp);
+ } else {
+ print "User $user is not a samba user\n";
+ }
+}
+
+if ($samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
+ my $_sambaAcctFlags;
+ if (defined($tmp = $Options{'H'})) {
+ #$tmp =~ s/\\/\\\\/g;
+ $_sambaAcctFlags=$tmp;
+ } else {
+ # I or J
+ my $flags;
+ $flags = $user_entry->get_value('sambaAcctFlags');
+
+ if (defined($tmp = $Options{'I'})) {
+ if ( !($flags =~ /D/) ) {
+ my $letters;
+ if ($flags =~ /(\w+)/) {
+ $letters = $1;
+ }
+ $_sambaAcctFlags="\[D$letters\]";
+ }
+ } elsif (defined($tmp = $Options{'J'})) {
+ if ( $flags =~ /D/ ) {
+ my $letters;
+ if ($flags =~ /(\w+)/) {
+ $letters = $1;
+ }
+ $letters =~ s/D//;
+ $_sambaAcctFlags="\[$letters\]";
+ }
+ }
+ }
+
+
+ if ("$_sambaAcctFlags" ne '') {
+ push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
+ }
+
+} elsif (!$samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
+ print "User $user is not a samba user\n";
+}
+
+# Let's connect to the directory first
+my $ldap_master=connect_ldap_master();
+
+# apply changes
+my $modify = $ldap_master->modify ( "$dn",
+ 'replace' => { @mods }
+ );
+$modify->code && warn "failed to modify entry: ", $modify->error ;
+
+# take down session
+$ldap_master->unbind;
+
+$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+if (defined($Options{'P'})) {
+ exec "/usr/local/sbin/smbldap-passwd.pl $user"
+}
+
+
+############################################################
+
+=head1 NAME
+
+smbldap-usermod.pl - Modify a user account
+
+=head1 SYNOPSIS
+
+smbldap-usermod.pl [-c comment] [-d home_dir]
+ [-g initial_group] [-G group[,...]]
+ [-l login_name] [-p passwd]
+ [-s shell] [-u uid [ -o]] [-x]
+ [-A canchange] [-B mustchange] [-C smbhome]
+ [-D homedrive] [-E scriptpath] [-F profilepath]
+ [-H acctflags] login
+
+=head1 DESCRIPTION
+
+The smbldap-usermod.pl command modifies the system account files
+ to reflect the changes that are specified on the command line.
+ The options which apply to the usermod command are
+
+ -c comment
+ The new value of the user's comment field (gecos).
+
+ -d home_dir
+ The user's new login directory.
+
+ -g initial_group
+ The group name or number of the user's new initial login group.
+ The group name must exist. A group number must refer to an
+ already existing group. The default group number is 1.
+
+ -G group,[...]
+ A list of supplementary groups which the user is also a member
+ of. Each group is separated from the next by a comma, with no
+ intervening whitespace. The groups are subject to the same
+ restrictions as the group given with the -g option. If the user
+ is currently a member of a group which is not listed, the user
+ will be removed from the group
+
+ -l login_name
+ The name of the user will be changed from login to login_name.
+ Nothing else is changed. In particular, the user's home direc
+ tory name should probably be changed to reflect the new login
+ name.
+
+ -s shell
+ The name of the user's new login shell. Setting this field to
+ blank causes the system to select the default login shell.
+
+ -u uid The numerical value of the user's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. Any files which the user owns and which are
+ located in the directory tree rooted at the user's home direc
+ tory will have the file user ID changed automatically. Files
+ outside of the user's home directory must be altered manually.
+
+ -x Creates rid and primaryGroupID in hex instead of decimal (for
+ Samba 2.2.2 unpatched only - higher versions always use decimal)
+
+ -A can change password ? 0 if no, 1 if yes
+
+ -B must change password ? 0 if no, 1 if yes
+
+ -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')
+
+ -D sambaHomeDrive (letter associated with home share, like 'H:')
+
+ -E sambaLogonScript, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+ -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+ -H sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+ -I disable user. Can't be used with -H or -J
+
+ -J enable user. Can't be used with -H or -I
+
+=head1 SEE ALSO
+
+ usermod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usershow.pl b/examples/LDAP/smbldap-tools/smbldap-usershow.pl
new file mode 100755
index 00000000000..173480d76c2
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-usershow.pl
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose of smbldap-userdisplay : user (posix,shadow,samba) display
+
+use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-?] username\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+my $lines = read_user($user);
+if (!defined($lines)) {
+ print "$0: user $user doesn't exist\n";
+ exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-usershow.pl - Show a user account informations
+
+=head1 SYNOPSIS
+
+ smbldap-usershow.pl login
+
+=head1 DESCRIPTION
+
+ The smbldap-usershow.pl command displays the informations
+ associated with the login. The named user must exist.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap_conf.pm b/examples/LDAP/smbldap-tools/smbldap_conf.pm
new file mode 100644
index 00000000000..257c205a2cd
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap_conf.pm
@@ -0,0 +1,248 @@
+#!/usr/bin/perl
+use strict;
+package smbldap_conf;
+
+# smbldap-tools.conf : Q & D configuration file for smbldap-tools
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# Purpose :
+# . be the configuration file for all smbldap-tools scripts
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
+ $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+ $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
+ $ldap_path $ldap_opts $ldapmodify $suffix $usersdn $computersdn
+ $groupsdn $scope $binddn $bindpasswd
+ $slaveDN $slavePw $masterDN $masterPw
+ $_userLoginShell $_userHomePrefix $_userGecos
+ $_defaultUserGid $_defaultComputerGid
+ $_skeletonDir $_userSmbHome
+ $_userProfile $_userHomeDrive
+ $_userScript $usersou $computersou $groupsou $SID $hash_encrypt $_defaultMaxPasswordAge
+ );
+
+use Exporter;
+$VERSION = 1.00;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+ $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
+ $ldap_path $ldap_opts $ldapmodify $suffix $usersdn
+ $computersdn $groupsdn $scope $binddn $bindpasswd
+ $slaveDN $slavePw $masterDN $masterPw
+ $_userLoginShell $_userHomePrefix $_userGecos
+ $_defaultUserGid $_defaultComputerGid $_skeletonDir
+ $_userSmbHome $_userProfile $_userHomeDrive $_userScript
+ $usersou $computersou $groupsou $SID $hash_encrypt $_defaultMaxPasswordAge
+ );
+
+
+##############################################################################
+#
+# General Configuration
+#
+##############################################################################
+
+# UID and GID starting at...
+$UID_START = 1000;
+$GID_START = 1000;
+
+# Put your own SID
+# to obtain this number do: "net getlocalsid"
+$SID='S-1-5-21-3516781642-1962875130-3438800523';
+
+##############################################################################
+#
+# LDAP Configuration
+#
+##############################################################################
+
+# Notes: to use to dual ldap servers backend for Samba, you must patch
+# Samba with the dual-head patch from IDEALX. If not using this patch
+# just use the same server for slaveLDAP and masterLDAP.
+# Those two servers declarations can also be used when you have
+# . one master LDAP server where all writing operations must be done
+# . one slave LDAP server where all reading operations must be done
+# (typically a replication directory)
+
+# Ex: $slaveLDAP = "127.0.0.1";
+$slaveLDAP = "127.0.0.1";
+$slavePort = "389";
+
+# Master LDAP : needed for write operations
+# Ex: $masterLDAP = "127.0.0.1";
+$masterLDAP = "127.0.0.1";
+$masterPort = "389";
+
+# Use SSL for LDAP
+# If set to "1", this option will use start_tls for connection
+# (you should also used the port 389)
+$ldapSSL = "0";
+
+# LDAP Suffix
+# Ex: $suffix = "dc=IDEALX,dc=ORG";
+$suffix = "dc=IDEALX,dc=COM";
+
+
+# Where are stored Users
+# Ex: $usersdn = "ou=Users,$suffix"; for ou=Users,dc=IDEALX,dc=ORG
+$usersou = q(_USERS_);
+$usersdn = "ou=$usersou,$suffix";
+
+# Where are stored Computers
+# Ex: $computersdn = "ou=Computers,$suffix"; for ou=Computers,dc=IDEALX,dc=ORG
+$computersou = q(_COMPUTERS_);
+$computersdn = "ou=$computersou,$suffix";
+
+# Where are stored Groups
+# Ex $groupsdn = "ou=Groups,$suffix"; for ou=Groups,dc=IDEALX,dc=ORG
+$groupsou = q(_GROUPS_);
+$groupsdn = "ou=$groupsou,$suffix";
+
+# Default scope Used
+$scope = "sub";
+
+# Unix password encryption (CRYPT, MD5, SMD5, SSHA, SHA)
+$hash_encrypt="SSHA";
+
+############################
+# Credential Configuration #
+############################
+# Bind DN used
+# Ex: $binddn = "cn=Manager,$suffix"; for cn=Manager,dc=IDEALX,dc=org
+$binddn = "cn=Manager,$suffix";
+
+# Bind DN passwd used
+# Ex: $bindpasswd = 'secret'; for 'secret'
+$bindpasswd = "secret";
+
+# Notes: if using dual ldap patch, you can specify to different configuration
+# By default, we will use the same DN (so it will work for standard Samba
+# release)
+$slaveDN = $binddn;
+$slavePw = $bindpasswd;
+$masterDN = $binddn;
+$masterPw = $bindpasswd;
+
+##############################################################################
+#
+# Unix Accounts Configuration
+#
+##############################################################################
+
+# Login defs
+# Default Login Shell
+# Ex: $_userLoginShell = q(/bin/bash);
+$_userLoginShell = q(_LOGINSHELL_);
+
+# Home directory prefix (without username)
+# Ex: $_userHomePrefix = q(/home/);
+$_userHomePrefix = q(_HOMEPREFIX_);
+
+# Gecos
+$_userGecos = q(System User);
+
+# Default User (POSIX and Samba) GID
+$_defaultUserGid = 513;
+
+# Default Computer (Samba) GID
+$_defaultComputerGid = 553;
+
+# Skel dir
+$_skeletonDir = q(/etc/skel);
+
+# Default password validation time (time in days) Comment the next line if
+# you don't want password to be enable for $_defaultMaxPasswordAge days (be
+# careful to the sambaPwdMustChange attribute's value)
+$_defaultMaxPasswordAge = 45;
+
+##############################################################################
+#
+# SAMBA Configuration
+#
+##############################################################################
+
+# The UNC path to home drives location without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\homes) for \\My-PDC-netbios-name\homes
+# Just comment this if you want to use the smb.conf 'logon home' directive
+# and/or desabling roaming profiles
+$_userSmbHome = q(\\\\_PDCNAME_\\homes);
+
+# The UNC path to profiles locations without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\profiles\\) for \\My-PDC-netbios-name\profiles
+# Just comment this if you want to use the smb.conf 'logon path' directive
+# and/or desabling roaming profiles
+$_userProfile = q(\\\\_PDCNAME_\\profiles\\);
+
+# The default Home Drive Letter mapping
+# (will be automatically mapped at logon time if home directory exist)
+# Ex: q(U:) for U:
+$_userHomeDrive = q(_HOMEDRIVE_);
+
+# The default user netlogon script name
+# if not used, will be automatically username.cmd
+# $_userScript = q(startup.cmd); # make sure script file is edited under dos
+
+
+##############################################################################
+#
+# SMBLDAP-TOOLS Configuration (default are ok for a RedHat)
+#
+##############################################################################
+
+# Allows not to use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm) but
+# prefer mkntpwd... most of the time, it's a wise choice :-)
+$with_smbpasswd = 0;
+$smbpasswd = "/usr/bin/smbpasswd";
+$mk_ntpasswd = "/usr/local/sbin/mkntpwd";
+
+# those next externals commands are kept fot the migration scripts and
+# for the populate script: this will be updated as soon as possible
+$slaveURI = "ldap://$slaveLDAP:$slavePort";
+$masterURI = "ldap://$masterLDAP:$masterPort";
+
+$ldap_path = "/usr/bin";
+
+if ( $ldapSSL eq "0" ) {
+ $ldap_opts = "-x";
+} elsif ( $ldapSSL eq "1" ) {
+ $ldap_opts = "-x -Z";
+} else {
+ die "ldapSSL option must be either 0 or 1.\n";
+}
+
+#$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI -D '$slaveDN' -w '$slavePw'";
+#$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI";
+$ldapmodify = "$ldap_path/ldapmodify $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapadd = "$ldap_path/ldapadd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+
+
+
+1;
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap_tools.pm b/examples/LDAP/smbldap-tools/smbldap_tools.pm
new file mode 100755
index 00000000000..d33a65b7d17
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap_tools.pm
@@ -0,0 +1,771 @@
+#! /usr/bin/perl -w
+use strict;
+package smbldap_tools;
+use smbldap_conf;
+use Net::LDAP;
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+
+# ugly funcs using global variables and spawning openldap clients
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+use Exporter;
+$VERSION = 1.00;
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ get_user_dn
+ get_group_dn
+ is_group_member
+ is_samba_user
+ is_unix_user
+ is_user_valid
+ does_sid_exist
+ get_dn_from_line
+ add_posix_machine
+ add_samba_machine
+ add_samba_machine_mkntpwd
+ group_add_user
+ add_grouplist_user
+ disable_user
+ delete_user
+ group_add
+ group_del
+ get_homedir
+ read_user
+ read_user_entry
+ read_group
+ read_group_entry
+ read_group_entry_gid
+ find_groups_of
+ parse_group
+ group_remove_member
+ group_get_members
+ do_ldapadd
+ do_ldapmodify
+ get_user_dn2
+ connect_ldap_master
+ connect_ldap_slave
+ group_type_by_name
+ );
+
+sub connect_ldap_master
+ {
+ # bind to a directory with dn and password
+ my $ldap_master = Net::LDAP->new(
+ "$masterLDAP",
+ port => "$masterPort",
+ version => 3,
+ # debug => 0xffff,
+ )
+ or die "erreur LDAP: Can't contact master ldap server ($@)";
+ if ($ldapSSL == 1) {
+ $ldap_master->start_tls(
+ # verify => 'require',
+ # clientcert => 'mycert.pem',
+ # clientkey => 'mykey.pem',
+ # decryptkey => sub { 'secret'; },
+ # capath => '/usr/local/cacerts/'
+ );
+ }
+ $ldap_master->bind ( "$binddn",
+ password => "$masterPw"
+ );
+ return($ldap_master);
+ }
+
+sub connect_ldap_slave
+ {
+ # bind to a directory with dn and password
+ my $ldap_slave = Net::LDAP->new(
+ "$slaveLDAP",
+ port => "$slavePort",
+ version => 3,
+ # debug => 0xffff,
+ )
+ or die "erreur LDAP: Can't contact slave ldap server ($@)";
+ if ($ldapSSL == 1) {
+ $ldap_slave->start_tls(
+ # verify => 'require',
+ # clientcert => 'mycert.pem',
+ # clientkey => 'mykey.pem',
+ # decryptkey => sub { 'secret'; },
+ # capath => '/usr/local/cacerts/'
+ );
+ }
+ $ldap_slave->bind ( "$binddn",
+ password => "$slavePw"
+ );
+ return($ldap_slave);
+ }
+
+sub get_user_dn
+ {
+ my $user = shift;
+ my $dn='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $suffix,
+ scope => $scope,
+ filter => "(&(objectclass=posixAccount)(uid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ $dn= $entry->dn;
+ }
+ $ldap_slave->unbind;
+ chomp($dn);
+ if ($dn eq '') {
+ return undef;
+ }
+ $dn="dn: ".$dn;
+ return $dn;
+ }
+
+
+sub get_user_dn2
+ {
+ my $user = shift;
+ my $dn='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $suffix,
+ scope => $scope,
+ filter => "(&(objectclass=posixAccount)(uid=$user))"
+ );
+ $mesg->code && warn "failed to perform search; ", $mesg->error;
+
+ foreach my $entry ($mesg->all_entries) {
+ $dn= $entry->dn;
+ }
+ $ldap_slave->unbind;
+ chomp($dn);
+ if ($dn eq '') {
+ return (1,undef);
+ }
+ $dn="dn: ".$dn;
+ return (1,$dn);
+ }
+
+
+sub get_group_dn
+ {
+ my $group = shift;
+ my $dn='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
+ );
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ $dn= $entry->dn;
+ }
+ $ldap_slave->unbind;
+ chomp($dn);
+ if ($dn eq '') {
+ return undef;
+ }
+ $dn="dn: ".$dn;
+ return $dn;
+ }
+
+# return (success, dn)
+# bool = is_samba_user($username)
+sub is_samba_user
+ {
+ my $user = shift;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $suffix,
+ scope => $scope,
+ filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ $ldap_slave->unbind;
+ return ($mesg->count ne 0);
+ }
+
+sub is_unix_user
+ {
+ my $user = shift;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $suffix,
+ scope => $scope,
+ filter => "(&(objectClass=posixAccount)(uid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ $ldap_slave->unbind;
+ return ($mesg->count ne 0);
+ }
+
+sub is_group_member
+ {
+ my $dn_group = shift;
+ my $user = shift;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $dn_group,
+ scope => 'base',
+ filter => "(&(memberUid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ $ldap_slave->unbind;
+ return ($mesg->count ne 0);
+ }
+
+# all entries = does_sid_exist($sid,$scope)
+sub does_sid_exist
+ {
+ my $sid = shift;
+ my $dn_group=shift;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( base => $dn_group,
+ scope => $scope,
+ filter => "(sambaSID=$sid)"
+ #filter => "(&(objectClass=sambaSamAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))"
+ );
+ $mesg->code && die $mesg->error;
+ $ldap_slave->unbind;
+ return ($mesg);
+ }
+
+# try to bind with user dn and password to validate current password
+sub is_user_valid
+ {
+ my ($user, $dn, $pass) = @_;
+ my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+ my $mesg= $ldap->bind (dn => $dn, password => $pass );
+ if ($mesg->code eq 0) {
+ $ldap->unbind;
+ return 1;
+ } else {
+ if ($ldap->bind()) {
+ $ldap->unbind;
+ return 0;
+ } else {
+ print ("The LDAP directory is not available.\n Check the server, cables ...");
+ $ldap->unbind;
+ return 0;
+ }
+ die "Problem : contact your administrator";
+ }
+ }
+
+
+# dn = get_dn_from_line ($dn_line)
+# helper to get "a=b,c=d" from "dn: a=b,c=d"
+sub get_dn_from_line
+ {
+ my $dn = shift;
+ $dn =~ s/^dn: //;
+ return $dn;
+ }
+
+
+# success = add_posix_machine($user, $uid, $gid)
+sub add_posix_machine
+ {
+ my ($user, $uid, $gid) = @_;
+ # bind to a directory with dn and password
+ my $ldap_master=connect_ldap_master();
+ my $add = $ldap_master->add ( "uid=$user,$computersdn",
+ attr => [
+ 'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
+ 'cn' => "$user",
+ 'sn' => "$user",
+ 'uid' => "$user",
+ 'uidNumber' => "$uid",
+ 'gidNumber' => "$gid",
+ 'homeDirectory' => '/dev/null',
+ 'loginShell' => '/bin/false',
+ 'description' => 'Computer',
+ ]
+ );
+
+ $add->code && warn "failed to add entry: ", $add->error ;
+ # take down the session
+ $ldap_master->unbind;
+
+ }
+
+
+# success = add_samba_machine($computername)
+sub add_samba_machine
+ {
+ my $user = shift;
+ system "smbpasswd -a -m $user";
+ return 1;
+ }
+
+sub add_samba_machine_mkntpwd
+ {
+ my ($user, $uid) = @_;
+ my $sambaSID = 2 * $uid + 1000;
+ my $name = $user;
+ $name =~ s/.$//s;
+
+ if ($mk_ntpasswd eq '') {
+ print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
+ return 0;
+ }
+
+ my $ntpwd = `$mk_ntpasswd '$name'`;
+ chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
+ chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
+
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ( "uid=$user,$computersdn",
+ changes => [
+ replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSamAccount']],
+ add => [sambaPwdLastSet => '0'],
+ add => [sambaLogonTime => '0'],
+ add => [sambaLogoffTime => '2147483647'],
+ add => [sambaKickoffTime => '2147483647'],
+ add => [sambaPwdCanChange => '0'],
+ add => [sambaPwdMustChange => '0'],
+ add => [sambaAcctFlags => '[W ]'],
+ add => [sambaLMPassword => "$lmpassword"],
+ add => [sambaNTPassword => "$ntpassword"],
+ add => [sambaSID => "$SID-$sambaSID"],
+ add => [sambaPrimaryGroupSID => "$SID-0"]
+ ]
+ );
+
+ $modify->code && die "failed to add entry: ", $modify->error ;
+
+ return 1;
+ # take down the session
+ $ldap_master->unbind;
+
+ }
+
+
+sub group_add_user
+ {
+ my ($group, $userid) = @_;
+ my $members='';
+ my $dn_line = get_group_dn($group);
+ if (!defined(get_group_dn($group))) {
+ print "$0: group \"$group\" doesn't exist\n";
+ exit (6);
+ }
+ if (!defined($dn_line)) {
+ return 1;
+ }
+ my $dn = get_dn_from_line("$dn_line");
+ # on look if the user is already present in the group
+ my $is_member=is_group_member($dn,$userid);
+ if ($is_member == 1) {
+ print "User \"$userid\" already member of the group \"$group\".\n";
+ } else {
+ # bind to a directory with dn and password
+ my $ldap_master=connect_ldap_master();
+ # It does not matter if the user already exist, Net::LDAP will add the user
+ # if he does not exist, and ignore him if his already in the directory.
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ add => [memberUid => $userid]
+ ]
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind;
+ }
+ }
+
+sub group_del
+ {
+ my $group_dn=shift;
+ # bind to a directory with dn and password
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->delete ($group_dn);
+ $modify->code && die "failed to delete group : ", $modify->error ;
+ # take down session
+ $ldap_master->unbind;
+ }
+
+sub add_grouplist_user
+ {
+ my ($grouplist, $user) = @_;
+ my @array = split(/,/, $grouplist);
+ foreach my $group (@array) {
+ group_add_user($group, $user);
+ }
+ }
+
+sub disable_user
+ {
+ my $user = shift;
+ my $dn_line;
+ my $dn = get_dn_from_line($dn_line);
+
+ if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+ }
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ replace => [userPassword => '{crypt}!x']
+ ]
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+
+ if (is_samba_user($user)) {
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ replace => [sambaAcctFlags => '[D ]']
+ ]
+ );
+ $modify->code && die "failed to modify entry: ", $modify->error ;
+ }
+ # take down session
+ $ldap_master->unbind;
+ }
+
+# delete_user($user)
+sub delete_user
+ {
+ my $user = shift;
+ my $dn_line;
+
+ if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+ }
+
+ my $dn = get_dn_from_line($dn_line);
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->delete($dn);
+ $ldap_master->unbind;
+ }
+
+# $gid = group_add($groupname, $group_gid, $force_using_existing_gid)
+sub group_add
+ {
+ my ($gname, $gid, $force) = @_;
+ my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+ }
+ if (!defined($gid)) {
+ while (defined(getgrgid($GID_START))) {
+ $GID_START++;
+ }
+ $gid = $GID_START;
+ } else {
+ if (!defined($force)) {
+ if (defined(getgrgid($gid))) {
+ return undef;
+ }
+ }
+ }
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+ my $ldap_master=connect_ldap_master();
+ my $modify = $ldap_master->add ( "cn=$gname,$groupsdn",
+ attrs => [
+ objectClass => 'posixGroup',
+ cn => "$gname",
+ gidNumber => "$gid"
+ ]
+ );
+
+ $modify->code && die "failed to add entry: ", $modify->error ;
+ # take down session
+ $ldap_master->unbind;
+ return $gid;
+ }
+
+# $homedir = get_homedir ($user)
+sub get_homedir
+ {
+ my $user = shift;
+ my $homeDir='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search (
+ base =>$suffix,
+ scope => $scope,
+ filter => "(&(objectclass=posixAccount)(uid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ foreach my $attr ($entry->attributes) {
+ if ($attr=~/\bhomeDirectory\b/) {
+ foreach my $ent ($entry->get_value($attr)) {
+ $homeDir.= $attr.": ".$ent."\n";
+ }
+ }
+ }
+ }
+ $ldap_slave->unbind;
+ chomp $homeDir;
+ if ($homeDir eq '') {
+ return undef;
+ }
+ $homeDir =~ s/^homeDirectory: //;
+ return $homeDir;
+ }
+
+# search for an user
+sub read_user
+ {
+ my $user = shift;
+ my $lines ='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $suffix,
+ scope => $scope,
+ filter => "(&(objectclass=posixAccount)(uid=$user))"
+ );
+
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ $lines.= "dn: " . $entry->dn."\n";
+ foreach my $attr ($entry->attributes) {
+ {
+ $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
+ }
+ }
+ }
+ # take down session
+ $ldap_slave->unbind;
+ chomp $lines;
+ if ($lines eq '') {
+ return undef;
+ }
+ return $lines;
+ }
+
+# search for a user
+# return the attributes in an array
+sub read_user_entry
+ {
+ my $user = shift;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $suffix,
+ scope => $scope,
+ filter => "(&(objectclass=posixAccount)(uid=$user))"
+ );
+
+ $mesg->code && die $mesg->error;
+ my $entry = $mesg->entry();
+ $ldap_slave->unbind;
+ return $entry;
+ }
+
+# search for a group
+sub read_group
+ {
+ my $user = shift;
+ my $lines ='';
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixGroup)(cn=$user))"
+ );
+
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ $lines.= "dn: " . $entry->dn."\n";
+ foreach my $attr ($entry->attributes) {
+ {
+ $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
+ }
+ }
+ }
+ # take down session
+ $ldap_slave->unbind;
+ chomp $lines;
+ if ($lines eq '') {
+ return undef;
+ }
+ return $lines;
+ }
+
+# find groups of a given user
+##### MODIFIE ########
+sub find_groups_of
+ {
+ my $user = shift;
+ my $lines ='';
+ my $ldap_slave=connect_ldap_slave;
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixGroup)(memberuid=$user))"
+ );
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ $lines.= "dn: ".$entry->dn."\n";
+ }
+ $ldap_slave->unbind;
+ chomp($lines);
+ if ($lines eq '') {
+ return undef;
+ }
+ return $lines;
+ }
+
+sub read_group_entry {
+ my $group = shift;
+ my $entry;
+ my %res;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixGroup)(cn=$group))"
+ );
+
+ $mesg->code && die $mesg->error;
+ my $nb=$mesg->count;
+ if ($nb > 1) {
+ print "Error: $nb groups exist \"cn=$group\"\n";
+ foreach $entry ($mesg->all_entries) { my $dn=$entry->dn; print " $dn\n"; }
+ exit 11;
+ } else {
+ $entry = $mesg->shift_entry();
+ }
+ return $entry;
+}
+
+sub read_group_entry_gid {
+ my $group = shift;
+ my %res;
+ my $ldap_slave=connect_ldap_slave();
+ my $mesg = $ldap_slave->search ( # perform a search
+ base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixGroup)(gidNumber=$group))"
+ );
+
+ $mesg->code && die $mesg->error;
+ my $entry = $mesg->shift_entry();
+ return $entry;
+}
+
+# return the gidnumber for a group given as name or gid
+# -1 : bad group name
+# -2 : bad gidnumber
+sub parse_group
+ {
+ my $userGidNumber = shift;
+ if ($userGidNumber =~ /[^\d]/ ) {
+ my $gname = $userGidNumber;
+ my $gidnum = getgrnam($gname);
+ if ($gidnum !~ /\d+/) {
+ return -1;
+ } else {
+ $userGidNumber = $gidnum;
+ }
+ } elsif (!defined(getgrgid($userGidNumber))) {
+ return -2;
+ }
+ return $userGidNumber;
+ }
+
+# remove $user from $group
+sub group_remove_member
+ {
+ my ($group, $user) = @_;
+ my $members='';
+ my $grp_line = get_group_dn($group);
+ if (!defined($grp_line)) {
+ return 0;
+ }
+ my $dn = get_dn_from_line($grp_line);
+ # we test if the user exist in the group
+ my $is_member=is_group_member($dn,$user);
+ if ($is_member == 1) {
+ my $ldap_master=connect_ldap_master();
+ # delete only the user from the group
+ my $modify = $ldap_master->modify ( "$dn",
+ changes => [
+ delete => [memberUid => ["$user"]]
+ ]
+ );
+ $modify->code && die "failed to delete entry: ", $modify->error ;
+ $ldap_master->unbind;
+ }
+ return 1;
+ }
+
+sub group_get_members
+ {
+ my ($group) = @_;
+ my $members;
+ my @resultat;
+ my $grp_line = get_group_dn($group);
+ if (!defined($grp_line)) {
+ return 0;
+ }
+
+ my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+ $ldap->bind ;
+ my $mesg = $ldap->search (
+ base => $groupsdn,
+ scope => $scope,
+ filter => "(&(objectclass=posixgroup)(cn=$group))"
+ );
+ $mesg->code && die $mesg->error;
+ foreach my $entry ($mesg->all_entries) {
+ foreach my $attr ($entry->attributes) {
+ if ($attr=~/\bmemberUid\b/) {
+ foreach my $ent ($entry->get_value($attr)) {
+ push (@resultat,$ent);
+ }
+ }
+ }
+ }
+ return @resultat;
+ }
+
+sub do_ldapmodify
+ {
+ my $ldif = shift;
+ my $FILE = "|$ldapmodify -r >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+$ldif
+EOF
+ ;
+ close FILE;
+ my $rc = $?;
+ return $rc;
+ }
+
+sub group_type_by_name {
+ my $type_name = shift;
+ my %groupmap = (
+ 'domain' => 2,
+ 'local' => 4,
+ 'builtin' => 5
+ );
+ return $groupmap{$type_name};
+}
+
+
+
+1;
+
diff --git a/examples/README b/examples/README
new file mode 100644
index 00000000000..22226067140
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,11 @@
+Copyright(C) Samba-Team 1993-2001
+
+This directory contains example config files and related material for
+Samba.
+
+At a minimum please refer to the smb.conf.default file for current
+information regarding global and share parameter settings.
+
+Send additions to: samba@samba.org
+
+
diff --git a/examples/VFS/.cvsignore b/examples/VFS/.cvsignore
new file mode 100644
index 00000000000..f269c98273c
--- /dev/null
+++ b/examples/VFS/.cvsignore
@@ -0,0 +1,9 @@
+.libs
+*.so
+*.o
+*.bak
+autom4te.cache
+autom4te-2.53.cache
+Makefile
+configure
+config.*
diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in
new file mode 100644
index 00000000000..c368974bd5e
--- /dev/null
+++ b/examples/VFS/Makefile.in
@@ -0,0 +1,43 @@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LDSHFLAGS = @LDSHFLAGS@
+INSTALLCMD = @INSTALL@
+SAMBA_SOURCE = @SAMBA_SOURCE@
+SHLIBEXT = @SHLIBEXT@
+OBJEXT = @OBJEXT@
+FLAGS = $(CFLAGS) -Iinclude -I$(SAMBA_SOURCE)/include -I$(SAMBA_SOURCE)/ubiqx -I$(SAMBA_SOURCE)/smbwrapper -I. $(CPPFLAGS) -I$(SAMBA_SOURCE)
+
+
+prefix = @prefix@
+libdir = @libdir@
+
+VFS_LIBDIR = $(libdir)/vfs
+
+# Auto target
+default: $(patsubst %.c,%.$(SHLIBEXT),$(wildcard *.c))
+
+# Pattern rules
+
+%.$(SHLIBEXT): %.$(OBJEXT)
+ @echo "Linking $@"
+ @$(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $<
+
+%.$(OBJEXT): %.c
+ @echo "Compiling $<"
+ @$(CC) $(FLAGS) -c $<
+
+
+install: default
+ $(INSTALLCMD) -d $(VFS_LIBDIR)
+ $(INSTALLCMD) -m 755 *.$(SHLIBEXT) $(VFS_LIBDIR)
+
+# Misc targets
+clean:
+ rm -rf .libs
+ rm -f core *~ *% *.bak *.o *.$(SHLIBEXT)
+
+distclean: clean
+ rm config.* Makefile
+
diff --git a/examples/VFS/README b/examples/VFS/README
new file mode 100644
index 00000000000..2f6196d1178
--- /dev/null
+++ b/examples/VFS/README
@@ -0,0 +1,20 @@
+README for Samba Virtual File System (VFS) Example
+===================================================
+
+This directory contains skeleton VFS modules. When used,
+this module simply passes all requests back to the disk functions
+(i.e it operates as a passthrough filter). It should be
+useful as a starting point for developing new VFS
+modules.
+
+Please look at skel_opaque.c when you want your module to provide
+final functions, like a database filesystem.
+
+Please look at skel_transport.c when you want your module to provide
+passthrough functions, like audit modules.
+
+Please read the VFS chapter in the HOWTO collection for general help
+on the usage of VFS modules.
+
+Further documentation on writing VFS modules for Samba can be found in
+Samba Developers Guide.
diff --git a/examples/VFS/autogen.sh b/examples/VFS/autogen.sh
new file mode 100755
index 00000000000..fcae16ec5c8
--- /dev/null
+++ b/examples/VFS/autogen.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# Run this script to build samba from CVS.
+
+## insert all possible names (only works with
+## autoconf 2.x
+#TESTAUTOHEADER="autoheader autoheader-2.53"
+TESTAUTOCONF="autoconf autoconf-2.53"
+
+#AUTOHEADERFOUND="0"
+AUTOCONFFOUND="0"
+
+
+##
+## Look for autoheader
+##
+#for i in $TESTAUTOHEADER; do
+# if which $i > /dev/null 2>&1; then
+# if [ `$i --version | head -n 1 | cut -d. -f 2` -ge 53 ]; then
+# AUTOHEADER=$i
+# AUTOHEADERFOUND="1"
+# break
+# fi
+# fi
+#done
+
+##
+## Look for autoconf
+##
+
+for i in $TESTAUTOCONF; do
+ if which $i > /dev/null 2>&1; then
+ if [ `$i --version | head -n 1 | cut -d. -f 2` -ge 53 ]; then
+ AUTOCONF=$i
+ AUTOCONFFOUND="1"
+ break
+ fi
+ fi
+done
+
+
+##
+## do we have it?
+##
+if [ "$AUTOCONFFOUND" = "0" -o "$AUTOHEADERFOUND" = "0" ]; then
+ echo "$0: need autoconf 2.53 or later to build samba from CVS" >&2
+ exit 1
+fi
+
+
+
+#echo "$0: running $AUTOHEADER"
+#$AUTOHEADER || exit 1
+
+echo "$0: running $AUTOCONF"
+$AUTOCONF || exit 1
+
+echo "Now run ./configure and then make."
+exit 0
+
diff --git a/examples/VFS/configure.in b/examples/VFS/configure.in
new file mode 100644
index 00000000000..fda4cf3a316
--- /dev/null
+++ b/examples/VFS/configure.in
@@ -0,0 +1,350 @@
+dnl -*- mode: m4-mode -*-
+dnl Process this file with autoconf to produce a configure script.
+
+dnl We must use autotools 2.53 or above
+AC_PREREQ(2.53)
+AC_INIT(Makefile.in)
+
+#dnl Uncomment this if you want to use your own define's too
+#AC_CONFIG_HEADER(module_config.h)
+#dnl To make sure that didn't get #define PACKAGE_* in modules_config.h
+#echo "" > confdefs.h
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+
+#################################################
+# Directory handling stuff to support both the
+# legacy SAMBA directories and FHS compliant
+# ones...
+AC_PREFIX_DEFAULT(/usr/local/samba)
+
+AC_ARG_WITH(fhs,
+[ --with-fhs Use FHS-compliant paths (default=no)],
+ libdir="\${prefix}/lib/samba",
+ libdir="\${prefix}/lib")
+
+AC_SUBST(libdir)
+
+SAMBA_SOURCE="../../source"
+####################################################
+# set the location location of the samba source tree
+AC_ARG_WITH(samba-source,
+[ --with-samba-source=DIR Where is the samba source tree (../../source)],
+[ case "$withval" in
+ yes|no)
+ #
+ # Just in case anybody calls it without argument
+ #
+ AC_MSG_WARN([--with-samba-source called without argument - will use default])
+ ;;
+ * )
+ SAMBA_SOURCE="$withval"
+ ;;
+ esac])
+
+AC_SUBST(SAMBA_SOURCE)
+
+dnl Unique-to-Samba variables we'll be playing with.
+AC_SUBST(CC)
+AC_SUBST(SHELL)
+AC_SUBST(LDSHFLAGS)
+AC_SUBST(SONAMEFLAG)
+AC_SUBST(SHLD)
+AC_SUBST(HOST_OS)
+AC_SUBST(PICFLAGS)
+AC_SUBST(PICSUFFIX)
+AC_SUBST(SHLIBEXT)
+AC_SUBST(INSTALLCLIENTCMD_SH)
+AC_SUBST(INSTALLCLIENTCMD_A)
+AC_SUBST(SHLIB_PROGS)
+AC_SUBST(EXTRA_BIN_PROGS)
+AC_SUBST(EXTRA_SBIN_PROGS)
+AC_SUBST(EXTRA_ALL_TARGETS)
+
+AC_ARG_ENABLE(debug,
+[ --enable-debug Turn on compiler debugging information (default=no)],
+ [if eval "test x$enable_debug = xyes"; then
+ CFLAGS="${CFLAGS} -g"
+ fi])
+
+AC_ARG_ENABLE(developer, [ --enable-developer Turn on developer warnings and debugging (default=no)],
+ [if eval "test x$enable_developer = xyes"; then
+ developer=yes
+ CFLAGS="${CFLAGS} -g -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER"
+ fi])
+
+# compile with optimization and without debugging by default, but
+# allow people to set their own preference.
+if test "x$CFLAGS" = x
+then
+ CFLAGS="-O ${CFLAGS}"
+fi
+
+ #################################################
+ # check for krb5-config from recent MIT and Heimdal kerberos 5
+ AC_PATH_PROG(KRB5_CONFIG, krb5-config)
+ AC_MSG_CHECKING(for working krb5-config)
+ if test -x "$KRB5_CONFIG"; then
+ CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
+ CPPFLAGS="$CPPFLAGS `$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
+ FOUND_KRB5=yes
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no. Fallback to previous krb5 detection strategy)
+ fi
+
+ if test x$FOUND_KRB5 = x"no"; then
+ #################################################
+ # check for location of Kerberos 5 install
+ AC_MSG_CHECKING(for kerberos 5 install path)
+ AC_ARG_WITH(krb5,
+ [ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)],
+ [ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ CFLAGS="$CFLAGS -I$withval/include"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ FOUND_KRB5=yes
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+ )
+ fi
+
+if test x$FOUND_KRB5 = x"no"; then
+#################################################
+# see if this box has the SuSE location for the heimdal kerberos implementation
+AC_MSG_CHECKING(for /usr/include/heimdal)
+if test -d /usr/include/heimdal; then
+ if test -f /usr/lib/heimdal/lib/libkrb5.a; then
+ CFLAGS="$CFLAGS -I/usr/include/heimdal"
+ CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal"
+ AC_MSG_RESULT(yes)
+ else
+ CFLAGS="$CFLAGS -I/usr/include/heimdal"
+ CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal"
+ AC_MSG_RESULT(yes)
+
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+fi
+
+
+if test x$FOUND_KRB5 = x"no"; then
+#################################################
+# see if this box has the RedHat location for kerberos
+AC_MSG_CHECKING(for /usr/kerberos)
+if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then
+ LDFLAGS="$LDFLAGS -L/usr/kerberos/lib"
+ CFLAGS="$CFLAGS -I/usr/kerberos/include"
+ CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include"
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+fi
+
+ # now check for krb5.h. Some systems have the libraries without the headers!
+ # note that this check is done here to allow for different kerberos
+ # include paths
+ AC_CHECK_HEADERS(krb5.h)
+
+ # now check for gssapi headers. This is also done here to allow for
+ # different kerberos include paths
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h com_err.h)
+
+#dnl Check if we use GNU ld
+#LD=ld
+#AC_PROG_LD_GNU
+
+#dnl look for executable suffix
+#AC_EXEEXT
+
+builddir=`pwd`
+AC_SUBST(builddir)
+
+# Assume non-shared by default and override below
+BLDSHARED="false"
+
+# these are the defaults, good for lots of systems
+HOST_OS="$host_os"
+LDSHFLAGS="-shared"
+SONAMEFLAG="#"
+SHLD="\${CC}"
+PICFLAGS=""
+PICSUFFIX="po"
+SHLIBEXT="so"
+
+if test "$enable_shared" = "yes"; then
+ # this bit needs to be modified for each OS that is suported by
+ # smbwrapper. You need to specify how to created a shared library and
+ # how to compile C code to produce PIC object files
+
+ AC_MSG_CHECKING([ability to build shared libraries])
+
+ # and these are for particular systems
+ case "$host_os" in
+ *linux*)
+ BLDSHARED="true"
+ LDSHFLAGS="-shared"
+ DYNEXP="-Wl,--export-dynamic"
+ PICFLAGS="-fPIC"
+ SONAMEFLAG="-Wl,-soname="
+ ;;
+ *solaris*)
+ BLDSHARED="true"
+ LDSHFLAGS="-G"
+ SONAMEFLAG="-h "
+ if test "${GCC}" = "yes"; then
+ PICFLAGS="-fPIC"
+ if test "${ac_cv_prog_gnu_ld}" = "yes"; then
+ DYNEXP="-Wl,-E"
+ fi
+ else
+ PICFLAGS="-KPIC"
+ ## ${CFLAGS} added for building 64-bit shared
+ ## libs using Sun's Compiler
+ LDSHFLAGS="-G \${CFLAGS}"
+ PICSUFFIX="po.o"
+ fi
+ ;;
+ *sunos*)
+ BLDSHARED="true"
+ LDSHFLAGS="-G"
+ SONAMEFLAG="-Wl,-h,"
+ PICFLAGS="-KPIC" # Is this correct for SunOS
+ ;;
+ *netbsd* | *freebsd*) BLDSHARED="true"
+ LDSHFLAGS="-shared"
+ DYNEXP="-Wl,--export-dynamic"
+ SONAMEFLAG="-Wl,-soname,"
+ PICFLAGS="-fPIC -DPIC"
+ ;;
+ *openbsd*) BLDSHARED="true"
+ LDSHFLAGS="-shared"
+ DYNEXP="-Wl,-Bdynamic"
+ SONAMEFLAG="-Wl,-soname,"
+ PICFLAGS="-fPIC"
+ ;;
+ *irix*)
+ case "$host_os" in
+ *irix6*)
+ ;;
+ esac
+ ATTEMPT_WRAP32_BUILD=yes
+ BLDSHARED="true"
+ LDSHFLAGS="-set_version sgi1.0 -shared"
+ SONAMEFLAG="-soname "
+ SHLD="\${LD}"
+ if test "${GCC}" = "yes"; then
+ PICFLAGS="-fPIC"
+ else
+ PICFLAGS="-KPIC"
+ fi
+ ;;
+ *aix*)
+ BLDSHARED="true"
+ LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry,-berok"
+ DYNEXP="-Wl,-brtl,-bexpall"
+ PICFLAGS="-O2"
+ if test "${GCC}" != "yes"; then
+ ## for funky AIX compiler using strncpy()
+ CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
+ fi
+ ;;
+ *hpux*)
+ SHLIBEXT="sl"
+ # Use special PIC flags for the native HP-UX compiler.
+ if test $ac_cv_prog_cc_Ae = yes; then
+ BLDSHARED="true"
+ SHLD="/usr/bin/ld"
+ LDSHFLAGS="-B symbolic -b -z"
+ SONAMEFLAG="+h "
+ PICFLAGS="+z"
+ fi
+ DYNEXP="-Wl,-E"
+ ;;
+ *qnx*)
+ ;;
+ *osf*)
+ BLDSHARED="true"
+ LDSHFLAGS="-shared"
+ SONAMEFLAG="-Wl,-soname,"
+ PICFLAGS="-fPIC"
+ ;;
+ *sco*)
+ ;;
+ *unixware*)
+ BLDSHARED="true"
+ LDSHFLAGS="-shared"
+ SONAMEFLAG="-Wl,-soname,"
+ PICFLAGS="-KPIC"
+ ;;
+ *next2*)
+ ;;
+ *dgux*) AC_CHECK_PROG( ROFF, groff, [groff -etpsR -Tascii -man])
+ ;;
+ *sysv4*)
+ case "$host" in
+ *-univel-*)
+ LDSHFLAGS="-G"
+ DYNEXP="-Bexport"
+ ;;
+ *mips-sni-sysv4*)
+ ;;
+ esac
+ ;;
+
+ *sysv5*)
+ LDSHFLAGS="-G"
+ ;;
+ *vos*)
+ BLDSHARED="false"
+ LDSHFLAGS=""
+ ;;
+ *)
+ ;;
+ esac
+ AC_SUBST(DYNEXP)
+ AC_MSG_RESULT($BLDSHARED)
+ AC_MSG_CHECKING([linker flags for shared libraries])
+ AC_MSG_RESULT([$LDSHFLAGS])
+ AC_MSG_CHECKING([compiler flags for position-independent code])
+ AC_MSG_RESULT([$PICFLAGS])
+fi
+
+#######################################################
+# test whether building a shared library actually works
+if test $BLDSHARED = true; then
+AC_CACHE_CHECK([whether building shared libraries actually works],
+ [ac_cv_shlib_works],[
+ ac_cv_shlib_works=no
+ # try building a trivial shared library
+ if test "$PICSUFFIX" = "po"; then
+ $CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o shlib.po ${srcdir-.}/tests/shlib.c &&
+ $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" shlib.po &&
+ ac_cv_shlib_works=yes
+ else
+ $CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c &&
+ mv shlib.$PICSUFFIX shlib.po &&
+ $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" shlib.po &&
+ ac_cv_shlib_works=yes
+ fi
+ rm -f "shlib.$SHLIBEXT" shlib.po
+])
+if test $ac_cv_shlib_works = no; then
+ BLDSHARED=false
+fi
+fi
+
+
+
+
+AC_OUTPUT(Makefile)
diff --git a/examples/VFS/install-sh b/examples/VFS/install-sh
new file mode 100644
index 00000000000..58719246f04
--- /dev/null
+++ b/examples/VFS/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/examples/VFS/shadow_copy_test.c b/examples/VFS/shadow_copy_test.c
new file mode 100644
index 00000000000..d2b7206cd35
--- /dev/null
+++ b/examples/VFS/shadow_copy_test.c
@@ -0,0 +1,83 @@
+/*
+ * TEST implementation of an Shadow Copy module
+ *
+ * Copyright (C) Stefan Metzmacher 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+/* USE THIS MODULE ONLY FOR TESTING!!!! */
+
+/*
+ For this share
+ Z:\
+
+ the ShadowCopies are in this directories
+
+ Z:\@GMT-2003.08.05-12.00.00\
+ Z:\@GMT-2003.08.05-12.01.00\
+ Z:\@GMT-2003.08.05-12.02.00\
+
+ e.g.
+
+ Z:\testfile.txt
+ Z:\@GMT-2003.08.05-12.02.00\testfile.txt
+
+ or:
+
+ Z:\testdir\testfile.txt
+ Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt
+
+
+ Note: Files must differ to be displayed via Windows Explorer!
+ Directories are always displayed...
+*/
+
+static int test_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+ uint32 num = 3;
+ uint32 i;
+
+ shadow_copy_data->num_volumes = num;
+
+ if (labels) {
+ shadow_copy_data->labels = (SHADOW_COPY_LABEL *)talloc_zero(shadow_copy_data->mem_ctx,(num)*sizeof(SHADOW_COPY_LABEL));
+ for (i=0;i<num;i++) {
+ snprintf(shadow_copy_data->labels[i], sizeof(SHADOW_COPY_LABEL), "@GMT-2003.08.05-12.%02u.00",i);
+ }
+ } else {
+ shadow_copy_data->labels = NULL;
+ }
+
+ return 0;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple shadow_copy_test_ops[] = {
+ {SMB_VFS_OP(test_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS init_module(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy_test", shadow_copy_test_ops);
+}
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
new file mode 100644
index 00000000000..310d305cee3
--- /dev/null
+++ b/examples/VFS/skel_opaque.c
@@ -0,0 +1,581 @@
+/*
+ * Skeleton VFS module. Implements passthrough operation of all VFS
+ * calls to disk functions.
+ *
+ * Copyright (C) Tim Potter, 1999-2000
+ * Copyright (C) Alexander Bokovoy, 2002
+ * Copyright (C) Stefan (metze) Metzmacher, 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "includes.h"
+
+/* PLEASE,PLEASE READ THE VFS MODULES CHAPTER OF THE
+ SAMBA DEVELOPERS GUIDE!!!!!!
+ */
+
+/* If you take this file as template for your module
+ * please make sure that you remove all vfswrap_* functions and
+ * implement your own function!!
+ *
+ * for functions you didn't want to provide implement dummy functions
+ * witch return ERROR and errno = ENOSYS; !
+ *
+ * --metze
+ */
+
+static int skel_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
+{
+ return 0;
+}
+
+static void skel_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+{
+ return;
+}
+
+static SMB_BIG_UINT skel_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path,
+ BOOL small_query, SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+ return vfswrap_disk_free(NULL, conn, path, small_query, bsize,
+ dfree, dsize);
+}
+
+static int skel_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+{
+ return vfswrap_get_quota(NULL, conn, qtype, id, dq);
+}
+
+static int skel_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+{
+ return vfswrap_set_quota(NULL, conn, qtype, id, dq);
+}
+
+static int skel_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+ return vfswrap_get_shadow_copy_data(NULL, fsp, shadow_copy_data, labels);
+}
+
+static DIR *skel_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
+{
+ return vfswrap_opendir(NULL, conn, fname);
+}
+
+static struct dirent *skel_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
+{
+ return vfswrap_readdir(NULL, conn, dirp);
+}
+
+static int skel_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+{
+ return vfswrap_mkdir(NULL, conn, path, mode);
+}
+
+static int skel_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return vfswrap_rmdir(NULL, conn, path);
+}
+
+static int skel_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dir)
+{
+ return vfswrap_closedir(NULL, conn, dir);
+}
+
+static int skel_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+{
+ return vfswrap_open(NULL, conn, fname, flags, mode);
+}
+
+static int skel_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return vfswrap_close(NULL, fsp, fd);
+}
+
+static ssize_t skel_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
+{
+ return vfswrap_read(NULL, fsp, fd, data, n);
+}
+
+static ssize_t skel_pread(vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset)
+{
+ return vfswrap_pread(NULL, fsp, fd, data, n, offset);
+}
+
+static ssize_t skel_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
+{
+ return vfswrap_write(NULL, fsp, fd, data, n);
+}
+
+ssize_t skel_pwrite(vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset)
+{
+ return vfswrap_pwrite(NULL, fsp, fd, data, n, offset);
+}
+
+static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
+{
+ return vfswrap_lseek(NULL, fsp, filedes, offset, whence);
+}
+
+static int skel_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
+{
+ return vfswrap_rename(NULL, conn, old, new);
+}
+
+static int skel_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return vfswrap_fsync(NULL, fsp, fd);
+}
+
+static int skel_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ return vfswrap_stat(NULL, conn, fname, sbuf);
+}
+
+static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
+{
+ return vfswrap_fstat(NULL, fsp, fd, sbuf);
+}
+
+static int skel_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
+{
+ return vfswrap_lstat(NULL, conn, path, sbuf);
+}
+
+static int skel_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return vfswrap_unlink(NULL, conn, path);
+}
+
+static int skel_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+{
+ return vfswrap_chmod(NULL, conn, path, mode);
+}
+
+static int skel_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+ return vfswrap_fchmod(NULL, fsp, fd, mode);
+}
+
+static int skel_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+{
+ return vfswrap_chown(NULL, conn, path, uid, gid);
+}
+
+static int skel_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
+{
+ return vfswrap_fchown(NULL, fsp, fd, uid, gid);
+}
+
+static int skel_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return vfswrap_chdir(NULL, conn, path);
+}
+
+static char *skel_getwd(vfs_handle_struct *handle, connection_struct *conn, char *buf)
+{
+ return vfswrap_getwd(NULL, conn, buf);
+}
+
+static int skel_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
+{
+ return vfswrap_utime(NULL, conn, path, times);
+}
+
+static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
+{
+ return vfswrap_ftruncate(NULL, fsp, fd, offset);
+}
+
+static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+{
+ return vfswrap_lock(NULL, fsp, fd, op, offset, count, type);
+}
+
+static BOOL skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+{
+ return vfswrap_symlink(NULL, conn, oldpath, newpath);
+}
+
+static BOOL skel_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
+{
+ return vfswrap_readlink(NULL, conn, path, buf, bufsiz);
+}
+
+static int skel_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+{
+ return vfswrap_link(NULL, conn, oldpath, newpath);
+}
+
+static int skel_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
+{
+ return vfswrap_mknod(NULL, conn, path, mode, dev);
+}
+
+static char *skel_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
+{
+ return vfswrap_realpath(NULL, conn, path, resolved_path);
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+{
+ errno = ENOSYS;
+ return 0;
+}
+
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+{
+ errno = ENOSYS;
+ return 0;
+}
+
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+{
+ errno = ENOSYS;
+ return False;
+}
+
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+{
+ errno = ENOSYS;
+ return False;
+}
+
+static int skel_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static void *skel_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+static SMB_ACL_T skel_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+static SMB_ACL_T skel_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+static int skel_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static char *skel_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+static SMB_ACL_T skel_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+static int skel_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
+size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t skel_flistxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static int skel_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple skel_op_tuples[] = {
+
+ /* Disk operations */
+
+ {SMB_VFS_OP(skel_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_disk_free), SMB_VFS_OP_DISK_FREE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_get_quota), SMB_VFS_OP_GET_QUOTA, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_set_quota), SMB_VFS_OP_SET_QUOTA, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
+
+ /* Directory operations */
+
+ {SMB_VFS_OP(skel_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_closedir), SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_OPAQUE},
+
+ /* File operations */
+
+ {SMB_VFS_OP(skel_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_read), SMB_VFS_OP_READ, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_pread), SMB_VFS_OP_PREAD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_write), SMB_VFS_OP_WRITE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_pwrite), SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lseek), SMB_VFS_OP_LSEEK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fsync), SMB_VFS_OP_FSYNC, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fchmod), SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_OPAQUE},
+
+ /* NT File ACL operations */
+
+ {SMB_VFS_OP(skel_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_OPAQUE},
+
+ /* POSIX ACL operations */
+
+ {SMB_VFS_OP(skel_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(skel_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_tag_type), SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_permset), SMB_VFS_OP_SYS_ACL_GET_PERMSET, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_qualifier), SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_fd), SMB_VFS_OP_SYS_ACL_GET_FD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_clear_perms), SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_add_perm), SMB_VFS_OP_SYS_ACL_ADD_PERM, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_to_text), SMB_VFS_OP_SYS_ACL_TO_TEXT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_init), SMB_VFS_OP_SYS_ACL_INIT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_create_entry), SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_set_tag_type), SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_set_qualifier), SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_set_permset), SMB_VFS_OP_SYS_ACL_SET_PERMSET, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_valid), SMB_VFS_OP_SYS_ACL_VALID, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_set_fd), SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_delete_def_file), SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_get_perm), SMB_VFS_OP_SYS_ACL_GET_PERM, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_free_acl), SMB_VFS_OP_SYS_ACL_FREE_ACL, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_sys_acl_free_qualifier), SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, SMB_VFS_LAYER_OPAQUE},
+
+ /* EA operations. */
+ {SMB_VFS_OP(skel_getxattr), SMB_VFS_OP_GETXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lgetxattr), SMB_VFS_OP_LGETXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fgetxattr), SMB_VFS_OP_FGETXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_listxattr), SMB_VFS_OP_LISTXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_llistxattr), SMB_VFS_OP_LLISTXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_flistxattr), SMB_VFS_OP_FLISTXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_removexattr), SMB_VFS_OP_REMOVEXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lremovexattr), SMB_VFS_OP_LREMOVEXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fremovexattr), SMB_VFS_OP_FREMOVEXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_setxattr), SMB_VFS_OP_SETXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_lsetxattr), SMB_VFS_OP_LSETXATTR, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_fsetxattr), SMB_VFS_OP_FSETXATTR, SMB_VFS_LAYER_OPAQUE},
+
+ {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS init_module(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "skel_opaque", skel_op_tuples);
+}
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
new file mode 100644
index 00000000000..448390e72f4
--- /dev/null
+++ b/examples/VFS/skel_transparent.c
@@ -0,0 +1,548 @@
+/*
+ * Skeleton VFS module. Implements passthrough operation of all VFS
+ * calls to disk functions.
+ *
+ * Copyright (C) Tim Potter, 1999-2000
+ * Copyright (C) Alexander Bokovoy, 2002
+ * Copyright (C) Stefan (metze) Metzmacher, 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "includes.h"
+
+/* PLEASE,PLEASE READ THE VFS MODULES CHAPTER OF THE
+ SAMBA DEVELOPERS GUIDE!!!!!!
+ */
+
+/* If you take this file as template for your module
+ * please make sure that you remove all functions you didn't
+ * want to implement!!
+ *
+ * This passthrough operations are useless in reall vfs modules!
+ *
+ * --metze
+ */
+
+static int skel_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
+{
+ return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+}
+
+static void skel_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+{
+ SMB_VFS_NEXT_DISCONNECT(handle, conn);
+}
+
+static SMB_BIG_UINT skel_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path,
+ BOOL small_query, SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+ return SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize,
+ dfree, dsize);
+}
+
+static int skel_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+{
+ return SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, dq);
+}
+
+static int skel_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+{
+ return SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq);
+}
+
+static int skel_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+ return SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data, labels);
+}
+
+static DIR *skel_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
+{
+ return SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
+}
+
+static struct dirent *skel_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
+{
+ return SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+}
+
+static int skel_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+{
+ return SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+}
+
+static int skel_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return SMB_VFS_NEXT_RMDIR(handle, conn, path);
+}
+
+static int skel_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dir)
+{
+ return SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir);
+}
+
+static int skel_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+{
+ return SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+}
+
+static int skel_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
+}
+
+static ssize_t skel_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
+{
+ return SMB_VFS_NEXT_READ(handle, fsp, fd, data, n);
+}
+
+static ssize_t skel_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset)
+{
+ return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, offset);
+}
+
+static ssize_t skel_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
+{
+ return SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n);
+}
+
+static ssize_t skel_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset)
+{
+ return SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, offset);
+}
+
+static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
+{
+ return SMB_VFS_NEXT_LSEEK(handle, fsp, filedes, offset, whence);
+}
+
+static int skel_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
+{
+ return SMB_VFS_NEXT_RENAME(handle, conn, old, new);
+}
+
+static int skel_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return SMB_VFS_NEXT_FSYNC(handle, fsp, fd);
+}
+
+static int skel_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ return SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf);
+}
+
+static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
+{
+ return SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf);
+}
+
+static int skel_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
+{
+ return SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf);
+}
+
+static int skel_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return SMB_VFS_NEXT_UNLINK(handle, conn, path);
+}
+
+static int skel_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+{
+ return SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+}
+
+static int skel_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode);
+}
+
+static int skel_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+{
+ return SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid);
+}
+
+static int skel_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
+{
+ return SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid);
+}
+
+static int skel_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return SMB_VFS_NEXT_CHDIR(handle, conn, path);
+}
+
+static char *skel_getwd(vfs_handle_struct *handle, connection_struct *conn, char *buf)
+{
+ return SMB_VFS_NEXT_GETWD(handle, conn, buf);
+}
+
+static int skel_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
+{
+ return SMB_VFS_NEXT_UTIME(handle, conn, path, times);
+}
+
+static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
+{
+ return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset);
+}
+
+static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+{
+ return SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type);
+}
+
+static BOOL skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+{
+ return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
+}
+
+static BOOL skel_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
+{
+ return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
+}
+
+static int skel_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+{
+ return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
+}
+
+static int skel_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
+{
+ return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev);
+}
+
+static char *skel_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
+{
+ return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+{
+ return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc);
+}
+
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+{
+ return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info, ppdesc);
+}
+
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+{
+ return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, fd, security_info_sent, psd);
+}
+
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+{
+ return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd);
+}
+
+static int skel_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
+{
+ /* If the underlying VFS doesn't have ACL support... */
+ if (!handle->vfs_next.ops.chmod_acl) {
+ errno = ENOSYS;
+ return -1;
+ }
+ return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode);
+}
+
+static int skel_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+ /* If the underlying VFS doesn't have ACL support... */
+ if (!handle->vfs_next.ops.fchmod_acl) {
+ errno = ENOSYS;
+ return -1;
+ }
+ return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode);
+}
+
+static int skel_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, entry_p);
+}
+
+static int skel_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, tag_type_p);
+}
+
+static int skel_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, permset_p);
+}
+
+static void *skel_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d);
+}
+
+static SMB_ACL_T skel_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type);
+}
+
+static SMB_ACL_T skel_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, fd);
+}
+
+static int skel_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
+{
+ return SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset);
+}
+
+static int skel_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ return SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm);
+}
+
+static char *skel_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
+{
+ return SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen);
+}
+
+static SMB_ACL_T skel_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
+{
+ return SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count);
+}
+
+static int skel_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
+{
+ return SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry);
+}
+
+static int skel_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
+{
+ return SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, tagtype);
+}
+
+static int skel_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
+{
+ return SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual);
+}
+
+static int skel_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
+{
+ return SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset);
+}
+
+static int skel_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
+{
+ return SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl);
+}
+
+static int skel_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+{
+ return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl);
+}
+
+static int skel_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
+{
+ return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, fd, theacl);
+}
+
+static int skel_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+{
+ return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path);
+}
+
+static int skel_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ return SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm);
+}
+
+static int skel_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
+{
+ return SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text);
+}
+
+static int skel_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
+{
+ return SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl);
+}
+
+static int skel_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
+{
+ return SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, tagtype);
+}
+
+static ssize_t skel_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
+{
+ return SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size);
+}
+
+static ssize_t skel_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
+size)
+{
+ return SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size);
+}
+
+static ssize_t skel_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
+{
+ return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, name, value, size);
+}
+
+static ssize_t skel_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+{
+ return SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size);
+}
+
+static ssize_t skel_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+{
+ return SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size);
+}
+
+static ssize_t skel_flistxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
+{
+ return SMB_VFS_NEXT_FLISTXATTR(handle, fsp, fd, list, size);
+}
+
+static int skel_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+{
+ return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name);
+}
+
+static int skel_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+{
+ return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name);
+}
+
+static int skel_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
+{
+ return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, name);
+}
+
+static int skel_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ return SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size, flags);
+}
+
+static int skel_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ return SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size, flags);
+}
+
+static int skel_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
+{
+ return SMB_VFS_NEXT_FSETXATTR(handle, fsp, fd, name, value, size, flags);
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple skel_op_tuples[] = {
+
+ /* Disk operations */
+
+ {SMB_VFS_OP(skel_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_disk_free), SMB_VFS_OP_DISK_FREE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_get_quota), SMB_VFS_OP_GET_QUOTA, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_set_quota), SMB_VFS_OP_SET_QUOTA, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_TRANSPARENT},
+
+ /* Directory operations */
+
+ {SMB_VFS_OP(skel_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_closedir), SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* File operations */
+
+ {SMB_VFS_OP(skel_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_read), SMB_VFS_OP_READ, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_write), SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lseek), SMB_VFS_OP_LSEEK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fsync), SMB_VFS_OP_FSYNC, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fchmod), SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* NT File ACL operations */
+
+ {SMB_VFS_OP(skel_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* POSIX ACL operations */
+
+ {SMB_VFS_OP(skel_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(skel_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_tag_type), SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_permset), SMB_VFS_OP_SYS_ACL_GET_PERMSET, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_qualifier), SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_fd), SMB_VFS_OP_SYS_ACL_GET_FD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_clear_perms), SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_add_perm), SMB_VFS_OP_SYS_ACL_ADD_PERM, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_to_text), SMB_VFS_OP_SYS_ACL_TO_TEXT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_init), SMB_VFS_OP_SYS_ACL_INIT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_create_entry), SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_set_tag_type), SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_set_qualifier), SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_set_permset), SMB_VFS_OP_SYS_ACL_SET_PERMSET, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_valid), SMB_VFS_OP_SYS_ACL_VALID, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_set_fd), SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_delete_def_file), SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_get_perm), SMB_VFS_OP_SYS_ACL_GET_PERM, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_free_acl), SMB_VFS_OP_SYS_ACL_FREE_ACL, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_sys_acl_free_qualifier), SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT},
+
+ /* EA operations. */
+ {SMB_VFS_OP(skel_getxattr), SMB_VFS_OP_GETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lgetxattr), SMB_VFS_OP_LGETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fgetxattr), SMB_VFS_OP_FGETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_listxattr), SMB_VFS_OP_LISTXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_llistxattr), SMB_VFS_OP_LLISTXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_flistxattr), SMB_VFS_OP_FLISTXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_removexattr), SMB_VFS_OP_REMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lremovexattr), SMB_VFS_OP_LREMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fremovexattr), SMB_VFS_OP_FREMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_setxattr), SMB_VFS_OP_SETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_lsetxattr), SMB_VFS_OP_LSETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_fsetxattr), SMB_VFS_OP_FSETXATTR, SMB_VFS_LAYER_TRANSPARENT},
+
+ {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS init_module(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "skel_transparent", skel_op_tuples);
+}
diff --git a/examples/appliance/Makefile b/examples/appliance/Makefile
new file mode 100644
index 00000000000..c49451add86
--- /dev/null
+++ b/examples/appliance/Makefile
@@ -0,0 +1,68 @@
+PREFIX=/usr/local/samba
+CONFIGOPTS=--with-pam --prefix=$(PREFIX) --with-smbmount
+
+
+all: headb tngb
+
+config:
+ (cd head/source; CFLAGS="-Wall -O2 -g" ./configure $(CONFIGOPTS))
+ (cd tng; CFLAGS="-Wall -O2 -g" ./configure $(CONFIGOPTS) --enable-shared=no)
+
+headb:
+ (cd head/source; make)
+
+tngb:
+ (cd tng; make bin/samedit bin/winbindd nsswitch)
+
+clean:
+ (cd head/source; make clean)
+ (cd tng; make clean)
+
+proto:
+ (cd head/source; make proto)
+ (cd tng; make proto)
+
+distclean:
+ (cd head/source; make clean; rm -f config.cache; rm -f Makefile)
+ (cd tng; make clean; rm -f config.cache; rm -f Makefile)
+
+install: installhead installtng
+
+installbin: installheadbin installtng
+
+installhead:
+ (cd head/source; make install)
+
+installheadbin:
+ (cd head/source; make installbin)
+
+installtng: tngb
+ (cd tng; \
+ rm -f $(PREFIX)/bin/samedit $(PREFIX)/bin/winbindd; \
+ cp bin/samedit bin/winbindd $(PREFIX)/bin; \
+ rm -f /lib/libnss_winbind.so.2 /lib/security/pam_winbind.so; \
+ cp nsswitch/libnss_winbind.so /lib/libnss_winbind.so.2; \
+ cp nsswitch/pam_winbind.so /lib/security/)
+
+stop:
+ -killall winbindd smbd nmbd
+
+start:
+ $(PREFIX)/bin/smbd
+ $(PREFIX)/bin/nmbd
+ $(PREFIX)/bin/winbindd
+
+restart: stop start
+
+updatehead:
+ (cd head; cvs -z9 update -d)
+
+updatetng:
+ (cd tng; cvs -z9 update -d)
+
+update: updatehead updatetng
+
+checkout:
+ -mkdir head tng
+ (cd head ; cvs -z9 co samba; mv samba head)
+ (cd head ; cvs -z9 co -r SAMBA_TNG samba/source; mv source tng)
diff --git a/examples/appliance/README b/examples/appliance/README
new file mode 100644
index 00000000000..3c9028fd89a
--- /dev/null
+++ b/examples/appliance/README
@@ -0,0 +1,52 @@
+This directory provides build tools for building a Samba based domain
+appliance.
+
+A appliance is a box that gets its username and group database from a
+domain controller, and does its authentication via a domain
+controller. Right now this is only supported by combining two CVS
+branches of Samba, which is what the files in this directory do.
+
+SETUP
+-----
+
+To setup an appliance do the following:
+
+1) build and install Samba using the .spec file or Makefile in this
+ directory.
+
+2) setup winbindd by following the directions in the winbindd man
+ page.
+
+3) test winbindd, validating that domain users and groups are visible
+ and that domain authentication works, both using unix tools and
+ smbclient.
+
+for appliance printing support also do this:
+
+4) create a print$ share with write permission for print
+ administrators.
+
+4) create the "nt printer driver" directory (by default
+ /usr/local/samba/lib/ntprinters) and make it writable by print
+ adminisrators.
+
+5) populate your /etc/printcap printer database
+
+6) add printers using the NT "add printer wizard" in the Printers
+ network folder.
+
+
+PACKAGING
+---------
+
+- Checkout the Samba CVS head branch into a directory call
+ samba-appliance-0.2/head
+
+- Checkout the source subdirectory of the Samba CVS SAMBA_TNG branch
+ into a directory call samba-appliance-0.2/tng
+
+- Copy Makefile and smb.conf-appliance to samba-appliance-0.2/
+
+- run build.sh
+
+That should build source and binary RPMs in /usr/src/redhat/{RPMS,SRPMS}
diff --git a/examples/appliance/appliance.spec b/examples/appliance/appliance.spec
new file mode 100644
index 00000000000..6fb631b4e2f
--- /dev/null
+++ b/examples/appliance/appliance.spec
@@ -0,0 +1,389 @@
+Summary: Samba SMB client and server
+Name: samba-appliance
+Version: 0.2
+Release: 1
+Copyright: GNU GPL version 2
+Group: Networking
+Source: %{name}-%{version}-src.tar.gz
+Packager: John H Terpstra [Samba-Team] <jht@samba.org>
+Requires: pam >= 0.64
+Prereq: chkconfig fileutils
+BuildRoot: /var/tmp/samba
+Provides: winbind
+
+%define prefix /usr/local/samba
+
+%define tng_build_dir $RPM_BUILD_DIR/%{name}-%{version}/tng
+%define head_build_dir $RPM_BUILD_DIR/%{name}-%{version}/head
+
+%description
+Samba provides an SMB server which can be used to provide
+network services to SMB (sometimes called "Lan Manager")
+clients, including various versions of MS Windows, OS/2,
+and other Linux machines. Samba also provides some SMB
+clients, which complement the built-in SMB filesystem
+in Linux. Samba uses NetBIOS over TCP/IP (NetBT) protocols
+and does NOT need NetBEUI (Microsoft Raw NetBIOS frame)
+protocol.
+
+Samba-2 features an almost working NT Domain Control
+capability and includes the new SWAT (Samba Web Administration
+Tool) that allows samba's smb.conf file to be remotely managed
+using your favourite web browser. For the time being this is
+being enabled on TCP port 901 via inetd.
+
+Please refer to the WHATSNEW.txt document for fixup information.
+This binary release includes encrypted password support.
+Please read the smb.conf file and ENCRYPTION.txt in the
+docs directory for implementation details.
+
+NOTE: Red Hat Linux 5.X Uses PAM which has integrated support
+for Shadow passwords. Do NOT recompile with the SHADOW_PWD option
+enabled. Red Hat Linux has built in support for quotas in PAM.
+
+%changelog
+* Mon Jun 5 2000 Tim Potter <tpot@samba.org>
+ - Modified to use prefix=/usr/local/samba everywhere
+
+* Sat Nov 29 1999 Matthew Vanecek <mev0003@unt.edu>
+ - Added a Prefix and changed "/usr" to "%{prefix}"
+
+* Sat Nov 11 1999 Tridge <tridge@linuxcare.com>
+ - changed from mount.smb to mount.smbfs
+
+* Sat Oct 9 1999 Tridge <tridge@linuxcare.com>
+ - removed smbwrapper
+ - added smbmnt and smbmount
+
+* Sun Apr 25 1999 John H Terpstra <jht@samba.org>
+ - added smbsh.1 man page
+
+* Fri Mar 26 1999 Andrew Tridgell <tridge@samba.org>
+ - added --with-pam as pam is no longer used by default
+
+* Sat Jan 27 1999 Jeremy Allison <jra@samba.org>
+ - Removed smbrun binary and tidied up some loose ends
+
+* Sun Oct 25 1998 John H Terpstra <jht@samba.org>
+ - Added parameters to /config to ensure smb.conf, lmhosts,
+ and smbusers never gets over-written.
+
+* Sat Oct 24 1998 John H Terpstra <jht@samba.org>
+ - removed README.smbsh file from docs area
+
+* Mon Oct 05 1998 John H Terpstra <jht@samba.org>
+ - Added rpcclient to binaries list
+ - Added smbwrapper stuff
+
+* Fri Aug 21 1998 John H Terpstra <jht@samba.org>
+ - Updated for Samba version 2.0 building
+
+* Tue Jul 07 1998 Erik Troan <ewt@redhat.com>
+ - updated postun triggerscript to check $0
+ - clear /etc/codepages from %preun instead of %postun
+
+* Sat Jul 04 1998 John H Terpstra <jht@samba.org>
+ - fixed codepage preservation during update via -Uvh
+
+* Mon Jun 08 1998 Erik Troan <ewt@redhat.com>
+ - made the %postun script a tad less agressive; no reason to remove
+ the logs or lock file
+ - the %postun and %preun should only exectute if this is the final
+ removal
+ - migrated %triggerpostun from Red Hat's samba package to work around
+ packaging problems in some Red Hat samba releases
+
+* Sun Apr 26 1998 John H Terpstra <jht@samba.org>
+ - Tidy up for early alpha releases
+ - added findsmb from SGI packaging
+
+* Thu Apr 09 1998 John H Terpstra <jht@samba.org>
+ - Updated spec file
+ - Included new codepage.936
+
+* Sat Mar 20 1998 John H Terpstra <jht@samba.org>
+ - Added swat facility
+
+* Sat Jan 24 1998 John H Terpstra <jht@samba.org>
+ - Many optimisations (some suggested by Manoj Kasichainula <manojk@io.com>
+ - Use of chkconfig in place of individual symlinks to /etc/rc.d/init/smb
+ - Compounded make line
+ - Updated smb.init restart mechanism
+ - Use compound mkdir -p line instead of individual calls to mkdir
+ - Fixed smb.conf file path for log files
+ - Fixed smb.conf file path for incoming smb print spool directory
+ - Added a number of options to smb.conf file
+ - Added smbadduser command (missed from all previous RPMs) - Doooh!
+ - Added smbuser file and smb.conf file updates for username map
+
+%prep
+%setup
+
+%build
+make config
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+# Install stuff for tng
+
+mkdir -p $RPM_BUILD_ROOT%{prefix}/bin
+mkdir -p $RPM_BUILD_ROOT/lib/security
+cp %{tng_build_dir}/bin/samedit $RPM_BUILD_ROOT%{prefix}/bin
+cp %{tng_build_dir}/bin/winbindd $RPM_BUILD_ROOT%{prefix}/bin
+cp %{tng_build_dir}/nsswitch/libnss_winbind.so $RPM_BUILD_ROOT/lib
+cp %{tng_build_dir}/nsswitch/pam_winbind.so $RPM_BUILD_ROOT/lib/security
+
+# Install stuff for head
+
+mkdir -p $RPM_BUILD_ROOT%{prefix}/lib/codepages/src
+mkdir -p $RPM_BUILD_ROOT/etc/{logrotate.d,pam.d}
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/{init.d,rc0.d,rc1.d,rc2.d,rc3.d,rc5.d,rc6.d}
+mkdir -p $RPM_BUILD_ROOT%{prefix}/bin
+mkdir -p $RPM_BUILD_ROOT%{prefix}/share/swat/{images,help,include}
+mkdir -p $RPM_BUILD_ROOT%{prefix}/man/{man1,man5,man7,man8}
+mkdir -p $RPM_BUILD_ROOT%{prefix}/var/locks
+mkdir -p $RPM_BUILD_ROOT%{prefix}/private
+
+# Install standard binary files
+for i in nmblookup smbclient smbspool smbpasswd smbstatus testparm testprns \
+ make_smbcodepage make_printerdef
+do
+install -m755 -s %{head_build_dir}/source/bin/$i $RPM_BUILD_ROOT%{prefix}/bin
+done
+for i in addtosmbpass mksmbpasswd.sh smbtar
+do
+install -m755 %{head_build_dir}/source/script/$i $RPM_BUILD_ROOT%{prefix}/bin
+done
+
+# Install secure binary files
+for i in smbd nmbd swat smbmount smbmnt smbumount
+do
+install -m755 -s %{head_build_dir}/source/bin/$i $RPM_BUILD_ROOT%{prefix}/bin
+done
+
+# we need a symlink for mount to recognise the smb filesystem type
+#ln -sf %{prefix}/bin/smbmount $RPM_BUILD_ROOT%{prefix}/bin/mount.smbfs
+
+# Install level 1 man pages
+for i in smbclient.1 smbrun.1 smbstatus.1 smbtar.1 testparm.1 testprns.1 make_smbcodepage.1 nmblookup.1
+do
+install -m644 %{head_build_dir}/docs/manpages/$i $RPM_BUILD_ROOT%{prefix}/man/man1
+done
+
+# Install codepage source files
+for i in 437 737 850 852 861 866 932 936 949 950
+do
+install -m644 %{head_build_dir}/source/codepages/codepage_def.$i $RPM_BUILD_ROOT%{prefix}/lib/codepages/src
+done
+
+# Install SWAT helper files
+for i in %{head_build_dir}/swat/help/*.html %{head_build_dir}/docs/htmldocs/*.html
+do
+install -m644 $i $RPM_BUILD_ROOT%{prefix}/share/swat/help
+done
+for i in %{head_build_dir}/swat/images/*.gif
+do
+install -m644 $i $RPM_BUILD_ROOT%{prefix}/share/swat/images
+done
+for i in %{head_build_dir}/swat/include/*.html
+do
+install -m644 $i $RPM_BUILD_ROOT%{prefix}/share/swat/include
+done
+
+# Install the miscellany
+install -m644 %{head_build_dir}/swat/README $RPM_BUILD_ROOT%{prefix}/share/swat
+install -m644 %{head_build_dir}/docs/manpages/smb.conf.5 $RPM_BUILD_ROOT%{prefix}/man/man5
+install -m644 %{head_build_dir}/docs/manpages/lmhosts.5 $RPM_BUILD_ROOT%{prefix}/man/man5
+install -m644 %{head_build_dir}/docs/manpages/smbpasswd.5 $RPM_BUILD_ROOT%{prefix}/man/man5
+install -m644 %{head_build_dir}/docs/manpages/samba.7 $RPM_BUILD_ROOT%{prefix}/man/man7
+install -m644 %{head_build_dir}/docs/manpages/smbd.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/nmbd.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/swat.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/smbmnt.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/smbmount.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/smbpasswd.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 %{head_build_dir}/docs/manpages/smbspool.8 $RPM_BUILD_ROOT%{prefix}/man/man8
+install -m644 $RPM_BUILD_DIR/%{name}-%{version}/smb.conf-appliance $RPM_BUILD_ROOT%{prefix}/lib/smb.conf
+install -m644 %{head_build_dir}/packaging/RedHat/smbusers $RPM_BUILD_ROOT/etc/smbusers
+install -m755 %{head_build_dir}/packaging/RedHat/smbprint $RPM_BUILD_ROOT%{prefix}/bin
+install -m755 %{head_build_dir}/packaging/RedHat/findsmb $RPM_BUILD_ROOT%{prefix}/bin
+install -m755 %{head_build_dir}/packaging/RedHat/smbadduser $RPM_BUILD_ROOT%{prefix}/bin
+install -m755 %{head_build_dir}/packaging/RedHat/smb.init $RPM_BUILD_ROOT/etc/rc.d/init.d/smb
+install -m755 %{head_build_dir}/packaging/RedHat/smb.init $RPM_BUILD_ROOT%{prefix}/bin/samba
+install -m644 %{head_build_dir}/packaging/RedHat/samba.pamd $RPM_BUILD_ROOT/etc/pam.d/samba
+install -m644 %{head_build_dir}/packaging/RedHat/samba.log $RPM_BUILD_ROOT/etc/logrotate.d/samba
+echo 127.0.0.1 localhost > $RPM_BUILD_ROOT/etc/lmhosts
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+#/sbin/chkconfig --add smb
+
+# Build codepage load files
+for i in 437 737 850 852 861 866 932 936 949 950
+do
+%{prefix}/bin/make_smbcodepage c $i %{prefix}/lib/codepages/src/codepage_def.$i %{prefix}/lib/codepages/codepage.$i
+done
+
+# Add swat entry to /etc/services if not already there
+if !( grep ^[:space:]*swat /etc/services > /dev/null ) then
+ echo 'swat 901/tcp # Add swat service used via inetd' >> /etc/services
+fi
+
+# Add swat entry to /etc/inetd.conf if needed
+if !( grep ^[:space:]*swat /etc/inetd.conf > /dev/null ) then
+ echo 'swat stream tcp nowait.400 root %{prefix}/sbin/swat swat' >> /etc/inetd.conf
+killall -1 inetd || :
+fi
+
+%preun
+if [ $1 = 0 ] ; then
+ /sbin/chkconfig --del smb
+
+ for n in %{prefix}/lib/codepages/*; do
+ if [ $n != %{prefix}/lib/codepages/src ]; then
+ rm -rf $n
+ fi
+ done
+ # We want to remove the browse.dat and wins.dat files so they can not interfer with a new version of samba!
+ if [ -e %{prefix}/var/locks/browse.dat ]; then
+ rm -f %{prefix}/var/locks/browse.dat
+ fi
+ if [ -e %{prefix}/var/locks/wins.dat ]; then
+ rm -f %{prefix}/var/locks/wins.dat
+ fi
+fi
+
+%postun
+# Only delete remnants of samba if this is the final deletion.
+if [ $1 = 0 ] ; then
+ if [ -x /etc/pam.d/samba ]; then
+ rm -f /etc/pam.d/samba
+ fi
+ if [ -e /var/log/samba ]; then
+ rm -rf /var/log/samba
+ fi
+ if [ -e /var/lock/samba ]; then
+ rm -rf /var/lock/samba
+ fi
+
+ # Remove swat entries from /etc/inetd.conf and /etc/services
+ cd /etc
+ tmpfile=/etc/tmp.$$
+ sed -e '/^[:space:]*swat.*$/d' /etc/inetd.conf > $tmpfile
+ mv $tmpfile inetd.conf
+ sed -e '/^[:space:]*swat.*$/d' /etc/services > $tmpfile
+ mv $tmpfile services
+fi
+
+%triggerpostun -- samba < samba-2.0.0
+if [ $0 != 0 ]; then
+ /sbin/chkconfig --add smb
+fi
+
+
+%files
+%doc %{head_build_dir}/README %{head_build_dir}/COPYING
+%doc %{head_build_dir}/Manifest %{head_build_dir}/Read-Manifest-Now
+%doc %{head_build_dir}/WHATSNEW.txt %{head_build_dir}/Roadmap
+%doc %{head_build_dir}/docs
+%doc %{head_build_dir}/swat/README
+%doc %{head_build_dir}/examples
+%attr(-,root,root) %{prefix}/bin/smbd
+%attr(-,root,root) %{prefix}/bin/nmbd
+%attr(-,root,root) %{prefix}/bin/swat
+%attr(-,root,root) %{prefix}/bin/smbmnt
+%attr(-,root,root) %{prefix}/bin/smbmount
+%attr(-,root,root) %{prefix}/bin/smbumount
+%attr(0750,root,root) %{prefix}/bin/samba
+%attr(-,root,root) %{prefix}/bin/addtosmbpass
+%attr(-,root,root) %{prefix}/bin/mksmbpasswd.sh
+%attr(-,root,root) %{prefix}/bin/smbclient
+%attr(-,root,root) %{prefix}/bin/smbspool
+%attr(-,root,root) %{prefix}/bin/testparm
+%attr(-,root,root) %{prefix}/bin/testprns
+%attr(-,root,root) %{prefix}/bin/findsmb
+%attr(-,root,root) %{prefix}/bin/smbstatus
+%attr(-,root,root) %{prefix}/bin/nmblookup
+%attr(-,root,root) %{prefix}/bin/make_smbcodepage
+%attr(-,root,root) %{prefix}/bin/make_printerdef
+%attr(-,root,root) %{prefix}/bin/smbpasswd
+%attr(-,root,root) %{prefix}/bin/smbtar
+%attr(-,root,root) %{prefix}/bin/smbprint
+%attr(-,root,root) %{prefix}/bin/smbadduser
+%attr(-,root,root) %{prefix}/share/swat/help/welcome.html
+%attr(-,root,root) %{prefix}/share/swat/help/DOMAIN_MEMBER.html
+%attr(-,root,root) %{prefix}/share/swat/help/NT_Security.html
+%attr(-,root,root) %{prefix}/share/swat/help/lmhosts.5.html
+%attr(-,root,root) %{prefix}/share/swat/help/make_smbcodepage.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/nmbd.8.html
+%attr(-,root,root) %{prefix}/share/swat/help/nmblookup.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/samba.7.html
+%attr(-,root,root) %{prefix}/share/swat/help/smb.conf.5.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbclient.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbspool.8.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbd.8.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbpasswd.5.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbpasswd.8.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbrun.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbstatus.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/smbtar.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/swat.8.html
+%attr(-,root,root) %{prefix}/share/swat/help/testparm.1.html
+%attr(-,root,root) %{prefix}/share/swat/help/testprns.1.html
+%attr(-,root,root) %{prefix}/share/swat/images/globals.gif
+%attr(-,root,root) %{prefix}/share/swat/images/home.gif
+%attr(-,root,root) %{prefix}/share/swat/images/passwd.gif
+%attr(-,root,root) %{prefix}/share/swat/images/printers.gif
+%attr(-,root,root) %{prefix}/share/swat/images/shares.gif
+%attr(-,root,root) %{prefix}/share/swat/images/samba.gif
+%attr(-,root,root) %{prefix}/share/swat/images/status.gif
+%attr(-,root,root) %{prefix}/share/swat/images/viewconfig.gif
+%attr(-,root,root) %{prefix}/share/swat/include/header.html
+%attr(-,root,root) %{prefix}/share/swat/include/footer.html
+%attr(-,root,root) %config(noreplace) /etc/lmhosts
+%attr(-,root,root) %config(noreplace) %{prefix}/lib/smb.conf
+%attr(-,root,root) %config(noreplace) /etc/smbusers
+%attr(-,root,root) /etc/rc.d/init.d/smb
+%attr(-,root,root) /etc/logrotate.d/samba
+%attr(-,root,root) /etc/pam.d/samba
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.437
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.737
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.850
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.852
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.861
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.866
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.932
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.936
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.949
+%attr(-,root,root) %{prefix}/lib/codepages/src/codepage_def.950
+%attr(-,root,root) %{prefix}/man/man1/smbstatus.1
+%attr(-,root,root) %{prefix}/man/man1/smbclient.1
+%attr(-,root,root) %{prefix}/man/man1/make_smbcodepage.1
+%attr(-,root,root) %{prefix}/man/man1/smbrun.1
+%attr(-,root,root) %{prefix}/man/man1/smbtar.1
+%attr(-,root,root) %{prefix}/man/man1/testparm.1
+%attr(-,root,root) %{prefix}/man/man1/testprns.1
+%attr(-,root,root) %{prefix}/man/man1/nmblookup.1
+%attr(-,root,root) %{prefix}/man/man5/smb.conf.5
+%attr(-,root,root) %{prefix}/man/man5/lmhosts.5
+%attr(-,root,root) %{prefix}/man/man5/smbpasswd.5
+%attr(-,root,root) %{prefix}/man/man7/samba.7
+%attr(-,root,root) %{prefix}/man/man8/smbd.8
+%attr(-,root,root) %{prefix}/man/man8/nmbd.8
+%attr(-,root,root) %{prefix}/man/man8/smbpasswd.8
+%attr(-,root,root) %{prefix}/man/man8/swat.8
+%attr(-,root,root) %{prefix}/man/man8/smbmnt.8
+%attr(-,root,root) %{prefix}/man/man8/smbmount.8
+%attr(-,root,root) %{prefix}/man/man8/smbspool.8
+%attr(-,root,root) %dir %{prefix}/lib/codepages
+%attr(-,root,root) %dir %{prefix}/lib/codepages/src
+%attr(-,root,root) %dir %{prefix}/var/locks
+%attr(-,root,root) %dir %{prefix}/private
+%attr(-,root,root) %{prefix}/bin/winbindd
+%attr(-,root,root) %{prefix}/bin/samedit
+%attr(-,root,root) /lib/libnss_winbind.so
+%attr(-,root,root) /lib/security/pam_winbind.so
diff --git a/examples/appliance/build.sh b/examples/appliance/build.sh
new file mode 100755
index 00000000000..ad7a4eb5fb3
--- /dev/null
+++ b/examples/appliance/build.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+tar --exclude=CVS -czf /usr/src/redhat/SOURCES/samba-appliance-0.2-src.tar.gz samba-appliance-0.2
+rpm -ba appliance.spec
diff --git a/examples/appliance/smb.conf-appliance b/examples/appliance/smb.conf-appliance
new file mode 100644
index 00000000000..a3c62256c5a
--- /dev/null
+++ b/examples/appliance/smb.conf-appliance
@@ -0,0 +1,8 @@
+[global]
+ workgroup = DOMAIN
+ security = domain
+ encrypt passwords = true
+ stat cache = false
+ winbind uid = 10000-20000
+ winbind gid = 10000-20000
+ password server = PDC
diff --git a/examples/auth/Makefile b/examples/auth/Makefile
new file mode 100644
index 00000000000..dac28fdd40a
--- /dev/null
+++ b/examples/auth/Makefile
@@ -0,0 +1,31 @@
+# Makefile for samba-pdb examples
+# Variables
+
+CC = gcc
+LIBTOOL = libtool
+
+SAMBA_SRC = ../../source
+SAMBA_INCL = ../../source/include
+UBIQX_SRC = ../../source/ubiqx
+SMBWR_SRC = ../../source/smbwrapper
+CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g
+AUTH_OBJS = auth_skel.so
+
+# Default target
+
+default: $(AUTH_OBJS)
+
+# Pattern rules
+
+%.so: %.lo
+ $(LIBTOOL) $(CC) -shared -o $@ $< $(LDFLAGS)
+
+%.lo: %.c
+ $(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
+
+# Misc targets
+
+clean:
+ rm -rf .libs
+ rm -f core *~ *% *.bak \
+ $(AUTH_OBJS) $(AUTH_OBJS:.so=.o) $(AUTH_OBJS:.so=.lo)
diff --git a/examples/auth/auth_skel.c b/examples/auth/auth_skel.c
new file mode 100644
index 00000000000..bcc3bdd96a3
--- /dev/null
+++ b/examples/auth/auth_skel.c
@@ -0,0 +1,59 @@
+/*
+ Unix SMB/CIFS implementation.
+ Password and authentication handling
+ Copyright (C) Andrew Bartlett 2001
+ Copyright (C) Jelmer Vernooij 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+static NTSTATUS check_skel_security(const struct auth_context *auth_context,
+ void *my_private_data,
+ TALLOC_CTX *mem_ctx,
+ const auth_usersupplied_info *user_info,
+ auth_serversupplied_info **server_info)
+{
+ if (!user_info || !auth_context) {
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ /* Insert your authentication checking code here,
+ * and return NT_STATUS_OK if authentication succeeds */
+
+ /* For now, just refuse all connections */
+ return NT_STATUS_LOGON_FAILURE;
+}
+
+/* module initialisation */
+NTSTATUS auth_init_skel(struct auth_context *auth_context, const char *param, auth_methods **auth_method)
+{
+ if (!make_auth_methods(auth_context, auth_method)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*auth_method)->auth = check_skel_security;
+ (*auth_method)->name = "skel";
+ return NT_STATUS_OK;
+}
+
+NTSTATUS init_module(void)
+{
+ return smb_register_auth(AUTH_INTERFACE_VERSION, "skel", auth_init_skel);
+}
diff --git a/examples/autofs/auto.a b/examples/autofs/auto.a
new file mode 100644
index 00000000000..0fa8f4efc30
--- /dev/null
+++ b/examples/autofs/auto.a
@@ -0,0 +1,15 @@
+# automount points below /a
+
+# This is an automounter map and it has the following format
+# key [ -mount-options-separated-by-comma ] location
+# Details may be found in the autofs(5) manpage
+
+# nfs servers
+valepp -fstype=nfs,rsize=8192,wsize=8192 valepp:/
+galaun -fstype=nfs,rsize=8192,wsize=8192 galaun:/
+
+# smb-servers
+supra_andreas -fstype=smb,username=andreas,password=foo ://supra/aheinrich
+supra_cspiel -fstype=smb,username=cspiel ://supra/cspiel
+phonon_andreas -fstype=smb,username=andreas ://phonon/andreas
+helium_cspiel -fstype=smb,username=cspiel ://helium/cspiel
diff --git a/examples/dce-dfs/README b/examples/dce-dfs/README
new file mode 100644
index 00000000000..4aaba8bb33e
--- /dev/null
+++ b/examples/dce-dfs/README
@@ -0,0 +1,4 @@
+this is a sample configuration file from Jim Doyle <doyle@oec.com> who
+did the DCE/DFS patches for Samba. It shows how to make DCE/DFS shares
+available.
+
diff --git a/examples/dce-dfs/smb.conf b/examples/dce-dfs/smb.conf
new file mode 100644
index 00000000000..f5f155b8e6c
--- /dev/null
+++ b/examples/dce-dfs/smb.conf
@@ -0,0 +1,42 @@
+[global]
+ printing = bsd
+ printcap name = /etc/printcap
+ load printers = no
+ guest account = guest
+ log file = /usr/local/samba/var/log.%m
+ log level = 8
+ password level = 8
+
+[homes]
+ comment = Home Directories
+ browseable = no
+ read only = no
+ create mode = 0750
+
+[test]
+ comment = test stuff
+ path = /dept/mis/home/testacct
+ valid users = testacct
+ public = no
+ writable = yes
+
+[namespace]
+ comment = DCE-DFS Global Root
+ path = /...
+ public = no
+ writable = yes
+
+[oecdfs]
+ comment = Corporate Cell
+ path = /.../corp.boston.oec.com/fs
+ browseable = no
+ read only = no
+ create mode = 0750
+
+[develdfs]
+ comment = Technology Development Cell
+ path = /.../devel.boston.oec.com/fs
+ browseable = no
+ read only = no
+ create mode = 0750
+
diff --git a/examples/genlogon/genlogon.pl b/examples/genlogon/genlogon.pl
new file mode 100644
index 00000000000..8ebf3921411
--- /dev/null
+++ b/examples/genlogon/genlogon.pl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+#
+# genlogon.pl
+#
+# Perl script to generate user logon scripts on the fly, when users
+# connect from a Windows client. This script should be called from smb.conf
+# with the %U, %G and %L parameters. I.e:
+#
+# root preexec = genlogon.pl %U %G %L
+#
+# The script generated will perform
+# the following:
+#
+# 1. Log the user connection to /var/log/samba/netlogon.log
+# 2. Set the PC's time to the Linux server time (which is maintained
+# daily to the National Institute of Standard's Atomic clock on the
+# internet.
+# 3. Connect the user's home drive to H: (H for Home).
+# 4. Connect common drives that everyone uses.
+# 5. Connect group-specific drives for certain user groups.
+# 6. Connect user-specific drives for certain users.
+# 7. Connect network printers.
+
+# Log client connection
+#($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+open LOG, ">>/var/log/samba/netlogon.log";
+print LOG "$mon/$mday/$year $hour:$min:$sec - User $ARGV[0] logged into $ARGV[1]\n";
+close LOG;
+
+# Start generating logon script
+open LOGON, ">/shared/netlogon/$ARGV[0].bat";
+print LOGON "\@ECHO OFF\r\n";
+
+# Connect shares just use by Software Development group
+if ($ARGV[1] eq "SOFTDEV" || $ARGV[0] eq "softdev")
+{
+ print LOGON "NET USE M: \\\\$ARGV[2]\\SOURCE\r\n";
+}
+
+# Connect shares just use by Technical Support staff
+if ($ARGV[1] eq "SUPPORT" || $ARGV[0] eq "support")
+{
+ print LOGON "NET USE S: \\\\$ARGV[2]\\SUPPORT\r\n";
+}
+
+# Connect shares just used by Administration staff
+If ($ARGV[1] eq "ADMIN" || $ARGV[0] eq "admin")
+{
+ print LOGON "NET USE L: \\\\$ARGV[2]\\ADMIN\r\n";
+ print LOGON "NET USE K: \\\\$ARGV[2]\\MKTING\r\n";
+}
+
+# Now connect Printers. We handle just two or three users a little
+# differently, because they are the exceptions that have desktop
+# printers on LPT1: - all other user's go to the LaserJet on the
+# server.
+if ($ARGV[0] eq 'jim'
+ || $ARGV[0] eq 'yvonne')
+{
+ print LOGON "NET UsE LPT2: \\\\$ARGV[2]\\LJET3\r\n";
+ print LOGON "NET USE LPT3: \\\\$ARGV[2]\\FAXQ\r\n";
+}
+else
+{
+ print LOGON "NET USE LPT1: \\\\$ARGV[2]\\LJET3\r\n";
+ print LOGON "NET USE LPT3: \\\\$ARGV[2]\\FAXQ\r\n";
+}
+
+# All done! Close the output file.
+close LOGON;
diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile
new file mode 100644
index 00000000000..fcd5ef29003
--- /dev/null
+++ b/examples/libsmbclient/Makefile
@@ -0,0 +1,36 @@
+#
+CC = gcc
+
+SAMBA_INCL = ../../source/include
+EXTLIB_INCL = -I/usr/include/gtk-1.2 \
+ -I/usr/include/glib-1.2 \
+ -I/usr/lib/glib/include
+
+CFLAGS = -I$(SAMBA_INCL) $(EXTLIB_INCL)
+
+LDFLAGS = -L/usr/lib
+
+all: testsmbc tree testacl testbrowse
+
+testsmbc: testsmbc.o
+ @echo Linking testsmbc
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lsmbclient -L/usr/local/lib
+
+testsmbc-static: testsmbc.o
+ @echo Linking testsmbc
+ @$(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $< -lsmbclient -ldl -lnsl
+
+tree: tree.o
+ @echo Linking tree
+ @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient $<
+
+testacl: testacl.o
+ @echo Linking testacl
+ @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient -lpopt $<
+
+testbrowse: testbrowse.o
+ @echo Linking testbrowse
+ @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -lsmbclient -lpopt $<
+
+clean:
+ @rm -f *.o *~
diff --git a/examples/libsmbclient/README b/examples/libsmbclient/README
new file mode 100644
index 00000000000..d9a9f829174
--- /dev/null
+++ b/examples/libsmbclient/README
@@ -0,0 +1,8 @@
+Some simple example programs for libsmbclient ...
+
+testsmbc.c is kinda broken as it has many hardcoded bits in it
+
+tree.c is an example of how you might do some of these things with GTK+
+It needs lots of work but shows you some ways to use libsmbclient.
+
+Richard Sharpe, 17-May-2001 ...
diff --git a/examples/libsmbclient/testacl.c b/examples/libsmbclient/testacl.c
new file mode 100644
index 00000000000..47668f7c9c4
--- /dev/null
+++ b/examples/libsmbclient/testacl.c
@@ -0,0 +1,280 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <popt.h>
+#include "libsmbclient.h"
+
+enum acl_mode
+{
+ SMB_ACL_GET,
+ SMB_ACL_SET,
+ SMB_ACL_DELETE,
+ SMB_ACL_MODIFY,
+ SMB_ACL_ADD,
+ SMB_ACL_CHOWN,
+ SMB_ACL_CHGRP
+};
+
+static void
+get_auth_data_fn(const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int maxLenWorkgroup,
+ char * pUsername,
+ int maxLenUsername,
+ char * pPassword,
+ int maxLenPassword)
+
+{
+ char temp[128];
+
+ fprintf(stdout, "Workgroup: [%s] ", pWorkgroup);
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == '\n') /* A new line? */
+ {
+ temp[strlen(temp) - 1] = '\0';
+ }
+
+ if (temp[0] != '\0')
+ {
+ strncpy(pWorkgroup, temp, maxLenWorkgroup - 1);
+ }
+
+ fprintf(stdout, "Username: [%s] ", pUsername);
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == '\n') /* A new line? */
+ {
+ temp[strlen(temp) - 1] = '\0';
+ }
+
+ if (temp[0] != '\0')
+ {
+ strncpy(pUsername, temp, maxLenUsername - 1);
+ }
+
+ fprintf(stdout, "Password: ");
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == '\n') /* A new line? */
+ {
+ temp[strlen(temp) - 1] = '\0';
+ }
+
+ if (temp[0] != '\0')
+ {
+ strncpy(pPassword, temp, maxLenPassword - 1);
+ }
+}
+
+
+int main(int argc, const char *argv[])
+{
+ int opt;
+ int flags;
+ int debug = 0;
+ int numeric = 0;
+ enum acl_mode mode = SMB_ACL_GET;
+ static char *the_acl = NULL;
+ int ret;
+ char *p;
+ char *debugstr;
+ char path[1024];
+ char value[1024];
+ poptContext pc;
+ struct poptOption long_options[] =
+ {
+ POPT_AUTOHELP
+ {
+ "numeric", 'n', POPT_ARG_NONE, &numeric,
+ 1, "Don't resolve sids or masks to names"
+ },
+ {
+ "debug", 'd', POPT_ARG_INT, &debug,
+ 0, "Set debug level (0-100)"
+ },
+ {
+ "delete", 'D', POPT_ARG_STRING, NULL,
+ 'D', "Delete an acl", "ACL"
+ },
+ {
+ "modify", 'M', POPT_ARG_STRING, NULL,
+ 'M', "Modify an acl", "ACL"
+ },
+ {
+ "add", 'a', POPT_ARG_STRING, NULL,
+ 'a', "Add an acl", "ACL"
+ },
+ {
+ "set", 'S', POPT_ARG_STRING, NULL,
+ 'S', "Set acls", "ACLS"
+ },
+ {
+ "chown", 'C', POPT_ARG_STRING, NULL,
+ 'C', "Change ownership of a file", "USERNAME"
+ },
+ {
+ "chgrp", 'G', POPT_ARG_STRING, NULL,
+ 'G', "Change group ownership of a file", "GROUPNAME"
+ },
+ {
+ "get", 'g', POPT_ARG_STRING, NULL,
+ 'g', "Get a specific acl attribute", "ACL"
+ },
+ {
+ NULL
+ }
+ };
+
+ setbuf(stdout, NULL);
+
+ pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "smb://server1/share1/filename");
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'S':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_SET;
+ break;
+
+ case 'D':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_DELETE;
+ break;
+
+ case 'M':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_MODIFY;
+ break;
+
+ case 'a':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_ADD;
+ break;
+
+ case 'g':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_GET;
+ break;
+
+ case 'C':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_CHOWN;
+ break;
+
+ case 'G':
+ the_acl = strdup(poptGetOptArg(pc));
+ mode = SMB_ACL_CHGRP;
+ break;
+ }
+ }
+
+ /* Make connection to server */
+ if(!poptPeekArg(pc)) {
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+
+ strcpy(path, poptGetArg(pc));
+
+ if (smbc_init(get_auth_data_fn, debug) != 0)
+ {
+ printf("Could not initialize smbc_ library\n");
+ return 1;
+ }
+
+ /* Perform requested action */
+
+ switch(mode)
+ {
+ case SMB_ACL_GET:
+ if (the_acl == NULL)
+ {
+ if (numeric)
+ {
+ the_acl = "system.nt_sec_desc.*";
+ }
+ else
+ {
+ the_acl = "system.nt_sec_desc.*+";
+ }
+ }
+ ret = smbc_getxattr(path, the_acl, value, sizeof(value));
+ if (ret < 0)
+ {
+ printf("Could not get attributes for [%s] %d: %s\n",
+ path, errno, strerror(errno));
+ return 1;
+ }
+
+ printf("Attributes for [%s] are:\n%s\n", path, value);
+ break;
+
+ case SMB_ACL_ADD:
+ flags = SMBC_XATTR_FLAG_CREATE;
+ debugstr = "add attributes";
+ goto do_set;
+
+ case SMB_ACL_MODIFY:
+ flags = SMBC_XATTR_FLAG_REPLACE;
+ debugstr = "modify attributes";
+ goto do_set;
+
+ case SMB_ACL_CHOWN:
+ snprintf(value, sizeof(value),
+ "system.nt_sec_desc.owner%s:%s",
+ numeric ? "" : "+", the_acl);
+ the_acl = value;
+ debugstr = "chown owner";
+ goto do_set;
+
+ case SMB_ACL_CHGRP:
+ snprintf(value, sizeof(value),
+ "system.nt_sec_desc.group%s:%s",
+ numeric ? "" : "+", the_acl);
+ the_acl = value;
+ debugstr = "change group";
+ goto do_set;
+
+ case SMB_ACL_SET:
+ flags = 0;
+ debugstr = "set attributes";
+
+ do_set:
+ if ((p = strchr(the_acl, ':')) == NULL)
+ {
+ printf("Missing value. ACL must be name:value pair\n");
+ return 1;
+ }
+
+ *p++ = '\0';
+
+ ret = smbc_setxattr(path, the_acl, p, strlen(p), flags);
+ if (ret < 0)
+ {
+ printf("Could not %s for [%s] %d: %s\n",
+ debugstr, path, errno, strerror(errno));
+ return 1;
+ }
+ break;
+
+ case SMB_ACL_DELETE:
+ ret = smbc_removexattr(path, the_acl);
+ if (ret < 0)
+ {
+ printf("Could not remove attribute %s for [%s] %d:%s\n",
+ the_acl, path, errno, strerror(errno));
+ return 1;
+ }
+ break;
+
+ default:
+ printf("operation not yet implemented\n");
+ break;
+ }
+
+ return 0;
+}
diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c
new file mode 100644
index 00000000000..d2472230a20
--- /dev/null
+++ b/examples/libsmbclient/testbrowse.c
@@ -0,0 +1,91 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB client library test program for browsing with different master browsers
+ Copyright (C) Derrell Lipman 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libsmbclient.h>
+
+static void
+auth_fn(const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int workgroup_len,
+ char * pUsername,
+ int username_len,
+ char * pPassword,
+ int password_len)
+
+{
+ strncpy(pUsername, "anonymous", username_len); /* doesn't matter what */
+ strncpy(pPassword, "password", password_len); /* ditto */
+}
+
+
+int
+main(int argc, char * argv[])
+{
+ int debug = 4;
+ int opt;
+ char * p;
+ char buf[1024];
+ int dir;
+ struct smbc_dirent * dirent;
+ char ** ppUrl;
+ char * urlList[] =
+ {
+ "smb://",
+ "smb://?mb=.any",
+ "smb://?mb=.all",
+ "smb://?mb=xx", /* this one is suupposed to fail */
+ NULL
+ };
+
+ if (smbc_init(auth_fn, debug) != 0)
+ {
+ printf("Could not initialize smbc_ library\n");
+ return 1;
+ }
+
+ for (ppUrl = urlList; *ppUrl != NULL; ppUrl++)
+ {
+ printf("Opening (%s)...\n", *ppUrl);
+
+ if ((dir = smbc_opendir(*ppUrl)) < 0)
+ {
+ printf("Could not open [%s] (%d:%s)\n",
+ *ppUrl, errno, strerror(errno));
+ continue;
+ }
+
+ while ((dirent = smbc_readdir(dir)) != NULL)
+ {
+ printf("%s\n", dirent->name);
+ }
+
+ smbc_closedir(dir);
+ }
+
+ exit(0);
+}
+
diff --git a/examples/libsmbclient/testsmbc.c b/examples/libsmbclient/testsmbc.c
new file mode 100644
index 00000000000..888a9c0d4f9
--- /dev/null
+++ b/examples/libsmbclient/testsmbc.c
@@ -0,0 +1,335 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB client library test program
+ Copyright (C) Andrew Tridgell 1998
+ Copyright (C) Richard Sharpe 2000
+ Copyright (C) John Terpsra 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libsmbclient.h>
+
+void auth_fn(const char *server, const char *share,
+ char *workgroup, int wgmaxlen, char *username, int unmaxlen,
+ char *password, int pwmaxlen)
+{
+ char temp[128];
+
+ fprintf(stdout, "Need password for //%s/%s\n", server, share);
+
+ fprintf(stdout, "Enter workgroup: [%s] ", workgroup);
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */
+ temp[strlen(temp) - 1] = 0x00;
+
+ if (temp[0]) strncpy(workgroup, temp, wgmaxlen - 1);
+
+ fprintf(stdout, "Enter username: [%s] ", username);
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */
+ temp[strlen(temp) - 1] = 0x00;
+
+ if (temp[0]) strncpy(username, temp, unmaxlen - 1);
+
+ fprintf(stdout, "Enter password: [%s] ", password);
+ fgets(temp, sizeof(temp), stdin);
+
+ if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */
+ temp[strlen(temp) - 1] = 0x00;
+
+ if (temp[0]) strncpy(password, temp, pwmaxlen - 1);
+
+}
+
+int global_id = 0;
+
+void print_list_fn(struct print_job_info *pji)
+{
+
+ fprintf(stdout, "Print job: ID: %u, Prio: %u, Size: %u, User: %s, Name: %s\n",
+ pji->id, pji->priority, pji->size, pji->user, pji->name);
+
+ global_id = pji->id;
+
+}
+
+int main(int argc, char *argv[])
+{
+ int err, fd, dh1, dh2, dh3, dsize, dirc;
+ const char *file = "smb://samba/public/testfile.txt";
+ const char *file2 = "smb://samba/public/testfile2.txt";
+ char buff[256];
+ char dirbuf[512];
+ char *dirp;
+ struct stat st1, st2;
+
+ err = smbc_init(auth_fn, 10); /* Initialize things */
+
+ if (err < 0) {
+
+ fprintf(stderr, "Initializing the smbclient library ...: %s\n", strerror(errno));
+
+ }
+
+ if (argc > 1) {
+
+ if ((dh1 = smbc_opendir(argv[1]))<1) {
+
+ fprintf(stderr, "Could not open directory: %s: %s\n",
+ argv[1], strerror(errno));
+
+ exit(1);
+
+ }
+
+ fprintf(stdout, "Directory handles: %u, %u, %u\n", dh1, dh2, dh3);
+
+ /* Now, list those directories, but in funny ways ... */
+
+ dirp = (char *)dirbuf;
+
+ if ((dirc = smbc_getdents(dh1, (struct smbc_dirent *)dirp,
+ sizeof(dirbuf))) < 0) {
+
+ fprintf(stderr, "Problems getting directory entries: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ /* Now, process the list of names ... */
+
+ fprintf(stdout, "Directory listing, size = %u\n", dirc);
+
+ while (dirc > 0) {
+
+ dsize = ((struct smbc_dirent *)dirp)->dirlen;
+ fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
+ ((struct smbc_dirent *)dirp)->smbc_type,
+ ((struct smbc_dirent *)dirp)->name,
+ ((struct smbc_dirent *)dirp)->comment);
+
+ dirp += dsize;
+ (char *)dirc -= dsize;
+
+ }
+
+ dirp = (char *)dirbuf;
+
+ exit(1);
+
+ }
+
+ /* For now, open a file on a server that is hard coded ... later will
+ * read from the command line ...
+ */
+
+ fd = smbc_open(file, O_RDWR | O_CREAT | O_TRUNC, 0666);
+
+ if (fd < 0) {
+
+ fprintf(stderr, "Creating file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Opened or created file: %s\n", file);
+
+ /* Now, write some date to the file ... */
+
+ bzero(buff, sizeof(buff));
+ strcpy(buff, "Some test data for the moment ...");
+
+ err = smbc_write(fd, buff, sizeof(buff));
+
+ if (err < 0) {
+
+ fprintf(stderr, "writing file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Wrote %d bytes to file: %s\n", sizeof(buff), buff);
+
+ /* Now, seek the file back to offset 0 */
+
+ err = smbc_lseek(fd, SEEK_SET, 0);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Seeking file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Completed lseek on file: %s\n", file);
+
+ /* Now, read the file contents back ... */
+
+ err = smbc_read(fd, buff, sizeof(buff));
+
+ if (err < 0) {
+
+ fprintf(stderr, "Reading file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Read file: %s\n", buff); /* Should check the contents */
+
+ fprintf(stdout, "Now fstat'ing file: %s\n", file);
+
+ err = smbc_fstat(fd, &st1);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Fstat'ing file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+
+ /* Now, close the file ... */
+
+ err = smbc_close(fd);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Closing file: %s: %s\n", file, strerror(errno));
+
+ }
+
+ /* Now, rename the file ... */
+
+ err = smbc_rename(file, file2);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Renaming file: %s to %s: %s\n", file, file2, strerror(errno));
+
+ }
+
+ fprintf(stdout, "Renamed file %s to %s\n", file, file2);
+
+ /* Now, create a file and delete it ... */
+
+ fprintf(stdout, "Now, creating file: %s so we can delete it.\n", file);
+
+ fd = smbc_open(file, O_RDWR | O_CREAT, 0666);
+
+ if (fd < 0) {
+
+ fprintf(stderr, "Creating file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Opened or created file: %s\n", file);
+
+ err = smbc_close(fd);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Closing file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ /* Now, delete the file ... */
+
+ fprintf(stdout, "File %s created, now deleting ...\n", file);
+
+ err = smbc_unlink(file);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Deleting file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ /* Now, stat the file, file 2 ... */
+
+ fprintf(stdout, "Now stat'ing file: %s\n", file);
+
+ err = smbc_stat(file2, &st2);
+
+ if (err < 0) {
+
+ fprintf(stderr, "Stat'ing file: %s: %s\n", file, strerror(errno));
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Stat'ed file: %s. Size = %d, mode = %04X\n", file2,
+ (int)st2.st_size, st2.st_mode);
+ fprintf(stdout, " time: %s\n", ctime(&st2.st_atime));
+ fprintf(stdout, "Earlier stat: %s, Size = %d, mode = %04X\n", file,
+ (int)st1.st_size, st1.st_mode);
+ fprintf(stdout, " time: %s\n", ctime(&st1.st_atime));
+
+ /* Now, make a directory ... */
+
+ fprintf(stdout, "Making directory smb://samba/public/make-dir\n");
+
+ if (smbc_mkdir("smb://samba/public/make-dir", 0666) < 0) {
+
+ fprintf(stderr, "Error making directory: smb://samba/public/make-dir: %s\n",
+ strerror(errno));
+
+ if (errno == EEXIST) { /* Try to delete the directory */
+
+ fprintf(stdout, "Trying to delete directory: smb://samba/public/make-dir\n");
+
+ if (smbc_rmdir("smb://samba/public/make-dir") < 0) { /* Error */
+
+ fprintf(stderr, "Error removing directory: smb://samba/public/make-dir: %s\n", strerror(errno));
+
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Making directory: smb://samba/public/make-dir\n");
+
+ if (smbc_mkdir("smb://samba/public/make-dir", 666) < 0) {
+
+ fprintf(stderr, "Error making directory: smb://samba/public/make-dir: %s\n",
+ strerror(errno));
+
+ fprintf(stderr, "I give up!\n");
+
+ exit(1);
+
+ }
+
+ }
+
+ exit(0);
+
+ }
+
+ fprintf(stdout, "Made dir: make-dir\n");
+ return 0;
+}
diff --git a/examples/libsmbclient/tree.c b/examples/libsmbclient/tree.c
new file mode 100644
index 00000000000..f50b3670cff
--- /dev/null
+++ b/examples/libsmbclient/tree.c
@@ -0,0 +1,813 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB client GTK+ tree-based application
+ Copyright (C) Andrew Tridgell 1998
+ Copyright (C) Richard Sharpe 2001
+ Copyright (C) John Terpstra 2001
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* example-gtk+ application, ripped off from the gtk+ tree.c sample */
+
+#include <stdio.h>
+#include <errno.h>
+#include <gtk/gtk.h>
+#include "libsmbclient.h"
+
+static GtkWidget *clist;
+
+struct tree_data {
+
+ guint32 type; /* Type of tree item, an SMBC_TYPE */
+ char name[256]; /* May need to change this later */
+
+};
+
+void error_message(gchar *message) {
+
+ GtkWidget *dialog, *label, *okay_button;
+
+ /* Create the widgets */
+
+ dialog = gtk_dialog_new();
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ label = gtk_label_new (message);
+ okay_button = gtk_button_new_with_label("Okay");
+
+ /* Ensure that the dialog box is destroyed when the user clicks ok. */
+
+ gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
+ okay_button);
+
+ /* Add the label, and show everything we've added to the dialog. */
+
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
+ label);
+ gtk_widget_show_all (dialog);
+}
+
+/*
+ * We are given a widget, and we want to retrieve its URL so we
+ * can do a directory listing.
+ *
+ * We walk back up the tree, picking up pieces until we hit a server or
+ * workgroup type and return a path from there
+ */
+
+static char path_string[1024];
+
+char *get_path(GtkWidget *item)
+{
+ GtkWidget *p = item;
+ struct tree_data *pd;
+ char *comps[1024]; /* We keep pointers to the components here */
+ int i = 0, j, level,type;
+
+ /* Walk back up the tree, getting the private data */
+
+ level = GTK_TREE(item->parent)->level;
+
+ /* Pick up this item's component info */
+
+ pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item));
+
+ comps[i++] = pd->name;
+ type = pd->type;
+
+ while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) {
+
+ /* Find the parent and extract the data etc ... */
+
+ p = GTK_WIDGET(p->parent);
+ p = GTK_WIDGET(GTK_TREE(p)->tree_owner);
+
+ pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p));
+
+ level = GTK_TREE(item->parent)->level;
+
+ comps[i++] = pd->name;
+ type = pd->type;
+
+ }
+
+ /*
+ * Got a list of comps now, should check that we did not hit a workgroup
+ * when we got other things as well ... Later
+ *
+ * Now, build the path
+ */
+
+ snprintf(path_string, sizeof(path_string), "smb:/");
+
+ for (j = i - 1; j >= 0; j--) {
+
+ strncat(path_string, "/", sizeof(path_string) - strlen(path_string));
+ strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string));
+
+ }
+
+ fprintf(stdout, "Path string = %s\n", path_string);
+
+ return path_string;
+
+}
+
+struct tree_data *make_tree_data(guint32 type, const char *name)
+{
+ struct tree_data *p = (struct tree_data *)malloc(sizeof(struct tree_data));
+
+ if (p) {
+
+ p->type = type;
+ strncpy(p->name, name, sizeof(p->name));
+
+ }
+
+ return p;
+
+}
+
+/* Note that this is called every time the user clicks on an item,
+ whether it is already selected or not. */
+static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
+ GtkWidget *subtree)
+{
+ gint dh, err, dirlen;
+ char dirbuf[512];
+ struct smbc_dirent *dirp;
+ struct stat st1;
+ char path[1024], path1[1024];
+
+ g_print ("select_child called for root tree %p, subtree %p, child %p\n",
+ root_tree, subtree, child);
+
+ /* Now, figure out what it is, and display it in the clist ... */
+
+ gtk_clist_clear(GTK_CLIST(clist)); /* Clear the CLIST */
+
+ /* Now, get the private data for the subtree */
+
+ strncpy(path, get_path(child), 1024);
+
+ if ((dh = smbc_opendir(path)) < 0) { /* Handle error */
+
+ g_print("cb_select_child: Could not open dir %s, %s\n", path,
+ strerror(errno));
+
+ gtk_main_quit();
+
+ return;
+
+ }
+
+ while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
+ sizeof(dirbuf))) != 0) {
+
+ if (err < 0) {
+
+ g_print("cb_select_child: Could not read dir %s, %s\n", path,
+ strerror(errno));
+
+ gtk_main_quit();
+
+ return;
+
+ }
+
+ dirp = (struct smbc_dirent *)dirbuf;
+
+ while (err > 0) {
+ gchar col1[128], col2[128], col3[128], col4[128];
+ gchar *rowdata[4] = {col1, col2, col3, col4};
+
+ dirlen = dirp->dirlen;
+
+ /* Format each of the items ... */
+
+ strncpy(col1, dirp->name, 128);
+
+ col2[0] = col3[0] = col4[0] = (char)0;
+
+ switch (dirp->smbc_type) {
+
+ case SMBC_WORKGROUP:
+
+ break;
+
+ case SMBC_SERVER:
+
+ strncpy(col2, (dirp->comment?dirp->comment:""), 128);
+
+ break;
+
+ case SMBC_FILE_SHARE:
+
+ strncpy(col2, (dirp->comment?dirp->comment:""), 128);
+
+ break;
+
+ case SMBC_PRINTER_SHARE:
+
+ strncpy(col2, (dirp->comment?dirp->comment:""), 128);
+ break;
+
+ case SMBC_COMMS_SHARE:
+
+ break;
+
+ case SMBC_IPC_SHARE:
+
+ break;
+
+ case SMBC_DIR:
+ case SMBC_FILE:
+
+ /* Get stats on the file/dir and see what we have */
+
+ if ((strcmp(dirp->name, ".") != 0) &&
+ (strcmp(dirp->name, "..") != 0)) {
+
+ strncpy(path1, path, sizeof(path1));
+ strncat(path1, "/", sizeof(path) - strlen(path));
+ strncat(path1, dirp->name, sizeof(path) - strlen(path));
+
+ if (smbc_stat(path1, &st1) < 0) {
+
+ if (errno != EBUSY) {
+
+ g_print("cb_select_child: Could not stat file %s, %s\n", path1,
+ strerror(errno));
+
+ gtk_main_quit();
+
+ return;
+
+ }
+ else {
+
+ strncpy(col2, "Device or resource busy", sizeof(col2));
+
+ }
+ }
+ else {
+ /* Now format each of the relevant things ... */
+
+ snprintf(col2, sizeof(col2), "%c%c%c%c%c%c%c%c%c(%0X)",
+ (st1.st_mode&S_IRUSR?'r':'-'),
+ (st1.st_mode&S_IWUSR?'w':'-'),
+ (st1.st_mode&S_IXUSR?'x':'-'),
+ (st1.st_mode&S_IRGRP?'r':'-'),
+ (st1.st_mode&S_IWGRP?'w':'-'),
+ (st1.st_mode&S_IXGRP?'x':'-'),
+ (st1.st_mode&S_IROTH?'r':'-'),
+ (st1.st_mode&S_IWOTH?'w':'-'),
+ (st1.st_mode&S_IXOTH?'x':'-'),
+ st1.st_mode);
+ snprintf(col3, sizeof(col3), "%u", st1.st_size);
+ snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_mtime));
+ }
+ }
+
+ break;
+
+ default:
+
+ break;
+ }
+
+ gtk_clist_append(GTK_CLIST(clist), rowdata);
+
+ (char *)dirp += dirlen;
+ err -= dirlen;
+
+ }
+
+ }
+
+}
+
+/* Note that this is never called */
+static void cb_unselect_child( GtkWidget *root_tree,
+ GtkWidget *child,
+ GtkWidget *subtree )
+{
+ g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
+ root_tree, subtree, child);
+}
+
+/* for all the GtkItem:: and GtkTreeItem:: signals */
+static void cb_itemsignal( GtkWidget *item,
+ gchar *signame )
+{
+ GtkWidget *real_tree, *aitem, *subtree;
+ gchar *name;
+ GtkLabel *label;
+ gint dh, err, dirlen, level;
+ char dirbuf[512];
+ struct smbc_dirent *dirp;
+
+ label = GTK_LABEL (GTK_BIN (item)->child);
+ /* Get the text of the label */
+ gtk_label_get (label, &name);
+
+ level = GTK_TREE(item->parent)->level;
+
+ /* Get the level of the tree which the item is in */
+ g_print ("%s called for item %s->%p, level %d\n", signame, name,
+ item, GTK_TREE (item->parent)->level);
+
+ real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */
+
+ if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
+ char server[128];
+
+ if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */
+ gchar errmsg[256];
+
+ g_print("cb_itemsignal: Could not open dir %s, %s\n", get_path(item),
+ strerror(errno));
+
+ snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno));
+
+ error_message(errmsg);
+
+ /* gtk_main_quit();*/
+
+ return;
+
+ }
+
+ while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
+ sizeof(dirbuf))) != 0) {
+
+ if (err < 0) { /* An error, report it */
+ gchar errmsg[256];
+
+ g_print("cb_itemsignal: Could not read dir smbc://, %s\n",
+ strerror(errno));
+
+ snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno));
+
+ error_message(errmsg);
+
+ /* gtk_main_quit();*/
+
+ return;
+
+ }
+
+ dirp = (struct smbc_dirent *)dirbuf;
+
+ while (err > 0) {
+ struct tree_data *my_data;
+
+ dirlen = dirp->dirlen;
+
+ my_data = make_tree_data(dirp->smbc_type, dirp->name);
+
+ if (!my_data) {
+
+ g_print("Could not allocate space for tree_data: %s\n",
+ dirp->name);
+
+ gtk_main_quit();
+ return;
+
+ }
+
+ aitem = gtk_tree_item_new_with_label(dirp->name);
+
+ /* Connect all GtkItem:: and GtkTreeItem:: signals */
+ gtk_signal_connect (GTK_OBJECT(aitem), "select",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "select");
+ gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
+ gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
+ gtk_signal_connect (GTK_OBJECT(aitem), "expand",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
+ gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
+ /* Add it to the parent tree */
+ gtk_tree_append (GTK_TREE(real_tree), aitem);
+
+ gtk_widget_show (aitem);
+
+ gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
+
+ fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
+
+ if (dirp->smbc_type != SMBC_FILE &&
+ dirp->smbc_type != SMBC_IPC_SHARE &&
+ (strcmp(dirp->name, ".") != 0) &&
+ (strcmp(dirp->name, "..") !=0)){
+
+ subtree = gtk_tree_new();
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
+
+ gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), real_tree);
+ gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
+
+ }
+
+ (char *)dirp += dirlen;
+ err -= dirlen;
+
+ }
+
+ }
+
+ smbc_closedir(dh);
+
+ }
+ else if (strncmp(signame, "collapse", 8) == 0) {
+ GtkWidget *subtree = gtk_tree_new();
+
+ gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
+
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
+
+ gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), real_tree);
+ gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
+
+ }
+
+}
+
+static void cb_selection_changed( GtkWidget *tree )
+{
+ GList *i;
+
+ g_print ("selection_change called for tree %p\n", tree);
+ g_print ("selected objects are:\n");
+
+ i = GTK_TREE_SELECTION(tree);
+ while (i){
+ gchar *name;
+ GtkLabel *label;
+ GtkWidget *item;
+
+ /* Get a GtkWidget pointer from the list node */
+ item = GTK_WIDGET (i->data);
+ label = GTK_LABEL (GTK_BIN (item)->child);
+ gtk_label_get (label, &name);
+ g_print ("\t%s on level %d\n", name, GTK_TREE
+ (item->parent)->level);
+ i = i->next;
+ }
+}
+
+/*
+ * Expand or collapse the whole network ...
+ */
+static void cb_wholenet(GtkWidget *item, gchar *signame)
+{
+ GtkWidget *real_tree, *aitem, *subtree;
+ gchar *name;
+ GtkLabel *label;
+ gint dh, err, dirlen;
+ char dirbuf[512];
+ struct smbc_dirent *dirp;
+
+ label = GTK_LABEL (GTK_BIN (item)->child);
+ gtk_label_get (label, &name);
+ g_print ("%s called for item %s->%p, level %d\n", signame, name,
+ item, GTK_TREE (item->parent)->level);
+
+ real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */
+
+ if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
+
+ if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */
+
+ g_print("cb_wholenet: Could not open dir smbc://, %s\n",
+ strerror(errno));
+
+ gtk_main_quit();
+
+ return;
+
+ }
+
+ while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
+ sizeof(dirbuf))) != 0) {
+
+ if (err < 0) { /* An error, report it */
+
+ g_print("cb_wholenet: Could not read dir smbc://, %s\n",
+ strerror(errno));
+
+ gtk_main_quit();
+
+ return;
+
+ }
+
+ dirp = (struct smbc_dirent *)dirbuf;
+
+ while (err > 0) {
+ struct tree_data *my_data;
+
+ dirlen = dirp->dirlen;
+
+ my_data = make_tree_data(dirp->smbc_type, dirp->name);
+
+ aitem = gtk_tree_item_new_with_label(dirp->name);
+
+ /* Connect all GtkItem:: and GtkTreeItem:: signals */
+ gtk_signal_connect (GTK_OBJECT(aitem), "select",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "select");
+ gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
+ gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
+ gtk_signal_connect (GTK_OBJECT(aitem), "expand",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
+ gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
+
+ gtk_tree_append (GTK_TREE(real_tree), aitem);
+ /* Show it - this can be done at any time */
+ gtk_widget_show (aitem);
+
+ gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
+
+ fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
+
+ subtree = gtk_tree_new();
+
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
+
+ gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), real_tree);
+ gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
+
+ (char *)dirp += dirlen;
+ err -= dirlen;
+
+ }
+
+ }
+
+ smbc_closedir(dh);
+
+ }
+ else { /* Must be collapse ... FIXME ... */
+ GtkWidget *subtree = gtk_tree_new();
+
+ gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
+
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
+
+ gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), real_tree);
+ gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
+
+
+ }
+
+}
+
+/* Should put up a dialog box to ask the user for username and password */
+
+static void
+auth_fn(const char *server, const char *share,
+ char *workgroup, int wgmaxlen, char *username, int unmaxlen,
+ char *password, int pwmaxlen)
+{
+
+ strncpy(username, "test", unmaxlen);
+ strncpy(password, "test", pwmaxlen);
+
+}
+
+static char *col_titles[] = {
+ "Name", "Attributes", "Size", "Modification Date",
+};
+
+int main( int argc,
+ char *argv[] )
+{
+ GtkWidget *window, *scrolled_win, *scrolled_win2, *tree;
+ GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane;
+ gint err, dh;
+ gint i;
+ char dirbuf[512];
+ struct smbc_dirent *dirp;
+
+ gtk_init (&argc, &argv);
+
+ /* Init the smbclient library */
+
+ err = smbc_init(auth_fn, 10);
+
+ /* Print an error response ... */
+
+ if (err < 0) {
+
+ fprintf(stderr, "smbc_init returned %s (%i)\nDo you have a ~/.smb/smb.conf file?\n", strerror(errno), errno);
+ exit(1);
+
+ }
+
+ /* a generic toplevel window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name(window, "main browser window");
+ gtk_signal_connect (GTK_OBJECT(window), "delete_event",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_window_set_title(GTK_WINDOW(window), "The Linux Windows Network Browser");
+ gtk_widget_set_usize(GTK_WIDGET(window), 750, -1);
+ gtk_container_set_border_width (GTK_CONTAINER(window), 5);
+
+ gtk_widget_show (window);
+
+ /* A container for the two panes ... */
+
+ main_hbox = gtk_hbox_new(FALSE, 1);
+ gtk_container_border_width(GTK_CONTAINER(main_hbox), 1);
+ gtk_container_add(GTK_CONTAINER(window), main_hbox);
+
+ gtk_widget_show(main_hbox);
+
+ l_pane = gtk_hpaned_new();
+ gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
+ r_pane = gtk_hpaned_new();
+ gtk_paned_gutter_size(GTK_PANED(r_pane), (GTK_PANED(r_pane))->handle_size);
+ gtk_container_add(GTK_CONTAINER(main_hbox), l_pane);
+ gtk_widget_show(l_pane);
+
+ /* A generic scrolled window */
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_usize (scrolled_win, 150, 200);
+ gtk_container_add (GTK_CONTAINER(l_pane), scrolled_win);
+ gtk_widget_show (scrolled_win);
+
+ /* Another generic scrolled window */
+ scrolled_win2 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win2),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_usize (scrolled_win2, 150, 200);
+ gtk_paned_add2 (GTK_PANED(l_pane), scrolled_win2);
+ gtk_widget_show (scrolled_win2);
+
+ /* Create the root tree */
+ tree = gtk_tree_new();
+ g_print ("root tree is %p\n", tree);
+ /* connect all GtkTree:: signals */
+ gtk_signal_connect (GTK_OBJECT(tree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), tree);
+ gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), tree);
+ gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
+ GTK_SIGNAL_FUNC(cb_selection_changed), tree);
+ /* Add it to the scrolled window */
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
+ tree);
+ /* Set the selection mode */
+ gtk_tree_set_selection_mode (GTK_TREE(tree),
+ GTK_SELECTION_MULTIPLE);
+ /* Show it */
+ gtk_widget_show (tree);
+
+ /* Now, create a clist and attach it to the second pane */
+
+ clist = gtk_clist_new_with_titles(4, col_titles);
+
+ gtk_container_add (GTK_CONTAINER(scrolled_win2), clist);
+
+ gtk_widget_show(clist);
+
+ /* Now, build the top level display ... */
+
+ if ((dh = smbc_opendir("smb://")) < 0) {
+
+ fprintf(stderr, "Could not list workgroups: smb://: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ /* Create a tree item for Whole Network */
+
+ item = gtk_tree_item_new_with_label ("Whole Network");
+ /* Connect all GtkItem:: and GtkTreeItem:: signals */
+ gtk_signal_connect (GTK_OBJECT(item), "select",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "select");
+ gtk_signal_connect (GTK_OBJECT(item), "deselect",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
+ gtk_signal_connect (GTK_OBJECT(item), "toggle",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
+ gtk_signal_connect (GTK_OBJECT(item), "expand",
+ GTK_SIGNAL_FUNC(cb_wholenet), "expand");
+ gtk_signal_connect (GTK_OBJECT(item), "collapse",
+ GTK_SIGNAL_FUNC(cb_wholenet), "collapse");
+ /* Add it to the parent tree */
+ gtk_tree_append (GTK_TREE(tree), item);
+ /* Show it - this can be done at any time */
+ gtk_widget_show (item);
+
+ subtree = gtk_tree_new(); /* A subtree for Whole Network */
+
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
+
+ gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), tree);
+ gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), tree);
+
+ /* Now, get the items in smb:/// and add them to the tree */
+
+ while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
+ sizeof(dirbuf))) != 0) {
+
+ if (err < 0) { /* Handle the error */
+
+ fprintf(stderr, "Could not read directory for smbc:///: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ dirp = (struct smbc_dirent *)dirbuf;
+
+ fprintf(stdout, "Dir len: %u\n", err);
+
+ while (err > 0) { /* Extract each entry and make a sub-tree */
+ struct tree_data *my_data;
+ int dirlen = dirp->dirlen;
+
+ my_data = make_tree_data(dirp->smbc_type, dirp->name);
+
+ item = gtk_tree_item_new_with_label(dirp->name);
+ /* Connect all GtkItem:: and GtkTreeItem:: signals */
+ gtk_signal_connect (GTK_OBJECT(item), "select",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "select");
+ gtk_signal_connect (GTK_OBJECT(item), "deselect",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
+ gtk_signal_connect (GTK_OBJECT(item), "toggle",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
+ gtk_signal_connect (GTK_OBJECT(item), "expand",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
+ gtk_signal_connect (GTK_OBJECT(item), "collapse",
+ GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
+ /* Add it to the parent tree */
+ gtk_tree_append (GTK_TREE(tree), item);
+ /* Show it - this can be done at any time */
+ gtk_widget_show (item);
+
+ gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data);
+
+ fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
+
+ subtree = gtk_tree_new();
+
+ gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
+
+ gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
+ GTK_SIGNAL_FUNC(cb_select_child), tree);
+ gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
+ GTK_SIGNAL_FUNC(cb_unselect_child), tree);
+
+ (char *)dirp += dirlen;
+ err -= dirlen;
+
+ }
+
+ }
+
+ smbc_closedir(dh); /* FIXME, check for error :-) */
+
+ /* Show the window and loop endlessly */
+ gtk_main();
+ return 0;
+}
+/* example-end */
diff --git a/examples/misc/extra_smbstatus b/examples/misc/extra_smbstatus
new file mode 100644
index 00000000000..7f77d07d00c
--- /dev/null
+++ b/examples/misc/extra_smbstatus
@@ -0,0 +1,50 @@
+Here's something that Paul Blackman sent me that may be useful:
+
+-------------------
+I created this script to do a few things that smbstatus doesn't at the
+moment. Perhaps you might want to include these. Sorry I haven't
+added things at source level, script was quick&easy.
+
+*******
+#!/bin/csh
+if ($1 == "-p") then
+ smbstatus -p |sort -u
+else if ($1 == "-c") then
+ echo There are `smbstatus -p |sort -u |grep -n -v z |grep -c :` unique smbd processes running.
+ else if ($1 == "-l") then
+ echo `date '+ %d/%m/%y %H:%M:%S'` `smbstatus -p |sort -u |grep -n -v z |grep -c :` >>$2
+else if ($1 == "-cs") then
+ echo There are `smbstatus |awk '$1==share {n++;} END {print n}' share=$2` concurrent connections to share: $2
+else if ($1 == "-csl") then
+ echo `date '+ %d/%m/%y %H:%M:%S'` `smbstatus |awk '$1==share {n++;} END {print n}' share=$2` >>$3
+else
+ echo "'smbstat -c' ==> Count unique smbd processes."
+ echo "'smbstat -p' ==> List unique smbd processes."
+ echo "'smbstat -l logfile' ==> Append a log entry for the number of"
+ echo " concurrent and unique processes to logfile."
+ echo "'smbstat -cs sharename'"
+ echo " ==> Count processes connected to sharename (assumed unique)"
+ echo "'smbstat -csl sharename logfile'"
+ echo " ==> Append a log entry for the number of concurrent"
+ echo " processes connected to sharename (assumed unique)"
+endif
+******
+
+Run this script from cron eg.
+
+0,5,10,15,20,25,30,35,40,50,55 * * * * /usr/local/samba/bin/smbstat -l /usr/local/samba/var/smbdcount.log
+
+and you get a good idea of usage over time.
+
+Cheers,
+~^ MIME OK ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
+ o | Paul Blackman ictinus@lake.canberra.edu.au
+ o | Co-operative Research ------------------------
+ o _ | Centre For Freshwater Ecology. Ph. (Aus) 06 2012518
+ -- (") o | University of Canberra, Australia. Fax. " 06 2015038
+ \_|_-- |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | "Spend a little love and get high"
+ _/ \_ | - Lenny Kravitz
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~ SAMBA Web Pages: http://samba.org/samba/ ~~~~~~~~~~~~~~
+
diff --git a/examples/misc/modify_samba_config.pl b/examples/misc/modify_samba_config.pl
new file mode 100755
index 00000000000..ad958625d66
--- /dev/null
+++ b/examples/misc/modify_samba_config.pl
@@ -0,0 +1,154 @@
+#!/usr/bin/perl
+
+##
+## Simple example of how to implement a '[add|delete] share command' for
+## use with the Windows NT Server Manager. See smb.conf(5) for details
+## on the '[add|delete] share command'
+##
+## Author : Gerald (Jerry) Carter <jerry@samba.org>
+##
+
+use POSIX qw(tmpnam);
+
+##
+## local variables
+##
+my $delete_mode = undef;
+my $add_mode = undef;
+my $tmp_file_name = undef;
+
+
+## check for correct parameters
+if ($#ARGV == 1) {
+ $delete_mode = 1;
+}
+elsif ($#ARGV == 3) {
+ $add_mode = 1;
+}
+else {
+ print "Usage: $0 configfile share [path] [comment]\n";
+ exit -1;
+}
+
+## first param is always the config file
+open (CONFIGFILE, "$ARGV[0]") || die "Unable to open $ARGV[0] for reading!\n";
+
+## FIXME!! Right now we throw away all comments in the file.
+while (<CONFIGFILE>) {
+
+ chomp($_);
+
+ ## eat leading whitespace
+ $_ =~ s/^\s*//;
+
+ ## eat trailing whitespace
+ $_ =~ s/\s*$//;
+
+
+ ## throw away comments
+ next if (($_ =~ /^#/) || ($_ =~ /^;/));
+
+ ## set the current section name for storing the hash
+ if ($_ =~ /^\[.*\]$/) {
+
+ $_ = substr($_, 1, length($_)-2);
+
+ if ( length($_) ) {
+ $section = $_;
+ }
+ else {
+ print "Bad Section Name - no closing ]\n";
+ exit -1;
+ }
+
+ next;
+ }
+
+ ## check for a param = value
+ if ($_ =~ /=/) {
+ ($param, $value) = split (/=/, $_,2);
+ $param =~ s/./\l$&/g;
+ $param =~ s/\s+//g;
+ $value =~ s/^\s+//;
+
+ $config{$section}{$param} = $value;
+
+ next;
+ }
+
+ ## should have a hash of hashes indexed by section name
+}
+close (CONFIGFILE);
+
+##
+## We have the smb.conf in our hash of hashes now.
+## Add or delete
+##
+if ($add_mode) {
+ $config{$ARGV[1]}{'path'} = $ARGV[2];
+ $config{$ARGV[1]}{'comment'} = $ARGV[3];
+}
+elsif ($delete_mode) {
+ delete $config{$ARGV[1]};
+}
+
+##
+## Print the resulting configuration
+##
+#do {
+# $tmp_file_name = tmpnam();
+# print "Using temporary file - $tmp_file_name\n";
+#} while (!sysopen(TMP, $tmp_file_name, O_RDWR|O_CREAT|O_EXCL));
+$tmp_file_name = tmpnam();
+open (TMP, ">$tmp_file_name") || die "Unable to open temporary file for writing!\n";
+
+PrintConfigFile(TMP);
+
+## now overwrite the original config file
+close (TMP);
+system ("cp -pf $ARGV[0] $ARGV[0].bak");
+system ("cp -pf $tmp_file_name $ARGV[0]");
+unlink $tmp_file_name;
+
+
+exit 0;
+
+
+
+
+
+#######################################################################################
+## PrintConfigFile()
+##
+sub PrintConfigFile {
+ my ($output) = @_;
+
+ ## print the file back out, beginning with the global section
+ print $output "#\n# Generated by $0\n#\n";
+
+ PrintSection ($output, 'global', $config{'global'});
+
+ foreach $section (keys %config) {
+
+ if ("$section" ne "global") {
+ print $output "## Section - [$section]\n";
+ PrintSection ($output, $section, $config{$section});
+ }
+ }
+
+ print $output "#\n# end of generated smb.conf\n#\n";
+}
+
+#######################################################################################
+## PrintSection()
+##
+sub PrintSection {
+ my ($outfile, $name, $section) = @_;
+
+ print $outfile "[$name]\n";
+ foreach $param (keys %$section) {
+ print $outfile "\t$param".' 'x(25-length($param)). " = $$section{$param}\n";
+ }
+ print $outfile "\n";
+
+}
diff --git a/examples/misc/swat.pl b/examples/misc/swat.pl
new file mode 100644
index 00000000000..f6414b63497
--- /dev/null
+++ b/examples/misc/swat.pl
@@ -0,0 +1,122 @@
+#! /usr/bin/perl5
+##
+## This is a simple script written by Herb Lewis @ SGI <herb@samba.org>
+## for reporting which parameters are supported by loadparm.c but
+## not by SWAT I just thought it looked fun and might be of interest to others
+## --jerry@samba.org
+##
+## Here is a little info on the usage and output format so you don't have
+## to dig through the code to understand what is printed.
+##
+## Useage: swat.pl [path_to_loadparm.c]
+##
+## The output consists of 4 columns of information
+## Option Name, Global Page, Share Page, Printer Page
+## The section separaters will also be printed (preceded by 16 *) to show
+## which options are grouped in the various sections.
+##
+## If the option name is preceded by an * it means this is a deprecated option.
+## If the option name is preceded by 5 spaces it means this is an alias for the
+## previous option.
+##
+## Under the Global Page, Share Page, and Printer Page columns there will be
+## one of 3 entries, BASIC, ADVANCED, or no. "BASIC" indicates this option will
+## show in the Basic View of that page in SWAT. "ADVANCED" indicates this
+## option will show in the Advanced View of that page in SWAT. "No" indicates
+## that this option is not available on that page in SWAT.
+##
+## Under the Global Page column, if an entry begins with an * it indicates that
+## this is actually specified in Samba as a "service parameter" not a "global
+## parameter" but you can set a default value for this on the Global Page in
+## SWAT.
+##
+## --herb@samba.org
+
+$lastone = "nothing";
+
+if (@ARGV[0]) {
+ $filename = @ARGV[0];
+} else {
+ $filename = "/usr3/samba20/samba/source/param/loadparm.c";
+}
+
+open (INFILE,$filename) || die "unable to open $filename\n";
+while (not eof(INFILE))
+{
+ $_ = <INFILE>;
+ last if ( /^static struct parm_struct parm_table/) ;
+}
+print "Option Name Global Page Share Page Printer Page\n";
+print "---------------------------------------------------------------------";
+while (not eof(INFILE))
+{
+ $_ = <INFILE>;
+ last if (/};/);
+ @fields = split(/,/,$_);
+ next if not ($fields[0] =~ /^.*{"/);
+ $fields[0] =~ s/.*{"//;
+ $fields[0] =~ s/"//;
+ if ($fields[3] eq $lastone) {
+ print " $fields[0]\n";
+ next;
+ }
+ $lastone = $fields[3];
+ $fields[2] =~ s/^\s+//;
+ $fields[2] =~ s/\s+$//;
+ $fields[2] =~ s/}.*$//;
+ $fields[6] =~ s/^\s+//;
+ $fields[6] =~ s/\s+$//;
+ $fields[6] =~ s/}.*$//;
+ if ($fields[2] =~ /P_SEPARATOR/) {
+ print "\n****************$fields[0]\n";
+ next;
+ }
+ else {
+ if ($fields[6] =~ /FLAG_DEPRECATED/) {
+ print "*$fields[0]".' 'x(31-length($fields[0]));
+ }
+ else {
+ print "$fields[0]".' 'x(32-length($fields[0]));
+ }
+ }
+ if (($fields[2] =~ /P_GLOBAL/) || ($fields[6] =~ /FLAG_GLOBAL/)) {
+ if ($fields[6] =~ /FLAG_GLOBAL/) {
+ print "*";
+ }
+ else {
+ print " ";
+ }
+ if ($fields[6] =~ /FLAG_BASIC/) {
+ print "BASIC ";
+ }
+ else {
+ print "ADVANCED ";
+ }
+ }
+ else {
+ print " no ";
+ }
+ if ($fields[6] =~ /FLAG_SHARE/) {
+ if ($fields[6] =~ /FLAG_BASIC/) {
+ print "BASIC ";
+ }
+ else {
+ print "ADVANCED ";
+ }
+ }
+ else {
+ print "no ";
+ }
+ if ($fields[6] =~ /FLAG_PRINT/) {
+ if ($fields[6] =~ /FLAG_BASIC/) {
+ print "BASIC";
+ }
+ else {
+ print "ADVANCED";
+ }
+ }
+ else {
+ print "no";
+ }
+ print "\n";
+}
diff --git a/examples/misc/wall.perl b/examples/misc/wall.perl
new file mode 100644
index 00000000000..9303658ce14
--- /dev/null
+++ b/examples/misc/wall.perl
@@ -0,0 +1,69 @@
+#!/usr/local/bin/perl
+#
+#@(#) smb-wall.pl Description:
+#@(#) A perl script which allows you to announce whatever you choose to
+#@(#) every PC client currently connected to a Samba Server...
+#@(#) ...using "smbclient -M" message to winpopup service.
+#@(#) Default usage is to message every connected PC.
+#@(#) Alternate usage is to message every pc on the argument list.
+#@(#) Hacked up by Keith Farrar <farrar@parc.xerox.com>
+#
+# Cleanup and corrections by
+# Michal Jaegermann <michal@ellpspace.math.ualberta.ca>
+# Message to send can be now also fed (quietly) from stdin; a pipe will do.
+#=============================================================================
+
+$smbstatus = "/usr/local/bin/smbstatus";
+$smbshout = "/usr/local/bin/smbclient -M";
+
+if (@ARGV) {
+ @clients = @ARGV;
+ undef @ARGV;
+}
+else { # no clients specified explicitly
+ open(PCLIST, "$smbstatus |") || die "$smbstatus failed!.\n$!\n";
+ while(<PCLIST>) {
+ last if /^Locked files:/;
+ split(' ', $_, 6);
+ # do not accept this line if less then six fields
+ next unless $_[5];
+ # if you have A LOT of clients you may speed things up by
+ # checking pid - no need to look further if this pid was already
+ # seen; left as an exercise :-)
+ $client = $_[4];
+ next unless $client =~ /^\w+\./; # expect 'dot' in a client name
+ next if grep($_ eq $client, @clients); # we want this name once
+ push(@clients, $client);
+ }
+ close(PCLIST);
+}
+
+if (-t) {
+ print <<'EOT';
+
+Enter message for Samba clients of this host
+(terminated with single '.' or end of file):
+EOT
+
+ while (<>) {
+ last if /^\.$/;
+ push(@message, $_);
+ }
+}
+else { # keep quiet and read message from stdin
+ @message = <>;
+}
+
+foreach(@clients) {
+## print "To $_:\n";
+ if (open(SENDMSG,"|$smbshout $_")) {
+ print SENDMSG @message;
+ close(SENDMSG);
+ }
+ else {
+ warn "Cannot notify $_ with $smbshout:\n$!\n";
+ }
+}
+
+exit 0;
+
diff --git a/examples/nss/nss_winbind.c b/examples/nss/nss_winbind.c
new file mode 100644
index 00000000000..968cc7adddc
--- /dev/null
+++ b/examples/nss/nss_winbind.c
@@ -0,0 +1,422 @@
+/*
+ nss sample code for extended winbindd functionality
+
+ Copyright (C) Andrew Tridgell (tridge@samba.org)
+
+ you are free to use this code in any way you see fit, including
+ without restriction, using this code in your own products. You do
+ not need to give any attribution.
+*/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <nss.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "nss_winbind.h"
+
+/*
+ find a function in the nss library
+*/
+static void *find_fn(struct nss_state *nss, const char *name)
+{
+ void *res;
+ char *s = NULL;
+
+ asprintf(&s, "_nss_%s_%s", nss->nss_name, name);
+ if (!s) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ res = dlsym(nss->dl_handle, s);
+ free(s);
+ if (!res) {
+ errno = ENOENT;
+ return NULL;
+ }
+ return res;
+}
+
+/*
+ establish a link to the nss library
+ Return 0 on success and -1 on error
+*/
+int nss_open(struct nss_state *nss, const char *nss_path)
+{
+ char *p;
+ p = strrchr(nss_path, '_');
+ if (!p) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ nss->nss_name = strdup(p+1);
+ p = strchr(nss->nss_name, '.');
+ if (p) *p = 0;
+
+ nss->dl_handle = dlopen(nss_path, RTLD_LAZY);
+ if (!nss->dl_handle) {
+ free(nss->nss_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ close and cleanup a nss state
+*/
+void nss_close(struct nss_state *nss)
+{
+ free(nss->nss_name);
+ dlclose(nss->dl_handle);
+}
+
+/*
+ make a getpwnam call.
+ Return 0 on success and -1 on error
+*/
+int nss_getpwent(struct nss_state *nss, struct passwd *pwd)
+{
+ enum nss_status (*_nss_getpwent_r)(struct passwd *, char *,
+ size_t , int *);
+ enum nss_status status;
+ int nss_errno = 0;
+
+ _nss_getpwent_r = find_fn(nss, "getpwent_r");
+
+ if (!_nss_getpwent_r) {
+ return -1;
+ }
+
+ status = _nss_getpwent_r(pwd, nss->pwnam_buf, sizeof(nss->pwnam_buf),
+ &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ make a setpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_setpwent(struct nss_state *nss)
+{
+ enum nss_status (*_nss_setpwent)(void) = find_fn(nss, "setpwent");
+ enum nss_status status;
+ if (!_nss_setpwent) {
+ return -1;
+ }
+ status = _nss_setpwent();
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ make a endpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_endpwent(struct nss_state *nss)
+{
+ enum nss_status (*_nss_endpwent)(void) = find_fn(nss, "endpwent");
+ enum nss_status status;
+ if (!_nss_endpwent) {
+ return -1;
+ }
+ status = _nss_endpwent();
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ convert a name to a SID
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_nametosid(struct nss_state *nss, const char *name, char **sid)
+{
+ enum nss_status (*_nss_nametosid)(const char *, char **, char *,
+ size_t, int *);
+ enum nss_status status;
+ int nss_errno = 0;
+ char buf[200];
+
+ _nss_nametosid = find_fn(nss, "nametosid");
+
+ if (!_nss_nametosid) {
+ return -1;
+ }
+
+ status = _nss_nametosid(name, sid, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *sid = strdup(*sid);
+
+ return 0;
+}
+
+/*
+ convert a SID to a name
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_sidtoname(struct nss_state *nss, const char *sid, char **name)
+{
+ enum nss_status (*_nss_sidtoname)(const char *, char **, char *,
+ size_t, int *);
+ enum nss_status status;
+ int nss_errno = 0;
+ char buf[200];
+
+ _nss_sidtoname = find_fn(nss, "sidtoname");
+
+ if (!_nss_sidtoname) {
+ return -1;
+ }
+
+ status = _nss_sidtoname(sid, name, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *name = strdup(*name);
+
+ return 0;
+}
+
+/*
+ return a list of group SIDs for a user SID
+ the returned list is NULL terminated
+ Return 0 on success and -1 on error
+*/
+int nss_getusersids(struct nss_state *nss, const char *user_sid, char ***sids)
+{
+ enum nss_status (*_nss_getusersids)(const char *, char **, int *,
+ char *, size_t, int *);
+ enum nss_status status;
+ int nss_errno = 0;
+ char *s;
+ int i, num_groups = 0;
+ unsigned bufsize = 10;
+ char *buf;
+
+ _nss_getusersids = find_fn(nss, "getusersids");
+
+ if (!_nss_getusersids) {
+ return -1;
+ }
+
+again:
+ buf = malloc(bufsize);
+ if (!buf) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ status = _nss_getusersids(user_sid, &s, &num_groups, buf, bufsize,
+ &nss_errno);
+
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ free(buf);
+ return -1;
+ }
+
+ if (status == NSS_STATUS_TRYAGAIN) {
+ bufsize *= 2;
+ free(buf);
+ goto again;
+ }
+
+ if (status != NSS_STATUS_SUCCESS) {
+ free(buf);
+ errno = nss_errno;
+ return -1;
+ }
+
+ if (num_groups == 0) {
+ free(buf);
+ return 0;
+ }
+
+ *sids = (char **)malloc(sizeof(char *) * (num_groups+1));
+ if (! *sids) {
+ errno = ENOMEM;
+ free(buf);
+ return -1;
+ }
+
+ for (i=0;i<num_groups;i++) {
+ (*sids)[i] = strdup(s);
+ s += strlen(s) + 1;
+ }
+ (*sids)[i] = NULL;
+
+ free(buf);
+
+ return 0;
+}
+
+/*
+ convert a sid to a uid
+ Return 0 on success and -1 on error
+*/
+int nss_sidtouid(struct nss_state *nss, const char *sid, uid_t *uid)
+{
+ enum nss_status (*_nss_sidtouid)(const char*, uid_t *, int*);
+
+ enum nss_status status;
+ int nss_errno = 0;
+
+ _nss_sidtouid = find_fn(nss, "sidtouid");
+
+ if (!_nss_sidtouid) {
+ return -1;
+ }
+
+ status = _nss_sidtouid(sid, uid, &nss_errno);
+
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ convert a sid to a gid
+ Return 0 on success and -1 on error
+*/
+int nss_sidtogid(struct nss_state *nss, const char *sid, gid_t *gid)
+{
+ enum nss_status (*_nss_sidtogid)(const char*, gid_t *, int*);
+
+ enum nss_status status;
+ int nss_errno = 0;
+
+ _nss_sidtogid = find_fn(nss, "sidtogid");
+
+ if (!_nss_sidtogid) {
+ return -1;
+ }
+
+ status = _nss_sidtogid(sid, gid, &nss_errno);
+
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ convert a uid to a sid
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_uidtosid(struct nss_state *nss, uid_t uid, char **sid)
+{
+ enum nss_status (*_nss_uidtosid)(uid_t, char **, char *,
+ size_t, int *);
+ enum nss_status status;
+ int nss_errno = 0;
+ char buf[200];
+
+ _nss_uidtosid = find_fn(nss, "uidtosid");
+
+ if (!_nss_uidtosid) {
+ return -1;
+ }
+
+ status = _nss_uidtosid(uid, sid, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *sid = strdup(*sid);
+
+ return 0;
+}
+
+/*
+ convert a gid to a sid
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_gidtosid(struct nss_state *nss, gid_t gid, char **sid)
+{
+ enum nss_status (*_nss_gidtosid)(gid_t, char **, char *,
+ size_t, int *);
+ enum nss_status status;
+ int nss_errno = 0;
+ char buf[200];
+
+ _nss_gidtosid = find_fn(nss, "gidtosid");
+
+ if (!_nss_gidtosid) {
+ return -1;
+ }
+
+ status = _nss_gidtosid(gid, sid, buf, sizeof(buf), &nss_errno);
+ if (status == NSS_STATUS_NOTFOUND) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ errno = nss_errno;
+ return -1;
+ }
+
+ *sid = strdup(*sid);
+
+ return 0;
+}
+
diff --git a/examples/nss/nss_winbind.h b/examples/nss/nss_winbind.h
new file mode 100644
index 00000000000..5a124a5a8ec
--- /dev/null
+++ b/examples/nss/nss_winbind.h
@@ -0,0 +1,97 @@
+/*
+ nss sample code for extended winbindd functionality
+
+ Copyright (C) Andrew Tridgell (tridge@samba.org)
+ Copyright (C) Volker Lendecke (vl@samba.org)
+
+ you are free to use this code in any way you see fit, including
+ without restriction, using this code in your own products. You do
+ not need to give any attribution.
+*/
+
+#define _GNU_SOURCE
+
+#include <pwd.h>
+#include <grp.h>
+
+struct nss_state {
+ void *dl_handle;
+ char *nss_name;
+ char pwnam_buf[512];
+};
+
+/*
+ establish a link to the nss library
+ Return 0 on success and -1 on error
+*/
+int nss_open(struct nss_state *nss, const char *nss_path);
+
+/*
+ close and cleanup a nss state
+*/
+void nss_close(struct nss_state *nss);
+
+/*
+ make a getpwnam call.
+ Return 0 on success and -1 on error
+*/
+int nss_getpwent(struct nss_state *nss, struct passwd *pwd);
+
+/*
+ make a setpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_setpwent(struct nss_state *nss);
+
+/*
+ make a endpwent call.
+ Return 0 on success and -1 on error
+*/
+int nss_endpwent(struct nss_state *nss);
+
+/*
+ convert a name to a SID
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_nametosid(struct nss_state *nss, const char *name, char **sid);
+
+/*
+ convert a SID to a name
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_sidtoname(struct nss_state *nss, const char *sid, char **name);
+
+/*
+ return a list of group SIDs for a user SID
+ the returned list is NULL terminated
+ Return 0 on success and -1 on error
+*/
+int nss_getusersids(struct nss_state *nss, const char *user_sid, char ***sids);
+
+/*
+ convert a sid to a uid
+ Return 0 on success and -1 on error
+*/
+int nss_sidtouid(struct nss_state *nss, const char *sid, uid_t *uid);
+
+/*
+ convert a sid to a gid
+ Return 0 on success and -1 on error
+*/
+int nss_sidtogid(struct nss_state *nss, const char *sid, gid_t *gid);
+
+/*
+ convert a uid to a sid
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_uidtosid(struct nss_state *nss, uid_t uid, char **sid);
+
+/*
+ convert a gid to a sid
+ caller frees
+ Return 0 on success and -1 on error
+*/
+int nss_gidtosid(struct nss_state *nss, gid_t gid, char **sid);
diff --git a/examples/nss/wbtest.c b/examples/nss/wbtest.c
new file mode 100644
index 00000000000..14265bd54c1
--- /dev/null
+++ b/examples/nss/wbtest.c
@@ -0,0 +1,111 @@
+/*
+ nss sample code for extended winbindd functionality
+
+ Copyright (C) Andrew Tridgell (tridge@samba.org)
+
+ you are free to use this code in any way you see fit, including
+ without restriction, using this code in your own products. You do
+ not need to give any attribution.
+*/
+
+/*
+ compile like this:
+
+ cc -o wbtest wbtest.c nss_winbind.c -ldl
+
+ and run like this:
+
+ ./wbtest /lib/libnss_winbind.so
+*/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <nss.h>
+#include <dlfcn.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "nss_winbind.h"
+
+static int nss_test_users(struct nss_state *nss)
+{
+ struct passwd pwd;
+
+ if (nss_setpwent(nss) != 0) {
+ perror("setpwent");
+ return -1;
+ }
+
+ /* loop over all users */
+ while ((nss_getpwent(nss, &pwd) == 0)) {
+ char *sid, **group_sids, *name2;
+ int i;
+
+ printf("User %s\n", pwd.pw_name);
+ if (nss_nametosid(nss, pwd.pw_name, &sid) != 0) {
+ perror("nametosid");
+ return -1;
+ }
+ printf("\tSID %s\n", sid);
+
+ if (nss_sidtoname(nss, sid, &name2) != 0) {
+ perror("sidtoname");
+ return -1;
+ }
+ printf("\tSID->name %s\n", name2);
+
+ if (nss_getusersids(nss, sid, &group_sids) != 0) {
+ perror("getusersids");
+ return -1;
+ }
+
+ printf("\tGroups:\n");
+ for (i=0; group_sids[i]; i++) {
+ printf("\t\t%s\n", group_sids[i]);
+ free(group_sids[i]);
+ }
+
+ free(sid);
+ free(name2);
+ free(group_sids);
+ }
+
+
+ if (nss_endpwent(nss) != 0) {
+ perror("endpwent");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ main program. It lists all users, listing user SIDs for each user
+ */
+int main(int argc, char *argv[])
+{
+ struct nss_state nss;
+ const char *so_path = "/lib/libnss_winbind.so";
+ int ret;
+
+ if (argc > 1) {
+ so_path = argv[1];
+ }
+
+ if (nss_open(&nss, so_path) != 0) {
+ perror("nss_open");
+ exit(1);
+ }
+
+ ret = nss_test_users(&nss);
+
+ nss_close(&nss);
+
+ return ret;
+}
diff --git a/examples/ntlogon/README b/examples/ntlogon/README
new file mode 100644
index 00000000000..e33c565d717
--- /dev/null
+++ b/examples/ntlogon/README
@@ -0,0 +1,160 @@
+ntlogon.py v0.8b Copyright 2002 by Timothy (rhacer) Grant
+This programme is released under the terms of the GNU Public License
+This programme has NO WARRANTY of any kind, use at your own risk.
+
+===================
+CHANGES SINCE v0.7b
+===================
+included patch that made machine name %m a macro substitution value.
+Thanks to: Nick Lopez <kimo_sabe@atdot.org>
+
+==================
+CHANGES SINCE v0.6
+==================
+PLEASE NOT THAT I AM CONSIDERING THIS A BETA UNTIL I GET SOME FEEDBACK
+FROM USERS ON WHETHER THE MACRO FEATURE WORKS FOR THEM.
+
+added the ability to define substitution macros: see the useage section
+
+removed the large docstring from the file and moved the information to
+the USEAGE section of this file
+
+cleaned up the code and made more flexible
+
+improved the code comments
+
+==================
+CHANGES SINCE v0.5
+==================
+added a -v --version switch
+
+added a --pause switch which will put a pause statement between each
+non-blank line of the script.
+
+===============
+A PERSONAL NOTE
+===============
+When I originally posted v0.5 on Freshmeat, I really expected *some*
+feedback. To date this little script has been downloaded over 700 times, but
+absolutely nobody has sent me an e-mail to tell me if it is useful, or if
+it is absolutely the stupidest waste of bandwidth they have ever seen.
+I'd really love to know if even one person other than me and the other techs
+here at Avalon have found it useful.
+
+Thanks.
+ rhacer (rhacer@craigelachie.org)
+
+September 27, 2000
+Thanks to those that did respond to my plea! I'd still love to hear from
+any other users!
+
+============
+INTRODUCTION
+============
+As my experience with Linux and Samba increased, I had no trouble whipping up
+a custom Perl, Python or Bash script to create Samba Logon Scripts, but I
+noticed that I changed things from place to place, and that my users had *no*
+chance of ever figuring out how to modify those scripts themselves.
+
+In an attempt to create a company wide standard that both my co-workers and my
+customers could *easily* modify I hit upon the scheme I used here.
+
+I settled on an INI file feel, because most who have experience with Win boxes
+have some concept of INI files.
+
+============
+INSTALLATION
+============
+The distribution archive contains three files:
+
+README This file
+ntlogon.py The actual Python script (place in /usr/local/samba/bin)
+ntlogon.conf A sample configuration file (place in /etc)
+
+This script was created using Python v1.5.2, and I believe it uses only
+standard libraries.
+
+Your smb.conf file needs to contain a netlogon section similar to the
+following (These settings *are not* normal on a RH box. These settings
+are all based on the excellent book that I learned Samba from: Samba
+Integrating Unix and Windows by John D. Blair. It is somewhat out of
+date now, but that's the history of the strange file locations):
+
+[netlogon]
+ path = /usr/local/samba/netlogon
+ writeable = no
+ guest ok = no
+ root preexec = /usr/local/samba/bin/ntlogon --user=%U --os=%m
+ root postexec = rm /usr/local/samba/netlogon/%U.bat
+
+======
+USEAGE
+======
+PLEASE SEE NTLOGON.CONF FOR A DETAILED CONFIGURATION EXAMPLE
+
+This programme will build a Windows NT logon script for users connecting
+to a Samba server. Samba macros that are curently understood:
+
+ %U user name
+ %G group name
+ %a machine architecture
+ %m machine netbios name
+
+This programme reads a configuration that looks strikingly similar to both
+the Samba configuration file, and a DOS "boot menu" AUTOEXEC.BAT file.
+
+The default file name is /etc/ntlogon.conf (though I really think it ought
+to be called ntlogon.batch!) You may change the filename by using the -f
+or --templatefile startup option.
+
+The default netlogon directory is /usr/local/samba/netlogon though this
+can be changed with the -d or --dir startup option.
+
+The default batch file name generated is username.bat if no username is
+specified the default value is logon.bat (e.g., if --user=fred is specified
+on the command line then the logon script generated will be stored in
+fred.bat)
+
+Use the --debug option to print the logon script to screen instead of the
+output file
+
+Use the --pause option to place a pause statement between each line of the
+script to assist in debugging a logon script.
+
+The file is divided into sections that have headers in square brackets
+
+[Global]
+[User-username]
+[Group-groupname]
+[OS-osname]
+
+The file may also contain user defined substitution macros. They are
+defined by placing the macro name on the left side of an equal sign,
+and the substitution text on the right side of the equal sign. They
+are also case sensitive:
+
+MAINDRIVE = G:
+USERDRIVE = U:
+SERVERNAME = myservername
+
+They are referenced by prepending a "%" sign to the variable name:
+
+NET USE %MAINDRIVE \\\\servername\\mainshare /YES
+NET USE %USERDRIVE \\\\%SERVERNAME\\usershare /YES
+
+==============
+SPECIAL THANKS
+==============
+Nick Lopez <kimo_sabe@atdot.org> for the net bios name patch.
+
+===================
+CONTACT INFORMATION
+===================
+Author : Timothy (rhacer) Grant
+
+I can be reached at tjg@craigelachie.org
+ntlogon website www.craigelachie.org/rhacer/ntlogon
+
+Please feel free to contact me with any suggestions, improvements, bugs you
+might find.
+
diff --git a/examples/ntlogon/ntlogon.conf b/examples/ntlogon/ntlogon.conf
new file mode 100644
index 00000000000..e1573a6118f
--- /dev/null
+++ b/examples/ntlogon/ntlogon.conf
@@ -0,0 +1,44 @@
+# Everything in the Global section applies to all users logging on to the
+# network
+[Global]
+
+#Some substitution macro definitions
+MAINDRIVE = G:
+USERDRIVE = U:
+SERVERNAME = myservername
+
+@ECHO "Welcome to our network!!!"
+NET TIME \\servername /SET /YES
+NET USE %MAINDRIVE \\%SERVERNAME\globalshare /YES
+
+# Map the private user area in the global section so we don't have to
+# create individual user entries for each user!
+NET USE %USERDRIVE \\servername\%U /YES
+
+# Group entries, User entries and OS entries each start with the
+# keyword followed by a dash followed by--appropriately enough the Group
+# name, the User name, or the OS name.
+[Group-admin]
+@ECHO "Welcome administrators!"
+NET USE G: \\servername\adminshare1 /YES
+NET USE I: \\servername\adminshare2 /YES
+
+[Group-peons]
+@ECHO "Be grateful we let you use computers!"
+NET USE G: \\servername\peonshare1 /YES
+
+[Group-hackers]
+@ECHO "What can I do for you today great one?"
+NET USE G: \\servername\hackershare1 /YES
+NET USE I: \\servername\adminshare2 /YES
+
+[User-fred]
+@ECHO "Hello there Fred!"
+NET USE F: \\servername\fredsspecialshare /YES
+
+[OS-WfWg]
+@ECHO "Time to upgrade isn't it?"
+
+# End configuration file
+
+X = Will this break?
diff --git a/examples/ntlogon/ntlogon.py b/examples/ntlogon/ntlogon.py
new file mode 100755
index 00000000000..ba46ba8ffcf
--- /dev/null
+++ b/examples/ntlogon/ntlogon.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python
+"""
+ntlogon.py written by Timothy (rhacer) Grant
+
+Copyright 1999 - 2002 by Timothy Grant
+
+is distributed under the terms of the GNU Public License.
+
+The format for the configuration file is as follows:
+
+While there is some room for confusion, we attempt to process things in
+order of specificity: Global first, Group second, User third, OS Type
+forth. This order can be debated forever, but it seems to make the most
+sense.
+
+# Everything in the Global section applies to all users logging on to the
+# network
+[Global]
+@ECHO "Welcome to our network!!!"
+NET TIME \\\\servername /SET /YES
+NET USE F: \\\\servername\\globalshare /YES
+
+# Map the private user area in the global section so we don't have to
+# create individual user entries for each user!
+NET USE U: \\\\servername\\%U /YES
+
+# Group entries, User entries and OS entries each start with the
+# keyword followed by a dash followed by--appropriately enough the Group
+# name, the User name, or the OS name.
+[Group-admin]
+@ECHO "Welcome administrators!"
+NET USE G: \\\\servername\\adminshare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[Group-peons]
+@ECHO "Be grateful we let you use computers!"
+NET USE G: \\\\servername\\peonshare1 /YES
+
+[Group-hackers]
+@ECHO "What can I do for you today great one?"
+NET USE G: \\\\servername\\hackershare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[User-fred]
+@ECHO "Hello there Fred!"
+NET USE F: \\\\servername\\fredsspecialshare /YES
+
+[OS-WfWg]
+@ECHO "Time to upgrade it?"
+
+# End configuration file
+
+usage: ntlogon [-g | --group=groupname]
+ [-u | --user=username]
+ [-o | --os=osname]
+ [-m | --machine=netbiosname]
+ [-f | --templatefile=filename]
+ [-d | --dir=netlogon directory]
+ [-v | --version]
+ [-h | --help]
+ [--pause]
+ [--debug]
+"""
+#
+#" This quote mark is an artifact of the inability of my editor to
+# correctly colour code anything after the triple-quoted docstring.
+# if your editor does not have this flaw, feel free to remove it.
+
+
+import sys
+import getopt
+import re
+import string
+import os
+
+version = "ntlogon.py v0.8"
+
+def buildScript(buf, sections, group, user, ostype, machine, debug, pause):
+ """
+ buildScript() Takes the contents of the template file and builds
+ a DOS batch file to be executed as an NT logon script. It does this
+ by determining which sections of the configuration file should be included
+ and creating a list object that contains each line contained in each
+ included section. The list object is then returned to the calling
+ routine.
+
+ All comments (#) are removed. A REM is inserted to show
+ which section of the configuration file each line comes from.
+ We leave blanklines as they are sometimes useful for debugging
+
+ We also replace all of the Samba macros (e.g., %U, %G, %a, %m) with their
+ expanded versions which have been passed to us by smbd
+ """
+ hdrstring = ''
+ script = []
+
+ #
+ # These are the Samba macros that we currently know about.
+ # any user defined macros will also be added to this dictionary.
+ # We do not store the % sign as part of the macro name.
+ # The replace routine will prepend the % sign to all possible
+ # replacements.
+ #
+ macros = {
+ 'U': user,
+ 'G': group,
+ 'a': ostype,
+ 'm': machine
+ }
+
+ #
+ # Process each section defined in the list sections
+ #
+ for s in sections:
+ # print 'searching for: ' + s
+
+ idx = 0
+
+ while idx < len(buf):
+ ln = buf[idx]
+
+ #
+ # We need to set up a regex for each possible section we
+ # know about. This is slightly complicated due to the fact
+ # that section headers contain user defined text.
+ #
+ if s == 'Global':
+ hdrstring = '\[ *' + s + ' *\]'
+ elif s == 'Group':
+ hdrstring = '\[ *' + s + ' *- *' + group + ' *\]'
+ elif s == 'User':
+ hdrstring = '\[ *' + s + ' *- *' + user + ' *\]'
+ elif s == 'OS':
+ hdrstring = '\[ *' + s + ' *- *' + ostype + ' *\]'
+ elif s == 'Machine':
+ hdrstring = '\[ *' + s + ' *- *' + machine + ' *\]'
+
+ #
+ # See if we have found a section header
+ #
+ if re.search(r'(?i)' + hdrstring, ln):
+ idx = idx + 1 # increment the counter to move to the next
+ # line.
+
+ x = re.match(r'([^#\r\n]*)', ln) # Determine the section
+ # name and strip out CR/LF
+ # and comment information
+
+ if debug:
+ print 'rem ' + x.group(1) + ' commands'
+ else:
+ # create the rem at the beginning of each section of the
+ # logon script.
+ script.append('rem ' + x.group(1) + ' commands')
+
+ #
+ # process each line until we have found another section
+ # header
+ #
+ while not re.search(r'.*\[.*\].*', buf[idx]):
+
+ #
+ # strip comments and line endings
+ #
+ x = re.match(r'([^#\r\n]*)', buf[idx])
+
+ if string.strip(x.group(1)) != '' :
+ # if there is still content after stripping comments and
+ # line endings then this is a line to process
+
+ line = x.group(1)
+
+ #
+ # Check to see if this is a macro definition line
+ #
+ vardef = re.match(r'(.*)=(.*)', line)
+
+ if vardef:
+ varname = string.strip(vardef.group(1)) # Strip leading and
+ varsub = string.strip(vardef.group(2)) # and trailing spaces
+
+ if varname == '':
+ print "Error: No substition name specified line: %d" % idx
+ sys.exit(1)
+
+ if varsub == '':
+ print "Error: No substitution text provided line: %d" % idx
+ sys.exit(1)
+
+ if macros.has_key(varname):
+ print "Warning: macro %s redefined line: %d" % (varname, idx)
+
+ macros[varname] = varsub
+ idx = idx + 1
+ continue
+
+ #
+ # Replace all the macros that we currently
+ # know about.
+ #
+ # Iterate over the dictionary that contains all known
+ # macro substitutions.
+ #
+ # We test for a macro name by prepending % to each dictionary
+ # key.
+ #
+ for varname in macros.keys():
+ line = re.sub(r'%' + varname + r'(\W)',
+ macros[varname] + r'\1', line)
+
+ if debug:
+ print line
+ if pause:
+ print 'pause'
+ else:
+ script.append(line)
+
+ idx = idx + 1
+
+ if idx == len(buf):
+ break # if we have reached the end of the file
+ # stop processing.
+
+ idx = idx + 1 # increment the line counter
+
+ if debug:
+ print ''
+ else:
+ script.append('')
+
+ return script
+
+# End buildScript()
+
+def run():
+ """
+ run() everything starts here. The main routine reads the command line
+ arguments, opens and reads the configuration file.
+ """
+ configfile = '/etc/ntlogon.conf' # Default configuration file
+ group = '' # Default group
+ user = '' # Default user
+ ostype = '' # Default os
+ machine = '' # Default machine type
+ outfile = 'logon.bat' # Default batch file name
+ # this file name WILL take on the form
+ # username.bat if a username is specified
+ debug = 0 # Default debugging mode
+ pause = 0 # Default pause mode
+ outdir = '/usr/local/samba/netlogon/' # Default netlogon directory
+
+ sections = ['Global', 'Machine', 'OS', 'Group', 'User'] # Currently supported
+ # configuration file
+ # sections
+
+ options, args = getopt.getopt(sys.argv[1:], 'd:f:g:ho:u:m:v',
+ ['templatefile=',
+ 'group=',
+ 'help',
+ 'os=',
+ 'user=',
+ 'machine=',
+ 'dir=',
+ 'version',
+ 'pause',
+ 'debug'])
+
+ #
+ # Process the command line arguments
+ #
+ for i in options:
+ # template file to process
+ if (i[0] == '-f') or (i[0] == '--templatefile'):
+ configfile = i[1]
+ # print 'configfile = ' + configfile
+
+ # define the group to be used
+ elif (i[0] == '-g') or (i[0] == '--group'):
+ group = i[1]
+ # print 'group = ' + group
+
+ # define the os type
+ elif (i[0] == '-o') or (i[0] == '--os'):
+ ostype = i[1]
+ # print 'os = ' + os
+
+ # define the user
+ elif (i[0] == '-u') or (i[0] == '--user'):
+ user = i[1]
+ outfile = user + '.bat' # Setup the output file name
+ # print 'user = ' + user
+
+ # define the machine
+ elif (i[0] == '-m') or (i[0] == '--machine'):
+ machine = i[1]
+
+ # define the netlogon directory
+ elif (i[0] == '-d') or (i[0] == '--dir'):
+ outdir = i[1]
+ # print 'outdir = ' + outdir
+
+ # if we are asked to turn on debug info, do so.
+ elif (i[0] == '--debug'):
+ debug = 1
+ # print 'debug = ' + debug
+
+ # if we are asked to turn on the automatic pause functionality, do so
+ elif (i[0] == '--pause'):
+ pause = 1
+ # print 'pause = ' + pause
+
+ # if we are asked for the version number, print it.
+ elif (i[0] == '-v') or (i[0] == '--version'):
+ print version
+ sys.exit(0)
+
+ # if we are asked for help print the docstring.
+ elif (i[0] == '-h') or (i[0] == '--help'):
+ print __doc__
+ sys.exit(0)
+
+ #
+ # open the configuration file
+ #
+ try:
+ iFile = open(configfile, 'r')
+ except IOError:
+ print 'Unable to open configuration file: ' + configfile
+ sys.exit(1)
+
+
+ #
+ # open the output file
+ #
+ if not debug:
+ try:
+ oFile = open(outdir + outfile, 'w')
+ except IOError:
+ print 'Unable to open logon script file: ' + outdir + outfile
+ sys.exit(1)
+
+ buf = iFile.readlines() # read in the entire configuration file
+
+ #
+ # call the script building routine
+ #
+ script = buildScript(buf, sections, group, user, ostype, machine, debug, pause)
+
+ #
+ # write out the script file
+ #
+ if not debug:
+ for ln in script:
+ oFile.write(ln + '\r\n')
+ if pause:
+ if string.strip(ln) != '': # Because whitespace
+ oFile.write('pause' + '\r\n') # is a useful tool, we
+ # don't put pauses after
+ # an empty line.
+
+
+# End run()
+
+#
+# immediate-mode commands, for drag-and-drop or execfile() execution
+#
+if __name__ == '__main__':
+ run()
+else:
+ print "Module ntlogon.py imported."
+ print "To run, type: ntlogon.run()"
+ print "To reload after changes to the source, type: reload(ntlogon)"
+
+#
+# End NTLogon.py
+#
diff --git a/examples/pdb/Makefile b/examples/pdb/Makefile
new file mode 100644
index 00000000000..a53cd5d5e2d
--- /dev/null
+++ b/examples/pdb/Makefile
@@ -0,0 +1,31 @@
+# Makefile for samba-pdb examples
+# Variables
+
+CC = gcc
+LIBTOOL = libtool
+
+SAMBA_SRC = ../../source
+SAMBA_INCL = ../../source/include
+UBIQX_SRC = ../../source/ubiqx
+SMBWR_SRC = ../../source/smbwrapper
+CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g -I/usr/include/heimdal -fPIC
+PDB_OBJS = pdb_test.so
+
+# Default target
+
+default: $(PDB_OBJS)
+
+# Pattern rules
+
+%.so: %.lo
+ $(LIBTOOL) $(CC) -shared -o $@ $< $(LDFLAGS)
+
+%.lo: %.c
+ $(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
+
+# Misc targets
+
+clean:
+ rm -rf .libs
+ rm -f core *~ *% *.bak \
+ $(PDB_OBJS) $(PDB_OBJS:.so=.o) $(PDB_OBJS:.so=.lo)
diff --git a/examples/pdb/README b/examples/pdb/README
new file mode 100644
index 00000000000..ab1baed2366
--- /dev/null
+++ b/examples/pdb/README
@@ -0,0 +1,16 @@
+README for Samba Password Database (PDB) examples
+====================================================
+Jelmer Vernooij <jelmer@nl.linux.org>
+Stefan (metze) Metzmacher <metze@samba.org>
+
+The pdb_test.c file in this directory contains a very basic example of
+a pdb plugin. It just prints the name of the function that is executed using
+DEBUG. Maybe it's nice to include some of the arguments to the function in the
+future too..
+
+To debug passdb backends, try to run gdb on the 'pdbedit' executable. That's
+really much easier than restarting smbd constantly and attaching with your
+debugger.
+
+New passdb plugins should go into the samba lib directory, (/usr/lib/samba/pdb/
+for most distributions). An example would be: /usr/lib/samba/pdb/test.so
diff --git a/examples/pdb/mysql/mysql.dump b/examples/pdb/mysql/mysql.dump
new file mode 100644
index 00000000000..5da75f5745c
--- /dev/null
+++ b/examples/pdb/mysql/mysql.dump
@@ -0,0 +1,37 @@
+# Put this in your MySQL database by running
+# mysql -u<user> -p<password> -h<host> <database> < mysql.dump
+
+CREATE TABLE user (
+ logon_time int(9),
+ logoff_time int(9),
+ kickoff_time int(9),
+ pass_last_set_time int(9),
+ pass_can_change_time int(9),
+ pass_must_change_time int(9),
+ username varchar(255),
+ domain varchar(255),
+ nt_username varchar(255),
+ nt_fullname varchar(255),
+ home_dir varchar(255),
+ dir_drive varchar(4),
+ logon_script varchar(255),
+ profile_path varchar(255),
+ acct_desc varchar(255),
+ workstations varchar(255),
+ unknown_str varchar(255),
+ munged_dial varchar(255),
+ uid int(9) NOT NULL DEFAULT "0" PRIMARY KEY auto_increment,
+ gid int(9),
+ user_sid varchar(255),
+ group_sid varchar(255),
+ lm_pw varchar(255),
+ nt_pw varchar(255),
+ acct_ctrl int(9),
+ unknown_3 int(9),
+ logon_divs int(9),
+ hours_len int(9),
+ unknown_5 int(9),
+ unknown_6 int(9),
+ bad_password_count int(9),
+ logon_count(9)
+);
diff --git a/examples/pdb/mysql/smb.conf b/examples/pdb/mysql/smb.conf
new file mode 100644
index 00000000000..61a3f198168
--- /dev/null
+++ b/examples/pdb/mysql/smb.conf
@@ -0,0 +1,11 @@
+[global]
+netbios name = FOOBAR
+workgroup = TESTGROUP
+security = domain
+domain logons = yes
+domain master = yes
+passdb backend = plugin:/usr/local/samba/lib/pdb_mysql.so:mysql
+mysql:mysql host = rhonwyn
+mysql:mysql user = samba
+mysql:mysql password = ambas
+mysql:mysql database = samba
diff --git a/examples/pdb/pdb_test.c b/examples/pdb/pdb_test.c
new file mode 100644
index 00000000000..e46c621d48e
--- /dev/null
+++ b/examples/pdb/pdb_test.c
@@ -0,0 +1,145 @@
+/*
+ * Test password backend for samba
+ * Copyright (C) Jelmer Vernooij 2002
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "includes.h"
+
+static int testsam_debug_level = DBGC_ALL;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS testsam_debug_level
+
+/***************************************************************
+ Start enumeration of the passwd list.
+****************************************************************/
+
+static NTSTATUS testsam_setsampwent(struct pdb_methods *methods, BOOL update)
+{
+ DEBUG(10, ("testsam_setsampwent called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/***************************************************************
+ End enumeration of the passwd list.
+****************************************************************/
+
+static void testsam_endsampwent(struct pdb_methods *methods)
+{
+ DEBUG(10, ("testsam_endsampwent called\n"));
+}
+
+/*****************************************************************
+ Get one SAM_ACCOUNT from the list (next in line)
+*****************************************************************/
+
+static NTSTATUS testsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user)
+{
+ DEBUG(10, ("testsam_getsampwent called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/******************************************************************
+ Lookup a name in the SAM database
+******************************************************************/
+
+static NTSTATUS testsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
+{
+ DEBUG(10, ("testsam_getsampwnam called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/***************************************************************************
+ Search by sid
+ **************************************************************************/
+
+static NTSTATUS testsam_getsampwsid (struct pdb_methods *methods, SAM_ACCOUNT *user, const DOM_SID *sid)
+{
+ DEBUG(10, ("testsam_getsampwsid called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/***************************************************************************
+ Delete a SAM_ACCOUNT
+****************************************************************************/
+
+static NTSTATUS testsam_delete_sam_account(struct pdb_methods *methods, SAM_ACCOUNT *sam_pass)
+{
+ DEBUG(10, ("testsam_delete_sam_account called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/***************************************************************************
+ Modifies an existing SAM_ACCOUNT
+****************************************************************************/
+
+static NTSTATUS testsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+{
+ DEBUG(10, ("testsam_update_sam_account called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/***************************************************************************
+ Adds an existing SAM_ACCOUNT
+****************************************************************************/
+
+static NTSTATUS testsam_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+{
+ DEBUG(10, ("testsam_add_sam_account called\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS testsam_init(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "testsam";
+
+ /* Functions your pdb module doesn't provide should be set
+ * to NULL */
+
+ (*pdb_method)->setsampwent = testsam_setsampwent;
+ (*pdb_method)->endsampwent = testsam_endsampwent;
+ (*pdb_method)->getsampwent = testsam_getsampwent;
+ (*pdb_method)->getsampwnam = testsam_getsampwnam;
+ (*pdb_method)->getsampwsid = testsam_getsampwsid;
+ (*pdb_method)->add_sam_account = testsam_add_sam_account;
+ (*pdb_method)->update_sam_account = testsam_update_sam_account;
+ (*pdb_method)->delete_sam_account = testsam_delete_sam_account;
+
+ testsam_debug_level = debug_add_class("testsam");
+ if (testsam_debug_level == -1) {
+ testsam_debug_level = DBGC_ALL;
+ DEBUG(0, ("testsam: Couldn't register custom debugging class!\n"));
+ } else DEBUG(0, ("testsam: Debug class number of 'testsam': %d\n", testsam_debug_level));
+
+ DEBUG(0, ("Initializing testsam\n"));
+ if (location)
+ DEBUG(10, ("Location: %s\n", location));
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS init_module(void) {
+ return smb_register_passdb(PASSDB_INTERFACE_VERSION, "testsam",
+ testsam_init);
+}
diff --git a/examples/pdb/sambapdb.dtd b/examples/pdb/sambapdb.dtd
new file mode 100644
index 00000000000..1f4054ddec4
--- /dev/null
+++ b/examples/pdb/sambapdb.dtd
@@ -0,0 +1,46 @@
+<!ELEMENT samba:crypt (#PCDATA)* >
+<!ATTLIST samba:crypt type CDATA #REQUIRED >
+
+<!ELEMENT samba:password (samba:crypt*) >
+<!ATTLIST samba:password last_set CDATA #IMPLIED
+ must_change CDATA #IMPLIED
+ can_change CDATA #IMPLIED>
+
+<!ELEMENT samba:group (#PCDATA)* >
+<!ATTLIST samba:group sid CDATA #REQUIRED
+ gid CDATA #IMPLIED >
+
+<!ELEMENT samba:domain (#PCDATA)* >
+<!ELEMENT samba:fullname (#PCDATA)* >
+<!ELEMENT samba:nt_username (#PCDATA)* >
+<!ELEMENT samba:logon_script (#PCDATA)* >
+<!ELEMENT samba:profile_path (#PCDATA)* >
+<!ELEMENT samba:logon_time (#PCDATA)* >
+<!ELEMENT samba:logoff_time (#PCDATA)* >
+<!ELEMENT samba:kickoff_time (#PCDATA)* >
+<!ELEMENT samba:logon_divs (#PCDATA)* >
+<!ELEMENT samba:hours_len (#PCDATA)* >
+<!ELEMENT samba:unknown_3 (#PCDATA)* >
+<!ELEMENT samba:unknown_5 (#PCDATA)* >
+<!ELEMENT samba:unknown_6 (#PCDATA)* >
+<!ELEMENT samba:homedir (#PCDATA)* >
+<!ELEMENT samba:unknown_str (#PCDATA)* >
+<!ELEMENT samba:dir_drive (#PCDATA)* >
+<!ELEMENT samba:munged_dial (#PCDATA)* >
+<!ELEMENT samba:acct_desc (#PCDATA)* >
+<!ELEMENT samba:acct_ctrl (#PCDATA)* >
+<!ELEMENT samba:workstations (#PCDATA)* >
+
+<!ELEMENT samba:user ( samba:group?, samba:domain?, samba:nt_username?, samba:fullname?, samba:homedir?, samba:dir_drive?, samba:logon_script?, samba:profile_path?, samba:password?, samba:acct_ctrl?,samba:unknown_3?, samba:logon_divs?, samba:hours_len?, samba:logon_time?, samba:logoff_time?, samba:kickoff_time?, samba:unknown_5?, samba:unknown_6?, samba:unknown_str?, samba:munged_dial?, samba:acct_desc?, samba:workstations? ) >
+
+<!ATTLIST samba:user sid CDATA #REQUIRED
+ uid CDATA #IMPLIED
+ name CDATA #REQUIRED>
+
+<!ELEMENT samba:users (samba:user*) >
+
+<!ELEMENT samba (samba:users?) >
+
+<!ATTLIST samba
+ xmlns CDATA #FIXED 'http://samba.org/~jelmer/sambapdb.dtd'>
+
diff --git a/examples/printer-accounting/README b/examples/printer-accounting/README
new file mode 100644
index 00000000000..b7ab42acb96
--- /dev/null
+++ b/examples/printer-accounting/README
@@ -0,0 +1,63 @@
+These are just a few examples of what you can do for printer accounting;
+they are really just hacks to show a manager how may pages were being
+printed out on his new hp5n :)
+
+acct-all will run acct-sum and read the log files to generate some
+stats.
+
+Here is a sample output of the raw stats :
+
+1996-06-10.15:02:15 pkelly master.fcp.oypi.com 538 0
+1996-06-10.15:06:40 pkelly master.fcp.oypi.com 537 0
+1996-06-10.15:32:12 ted master.fcp.oypi.com 547 0
+1996-06-11.09:06:15 violet master.fcp.oypi.com 2667 0
+1996-06-11.09:48:02 violet master.fcp.oypi.com 66304 5
+1996-06-11.09:50:04 violet master.fcp.oypi.com 116975 9
+1996-06-11.09:57:20 violet master.fcp.oypi.com 3013 1
+1996-06-11.10:13:17 pkelly master.fcp.oypi.com 3407 1
+1996-06-11.12:37:06 craig master.fcp.oypi.com 13639 2
+1996-06-11.12:42:23 pkelly master.fcp.oypi.com 13639 2
+1996-06-11.12:45:11 marlene master.fcp.oypi.com 515 0
+1996-06-11.14:17:10 lucie master.fcp.oypi.com 1405 1
+1996-06-11.14:36:03 laura master.fcp.oypi.com 45486 5
+1996-06-11.15:08:21 violet master.fcp.oypi.com 1923 1
+1996-06-11.15:09:42 laura master.fcp.oypi.com 4821 1
+1996-06-11.15:12:28 laura master.fcp.oypi.com 46277 5
+1996-06-11.15:19:38 violet master.fcp.oypi.com 3503 1
+1996-06-11.15:21:49 lucie master.fcp.oypi.com 493 0
+1996-06-11.15:43:36 al master.fcp.oypi.com 3067 1
+
+And the output after the acct-sum is done on a full set of files
+in /var/log/lp/*
+
+master[1072] /var/log/lp$ /etc/conf/acct-all
+
+Sun Jul 21 23:03:16 EDT 1996
+
+Pages are approximate ...
+
+User Jobs Pages Size
+al 1 1 2 KB
+craig 1 2 13 KB
+jack 68 235 1995 KB
+laura 88 328 3050 KB
+lucie 221 379 3529 KB
+marlene 12 151 1539 KB
+melanie 83 365 3691 KB
+michelle 68 219 1987 KB
+mike 2 10 81 KB
+neil 111 225 2753 KB
+operator 44 137 1132 KB
+pkelly 368 984 11154 KB
+root 8 0 29 KB
+ted 158 257 2337 KB
+tony 244 368 2455 KB
+violet 419 1002 10072 KB
+
+
+Printer Jobs Pages
+hp2p 3 4
+hp5 915 2135
+lp 978 2524
+
+<pkelly@ets.net>
diff --git a/examples/printer-accounting/acct-all b/examples/printer-accounting/acct-all
new file mode 100644
index 00000000000..dc8f175b3cb
--- /dev/null
+++ b/examples/printer-accounting/acct-all
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+echo ""
+date
+echo ""
+echo "Pages are approximate ..."
+echo ""
+/etc/conf/acct-sum /var/log/lp/*
+echo ""
diff --git a/examples/printer-accounting/acct-sum b/examples/printer-accounting/acct-sum
new file mode 100644
index 00000000000..ffbfc8d8801
--- /dev/null
+++ b/examples/printer-accounting/acct-sum
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+while (<>) {
+ ($date, $user, $machine, $size, $pages) = split(' ');
+
+ $Printer{$ARGV}++;
+ $PrinterPages{$ARGV} += $pages;
+
+ $Jobs{$user}++;
+ $Size{$user}+= $size;
+ $Pages{$user}+= $pages;
+}
+
+printf "%-15s %5s %8s %8s\n", qw(User Jobs Pages Size);
+foreach $user (sort keys %Jobs) {
+ printf "%-15s %5d %8d %8d \KB\n",
+ $user, $Jobs{$user}, $Pages{$user}, $Size{$user}/1024;
+}
+
+
+print "\n\n";
+printf "%-15s %5s %8s %8s\n", qw(Printer Jobs Pages);
+foreach $prn (sort keys %Printer) {
+ ($name = $prn) =~ s=.*/==;
+ printf "%-15s %5d %8d\n",
+ $name, $Printer{$prn}, $PrinterPages{$prn};
+}
+
+
diff --git a/examples/printer-accounting/hp5-redir b/examples/printer-accounting/hp5-redir
new file mode 100644
index 00000000000..ea1299068a3
--- /dev/null
+++ b/examples/printer-accounting/hp5-redir
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+#
+# 0 == stdin == docuement
+# 1 == stdout == printer
+# 2 == stderr == logging
+#
+# With redirection to another valid /etc/printcap entry
+#
+
+umask(002);
+
+# -w132 -l66 -i0 -n pkelly -h master.fcp.oypi.com /var/log/lp-acct
+require "getopts.pl";
+&Getopts("w:l:i:n:h:");
+
+chomp($date = `date '+%Y-%m-%d.%T'`);
+
+($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks)
+ = stat(STDIN);
+
+# send to the real printer now.
+open(P, "|lpr -Pmgmt0") || die "Can't print to hp5-real ($!)\n";
+$cnt = 0;
+while (sysread(STDIN, $buf, 10240)) {
+ print P $buf;
+ # this is ugly, but it gives the approx in pages. We
+ # don't print graphics, so ... There must be a better way :)
+ $cnt += ($buf =~ /^L/g);
+}
+close(P);
+
+$acct = shift;
+if (open(ACCT, ">>$acct")) {
+ print ACCT "$date $opt_n $opt_h $size $cnt\n";
+ close(ACCT);
+} else {
+ warn "Err: Can't account for it ($!)\n";
+ warn "Log: $date $opt_n $opt_h $size $cnt\n";
+}
diff --git a/examples/printer-accounting/lp-acct b/examples/printer-accounting/lp-acct
new file mode 100644
index 00000000000..91a3def08f8
--- /dev/null
+++ b/examples/printer-accounting/lp-acct
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+#
+# 0 == stdin == docuement
+# 1 == stdout == printer
+# 2 == stderr == logging
+#
+# Regular, with no redirection
+#
+
+umask(002);
+
+# -w132 -l66 -i0 -n pkelly -h master.fcp.oypi.com /var/log/lp-acct
+require "getopts.pl";
+&Getopts("w:l:i:n:h:");
+
+chomp($date = `date '+%Y-%m-%d.%T'`);
+
+($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks)
+ = stat(STDIN);
+
+$cnt = 0;
+while (sysread(STDIN, $buf, 10240)) {
+ print $buf;
+ $cnt += ($buf =~ /^L/g);
+}
+
+$acct = shift;
+if (open(ACCT, ">>$acct")) {
+ print ACCT "$date $opt_n $opt_h $size $cnt\n";
+ close(ACCT);
+} else {
+ warn "Err: Can't account for it ($!)\n";
+ warn "Log: $date $opt_n $opt_h $size $cnt\n";
+}
diff --git a/examples/printer-accounting/printcap b/examples/printer-accounting/printcap
new file mode 100644
index 00000000000..976005a097c
--- /dev/null
+++ b/examples/printer-accounting/printcap
@@ -0,0 +1,22 @@
+# HP5N - Accounting entry
+#
+# This file calls the filter, hp5-redir to do the numbers and then
+# is redirected to the real entry, mgmt0, which is a remote HP5N
+# on the LAN with it's own IP number.
+#
+hp5:lp=/dev/lp1:\
+ :sd=/usr/spool/lpd/hp5-acct:\
+ :lf=/var/log/lp-err:\
+ :af=/var/log/lp/hp5:\
+ :if=/usr/local/bin/lp/hp5-redir:\
+ :sh:sf:\
+ :mx#0:
+
+# HP5N - Real printer location
+mgmt0:\
+ :rm=hp5.fcp.oypi.com:\
+ :rp=hp5.fcp.oypi.com:\
+ :sd=/usr/spool/lpd/mgmt0:\
+ :sh:sf:\
+ :mx#0:
+
diff --git a/examples/printing/prtpub.c b/examples/printing/prtpub.c
new file mode 100644
index 00000000000..ea71e03d073
--- /dev/null
+++ b/examples/printing/prtpub.c
@@ -0,0 +1,238 @@
+/*
+ * Set printer capabilities in DsDriver Keys on remote printer
+ * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This needs to be defined for certain compilers */
+#define WINVER 0x0500
+
+#include <tchar.h>
+#include <windows.h>
+#include <stdio.h>
+
+#define SAMBA_PORT _T("Samba")
+
+TCHAR *PrintLastError(void)
+{
+ static TCHAR msgtxt[1024*sizeof(TCHAR)];
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ 0, msgtxt, 0, NULL);
+
+ return msgtxt;
+}
+
+void map_orientation(HANDLE ph, TCHAR *printer, TCHAR *port)
+{
+ DWORD rot;
+ TCHAR portrait_only[] = _T("PORTRAIT\0");
+ TCHAR both[] = _T("LANDSCAPE\0PORTRAIT\0");
+
+ /* orentation of 90 or 270 indicates landscape supported, 0 means it isn't */
+ rot = DeviceCapabilities(printer, port, DC_BINNAMES, NULL, NULL);
+
+ printf("printOrientationsSupported:\n");
+
+ if (rot) {
+ printf("\tPORTRAIT\n\tLANDSCAPE\n");
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printOrientationsSupported"), REG_MULTI_SZ,
+ both, sizeof(both));
+ } else {
+ printf("\tPORTRAIT\n");
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printOrientationsSupported"), REG_MULTI_SZ,
+ portrait_only, sizeof(portrait_only));
+ }
+}
+
+void map_resolution(HANDLE ph, TCHAR *printer, TCHAR *port)
+{
+ DWORD num, *res, maxres = 0, i;
+
+ num = DeviceCapabilities(printer, port, DC_ENUMRESOLUTIONS, NULL, NULL);
+ if ((DWORD) -1 == num)
+ return;
+ res = malloc(num*2*sizeof(DWORD));
+ num = DeviceCapabilities(printer, port, DC_ENUMRESOLUTIONS, (BYTE *) res, NULL);
+ for (i=0; i < num*2; i++) {
+ maxres = (res[i] > maxres) ? res[i] : maxres;
+ }
+ printf("printMaxResolutionSupported: %d\n", maxres);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printMaxResolutionSupported"), REG_DWORD,
+ (BYTE *) &maxres, sizeof(maxres));
+}
+
+void map_extents(HANDLE ph, TCHAR *printer, TCHAR *port)
+{
+ DWORD extentval, xval, yval;
+
+ extentval = DeviceCapabilities(printer, port, DC_MINEXTENT, NULL, NULL);
+ xval = (DWORD) (LOWORD(extentval));
+ yval = (DWORD) (HIWORD(extentval));
+ printf("printMinXExtent: %d\n", xval);
+ printf("printMinYExtent: %d\n", yval);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printMinXExtent"), REG_DWORD, (BYTE *) &xval, sizeof(xval));
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printMinYExtent"), REG_DWORD, (BYTE *) &yval, sizeof(yval));
+ extentval = DeviceCapabilities(printer, port, DC_MAXEXTENT, NULL, NULL);
+ xval = (DWORD) (LOWORD(extentval));
+ yval = (DWORD) (HIWORD(extentval));
+ printf("printMaxXExtent: %d\n", xval);
+ printf("printMaxYExtent: %d\n", yval);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printMaxXExtent"), REG_DWORD, (BYTE *) &xval, sizeof(xval));
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printMaxYExtent"), REG_DWORD, (BYTE *) &yval, sizeof(yval));
+}
+
+void map_printrateunit(HANDLE ph, TCHAR *printer, TCHAR *port)
+{
+ DWORD unit;
+ TCHAR ppm[] = _T("PagesPerMinute");
+ TCHAR ipm[] = _T("InchesPerMinute");
+ TCHAR lpm[] = _T("LinesPerMinute");
+ TCHAR cps[] = _T("CharactersPerSecond");
+
+ unit = DeviceCapabilities(printer, port, DC_PRINTRATEUNIT, NULL, NULL);
+ switch(unit) {
+ case PRINTRATEUNIT_PPM:
+ printf("printRateUnit: %s\n", ppm);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printRateUnit"), REG_SZ, ppm, sizeof(ppm));
+ break;
+ case PRINTRATEUNIT_IPM:
+ printf("printRateUnit: %s\n", ipm);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printRateUnit"), REG_SZ, ipm, sizeof(ipm));
+ break;
+ case PRINTRATEUNIT_LPM:
+ printf("printRateUnit: %s\n", lpm);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printRateUnit"), REG_SZ, lpm, sizeof(lpm));
+ break;
+ case PRINTRATEUNIT_CPS:
+ printf("printRateUnit: %s\n", cps);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, _T("printRateUnit"), REG_SZ, cps, sizeof(cps));
+ break;
+ default:
+ printf("printRateUnit: unknown value %d\n", unit);
+ }
+}
+
+void map_generic_boolean(HANDLE ph, TCHAR *printer, TCHAR *port, WORD cap, TCHAR *key)
+{
+ BYTE boolval;
+ /* DeviceCapabilities doesn't always return 1 for true...just nonzero */
+ boolval = (BYTE) (DeviceCapabilities(printer, port, cap, NULL, NULL) ? 1 : 0);
+ printf("%s: %s\n", key, boolval ? "TRUE" : "FALSE");
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, key, REG_BINARY, &boolval, sizeof(boolval));
+}
+
+void map_generic_dword(HANDLE ph, TCHAR *printer, TCHAR *port, WORD cap, TCHAR *key)
+{
+ DWORD dword;
+
+ dword = DeviceCapabilities(printer, port, cap, NULL, NULL);
+ if ((DWORD) -1 == dword)
+ return;
+
+ printf("%s: %d\n", key, dword);
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, key, REG_DWORD, (BYTE *) &dword, sizeof(dword));
+}
+
+void map_generic_multi_sz(HANDLE ph, TCHAR *printer, TCHAR *port, WORD cap, TCHAR *key, int size)
+{
+ TCHAR *strings_in;
+ TCHAR *strings_out, *strings_cur;
+ DWORD num_items, i;
+
+ num_items = DeviceCapabilities(printer, port, cap, NULL, NULL);
+ if ((DWORD) -1 == num_items)
+ return;
+ strings_in = malloc(num_items * size);
+ strings_out = calloc(num_items, size);
+ num_items = DeviceCapabilities(printer, port, cap, strings_in, NULL);
+ printf("%s:\n", key);
+ for (i=0, strings_cur = strings_out; i < num_items; i++) {
+ _tcsncpy(strings_cur, &strings_in[i*size], size);
+ printf("\t%s\n", strings_cur);
+ strings_cur += _tcslen(strings_cur) + 1;
+ }
+
+ SetPrinterDataEx(ph, SPLDS_DRIVER_KEY, key, REG_MULTI_SZ, strings_out,
+ (strings_cur - strings_out + 1) * sizeof(TCHAR));
+
+ free(strings_in);
+ free(strings_out);
+}
+
+int main(int argc, char *argv[])
+{
+ HANDLE ph;
+ BYTE *driver_info;
+ DWORD needed;
+ TCHAR *printer;
+ TCHAR *port = SAMBA_PORT;
+ PRINTER_DEFAULTS admin_access = {NULL, NULL, PRINTER_ACCESS_ADMINISTER};
+ PRINTER_INFO_7 publish = {NULL, DSPRINT_PUBLISH};
+
+ if (argc < 2) {
+ printf("Usage: %s <printername>\n", argv[0]);
+ return -1;
+ }
+
+ printer = argv[1];
+
+ if (!(OpenPrinter(printer, &ph, &admin_access))) {
+ printf("OpenPrinter failed, error = %s\n", PrintLastError());
+ return -1;
+ }
+
+ GetPrinterDriver(ph, NULL, 1, NULL, 0, &needed);
+ if (!needed) {
+ printf("GetPrinterDriver failed, error = %s\n", PrintLastError());
+ ClosePrinter(ph);
+ return -1;
+ }
+ driver_info = malloc(needed);
+ if (!(GetPrinterDriver(ph, NULL, 1, driver_info, needed, &needed))) {
+ printf("GetPrinterDriver failed, error = %s\n", PrintLastError());
+ ClosePrinter(ph);
+ return -1;
+ }
+
+ map_generic_multi_sz(ph, printer, port, DC_BINNAMES, _T("printBinNames"), 24);
+ map_generic_boolean(ph, printer, port, DC_COLLATE, _T("printCollate"));
+ map_generic_dword(ph, printer, port, DC_COPIES, _T("printMaxCopies"));
+ map_generic_dword(ph, printer, port, DC_DRIVER, _T("driverVersion"));
+ map_generic_boolean(ph, printer, port, DC_DUPLEX, _T("printDuplexSupported"));
+ map_extents(ph, printer, port);
+ map_resolution(ph, printer, port);
+ map_orientation(ph, printer, port);
+ map_generic_multi_sz(ph, printer, port, DC_PAPERNAMES, _T("printMediaSupported"), 64);
+#if (WINVER >= 0x0500)
+ map_generic_boolean(ph, printer, port, DC_COLORDEVICE, _T("printColor"));
+ map_generic_multi_sz(ph, printer, port, DC_PERSONALITY, _T("printLanguage"), 64);
+ map_generic_multi_sz(ph, printer, port, DC_MEDIAREADY, _T("printMediaReady"),64);
+ map_generic_dword(ph, printer, port, DC_PRINTERMEM, _T("printMemory"));
+ map_generic_dword(ph, printer, port, DC_PRINTRATE, _T("printRate"));
+ map_printrateunit(ph, printer, port);
+#ifdef DC_STAPLE
+ map_generic_boolean(ph, printer, port, DC_STAPLE, _T("printStaplingSupported"));
+#endif
+#ifdef DC_PRINTRATEPPM
+ map_generic_dword(ph, printer, port, DC_PRINTRATEPPM, _T("printPagesPerMinute"));
+#endif
+#endif
+ SetPrinter(ph, 7, (BYTE *) &publish, 0);
+ ClosePrinter(ph);
+ return 0;
+}
diff --git a/examples/printing/readme.prtpub b/examples/printing/readme.prtpub
new file mode 100644
index 00000000000..319ce605c3b
--- /dev/null
+++ b/examples/printing/readme.prtpub
@@ -0,0 +1,12 @@
+prtpub.c contains a program which, when compiled with Visual C, can
+download a driver for a printer, query the capabilities of the driver,
+then write back the DsDriver keys necessary to publish all the fields
+of a printer in the directory. After writing back the fields, it issues
+a SetPrinter with info level 7, telling the server to publish the
+printer.
+
+It also writes the fields to stdout.
+
+In order to be distributed, it should be compiled using DLLs for C runtime.
+
+The program takes the UNC name of a printer as the only argument.
diff --git a/examples/printing/smbprint b/examples/printing/smbprint
new file mode 100755
index 00000000000..61ee41f4440
--- /dev/null
+++ b/examples/printing/smbprint
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+# This script is an input filter for printcap printing on a unix machine. It
+# uses the smbclient program to print the file to the specified smb-based
+# server and service.
+# For example you could have a printcap entry like this
+#
+# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
+#
+# which would create a unix printer called "smb" that will print via this
+# script. You will need to create the spool directory /usr/spool/smb with
+# appropriate permissions and ownerships for your system.
+
+# Set these to the server and service you wish to print to
+# In this example I have a WfWg PC called "lapland" that has a printer
+# exported called "printer" with no password.
+
+#
+# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
+# so that the server, service, and password can be read from
+# a /usr/var/spool/lpd/PRINTNAME/.config file.
+#
+# Script further modified by Richard Sharpe to fix some things.
+# Get rid of the -x on the first line, and add parameters
+#
+# -t now causes translate to be used when sending files
+#
+# Further modifications by Alfred Perlstein to fix some problems and
+# improve the quality of the code (3-Dec-2001).
+#
+# More hacking by Richard Sharpe to improve portability. 9-Dec-2001.
+#
+# In order for this to work the /etc/printcap entry must include an
+# accounting file (af=...):
+#
+# cdcolour:\
+# :cm=CD IBM Colorjet on 6th:\
+# :sd=/var/spool/lpd/cdcolour:\
+# :af=/var/spool/lpd/cdcolour/acct:\
+# :if=/usr/local/etc/smbprint:\
+# :mx=0:\
+# :lp=/dev/null:
+#
+# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
+# server=PC_SERVER
+# service=PR_SHARENAME
+# password="password"
+#
+# E.g.
+# server=PAULS_PC
+# service=CJET_371
+# password=""
+
+#smbclient=/usr/pkg/bin/smbclient
+# Assume that smbclient will be in the same place as smbprint
+
+smbclient="`dirname $0`/smbclient"
+
+#
+# The last parameter to the filter is the accounting file name.
+# Extract the directory name from the file name.
+# Concat this with /.config to get the config file.
+#
+TRANS=0
+eval acct_file=\${$#}
+spool_dir=`dirname $acct_file`
+config_file=$spool_dir/.config
+
+# Should read the following variables set in the config file:
+# server
+# service
+# password
+# username (optional)
+# IP (optional)
+# debug (optional)
+# debugsmb (optional)
+# debugfile (optional)
+. $config_file
+
+if [ "x$password" = "x" ] ; then
+ password="-N"
+fi
+
+if [ "x$username" == "x" ] ; then
+ username="$server";
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -t)
+ TRANS=1
+ ;;
+
+ *) # Bad Parameters, ignore them ...
+ ;;
+ esac
+ shift
+done
+
+command="print - ;"
+if [ $TRANS -eq 1 ]; then
+ command="translate;$command";
+fi
+
+debugfile="/tmp/smb-print.log"
+if [ "x$debug" = "x" ] ; then
+ debugfile=/dev/null debugargs=
+else
+ if [ $debug -eq 0 ] ; then
+ debugfile=/dev/null debugargs=
+ else
+ set -x; exec >>$debugfile 2>&1
+ debugargs="$debugfile."
+ #[ "x$debugsmb" == "x" ] || debugargs="$debugargs -d $debugsmb"
+ fi
+fi
+
+if [ "x$smbconf" != "x" ]; then
+
+ smbconf="-s $smbconf"
+
+fi
+
+if [ "x$IP" != "x" ]; then
+
+ IP="-I $IP"
+
+fi
+
+if [ "x$debugargs" != "x" ]; then
+
+ debugargs="-l $debugargs"
+
+fi
+
+$smbclient \
+ "\\\\$server\\$service" \
+ $password \
+ $smbconf \
+ $IP \
+ $debugargs \
+ -U $username \
+ -c "$command"
+#
diff --git a/examples/printing/smbprint-new.sh b/examples/printing/smbprint-new.sh
new file mode 100644
index 00000000000..61ee41f4440
--- /dev/null
+++ b/examples/printing/smbprint-new.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+# This script is an input filter for printcap printing on a unix machine. It
+# uses the smbclient program to print the file to the specified smb-based
+# server and service.
+# For example you could have a printcap entry like this
+#
+# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
+#
+# which would create a unix printer called "smb" that will print via this
+# script. You will need to create the spool directory /usr/spool/smb with
+# appropriate permissions and ownerships for your system.
+
+# Set these to the server and service you wish to print to
+# In this example I have a WfWg PC called "lapland" that has a printer
+# exported called "printer" with no password.
+
+#
+# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
+# so that the server, service, and password can be read from
+# a /usr/var/spool/lpd/PRINTNAME/.config file.
+#
+# Script further modified by Richard Sharpe to fix some things.
+# Get rid of the -x on the first line, and add parameters
+#
+# -t now causes translate to be used when sending files
+#
+# Further modifications by Alfred Perlstein to fix some problems and
+# improve the quality of the code (3-Dec-2001).
+#
+# More hacking by Richard Sharpe to improve portability. 9-Dec-2001.
+#
+# In order for this to work the /etc/printcap entry must include an
+# accounting file (af=...):
+#
+# cdcolour:\
+# :cm=CD IBM Colorjet on 6th:\
+# :sd=/var/spool/lpd/cdcolour:\
+# :af=/var/spool/lpd/cdcolour/acct:\
+# :if=/usr/local/etc/smbprint:\
+# :mx=0:\
+# :lp=/dev/null:
+#
+# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
+# server=PC_SERVER
+# service=PR_SHARENAME
+# password="password"
+#
+# E.g.
+# server=PAULS_PC
+# service=CJET_371
+# password=""
+
+#smbclient=/usr/pkg/bin/smbclient
+# Assume that smbclient will be in the same place as smbprint
+
+smbclient="`dirname $0`/smbclient"
+
+#
+# The last parameter to the filter is the accounting file name.
+# Extract the directory name from the file name.
+# Concat this with /.config to get the config file.
+#
+TRANS=0
+eval acct_file=\${$#}
+spool_dir=`dirname $acct_file`
+config_file=$spool_dir/.config
+
+# Should read the following variables set in the config file:
+# server
+# service
+# password
+# username (optional)
+# IP (optional)
+# debug (optional)
+# debugsmb (optional)
+# debugfile (optional)
+. $config_file
+
+if [ "x$password" = "x" ] ; then
+ password="-N"
+fi
+
+if [ "x$username" == "x" ] ; then
+ username="$server";
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -t)
+ TRANS=1
+ ;;
+
+ *) # Bad Parameters, ignore them ...
+ ;;
+ esac
+ shift
+done
+
+command="print - ;"
+if [ $TRANS -eq 1 ]; then
+ command="translate;$command";
+fi
+
+debugfile="/tmp/smb-print.log"
+if [ "x$debug" = "x" ] ; then
+ debugfile=/dev/null debugargs=
+else
+ if [ $debug -eq 0 ] ; then
+ debugfile=/dev/null debugargs=
+ else
+ set -x; exec >>$debugfile 2>&1
+ debugargs="$debugfile."
+ #[ "x$debugsmb" == "x" ] || debugargs="$debugargs -d $debugsmb"
+ fi
+fi
+
+if [ "x$smbconf" != "x" ]; then
+
+ smbconf="-s $smbconf"
+
+fi
+
+if [ "x$IP" != "x" ]; then
+
+ IP="-I $IP"
+
+fi
+
+if [ "x$debugargs" != "x" ]; then
+
+ debugargs="-l $debugargs"
+
+fi
+
+$smbclient \
+ "\\\\$server\\$service" \
+ $password \
+ $smbconf \
+ $IP \
+ $debugargs \
+ -U $username \
+ -c "$command"
+#
diff --git a/examples/printing/smbprint.old b/examples/printing/smbprint.old
new file mode 100755
index 00000000000..5a00a2a8aa8
--- /dev/null
+++ b/examples/printing/smbprint.old
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# This script is an input filter for printcap printing on a unix machine. It
+# uses the smbclient program to print the file to the specified smb-based
+# server and service.
+# For example you could have a printcap entry like this
+#
+# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
+#
+# which would create a unix printer called "smb" that will print via this
+# script. You will need to create the spool directory /usr/spool/smb with
+# appropriate permissions and ownerships for your system.
+
+# Set these to the server and service you wish to print to
+# In this example I have a WfWg PC called "lapland" that has a printer
+# exported called "printer" with no password.
+
+#
+# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
+# so that the server, service, and password can be read from
+# a /usr/var/spool/lpd/PRINTNAME/.config file.
+#
+# Script further modified by Richard Sharpe to fix some things.
+# Get rid of the -x on the first line, and add parameters
+#
+# -t now causes translate to be used when sending files
+#
+# In order for this to work the /etc/printcap entry must include an
+# accounting file (af=...):
+#
+# cdcolour:\
+# :cm=CD IBM Colorjet on 6th:\
+# :sd=/var/spool/lpd/cdcolour:\
+# :af=/var/spool/lpd/cdcolour/acct:\
+# :if=/usr/local/etc/smbprint:\
+# :mx=0:\
+# :lp=/dev/null:
+#
+# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
+# server=PC_SERVER
+# service=PR_SHARENAME
+# password="password"
+#
+# E.g.
+# server=PAULS_PC
+# service=CJET_371
+# password=""
+
+#
+# Debugging log file, change to /dev/null if you like.
+#
+logfile=/tmp/smb-print.log
+# logfile=/dev/null
+
+
+#
+# The last parameter to the filter is the accounting file name.
+# Extract the directory name from the file name.
+# Concat this with /.config to get the config file.
+#
+TRANS=0
+eval acct_file=\${$#}
+spool_dir=`dirname $acct_file`
+config_file=$spool_dir/.config
+
+# Should read the following variables set in the config file:
+# server
+# service
+# password
+eval `cat $config_file`
+
+while getopts t c; do
+ case $c in
+ t)
+ TRANS=1
+ ;;
+
+ '?') # Bad parameters, ignore it ...
+ ;;
+ esac
+done
+#
+# Some debugging help, change the >> to > if you want to same space.
+#
+echo "server $server, service $service" >> $logfile
+
+(
+# NOTE You may wish to add the line `echo translate' if you want automatic
+# CR/LF translation when printing.
+ if [ $TRANS -eq 1 ]; then
+ echo translate
+ fi
+ echo "print -"
+ cat
+) | /usr/local/samba/bin/smbclient "\\\\$server\\$service" $password -U $server -N -P >> $logfile
diff --git a/examples/printing/smbprint.sysv b/examples/printing/smbprint.sysv
new file mode 100644
index 00000000000..11fea21441b
--- /dev/null
+++ b/examples/printing/smbprint.sysv
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# @(#) smbprint.sysv version 1.0 Ross Wakelin <r.wakelin@march.co.uk>
+#
+# Version 1.0 13 January 1995
+# modified from the original smbprint (bsd) script
+#
+# this script is a System 5 printer interface script. It
+# uses the smbclient program to print the file to the specified smb-based
+# server and service.
+#
+# To add this to your lp system, copy this file into your samba directory
+# (the example here is /opt/samba), modify the server and service variables
+# and then execute the following command (as root)
+#
+# lpadmin -punixprintername -v/dev/null -i/opt/samba/smbprint
+#
+# where unixprintername is the name that the printer will be known as
+# on your unix box.
+#
+# the script smbprint will be copied into your printer administration
+# directory (/usr/lib/lp or /etc/lp) as a new interface
+# (interface/unixprintername)
+# Then you have to enable unixprintername and accept unixprintername
+#
+# This script will then be called by the lp service to print the files
+# This script will have 6 or more parameters passed to it by the lp service.
+# The first five will contain details of the print job, who queued it etc,
+# while parameters 6 onwards are a list of files to print. We just
+# cat these at the samba client.
+#
+# Set these to the server and service you wish to print to
+# In this example I have a WfWg PC called "lapland" that has a printer
+# exported called "printer" with no password.
+#
+# clear out the unwanted parameters
+shift;shift;shift;shift;shift
+# now the argument list is just the files to print
+
+server=admin
+service=hplj2
+password=""
+
+(
+# NOTE You may wish to add the line `echo translate' if you want automatic
+# CR/LF translation when printing.
+ echo translate
+ echo "print -"
+ cat $*
+) | /opt/samba/smbclient "\\\\$server\\$service" $password -N > /dev/null
+exit $?
+
diff --git a/examples/simple/README b/examples/simple/README
new file mode 100644
index 00000000000..9628aa8260d
--- /dev/null
+++ b/examples/simple/README
@@ -0,0 +1,2 @@
+This is the "original" sample config file.
+
diff --git a/examples/simple/smb.conf b/examples/simple/smb.conf
new file mode 100644
index 00000000000..786bf49057c
--- /dev/null
+++ b/examples/simple/smb.conf
@@ -0,0 +1,167 @@
+; Configuration file for smbd.
+; ============================================================================
+; For the format of this file and comprehensive descriptions of all the
+; configuration option, please refer to the man page for smb.conf(5).
+;
+; The following configuration should suit most systems for basic usage and
+; initial testing. It gives all clients access to their home directories and
+; allows access to all printers specified in /etc/printcap.
+;
+; Things you need to check:
+; --------------------------
+;
+; 1: Check the path to your printcap file. If you are using a system that does
+; not use printcap (eg., Solaris), create a file containing lines of the
+; form
+;
+; printername|printername|printername|
+;
+; where each "printername" is the name of a printer you want to provide
+; access to. Then alter the "printcap =" entry to point to the new file.
+;
+; If using Solaris, the following command will generate a suitable printcap
+; file:
+;
+; lpc status | grep ":" | sed s/:/\|/ > myprintcap
+;
+; 2: Make sure the "print command" entry is correct for your system. This
+; command should submit a file (represented by %s) to a printer
+; (represented by %p) for printing and should REMOVE the file after
+; printing.
+;
+; One most systems the default will be OK, as long as you get "printing ="
+; right.
+;
+; It is also a good idea to use an absolute path in the print command
+; as there is no guarantee the search path will be set correctly.
+;
+; 3: Make sure the "printing =" option is set correctly for your system.
+; Possible values are "sysv", "bsd" or "aix".
+;
+; 4: Make sure the "lpq command" entry is correct for your system. The default
+; may not work for you.
+;
+; 5: Make sure that the user specified in "guest account" exists. Typically
+; this will be a user that cannot log in and has minimal privileges.
+; Often the "nobody" account doesn't work (very system dependant).
+;
+; 6: You should consider the "security =" option. See a full description
+; in the main documentation and the smb.conf(5) manual page
+;
+; 7: Look at the "hosts allow" option, unless you want everyone on the internet
+; to be able to access your files.
+;
+[global]
+ printing = bsd
+ printcap name = /etc/printcap
+ load printers = yes
+ guest account = pcguest
+; This next option sets a separate log file for each client. Remove
+; it if you want a combined log file.
+ log file = /usr/local/samba/log.%m
+
+; You will need a world readable lock directory and "share modes=yes"
+; if you want to support the file sharing modes for multiple users
+; of the same files
+; lock directory = /usr/local/samba/var/locks
+; share modes = yes
+
+[homes]
+ comment = Home Directories
+ browseable = no
+ read only = no
+ create mode = 0750
+
+[printers]
+ comment = All Printers
+ browseable = no
+ printable = yes
+ public = no
+ writable = no
+ create mode = 0700
+
+; you might also want this one, notice that it is read only so as not to give
+; people without an account write access.
+;
+; [tmp]
+; comment = Temporary file space
+; path = /tmp
+; read only = yes
+; public = yes
+
+;
+; Other examples.
+;
+; A private printer, usable only by fred. Spool data will be placed in fred's
+; home directory. Note that fred must have write access to the spool directory,
+; wherever it is.
+;[fredsprn]
+; comment = Fred's Printer
+; valid users = fred
+; path = /homes/fred
+; printer = freds_printer
+; public = no
+; writable = no
+; printable = yes
+;
+; A private directory, usable only by fred. Note that fred requires write
+; access to the directory.
+;[fredsdir]
+; comment = Fred's Service
+; path = /usr/somewhere/private
+; valid users = fred
+; public = no
+; writable = yes
+; printable = no
+;
+; A publicly accessible directory, but read only, except for people in
+; the staff group
+;[public]
+; comment = Public Stuff
+; path = /usr/somewhere/public
+; public = yes
+; writable = no
+; printable = no
+; write list = @staff
+;
+; a service which has a different directory for each machine that connects
+; this allows you to tailor configurations to incoming machines. You could
+; also use the %u option to tailor it by user name.
+; The %m gets replaced with the machine name that is connecting.
+;[pchome]
+; comment = PC Directories
+; path = /usr/pc/%m
+; public = no
+; writeable = yes
+;
+;
+; A publicly accessible directory, read/write to all users. Note that all files
+; created in the directory by users will be owned by the default user, so
+; any user with access can delete any other user's files. Obviously this
+; directory must be writable by the default user. Another user could of course
+; be specified, in which case all files would be owned by that user instead.
+;[public]
+; path = /usr/somewhere/else/public
+; public = yes
+; only guest = yes
+; writable = yes
+; printable = no
+;
+;
+; The following two entries demonstrate how to share a directory so that two
+; users can place files there that will be owned by the specific users. In this
+; setup, the directory should be writable by both users and should have the
+; sticky bit set on it to prevent abuse. Obviously this could be extended to
+; as many users as required.
+;[myshare]
+; comment = Mary's and Fred's stuff
+; path = /usr/somewhere/shared
+; valid users = mary fred
+; public = no
+; writable = yes
+; printable = no
+; create mask = 0765
+
+
+
+
diff --git a/examples/smb.conf.default b/examples/smb.conf.default
new file mode 100644
index 00000000000..839fede1233
--- /dev/null
+++ b/examples/smb.conf.default
@@ -0,0 +1,273 @@
+# This is the main Samba configuration file. You should read the
+# smb.conf(5) manual page in order to understand the options listed
+# here. Samba has a huge number of configurable options (perhaps too
+# many!) most of which are not shown in this example
+#
+# For a step to step guide on installing, configuring and using samba,
+# read the Samba HOWTO Collection.
+#
+# Any line which starts with a ; (semi-colon) or a # (hash)
+# is a comment and is ignored. In this example we will use a #
+# for commentry and a ; for parts of the config file that you
+# may wish to enable
+#
+# NOTE: Whenever you modify this file you should run the command "testparm"
+# to check that you have not made any basic syntactic errors.
+#
+#======================= Global Settings =====================================
+[global]
+
+# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4
+ workgroup = MYGROUP
+
+# server string is the equivalent of the NT Description field
+ server string = Samba Server
+
+# Security mode. Defines in which mode Samba will operate. Possible
+# values are share, user, server, domain and ads. Most people will want
+# user level security. See the HOWTO Collection for details.
+ security = user
+
+# This option is important for security. It allows you to restrict
+# connections to machines which are on your local network. The
+# following example restricts access to two C class networks and
+# the "loopback" interface. For more examples of the syntax see
+# the smb.conf man page
+; hosts allow = 192.168.1. 192.168.2. 127.
+
+# If you want to automatically load your printer list rather
+# than setting them up individually then you'll need this
+ load printers = yes
+
+# you may wish to override the location of the printcap file
+; printcap name = /etc/printcap
+
+# on SystemV system setting printcap name to lpstat should allow
+# you to automatically obtain a printer list from the SystemV spool
+# system
+; printcap name = lpstat
+
+# It should not be necessary to specify the print system type unless
+# it is non-standard. Currently supported print systems include:
+# bsd, cups, sysv, plp, lprng, aix, hpux, qnx
+; printing = cups
+
+# Uncomment this if you want a guest account, you must add this to /etc/passwd
+# otherwise the user "nobody" is used
+; guest account = pcguest
+
+# this tells Samba to use a separate log file for each machine
+# that connects
+ log file = /usr/local/samba/var/log.%m
+
+# Put a capping on the size of the log files (in Kb).
+ max log size = 50
+
+# Use password server option only with security = server
+# The argument list may include:
+# password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
+# or to auto-locate the domain controller/s
+# password server = *
+; password server = <NT-Server-Name>
+
+# Use the realm option only with security = ads
+# Specifies the Active Directory realm the host is part of
+; realm = MY_REALM
+
+# Backend to store user information in. New installations should
+# use either tdbsam or ldapsam. smbpasswd is available for backwards
+# compatibility. tdbsam requires no further configuration.
+; passdb backend = tdbsam
+
+# Using the following line enables you to customise your configuration
+# on a per machine basis. The %m gets replaced with the netbios name
+# of the machine that is connecting.
+# Note: Consider carefully the location in the configuration file of
+# this line. The included file is read at that point.
+; include = /usr/local/samba/lib/smb.conf.%m
+
+# Most people will find that this option gives better performance.
+# See the chapter 'Samba performance issues' in the Samba HOWTO Collection
+# and the manual pages for details.
+# You may want to add the following on a Linux system:
+# SO_RCVBUF=8192 SO_SNDBUF=8192
+ socket options = TCP_NODELAY
+
+# Configure Samba to use multiple interfaces
+# If you have multiple network interfaces then you must list them
+# here. See the man page for details.
+; interfaces = 192.168.12.2/24 192.168.13.2/24
+
+# Browser Control Options:
+# set local master to no if you don't want Samba to become a master
+# browser on your network. Otherwise the normal election rules apply
+; local master = no
+
+# OS Level determines the precedence of this server in master browser
+# elections. The default value should be reasonable
+; os level = 33
+
+# Domain Master specifies Samba to be the Domain Master Browser. This
+# allows Samba to collate browse lists between subnets. Don't use this
+# if you already have a Windows NT domain controller doing this job
+; domain master = yes
+
+# Preferred Master causes Samba to force a local browser election on startup
+# and gives it a slightly higher chance of winning the election
+; preferred master = yes
+
+# Enable this if you want Samba to be a domain logon server for
+# Windows95 workstations.
+; domain logons = yes
+
+# if you enable domain logons then you may want a per-machine or
+# per user logon script
+# run a specific logon batch file per workstation (machine)
+; logon script = %m.bat
+# run a specific logon batch file per username
+; logon script = %U.bat
+
+# Where to store roving profiles (only for Win95 and WinNT)
+# %L substitutes for this servers netbios name, %U is username
+# You must uncomment the [Profiles] share below
+; logon path = \\%L\Profiles\%U
+
+# Windows Internet Name Serving Support Section:
+# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
+; wins support = yes
+
+# WINS Server - Tells the NMBD components of Samba to be a WINS Client
+# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
+; wins server = w.x.y.z
+
+# WINS Proxy - Tells Samba to answer name resolution queries on
+# behalf of a non WINS capable client, for this to work there must be
+# at least one WINS Server on the network. The default is NO.
+; wins proxy = yes
+
+# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
+# via DNS nslookups. The default is NO.
+ dns proxy = no
+
+# These scripts are used on a domain controller or stand-alone
+# machine to add or delete corresponding unix accounts
+; add user script = /usr/sbin/useradd %u
+; add group script = /usr/sbin/groupadd %g
+; add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u
+; delete user script = /usr/sbin/userdel %u
+; delete user from group script = /usr/sbin/deluser %u %g
+; delete group script = /usr/sbin/groupdel %g
+
+
+#============================ Share Definitions ==============================
+[homes]
+ comment = Home Directories
+ browseable = no
+ writable = yes
+
+# Un-comment the following and create the netlogon directory for Domain Logons
+; [netlogon]
+; comment = Network Logon Service
+; path = /usr/local/samba/lib/netlogon
+; guest ok = yes
+; writable = no
+; share modes = no
+
+
+# Un-comment the following to provide a specific roving profile share
+# the default is to use the user's home directory
+;[Profiles]
+; path = /usr/local/samba/profiles
+; browseable = no
+; guest ok = yes
+
+
+# NOTE: If you have a BSD-style print system there is no need to
+# specifically define each individual printer
+[printers]
+ comment = All Printers
+ path = /usr/spool/samba
+ browseable = no
+# Set public = yes to allow user 'guest account' to print
+ guest ok = no
+ writable = no
+ printable = yes
+
+# This one is useful for people to share files
+;[tmp]
+; comment = Temporary file space
+; path = /tmp
+; read only = no
+; public = yes
+
+# A publicly accessible directory, but read only, except for people in
+# the "staff" group
+;[public]
+; comment = Public Stuff
+; path = /home/samba
+; public = yes
+; writable = yes
+; printable = no
+; write list = @staff
+
+# Other examples.
+#
+# A private printer, usable only by fred. Spool data will be placed in fred's
+# home directory. Note that fred must have write access to the spool directory,
+# wherever it is.
+;[fredsprn]
+; comment = Fred's Printer
+; valid users = fred
+; path = /homes/fred
+; printer = freds_printer
+; public = no
+; writable = no
+; printable = yes
+
+# A private directory, usable only by fred. Note that fred requires write
+# access to the directory.
+;[fredsdir]
+; comment = Fred's Service
+; path = /usr/somewhere/private
+; valid users = fred
+; public = no
+; writable = yes
+; printable = no
+
+# a service which has a different directory for each machine that connects
+# this allows you to tailor configurations to incoming machines. You could
+# also use the %U option to tailor it by user name.
+# The %m gets replaced with the machine name that is connecting.
+;[pchome]
+; comment = PC Directories
+; path = /usr/pc/%m
+; public = no
+; writable = yes
+
+# A publicly accessible directory, read/write to all users. Note that all files
+# created in the directory by users will be owned by the default user, so
+# any user with access can delete any other user's files. Obviously this
+# directory must be writable by the default user. Another user could of course
+# be specified, in which case all files would be owned by that user instead.
+;[public]
+; path = /usr/somewhere/else/public
+; public = yes
+; only guest = yes
+; writable = yes
+; printable = no
+
+# The following two entries demonstrate how to share a directory so that two
+# users can place files there that will be owned by the specific users. In this
+# setup, the directory should be writable by both users and should have the
+# sticky bit set on it to prevent abuse. Obviously this could be extended to
+# as many users as required.
+;[myshare]
+; comment = Mary's and Fred's stuff
+; path = /usr/somewhere/shared
+; valid users = mary fred
+; public = no
+; writable = yes
+; printable = no
+; create mask = 0765
+
+
diff --git a/examples/svr4-startup/README b/examples/svr4-startup/README
new file mode 100644
index 00000000000..8ed9f744770
--- /dev/null
+++ b/examples/svr4-startup/README
@@ -0,0 +1,24 @@
+Hi and thanks for this great software.
+
+Solaris (and other sysv) machines have a standardized way of
+starting and shutting down services (you may well know that already).
+
+Here's a piece of code one could place under /etc/init.d
+and create appropriate link from, say
+
+ /etc/rc2.d/S99samba.server
+
+to make smbd start and stop automatically with system bootups and
+shutdowns. Each one should edit the lines containing the
+daemon calls to agree with his/her installation (the code below
+works with the defaults) and workgroup setup (we use the -G and -n
+options).
+
+
+I hope this will be of use --- at least it is for me.
+
+Yours,
+
+Timo Knuutila
+knuutila@cs.utu.fi
+
diff --git a/examples/svr4-startup/samba.server b/examples/svr4-startup/samba.server
new file mode 100755
index 00000000000..0a47fdb10ce
--- /dev/null
+++ b/examples/svr4-startup/samba.server
@@ -0,0 +1,38 @@
+#!/bin/sh
+#ident "@(#)samba.server 1.0 96/06/19 TK" /* SVr4.0 1.1.13.1*/
+#
+# Please send info on modifications to knuutila@cs.utu.fi
+#
+# This file should have uid root, gid sys and chmod 744
+#
+if [ ! -d /usr/bin ]
+then # /usr not mounted
+ exit
+fi
+
+killproc() { # kill the named process(es)
+ pid=`/usr/bin/ps -e |
+ /usr/bin/grep -w $1 |
+ /usr/bin/sed -e 's/^ *//' -e 's/ .*//'`
+ [ "$pid" != "" ] && kill $pid
+}
+
+# Start/stop processes required for samba server
+
+case "$1" in
+
+'start')
+#
+# Edit these lines to suit your installation (paths, workgroup, host)
+#
+ /opt/samba/bin/smbd -D -s/opt/samba/smb.conf
+ /opt/samba/bin/nmbd -D -l/opt/samba/log -s/opt/samba/smb.conf
+ ;;
+'stop')
+ killproc nmbd
+ killproc smbd
+ ;;
+*)
+ echo "Usage: /etc/init.d/samba.server { start | stop }"
+ ;;
+esac
diff --git a/examples/thoralf/smb.conf b/examples/thoralf/smb.conf
new file mode 100644
index 00000000000..f9f147474a8
--- /dev/null
+++ b/examples/thoralf/smb.conf
@@ -0,0 +1,152 @@
+; Configuration file for smbd (Samba 1.9.15p8)
+; created by Thoralf Freitag. Send comments to:
+; <Thoralf.Freitag@remserv.rz.fhtw-berlin.de> or
+; <Thoralf.Freitag@t-online.de>
+; last edit 24.04.1995 01:11
+;
+;
+
+[global]
+
+ protocol = NT1
+ ;long filenames for win95
+ mangle case = yes
+ ;lower and upper letters
+ mangled names = yes
+ default case = lower
+ case sensitive = no
+ preserve case = yes
+ short preserve case = yes
+
+ printing = bsd
+ printcap name = /etc/printcap
+ lpq cache time = 0
+ workgroup = WORKGROUP
+ admin users = su
+ ;su is allowed to do all !!!
+ guest account = ftp
+ ;guest is same as user ftp
+ default service = reference
+ ;is possibly helpful to browsing under win 95
+ os level = 2
+ log file = /var/adm/log.smb
+ max log size = 10
+ debug level = 1
+ share modes = yes
+ lock directory = /var/adm
+
+[JP_360_raw]
+ comment = Networkprinter queue for Olivetti JP 360 (untreated RAW format)
+ browseable = yes
+ available = yes
+ public = no
+ force user = root
+ writable = no
+ printable = yes
+ printer name = samba
+ ;samba is an alias name for an raw_printer in your /etc/printcap
+ path = /samba/tmp
+ create mode = 0700
+
+[JP_360_mono]
+ comment = Networkprinter queue for Olivetti JP 360 Mono (with apsfilter)
+ browseable = yes
+ available = yes
+ public = no
+ force user = root
+ writable = no
+ printable = yes
+ printer name = lp
+ ;lp means the standard printer in your /etc/printcap
+ path = /samba/tmp
+ create mode = 0700
+
+[JP_360_color]
+ comment = Networkprinter queue for Olivetti JP 360 Color (with apsfilter)
+ browseable = yes
+ available = yes
+ public = no
+ force user = root
+ writable = no
+ printable = yes
+ printer name = lp4
+ ;my printer need this to print with his color cartridge
+ ;--> the lpd is drive to the printer as an color printer
+ path = /samba/tmp
+ create mode = 0700
+
+[tmp]
+ comment = the garbage dump
+ browseable = yes
+ available = yes
+ public = yes
+ read only = no
+ printable = no
+ path = /samba/tmp
+ create mask = 0777
+
+[transfer]
+ comment = the market place
+ browseable = yes
+ available = yes
+ public = yes
+ read only = no
+ printable = no
+ path = /samba/transfer
+ create mask = 0777
+
+[homes]
+ comment = home directories
+ browseable = no
+ ;ONLY the home-dirs are visible, not the service itself
+ available = yes
+ guest ok = no
+ read only = no
+ printable = no
+ create mode = 0700
+
+[install]
+ comment = all of the many install files
+ browsable = yes
+ available = yes
+ public = no
+ username = @root, @users
+ writable = yes
+ read list = @users
+ printable = no
+ path = /samba/install
+ create mode = 0755
+
+[doc-help]
+ comment = documentations, helpfiles, FAQ's
+ browsable = yes
+ available = yes
+ public = no
+ username = @root, @users
+ writable = yes
+ read list = @users
+ printable = no
+ path = /samba/doc
+ create mode = 0755
+
+[cd_rom_2]
+ comment = the CD in the CD-ROM drive on PANDORA
+ browsable = yes
+ available = yes
+ public = yes
+ writable = no
+ printable = no
+ path = /cdrom
+
+[reference]
+ ;the default, if invalid accesses
+ comment = PANDORA: Samba LAN manager
+ browsable = yes
+ ;only as an hint
+ available = no
+ ;however no access possible
+ public = yes
+ writable = no
+ printable = no
+ path = /samba/tmp
+
diff --git a/examples/tridge/README b/examples/tridge/README
new file mode 100644
index 00000000000..11c72f20b3a
--- /dev/null
+++ b/examples/tridge/README
@@ -0,0 +1,8 @@
+This is the configuration I use at home. I have 2 client PCs, one
+running Win95, one running alternately WfWg and NTAS3.5. My server is
+a 486dx2-66 Linux box.
+
+Note that I use the %a and %m macros to load smb.conf extensions
+particular to machines and architectures. This gives me a lot of
+flexibility in how I handle each of the machines.
+
diff --git a/examples/tridge/smb.conf b/examples/tridge/smb.conf
new file mode 100644
index 00000000000..a2f269f3b76
--- /dev/null
+++ b/examples/tridge/smb.conf
@@ -0,0 +1,101 @@
+[global]
+ config file = /usr/local/samba/smb.conf.%m
+ status = yes
+ security = user
+ encrypt passwords = yes
+ server string = Tridge (%v,%h)
+ load printers = yes
+ log level = 1
+ log file = /usr/local/samba/var/log.%m
+ guest account = pcguest
+ hosts allow = 192.0.2. localhost
+ password level = 2
+ auto services = tridge susan
+ message command = csh -c '/usr/bin/X11/xedit -display :0 %s;rm %s' &
+ read prediction = yes
+ socket options = TCP_NODELAY
+ valid chars = : : :
+ share modes = yes
+ locking = yes
+ strict locking = yes
+ keepalive = 30
+ include = /usr/local/samba/lib/smb.conf.%m
+ include = /usr/local/samba/lib/smb.conf.%a
+
+
+[uniprint]
+ comment = University Printing
+ path = /home/susan/print
+ user = susan
+ postscript = yes
+ print ok = yes
+ print command = xmenu -heading "%s" OK&
+
+[testprn]
+ comment = Test printer
+ path = /tmp
+ user = susan
+ print ok = yes
+ print command = cp %s /tmp/smb.%U.prn
+ lpq command = cat /tmp/xxyz
+
+[amd]
+ comment = amd area
+ path = /mount
+ force user = tridge
+ read only = no
+
+[homes]
+ browseable = no
+ guest ok = no
+ read only = no
+ create mask = 0755
+
+[printers]
+ browseable = no
+ comment = Printer in Printcap
+ guest ok = no
+ path = /tmp
+ read only = no
+ print ok = yes
+
+[dos]
+ browseable = yes
+ comment = Dos Files
+ force group = samba
+ create mode = 0775
+ path = /home/tridge/dos
+ copy = homes
+
+[msoffice]
+ browseable = yes
+ comment = Microsoft Office
+ force group = samba
+ create mode = 0775
+ path = /data/msoffice
+ read only = yes
+
+[root]
+ comment = Root Dir
+ copy = dos
+ path = /
+ dont descend = /proc ./proc /etc
+
+[tmp]
+ comment = tmp files
+ copy = dos
+ path = /tmp
+ read only = no
+
+
+[cdrom]
+ comment = Tridge's CdRom
+ path = /mount/cdrom
+ read only = yes
+ locking = no
+
+[data]
+ comment = Data Partition
+ path = /data
+ read only = yes
+ guest ok = yes
diff --git a/examples/tridge/smb.conf.WinNT b/examples/tridge/smb.conf.WinNT
new file mode 100644
index 00000000000..f490f830ca7
--- /dev/null
+++ b/examples/tridge/smb.conf.WinNT
@@ -0,0 +1,14 @@
+#log level = 4
+#readraw = no
+#writeraw = no
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/tridge/smb.conf.fjall b/examples/tridge/smb.conf.fjall
new file mode 100644
index 00000000000..76f4d0e3cad
--- /dev/null
+++ b/examples/tridge/smb.conf.fjall
@@ -0,0 +1,21 @@
+;log level = 4
+;readraw = no
+;writeraw = no
+;password level = 4
+;mangled map = (;1 )
+;protocol = lanman1
+;user = susan
+;getwd cache = no
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/tridge/smb.conf.lapland b/examples/tridge/smb.conf.lapland
new file mode 100644
index 00000000000..f490f830ca7
--- /dev/null
+++ b/examples/tridge/smb.conf.lapland
@@ -0,0 +1,14 @@
+#log level = 4
+#readraw = no
+#writeraw = no
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/tridge/smb.conf.vittjokk b/examples/tridge/smb.conf.vittjokk
new file mode 100644
index 00000000000..919ecd15420
--- /dev/null
+++ b/examples/tridge/smb.conf.vittjokk
@@ -0,0 +1,14 @@
+;protocol = LANMAN2
+log level = 2
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/validchars/msdos70.out b/examples/validchars/msdos70.out
new file mode 100644
index 00000000000..a722b83604f
--- /dev/null
+++ b/examples/validchars/msdos70.out
@@ -0,0 +1,257 @@
+255: ok
+254: ok
+253: ok
+252: ok
+251: ok
+250: ok
+249: ok
+248: ok
+247: ok
+246: ok
+245: ok
+244: ok
+243: ok
+242: ok
+241: ok
+240: ok
+239: ok
+238: ok
+237: ok
+236: 237
+235: ok
+234: ok
+233: ok
+232: ok
+231: 232
+230: ok
+229: ok
+228: 229
+227: ok
+226: ok
+225: ok
+224: ok
+223: ok
+222: ok
+221: ok
+220: ok
+219: ok
+218: ok
+217: ok
+216: ok
+215: ok
+214: ok
+213: 73
+212: ok
+211: ok
+210: ok
+209: ok
+208: 209
+207: ok
+206: ok
+205: ok
+204: ok
+203: ok
+202: ok
+201: ok
+200: ok
+199: ok
+198: 199
+197: ok
+196: ok
+195: ok
+194: ok
+193: ok
+192: ok
+191: ok
+190: ok
+189: ok
+188: ok
+187: ok
+186: ok
+185: ok
+184: ok
+183: ok
+182: ok
+181: ok
+180: ok
+179: ok
+178: ok
+177: ok
+176: ok
+175: ok
+174: ok
+173: ok
+172: ok
+171: ok
+170: ok
+169: ok
+168: ok
+167: ok
+166: ok
+165: ok
+164: 165
+163: 233
+162: 224
+161: 214
+160: 181
+159: ok
+158: ok
+157: ok
+156: ok
+155: 157
+154: ok
+153: ok
+152: length 0
+151: 235
+150: 234
+149: 227
+148: 153
+147: 226
+146: ok
+145: 146
+144: ok
+143: ok
+142: ok
+141: 222
+140: 215
+139: 216
+138: 212
+137: 211
+136: 210
+135: 128
+134: 143
+133: 183
+132: 142
+131: 182
+130: 144
+129: 154
+128: ok
+127: ok
+126: ok
+125: ok
+124: open unlink 0
+123: ok
+122: 90
+121: 89
+120: 88
+119: 87
+118: 86
+117: 85
+116: 84
+115: 83
+114: 82
+113: 81
+112: 80
+111: 79
+110: 78
+109: 77
+108: 76
+107: 75
+106: 74
+105: 73
+104: 72
+103: 71
+102: 70
+101: 69
+100: 68
+99: 67
+98: 66
+97: 65
+96: ok
+95: ok
+94: ok
+93: open unlink 0
+92: open unlink 0
+91: open unlink 0
+90: ok
+89: ok
+88: ok
+87: ok
+86: ok
+85: ok
+84: ok
+83: ok
+82: ok
+81: ok
+80: ok
+79: ok
+78: ok
+77: ok
+76: ok
+75: ok
+74: ok
+73: ok
+72: ok
+71: ok
+70: ok
+69: ok
+68: ok
+67: ok
+66: ok
+65: ok
+64: ok
+63: open unlink 0
+62: open unlink 0
+61: open unlink 0
+60: open unlink 0
+59: open unlink 0
+58: open unlink 0
+57: ok
+56: ok
+55: ok
+54: ok
+53: ok
+52: ok
+51: ok
+50: ok
+49: ok
+48: ok
+47: open unlink 0
+46: open unlink 0
+45: ok
+44: open unlink 0
+43: open unlink 0
+42: open unlink 0
+41: ok
+40: ok
+39: ok
+38: ok
+37: ok
+36: ok
+35: ok
+34: open unlink 0
+33: ok
+32: open unlink 0
+31: open unlink 0
+30: open unlink 0
+29: open unlink 0
+28: open unlink 0
+27: open unlink 0
+26: open unlink 0
+25: open unlink 0
+24: open unlink 0
+23: open unlink 0
+22: open unlink 0
+21: open unlink 0
+20: open unlink 0
+19: open unlink 0
+18: open unlink 0
+17: open unlink 0
+16: open unlink 0
+15: open unlink 0
+14: open unlink 0
+13: open unlink 0
+12: open unlink 0
+11: open unlink 0
+10: open unlink 0
+9: open unlink 0
+8: open unlink 0
+7: open unlink 0
+6: open unlink 0
+5: open unlink 0
+4: open unlink 0
+3: open unlink 0
+2: open unlink 0
+1: open unlink 0
+
+ valid chars = 73:213 213:73 73:73 33 35 36 37 38 39 40 41 45 48 49 50 51 52 53 54 55 56 57 64 97:65 98:66 99:67 100:68 101:69 102:70 103:71 104:72 105:73 106:74 107:75 108:76 109:77 110:78 111:79 112:80 113:81 114:82 115:83 116:84 117:85 118:86 119:87 120:88 121:89 122:90 94 95 96 123 125 126 127 135:128 132:142 134:143 130:144 145:146 148:153 129:154 156 155:157 158 159 164:165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 160:181 131:182 133:183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198:199 200 201 202 203 204 205 206 207 208:209 136:210 137:211 138:212 161:214 140:215 139:216 217 218 219 220 221 141:222 223 162:224 225 147:226 149:227 228:229 230 231:232 163:233 150:234 151:235 236:237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
diff --git a/examples/validchars/nwdos70.out b/examples/validchars/nwdos70.out
new file mode 100644
index 00000000000..b0dbf628531
--- /dev/null
+++ b/examples/validchars/nwdos70.out
@@ -0,0 +1,257 @@
+255: ok
+254: ok
+253: ok
+252: ok
+251: ok
+250: ok
+249: ok
+248: ok
+247: ok
+246: ok
+245: ok
+244: ok
+243: ok
+242: ok
+241: ok
+240: ok
+239: ok
+238: ok
+237: ok
+236: ok
+235: ok
+234: ok
+233: ok
+232: ok
+231: ok
+230: ok
+229: ok
+228: ok
+227: ok
+226: ok
+225: ok
+224: ok
+223: ok
+222: ok
+221: ok
+220: ok
+219: ok
+218: ok
+217: ok
+216: ok
+215: ok
+214: ok
+213: ok
+212: ok
+211: ok
+210: ok
+209: ok
+208: ok
+207: ok
+206: ok
+205: ok
+204: ok
+203: ok
+202: ok
+201: ok
+200: ok
+199: ok
+198: ok
+197: ok
+196: ok
+195: ok
+194: ok
+193: ok
+192: ok
+191: ok
+190: ok
+189: ok
+188: ok
+187: ok
+186: ok
+185: ok
+184: ok
+183: ok
+182: ok
+181: ok
+180: ok
+179: ok
+178: ok
+177: ok
+176: ok
+175: ok
+174: ok
+173: ok
+172: ok
+171: ok
+170: ok
+169: ok
+168: ok
+167: ok
+166: ok
+165: ok
+164: 165
+163: 85
+162: 79
+161: 73
+160: 65
+159: ok
+158: ok
+157: ok
+156: ok
+155: ok
+154: ok
+153: ok
+152: 89
+151: 85
+150: 85
+149: 79
+148: 153
+147: 79
+146: ok
+145: 146
+144: ok
+143: ok
+142: ok
+141: 73
+140: 73
+139: 73
+138: 69
+137: 69
+136: 69
+135: 128
+134: 143
+133: 65
+132: 142
+131: 65
+130: 69
+129: 154
+128: ok
+127: ok
+126: ok
+125: ok
+124: open unlink 0
+123: ok
+122: 90
+121: 89
+120: 88
+119: 87
+118: 86
+117: 85
+116: 84
+115: 83
+114: 82
+113: 81
+112: 80
+111: 79
+110: 78
+109: 77
+108: 76
+107: 75
+106: 74
+105: 73
+104: 72
+103: 71
+102: 70
+101: 69
+100: 68
+99: 67
+98: 66
+97: 65
+96: ok
+95: ok
+94: ok
+93: open unlink 0
+92: open unlink 0
+91: open unlink 0
+90: ok
+89: ok
+88: ok
+87: ok
+86: ok
+85: ok
+84: ok
+83: ok
+82: ok
+81: ok
+80: ok
+79: ok
+78: ok
+77: ok
+76: ok
+75: ok
+74: ok
+73: ok
+72: ok
+71: ok
+70: ok
+69: ok
+68: ok
+67: ok
+66: ok
+65: ok
+64: ok
+63: open unlink 0
+62: open unlink 0
+61: open unlink 0
+60: open unlink 0
+59: open unlink 0
+58: open unlink 0
+57: ok
+56: ok
+55: ok
+54: ok
+53: ok
+52: ok
+51: ok
+50: ok
+49: ok
+48: ok
+47: open unlink 0
+46: open unlink 0
+45: ok
+44: open unlink 0
+43: open unlink 0
+42: open unlink 0
+41: ok
+40: ok
+39: ok
+38: ok
+37: ok
+36: ok
+35: ok
+34: open unlink 0
+33: ok
+32: length 0
+31: open unlink 0
+30: open unlink 0
+29: open unlink 0
+28: open unlink 0
+27: open unlink 0
+26: open unlink 0
+25: open unlink 0
+24: open unlink 0
+23: open unlink 0
+22: open unlink 0
+21: open unlink 0
+20: open unlink 0
+19: open unlink 0
+18: open unlink 0
+17: open unlink 0
+16: open unlink 0
+15: open unlink 0
+14: open unlink 0
+13: open unlink 0
+12: open unlink 0
+11: open unlink 0
+10: open unlink 0
+9: open unlink 0
+8: open unlink 0
+7: open unlink 0
+6: open unlink 0
+5: open unlink 0
+4: open unlink 0
+3: open unlink 0
+2: open unlink 0
+1: open unlink 0
+
+ valid chars = 69:130 130:69 69:69 65:131 131:65 65:65 65:133 133:65 65:65 69:136 136:69 69:69 69:137 137:69 69:69 69:138 138:69 69:69 73:139 139:73 73:73 73:140 140:73 73:73 73:141 141:73 73:73 79:147 147:79 79:79 79:149 149:79 79:79 85:150 150:85 85:85 85:151 151:85 85:85 89:152 152:89 89:89 65:160 160:65 65:65 73:161 161:73 73:73 79:162 162:79 79:79 85:163 163:85 85:85 33 35 36 37 38 39 40 41 45 48 49 50 51 52 53 54 55 56 57 64 97:65 98:66 99:67 100:68 101:69 102:70 103:71 104:72 105:73 106:74 107:75 108:76 109:77 110:78 111:79 112:80 113:81 114:82 115:83 116:84 117:85 118:86 119:87 120:88 121:89 122:90 94 95 96 123 125 126 127 135:128 132:142 134:143 144 145:146 148:153 129:154 155 156 157 158 159 164:165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
diff --git a/examples/validchars/readme b/examples/validchars/readme
new file mode 100644
index 00000000000..6487fbd766a
--- /dev/null
+++ b/examples/validchars/readme
@@ -0,0 +1,101 @@
+Note: All files in this directory are DOS formatted (CRLF line terminator).
+
+!!! VIRUS WARNING !!! I do not know if VALIDCHR.COM is virus free !!!
+I think that my system is virus free here because I do not run any games
+or other copied software. I only run Shareware/Freeware etc. from CD-ROMs
+or from registered disks, however I do not use viral scanners because
+I have not registered any (I consider `having no sex' is better than
+`testing for AIDS on a regular basis', if you know what I mean).
+
+This is VALIDCHR, a little DOS program I wrote to create
+an apropriate `valid chars =' config parameter.
+It is freeware and is thought to be distributed freely with Samba.
+
+WARNING:
+ Your SMB driver may use another character map as the one VALIDCHR
+ sees. The only way you can tell this is that some file names fail.
+ Under Win95 everything is fine, though.
+
+Usage:
+ c:
+ mkdir junk_dir
+ cd junk_dir
+ a:validchr > a:output.log
+ cd ..
+ rmdir junk_dir
+
+Siedeffects:
+ Files named *.TST may be deleted.
+
+Verification:
+ For diagnostic purpose you can run VALIDCHR on a Samba mounted drive.
+ Then you can use unix diff to compare the output of the network and
+ the hard drive. These two outputs usually differ! However there
+ should be few differences. I get following on Win95 (c: visa e:)
+ 104c104
+ < 152: length 0
+ ---
+ > 152: 95
+ (diff line for `valid chars =' deleted because it's uninteresting)
+ You can see, `y diaresis' can be mapped on the network drive while
+ it cannot be mapped on the hard drive. Everything else is identical.
+ However this gives a hint that one can improve the mapping.
+
+Bugs:
+ Yes, probably some.
+
+
+VALIDCHR must be run on the system which character mapping should be probed.
+It must be run on the hard drive for this. VALIDCHR ALTERS THE CURRENT
+DIRECTORY AND REMOVES SOME FILES, SO ALWAYS RUN IT IN A junk DIRECTORY !!!
+You should redirect the output of VALIDCHR. At the end of the output is a
+line like
+ valid chars = x:y y:x x:x ... a:b c ...
+which is suitable for your smb.conf file. (you should remove the DOS CR
+character, because DOS uses CRLF while Unix uses LF only.)
+
+Note that some mappings at the beginning of the `valid chars =' line like
+A:B B:A B:B
+might look a little bit strange to you, however sometimes character A
+has to be mapped to character B independently of a default mapping
+to uppercase or lowercase while character B must not be touched. I found
+this out the hard way ... Consider it a crude workaround, because Samba
+lacks the possibility to map characters in one direction only!
+
+VALIDCHR usually issues one warning for character 32.
+You may ignore these and any other warnings.
+
+VALIDCHR does not test for character NUL (this is the directory end marker).
+
+validchr.c is the source code to validchr.com
+ You may do anything with the source code (copy, change, sell, burn)
+validchr.com is a Borland C compiled binary.
+ Beware, it may contain a virus (if my system contains one).
+nwdos70.out is the output of an VALIDCHR-run under Novell DOS 7.0
+ while no codepage (no display.sys) was active.
+msdos70.out is the output of an VALIDCHR-run under MS-DOS 7.0 (Win95 DOS)
+ while codepage 850 was active.
+
+I have no other MS-DOS systems at home currently.
+(I have access to MS-DOS 3.0, 3.2, 3.3, 5.0 and 6.22, however I have no time
+ to run VALIDCHR there)
+
+Some words to the output
+(for people not fammiliar with programming language C):
+
+probed_char: [text] mapped_char
+
+probed_char is the character probed to be written to disk
+text may be empty or contain:
+ open File could not be opened.
+ close File could not be closed (should not happen)
+ length File name was shortened (usually occurs on SPC)
+ unlink File cannot be unlinked (usually when open fails)
+mapped_char is the character which is used by MS-DOS in the directory
+ This is usually the uppercase character.
+ The mapped character is 0 if something failed (you may say
+ that the character is not supported)
+
+The last line in the output is documented in the smb.conf manual page ;)
+
+tino@augsburg.net
diff --git a/examples/validchars/validchr.c b/examples/validchars/validchr.c
new file mode 100644
index 00000000000..415546cb841
--- /dev/null
+++ b/examples/validchars/validchr.c
@@ -0,0 +1,123 @@
+/* by tino@augsburg.net
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <dirent.h>
+
+unsigned char
+test(void)
+{
+ DIR *dir;
+ struct dirent *dp;
+ unsigned char c;
+
+ if ((dir=opendir("."))==0)
+ {
+ perror("open .");
+ return 0;
+ }
+ c = 0;
+ while ((dp=readdir(dir))!=0)
+ {
+ size_t len;
+
+ len = strlen(dp->d_name);
+ if (len<4)
+ continue;
+ if (strcmp(dp->d_name+len-4, ".TST"))
+ continue;
+ if (len!=5)
+ {
+ fprintf(stderr, "warning: %s\n", dp->d_name);
+ printf(" length");
+ continue;
+ }
+ if (c)
+ printf(" double%d\n", c);
+ c = dp->d_name[0];
+ }
+ if (closedir(dir))
+ perror("close .");
+ return c;
+}
+
+int
+main(void)
+{
+ char name[256];
+ unsigned char map[256], upper[256], lower[256];
+ int i, j, c;
+ FILE *fd;
+
+ if (test())
+ {
+ printf("There are *.TST files, please remove\n");
+ return 0;
+ }
+ for (i=0; ++i<256; )
+ {
+ lower[i] = i;
+ upper[i] = 0;
+ }
+ for (i=256; --i; )
+ {
+ map[i] = i;
+ strcpy(name, "..TST");
+ name[0] = i;
+ printf("%d:", i);
+ if ((fd=fopen(name, "w"))==0)
+ printf(" open");
+ else
+ fclose(fd);
+ c = test();
+ if (unlink(name))
+ printf(" unlink");
+ if (c==i)
+ printf(" ok");
+ else
+ printf(" %d", c);
+ printf("\n");
+ if (c!=i)
+ {
+ upper[c]++;
+ lower[c] = i;
+ }
+ map[i] = c;
+ }
+
+ /* Uppercase characters are detected above on:
+ * The character is mapped to itself and there is a
+ * character which maps to it.
+ * Lowercase characters are the lowest character pointing to another one.
+ * Else it is a one way character.
+ *
+ * For this reason we have to process the list
+ * 1) for 'one way' characters
+ * 'one way' is something which is no upper and no lower character.
+ * This is an awful, crude and ugly hack due to missing Samba support.
+ * 2) for true uppercase/lowercase characters
+ * 3) for standalone characters
+ * Note that there might be characters which do not fall into 1 to 3.
+ */
+ printf("\n valid chars =");
+ for (i=0; ++i<256; )
+ if (map[i] && map[i]!=i && lower[map[i]]!=i)
+ {
+ if (!upper[i])
+ printf(" %d:%d %d:%d %d:%d", /*1*/
+ map[i], i, i, map[i], map[i], map[i]);
+ else
+ fprintf(stderr, "ignoring map %d->%d because of %d->%d\n",
+ lower[i], i, i, map[i]);
+ }
+ for (i=0; ++i<256; )
+ if (map[i] && map[i]==i)
+ if (upper[i])
+ printf(" %d:%d", lower[i], i); /*2*/
+ else
+ printf(" %d", i); /*3*/
+ printf("\n");
+ return 0;
+}
diff --git a/examples/validchars/validchr.com b/examples/validchars/validchr.com
new file mode 100644
index 00000000000..a5dbb39bedf
--- /dev/null
+++ b/examples/validchars/validchr.com
@@ -0,0 +1,77 @@
+.0!.,ڣ   . ] 3؋aC&8ùى  +>#s>#>'r(>R#r"G;r>#t>R#u;wډ  +؎JW!_ҋ3.&>'+>$#vG> r@w> r7X!r*g$#!r H!r@ HI!r
+X!sb 
+t @p&3.&&6 6 6 Py.VW&&_^ËLF! 5!  5!  5!  5!  %ʎں{!% !% !% !% !ø׋;t&?t&O2;sӃ;t&?&t&_&Wô׋;t&?t &8gr&gӃ;t&?&t&_&Wô@!ù .PPUVW!P6YF u !PYF]VYsO !PPYY t8tV!P"P!PmY~tFP%!PWYYFvtY uvY t0!PYFt_^]UC
+t 8!PY3aF^؊F^FF=|Fƍ^؊F^!PPYYFvd!PYYh!PPYYF u j!PvYFPJY tp!PeYF;Fu
+x!PUY v|!PHYY!P?YF;Ft^^؊F^؊FNt2!PYFҍ^؀?u^؊;Fu鬍^؊‹؊;Fu鋍^؊ uJ^؊P^؊P^؊Pvv^؊P!PZ0^؊Pvv^؊P!P"Pw FF=} FW^؀?tI^؊;Fu7^؀?tv^؊P!P v!PYYFF=|!]U>! u!F&!3]UC2V!r ^3P?]UCVN!r3P$]U/!SV!NNV!YZ!Qr3S]U/!SV!O!YZ!Qr3S]UVv u!!&>!u!~u u!!vY^]U3PPv]UP3Pv]3PP3PøPP3PyUVv |X~W6T#V# ރ0T#6 ^]UVvV^]UD^!%]U"VW~
+^$wXrSF N }~t -G؃ٍv+F +F uNN,
+s:FﰪF
+_^] U3Pvv
+PPaPj]U^で&#BF
+^NV!rP]UVvV u.'v u#PVYYP#PVYY^]UVWv~V3P=uPFPVTYY t׋_^];$#s+LJ&#ڱƇ!!㉇!B;$#rՠ!PtY u&!P!t3P3P!PZ!P@Y u&!P!t3P3P!P&UAV!r3P]Ê'@'UVWFFPFFW2I_6GNu/SQRj+jPWvV
+ uFFP~jZY[j~~v
+t<%t6GNv<%t~3ɉNNNFF2Ћ؀ `s#v.wNЀwNŀw~+tV뵃fN 맀wMFu)N8~6Fs y؃NFou׉FbsʵFU,0wF |F3uF tFNeNfY
+
+
+FV3҈V~6
+FV~6GGvFt6GG~~ u u~u 6NRPWǘPFPSV }Vv~^67CC^F t6CC^:Z6FfN+ϋV;韉vV~6F~26‰vV~F u 6=F 6=F u#P;NvN酉vV~N }WQ^SR#FPFt F
+FP~FtV ~&=-uI+~V&=-t F
+tO&~~
+N }N~^#F=ufou ~FxtXuN@KKn}FNFu  yK;F@t 0hFbV ~'++&<-t< t<+u&CIK08+&6GN+ ~ ˰ Uv~F u 6=F6=FP*FF&FtGG&v~%
+u~P}~tF_^]^ H S   | A  # ' M  n t UVW~vY@PvW _^]UFԁ;s 3  ]UFV ҋ ur
+;s  ]UvY]UFRPYY]ú$$)$@!'.$@!UVDF^N
+!r ~uP]VW\r;X$tB_^9V$t#wt6X$ ;6V$t TGX$ 3V$X$Z$S[;V$twu?u2?t\ߋ;t>Z$wu|Z$Ë6Z$ t|\]wÉZ$__VWD tRr6%=s>V$tZ$ t 9s_;uf!397sk_^P3PP6[[%t 3RP([[XP3SP[[=t؉V$X$X@[3P3SP[[=tءX$GX$X@X3)7@\uËSPQP[ tv VF$[^˃;w5;X$uSPK[[]+)|Bˋ7كVWU^F
+ t7 t-IЃs;r wO PeS3[]_^&&UNCFV!rPy]UV;$#r PdLJ&#RY]U>^!r LJ&#3P5]UVWv YPY u
+ 3pvV YYO t߀8:t8\t
+8/t\$a$PV YY/PY u  VWPV t VYWY뙉u+E-E.݋_^]UVv|.uVPt+D-^]UVv|.t
+ 3D- u VY uD-^]UVv t|.t  D.t+YV Y3^]UVW~ td9}u_}t=} WVY uKEtuY}| EPWYEEE} t3PPu PYE _^]UVW~ unf9}t^=|)Eu
+9E
+uF9E
+u8EE
+0.E@)5PEE
+PEP
+;t EuM3_^]UVWF>$#!DtVbYFO uF_^]UVWvFF<ru wuau  F3i F+t<+uttbu+u Ftu@buʀN#% Ћ©t@! ^^F_^]UVv
+vFPFP4D t |}'vF FPvD
+} DD3ADP'Y tLPDt3P3PV tVYD ^]V!||$#!փ;w||3^U u3 Rvv3P$]UPvvFP]UVWv<}
+TB 3+‹ЋD@u,L
+<} Iـ?
+uGJ uA?
+uGJ u_^]UVWv~
+V7Y tGu<~ V|)FVd_DD
+WvvDPu
+=u3_^]UVvP33PRDPUVFu=u鄃<}tD&#tWP33PRDPVFu=tP3PvvDPu =u*FVFVVFV V)FVVF^]UVW~vNsF_^]UN<V!rP]U^++Ҵ@!]UVWv~uN#% 3PvYYFtx#>P#ǩuP.~u#>T#t
+6T#ǀt3F t7PPtv3PO }WYvv6 }lVvYY |Z3PW~YYFt ƀt% PPW[
+tWFtttPPv |/t3ց RFt3Z Ћ㉗&#_^]UNu
+uV"N
+=!rFF% ^㉇&#FP]U ;$}> |  ㋗f$&Rv&P"PT]UP!PvFP]UVv VFPYY^]UVW~F<'=}:]
+E
+Eu><'
+t
+><' tWY uڸEuEuMM}tE=t WeY uʋE؉]
+E
+<'Eu鈀><'
+t><' uzW2Y tqmE&#tP33PREP><'
+uE@uP&PEPO=uP<'PEP7=t
+Eu=<'_^]U!PvYY]UVW~FFEt)W^FPYY=u3YFN uIE@u}u隋E;FsQ=t W=Y uŊE&#tP33PREPvvEPn;Fu݋F|=u
++E WY t`vvu
+FFE
+霊E&#tP33PREP!vvEP;Fta\}t=/}]
+E
+vFW^FPVYY=uFN uvvEP;FtF_^]UVWv~
+9tu ~v馃>&u!u&>&u !u&<tP33PRVjDtt,YdDDD
+~t> v:!B ~uWYF uuLlFD
+D|~uL3_^]UVW~2u~+tIs_^]UVW؎3؋~2ыvD]+_^]UVW~2ы~F_^]UW؎~3H_]UVW~v;>$#r
+PF@=s3Ӌ&#tP33PRW&#@uvVW訃霋で&#vFFMN^FF<
+u FFFx+Ё|'+VPW[;tu=F+F1x~ux+ v!VxPW ;ttŋF+F_^]U^&#tP@^NV!rP^く&#XP]VW3!;>$#sDtVYG;>$#r_^VW!DtV"YO u_^Borland C++ - Copyright 1991 Borland Intl.Divide error
+Abnormal program termination
+>'>'.open ..TSTwarning: %s
+ length double%d
+close .There are *.TST files, please remove
+..TST%d:w open unlink ok %d
+
+ valid chars = %d:%d %d:%d %d:%dignoring map %d->%d because of %d->%d
+ %d:%d %d
+ !
+!"C"B$"```@),(((((),(((),#,*((((**#(#%(TMP.$$$(null)  
+
+   print scanf : floating point formats not linked
+\*.**.*$$$%%%%7%G%\%n%%%%%%%%&&#&4&E&W&i&j&k&l&m&n&o&p&q&r&s&&&&&&&&&&&&&&&0Error 0Invalid function numberNo such file or directoryPath not foundToo many open filesPermission deniedBad file numberMemory arena trashedNot enough memoryInvalid memory block addressInvalid environmentInvalid formatInvalid access codeInvalid dataNo such deviceAttempted to remove current directoryNot same deviceNo more filesInvalid argumentArg list too bigExec format errorCross-device linkMath argumentResult too largeFile already existsPossible deadlockUnknown error%s: %s
diff --git a/examples/wins_hook/README b/examples/wins_hook/README
new file mode 100644
index 00000000000..1147f57e22f
--- /dev/null
+++ b/examples/wins_hook/README
@@ -0,0 +1,8 @@
+This is an example script for doing dynamic DNS updates from the WINS
+database. You use this by putting the full path to the script in the
+"wins hook" option in smb.conf. Remember to mark the script executable
+and to set the right domain at the top of the script.
+
+See the BIND documentation for how to enable dynamic DNS
+updates. Remember to restrict the updates as far as you can to reduce
+the security risks inherent in dynamic DNS.
diff --git a/examples/wins_hook/dns_update b/examples/wins_hook/dns_update
new file mode 100644
index 00000000000..a4c1a79ab9c
--- /dev/null
+++ b/examples/wins_hook/dns_update
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# Example script for "wins hook". This attempts to update the DNS with
+# new A records for the NETBIOS name that Samba passes us. We do this
+# the simple way, by deleting all DNS records for the name and then
+# readding all the expected 'A' records.
+#
+# Written by Stephen Rothwell <sfr@linuxcare.com>
+#
+
+#
+# Configurable things
+#
+# The domain in which to create names
+# YOU MUST CHANGE THIS
+# N.B. include the trailing dot
+#
+# It is a good idea to use a subdomain of your primary domain to ensure
+# that rogue machines can't take over (or delete) important names on
+# your network.
+DOMAIN=wins.example.com.
+
+#
+# The DNS TTL to give the records (in seconds)
+#
+TTL=3600
+#
+# NETBIOS name types that we want to create DNS records for:
+# 20 is server
+# 00 is workstation
+# 03 is user
+#
+USEFUL_TYPES="20 00 03"
+#
+# The name of a cache file to use to avoid continual updates
+# of the same name and IP addresses. If you comment this out
+# then the cache is not kept at all.
+#
+#CACHE_FILE=/usr/local/samba/var/wins_update.cache
+
+if [ $# -lt 4 ]; then
+ echo "Usage: $0 op name type ttl [ip_addr ...]" 1>&2
+ echo " op is one of add, refresh, delete" 1>&2
+ echo " name is the NETBIOS name" 1>&2
+ echo " type is the NETBIOS name type" 1>&2
+ echo " ttl is the NETBIOS time to live" 1>&2
+ echo " ip_addr's are the remaining IP addresses for this name" 1>&2
+ exit 1
+fi
+
+NSUPDATE=`which nsupdate`
+[ -x "$NSUPDATE" ] || NSUPDATE=/usr/bin/nsupdate
+[ -x "$NSUPDATE" ] || NSUPDATE=/sbin/nsupdate
+[ -x "$NSUPDATE" ] || NSUPDATE=/usr/sbin/nsupdate
+[ -x "$NSUPDATE" ] || {
+ echo "Cannot find nsupdate." 1>&2
+ exit 1
+}
+
+OP=$1
+NAME=$2
+TYPE=$3
+WINS_TTL=$4
+shift 4
+IP_ADDRS="$@"
+
+do_update=0
+for i in $USEFUL_TYPES
+do
+ [ "$TYPE" = "$i" ] && do_update=1
+done
+[ $do_update = 1 ] || exit 0
+
+if [ -n "$CACHE_FILE" ]; then
+ if [ -r "$CACHE_FILE" ]; then
+ fgrep -q -x -i "$NAME $IP_ADDRS" "$CACHE_FILE" &&
+ exit 0
+ grep -v -i "^$NAME " "$CACHE_FILE" >"$CACHE_FILE".$$
+ fi
+ echo "$NAME $IP_ADDRS" >>"$CACHE_FILE".$$
+ mv "$CACHE_FILE" "$CACHE_FILE".old 2>/dev/null
+ mv "$CACHE_FILE".$$ "$CACHE_FILE"
+fi
+
+{
+ echo update delete $NAME.$DOMAIN
+ for i in $IP_ADDRS
+ do
+ echo update add $NAME.$DOMAIN $TTL A $i
+ done
+ echo
+} 2>/dev/null | $NSUPDATE >/dev/null 2>&1 &
+
+exit 0