|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Linux::usermod;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
7474
 | 
 use strict;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
    | 
| 
4
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use Carp;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
    | 
| 
5
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use Fcntl ':flock';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
139
 | 
    | 
| 
6
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
11
 | 
 use vars qw($VERSION);  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2573
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = 0.69;  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $file_passwd  = '/etc/passwd';  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $file_shadow  = '/etc/shadow';  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $file_group	  = '/etc/group';  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $file_gshadow = '/etc/gshadow';  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %field = (  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NAME     => 0,	#The user's name  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	PPASSWORD=> 1,	#The "passwd" file password  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	UID      => 2,	#The user's id  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	GID      => 3,	#The user's group id   | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	COMMENT  => 4,	#The comment about the user  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	HOME     => 5,	#The user's home directory  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	SHELL	 => 6,	#The user's shell  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	SNAME	 => 7,	#The user's name in shadow file   | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	PASSWORD => 8,	#The 13-character encrypted password  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	LASTCHG  => 9, 	#The number of days since January 1, 1970 of the last password changed date  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	MIN	 => 10, #The minimum number of days required between password changes  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	MAX	 => 11,	#The maximum number of days the password is valid  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	WARN	 => 12,	#The number of days before expiring the password that the user is warned  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	INACTIVE => 13,	#The number of days of inactivity allowed for the user  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	EXPIRE 	 => 14,	#The number of days since January 1, 1970 that account is disabled  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	FLAG	 => 15	#Currently not used.	  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %gfield = (  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NAME	 => 0, #The group name  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	PPASSWORD=> 1, #The group password  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	GID	 => 2, #The group id number  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	USERS	 => 3, #The group members (users)  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	SNAME	 => 4, #The group name in gshadow file  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	PASSWORD => 5, #The encrypted ggroup password  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	GA	 => 6, #The group administrators  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	GU	 => 7  #The group members (users)  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub fields { keys %field }  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub gfields { keys %gfield }  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
49
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
15
 | 
 	my $class = shift;  | 
| 
50
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	my $user  = shift;  | 
| 
51
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	my $flag  = shift;  | 
| 
52
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my @args;  | 
| 
53
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
 	if ($flag){   | 
| 
54
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		croak "no such group" unless _exists($user, $flag);  | 
| 
55
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		@args = _read_grp($user);  | 
| 
56
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		push @args, '__G__';  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}else{   | 
| 
58
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		croak "no such user" unless _exists($user, $flag);  | 
| 
59
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		@args = _read_user($user);  | 
| 
60
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		push @args, '__U__';  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
62
 | 
2
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
25
 | 
 	return bless [ @args ], ref($class)||$class;  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get {  | 
| 
66
 | 
9
 | 
 
 | 
 
 | 
  
9
  
 | 
  
1
  
 | 
75
 | 
 	my $self = shift;  | 
| 
67
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	my $what = shift;  | 
| 
68
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 	my $key;  | 
| 
69
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
 	if($self->[-1] eq '__U__'){  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 		if($what =~ /^\d{1,2}$/){  | 
| 
71
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			while(my($k, $v) = each %field){  | 
| 
72
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$v == $what and $key = $k   | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
74
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			return $self->[$field{$key}]  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
76
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 		$what = uc $what;  | 
| 
77
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
 		return $self->[$field{$what}]  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	elsif($self->[-1] eq '__G__'){  | 
| 
80
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 		if($what =~ /^\d{1,2}$/){  | 
| 
81
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			while(my($k, $v) = each %gfield){  | 
| 
82
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$v == $what and $key = $k  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
84
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			return $self->[$gfield{$key}]  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
86
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		$what = uc $what;  | 
| 
87
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 		return $self->[$gfield{$what}]  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}		  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set {  | 
| 
92
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
9
 | 
 	my $self = shift;  | 
| 
93
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my $what = shift;  | 
| 
94
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	my $newval = shift;  | 
| 
95
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 	$what = uc $what;  | 
| 
96
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
12
 | 
 	return 0 unless exists($field{$what}) or exists($gfield{$what});  | 
| 
97
 | 
1
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
10
 | 
 	return 0 if $newval =~ /:/ and ($field{$what} != 8 or $gfield{$what} != 4);   | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	$newval = '' if $newval =~  /^undef$/i;  | 
| 
99
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	if($self->[-1] eq '__U__'){  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	 my $flag = shift || 0;  | 
| 
101
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 my $oldval = $self->[$field{$what}];  | 
| 
102
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 my $name = $self->[$field{NAME}];  | 
| 
103
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 _clean($name);  | 
| 
104
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 $self->[$field{$what}] = $newval;  | 
| 
105
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 if($field{$what} <= 6){  | 
| 
106
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @file = _io("$file_passwd", '', 'r');  | 
| 
107
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @user;  | 
| 
108
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->[$_] for 0..6;  | 
| 
109
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $user = join ':', @user;  | 
| 
110
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){ s/.+/$user/ if /^\Q$name\E:/ }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
111
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io("$file_passwd", \@file, 'w');  | 
| 
112
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if($field{$what} == 0){  | 
| 
113
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			croak "invalid name" if $newval !~ /^([A-Z]|[a-z]){1}\w{0,254}/;  | 
| 
114
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my %names;  | 
| 
115
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			@file = @user = ();  | 
| 
116
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			@file = _io("$file_shadow", '', 'r');  | 
| 
117
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			map{ /^(.[^:]+):/ and $names{$1} = 1 }@file;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
118
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			croak "user name $newval already exists" if defined($names{$newval});	  | 
| 
119
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			undef %names;  | 
| 
120
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			push @user, $self->[$_] for 8..14;  | 
| 
121
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			unshift @user, $self->[0];  | 
| 
122
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$user = join ':', @user;  | 
| 
123
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			for(@file){ s/.+/$user/ if /^\Q$name\E:/ }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
124
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			_io("$file_shadow", \@file, 'w') and return 1  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
128
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 if($field{$what} > 6){	  | 
| 
129
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @file = _io("$file_shadow", '', 'r');  | 
| 
130
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$self->[9] = _get_1970_diff() if $field{$what} == 8;  | 
| 
131
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 		if($field{$what} == 8 && $newval){  | 
| 
132
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$oldval =~ /^!/ and my $lock = 1;  | 
| 
133
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$self->[8] = _gen_pass($self->[$field{$what}], $lock) unless $flag;  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
135
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @user;  | 
| 
136
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, "$self->[$_]" for 7..15;  | 
| 
137
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $user = join ':', @user;  | 
| 
138
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){ s/.+/$user/ if /^\Q$name\E:/ }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
139
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io("$file_shadow", \@file, 'w');  | 
| 
140
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if($field{$what} == 7){  | 
| 
141
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			@file = @user = ();  | 
| 
142
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			@file = _io("$file_passwd", '', 'r');  | 
| 
143
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			push @user, $self->[$_] for 1..6;  | 
| 
144
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			unshift @user, $self->[7];  | 
| 
145
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$user = join ':', @user;  | 
| 
146
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			for(@file){ s/.+/$user/ if /^\Q$name\E:/ }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
147
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			_io("$file_passwd", \@file, 'w') and return 1  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	elsif($self->[-1] eq '__G__'){  | 
| 
152
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	 my $name = $self->[$gfield{NAME}];  | 
| 
153
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	 my $oldval = $self->[$gfield{$what}];  | 
| 
154
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	 $self->[$gfield{$what}] = $newval;  | 
| 
155
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
7
 | 
 	 if($gfield{$what} == 0 or $gfield{$what} == 4){	  | 
| 
156
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		croak "invalid name" if $newval !~ /^([A-Z]|[a-z]){1}\w{0,254}/;  | 
| 
157
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 	my @file = _io($file_group, '', 'r');  | 
| 
158
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my %names;  | 
| 
159
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		map{ m#^(.[^:]+):# and $names{$1} }@file;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
160
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		croak "group name $newval already exists" if exists($names{$newval});  | 
| 
161
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		undef %names;  | 
| 
162
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
163
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			/^$oldval:/ or next;  | 
| 
164
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";  | 
| 
165
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
167
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_group, \@file, 'w');  | 
| 
168
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		@file = _io($file_gshadow, '', 'r');  | 
| 
169
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
170
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			/^$oldval:/ or next;  | 
| 
171
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$self->[4] = $newval;  | 
| 
172
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";  | 
| 
173
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
175
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_gshadow, \@file, 'w') and return 1  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
177
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
8
 | 
 	 if($gfield{$what} == 3 or $gfield{$what} == 7){  | 
| 
178
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(split /\s+/, $newval){  | 
| 
179
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			croak "$_ does not exist" unless(_exists($_))  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
181
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $users = join ',', split /\s+/, "$newval";  | 
| 
182
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$self->[3] = $users;  | 
| 
183
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @file = _io($file_group, '', 'r');  | 
| 
184
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
185
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			/^\Q$name\E:/ or next;  | 
| 
186
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";  | 
| 
187
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
189
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_group, \@file, 'w');  | 
| 
190
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		@file = _io($file_gshadow, '', 'r');  | 
| 
191
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$self->[7] = $users;  | 
| 
192
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
193
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			/^\Q$name\E:/ or next;  | 
| 
194
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[3]";  | 
| 
195
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
197
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_gshadow, \@file, 'w') and return 1  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
199
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	 if($gfield{$what} == 2){	  | 
| 
200
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	 	croak "wrong group id" if $newval < 1 or $newval > 65535;  | 
| 
201
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my %ids;  | 
| 
202
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @file  = _io("$file_group", '', 'r');  | 
| 
203
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		map { /^.+?:.*?:(.+):/ and $ids{$1} = 1 } @file;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
204
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		croak "group id $newval already exists" if $ids{$newval};  | 
| 
205
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
206
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			/^\Q$name\E:/ or next;  | 
| 
207
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";  | 
| 
208
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
210
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_group, \@file, 'w') and return 1  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
212
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	 if($gfield{$what} == 6){  | 
| 
213
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		croak "user $newval does not exist" unless(_exists($newval));  | 
| 
214
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		$self->[6] = $newval;  | 
| 
215
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		my @file = _io($file_gshadow, '', 'r');  | 
| 
216
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		for(@file){  | 
| 
217
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
 		        /^\Q$name\E:/ or next;  | 
| 
218
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 			my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";  | 
| 
219
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 			s/.+/$newline/;  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
221
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		_io($file_gshadow, \@file, 'w') and return 1  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
223
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	 if($gfield{$what} == 1 or $gfield{$what} == 5){  | 
| 
224
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
15
 | 
 	 	no strict 'refs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3799
 | 
    | 
| 
225
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 	my $salt = join '', ('a'..'z', 'A'..'Z', 0..9)[rand 26,rand 26,rand 26];  | 
| 
226
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $newpass;  | 
| 
227
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if($newval)  | 
| 
228
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			{ $newpass = crypt($newval, $salt) }  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		else  | 
| 
230
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			{ $newpass = '!' }  | 
| 
231
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my @file = _io($file_gshadow, '', 'r');  | 
| 
232
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$self->[1] = 'x';  | 
| 
233
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$self->[5] = $newpass;  | 
| 
234
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
235
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		        /^\Q$name\E:/ or next;  | 
| 
236
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";  | 
| 
237
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;   | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
239
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_gshadow, \@file, 'w');  | 
| 
240
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		@file = _io($file_group, '', 'r');  | 
| 
241
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(@file){  | 
| 
242
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		        /^\Q$name\E:/ or next;  | 
| 
243
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";  | 
| 
244
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			s/.+/$newline/;  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
246
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		_io($file_group, \@file, 'w') and return 1  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 }  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
249
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return 0  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _read_user {  | 
| 
253
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
2
 | 
 	my $username = shift;  | 
| 
254
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my (@user, @tmp, @file);  | 
| 
255
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	@file = _io($file_passwd, '', 'r');  | 
| 
256
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	for(@file){  | 
| 
257
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 		/^\Q$username\E:/ or next;  | 
| 
258
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		my $user = $_;  | 
| 
259
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		for(1..7){  | 
| 
260
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
98
 | 
 			$user =~ m#(.[^:]*){$_}#;  | 
| 
261
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 			my $ss = $1;  | 
| 
262
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 			$ss =~ s/(^:*|:*$)//;  | 
| 
263
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 			$tmp[$_ - 1] = $ss;  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} last  | 
| 
265
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	}  | 
| 
266
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	@user = @tmp;  | 
| 
267
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	@tmp = ();  | 
| 
268
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	@file = _io($file_shadow, '', 'r');  | 
| 
269
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	for(@file){  | 
| 
270
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 		/^\Q$username\E:/ or next;  | 
| 
271
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		my $user = $_;  | 
| 
272
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		for(1..9){  | 
| 
273
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
123
 | 
 			$user =~ m#(.[^:]*){$_}#;  | 
| 
274
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 			my $ss = $1;  | 
| 
275
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 			$ss =~ s/(^:*|:*$)//;  | 
| 
276
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 			$tmp[$_ - 1] = $ss;  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} last  | 
| 
278
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	}  | 
| 
279
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 	@user = (@user, @tmp);  | 
| 
280
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	return (@user);  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _gen_pass {  | 
| 
284
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 	my $password = shift;  | 
| 
285
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $flag = shift;  | 
| 
286
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$password or croak "no password given";  | 
| 
287
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my @rands = ( "A" .. "Z", "a" .. "z", 0 .. 9 );  | 
| 
288
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $salt = join("", @rands[ map { rand @rands } ( 1 .. 8 ) ]);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
289
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$password = ($flag)?'!'.crypt($password, q($1$)."$salt"):crypt($password, q($1$)."$salt");  | 
| 
290
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return $password  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _exists {  | 
| 
294
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
8
 | 
 	my $name	= shift;  | 
| 
295
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my $gflag	= shift;   | 
| 
296
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 	my $file	= ($gflag) ? "$file_group" : "$file_passwd";   | 
| 
297
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	my @file	= _io("$file", '', 'r');  | 
| 
298
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	my $flag;  | 
| 
299
 | 
4
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
58
 | 
 	/^\Q$name\E:/ and $flag = 1 for @file;  | 
| 
300
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 	return $flag ? 1 : 0  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add {  | 
| 
304
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
418
 | 
 	my $class = shift;  | 
| 
305
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my (%fields, $c, @args);  | 
| 
306
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 	push @args, $_ for @_;  | 
| 
307
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	croak "no username given" if scalar @args == 0;  | 
| 
308
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	croak "user $args[0] exists" if _exists($args[0]);  | 
| 
309
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	for(@args){  | 
| 
310
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 		chomp($_);  | 
| 
311
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
36
 | 
 		/^\s*$/ and $c++ and next;  | 
| 
312
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 		$c++;  | 
| 
313
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 		if($c == 1){  | 
| 
314
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 			croak "wrong username given" if /:/;  | 
| 
315
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
554
 | 
 			croak "wrong username" unless /^([A-Z]|[a-z]){1}\w{0,254}/;  | 
| 
316
 | 
1
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
6
 | 
 			$fields{username} = $_ || croak "no username given";  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
318
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 		if($c == 2){  | 
| 
319
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			croak "wrong password length" unless /^(.*){0,254}$/;  | 
| 
320
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$fields{password} = _gen_pass($_) if $_;  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
322
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 		if($c == 3){  | 
| 
323
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 			$_ eq '' and $_ = 1000;  | 
| 
324
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 		 	croak "wrong uid" unless /^\d+$/;  | 
| 
325
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
8
 | 
 			croak "wrong uid" if $_ > 65535 or $_ < 1;  | 
| 
326
 | 
1
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
6
 | 
 			$fields{uid} = $_ || 1000;  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
328
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 		if($c == 4){  | 
| 
329
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 			$_ eq '' and $_ = 1000;  | 
| 
330
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 			croak "wrong gid" unless /^\d+$/;  | 
| 
331
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
6
 | 
 			if(/^\d+$/){ croak "wrong gid" if $_ > 65535 or $_ < 1 }  | 
| 
 
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
332
 | 
1
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
5
 | 
 			$fields{gid} = $_ || $fields{uid};  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
334
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 		if($c == 5){  | 
| 
335
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			croak "wrong comment given" if /:/;  | 
| 
336
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 			$fields{comment} = $_;  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
338
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 		if($c == 6){  | 
| 
339
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 			croak "wrong home given" if /:/;  | 
| 
340
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 			$fields{home} = $_;  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
342
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 		if($c == 7){  | 
| 
343
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 			croak " wrong shell given" if /:/;  | 
| 
344
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 			$fields{shell} = $_;  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
347
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	$fields{password} or $fields{password} = '!';  | 
| 
348
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	my @file = _io("$file_passwd", '', 'r');  | 
| 
349
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my @ids;  | 
| 
350
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	push @ids, (split /:/)[2] for @file;  | 
| 
351
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	for (@ids){   | 
| 
352
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if ($fields{uid} == $_){  | 
| 
353
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$fields{uid} = 1000;  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			last  | 
| 
355
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		}  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
357
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	if($fields{uid} == 1000){  | 
| 
358
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	   for(sort @ids){   | 
| 
359
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$_ < 1000 and next;  | 
| 
360
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$fields{uid} == $_ and $fields{uid}++;  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	   }  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
363
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	$fields{gid} = $fields{uid} if !$fields{gid};  | 
| 
364
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 	my @newuser = ("$fields{username}:x:$fields{uid}:$fields{gid}:$fields{comment}:$fields{home}:$fields{shell}");  | 
| 
365
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	_io("$file_passwd", \@newuser, 'a');  | 
| 
366
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my $time_1970 = _get_1970_diff();  | 
| 
367
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	@newuser = ("$fields{username}:$fields{password}:$time_1970:0:99999:7:::");  | 
| 
368
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	_io("$file_shadow", \@newuser, 'a');  | 
| 
369
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	return 1  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub grpadd {  | 
| 
373
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
9
 | 
 	my $class = shift;  | 
| 
374
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my $group = shift or croak "empty group name";  | 
| 
375
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
 	my $gid = shift;  | 
| 
376
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my $users = shift;  | 
| 
377
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
 	my (@tmp, %file, @newgroup);  | 
| 
378
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my @file  = _io("$file_group", '', 'r');  | 
| 
379
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	croak "wrong group name" unless $group =~ /^([A-Z]|[a-z]){1}\w{0,254}/;  | 
| 
380
 | 
1
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	map { @tmp = split /:/, $_ and $file{$tmp[0]} = $tmp[2] } @file;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
381
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	exists($file{$group}) and croak "group $group already exists";  | 
| 
382
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	if(!$gid){  | 
| 
383
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$gid = 100;  | 
| 
384
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for(sort {$a <=> $b} values %file){   | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
385
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			next if $_ < 100;   | 
| 
386
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$gid == $_ and $gid++   | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
389
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my $userlist = join(',', split(/\s+/, $users));  | 
| 
390
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	@newgroup = ("$group:x:$gid:$userlist");  | 
| 
391
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	_io("$file_group", \@newgroup, 'a');  | 
| 
392
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	@newgroup = ("$group:!!::$userlist");  | 
| 
393
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	_io("$file_gshadow", \@newgroup, 'a');  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub del {  | 
| 
397
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $class = shift;  | 
| 
398
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $username = shift;  | 
| 
399
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_exists($username) or croak "user $username does not exist";  | 
| 
400
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my @old = _io("$file_passwd", '', 'r');  | 
| 
401
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my @new;  | 
| 
402
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	/^\Q$username\E:/ or push @new, $_ for @old;  | 
| 
403
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_io("$file_passwd", \@new, 'w');  | 
| 
404
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	@new = ();  | 
| 
405
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	@old = _io("$file_shadow", '', 'r');  | 
| 
406
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	/^\Q$username\E:/ or push @new, $_ for @old;  | 
| 
407
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_io("$file_shadow", \@new, 'w');  | 
| 
408
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return 1  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub grpdel {  | 
| 
412
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $class = shift;  | 
| 
413
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $group = shift or croak "empty group name/gid";  | 
| 
414
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my (@tmp, %file);  | 
| 
415
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my @file  = _io("$file_group", '', 'r');  | 
| 
416
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	map { @tmp = split /:/, $_ and $file{$tmp[0]} = $tmp[2] } @file;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
417
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	exists($file{$group}) or croak "group $group does not exists";  | 
| 
418
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	@tmp = ();  | 
| 
419
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	/^$group/ or push @tmp, $_ for @file;  | 
| 
420
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_io("$file_group", \@tmp, 'w');  | 
| 
421
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	@file = _io("$file_gshadow", '', 'r');  | 
| 
422
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	@tmp = ();  | 
| 
423
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	/^$group/ or push @tmp, $_ for @file;  | 
| 
424
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_io("$file_gshadow", \@tmp, 'w');  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _read_grp {  | 
| 
429
 | 
1
 | 
  
 50
  
 | 
 
 | 
  
1
  
 | 
 
 | 
3
 | 
 	my $group = shift or croak "empty group name/gid";  | 
| 
430
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my (@tmp, @grp);  | 
| 
431
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	my @file  = _io("$file_group", '', 'r');  | 
| 
432
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	for(@file){  | 
| 
433
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 		/^$group:/ or next;  | 
| 
434
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		my $user = $_;  | 
| 
435
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		for(1..4){  | 
| 
436
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
153
 | 
 			$user =~ /(.[^:]*){$_}/;  | 
| 
437
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			my $ss = $1;  | 
| 
438
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 			$ss =~ s/(^:*|:*$)//;  | 
| 
439
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 			$tmp[$_ - 1] = $ss;  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} last   | 
| 
441
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	}  | 
| 
442
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	@grp = @tmp;  | 
| 
443
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	@file  = _io("$file_gshadow", '', 'r');  | 
| 
444
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	for(@file){  | 
| 
445
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 		/^$group:/ or next;  | 
| 
446
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		my $user = $_;  | 
| 
447
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		for(1..4){  | 
| 
448
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
698
 | 
 			$user =~ /(.[^:]*){$_}/;  | 
| 
449
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 			my $ss = $1;  | 
| 
450
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
 			$ss =~ s/(^:*|:*$)//;  | 
| 
451
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			$tmp[$_ - 1] = $ss;  | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} last  | 
| 
453
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	}  | 
| 
454
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 	@grp = (@grp, @tmp);  | 
| 
455
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	return (@grp)  | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub tobsd{  | 
| 
459
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $self = shift;  | 
| 
460
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	(my @file) = _io("$file_shadow", '', 'r');  | 
| 
461
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $name = $self->get('name');  | 
| 
462
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my @user;  | 
| 
463
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	for(@file){  | 
| 
464
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		/^\Q$name\E:/ or next;  | 
| 
465
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $name, ':';  | 
| 
466
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('password'), ':';  | 
| 
467
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('uid'), ':';  | 
| 
468
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('gid'), ':';  | 
| 
469
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, ':';  | 
| 
470
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('expire') || 0, ':';  | 
| 
471
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('expire') || 0, ':';  | 
| 
472
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('comment'), ':';  | 
| 
473
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('home'), ':';  | 
| 
474
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		push @user, $self->get('shell');  | 
| 
475
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $user = join '', @user;  | 
| 
476
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		s/.*/$user/;  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
478
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	_io("$file_shadow", \@file, 'w');  | 
| 
479
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return 1  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _io{  | 
| 
483
 | 
16
 | 
 
 | 
 
 | 
  
16
  
 | 
 
 | 
21
 | 
         my $file = shift;  | 
| 
484
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	my $newvals = shift;  | 
| 
485
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	my $flag = shift;  | 
| 
486
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	my @file;  | 
| 
487
 | 
16
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
223
 | 
 	croak $! unless -f $file;  | 
| 
488
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
 	local *FH;  | 
| 
489
 | 
16
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
59
 | 
 	die "posible flags: r/w/a" unless $flag =~ /^(r|w|a)$/;  | 
| 
490
 | 
16
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
37
 | 
 	if($flag eq 'r'){  | 
| 
491
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
468
 | 
 		open FH, $file or croak "can't open_r $file $!";  | 
| 
492
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
79
 | 
 		flock FH, LOCK_SH or croak "can't lock_sh $file";  | 
| 
493
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
217
 | 
 		@file = ;  | 
| 
494
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
116
 | 
 		close FH;  | 
| 
495
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 		map { s/\n// } @file;  | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
    | 
| 
496
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
 		return @file;  | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
498
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	if($flag eq 'w'){  | 
| 
499
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
98
 | 
 		open FH, "> $file" or croak "can't open_w $file $!";  | 
| 
500
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 		flock FH, LOCK_EX or croak "can't lock_ex $file";  | 
| 
501
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		print FH "$_\n" for @{$newvals};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
    | 
| 
502
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
 		close FH;  | 
| 
503
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 		return 1  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
505
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
 	if($flag eq 'a'){  | 
| 
506
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
126
 | 
 		open FH, ">> $file" or croak "can't open_a $file $!";  | 
| 
507
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 		flock FH, LOCK_EX or croak "can't lock_ex $file";  | 
| 
508
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		print FH "$_\n" for @{$newvals};  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
    | 
| 
509
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
220
 | 
 		close FH;  | 
| 
510
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 		return 1  | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub users{  | 
| 
515
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $class = shift;  | 
| 
516
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	(my @file) = _io("$file_passwd", '', 'r');  | 
| 
517
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my (%users, @users);  | 
| 
518
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	m#^(.[^:]+):# and push @users, $1 for @file;  | 
| 
519
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	map{ $users{$_} = 1 }@users;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
520
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return %users  | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub grps{  | 
| 
524
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $class = shift;  | 
| 
525
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	(my @file) = _io("$file_group", '', 'r');  | 
| 
526
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my (%users, @users);  | 
| 
527
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	m#^(.[^:]+):# and push @users, $1 for @file;  | 
| 
528
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	map{ $users{$_} = 1 }@users;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
529
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return %users  | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub lock{  | 
| 
533
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $self = shift;  | 
| 
534
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $password = $self->get("password");  | 
| 
535
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return 1 if $password =~ /^\!/;  | 
| 
536
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$password =~ s/(.*)/!$1/;  | 
| 
537
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$self->set("password", $password, 1);  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub unlock{  | 
| 
541
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
         my $self = shift;  | 
| 
542
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $password = $self->get("password");  | 
| 
543
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return if $password !~ /^\!/;  | 
| 
544
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$password =~ s/^\!//;  | 
| 
545
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	$password ||= 'undef';  | 
| 
546
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->set("password", $password, 1);  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
549
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
9
 | 
 sub _get_1970_diff{ return int time / (3600 * 24) }  | 
| 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _clean{  | 
| 
552
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 	my $specchars = \shift;  | 
| 
553
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $special = qr#\$|\*|\@|\^|\+|\.|\?|\)|\(|\||\]|\[|\{|\}#;  | 
| 
554
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$$specchars =~ s/($special)/\\$1/g;  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1  | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |