1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
#!/usr/bin/perl
#
# wmanagerrc-update -- update your wmanager settings automatically
# Copyright (C) 2000 Tommi Virtanen <tv@debian.org>
# Copyright (C) 2008, 2010, 2014, 2015 Peter Pentchev <roam@ringlet.net>
use 5.010;
use strict;
use warnings;
use File::Spec::Link;
use File::Temp;
use POSIX qw/WEXITSTATUS WIFEXITED/;
sub collect_user()
{
my $fname = "$ENV{HOME}/.wmanagerrc.user";
open my $f, '<', $fname or do {
if ($!{ENOENT}) {
return ();
} else {
die "Could not open $fname: $!\n";
}
};
my @res = <$f>;
close $f or
die "Could not close $fname: $!\n";
s/[\r\n]*$// for @res;
return @res;
}
sub collect_alternatives()
{
my $pid = open my $f, '-|';
if ($pid == -1) {
die "Could not fork for update-alternatives: $!\n";
} elsif ($pid == 0) {
my @cmd = ('update-alternatives', '--query', 'x-window-manager');
exec { $cmd[0] } @cmd;
die "Could not execute @cmd: $!\n";
}
my $alt;
my %p;
while (<$f>) {
s/[\r\n]*$//;
if (/^Alternative:\s+([\/\w.+-]+)$/) {
if (defined $alt) {
die "Could not parse the update-alternatives output: Alternative without Priority\n";
}
$alt = $1;
} elsif (/^Priority:\s+(\d+)$/) {
if (!defined $alt) {
die "Could not parse the update-alternatives output: Priority without Alternative\n";
}
push @{$p{$1}}, $alt;
undef $alt;
}
}
close $f;
my $res = $?;
if (!WIFEXITED($res) || WEXITSTATUS($res) != 0) {
die "The update-alternatives query failed\n";
}
my @files = map { sort @{$p{$_}} } sort { $a <=> $b } keys %p;
@files = grep defined, map { File::Spec::Link->resolve($_) } @files;
my @output;
$pid = open $f, '-|';
if ($pid == -1) {
die "Could not fork for dpkg -S: $!\n";
} elsif ($pid == 0) {
my @cmd = ('dpkg', '-S', '--', @files);
exec { $cmd[0] } @cmd;
die "Could not exec @cmd: $!\n";
}
while (<$f>) {
s/[\r\n]*$//;
next if /^dpkg:/;
s/:[[:space:]]+/=/;
push @output, $_;
}
close $f;
$res = $?;
if (!WIFEXITED($res) || WEXITSTATUS($res) != 0) {
die "The dpkg -S query failed\n";
}
return @output;
}
sub order_alternatives(@)
{
my @cand = @_;
my @split = map {
if (/^([^=]+?)[[:space:]]*=/) {
[$1, $_]
} else {
()
}
} @cand;
my $fname = "$ENV{HOME}/.wmanagerrc.order";
open my $f, '<', $fname or do {
if ($!{ENOENT}) {
return @cand;
} else {
die "Could not open $fname: $!\n";
}
};
my %c = map { ($_->[0], $_->[1]) } @split;
my @order;
while (<$f>) {
s/[\r\n]*$//;
next unless exists $c{$_};
push @order, $c{$_};
delete $c{$_};
}
close $f;
push @order, map $_->[1], grep exists $c{$_->[0]}, @split;
return @order;
}
sub write_menu(@)
{
my @cand = @_;
my $tempf = File::Temp->new(TEMPLATE=> '.wmanagerrc.XXXXXX', DIR => $ENV{HOME});
print $tempf "$_\n" for @cand;
my $fname = "$ENV{HOME}/.wmanagerrc";
rename $tempf->filename(), $fname or
die "Could not rename ".$tempf->filename()." to $fname: $!\n";
$tempf->unlink_on_destroy(0);
}
MAIN:
{
my @cand = (collect_user, collect_alternatives);
@cand = order_alternatives @cand;
write_menu @cand;
}
|