nsswrapper: implement group_del() in nss_wrapper.pl.
[Samba.git] / lib / nss_wrapper / nss_wrapper.pl
blobcfd3206c2ae759e3aa6376136afbd76ff86a020e
1 #!/usr/bin/perl
4 use strict;
6 use Getopt::Long;
7 use Cwd qw(abs_path);
9 my $opt_help = 0;
10 my $opt_path = undef;
11 my $opt_action = undef;
12 my $opt_type = undef;
13 my $opt_name = undef;
15 my $passwdfn = undef;
16 my $groupfn = undef;
17 my $actionfn = undef;
19 sub passwd_add($$);
20 sub passwd_delete($$);
21 sub group_add($$);
22 sub group_delete($$);
24 my $result = GetOptions(
25 'help|h|?' => \$opt_help,
26 'path=s' => \$opt_path,
27 'action=s' => \$opt_action,
28 'type=s' => \$opt_type,
29 'name=s' => \$opt_name
32 sub usage($;$)
34 my ($ret, $msg) = @_;
36 print $msg."\n\n" if defined($msg);
38 print "usage:
40 --help|-h|-? Show this help.
42 --path <path> Path of the 'passwd' or 'group' file.
44 --type <type> Only 'passwd' and 'group' are supported yet,
45 maybe 'member' will be added in future.
47 --action <action> 'add' or 'delete'.
49 --name <name> The name of the object.
51 exit($ret);
54 usage(1) if (not $result);
56 usage(0) if ($opt_help);
58 if (not defined($opt_path)) {
59 usage(1, "missing: --path <path>");
61 if ($opt_path eq "" or $opt_path eq "/") {
62 usage(1, "invalid: --path <path>: '$opt_path'");
64 my $opt_fullpath = abs_path($opt_path);
65 if (not defined($opt_fullpath)) {
66 usage(1, "invalid: --path <path>: '$opt_path'");
70 if (not defined($opt_action)) {
71 usage(1, "missing: --action [add|delete]");
73 if ($opt_action eq "add") {
74 $passwdfn = \&passwd_add;
75 $groupfn = \&group_add;
76 } elsif ($opt_action eq "delete") {
77 $passwdfn = \&passwd_delete;
78 $groupfn = \&group_delete;
79 } else {
80 usage(1, "invalid: --action [add|delete]: '$opt_action'");
83 if (not defined($opt_type)) {
84 usage(1, "missing: --type [passwd|group]");
86 if ($opt_type eq "passwd") {
87 $actionfn = $passwdfn;
88 } elsif ($opt_type eq "group") {
89 $actionfn = $groupfn;
90 } else {
91 usage(1, "invalid: --type [passwd|group]: '$opt_type'")
94 if (not defined($opt_name)) {
95 usage(1, "missing: --name <name>");
97 if ($opt_name eq "") {
98 usage(1, "invalid: --name <name>");
101 exit $actionfn->($opt_fullpath, $opt_name);
103 sub passwd_add_entry($$);
105 sub passwd_load($)
107 my ($path) = @_;
108 my @lines;
109 my $passwd = undef;
111 open(PWD, "<$path") or die("Unable to open '$path' for read");
112 @lines = <PWD>;
113 close(PWD);
115 $passwd->{array} = ();
116 $passwd->{name} = {};
117 $passwd->{uid} = {};
118 $passwd->{path} = $path;
120 foreach my $line (@lines) {
121 passwd_add_entry($passwd, $line);
124 return $passwd;
127 sub group_add_entry($$);
129 sub group_load($)
131 my ($path) = @_;
132 my @lines;
133 my $group = undef;
135 open(GROUP, "<$path") or die("Unable to open '$path' for read");
136 @lines = <GROUP>;
137 close(GROUP);
139 $group->{array} = ();
140 $group->{name} = {};
141 $group->{gid} = {};
142 $group->{path} = $path;
144 foreach my $line (@lines) {
145 group_add_entry($group, $line);
148 return $group;
151 sub passwd_lookup_name($$)
153 my ($passwd, $name) = @_;
155 return undef unless defined($passwd->{name}{$name});
157 return $passwd->{name}{$name};
160 sub group_lookup_name($$)
162 my ($group, $name) = @_;
164 return undef unless defined($group->{name}{$name});
166 return $group->{name}{$name};
169 sub passwd_lookup_uid($$)
171 my ($passwd, $uid) = @_;
173 return undef unless defined($passwd->{uid}{$uid});
175 return $passwd->{uid}{$uid};
178 sub group_lookup_gid($$)
180 my ($group, $gid) = @_;
182 return undef unless defined($group->{gid}{$gid});
184 return $group->{gid}{$gid};
187 sub passwd_get_free_uid($)
189 my ($passwd) = @_;
190 my $uid = 1000;
192 while (passwd_lookup_uid($passwd, $uid)) {
193 $uid++;
196 return $uid;
199 sub group_get_free_gid($)
201 my ($group) = @_;
202 my $gid = 1000;
204 while (group_lookup_gid($group, $gid)) {
205 $gid++;
208 return $gid;
211 sub passwd_add_entry($$)
213 my ($passwd, $str) = @_;
215 chomp $str;
216 my @e = split(':', $str);
218 push(@{$passwd->{array}}, \@e);
219 $passwd->{name}{$e[0]} = \@e;
220 $passwd->{uid}{$e[2]} = \@e;
223 sub group_add_entry($$)
225 my ($group, $str) = @_;
227 chomp $str;
228 my @e = split(':', $str);
230 push(@{$group->{array}}, \@e);
231 $group->{name}{$e[0]} = \@e;
232 $group->{gid}{$e[2]} = \@e;
235 sub passwd_remove_entry($$)
237 my ($passwd, $eref) = @_;
239 for (my $i = 0; defined($passwd->{array}[$i]); $i++) {
240 if ($eref == $passwd->{array}[$i]) {
241 $passwd->{array}[$i] = undef;
245 delete $passwd->{name}{${$eref}[0]};
246 delete $passwd->{uid}{${$eref}[2]};
249 sub group_remove_entry($$)
251 my ($group, $eref) = @_;
253 for (my $i = 0; defined($group->{array}[$i]); $i++) {
254 if ($eref == $group->{array}[$i]) {
255 $group->{array}[$i] = undef;
259 delete $group->{name}{${$eref}[0]};
260 delete $group->{gid}{${$eref}[2]};
263 sub passwd_save($)
265 my ($passwd) = @_;
266 my @lines = ();
267 my $path = $passwd->{path};
268 my $tmppath = $path.$$;
270 foreach my $eref (@{$passwd->{array}}) {
271 next unless defined($eref);
273 my $line = join(':', @{$eref});
274 push(@lines, $line);
277 open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write");
278 print PWD join("\n", @lines)."\n";
279 close(PWD);
280 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
283 sub group_save($)
285 my ($group) = @_;
286 my @lines = ();
287 my $path = $group->{path};
288 my $tmppath = $path.$$;
290 foreach my $eref (@{$group->{array}}) {
291 next unless defined($eref);
293 my $line = join(':', @{$eref});
294 if (scalar(@{$eref}) == 3) {
295 $line .= ":";
297 push(@lines, $line);
300 open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write");
301 print GROUP join("\n", @lines)."\n";
302 close(GROUP);
303 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
306 sub passwd_add($$)
308 my ($path, $name) = @_;
310 #print "passwd_add: '$name' in '$path'\n";
312 my $passwd = passwd_load($path);
314 my $e = passwd_lookup_name($passwd, $name);
315 die("account[$name] already exists in '$path'") if defined($e);
317 my $uid = passwd_get_free_uid($passwd);
318 my $gid = 65534;# nogroup gid
320 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
322 passwd_add_entry($passwd, $pwent);
324 passwd_save($passwd);
326 return 0;
329 sub passwd_delete($$)
331 my ($path, $name) = @_;
333 #print "passwd_delete: '$name' in '$path'\n";
335 my $passwd = passwd_load($path);
337 my $e = passwd_lookup_name($passwd, $name);
338 die("account[$name] does not exists in '$path'") unless defined($e);
340 passwd_remove_entry($passwd, $e);
342 passwd_save($passwd);
344 return 0;
347 sub group_add($$)
349 my ($path, $name) = @_;
351 #print "group_add: '$name' in '$path'\n";
353 my $group = group_load($path);
355 my $e = group_lookup_name($group, $name);
356 die("group[$name] already exists in '$path'") if defined($e);
358 my $gid = group_get_free_gid($group);
360 my $gwent = $name.":x:".$gid.":".""; #no members yet
362 group_add_entry($group, $gwent);
364 group_save($group);
366 #printf("%d\n", $gid);
368 return 0;
371 sub group_delete($$)
373 my ($path, $name) = @_;
375 #print "group_delete: '$name' in '$path'\n";
377 my $group = group_load($path);
379 my $e = group_lookup_name($group, $name);
380 die("group[$name] does not exists in '$path'") unless defined($e);
382 group_remove_entry($group, $e);
384 group_save($group);
386 return 0;