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' is supported yet,
45 but 'group' and maybe 'member' will be added
48 --action <action> 'add' or 'delete'.
50 --name <name> The name of the object.
55 usage
(1) if (not $result);
57 usage
(0) if ($opt_help);
59 if (not defined($opt_path)) {
60 usage
(1, "missing: --path <path>");
62 if ($opt_path eq "" or $opt_path eq "/") {
63 usage
(1, "invalid: --path <path>: '$opt_path'");
65 my $opt_fullpath = abs_path
($opt_path);
66 if (not defined($opt_fullpath)) {
67 usage
(1, "invalid: --path <path>: '$opt_path'");
71 if (not defined($opt_action)) {
72 usage
(1, "missing: --action [add|delete]");
74 if ($opt_action eq "add") {
75 $passwdfn = \
&passwd_add
;
76 $groupfn = \
&group_add
;
77 } elsif ($opt_action eq "delete") {
78 $passwdfn = \
&passwd_delete
;
79 $groupfn = \
&group_delete
;
81 usage
(1, "invalid: --action [add|delete]: '$opt_action'");
84 if (not defined($opt_type)) {
85 usage
(1, "missing: --type [passwd|group]");
87 if ($opt_type eq "passwd") {
88 $actionfn = $passwdfn;
89 } elsif ($opt_type eq "group") {
92 usage
(1, "invalid: --type [passwd|group]: '$opt_type'")
95 if (not defined($opt_name)) {
96 usage
(1, "missing: --name <name>");
98 if ($opt_name eq "") {
99 usage
(1, "invalid: --name <name>");
102 exit $actionfn->($opt_fullpath, $opt_name);
104 sub passwd_add_entry
($$);
112 open(PWD
, "<$path") or die("Unable to open '$path' for read");
116 $passwd->{array
} = ();
117 $passwd->{name
} = {};
119 $passwd->{path
} = $path;
121 foreach my $line (@lines) {
122 passwd_add_entry
($passwd, $line);
128 sub passwd_lookup_name
($$)
130 my ($passwd, $name) = @_;
132 return undef unless defined($passwd->{name
}{$name});
134 return $passwd->{name
}{$name};
137 sub passwd_lookup_uid
($$)
139 my ($passwd, $uid) = @_;
141 return undef unless defined($passwd->{uid
}{$uid});
143 return $passwd->{uid
}{$uid};
146 sub passwd_get_free_uid
($)
151 while (passwd_lookup_uid
($passwd, $uid)) {
158 sub passwd_add_entry
($$)
160 my ($passwd, $str) = @_;
163 my @e = split(':', $str);
165 push(@
{$passwd->{array
}}, \
@e);
166 $passwd->{name
}{$e[0]} = \
@e;
167 $passwd->{uid
}{$e[2]} = \
@e;
170 sub passwd_remove_entry
($$)
172 my ($passwd, $eref) = @_;
174 for (my $i = 0; defined($passwd->{array
}[$i]); $i++) {
175 if ($eref == $passwd->{array
}[$i]) {
176 $passwd->{array
}[$i] = undef;
180 delete $passwd->{name
}{${$eref}[0]};
181 delete $passwd->{uid
}{${$eref}[2]};
188 my $path = $passwd->{path
};
189 my $tmppath = $path.$$;
191 foreach my $eref (@
{$passwd->{array
}}) {
192 next unless defined($eref);
194 my $line = join(':', @
{$eref});
198 open(PWD
, ">$tmppath") or die("Unable to open '$tmppath' for write");
199 print PWD
join("\n", @lines)."\n";
201 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
206 my ($path, $name) = @_;
208 #print "passwd_add: '$name' in '$path'\n";
210 my $passwd = passwd_load
($path);
212 my $e = passwd_lookup_name
($passwd, $name);
213 die("account[$name] already exists in '$path'") if defined($e);
215 my $uid = passwd_get_free_uid
($passwd);
216 my $gid = 65534;# nogroup gid
218 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
220 passwd_add_entry
($passwd, $pwent);
222 passwd_save
($passwd);
227 sub passwd_delete
($$)
229 my ($path, $name) = @_;
231 #print "passwd_delete: '$name' in '$path'\n";
233 my $passwd = passwd_load
($path);
235 my $e = passwd_lookup_name
($passwd, $name);
236 die("account[$name] does not exists in '$path'") unless defined($e);
238 passwd_remove_entry
($passwd, $e);
240 passwd_save
($passwd);
247 my ($path, $name) = @_;
249 #print "group_add: '$name' in '$path'\n";
251 die("group_add: not implemented yet!");
258 my ($path, $name) = @_;
260 #print "group_delete: '$name' in '$path'\n";
262 die("group_delete: not implemented yet!");