10 my $opt_passwd_path = undef;
11 my $opt_group_path = undef;
12 my $opt_action = undef;
15 my $opt_member = undef;
16 my $opt_gid = 65534;# nogroup gid
23 sub passwd_add
($$$$$);
24 sub passwd_delete
($$$$$);
26 sub group_delete
($$$$$);
27 sub member_add
($$$$$);
28 sub member_delete
($$$$$);
32 my $result = GetOptions
(
33 'help|h|?' => \
$opt_help,
34 'passwd_path=s' => \
$opt_passwd_path,
35 'group_path=s' => \
$opt_group_path,
36 'action=s' => \
$opt_action,
37 'type=s' => \
$opt_type,
38 'name=s' => \
$opt_name,
39 'member=s' => \
$opt_member,
47 print $msg."\n\n" if defined($msg);
51 --help|-h|-? Show this help.
53 --passwd_path <path> Path of the 'passwd' file.
54 --group_path <path> Path of the 'group' file.
56 --type <type> 'passwd', 'group' and 'member' are supported.
58 --action <action> 'add' or 'delete'.
60 --name <name> The name of the object.
62 --member <member> The name of the member.
64 --gid <gid> Primary Group ID for new users.
69 usage
(1) if (not $result);
71 usage
(0) if ($opt_help);
73 if (not defined($opt_action)) {
74 usage
(1, "missing: --action [add|delete]");
76 if ($opt_action eq "add") {
77 $passwdfn = \
&passwd_add
;
78 $groupfn = \
&group_add
;
79 $memberfn = \
&member_add
;
80 } elsif ($opt_action eq "delete") {
81 $passwdfn = \
&passwd_delete
;
82 $groupfn = \
&group_delete
;
83 $memberfn = \
&member_delete
;
85 usage
(1, "invalid: --action [add|delete]: '$opt_action'");
88 if (not defined($opt_type)) {
89 usage
(1, "missing: --type [passwd|group|member]");
91 if ($opt_type eq "member" and not defined($opt_member)) {
92 usage
(1, "missing: --member <member>");
94 my $opt_fullpath_passwd;
95 my $opt_fullpath_group;
96 if ($opt_type eq "passwd") {
97 $actionfn = $passwdfn;
98 $opt_fullpath_passwd = check_path
($opt_passwd_path, $opt_type);
99 } elsif ($opt_type eq "group") {
100 $actionfn = $groupfn;
101 $opt_fullpath_group = check_path
($opt_group_path, $opt_type);
102 } elsif ($opt_type eq "member") {
103 $actionfn = $memberfn;
104 $opt_fullpath_passwd = check_path
($opt_passwd_path, "passwd");
105 $opt_fullpath_group = check_path
($opt_group_path, "group");
107 usage
(1, "invalid: --type [passwd|group]: '$opt_type'")
110 if (not defined($opt_name)) {
111 usage
(1, "missing: --name <name>");
113 if ($opt_name eq "") {
114 usage
(1, "invalid: --name <name>");
117 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid);
121 my ($path,$type) = @_;
123 if (not defined($path)) {
124 usage
(1, "missing: --$type\_path <path>");
126 if ($path eq "" or $path eq "/") {
127 usage
(1, "invalid: --$type\_path <path>: '$path'");
129 my $fullpath = abs_path
($path);
130 if (not defined($fullpath)) {
131 usage
(1, "invalid: --$type\_path <path>: '$path'");
136 sub passwd_add_entry
($$);
144 open(PWD
, "<$path") or die("Unable to open '$path' for read");
148 $passwd->{array
} = ();
149 $passwd->{name
} = {};
151 $passwd->{path
} = $path;
153 foreach my $line (@lines) {
154 passwd_add_entry
($passwd, $line);
160 sub group_add_entry
($$);
168 open(GROUP
, "<$path") or die("Unable to open '$path' for read");
172 $group->{array
} = ();
175 $group->{path
} = $path;
177 foreach my $line (@lines) {
178 group_add_entry
($group, $line);
184 sub passwd_lookup_name
($$)
186 my ($passwd, $name) = @_;
188 return undef unless defined($passwd->{name
}{$name});
190 return $passwd->{name
}{$name};
193 sub group_lookup_name
($$)
195 my ($group, $name) = @_;
197 return undef unless defined($group->{name
}{$name});
199 return $group->{name
}{$name};
202 sub passwd_lookup_uid
($$)
204 my ($passwd, $uid) = @_;
206 return undef unless defined($passwd->{uid
}{$uid});
208 return $passwd->{uid
}{$uid};
211 sub group_lookup_gid
($$)
213 my ($group, $gid) = @_;
215 return undef unless defined($group->{gid
}{$gid});
217 return $group->{gid
}{$gid};
220 sub passwd_get_free_uid
($)
225 while (passwd_lookup_uid
($passwd, $uid)) {
232 sub group_get_free_gid
($)
237 while (group_lookup_gid
($group, $gid)) {
244 sub passwd_add_entry
($$)
246 my ($passwd, $str) = @_;
249 my @e = split(':', $str);
251 push(@
{$passwd->{array
}}, \
@e);
252 $passwd->{name
}{$e[0]} = \
@e;
253 $passwd->{uid
}{$e[2]} = \
@e;
256 sub group_add_entry
($$)
258 my ($group, $str) = @_;
261 my @e = split(':', $str);
263 push(@
{$group->{array
}}, \
@e);
264 $group->{name
}{$e[0]} = \
@e;
265 $group->{gid
}{$e[2]} = \
@e;
268 sub passwd_remove_entry
($$)
270 my ($passwd, $eref) = @_;
272 for (my $i = 0; defined($passwd->{array
}[$i]); $i++) {
273 if ($eref == $passwd->{array
}[$i]) {
274 $passwd->{array
}[$i] = undef;
278 delete $passwd->{name
}{${$eref}[0]};
279 delete $passwd->{uid
}{${$eref}[2]};
282 sub group_remove_entry
($$)
284 my ($group, $eref) = @_;
286 for (my $i = 0; defined($group->{array
}[$i]); $i++) {
287 if ($eref == $group->{array
}[$i]) {
288 $group->{array
}[$i] = undef;
292 delete $group->{name
}{${$eref}[0]};
293 delete $group->{gid
}{${$eref}[2]};
296 sub group_add_member
($$$)
298 my ($group, $eref, $username) = @_;
301 my $str = @
$eref[3] || undef;
303 @members = split(",", $str);
306 foreach my $member (@members) {
307 if ($member and $member eq $username) {
308 die("account[$username] is already member of '@$eref[0]'");
312 push(@members, $username);
314 my $gwent = @
$eref[0].":x:".@
$eref[2].":".join(",", @members);
316 group_remove_entry
($group, $eref);
318 group_add_entry
($group, $gwent);
321 sub group_delete_member
($$$)
323 my ($group, $eref, $username) = @_;
326 my $str = @
$eref[3] || undef;
328 @members = split(",", $str);
333 foreach my $member (@members) {
334 if ($member and $member ne $username) {
335 push(@new_members, $member);
342 die("account[$username] is not member of '@$eref[0]'");
345 my $gwent = @
$eref[0].":x:".@
$eref[2].":".join(",", @new_members);
347 group_remove_entry
($group, $eref);
349 group_add_entry
($group, $gwent);
356 my $path = $passwd->{path
};
357 my $tmppath = $path.$$;
359 foreach my $eref (@
{$passwd->{array
}}) {
360 next unless defined($eref);
362 my $line = join(':', @
{$eref});
366 open(PWD
, ">$tmppath") or die("Unable to open '$tmppath' for write");
367 print PWD
join("\n", @lines)."\n";
369 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
376 my $path = $group->{path
};
377 my $tmppath = $path.$$;
379 foreach my $eref (@
{$group->{array
}}) {
380 next unless defined($eref);
382 my $line = join(':', @
{$eref});
383 if (scalar(@
{$eref}) == 3) {
389 open(GROUP
, ">$tmppath") or die("Unable to open '$tmppath' for write");
390 print GROUP
join("\n", @lines)."\n";
392 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
395 sub passwd_add
($$$$$)
397 my ($path, $dummy, $dummy2, $name, $gid) = @_;
399 #print "passwd_add: '$name' in '$path'\n";
401 my $passwd = passwd_load
($path);
403 my $e = passwd_lookup_name
($passwd, $name);
404 die("account[$name] already exists in '$path'") if defined($e);
406 my $uid = passwd_get_free_uid
($passwd);
408 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
410 passwd_add_entry
($passwd, $pwent);
412 passwd_save
($passwd);
417 sub passwd_delete
($$$$$)
419 my ($path, $dummy, $dummy2, $name, $dummy3) = @_;
421 #print "passwd_delete: '$name' in '$path'\n";
423 my $passwd = passwd_load
($path);
425 my $e = passwd_lookup_name
($passwd, $name);
426 die("account[$name] does not exists in '$path'") unless defined($e);
428 passwd_remove_entry
($passwd, $e);
430 passwd_save
($passwd);
437 my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
439 #print "group_add: '$name' in '$path'\n";
441 my $group = group_load
($path);
443 my $e = group_lookup_name
($group, $name);
444 die("group[$name] already exists in '$path'") if defined($e);
446 my $gid = group_get_free_gid
($group);
448 my $gwent = $name.":x:".$gid.":"."";
450 group_add_entry
($group, $gwent);
454 #printf("%d\n", $gid);
459 sub group_delete
($$$$$)
461 my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
463 #print "group_delete: '$name' in '$path'\n";
465 my $group = group_load
($path);
467 my $e = group_lookup_name
($group, $name);
468 die("group[$name] does not exists in '$path'") unless defined($e);
470 group_remove_entry
($group, $e);
477 sub member_add
($$$$$)
479 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
481 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
483 my $group = group_load
($group_path);
485 my $g = group_lookup_name
($group, $groupname);
486 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
488 my $passwd = passwd_load
($passwd_path);
490 my $u = passwd_lookup_name
($passwd, $username);
491 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
493 group_add_member
($group, $g, $username);
500 sub member_delete
($$$$$)
502 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
504 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
506 my $group = group_load
($group_path);
508 my $g = group_lookup_name
($group, $groupname);
509 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
511 my $passwd = passwd_load
($passwd_path);
513 my $u = passwd_lookup_name
($passwd, $username);
514 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
516 group_delete_member
($group, $g, $username);