10 my $opt_passwd_path = undef;
11 my $opt_group_path = undef;
12 my $opt_action = undef;
21 sub passwd_delete($$);
25 my $result = GetOptions(
26 'help|h|?' => \$opt_help,
27 'passwd_path=s' => \$opt_passwd_path,
28 'group_path=s' => \$opt_group_path,
29 'action=s' => \$opt_action,
30 'type=s' => \$opt_type,
31 'name=s' => \$opt_name
38 print $msg."\n\n" if defined($msg);
42 --help|-h|-? Show this help.
44 --passwd_path <path> Path of the 'passwd' file.
45 --group_path <path> Path of the 'group' file.
47 --type <type> Only 'passwd' and 'group' are supported yet,
48 maybe 'member' will be added in future.
50 --action <action> 'add' or 'delete'.
52 --name <name> The name of the object.
57 usage(1) if (not $result);
59 usage(0) if ($opt_help);
61 if (not defined($opt_action)) {
62 usage(1, "missing: --action [add|delete]");
64 if ($opt_action eq "add") {
65 $passwdfn = \&passwd_add;
66 $groupfn = \&group_add;
67 } elsif ($opt_action eq "delete") {
68 $passwdfn = \&passwd_delete;
69 $groupfn = \&group_delete;
71 usage(1, "invalid: --action [add|delete]: '$opt_action'");
74 if (not defined($opt_type)) {
75 usage(1, "missing: --type [passwd|group]");
78 if ($opt_type eq "passwd") {
79 $actionfn = $passwdfn;
80 $opt_fullpath = check_path($opt_passwd_path, $opt_type);
81 } elsif ($opt_type eq "group") {
83 $opt_fullpath = check_path($opt_group_path, $opt_type);
85 usage(1, "invalid: --type [passwd|group]: '$opt_type'")
88 if (not defined($opt_name)) {
89 usage(1, "missing: --name <name>");
91 if ($opt_name eq "") {
92 usage(1, "invalid: --name <name>");
95 exit $actionfn->($opt_fullpath, $opt_name);
99 my ($path,$type) = @_;
101 if (not defined($path)) {
102 usage(1, "missing: --$type\_path <path>");
104 if ($path eq "" or $path eq "/") {
105 usage(1, "invalid: --$type\_path <path>: '$path'");
107 my $fullpath = abs_path($path);
108 if (not defined($fullpath)) {
109 usage(1, "invalid: --$type\_path <path>: '$path'");
114 sub passwd_add_entry($$);
122 open(PWD, "<$path") or die("Unable to open '$path' for read");
126 $passwd->{array} = ();
127 $passwd->{name} = {};
129 $passwd->{path} = $path;
131 foreach my $line (@lines) {
132 passwd_add_entry($passwd, $line);
138 sub group_add_entry($$);
146 open(GROUP, "<$path") or die("Unable to open '$path' for read");
150 $group->{array} = ();
153 $group->{path} = $path;
155 foreach my $line (@lines) {
156 group_add_entry($group, $line);
162 sub passwd_lookup_name($$)
164 my ($passwd, $name) = @_;
166 return undef unless defined($passwd->{name}{$name});
168 return $passwd->{name}{$name};
171 sub group_lookup_name($$)
173 my ($group, $name) = @_;
175 return undef unless defined($group->{name}{$name});
177 return $group->{name}{$name};
180 sub passwd_lookup_uid($$)
182 my ($passwd, $uid) = @_;
184 return undef unless defined($passwd->{uid}{$uid});
186 return $passwd->{uid}{$uid};
189 sub group_lookup_gid($$)
191 my ($group, $gid) = @_;
193 return undef unless defined($group->{gid}{$gid});
195 return $group->{gid}{$gid};
198 sub passwd_get_free_uid($)
203 while (passwd_lookup_uid($passwd, $uid)) {
210 sub group_get_free_gid($)
215 while (group_lookup_gid($group, $gid)) {
222 sub passwd_add_entry($$)
224 my ($passwd, $str) = @_;
227 my @e = split(':', $str);
229 push(@{$passwd->{array}}, \@e);
230 $passwd->{name}{$e[0]} = \@e;
231 $passwd->{uid}{$e[2]} = \@e;
234 sub group_add_entry($$)
236 my ($group, $str) = @_;
239 my @e = split(':', $str);
241 push(@{$group->{array}}, \@e);
242 $group->{name}{$e[0]} = \@e;
243 $group->{gid}{$e[2]} = \@e;
246 sub passwd_remove_entry($$)
248 my ($passwd, $eref) = @_;
250 for (my $i = 0; defined($passwd->{array}[$i]); $i++) {
251 if ($eref == $passwd->{array}[$i]) {
252 $passwd->{array}[$i] = undef;
256 delete $passwd->{name}{${$eref}[0]};
257 delete $passwd->{uid}{${$eref}[2]};
260 sub group_remove_entry($$)
262 my ($group, $eref) = @_;
264 for (my $i = 0; defined($group->{array}[$i]); $i++) {
265 if ($eref == $group->{array}[$i]) {
266 $group->{array}[$i] = undef;
270 delete $group->{name}{${$eref}[0]};
271 delete $group->{gid}{${$eref}[2]};
278 my $path = $passwd->{path};
279 my $tmppath = $path.$$;
281 foreach my $eref (@{$passwd->{array}}) {
282 next unless defined($eref);
284 my $line = join(':', @{$eref});
288 open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write");
289 print PWD join("\n", @lines)."\n";
291 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
298 my $path = $group->{path};
299 my $tmppath = $path.$$;
301 foreach my $eref (@{$group->{array}}) {
302 next unless defined($eref);
304 my $line = join(':', @{$eref});
305 if (scalar(@{$eref}) == 3) {
311 open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write");
312 print GROUP join("\n", @lines)."\n";
314 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
319 my ($path, $name) = @_;
321 #print "passwd_add: '$name' in '$path'\n";
323 my $passwd = passwd_load($path);
325 my $e = passwd_lookup_name($passwd, $name);
326 die("account[$name] already exists in '$path'") if defined($e);
328 my $uid = passwd_get_free_uid($passwd);
329 my $gid = 65534;# nogroup gid
331 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
333 passwd_add_entry($passwd, $pwent);
335 passwd_save($passwd);
340 sub passwd_delete($$)
342 my ($path, $name) = @_;
344 #print "passwd_delete: '$name' in '$path'\n";
346 my $passwd = passwd_load($path);
348 my $e = passwd_lookup_name($passwd, $name);
349 die("account[$name] does not exists in '$path'") unless defined($e);
351 passwd_remove_entry($passwd, $e);
353 passwd_save($passwd);
360 my ($path, $name) = @_;
362 #print "group_add: '$name' in '$path'\n";
364 my $group = group_load($path);
366 my $e = group_lookup_name($group, $name);
367 die("group[$name] already exists in '$path'") if defined($e);
369 my $gid = group_get_free_gid($group);
371 my $gwent = $name.":x:".$gid.":".""; #no members yet
373 group_add_entry($group, $gwent);
377 #printf("%d\n", $gid);
384 my ($path, $name) = @_;
386 #print "group_delete: '$name' in '$path'\n";
388 my $group = group_load($path);
390 my $e = group_lookup_name($group, $name);
391 die("group[$name] does not exists in '$path'") unless defined($e);
393 group_remove_entry($group, $e);