| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package MDK::Common::System; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
MDK::Common::System - system-related useful functions |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use MDK::Common::System qw(:all); |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 EXPORTS |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=over |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=item %compat_arch |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
architecture compatibility mapping (eg: k6 => i586, k7 => k6 ...) |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=item %printable_chars |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
7 bit ascii characters |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=item $sizeof_int |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sizeof(int) |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=item $bitof_int |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
$sizeof_int * 8 |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=item arch() |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
return the architecture (eg: i686, ppc, ia64, k7...) |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=item typeFromMagic(FILENAME, LIST) |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
find the first corresponding magic in FILENAME. eg of LIST: |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
[ 'empty', 0, "\0\0\0\0" ], |
|
40
|
|
|
|
|
|
|
[ 'grub', 0, "\xEBG", 0x17d, "stage1 \0" ], |
|
41
|
|
|
|
|
|
|
[ 'lilo', 0x2, "LILO" ], |
|
42
|
|
|
|
|
|
|
sub { my ($F) = @_; |
|
43
|
|
|
|
|
|
|
#- standard grub has no good magic (Mageia's grub is patched to have "GRUB" at offset 6) |
|
44
|
|
|
|
|
|
|
#- so scanning a range of possible places where grub can have its string |
|
45
|
|
|
|
|
|
|
my ($min, $max, $magic) = (0x176, 0x181, "GRUB \0"); |
|
46
|
|
|
|
|
|
|
my $tmp; |
|
47
|
|
|
|
|
|
|
sysseek($F, 0, 0) && sysread($F, $tmp, $max + length($magic)) or return; |
|
48
|
|
|
|
|
|
|
substr($tmp, 0, 2) eq "\xEBH" or return; |
|
49
|
|
|
|
|
|
|
index($tmp, $magic, $min) >= 0 && "grub"; |
|
50
|
|
|
|
|
|
|
}, |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
where each entry is [ magic_name, offset, string, offset, string, ... ]. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=item list_passwd() |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
return the list of users as given by C (see perlfunc) |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item is_real_user() |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
checks whether or not the user is a system user or a real user |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item is_real_group() |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
checks whether or not the group is a system group or a real group |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item list_home() |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
return the list of home (eg: /home/foo, /home/pixel, ...) |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=item list_skels() |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
return the directories where we can find dot files: homes, /root and /etc/skel |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=item list_users() |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
return the list of unprivilegied users (uses the is_real_user function to filter |
|
77
|
|
|
|
|
|
|
out system users from the full list) |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item syscall_(NAME, PARA) |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
calls the syscall NAME |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item psizeof(STRING) |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
useful to know the length of a C format string. |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
psizeof("I I I C C S") = 4 + 4 + 4 + 1 + 1 + 2 = 16 |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item availableMemory() |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
size of swap + memory |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item availableRamMB() |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
size of RAM as reported by the BIOS (it is a round number that can be |
|
96
|
|
|
|
|
|
|
displayed or given as "mem=128M" to the kernel) |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item gettimeofday() |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
returns the epoch in microseconds |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item unix2dos(STRING) |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
takes care of CR/LF translation |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item whereis_binary(STRING) |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
return the first absolute file in $PATH (similar to which(1) and whereis(1)) |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item getVarsFromSh(FILENAME) |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
returns a hash associating shell variables to their value. useful for config |
|
113
|
|
|
|
|
|
|
files such as /etc/sysconfig files |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=item setVarsInSh(FILENAME, HASH REF) |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
write file in shell format association a shell variable + value for each |
|
118
|
|
|
|
|
|
|
key/value |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item setVarsInSh(FILENAME, HASH REF, LIST) |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
restrict the fields that will be printed to LIST |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item setVarsInShMode(FILENAME, INT, HASH REF, LIST) |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
like setVarsInSh with INT being the chmod value for the config file |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item addVarsInSh(FILENAME, HASH REF) |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
like setVarsInSh but keeping the entries in the file |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=item addVarsInSh(FILENAME, HASH REF, LIST) |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
like setVarsInSh but keeping the entries in the file |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item addVarsInShMode(FILENAME, INT, HASH REF, LIST) |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
like addVarsInShMode but keeping the entries in the file |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item setExportedVarsInCsh(FILENAME, HASH REF, LIST) |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
same as C for csh format |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item template2file(FILENAME_IN, FILENAME_OUT, HASH) |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
read in a template file, replace keys @@@key@@@ with value, save it in out |
|
147
|
|
|
|
|
|
|
file |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=item template2userfile(PREFIX, FILENAME_IN, FILENAME_OUT, BOOL, HASH) |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
read in a template file, replace keys @@@key@@@ with value, save it in every homes. |
|
152
|
|
|
|
|
|
|
If BOOL is true, overwrite existing files. FILENAME_OUT must be a relative filename |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item read_gnomekderc(FILENAME, STRING) |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
reads GNOME-like and KDE-like config files (aka windows-like). |
|
157
|
|
|
|
|
|
|
You must give a category. eg: |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
read_gnomekderc("/etc/skels/.kderc", 'KDE') |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=item update_gnomekderc(FILENAME, STRING, HASH) |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
modifies GNOME-like and KDE-like config files (aka windows-like). |
|
164
|
|
|
|
|
|
|
If the category doesn't exist, it creates it. eg: |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
update_gnomekderc("/etc/skels/.kderc", 'KDE', |
|
167
|
|
|
|
|
|
|
kfmIconStyle => "Large") |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item fuzzy_pidofs(REGEXP) |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
return the list of process ids matching the regexp |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=back |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 OTHER |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=over |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item better_arch(ARCH1, ARCH2) |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
is ARCH1 compatible with ARCH2? |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
better_arch('i386', 'ia64') and better_arch('ia64', 'i386') are false |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
better_arch('k7', 'k6') is true and better_arch('k6', 'k7') is false |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=item compat_arch(STRING) |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
test the architecture compatibility. eg: |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
compat_arch('i386') is false on a ia64 |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
compat_arch('k6') is true on a k6 and k7 but false on a i386 and i686 |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=back |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
L |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=cut |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
1
|
|
|
1
|
|
6
|
use MDK::Common::Math; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
36
|
|
|
205
|
1
|
|
|
1
|
|
5
|
use MDK::Common::File; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
25
|
|
|
206
|
1
|
|
|
1
|
|
4
|
use MDK::Common::DataStructure; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
23
|
|
|
207
|
|
|
|
|
|
|
|
|
208
|
1
|
|
|
1
|
|
4
|
use Exporter; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
2754
|
|
|
209
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
210
|
|
|
|
|
|
|
our @EXPORT_OK = qw(%compat_arch $printable_chars $sizeof_int $bitof_int arch distrib typeFromMagic list_passwd is_real_user is_real_group list_home list_skels list_users syscall_ psizeof availableMemory availableRamMB gettimeofday unix2dos whereis_binary getVarsFromSh setVarsInSh setVarsInShMode addVarsInSh addVarsInShMode setExportedVarsInSh setExportedVarsInCsh template2file template2userfile read_gnomekderc update_gnomekderc fuzzy_pidofs); #); |
|
211
|
|
|
|
|
|
|
our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
our %compat_arch = ( #- compatibilty arch mapping. |
|
215
|
|
|
|
|
|
|
'noarch' => undef, |
|
216
|
|
|
|
|
|
|
'ia32' => 'noarch', |
|
217
|
|
|
|
|
|
|
'i386' => 'ia32', |
|
218
|
|
|
|
|
|
|
'i486' => 'i386', |
|
219
|
|
|
|
|
|
|
'i586' => 'i486', |
|
220
|
|
|
|
|
|
|
'i686' => 'i586', |
|
221
|
|
|
|
|
|
|
'i786' => 'i686', |
|
222
|
|
|
|
|
|
|
'k6' => 'i586', |
|
223
|
|
|
|
|
|
|
'k7' => 'k6', |
|
224
|
|
|
|
|
|
|
'k8' => 'k7', |
|
225
|
|
|
|
|
|
|
'x86_64' => 'i686', |
|
226
|
|
|
|
|
|
|
'amd64' => 'x86_64', |
|
227
|
|
|
|
|
|
|
'ia64' => 'noarch', |
|
228
|
|
|
|
|
|
|
'ppc' => 'noarch', |
|
229
|
|
|
|
|
|
|
'alpha' => 'noarch', |
|
230
|
|
|
|
|
|
|
'sparc' => 'noarch', |
|
231
|
|
|
|
|
|
|
'sparc32' => 'sparc', |
|
232
|
|
|
|
|
|
|
'sparc64' => 'sparc32', |
|
233
|
|
|
|
|
|
|
'ia64' => 'noarch', |
|
234
|
|
|
|
|
|
|
); |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
our $printable_chars = "\x20-\x7E"; |
|
237
|
|
|
|
|
|
|
our $sizeof_int = psizeof("i"); |
|
238
|
|
|
|
|
|
|
our $bitof_int = $sizeof_int * 8; |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub arch() { |
|
242
|
0
|
|
|
0
|
1
|
0
|
my $SYS_NMLN = 65; |
|
243
|
0
|
|
|
|
|
0
|
my $format = "Z$SYS_NMLN" x 6; |
|
244
|
0
|
|
|
|
|
0
|
my $t = pack $format; |
|
245
|
0
|
|
|
|
|
0
|
syscall_('uname', $t); |
|
246
|
0
|
|
|
|
|
0
|
(unpack($format, $t))[4]; |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
sub better_arch { |
|
249
|
0
|
|
|
0
|
1
|
0
|
my ($new, $old) = @_; |
|
250
|
0
|
|
0
|
|
|
0
|
while ($new && $new ne $old) { $new = $compat_arch{$new} } |
|
|
0
|
|
|
|
|
0
|
|
|
251
|
0
|
|
|
|
|
0
|
$new; |
|
252
|
|
|
|
|
|
|
} |
|
253
|
0
|
|
|
0
|
1
|
0
|
sub compat_arch { better_arch(arch(), $_[0]) } |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub distrib() { |
|
256
|
0
|
|
|
0
|
0
|
0
|
my $release = MDK::Common::File::cat_('/etc/release'); |
|
257
|
0
|
|
|
|
|
0
|
my ($real_system, $real_product) = $release =~ /(.*) release ([\d.]+)/; |
|
258
|
0
|
|
|
|
|
0
|
my $oem_config = '/etc/sysconfig/oem'; |
|
259
|
0
|
|
0
|
|
|
0
|
my %oem = -f $oem_config && getVarsFromSh($oem_config); |
|
260
|
|
|
|
|
|
|
#- (blino) FIXME: merge with release functions from /usr/lib/libDrakX/common.pm (including product.id parsing) |
|
261
|
0
|
|
|
|
|
0
|
my ($default_company) = split(' ', $real_system); |
|
262
|
0
|
|
0
|
|
|
0
|
my $company = $oem{COMPANY} || $default_company || 'Unknown vendor'; |
|
263
|
0
|
|
0
|
|
|
0
|
my $system = $oem{SYSTEM} || $real_system; |
|
264
|
0
|
|
0
|
|
|
0
|
my $product = $oem{PRODUCT} || $real_product; |
|
265
|
0
|
|
|
|
|
0
|
(company => $company, system => $system, product => $product, real_system => $real_system, real_product => $real_product); |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub typeFromMagic { |
|
269
|
0
|
|
|
0
|
1
|
0
|
my $f = shift; |
|
270
|
0
|
0
|
|
|
|
0
|
sysopen(my $F, $f, 0) or return; |
|
271
|
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
0
|
my $tmp; |
|
273
|
0
|
|
|
|
|
0
|
M: foreach (@_) { |
|
274
|
0
|
0
|
|
|
|
0
|
if (ref($_) eq 'CODE') { |
|
275
|
0
|
0
|
|
|
|
0
|
my $name = $_->($F) or next M; |
|
276
|
0
|
|
|
|
|
0
|
return $name; |
|
277
|
|
|
|
|
|
|
} else { |
|
278
|
0
|
|
|
|
|
0
|
my ($name, @l) = @$_; |
|
279
|
0
|
|
|
|
|
0
|
while (@l) { |
|
280
|
0
|
|
|
|
|
0
|
my ($offset, $signature) = splice(@l, 0, 2); |
|
281
|
0
|
0
|
|
|
|
0
|
sysseek($F, $offset, 0) or next M; |
|
282
|
0
|
|
|
|
|
0
|
sysread($F, $tmp, length $signature); |
|
283
|
0
|
0
|
|
|
|
0
|
$tmp eq $signature or next M; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
0
|
|
|
|
|
0
|
return $name; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
} |
|
288
|
0
|
|
|
|
|
0
|
undef; |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub list_passwd() { |
|
293
|
0
|
|
|
0
|
1
|
0
|
my (@l, @e); |
|
294
|
0
|
|
|
|
|
0
|
setpwent(); |
|
295
|
0
|
|
|
|
|
0
|
while (@e = getpwent()) { push @l, [ @e ] } |
|
|
0
|
|
|
|
|
0
|
|
|
296
|
0
|
|
|
|
|
0
|
endpwent(); |
|
297
|
0
|
|
|
|
|
0
|
@l; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
sub is_real_user { |
|
300
|
0
|
|
|
0
|
1
|
0
|
my ($username) = @_; |
|
301
|
|
|
|
|
|
|
|
|
302
|
0
|
0
|
|
|
|
0
|
return 0 if $username eq "nobody"; |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# We consider real users to be those users who: |
|
305
|
|
|
|
|
|
|
# Have a UID >= 1000 |
|
306
|
|
|
|
|
|
|
# or |
|
307
|
|
|
|
|
|
|
# Have a UID >= 500 |
|
308
|
|
|
|
|
|
|
# and have a homedir that is not / or does not start with /var or /run |
|
309
|
|
|
|
|
|
|
# and have a shell that does not end in "nologin" or "false" |
|
310
|
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
0
|
my (undef, undef, $uid, undef, undef, undef, undef, $homedir, $shell) = getpwnam($username); |
|
312
|
0
|
0
|
0
|
|
|
0
|
($uid >= 1000 || ($uid >= 500 && $homedir !~ m!^/($|var/|run/)! && $shell !~ /(nologin|false)$/)); |
|
|
|
|
0
|
|
|
|
|
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
sub is_real_group { |
|
315
|
0
|
|
|
0
|
1
|
0
|
my ($groupname) = @_; |
|
316
|
|
|
|
|
|
|
|
|
317
|
0
|
0
|
|
|
|
0
|
return 0 if $groupname eq "nogroup"; |
|
318
|
|
|
|
|
|
|
|
|
319
|
0
|
|
|
|
|
0
|
my (undef, undef, $gid, $members) = getgrnam($groupname); |
|
320
|
0
|
0
|
|
|
|
0
|
return 0 if $gid < 500; |
|
321
|
0
|
0
|
|
|
|
0
|
return 1 if $gid >= 1000; |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# We are in the range 500-1000, so we need some heuristic. |
|
324
|
|
|
|
|
|
|
# We consider ourselves a "real" group if this is the primary group of a user |
|
325
|
|
|
|
|
|
|
# with the same name, or we have any member users who are "real" |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
0
|
my (undef, undef, undef, $ugid) = getpwnam($groupname); |
|
328
|
0
|
0
|
0
|
|
|
0
|
return 1 if $ugid == $gid && is_real_user($groupname); |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# OK we're not a primary group, but perhaps we have some real members? |
|
331
|
0
|
|
|
|
|
0
|
foreach (split(' ', $members)) { |
|
332
|
0
|
0
|
|
|
|
0
|
return 1 if is_real_user($_); |
|
333
|
|
|
|
|
|
|
} |
|
334
|
0
|
|
|
|
|
0
|
return 0; |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
sub list_home() { |
|
337
|
0
|
|
|
0
|
1
|
0
|
MDK::Common::DataStructure::uniq(map { $_->[7] } grep { is_real_user($_->[0]) } list_passwd()); |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
sub list_skels { |
|
340
|
0
|
|
|
0
|
1
|
0
|
my ($prefix, $suffix) = @_; |
|
341
|
0
|
0
|
|
|
|
0
|
grep { -d $_ && -w $_ } map { "$prefix$_/$suffix" } '/etc/skel', '/root', list_home(); |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub list_users() { |
|
345
|
0
|
0
|
|
0
|
1
|
0
|
MDK::Common::DataStructure::uniq(map { is_real_user($_->[0]) ? $_->[0] : () } list_passwd()); |
|
|
0
|
|
|
|
|
0
|
|
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub syscall_ { |
|
351
|
0
|
|
|
0
|
1
|
0
|
my $f = shift; |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
#- load syscall.ph in package "main". If every use of syscall.ph do the same, all will be nice |
|
354
|
|
|
|
|
|
|
package main; |
|
355
|
0
|
|
|
|
|
0
|
require 'syscall.ph'; |
|
356
|
|
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
0
|
syscall(&{"main::SYS_$f"}, @_) == 0; |
|
|
0
|
|
|
|
|
0
|
|
|
358
|
|
|
|
|
|
|
} |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
#- return the size of the partition and its free space in KiB |
|
362
|
|
|
|
|
|
|
sub df { |
|
363
|
0
|
|
|
0
|
0
|
0
|
my ($mntpoint) = @_; |
|
364
|
0
|
|
|
|
|
0
|
require Filesys::Df; |
|
365
|
0
|
|
|
|
|
0
|
my $df = Filesys::Df::df($mntpoint, 1024); # ask 1kb values |
|
366
|
0
|
|
|
|
|
0
|
@$df{qw(blocks bfree)}; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
|
|
369
|
0
|
|
|
0
|
0
|
0
|
sub sync() { syscall_('sync') } |
|
370
|
1
|
|
|
1
|
1
|
3
|
sub psizeof { length pack $_[0] } |
|
371
|
0
|
|
|
0
|
1
|
|
sub availableMemory() { MDK::Common::Math::sum(map { /(\d+)/ } grep { /^(MemTotal|SwapTotal):/ } MDK::Common::File::cat_("/proc/meminfo")) } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
372
|
0
|
|
|
0
|
1
|
|
sub availableRamMB() { 4 * MDK::Common::Math::round((-s '/proc/kcore') / 1024 / 1024 / 4) } |
|
373
|
0
|
0
|
|
0
|
1
|
|
sub gettimeofday() { my $t = pack "LL"; syscall_('gettimeofday', $t, 0) or die "gettimeofday failed: $!\n"; unpack("LL", $t) } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
374
|
0
|
|
|
0
|
1
|
|
sub unix2dos { local $_ = $_[0]; s/\015$//mg; s/$/\015/mg; $_ } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub expandLinkInChroot { |
|
377
|
0
|
|
|
0
|
0
|
|
my ($file, $prefix) = @_; |
|
378
|
0
|
|
|
|
|
|
my $l = readlink "$prefix$file"; |
|
379
|
0
|
0
|
|
|
|
|
return unless $l; |
|
380
|
0
|
0
|
|
|
|
|
return $l if $l =~ m!^/!; |
|
381
|
0
|
|
|
|
|
|
my $path = $file; |
|
382
|
0
|
|
|
|
|
|
$path =~ s!/[^/]*$!!; |
|
383
|
0
|
|
|
|
|
|
$path .= "/$l"; |
|
384
|
0
|
|
|
|
|
|
return $path; |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub whereis_binary { |
|
388
|
0
|
|
|
0
|
1
|
|
my ($prog, $o_prefix) = @_; |
|
389
|
0
|
0
|
|
|
|
|
if ($prog =~ m!/!) { |
|
390
|
0
|
|
|
|
|
|
require MDK::Common::Various; |
|
391
|
0
|
|
|
|
|
|
warn qq(don't call whereis_binary with a name containing a "/" (the culprit is: $prog)\n) . MDK::Common::Various::backtrace(); |
|
392
|
0
|
|
|
|
|
|
return; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
0
|
|
|
|
|
|
foreach (split(':', $ENV{PATH})) { |
|
395
|
0
|
|
|
|
|
|
my $f = "$_/$prog"; |
|
396
|
0
|
|
|
|
|
|
my $links = 0; |
|
397
|
0
|
|
|
|
|
|
my $l = $f; |
|
398
|
0
|
|
|
|
|
|
while (-l "$o_prefix$l") { |
|
399
|
0
|
|
|
|
|
|
$l = expandLinkInChroot($l, $o_prefix); |
|
400
|
0
|
0
|
|
|
|
|
if ($links++ > 16) { |
|
401
|
0
|
|
|
|
|
|
warn qq(symlink recursion too deep in whereis_binary\n); |
|
402
|
0
|
|
|
|
|
|
return; |
|
403
|
|
|
|
|
|
|
} |
|
404
|
|
|
|
|
|
|
} |
|
405
|
0
|
0
|
|
|
|
|
-x "$o_prefix$l" and return $f; |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
sub getVarsFromSh { |
|
410
|
0
|
|
|
0
|
1
|
|
my %l; |
|
411
|
0
|
0
|
|
|
|
|
open(my $F, $_[0]) or return; |
|
412
|
0
|
|
|
|
|
|
local $_; |
|
413
|
0
|
|
|
|
|
|
while (<$F>) { |
|
414
|
0
|
|
|
|
|
|
s/^\s*#.*//; # remove comment-only lines |
|
415
|
0
|
|
|
|
|
|
s/^\s*//; # leading space |
|
416
|
0
|
0
|
|
|
|
|
my ($v, $val) = /^(\w+)=(.*)/ or next; |
|
417
|
0
|
0
|
|
|
|
|
if ($val =~ /^"(.*)"(\s+#.*)?$/) { |
|
|
|
0
|
|
|
|
|
|
|
418
|
0
|
|
|
|
|
|
$val = $1; |
|
419
|
|
|
|
|
|
|
} elsif ($val =~ /^'(.*)'(\s+#.*)?$/) { |
|
420
|
0
|
|
|
|
|
|
$val = $1; |
|
421
|
0
|
|
|
|
|
|
$val =~ s/(^|[^'])'\\''/$1'/g; |
|
422
|
|
|
|
|
|
|
} |
|
423
|
0
|
|
|
|
|
|
$l{$v} = $val; |
|
424
|
|
|
|
|
|
|
} |
|
425
|
0
|
|
|
|
|
|
%l; |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub addVarsInSh { |
|
429
|
0
|
|
|
0
|
1
|
|
my ($file, $l, @fields) = @_; |
|
430
|
0
|
|
|
|
|
|
addVarsInShMode($file, 0777 ^ umask(), $l, @fields); |
|
431
|
|
|
|
|
|
|
} |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub addVarsInShMode { |
|
434
|
0
|
|
|
0
|
1
|
|
my ($file, $mod, $l, @fields) = @_; |
|
435
|
0
|
0
|
|
|
|
|
my %l = @fields ? map { $_ => $l->{$_} } @fields : %$l; |
|
|
0
|
|
|
|
|
|
|
|
436
|
0
|
|
|
|
|
|
my %l2 = getVarsFromSh($file); |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# below is add2hash_(\%l, \%l2); |
|
439
|
0
|
|
0
|
|
|
|
exists $l{$_} or $l{$_} = $l2{$_} foreach keys %l2; |
|
440
|
|
|
|
|
|
|
|
|
441
|
0
|
|
|
|
|
|
setVarsInShMode($file, $mod, \%l); |
|
442
|
|
|
|
|
|
|
} |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub setVarsInSh { |
|
445
|
0
|
|
|
0
|
1
|
|
my ($file, $l, @fields) = @_; |
|
446
|
0
|
|
|
|
|
|
setVarsInShMode($file, 0777 ^ umask(), $l, @fields); |
|
447
|
|
|
|
|
|
|
} |
|
448
|
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
sub quoteForSh { |
|
450
|
0
|
|
|
0
|
0
|
|
my ($val) = @_; |
|
451
|
0
|
0
|
|
|
|
|
if ($val =~ /["`\$]/) { |
|
|
|
0
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
$val =~ s/(')/$1\\$1$1/g; |
|
453
|
0
|
|
|
|
|
|
$val = qq('$val'); |
|
454
|
|
|
|
|
|
|
} elsif ($val =~ /[\(\)'|\s\\;<>\[\]~{}*?]/) { |
|
455
|
0
|
|
|
|
|
|
$val = qq("$val"); |
|
456
|
|
|
|
|
|
|
} |
|
457
|
0
|
|
|
|
|
|
$val; |
|
458
|
|
|
|
|
|
|
} |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub setVarsInShMode { |
|
461
|
0
|
|
|
0
|
1
|
|
my ($file, $mod, $l, @fields) = @_; |
|
462
|
0
|
0
|
|
|
|
|
@fields = sort keys %$l unless @fields; |
|
463
|
|
|
|
|
|
|
my $string = join('', |
|
464
|
0
|
|
|
|
|
|
map { "$_=" . quoteForSh($l->{$_}) . "\n" } grep { $l->{$_} } @fields |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
); |
|
466
|
0
|
0
|
|
|
|
|
if ($file =~ m!^/home/!) { |
|
467
|
0
|
|
|
|
|
|
MDK::Common::File::secured_output($file, $string); |
|
468
|
|
|
|
|
|
|
} else { |
|
469
|
0
|
|
|
|
|
|
MDK::Common::File::output($file, $string); |
|
470
|
|
|
|
|
|
|
} |
|
471
|
|
|
|
|
|
|
|
|
472
|
0
|
|
|
|
|
|
chmod $mod, $file; |
|
473
|
|
|
|
|
|
|
} |
|
474
|
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub setExportedVarsInSh { |
|
476
|
0
|
|
|
0
|
0
|
|
my ($file, $l, @fields) = @_; |
|
477
|
0
|
0
|
|
|
|
|
@fields = keys %$l unless @fields; |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
MDK::Common::File::output($file, |
|
480
|
0
|
0
|
|
|
|
|
(map { $l->{$_} ? "$_=" . quoteForSh($l->{$_}) . "\n" : () } @fields), |
|
|
0
|
0
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
@fields ? "export " . join(" ", @fields) . "\n" : (), |
|
482
|
|
|
|
|
|
|
); |
|
483
|
|
|
|
|
|
|
} |
|
484
|
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
sub setExportedVarsInCsh { |
|
486
|
0
|
|
|
0
|
1
|
|
my ($file, $l, @fields) = @_; |
|
487
|
0
|
0
|
|
|
|
|
@fields = keys %$l unless @fields; |
|
488
|
|
|
|
|
|
|
|
|
489
|
0
|
0
|
|
|
|
|
MDK::Common::File::output($file, map { $l->{$_} ? "setenv $_ " . quoteForSh($l->{$_}) . "\n" : () } @fields); |
|
|
0
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
} |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
sub template2file { |
|
493
|
0
|
|
|
0
|
1
|
|
my ($in, $out, %toreplace) = @_; |
|
494
|
0
|
|
|
|
|
|
MDK::Common::File::output($out, map { s/@@@(.*?)@@@/$toreplace{$1}/g; $_ } MDK::Common::File::cat_($in)); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
sub template2userfile { |
|
497
|
0
|
|
|
0
|
1
|
|
my ($prefix, $in, $out_rel, $force, %toreplace) = @_; |
|
498
|
|
|
|
|
|
|
|
|
499
|
0
|
|
|
|
|
|
foreach (list_skels($prefix, $out_rel)) { |
|
500
|
0
|
0
|
0
|
|
|
|
-d MDK::Common::File::dirname($_) or !-e $_ or $force or next; |
|
|
|
|
0
|
|
|
|
|
|
501
|
|
|
|
|
|
|
|
|
502
|
0
|
|
|
|
|
|
template2file($in, $_, %toreplace); |
|
503
|
0
|
0
|
|
|
|
|
m|/home/(.+?)/| and chown(getpwnam($1), getgrnam($1), $_); |
|
504
|
|
|
|
|
|
|
} |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
sub read_gnomekderc { |
|
508
|
0
|
|
|
0
|
1
|
|
my ($file, $category) = @_; |
|
509
|
0
|
|
|
|
|
|
my %h; |
|
510
|
0
|
|
|
|
|
|
foreach (MDK::Common::File::cat_($file), "[NOCATEGORY]\n") { |
|
511
|
0
|
0
|
|
|
|
|
if (/^\s*\[\Q$category\E\]/i ... /^\[/) { |
|
512
|
0
|
0
|
|
|
|
|
$h{$1} = $2 if /^\s*([^=]*?)=(.*)/; |
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
} |
|
515
|
0
|
|
|
|
|
|
%h; |
|
516
|
|
|
|
|
|
|
} |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub update_gnomekderc { |
|
519
|
0
|
|
|
0
|
1
|
|
my ($file, $category, %subst_) = @_; |
|
520
|
|
|
|
|
|
|
|
|
521
|
0
|
|
|
|
|
|
my %subst = map { lc($_) => [ $_, $subst_{$_} ] } keys %subst_; |
|
|
0
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
|
|
523
|
0
|
|
|
|
|
|
my $s; |
|
524
|
0
|
0
|
|
|
|
|
defined($category) or $category = "DEFAULTCATEGORY"; |
|
525
|
0
|
|
|
|
|
|
foreach ("[DEFAULTCATEGORY]\n", MDK::Common::File::cat_($file), "[NOCATEGORY]\n") { |
|
526
|
0
|
0
|
|
|
|
|
if (my $i = /^\s*\[\Q$category\E\]/i ... /^\[/) { |
|
527
|
0
|
0
|
|
|
|
|
if ($i =~ /E/) { #- for last line of category |
|
|
|
0
|
|
|
|
|
|
|
528
|
0
|
|
|
|
|
|
chomp $s; $s .= "\n"; |
|
|
0
|
|
|
|
|
|
|
|
529
|
0
|
|
|
|
|
|
$s .= "$_->[0]=$_->[1]\n" foreach values %subst; |
|
530
|
0
|
|
|
|
|
|
%subst = (); |
|
531
|
|
|
|
|
|
|
} elsif (/^\s*([^=]*?)=/) { |
|
532
|
0
|
0
|
|
|
|
|
if (my $e = delete $subst{lc($1)}) { |
|
533
|
0
|
|
|
|
|
|
$_ = "$1=$e->[1]\n"; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
} |
|
536
|
|
|
|
|
|
|
} |
|
537
|
0
|
0
|
|
|
|
|
$s .= $_ if !/^\[(NO|DEFAULT)CATEGORY\]/; |
|
538
|
|
|
|
|
|
|
} |
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
#- if category has not been found above (DEFAULTCATEGORY is always found). |
|
541
|
0
|
0
|
|
|
|
|
if (keys %subst) { |
|
542
|
0
|
|
|
|
|
|
chomp $s; |
|
543
|
0
|
|
|
|
|
|
$s .= "\n[$category]\n"; |
|
544
|
0
|
|
|
|
|
|
$s .= "$_->[0]=$_->[1]\n" foreach values %subst; |
|
545
|
|
|
|
|
|
|
} |
|
546
|
|
|
|
|
|
|
|
|
547
|
0
|
|
|
|
|
|
MDK::Common::File::output_p($file, $s); |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub fuzzy_pidofs { |
|
552
|
0
|
|
|
0
|
1
|
|
my ($regexp) = @_; |
|
553
|
|
|
|
|
|
|
grep { |
|
554
|
0
|
0
|
|
|
|
|
if (/^(\d+)$/) { |
|
|
0
|
|
|
|
|
|
|
|
555
|
0
|
|
0
|
|
|
|
my $s = MDK::Common::File::cat_("/proc/$_/cmdline") || |
|
556
|
|
|
|
|
|
|
readlink("/proc/$_/exe") || |
|
557
|
|
|
|
|
|
|
MDK::Common::File::cat_("/proc/$_/stat") =~ /\s(\S+)/ && $1 || |
|
558
|
|
|
|
|
|
|
''; |
|
559
|
0
|
|
|
|
|
|
$s =~ /$regexp/; |
|
560
|
|
|
|
|
|
|
} else { |
|
561
|
0
|
|
|
|
|
|
0; |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
} MDK::Common::File::all('/proc'); |
|
564
|
|
|
|
|
|
|
} |
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
1; |