patch smbldap-tools-0.8.4

Jianliang Lu j.lu at tiesse.com
Thu Apr 1 10:09:13 GMT 2004


In attachment is the patch for smbldap-tools-0.8.4.

The main changes for smbldap-tools-0.8.4 are following:

- Use Getopt::Long, extended processing of command line options.

- Use Pod::Usage to print a usage message from embedded pod documentation.

- For every ldap_master->fn operation, if it failed the progarm will exit,
  so changed from "warn" to "die".

- Added the option -r rid for smbldap-useradd and smblap-usermod. This is 
  useful for migration issue.

- For both smbldap-useradd and smbldap-groupadd, if the -a is selected without
  select the rid or sid, other than check the existence of the sid calculated
  from the rid=2 * $userUidNumber + 1000, we'll do a rid++ until find suitable
  rid. Also, the check of existence of the sid is applied to Computer scope
  as well.

- Added the option -W to smbldap-useradd for create posix machine account only
  and -w to create samba machine account. This is useful for joindomain with 
  or without "create a computer account in the domain " option from windows
  client.

- In smbldap-usermod, the " -l newname " is implemented to change account
  name. The -R to reset the "sambaBadPasswordCount" and unlock the user if it
  was autolocked.

- Added -a to smbldap-usershow and smbldap-groupshow for show all users or  
  groups.

- Added "read_alluser_entry", "read_allgroup_entry" and "is_samba_group" to 
  smbldap_tools.pm.

Jianliang Lu

TieSse s.p.a.     Ivrea (To) - Italy
j.lu at tiesse.com   luj at libero.it
http://www.tiesse.com
-------------- next part --------------
--- ./smbldap-groupadd.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-groupadd	Wed Mar 31 11:20:24 2004
@@ -29,62 +29,115 @@
 use FindBin qw($RealBin);
 use lib "$RealBin/";
 use smbldap_tools;
-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);
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+my $group_sid;
+my $group_rid;
+my $group_type;
+my $group_type_nam;
+my $_groupGidNumber;
+
+my ($opt_auto_group ,$opt_not_unique_gid , $opt_print_gid ,$opt_help,$opt_man);
+
+my $ok = GetOptions( 
+        "auto-groupmap|a", \$opt_auto_group,	
+        "gid|g=n",   \$_groupGidNumber,
+        "rid|r=n",   \$group_rid,
+        "sid|s=s",   \$group_sid,
+	    "not-unique|o", \$opt_not_unique_gid,
+	    "group-type|t=s",	\$group_type_nam,
+	    "print-gid|p",  \$opt_print_gid,
+	    "help|?", \$opt_help,
+		"man",\$opt_man);
+
+if ($opt_man) {
+#
+# Code hacked from perldoc 
+#
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many group given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+#
+# Control 
+
+if (defined($group_rid) && defined($group_sid) ) {
+	pod2usage({-verbose => 1, -message => "$myprogname: only one of the options [--rid|-r] and [--sid|-s] are possible\n",-exitval => 1,-output => \*STDERR}) ;
+}
+
+if (defined($group_rid) || defined($group_sid) || defined($opt_auto_group)) {
+	if (defined($group_type_nam) && $group_type_nam !~ /^domain$|^builtin$|^local$/ ) {
+		pod2usage({-verbose => 1, -message => "$myprogname: the option [--group_type|-t] accept only one of 'builtin','domain','local' value\n",-exitval => 1,-output => \*STDERR}) ;
+	}
+}
+if (defined($group_type_nam)) {
+	if (!defined($group_sid) && !defined($group_sid) && !defined($opt_auto_group) ) {
+		pod2usage({-verbose => 1, -message => "$myprogname: the option [--group_type|-t] {builtin|local|domain} \n require any of [--auto-group|a], [--sid|s] or [--rid|r] \n",-exitval => 1,-output => \*STDERR}) ;
+	}
+}
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
 }
 
 my $_groupName = $ARGV[0];
 
 if (defined(get_group_dn($_groupName))) {
-  warn "$0: group $_groupName exists\n";
+  warn "$myprogname: 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";
+if (! defined ($_groupGidNumber = group_add($_groupName, $_groupGidNumber, $opt_not_unique_gid))) {
+  warn "$myprogname: 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 = $config{SID}.'-'.$group_rid;
+#
+# Invariant: $_groupGidNumber is defined 
+# 
+if (defined($group_sid)) {
+	if($group_sid !~ /^S-(?:\d+-)+\d+$/) {
+    	warn "$myprogname: illegal group-sid $group_sid\n";
+    	exit(7);
+	}
+}
+elsif (defined($group_rid) || defined($opt_auto_group)) {
+	if (!defined($group_rid)){
+   		# algorithmic mapping
+    	$group_rid = 2*$_groupGidNumber+1001;
+   	     # let's test if this SID already exist
+  		$group_sid = $config{SID}.'-'.$group_rid;
+  		my $test_exist_sid=does_sid_exist($group_sid,$config{groupsdn});
+   		while ($test_exist_sid->count == 1) {
+				$group_rid++;
+  				$group_sid = $config{SID}.'-'.$group_rid;
+  				$test_exist_sid=does_sid_exist($group_sid,$config{groupsdn});
+   	     }
+	}
+  	$group_sid = $config{SID}.'-'.$group_rid;
 }
+#
+# Invariant if opt_auto_group or group_rid or group_sid 
+# group_sid is well-defined
 
-if ($Options{'r'} || $Options{'a'} || $Options{'s'}) {
+if ($group_sid) {
   # let's test if this SID already exist
   my $test_exist_sid=does_sid_exist($group_sid,$config{groupsdn});
   if ($test_exist_sid->count == 1) {
@@ -99,12 +152,11 @@
   }
 }
 
-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";
+# group_sid is always defined also if auto_group is set 
+if (defined($group_sid)) {
+  if (defined($group_type_nam)) {
+    unless (defined($group_type = &group_type_by_name($group_type_nam))) {
+      warn "$myprogname: unknown group type $group_type_nam\n";
       exit(8);
     }
   } else {
@@ -118,16 +170,34 @@
 											  'sambaGroupType' => $group_type
 											 }
 									);
-  $modify->code && warn "failed to delete entry: ", $modify->error ;
+  $modify->code && die "failed to delete entry: ", $modify->error ;
   # take down session
-  $ldap_master->unbind
+  $ldap_master->unbind;
 }
 
-if ($Options{'p'}) {
-  print STDOUT "$_groupGidNumber";
+if (defined($opt_print_gid)) {
+  print STDOUT "gid=$_groupGidNumber\n";
 }
 exit(0);
 
+###################################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname [-agorst?] groupname
+ {-a|--auto-group-map}   add automatic group mapping entry
+ {-g|--gid}              gid
+ {-o|--not-unique}       gid is not unique
+ {-r|--rid}              group-rid
+ {-s|--sid}              group-sid
+ {-t|--group-type}        group-type (builtin,local,domain)
+ {-p|--print-gid}        print the gidNumber to stdout
+ {-?|--help}             show this help message
+ {--man}                 print the man page
+EOF
+ exit ($rc);
+}
+
 ########################################
 
 =head1 NAME
@@ -136,18 +206,29 @@
 
 =head1 SYNOPSIS
 
-       smbldap-groupadd [-g gid [-o]] group
+	   smbldap-groupadd [-agorst?] group
+		 {-a|--auto-group-map}   add automatic group mapping entry
+		 {-g|--gid}              gid
+		 {-o|--not-unique}       gid is not unique
+		 {-r|--rid}              group-rid
+		 {-s|--sid}              group-sid
+		 {-t|--group-type}        group-type (builtin,local,domain)
+		 {-p|--print-gid}        print the gidNumber to stdout
+		 {-?|--help}             show this help message
+		 {--man}                 print the man page
 
 =head1 DESCRIPTION
-       The smbldap-groupadd 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.
+
+   The smbldap-groupadd 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
 
--- ./smbldap.conf.orig	Thu Mar 25 14:08:06 2004
+++ ./smbldap.conf	Thu Mar 25 14:06:53 2004
@@ -149,7 +149,7 @@
 
 # The default user netlogon script name
 # if not used, will be automatically username.cmd
-# $userScript=startup.cmd # make sure script file is edited under dos
+userScript=startup.cmd 
 
 
 ##############################################################################
--- ./smbldap-groupmod.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-groupmod	Mon Mar 15 14:44:30 2004
@@ -32,35 +32,70 @@
 use smbldap_tools;
 
 #####################
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
 
-use Getopt::Std;
-my %Options;
+# 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);
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+my $group_sid;
+my $group_rid;
+my $group_type;
+my $group_type_nam;
+my $gid;
+my $new_gid;
+my $group_entry;
+my $newname;
+
+my ($opt_auto_group ,$opt_not_unique_gid , $opt_members_add,$opt_members_del,$opt_help,$opt_man);
+
+my $ok = GetOptions( 
+        "auto-groupmap|a", \$opt_auto_group,	
+        "gid|g=n",   \$new_gid,
+        "rid|r=n",   \$group_rid,
+        "sid|s=s",   \$group_sid,
+	    "not-unique|o", \$opt_not_unique_gid,
+	    "new-groupname|n=s",	\$newname,
+	    "add-member|m=s",	\$opt_members_add,
+	    "del-member|x=s",	\$opt_members_del,
+	    "group-type|t=s",	\$group_type_nam,
+	    "help|?", \$opt_help,
+		"man",\$opt_man);
+
+if ($opt_man) {
+#
+# Code hacked from perldoc 
+#
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many group given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+#
+
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
 }
 
 my $groupName = $ARGV[0];
-my $group_entry;
 
 if (! ($group_entry = read_group_entry($groupName))) {
-  print "$0: group $groupName doesn't exist\n";
+  print "$myprogname: 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";
 
@@ -68,25 +103,50 @@
   system "/etc/init.d/nscd restart > /dev/null 2>&1";
 }
 
-my $gid = getgrnam($groupName);
+$gid = getgrnam($groupName);
 unless (defined ($gid)) {
-  print "$0: group $groupName not found!\n";
+  print "$myprogname: 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";
+my $is_samba_gp = is_samba_group($groupName);
+#
+# Control 
+# 
+if (defined($group_rid) || defined($group_sid) || defined($group_type_nam)) {
+   if (!($is_samba_gp)) {
+        if (!defined($opt_auto_group)) {
+		pod2usage({-verbose => 1, -message => "$myprogname: incompatible options:\n the group $groupName isn't a samba group \n",-exitval => 1,-output => \*STDERR}) ;
+		}
+   }
+}   
+#
+if (defined($group_type_nam) && $group_type_nam !~ /^domain$|^builtin$|^local$/ ) {
+    	pod2usage({-verbose => 1, -message => "$myprogname: the option [--group_type|-t] accept only one of 'builtin','domain','local' value\n",-exitval => 1,-output => \*STDERR}) ;
+	}
+if (defined($group_rid) && defined($group_sid)) {
+		pod2usage({-verbose => 1, -message => "$myprogname: only one of the options [--rid|-r] and [--sid|-s] are possible\n",-exitval => 1,-output => \*STDERR}) ;
+}
+if (defined($opt_not_unique_gid) && !defined($new_gid)) {
+		pod2usage({-verbose => 1, -message => "$myprogname: the option [--not-unique|-o] require [--gid|g]\n",-exitval => 1,-output => \*STDERR}) ;
+}
+
+if (defined($new_gid) and $new_gid =~ /\d+/) {
+  if (!defined($opt_not_unique_gid)) {
+	if (defined(getgrgid($new_gid))) {
+	  print "$myprogname: gid $new_gid exists\n";
 	  exit (6);
 	}
   }
-  if (!($gid == $tmp)) {
+  if (!($gid == $new_gid)) {
+    # ok new is different from old : do equal 
+	# so if is defined auto_group and not a samba group
+	# define algorithmic the SID (see above)
+	$gid=$new_gid;
 	my $ldap_master=connect_ldap_master();
 	my $modify = $ldap_master->modify ( "cn=$groupName,$config{groupsdn}",
 										changes => [
-													replace => [gidNumber => $tmp]
+													replace => [gidNumber => $new_gid]
 												   ]
 									  );
 	$modify->code && die "failed to modify entry: ", $modify->error ;
@@ -106,13 +166,15 @@
 								   );
   $modify->code && die "failed to modify entry: ", $modify->error ;
   # take down session
-  $ldap_master->unbind
+  $ldap_master->unbind;
+  $groupName=$newname;
 }
 
+
+
 # Add members
-if (defined($Options{'m'})) {
-  my $members = $Options{'m'};
-  my @members = split( /,/, $members );
+if ($opt_members_add) {
+  my @members = split( /,/, $opt_members_add);
   my $member;
   foreach $member ( @members ) {
 	my $group_entry=read_group_entry($groupName);
@@ -128,7 +190,7 @@
 														add => [memberUid => $member]
 													   ]
 										  );
-		$modify->code && warn "failed to add entry: ", $modify->error ;
+		$modify->code && die "failed to add entry: ", $modify->error ;
 		# take down session
 		$ldap_master->unbind
 	  }
@@ -139,9 +201,8 @@
 }
 
 # Delete members
-if (defined($Options{'x'})) {
-  my $members = $Options{'x'};
-  my @members = split( /,/, $members );
+if ($opt_members_del) {
+  my @members = split( /,/, $opt_members_del);
   my $member;
   foreach $member ( @members ) {
         my $group_entry=read_group_entry($groupName);
@@ -162,42 +223,48 @@
 	}
   }
 }
-
-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);
-    }
+######
+#
+# Invariant: $gid is defined 
+# 
+if (defined($group_sid)){ 
+	if($group_sid !~ /^S-(?:\d+-)+\d+$/) {
+   		warn "$myprogname: illegal group-sid $group_sid\n";
+    	exit(7);
+	}
+}
+elsif (defined($group_rid) || defined($opt_auto_group)) {
+  if (defined($group_rid)) {
+    $group_sid = $config{SID}.'-'.$group_rid;
   } else {
+    # is defined opt_auto_group and if is_samba_group set sid at your sid 
+	# else
     # algorithmic mapping
-    $group_rid = 2*$gid+1001;
+	if ($is_samba_gp) {
+    	my $group_entry=read_group_entry($groupName);
+#    	$group_sid = $group_entry->sambaSID;
+    	$group_sid = $group_entry->get_value('sambaSID');
+	} else {
+    	$group_rid = 2*$gid+1001;
+    	$group_sid = $config{SID}.'-'.$group_rid;
+		}
   }
-  $group_sid = $config{SID}.'-'.$group_rid;
 }
+#
+# Invariant: if opt_auto_group or group_rid or group_sid 
+# or is a samba group 
+# group_sid is well-defined
 
 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))) {
+  if (defined($group_type_nam)) {
+    if (defined($group_type = &group_type_by_name($group_type_nam))) {
       push(@mods, 'sambaGroupType' => $group_type);
     } else {
-      print "$0: unknown group type $tmp\n";
+      print "$myprogname: unknown group type $group_type_nam\n";
       exit(8);
     }
   } else {
@@ -231,6 +298,26 @@
 
 exit (0);
 
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname  [-a] [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] [-r rid] [-s sid] [-t type] groupname
+
+  {-a|--auto-groupmap}  add automatic group mapping entry
+  {-g|--gid}            new gid;
+  {-o|--not-unique}     gid is not unique
+  {-n|--new-groupname}  new group name
+  {-m|--add-member}     add members (comma delimited)
+  {-r|--rid}            group-rid
+  {-s|--sid}            group-sid
+  {-t|--group-type}     group-type (builtin,local,domain)
+  {-x|--del-member}     delete members (comma delimted)
+  {-?|--help}            show this help message
+  {--man}                print the man page
+EOF
+ exit ($rc);
+}
+
 ############################################################
 
 =head1 NAME
@@ -239,41 +326,45 @@
 
 =head1 SYNOPSIS
 
-smbldap-groupmod [-g gid [-o]] [-n group_name ] group
+smbldap-groupmod {-a|--auto-groupmap} 
+[{-g|--gid} gid {-o|--not-unique}] [{-n|--new-groupname} name] [{-m|--add-member} members(,)] [{-r|--rid} rid] [{-s|--sid} sid] [{-t|--group-type} type] [{-x|--del-member} members (,)]  groupname 
+
+smbldap-groupmod {-?|--help} {--man} 
 
 =head1 DESCRIPTION
 
 The smbldap-groupmod 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
+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.
+  -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.
+  -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.
+  -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.
+  -x members
+     The members to be removed from the group in comma-delimted form.
 
 =head1 EXAMPLES
 
-       smbldap-groupmod -g 253 development
-	      This will change the GID of the 'development' group to '253'.
+     smbldap-groupmod -g 253 development
+     This will change the GID of the 'development' group to '253'.
 
-       smbldap-groupmod -n Idiots Managers
-	      This will change the name of the 'Managers' group to 'Idiots'.
+     smbldap-groupmod -n Idiots Managers
+     This will change the name of the 'Managers' group to 'Idiots'.
 
-       smbldap-groupmod -m "jdoe,jsmith" "Domain Admins"
-	      This will add 'jdoe' and 'jsmith' to the 'Domain Admins' group.
+     smbldap-groupmod -m "jdoe,jsmith" "Domain Admins"
+     This will add 'jdoe' and 'jsmith' to the 'Domain Admins' group.
 
-       smbldap-groupmod -x "jdoe,jsmith" "Domain Admins"
-	      This will remove 'jdoe' and 'jsmith' from the 'Domain Admins' group.
+     smbldap-groupmod -x "jdoe,jsmith" "Domain Admins"
+     This will remove 'jdoe' and 'jsmith' from the 'Domain Admins' group.
 
 =head1 SEE ALSO
 
--- ./smbldap-groupshow.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-groupshow	Mon Mar 15 14:44:30 2004
@@ -32,29 +32,91 @@
 use FindBin qw($RealBin);
 use lib "$RealBin/";
 use smbldap_tools;
-use Getopt::Std;
-my %Options;
-
-my $ok = getopts('?', \%Options);
+##############
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+my ($opt_all_group,$opt_help,$opt_man);
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+
+my $ok = GetOptions( 
+   "all-group|a", \$opt_all_group,	
+    "help|?", \$opt_help,
+	"man",\$opt_man);
+# 
+# if man and help do man
+#
+if ($opt_man) {
+#
+# Code hacked from perldoc 
+#
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+#
+if (defined($opt_all_group) && (@ARGV >= 1)) {
+	pod2usage({-verbose => 1, -message => "$myprogname: the option [--all-group|-a] doesn't require a group \n",-exitval => 1,-output => \*STDERR}) ;
+}
+pod2usage({-verbose => 1, -message => "$myprogname: Too many group given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
 
-if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-  print "Usage: $0 [-?] group\n";
-  print "  -?	show this help message\n";
-	exit (1);
+if  (!$ok )  {
+  show_usage(1);
 }
 
-# Read only first @ARGV
-my $group = $ARGV[0];
+my $group;
+if (defined($opt_all_group)) { 
+    my @attrs=('cn');
+	my $lines=read_allgroup_entry(\@attrs);
+	if (defined($lines)) {
+     print "$lines\n";
+	} else
+	{
+	 print "$myprogname: no samba group found\n";
+	}
+} 
+else {
+	if  (@ARGV < 1 )  {
+  		show_usage(1);
+    }
+ # Read only first @ARGV
+ $group = $ARGV[0];
+
+ my $lines = read_group($group);
+ if (!defined($lines)) {
+     print "$0: group $group doesn't exist\n";
+     exit (1);
+ }
 
-my $lines = read_group($group);
-if (!defined($lines)) {
-    print "$0: group $group doesn't exist\n";
-    exit (1);
+ print "$lines\n";
 }
 
-print "$lines\n";
-
 exit(0);
+#################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname {-a|--all-group} {-?|--help} [--man] [group]
+ {-a|--all-group}       display the name of all samba groups 
+ {-?|--help}            show this help message
+ {--man}                print the man page
+EOF
+ exit ($rc);
+}
 
 ############################################################
 
@@ -65,11 +127,15 @@
 =head1 SYNOPSIS
 
        smbldap-groupshow groupname
+       smbldap-groupshow [-a|--all-group] 
+       smbldap-groupshow [-?|--help] [--man]
 
 =head1 DESCRIPTION
 
        The smbldap-groupshow command displays informations
-       associated with the given group.
+       associated with the given group or lists all samba group 
+	   name.
+	    
 
 =cut
 
--- ./smbldap-userdel.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-userdel	Mon Mar 15 14:44:30 2004
@@ -32,35 +32,61 @@
 
 
 #####################
-
-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);
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+my ($opt_remove_home_dir,$opt_help,$opt_man);
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+
+my $ok = GetOptions( 
+   "remove-home|r", \$opt_remove_home_dir,	
+    "help|?", \$opt_help,
+	"man",\$opt_man);
+
+
+# if man and help do man
+# Code hacked from perldoc 
+#
+if ($opt_man) {
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many user given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+#
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
 }
-
 # Read only first @ARGV
 my $user = $ARGV[0];
 
 my $dn;
-# user must not exist in LDAP
+# user must exist in LDAP
 if (!defined($dn=get_user_dn($user))) {
-  print "$0: user $user does not exist\n";
+  print "$myprogname: user $user does not exist\n";
   exit (6);
 }
 
 if ($< != 0) {
-  print "You must be root to delete an user\n";
+  print "$myprogname: You must be root to delete an user\n";
   exit (1);
 }
 
 my $homedir;
-if (defined($Options{'r'})) {
+if (defined($opt_remove_home_dir)) {
   $homedir=get_homedir($user);
 }
 
@@ -84,7 +110,7 @@
 delete_user($user);
 
 # delete dir -- be sure that homeDir is not a strange value
-if (defined($Options{'r'})) {
+if (defined($opt_remove_home_dir)) {
   if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
 	system "rm -rf $homedir";
   }
@@ -98,6 +124,18 @@
 
 exit (0);
 
+#################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname {-r|--remove-home} {-?|--help} [--man] username
+ {-r|--remove-home}     remove home directory
+ {-?|--help}            show this help message
+ {--man}                print the man page
+EOF
+ exit ($rc);
+}
+############################################################
 ############################################################
 
 =head1 NAME
--- ./smbldap-usermod.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-usermod	Wed Mar 31 09:23:06 2004
@@ -32,41 +32,77 @@
 
 #####################
 
-use Getopt::Std;
-my %Options;
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
 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\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);
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+
+my $_userUidNumber;
+my $_userGidNumber;
+my $_userRidNumber;
+my $grouplist;
+my $userHomeDirectory;
+my $userLoginShell;
+my $userGecos;
+my $skeletonDir;
+my ($userCN,$userSN);
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+my ($opt_can_changepass ,$opt_not_unique_uid,$opt_password ,$opt_must_changepass ,$smb_home_path ,$smb_home_drive ,$smb_logon_script ,$smb_profile_path ,$_sambaAcctFlags ,$opt_help ,$opt_win_user ,$opt_enable,$opt_disable,$opt_badpwd_reset,$smb_expire_date,$opt_man,$newname);
+
+my $ok = GetOptions( 
+        "win-account|a", \$opt_win_user,	
+	    "not-unique|o", \$opt_not_unique_uid,
+		"login-name|l=s",\$newname,
+        "uid|u=n",       \$_userUidNumber,
+        "gid|g=n",   \$_userGidNumber,
+        "rid|r=n",   \$_userRidNumber,
+	    "supplementary-group|G=s",	\$grouplist,
+	    "home|d=s",	\$userHomeDirectory,
+	    "shell|s=s",	\$userLoginShell,
+	    "gecos|c=s",	\$userGecos,
+	    "skeleton-dir|k=s",	\$skeletonDir,
+	    "password|P",  \$opt_password,
+	    "can-change-pass|A=n", \$opt_can_changepass,
+	    "must-change-pass|B=n",\$opt_must_changepass,
+		"smb-expire-date|e=s" , \$smb_expire_date,
+	    "smb-home-path|C=s",\$smb_home_path,
+	    "smb-home-drive|D=s",\$smb_home_drive,
+	    "smb-logon-script|E=s",	\$smb_logon_script,
+	    "smb-profile-path|F=s",\$smb_profile_path,
+	    "smb-flag|H=s",\$_sambaAcctFlags,
+		"smb-disable|I",\$opt_disable,
+		"smb-enable|J",\$opt_enable,
+		"badpwd-reset|R",\$opt_badpwd_reset,
+	    "cname|N=s",	\$userCN,
+	    "surname|S=s",	\$userSN,
+	    "help|?", \$opt_help,
+		"man",\$opt_man);
+
+#
+# Code hacked from perldoc 
+#
+if ($opt_man) {
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+show_usage(1) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many user given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
 }
 
 if ($< != 0) {
@@ -80,7 +116,7 @@
 # Read user data
 my $user_entry = read_user_entry($user);
 if (!defined($user_entry)) {
-  print "$0: user $user doesn't exist\n";
+  print "$myprogname: user $user doesn't exist\n";
   exit (1);
 }
 
@@ -94,14 +130,14 @@
 
 my $tmp;
 my @mods;
-if (defined($tmp = $Options{'a'})) {
+if (defined($opt_win_user) and ($samba == 0)) {
 	# 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 $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;
@@ -120,27 +156,53 @@
                                                                                                         add => [sambaAcctFlags => "$valacctflags"],
                                                                                                    ]
 								  );
-	$modify->code && warn "failed to modify entry: ", $modify->error ;
+	$modify->code && die "failed to modify entry: ", $modify->error ;
+	$ldap_master->unbind;
 }
 
+if (defined($newname)) {
+  my @mods;
+  my $ldap_master=connect_ldap_master();
+  my $modify = $ldap_master->moddn (
+                                    "uid=$user,$config{usersdn}",
+                                     newrdn => "uid=$newname",
+                                     deleteoldrdn => "1",
+                                     newsuperior => "$config{usersdn}"
+                                   );
+  $modify->code && die "failed to modify entry: ", $modify->error ;
+  
+  # I prefer automatic update of sn and cn if rdn change
+  # but if the user prefer... in this case do it later
+  push(@mods, 'cn' => $newname) unless (defined($userCN));
+  push(@mods, 'sn' => $newname) unless (defined($userSN));
+  if (@mods) {
+    $modify = $ldap_master->modify (  "uid=$newname,$config{usersdn}",
+									'replace' => { @mods }
+								  );
+    $modify->code && die "failed to modify entry: ", $modify->error ;
+  }
+  #take down session
+  $ldap_master->unbind;
+  $user=$newname; # swap
+}
+
+
 # Process options
 my $changed_uid;
-my $_userUidNumber;
-my $_userRid;
-if (defined($tmp = $Options{'u'})) {
-  if (defined($Options{'o'})) {
+if (defined($_userUidNumber)) {
+  if (defined($opt_not_unique_uid)) {
 	$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 (getpwuid($_userUidNumber)) {
 	  if ($nscd_status == 0) {
 		system "/etc/init.d/nscd start > /dev/null 2>&1";
 	  }
 
-	  print "$0: uid number $tmp exists\n";
+	  print "$myprogname: uid number $_userUidNumber exists\n";
 	  exit (6);
 	}
 	if ($nscd_status == 0) {
@@ -148,26 +210,43 @@
 	}
 
   }
-  push(@mods, 'uidNumber', $tmp);
-  $_userUidNumber = $tmp;
+  push(@mods, 'uidNumber', $_userUidNumber);
+  $changed_uid = 1;
+}
+
+if (defined($_userRidNumber)) {
   if ($samba) {
-    # as rid we use 2 * uid + 1000
-    my $_userRid = 2 * $_userUidNumber + 1000;
-    if (defined($Options{'x'})) {
-      $_userRid= sprint("%x", $_userRid);
+	my $user_sid = $config{SID}.'-'.$_userRidNumber;
+
+    my $test_exist_sid_userdn=does_sid_exist($user_sid,$config{usersdn});
+	if ($test_exist_sid_userdn->count == 1) { 
+		my $user_entry = $test_exist_sid_userdn->shift_entry();
+		if ($user_entry->get_value('uid') ne $user ){
+			print "rid already exist, select another rid! \n";
+			exit 6;
+		}
+	}
+    if ($config{computersdn} ne $config{usersdn}) {
+    	my $test_exist_sid_computersdn=does_sid_exist($user_sid,$config{computersdn});
+    	if ($test_exist_sid_computersdn->count == 1) {
+			my $user_entry = $test_exist_sid_computersdn->shift_entry();
+			if ($user_entry->get_value('uid') ne $user ){
+				print "rid already exist, select another rid! \n";
+				exit 6;
+			}
+        }
     }
-    push(@mods, 'sambaSID', $config{SID}.'-'.$_userRid);
+    push(@mods, 'sambaSID', $user_sid);
   }
-  $changed_uid = 1;
 }
 
 my $changed_gid;
-my $_userGidNumber;
 my $_userGroupSID;
-if (defined($tmp = $Options{'g'})) {
-  $_userGidNumber = parse_group($tmp);
+if (defined($_userGidNumber)) {
+  # userGidNumber could be a groupname or a gid
+  $_userGidNumber = parse_group($_userGidNumber);
   if ($_userGidNumber < 0) {
-	print "$0: group $tmp doesn't exist\n";
+	print "$myprogname: group $_userGidNumber doesn't exist\n";
 	exit (6);
   }
   push(@mods, 'gidNumber', $_userGidNumber);
@@ -177,6 +256,7 @@
     my $_userGroupSID = $group_entry->get_value('sambaSID');
     unless ($_userGroupSID) {
       print "Error: sambaPrimaryGroupSid could not be set (sambaSID for group $_userGidNumber does not exist\n";
+      print "$myprogname: group SID not set for unix group $_userGidNumber\n";
       exit (7);
     }
     push(@mods, 'sambaPrimaryGroupSid', $_userGroupSID);
@@ -184,32 +264,34 @@
   $changed_gid = 1;
 }
 
-if (defined($tmp = $Options{'s'})) {
-  push(@mods, 'loginShell' => $tmp);
+if (defined($userLoginShell)) {
+  push(@mods, 'loginShell' => $userLoginShell);
 }
 
 
-if (defined($tmp = $Options{'c'})) {
-  push(@mods, 'gecos' => $tmp,
-	   'description' => $tmp);
+if (defined($userGecos)) {
+  push(@mods, 'gecos' => $userGecos,
+	   'description' => $userGecos);
   if ($samba == 1) {
-    push(@mods, 'displayName' => $tmp);
+    push(@mods, 'displayName' => $userGecos);
   }
 }
 
-if (defined($tmp = $Options{'d'})) {
-  push(@mods, 'homeDirectory' => $tmp);
+
+if (defined($userHomeDirectory)) {
+  push(@mods, 'homeDirectory' => $userHomeDirectory);
 }
 
-if (defined($tmp = $Options{'N'})) { 
-  push(@mods, 'cn' => $tmp);
+if (defined($userCN)) { 
+  push(@mods, 'cn' => $userCN);
 }
 
-if (defined($tmp = $Options{'S'})) { 
-  push(@mods, 'sn' => $tmp);
+if (defined($userSN)) { 
+  push(@mods, 'sn' => $userSN);
 }
 
-if (defined($tmp = $Options{'G'})) {
+
+if (defined($grouplist)) {
 
   # remove user from old groups
   my $groups = find_groups_of $user;
@@ -228,7 +310,7 @@
   }
 
   # add user to new groups
-  add_grouplist_user($tmp, $user);
+  add_grouplist_user($grouplist, $user);
 }
 
 #
@@ -245,21 +327,25 @@
 
 $samba = is_samba_user($user);
 
-if (defined($tmp = $Options{'e'})) {
+if (defined($smb_expire_date)) {
   if ($samba == 1) {
-	my $kickoffTime=`date --date='$tmp' +%s`;
-	chomp($kickoffTime);
-	push(@mods, 'sambakickoffTime' => $kickoffTime);
+	my $kickoffTime=`date --date='$smb_expire_date' +%s 2>&1`;
+ 	if ($?) {
+  		die "$myprogname: $smb_expire_date is incorrect\n. See (sh-utils)Date input format in the info documentation \n";
+    } else {
+		chomp($kickoffTime);
+		push(@mods, 'sambakickoffTime' => $kickoffTime);
+	}
   } else {
   	print "User $user is not a samba user\n";
   }
 }
 
 my $_sambaPwdCanChange;
-if (defined($tmp = $Options{'A'})) {
+if (defined($opt_can_changepass)) {
   if ($samba == 1) {
     $attr = "sambaPwdCanChange";
-    if ($tmp != 0) {
+    if ($opt_can_changepass != 0) {
       $_sambaPwdCanChange=0;
     } else {
       $_sambaPwdCanChange=$winmagic;
@@ -270,10 +356,31 @@
   }
 }
 
+if (defined($opt_badpwd_reset)) {
+  if ($samba == 1) {
+      # if the user is lockout, we should unlock it
+      my $_sambaAcctFlags;
+      my $flags = $user_entry->get_value('sambaAcctFlags');
+      if ( $flags =~ /L/ ) {
+      	my $letters;
+      	if ($flags =~ /(\w+)/) {
+  		  $letters = $1;
+      	}
+      	$letters =~ s/L//;
+  		$_sambaAcctFlags="\[$letters\]";
+      	push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
+      }
+		push(@mods, 'sambaBadPasswordTime' => '0');
+    	push(@mods, 'sambaBadPasswordCount' => '0');
+  } else {
+  	print "User $user is not a samba user\n";
+  }
+}
+
 my $_sambaPwdMustChange;
-if (defined($tmp = $Options{'B'})) {
+if (defined($opt_must_changepass)) {
   if ($samba == 1) {
-    if ($tmp != 0) {
+    if ($opt_must_changepass != 0) {
       $_sambaPwdMustChange=0;
       # To force a user to change his password:
       # . the attribut sambaPwdLastSet must be != 0
@@ -286,12 +393,12 @@
   		$letters = $1;
       	}
       	$letters =~ s/X//;
-  	$_sambaAcctFlags="\[$letters\]";
+  		$_sambaAcctFlags="\[$letters\]";
       	push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
       }
       my $_sambaPwdLastSet = $user_entry->get_value('sambaPwdLastSet');
       if ($_sambaPwdLastSet == 0) {
-	push(@mods, 'sambaPwdLastSet' => $winmagic);
+		push(@mods, 'sambaPwdLastSet' => $winmagic);
       }
     } else {
       $_sambaPwdMustChange=$winmagic;
@@ -302,54 +409,50 @@
   }
 }
 
-if (defined($tmp = $Options{'C'})) {
+if (defined($smb_home_path)) {
   if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    push(@mods, 'sambaHomePath' => $tmp);
+    push(@mods, 'sambaHomePath' => $smb_home_path);
   } else {
   	print "User $user is not a samba user\n";
   }
 }
 
 my $_sambaHomeDrive;
-if (defined($tmp = $Options{'D'})) {
+if (defined($smb_home_drive)) {
   if ($samba == 1) {
-    $tmp = $tmp.":" unless ($tmp =~ /:/);
-    push(@mods, 'sambaHomeDrive' => $tmp);
+    $smb_home_drive = $smb_home_drive.":" unless ($smb_home_drive =~ /:/);
+    push(@mods, 'sambaHomeDrive' => $smb_home_drive);
   } else {
   	print "User $user is not a samba user\n";
   }
 }
 
-if (defined($tmp = $Options{'E'})) {
+if (defined($smb_logon_script)) {
   if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    push(@mods, 'sambaLogonScript' => $tmp);
+    push(@mods, 'sambaLogonScript' => $smb_logon_script);
   } else {
   	print "User $user is not a samba user\n";
   }
 }
 
-if (defined($tmp = $Options{'F'})) {
+if (defined($smb_profile_path)) {
   if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    push(@mods, 'sambaProfilePath' => $tmp);
+    push(@mods, 'sambaProfilePath' => $smb_profile_path);
   } 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 {
+if ($samba == 1 and (defined ($_sambaAcctFlags) or defined ($opt_disable) or defined ($opt_enable))) {
+  if (! defined($_sambaAcctFlags)) {
     # I or J
     my $flags;
     $flags = $user_entry->get_value('sambaAcctFlags');
 
-    if (defined($tmp = $Options{'I'})) {
+    if (defined($opt_disable)) {
       if ( !($flags =~ /D/) ) {
 		my $letters;
 		if ($flags =~ /(\w+)/) {
@@ -357,7 +460,7 @@
 		}
 		$_sambaAcctFlags="\[D$letters\]";
       }
-    } elsif (defined($tmp = $Options{'J'})) {
+    } elsif (defined($opt_enable)) {
 	  if ( $flags =~ /D/ ) {
 		my $letters;
 		if ($flags =~ /(\w+)/) {
@@ -367,14 +470,12 @@
 		$_sambaAcctFlags="\[$letters\]";
 	  }
 	}
+  }elsif (defined($_sambaAcctFlags)) {
+		$_sambaAcctFlags="\[$_sambaAcctFlags\]";
   }
+  push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
 
-
-  if ("$_sambaAcctFlags" ne '') {
-    push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
-  }
-
-} elsif (!$samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
+} elsif (!$samba == 1 and (defined $_sambaAcctFlags or defined $opt_disable or defined $opt_enable)) {
   print "User $user is not a samba user\n";
 }
 
@@ -382,10 +483,12 @@
 my $ldap_master=connect_ldap_master();
 
 # apply changes
-my $modify = $ldap_master->modify ( "$dn",
+if (@mods) {
+	my $modify = $ldap_master->modify ( "$dn",
 									'replace' => { @mods }
 								  );
-$modify->code && warn "failed to modify entry: ", $modify->error ;
+	$modify->code && die "failed to modify entry: ", $modify->error ;
+}
 
 # take down session
 $ldap_master->unbind;
@@ -396,11 +499,55 @@
   system "/etc/init.d/nscd restart > /dev/null 2>&1";
 }
 
-if (defined($Options{'P'})) {
+if (defined($opt_password)) {
   exec "$RealBin/smbldap-passwd $user"
 }
 
+exit(0);
 
+#######################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname  
+
+  {-a|--win-account}    is a Windows User (otherwise, Posix stuff only)
+  {-l|--login-name}     new user name
+  {-o|--not-unique}     gid is not unique
+  {-u|--uid}            new uid
+  {-g|--gid}            new gid;
+  {-r|--rid}            new rid;
+  {-d|--home }          home directory
+  {-s|--shell}          shell
+  {-G|--supplementary-group} supplementary comma-separated groups
+  {-c|--gecos}          gecos
+  {-k|--skeleton-dir}    skeleton dir (with -m)
+  {-e|--smb-expire-date} expire date;
+  {-P|--password}        ends by invoking smbldap-passwd.pl
+  {-A|--can-change-pass} can change password ? 0 if no, 1 if yes
+  {-B|--must-change-pass} must change password ? 0 if no, 1 if yes
+  {-C|--smb-home-path}   sambaHomePath 
+                         (SMB home share, like '\\\\PDC-SRV\\homes')
+  {-D|--smb-home-drive}  sambaHomeDrive 
+                         (letter associated with home share, like 'H:')
+  {-E|--smb-logon-script} sambaLogonScript 
+                         (DOS script to execute on login)
+  {-F|--smb-profile-path} sambaProfilePath 
+                         (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+  {-H|--smb-flag}        sambaAcctFlags 
+                         (samba account control bits like '[NDHTUMWSLKI]')
+  {-N|--cname}           canonical name
+  {-S|--surname}         surname
+  {-I|--smb-disable}     disable user. Can't be used with -H or -J
+  {-J|--smb-enable}      enable user. Can't be used with -H or -I
+  {-R|--badpwd-reset}    reset bad password count and unlock the account if it was 
+                         locked out
+  {-?|--help}            show this help message
+  {--man}                print the man page
+EOF
+ exit ($rc);
+}
+############################################################
 ############################################################
 
 =head1 NAME
@@ -459,8 +606,7 @@
               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)
+       -r rid The numerical  value  of  the  user's rid.     
 
        -A     can change password ? 0 if no, 1 if yes
 
@@ -480,6 +626,8 @@
 
        -J     enable user. Can't be used with -H or -I
 
+       -R     reset bad password count and unlock the account if it was locked out
+
 =head1 SEE ALSO
 
        usermod(1)
--- ./smbldap-usershow.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-usershow	Mon Mar 15 14:44:30 2004
@@ -30,30 +30,126 @@
 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);
+##############
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+my ($opt_all_user,$opt_timestamp,$opt_help,$opt_man);
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+
+my $ok = GetOptions( 
+   "all-user|a", \$opt_all_user,	
+   "timestamp|t", \$opt_timestamp,	
+    "help|?", \$opt_help,
+	"man",\$opt_man);
+# 
+#
+#
+# Code hacked from perldoc 
+#
+if ($opt_man) {
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+show_usage(1) if $opt_help;
+#
+if (defined($opt_all_user) && (@ARGV >= 1)) {
+	pod2usage({-verbose => 1, -message => "$myprogname: the option [--all-user|-a] doesn't require an user \n",-exitval => 1,-output => \*STDERR}) ;
+}
+pod2usage({-verbose => 1, -message => "$myprogname: Too many user given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+if  (!$ok )  {
+  show_usage(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);
+my $user;
+if (defined($opt_all_user)) { 
+    my @attrs=('uid');
+	my $lines=read_alluser_entry(\@attrs);
+	if (defined($lines)) {
+     print "$lines\n";
+	} else
+	{
+	 print "$myprogname: no user found\n";
+	}
+} 
+else {
+	if  (@ARGV < 1 )  {
+  		show_usage(1);
+    }
+	$user = $ARGV[0];
+	my $lines = read_user($user);
+	if (!defined($lines)) {
+	 print "$myprogname: user $user doesn't exist\n";
+   	 exit (1);
+	}
+	if (defined($opt_timestamp)) { 
+			my @newline = split(/\n/,$lines);
+		$lines = "";
+		my $line;
+		foreach $line (@newline){
+			my @lline = split(/\: /, $line);
+			if ((($lline[0] =~ /Time/) || ($lline[0] =~ /sambaPwd/)) && (!($lline[0] =~ /sambaPwdH/)) && ($lline[1] != 0)) {
+				$lline[1] = scalar localtime($lline[1]); 	
+				$line = "$lline[0]".": "."$lline[1]";
+			}
+			$lines .= $line."\n";
+		}
+	}
+    print "$lines\n";
+
+	# user's groups
+	my $groups = find_groups_of($user);
+
+
+	print "\nGlobal Group memberships: \n\n";
+
+	if (defined($groups)){
+		my @grplines = split(/\n/,$groups);
+		my $grp;
+		foreach $grp (@grplines) {
+  			my $gname = "";
+  			if ( $grp =~ /dn: cn=([^,]+),/) {
+				$gname = $1;
+				print "$gname\n";
+  			}
+		}
+		print "\n";
+	}
+#	$groups =~ s/dn.*?cn=(.*?\w),.*?(?:\n|$)/$1\n/g;
+#	print "$groups\n";
 }
 
-print "$lines\n";
-
 exit(0);
 
+#################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname {-a|--all-user} {-?|--help} [--man] [username]
+ {-a|--all-user}        display the name of all users 
+ {-t|--timestamp}       display the timestamp in ctime liked format (dd,mm,hh...)
+ {-?|--help}            show this help message
+ {--man}                print the man page
+EOF
+ exit ($rc);
+}
+
 ############################################################
 
 =head1 NAME
--- ./smbldap_tools.pm.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap_tools.pm	Thu Mar 25 09:52:22 2004
@@ -39,6 +39,7 @@
 	     get_user_dn
 	     get_group_dn
 	     is_group_member
+		 is_samba_group
 	     is_samba_user
 	     is_unix_user
 	     is_user_valid
@@ -54,10 +55,12 @@
 	     group_add
 	     group_del
 	     get_homedir
+		 read_alluser_entry
 	     read_user
 	     read_user_entry
 	     read_group
 	     read_group_entry
+		 read_allgroup_entry
 	     read_group_entry_gid
 	     find_groups_of
 	     parse_group
@@ -245,6 +248,25 @@
 	return $dn;
   }
 
+
+
+# return (success, dn)
+# bool = is_samba_group($groupname)
+sub is_samba_group
+  {
+	my $group = shift;
+	my $ldap_slave=connect_ldap_slave();
+	my $mesg = $ldap_slave->search (    base   => $config{suffix},
+										scope => $config{scope},
+										filter => "(&(objectClass=sambaGroupMapping)(cn=$group))"
+								   );
+	$mesg->code && die $mesg->error;
+	$ldap_slave->unbind;
+	return ($mesg->count ne 0);
+  }
+
+# return (success, dn)
+
 # return (success, dn)
 # bool = is_samba_user($username)
 sub is_samba_user
@@ -356,7 +378,7 @@
 										  ]
 								);
 	
-	$add->code && warn "failed to add entry: ", $add->error ;
+	$add->code && die "failed to add entry: ", $add->error ;
 	# take down the session
 	$ldap_master->unbind;
 
@@ -611,6 +633,45 @@
 	return $lines;
   }
 
+
+# search for all samba user
+# return the attributes requested 
+# input must contain an arrayref 
+sub read_alluser_entry
+  {
+	my $attrs_ref = shift;
+	if (ref($attrs_ref) ne "ARRAY" ) {
+	 return undef;
+	}
+	my $lines='';
+	if (!$attrs_ref ) { $attrs_ref = ['uid' ]; }
+	my $ldap_slave=connect_ldap_slave();
+	my  $mesg = $ldap_slave->search ( # perform a search
+									 base   => $config{suffix},
+									 scope => $config{scope},
+									 filter => "(&(objectclass=posixAccount)(objectClass=sambaSamAccount))",
+									 attrs => $attrs_ref
+									);
+
+	$mesg->code && die $mesg->error;
+	if ($mesg->count() >0 ) {
+		foreach my $entry ($mesg->all_entries()) {
+	  		foreach my $attr ($entry->attributes) {
+				{
+		  				$lines.= join(',', $entry->get_value($attr))."\n";
+				}
+	        }
+		
+		}
+	}
+	$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
@@ -659,6 +720,47 @@
 	return $lines;
   }
 
+
+
+# search for all samba group
+# return the attributes requested 
+# input must contain an arrayref 
+sub read_allgroup_entry
+  {
+	my $attrs_ref = shift;
+	if (ref($attrs_ref) ne "ARRAY" ) {
+	 return undef;
+	}
+	my $lines='';
+	if (!$attrs_ref ) { $attrs_ref = ['cn' ]; }
+	my $ldap_slave=connect_ldap_slave();
+	my  $mesg = $ldap_slave->search ( # perform a search
+									 base   => $config{groupsdn},
+									 scope => $config{scope},
+									 filter => "(&(objectclass=posixGroup)(objectClass=sambaGroupMapping))",
+									 attrs => $attrs_ref
+									);
+
+	$mesg->code && die $mesg->error;
+	if ($mesg->count() >0 ) {
+		foreach my $entry ($mesg->all_entries()) {
+	  		foreach my $attr ($entry->attributes) {
+				{
+		  				$lines.= join(',', $entry->get_value($attr))."\n";
+				}
+	        }
+		
+		}
+	}
+	$ldap_slave->unbind;
+	chomp $lines;
+	if ($lines eq '') {
+	  return undef;
+	}
+	return $lines;
+ }
+
+
 # find groups of a given user
 ##### MODIFIE ########
 sub find_groups_of
--- ./smbldap-groupdel.orig	Mon Mar 15 14:44:30 2004
+++ ./smbldap-groupdel	Mon Mar 15 14:44:30 2004
@@ -31,14 +31,44 @@
 use smbldap_tools;
 
 #####################
-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);
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
+
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+
+my ($opt_help,$opt_man);
+
+my $ok = GetOptions( 
+	    "help|?", \$opt_help,
+		"man",\$opt_man);
+
+if ($opt_man) {
+#
+# Code hacked from perldoc 
+#
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many group given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+#
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
 }
 
 my $_groupName = $ARGV[0];
@@ -64,8 +94,19 @@
 #    exit (7);
 #}
 
-
 exit (0);
+#########################################
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname [-?|--help] [--man] groupname
+
+ {-?|--help}            show this help message
+ {--man}                print the man page
+ 
+EOF
+ exit ($rc);
+}
 
 ############################################################
 
@@ -77,13 +118,17 @@
 
        smbldap-groupdel group
 
+       smbldap-groupdel [-?|--help] [--man]
+
 =head1 DESCRIPTION
 
-       The smbldap-groupdel command modifies the system account files,
-       deleting all entries that refer to group. The named group must exist.
+       The smbldap-groupdel 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.
+       You must manually check all filesystems to insure that no 
+       files remain with the named group as the file group ID.
 
 =head1 SEE ALSO
 
--- ./smbldap-useradd.orig	Mon Mar 15 15:47:59 2004
+++ ./smbldap-useradd	Wed Mar 31 16:40:14 2004
@@ -32,39 +32,89 @@
 use smbldap_tools;
 #####################
 
-use Getopt::Std;
-my %Options;
+use Getopt::Long;
+use Pod::Usage;
+sub show_usage($);
 
-my $ok = getopts('anmwiPG:u:g:d:s:c:k:A:B:C:D:E:F:H:N:S:?', \%Options);
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
 
-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 "  -i	is a trust account (Windows Workstation)\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\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);
-}
 
+my $userUidNumber;
+my $userGidNumber;
+my $userRidNumber;
+my $grouplist;
+my $userHomeDirectory;
+my $userLoginShell;
+my $userGecos;
+my $skeletonDir;
+my ($userCN,$userSN);
+our $myprogname = $0;
+$myprogname =~ s,.*/,,;
+my ($opt_can_changepass ,$opt_makehome , $opt_password ,$opt_must_changepass ,$opt_home_path ,$opt_home_drive ,$opt_logon_script ,$opt_profile_path ,$opt_flag ,$opt_help  ,$opt_win_user ,$opt_win_workstation,$opt_win_workstation_posix ,$opt_interdomain ,$opt_man);
+
+my $ok = GetOptions( 
+        "win-user|a", \$opt_win_user,	
+        "win-workstation|w", \$opt_win_workstation,
+        "win-workstation-posix|W", \$opt_win_workstation_posix,
+	    "win-interdomain|i", \$opt_interdomain,
+        "uid|u=n",       \$userUidNumber,
+        "gid|g=n",   \$userGidNumber,
+        "rid|r=n",   \$userRidNumber,
+	    "supplementary-group|G=s",	\$grouplist,
+	    "home|d=s",	\$userHomeDirectory,
+	    "shell|s=s",	\$userLoginShell,
+	    "gecos|c=s",	\$userGecos,
+	    "make-home|m", \$opt_makehome,
+	    "skeleton-dir|k=s",	\$skeletonDir,
+	    "password|P",  \$opt_password,
+	    "can-change-pass|A=n", \$opt_can_changepass,
+	    "must-change-pass|B=n",\$opt_must_changepass,
+	    "smb-home-path|C=s",\$opt_home_path,
+	    "smb-home-drive|D=s",\$opt_home_drive,
+	    "smb-logon-script|E=s",	\$opt_logon_script,
+	    "smb-profile-path|F=s",\$opt_profile_path,
+	    "smb-flag|H=s",\$opt_flag,
+	    "cname|N=s",	\$userCN,
+	    "surname|S=s",	\$userSN,
+	    "help|?", \$opt_help,
+		"man",\$opt_man);
+
+if ($opt_man) {
+#
+# Code hacked from perldoc 
+#
+ if ($> == 0 || $< == 0) { 
+        my $id = eval { getpwnam("nobody") };
+           $id = eval { getpwnam("nouser") } unless defined $id;
+           $id = -2 unless defined $id;
+        eval {
+            $> = $id;  # must do this one first!
+            $< = $id;
+        };
+ }
+pod2usage(-verbose => 2, -exitval => 0,-output => \*STDOUT) ;
+}
+
+pod2usage(-verbose => 1, -exitval => 0,-output => \*STDOUT) if $opt_help;
+pod2usage({-verbose => 1, -message => "$myprogname: Too many user given \n",-exitval => 1,-output =>\*STDERR}) if (@ARGV > 1);
+#
+# Controls input validity
+#
+if (defined($opt_win_workstation) || defined($opt_interdomain)  || defined($opt_win_workstation_posix)) {
+  if (defined($grouplist) || defined($opt_makehome) || defined($skeletonDir) || defined($opt_password) || defined($opt_can_changepass) || defined($opt_must_changepass) || defined($opt_home_path) || defined($opt_home_drive) || defined($opt_logon_script) || defined($opt_profile_path) || defined($opt_flag) ) {
+	pod2usage({-verbose => 1, -message => "$myprogname: Incompatible options for [--win-workstation|-w] or [--win-interdomain|-i] \n",-exitval => 1,-output => \*STDERR}) ;
+  }
+}
+elsif (! defined($opt_win_user)) {
+  if ( defined($opt_can_changepass) || defined($opt_must_changepass) || defined($opt_home_path) || defined($opt_home_drive) || defined($opt_logon_script) || defined($opt_profile_path) || defined($opt_flag) ) {
+	pod2usage({-verbose => 1, -message => "$myprogname:  This options are valid only for [--win-user|-a] \n",-exitval => 1,-output => \*STDERR}) ;
+  }
+}
+if  (!$ok || @ARGV <1 )  {
+  show_usage(1);
+}
 
 # cause problems when dealing with getpwuid because of the
 # negative ttl and ldap modification
@@ -76,7 +126,6 @@
 
 
 # Read options
-my $userUidNumber = $Options{'u'};
 if (!defined($userUidNumber)) { 
   # find first unused uid starting from $config{UID_START}
   while (defined(getpwuid($config{UID_START}))) {
@@ -93,30 +142,18 @@
 
 
 my $createGroup = 0;
-my $userGidNumber = $Options{'g'};
 # gid not specified ? 
 if (!defined($userGidNumber)) {
   # windows machine => $config{defaultComputerGid}
-  if (defined($Options{'w'})) {
+  if (defined($opt_win_workstation) || defined($opt_interdomain) || defined($opt_win_workstation_posix )) {
 	$userGidNumber = $config{defaultComputerGid};
-	#    } elsif (!defined($Options{'n'})) {
-	# create new group (redhat style)
-	# find first unused gid starting from $config{GID_START}
-	#	while (defined(getgrgid($config{GID_START}))) {
-	#		$config{GID_START}++;
-	#	}
-	#	$userGidNumber = $config{GID_START};
-
-	#	$createGroup = 1;
-
   } else {
-	# user will have gid = $config{defaultUserGid}
 	$userGidNumber = $config{defaultUserGid};
   }
 } else {
   my $gid;
   if (($gid = parse_group($userGidNumber)) < 0) {
-	print "$0: unknown group $userGidNumber\n";
+	print "$myprogname: unknown group $userGidNumber\n";
 	exit (6);
   }
   $userGidNumber = $gid;
@@ -129,17 +166,17 @@
 if ($userName =~ /^([\w -.]+\$?)$/) {
   $userName = $1;
 } else {
-  print "$0: illegal username\n";
+  print "$myprogname: 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";
+  print "$myprogname: user $userName exists\n";
   exit (9);
 } elsif (!$rc) {
-  print "$0: error in get_user_dn2\n";
+  print "$myprogname: error in get_user_dn2\n";
   exit(10);
 }
 
@@ -147,55 +184,71 @@
 my $userGroupSID;
 my $userRid;
 my $user_sid;
-if (defined $Options{'a'} or defined $Options{'i'}) {
+if (defined($opt_win_user) || defined($opt_interdomain) || defined($opt_win_workstation)) {
 	# 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 "Error: SID not set for unix group $userGidNumber\n";
+	  print "$myprogname: 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
-	$user_sid="$config{SID}-$userRid";
-        my $test_exist_sid=does_sid_exist($user_sid,$config{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);
-        }
+	if (defined($userRidNumber)) {
+		my $user_sid = $config{SID}.'-'.$userRidNumber;
+
+    	my $test_exist_sid_userdn=does_sid_exist($user_sid,$config{usersdn});
+		if ($test_exist_sid_userdn->count == 1) { 
+			print "rid already exist, select another rid! \n";
+			exit 6;
+		}
+    	if ($config{computersdn} ne $config{usersdn}) {
+    		my $test_exist_sid_computersdn=does_sid_exist($user_sid,$config{computersdn});
+    		if ($test_exist_sid_computersdn->count == 1) {
+				print "rid already exist, select another rid! \n";
+				exit 6;
+       	 	}
+  		}
+		$userRid = $userRidNumber;
+	}else{
+		# as rid we use 2 * uid + 1000
+		$userRid = 2 * $userUidNumber + 1000;
+   	     # let's test if this SID already exist
+		$user_sid="$config{SID}-$userRid";
+   		 my $test_exist_sid_userdn=does_sid_exist($user_sid,$config{usersdn});
+   		 while ($test_exist_sid_userdn->count == 1) {
+				$userRid++;
+				$user_sid="$config{SID}-$userRid";
+                $test_exist_sid_userdn=does_sid_exist($user_sid,$config{usersdn});
+   	     }
+  		if ($config{computersdn} ne $config{usersdn}) {
+   		 my $test_exist_sid_computersdn=does_sid_exist($user_sid,$config{computersdn});
+   			 while ($test_exist_sid_computersdn->count == 1) {
+				$userRid++;
+				$user_sid="$config{SID}-$userRid";
+                $test_exist_sid_computersdn=does_sid_exist($user_sid,$config{computersdn});
+   	     	}
+ 		}
+ 	}
 }
 
-my $userHomeDirectory;
-my ($userCN, $userSN);
 my $tmp;
-if (!defined($userHomeDirectory = $Options{'d'})) {
+if (!defined($userHomeDirectory)) {
   $userHomeDirectory = $config{userHomePrefix}."/".$userName;
 }
-$config{userLoginShell} = $tmp if (defined($tmp = $Options{'s'}));
-$config{userGecos} = $tmp if (defined($tmp = $Options{'c'}));
-$config{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'}));
-
+$config{userLoginShell} = $tmp if (defined($tmp = $userLoginShell));
+$config{userGecos} = $tmp if (defined($tmp = $userGecos));
+$config{skeletonDir} = $tmp if (defined($tmp = $skeletonDir));
+$userCN = ($userCN || $userGecos || $userName);
+$userSN = ($userSN || $userName);
 
 ########################
 
 my $ldap_master=connect_ldap_master();
 
 # MACHINE ACCOUNT
-if (defined($Options{'w'}) or defined($Options{'i'})) {
+if (defined($opt_win_workstation) || defined($opt_interdomain) || defined($opt_win_workstation_posix)) {
    
   # add a trailing dollar if missing
   if ($userName =~ /[^\$]$/s) {
@@ -208,7 +261,32 @@
 	die "$0: error while adding posix account\n";
   }
 
-  if (defined($Options{'i'})) {
+  if (defined($opt_win_workstation)) {
+	if (!add_samba_machine($userName)) {
+		  die "$myprogname: error while adding samba account\n";
+		}
+	my $modify = $ldap_master->modify ( "uid=$userName,$config{computersdn}",
+				changes => [
+				
+				replace => [sambaAcctFlags => '[W          ]'],
+
+				replace => [sambaPwdLastSet => '0'],
+
+				replace => [sambaLogonTime => '0'],
+
+                replace => [sambaLogoffTime => '2147483647'],
+
+                replace => [sambaKickoffTime => '2147483647'],
+                
+				replace => [sambaPwdCanChange => '0'],
+
+                replace => [sambaPwdMustChange => '2147483647'],
+
+				]
+				  );
+	$modify->code && die "failed to modify entry: ", $modify->error ;
+  	
+  } elsif (defined($opt_interdomain)) {
 	# For machine trust account
 	# Objectclass sambaSAMAccount must be added now !
         if ($config{mk_ntpasswd} eq '') {
@@ -241,21 +319,21 @@
         chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
 
         my $modify = $ldap_master->modify ( "uid=$userName,$config{computersdn}",
-                                                                                changes => [
-                                                                                                        replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSAMAccount']],
-                                                                                                        add => [sambaPwdLastSet => '0'],
+				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 => [sambaPwdMustChange => '2147483647'],
                                                                                                         add => [sambaAcctFlags => '[I          ]'],
                                                                                                         add => [sambaLMPassword => "$lmpassword"],
                                                                                                         add => [sambaNTPassword => "$ntpassword"],
-                                                                                                        add => [sambaSID => "$user_sid"],
-                                                                                                        add => [sambaPrimaryGroupSID => "$config{SID}-553"]
+                                                                                                        add => [sambaSID => "$user_sid"]
                                                                                                    ]
-                                                                          );
+               );
 
         $modify->code && die "failed to add entry: ", $modify->error ;
   }
@@ -269,7 +347,7 @@
 
 my $add = $ldap_master->add ("uid=$userName,$config{usersdn}",
 							 attr => [
-									  'objectclass' => ['top','inetOrgPerson','posixAccount','shadowAccount'],
+									  'objectclass' => ['top','inetOrgPerson','posixAccount'],
 									  'cn'   => "$userCN",
 									  'sn'   => "$userSN",
 									  'uid'   => "$userName",
@@ -283,7 +361,7 @@
 									 ]
 							);
 
-$add->code && warn "failed to add entry: ", $add->error ;
+$add->code && die "failed to add entry: ", $add->error ;
 
 
 #if ($createGroup) {
@@ -292,14 +370,13 @@
 
 group_add_user($userGidNumber, $userName);
 
-my $grouplist;
 # adds to supplementary groups
-if (defined($grouplist = $Options{'G'})) {
+if (defined($grouplist) ){
   add_grouplist_user($grouplist, $userName);
 }
 
 # If user was created successfully then we should create his/her home dir
-if (defined($tmp = $Options{'m'})) {
+if (defined($tmp = $opt_makehome) ){
   unless ( $userName =~ /\$$/ ) {
     if ( !(-e $userHomeDirectory) ) {
 	  system "mkdir $userHomeDirectory 2>/dev/null";
@@ -312,16 +389,16 @@
 
 
 # Add Samba user infos
-if (defined($Options{'a'})) {
+if (defined($opt_win_user)) {
   if (!$config{with_smbpasswd}) {
 
 	my $winmagic = 2147483647;
 	my $valpwdcanchange = 0;
 	my $valpwdmustchange = $winmagic;
 	my $valpwdlastset = 0;
-	my $valacctflags = "[UX]";
+	my $valacctflags = "[UX         ]";
 
-	if (defined($tmp = $Options{'A'})) {
+	if (defined($tmp = $opt_can_changepass)) {
 	  if ($tmp != 0) {
 		$valpwdcanchange = "0";
 	  } else {
@@ -329,27 +406,27 @@
 	  }
 	}
 
-	if (defined($tmp = $Options{'B'})) {
+	if (defined($tmp = $opt_must_changepass)) {
 	  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]";
+		$valacctflags = "[U          ]";
 	  } else {
 		$valpwdmustchange = "$winmagic";
 	  }
 	}
 
-	if (defined($tmp = $Options{'H'})) {
-	  $valacctflags = "$tmp";
+	if (defined($tmp = $opt_flag)) {
+	  $valacctflags = "[$tmp]";
 	}
 
 
 	my $modify = $ldap_master->modify ( "uid=$userName,$config{usersdn}",
 										changes => [
-													add => [objectClass => 'sambaSAMAccount'],
+													add => [objectClass => 'sambaSamAccount'],
 													add => [sambaPwdLastSet => "$valpwdlastset"],
 													add => [sambaLogonTime => '0'],
 													add => [sambaLogoffTime => '2147483647'],
@@ -374,7 +451,7 @@
     ;
 	close FILE;
 	if ($?) {
-	  print "$0: error adding samba account\n";
+	  print "$myprogname: error adding samba account\n";
 	  exit (10);
 	}
   }								# with_smbpasswd
@@ -386,7 +463,7 @@
   } else {
         $valscriptpath = "$userName.cmd";
   }
-  if (defined($tmp = $Options{'E'})) {
+  if (defined($tmp = $opt_logon_script)) {
     $valscriptpath = "$tmp";
   }
 
@@ -394,7 +471,7 @@
   if (defined $config{userSmbHome}) {
        $valsmbhome = "$config{userSmbHome}";
   }
-  if (defined($tmp = $Options{'C'})) {
+  if (defined($opt_home_path)) {
     $valsmbhome = "$tmp";
   }
   if (defined $valsmbhome and $valsmbhome ne "") {
@@ -402,7 +479,7 @@
   }
 
   my $valhomedrive = "$config{userHomeDrive}";
-  if (defined($tmp = $Options{'D'})) {
+  if (defined($tmp = $opt_home_drive)) {
     $tmp = $tmp.":" unless ($tmp =~ /:/);
     $valhomedrive = "$tmp";
   }
@@ -412,7 +489,7 @@
        $valprofilepath = "$config{userProfile}$userName";
   }
 
-  if (defined($tmp = $Options{'F'})) {
+  if (defined($tmp = $opt_profile_path)) {
     $valprofilepath = "$tmp";
   }
   if (defined $valprofilepath and $valprofilepath ne "") {
@@ -439,12 +516,51 @@
 $ldap_master->unbind;			# take down session
 
 
-if (defined($Options{'P'})) {
+if (defined($opt_password)) {
   exec "$RealBin/smbldap-passwd $userName"
 }
 
 exit 0;
 
+sub show_usage ($) {
+  my $rc=shift @_;
+  print STDERR <<EOF;
+Usage: $myprogname [-awWimugdsckGPABCDEFH?] username
+ {-a|--win-user}        is a Windows User (otherwise, Posix stuff only)
+ {-w|--win-workstation} is a Windows Workstation (otherwise, Posix stuff only)
+ {-W|--win-workstation_posix} is a Windows Workstation,  Posix stuff only
+ {-i|--win-interdomain} is a Windows interdomain trust account 
+                        (otherwise, Posix stuff only)
+ {-u|--uid}             uid
+ {-g|--gid}             gid
+ {-G|--supplementary-group} supplementary comma-separated groups
+ {-d|--home}            home
+ {-s|--shell}           shell
+ {-c|--gecos}           gecos
+ {-m|--make-home}       creates home directory and copies /etc/skel
+ {-k|--skeleton-dir}    skeleton dir (with -m)
+ {-P|--password}        ends by invoking smbldap-passwd.pl
+ {-A|--can-change-pass} can change password ? 0 if no, 1 if yes
+ {-B|--must-change-pass} must change password ? 0 if no, 1 if yes
+ {-C|--smb-home-path}   sambaHomePath 
+                        (SMB home share, like '\\\\PDC-SRV\\homes')
+ {-D|--smb-home-drive}  sambaHomeDrive 
+                        (letter associated with home share, like 'H:')
+ {-E|--smb-logon-script} sambaLogonScript 
+                        (DOS script to execute on login)
+ {-F|--smb-profile-path} sambaProfilePath 
+                        (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+ {-H|--smb-flag}        sambaAcctFlags 
+                        (samba account control bits like '[NDHTUMWSLKI]')
+ {-N|--cname}           canonical name
+ {-S|--surname}         surname
+ {-?|--help}            show this help message
+ {--man}                print the man page
+EOF
+ exit ($rc);
+}
+
+
 ########################################
 
 =head1 NAME


More information about the samba-technical mailing list