11 my $opt_action = undef;
20 sub passwd_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
36 print $msg."\n\n" if defined($msg);
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.
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
;
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") {
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
($$);
111 open(PWD
, "<$path") or die("Unable to open '$path' for read");
115 $passwd->{array
} = ();
116 $passwd->{name
} = {};
118 $passwd->{path
} = $path;
120 foreach my $line (@lines) {
121 passwd_add_entry
($passwd, $line);
127 sub group_add_entry
($$);
135 open(GROUP
, "<$path") or die("Unable to open '$path' for read");
139 $group->{array
} = ();
142 $group->{path
} = $path;
144 foreach my $line (@lines) {
145 group_add_entry
($group, $line);
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
($)
192 while (passwd_lookup_uid
($passwd, $uid)) {
199 sub group_get_free_gid
($)
204 while (group_lookup_gid
($group, $gid)) {
211 sub passwd_add_entry
($$)
213 my ($passwd, $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) = @_;
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]};
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});
277 open(PWD
, ">$tmppath") or die("Unable to open '$tmppath' for write");
278 print PWD
join("\n", @lines)."\n";
280 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
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) {
300 open(GROUP
, ">$tmppath") or die("Unable to open '$tmppath' for write");
301 print GROUP
join("\n", @lines)."\n";
303 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
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);
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);
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);
366 #printf("%d\n", $gid);
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);