File: wmanagerrc-update

package info (click to toggle)
wmanager 0.3.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 244 kB
  • sloc: cpp: 497; python: 411; perl: 124; makefile: 108; sh: 83
file content (143 lines) | stat: -rw-r--r-- 3,073 bytes parent folder | download | duplicates (5)
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;
}