10 my $opt_passwd_path = undef;
11 my $opt_group_path = undef;
12 my $opt_action = undef;
15 my $opt_member = undef;
23 sub passwd_delete
($$$$);
25 sub group_delete
($$$$);
27 sub member_delete
($$$$);
31 my $result = GetOptions
(
32 'help|h|?' => \
$opt_help,
33 'passwd_path=s' => \
$opt_passwd_path,
34 'group_path=s' => \
$opt_group_path,
35 'action=s' => \
$opt_action,
36 'type=s' => \
$opt_type,
37 'name=s' => \
$opt_name,
38 'member=s' => \
$opt_member
45 print $msg."\n\n" if defined($msg);
49 --help|-h|-? Show this help.
51 --passwd_path <path> Path of the 'passwd' file.
52 --group_path <path> Path of the 'group' file.
54 --type <type> 'passwd', 'group' and 'member' are supported.
56 --action <action> 'add' or 'delete'.
58 --name <name> The name of the object.
60 --member <member> The name of the member.
65 usage
(1) if (not $result);
67 usage
(0) if ($opt_help);
69 if (not defined($opt_action)) {
70 usage
(1, "missing: --action [add|delete]");
72 if ($opt_action eq "add") {
73 $passwdfn = \
&passwd_add
;
74 $groupfn = \
&group_add
;
75 $memberfn = \
&member_add
;
76 } elsif ($opt_action eq "delete") {
77 $passwdfn = \
&passwd_delete
;
78 $groupfn = \
&group_delete
;
79 $memberfn = \
&member_delete
;
81 usage
(1, "invalid: --action [add|delete]: '$opt_action'");
84 if (not defined($opt_type)) {
85 usage
(1, "missing: --type [passwd|group|member]");
87 if ($opt_type eq "member" and not defined($opt_member)) {
88 usage
(1, "missing: --member <member>");
90 my $opt_fullpath_passwd;
91 my $opt_fullpath_group;
92 if ($opt_type eq "passwd") {
93 $actionfn = $passwdfn;
94 $opt_fullpath_passwd = check_path
($opt_passwd_path, $opt_type);
95 } elsif ($opt_type eq "group") {
97 $opt_fullpath_group = check_path
($opt_group_path, $opt_type);
98 } elsif ($opt_type eq "member") {
99 $actionfn = $memberfn;
100 $opt_fullpath_passwd = check_path
($opt_passwd_path, "passwd");
101 $opt_fullpath_group = check_path
($opt_group_path, "group");
103 usage
(1, "invalid: --type [passwd|group]: '$opt_type'")
106 if (not defined($opt_name)) {
107 usage
(1, "missing: --name <name>");
109 if ($opt_name eq "") {
110 usage
(1, "invalid: --name <name>");
113 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name);
117 my ($path,$type) = @_;
119 if (not defined($path)) {
120 usage
(1, "missing: --$type\_path <path>");
122 if ($path eq "" or $path eq "/") {
123 usage
(1, "invalid: --$type\_path <path>: '$path'");
125 my $fullpath = abs_path
($path);
126 if (not defined($fullpath)) {
127 usage
(1, "invalid: --$type\_path <path>: '$path'");
132 sub passwd_add_entry
($$);
140 open(PWD
, "<$path") or die("Unable to open '$path' for read");
144 $passwd->{array
} = ();
145 $passwd->{name
} = {};
147 $passwd->{path
} = $path;
149 foreach my $line (@lines) {
150 passwd_add_entry
($passwd, $line);
156 sub group_add_entry
($$);
164 open(GROUP
, "<$path") or die("Unable to open '$path' for read");
168 $group->{array
} = ();
171 $group->{path
} = $path;
173 foreach my $line (@lines) {
174 group_add_entry
($group, $line);
180 sub passwd_lookup_name
($$)
182 my ($passwd, $name) = @_;
184 return undef unless defined($passwd->{name
}{$name});
186 return $passwd->{name
}{$name};
189 sub group_lookup_name
($$)
191 my ($group, $name) = @_;
193 return undef unless defined($group->{name
}{$name});
195 return $group->{name
}{$name};
198 sub passwd_lookup_uid
($$)
200 my ($passwd, $uid) = @_;
202 return undef unless defined($passwd->{uid
}{$uid});
204 return $passwd->{uid
}{$uid};
207 sub group_lookup_gid
($$)
209 my ($group, $gid) = @_;
211 return undef unless defined($group->{gid
}{$gid});
213 return $group->{gid
}{$gid};
216 sub passwd_get_free_uid
($)
221 while (passwd_lookup_uid
($passwd, $uid)) {
228 sub group_get_free_gid
($)
233 while (group_lookup_gid
($group, $gid)) {
240 sub passwd_add_entry
($$)
242 my ($passwd, $str) = @_;
245 my @e = split(':', $str);
247 push(@
{$passwd->{array
}}, \
@e);
248 $passwd->{name
}{$e[0]} = \
@e;
249 $passwd->{uid
}{$e[2]} = \
@e;
252 sub group_add_entry
($$)
254 my ($group, $str) = @_;
257 my @e = split(':', $str);
259 push(@
{$group->{array
}}, \
@e);
260 $group->{name
}{$e[0]} = \
@e;
261 $group->{gid
}{$e[2]} = \
@e;
264 sub passwd_remove_entry
($$)
266 my ($passwd, $eref) = @_;
268 for (my $i = 0; defined($passwd->{array
}[$i]); $i++) {
269 if ($eref == $passwd->{array
}[$i]) {
270 $passwd->{array
}[$i] = undef;
274 delete $passwd->{name
}{${$eref}[0]};
275 delete $passwd->{uid
}{${$eref}[2]};
278 sub group_remove_entry
($$)
280 my ($group, $eref) = @_;
282 for (my $i = 0; defined($group->{array
}[$i]); $i++) {
283 if ($eref == $group->{array
}[$i]) {
284 $group->{array
}[$i] = undef;
288 delete $group->{name
}{${$eref}[0]};
289 delete $group->{gid
}{${$eref}[2]};
292 sub group_add_member
($$$)
294 my ($group, $eref, $username) = @_;
297 my $str = @
$eref[3] || undef;
299 @members = split(",", $str);
302 foreach my $member (@members) {
303 if ($member and $member eq $username) {
304 die("account[$username] is already member of '@$eref[0]'");
308 push(@members, $username);
310 my $gwent = @
$eref[0].":x:".@
$eref[2].":".join(",", @members);
312 group_remove_entry
($group, $eref);
314 group_add_entry
($group, $gwent);
317 sub group_delete_member
($$$)
319 my ($group, $eref, $username) = @_;
322 my $str = @
$eref[3] || undef;
324 @members = split(",", $str);
329 foreach my $member (@members) {
330 if ($member and $member ne $username) {
331 push(@new_members, $member);
338 die("account[$username] is not member of '@$eref[0]'");
341 my $gwent = @
$eref[0].":x:".@
$eref[2].":".join(",", @new_members);
343 group_remove_entry
($group, $eref);
345 group_add_entry
($group, $gwent);
352 my $path = $passwd->{path
};
353 my $tmppath = $path.$$;
355 foreach my $eref (@
{$passwd->{array
}}) {
356 next unless defined($eref);
358 my $line = join(':', @
{$eref});
362 open(PWD
, ">$tmppath") or die("Unable to open '$tmppath' for write");
363 print PWD
join("\n", @lines)."\n";
365 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
372 my $path = $group->{path
};
373 my $tmppath = $path.$$;
375 foreach my $eref (@
{$group->{array
}}) {
376 next unless defined($eref);
378 my $line = join(':', @
{$eref});
379 if (scalar(@
{$eref}) == 3) {
385 open(GROUP
, ">$tmppath") or die("Unable to open '$tmppath' for write");
386 print GROUP
join("\n", @lines)."\n";
388 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
393 my ($path, $dummy, $dummy2, $name) = @_;
395 #print "passwd_add: '$name' in '$path'\n";
397 my $passwd = passwd_load
($path);
399 my $e = passwd_lookup_name
($passwd, $name);
400 die("account[$name] already exists in '$path'") if defined($e);
402 my $uid = passwd_get_free_uid
($passwd);
403 my $gid = 65534;# nogroup gid
405 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
407 passwd_add_entry
($passwd, $pwent);
409 passwd_save
($passwd);
414 sub passwd_delete
($$$$)
416 my ($path, $dummy, $dummy2, $name) = @_;
418 #print "passwd_delete: '$name' in '$path'\n";
420 my $passwd = passwd_load
($path);
422 my $e = passwd_lookup_name
($passwd, $name);
423 die("account[$name] does not exists in '$path'") unless defined($e);
425 passwd_remove_entry
($passwd, $e);
427 passwd_save
($passwd);
434 my ($dummy, $dummy2, $path, $name) = @_;
436 #print "group_add: '$name' in '$path'\n";
438 my $group = group_load
($path);
440 my $e = group_lookup_name
($group, $name);
441 die("group[$name] already exists in '$path'") if defined($e);
443 my $gid = group_get_free_gid
($group);
445 my $gwent = $name.":x:".$gid.":"."";
447 group_add_entry
($group, $gwent);
451 #printf("%d\n", $gid);
456 sub group_delete
($$$$)
458 my ($dummy, $dummy2, $path, $name) = @_;
460 #print "group_delete: '$name' in '$path'\n";
462 my $group = group_load
($path);
464 my $e = group_lookup_name
($group, $name);
465 die("group[$name] does not exists in '$path'") unless defined($e);
467 group_remove_entry
($group, $e);
476 my ($passwd_path, $username, $group_path, $groupname) = @_;
478 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
480 my $group = group_load
($group_path);
482 my $g = group_lookup_name
($group, $groupname);
483 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
485 my $passwd = passwd_load
($passwd_path);
487 my $u = passwd_lookup_name
($passwd, $username);
488 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
490 group_add_member
($group, $g, $username);
497 sub member_delete
($$$$)
499 my ($passwd_path, $username, $group_path, $groupname) = @_;
501 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
503 my $group = group_load
($group_path);
505 my $g = group_lookup_name
($group, $groupname);
506 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
508 my $passwd = passwd_load
($passwd_path);
510 my $u = passwd_lookup_name
($passwd, $username);
511 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
513 group_delete_member
($group, $g, $username);