summaryrefslogtreecommitdiffstats
path: root/MDK/Common/System.pm
diff options
context:
space:
mode:
Diffstat (limited to 'MDK/Common/System.pm')
-rw-r--r--MDK/Common/System.pm181
1 files changed, 181 insertions, 0 deletions
diff --git a/MDK/Common/System.pm b/MDK/Common/System.pm
new file mode 100644
index 0000000..c8c4535
--- /dev/null
+++ b/MDK/Common/System.pm
@@ -0,0 +1,181 @@
+package MDK::Common::System;
+
+use MDK::Common::Math;
+use MDK::Common::File;
+
+
+use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK %compat_arch $printable_chars $sizeof_int $bitof_int); #);
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(%compat_arch $printable_chars $sizeof_int $bitof_int typeFromMagic list_passwd list_home list_skels syscall_ df sync psizeof availableMemory availableRamMB gettimeofday unix2dos getVarsFromSh setVarsInSh setVarsInShMode setVarsInCsh template2file template2userfile update_userkderc); #);
+%EXPORT_TAGS = (all => [ @EXPORT_OK ]);
+
+
+%compat_arch = ( #- compatibilty arch mapping.
+ 'noarch' => undef,
+ 'ia32' => 'noarch',
+ 'i386' => 'ia32',
+ 'i486' => 'i386',
+ 'i586' => 'i486',
+ 'i686' => 'i586',
+ 'i786' => 'i686',
+ 'k6' => 'i586',
+ 'k7' => 'k6',
+ 'k8' => 'k7',
+ 'ia64' => 'noarch',
+ 'ppc' => 'noarch',
+ 'alpha' => 'noarch',
+ 'sparc' => 'noarch',
+ 'sparc32' => 'sparc',
+ 'sparc64' => 'sparc32',
+ 'ia64' => 'noarch',
+ );
+
+$printable_chars = "\x20-\x7E";
+$sizeof_int = psizeof("i");
+$bitof_int = $sizeof_int * 8;
+
+sub typeFromMagic {
+ my $f = shift;
+ local *F; sysopen F, $f, 0 or return;
+
+ my $tmp;
+ M: foreach (@_) {
+ my ($name, @l) = @$_;
+ while (@l) {
+ my ($offset, $signature) = splice(@l, 0, 2);
+ sysseek(F, $offset, 0) or next M;
+ sysread(F, $tmp, length $signature);
+ $tmp eq $signature or next M;
+ }
+ return $name;
+ }
+ undef;
+}
+
+
+sub list_passwd() {
+ my (@l, @e);
+ setpwent();
+ while (@e = getpwent()) { push @l, [ @e ] }
+ endpwent();
+ @l;
+}
+sub list_home() {
+ map { $_->[7] } grep { $_->[2] >= 500 } list_passwd();
+}
+sub list_skels {
+ my ($prefix, $suffix) = @_;
+ grep { -d $_ && -w $_ } map { "$prefix$_/$suffix" } '/etc/skel', '/root', list_home();
+}
+
+
+
+sub syscall_ {
+ my $f = shift;
+
+ require 'syscall.ph';
+ syscall(&{$common::{"SYS_$f"}}, @_) == 0;
+}
+
+
+#- return the size of the partition and its free space in KiB
+sub df {
+ my ($mntpoint) = @_;
+ my ($blocksize, $size, $free);
+ my $buf = ' ' x 20000;
+ syscall_('statfs', $mntpoint, $buf) or return;
+ (undef, $blocksize, $size, $free, undef, undef) = unpack "L!6", $buf;
+ map { $_ * ($blocksize / 1024) } $size, $free;
+}
+
+sub sync { syscall_('sync') }
+sub psizeof { length pack $_[0] }
+sub availableMemory() { MDK::Common::Math::sum(map { /(\d+)/ } grep { /^(MemTotal|SwapTotal):/ } MDK::Common::File::cat_("/proc/meminfo")); }
+sub availableRamMB() { 4 * MDK::Common::Math::round((-s '/proc/kcore') / 1024 / 1024 / 4); }
+sub gettimeofday { my $t = pack "LL"; syscall_('gettimeofday', $t, 0) or die "gettimeofday failed: $!\n"; unpack("LL", $t) }
+sub unix2dos { local $_ = $_[0]; s/\015$//mg; s/$/\015/mg; $_ }
+
+
+
+sub getVarsFromSh {
+ my %l;
+ local *F; open F, $_[0] or return;
+ local $_;
+ while (<F>) {
+ s/#.*//; # remove comments
+ my ($v, $val, $val2) =
+ /^\s* # leading space
+ (\w+) = # variable
+ (
+ "([^"]*)" # double-quoted text
+ | '([^']*)' # single-quoted text
+ | [^'"\s]+ # normal text
+ )
+ \s*$ # end of line
+ /x or next;
+ $l{$v} = defined $val2 ? $val2 : $val;
+ }
+ %l;
+}
+
+sub setVarsInSh {
+ my ($file, $l, @fields) = @_;
+ setVarsInShMode($file, 0777 ^ umask(), $l, @fields);
+}
+
+sub setVarsInShMode {
+ my ($file, $mod, $l, @fields) = @_;
+ @fields = keys %$l unless @fields;
+
+ local *F;
+ open F, "> $file" or die "cannot create config file $file";
+ chmod $mod, $file;
+ $l->{$_} and print F "$_=$l->{$_}\n" foreach @fields;
+}
+
+sub setVarsInCsh {
+ my ($file, $l, @fields) = @_;
+ @fields = keys %$l unless @fields;
+
+ local *F;
+ open F, "> $_[0]" or die "cannot create config file $file";
+ $l->{$_} and print F "setenv $_ $l->{$_}\n" foreach @fields;
+}
+
+sub template2file {
+ my ($in, $out, %toreplace) = @_;
+ output $out, map { s/@@@(.*?)@@@/$toreplace{$1}/g; $_ } MDK::Common::File::cat_($in);
+}
+sub template2userfile {
+ my ($prefix, $in, $out_rel, $force, %toreplace) = @_;
+
+ foreach (list_skels($prefix, $out_rel)) {
+ -d MDK::Common::File::dirname($_) or !-e $_ or $force or next;
+
+ template2file($in, $_, %toreplace);
+ m|/home/(.+?)/| and chown(getpwnam($1), getgrnam($1), $_);
+ }
+}
+sub update_userkderc {
+ my ($file, $category, %subst) = @_;
+
+ output $file,
+ (map {
+ my $l = $_;
+ s/^\s*//;
+ if (my $i = /^\[$category\]/i ... /^\[/) {
+ if ($i =~ /E/) { #- for last line of category
+ $l = join('', map_each { "$::a=$::b\n" } %subst) . $l;
+ %subst = ();
+ } elsif (/^(\w*?)=/) {
+ if (my $e = delete $subst{lc($1)}) {
+ $l = "$1=$e\n";
+ }
+ }
+ }
+ $l;
+ } MDK::Common::File::cat_($file)),
+ (%subst && "[$category]\n", map_each { "$::a=$::b\n" } %subst); #- if category has not been found above.
+}
+
+1;