chiark / gitweb /
xenophobe tunnel
[ian-dotfiles.git] / process
1 #!/usr/bin/perl
2
3 use POSIX;
4
5 $action=0;
6 defined($umask=umask) or die $!;
7 $home= $ENV{'HOME'}.'/';
8
9 while ($ARGV[0] =~ m/^-/) {
10     $_= shift(@ARGV);
11     last if m/^--$/;
12     while (m/^-./) {
13         if (s/^-y/-/) {
14             $action=1;
15         } elsif (s/^-u([0-7]{3})/-/) {
16             $umask= oct $1;
17         } elsif (s/^-h/-/) {
18             $home= $';
19         } else {
20             die;
21         }
22     }
23 }
24 die if @ARGV;
25
26 stat $home or die $!;
27 -d _ or die;
28
29 sub read_prep ($) {
30     my ($inputfile) = @_;
31     defined($c= open P, "-|") or die $!;
32     if (!$c) { exec './gpt','config',$inputfile; die $!; }
33 }
34 sub fin_prep () {
35     close P; die "$?" if $?;
36 }
37
38 read_prep('perms');
39 for (;;) {
40     $!=0; defined($_=<P>) or die $!;
41     chomp; s/^\s+//; s/\s+$//;
42     next if m/^\#/; next unless m/\S/;
43     last if m/^\.$/;
44     if (m/(.*\S)\s+\-\>\s+(\S.*)/) {
45         $linktargs{$1}= $2;
46     } elsif (m/^(.*\S)\s+\-\-$/) {
47         $exclude{$1}= 1;
48     } elsif (m/^(.*\S)\s+(\S+)$/) {
49         ($of,$pe)=($1,$2);
50         $isdir= $of =~ s,/$,,;
51         if ($pe =~ m/^[0-7]+$/) {
52             $pe= oct $&;
53         } elsif ($pe eq '+x') {
54             $pe= 0777&~$umask;
55         } elsif ($pe eq '/') {
56             $pe= 02777&~$umask;
57         } else {
58             die "$pe ?";
59         }
60         ($isdir ? $dirperms{$of} : $fileperms{$of}) = $pe;
61     }
62 }
63 fin_prep();
64
65 sub mkparents ($) {
66     my ($parent) = @_;
67     $parent =~ s,/[^/]+$,, or return;
68     ensuredir($parent);
69 }
70
71 sub maybe_chmod ($$$) {
72     my ($nowperms,$perms,$obj) = @_;
73     return if $nowperms==$perms;
74     if ($action) {
75         chmod $perms, $home.$obj or die $!;
76     } else {
77         would($obj, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
78     }
79 }
80
81 sub ensuredir ($) {
82     my ($dir) = @_;
83     mkparents($dir);
84     $perms= exists $dirperms{$dir} ? $dirperms{$dir} : 02777&~$umask;
85     if (stat $home.$dir) {
86         -d _ or die "$dir is not a directory!";
87         $nowperms= (stat _)[2] & 07777;
88         maybe_chmod($nowperms,$perms,$dir);
89     } else {
90         die $! unless $!==&ENOENT;
91         if ($action) {
92             mkdir $home.$dir, $perms or die $!;
93         } else {
94             would($dir, sprintf 'mkdir %04o', $perms);
95         }
96     }
97 }
98
99 -d 'new' or mkdir 'new', 02700 or die $!;
100
101 sub prep_proc ($$) {
102     my ($if,$newf) = @_;
103     my ($c);
104     defined($c= fork) or die $!;
105     if (!$c) {
106         unlink $newf;
107         open STDOUT, "> $newf" or die "$newf $!";
108         exec './gpt','config',$if; die $!;
109     }
110     $!=0; waitpid($c,0)==$c or die $!;
111     $? and die $?;
112 }
113
114 opendir D, "files" or die $!;
115 while ($if=readdir D) {
116     next unless $if =~ m/^[_a-z0-9\\]/;
117     $of= $if; 
118     $of =~ s,_,/,g; 
119     $of =~ s,^/,,;
120     $of =~ s,//,_,g;
121     $of =~ s/\\([0-9a-f][0-9a-f]|_|\\)/
122         length $1 eq 1 ? $1 : sprintf '%c', hex $1 
123             /ge;
124
125     next if $exclude{$of};
126
127     mkparents($of);
128     $newf= 'new/'.$if;
129     prep_proc('files/'.$if,$newf);
130
131     $perms= exists $fileperms{$of} ? $fileperms{$of} : 00666&~$umask;
132     chmod $perms, $newf or die $!;
133     
134     if (stat $home.$of) {
135         -f _ or die "$of is not a file!";
136         $nowperms= (stat _)[2] & 07777;
137         if ($nowperms != $perms) {
138             would($of, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
139         }
140         system 'diff','-u',$home.$of,$newf;
141         $?==0 or $?==256 or die $?;
142         $changes++ if $?;
143     } else {
144         die unless $!==&ENOENT;
145         would($of, sprintf 'create %04o', $perms);
146     }
147     if ($action) {
148         rename $newf,$home.$of or die $!;
149     }
150
151     delete $fileperms{$of};
152 }
153 closedir D or die $!;
154
155 die join(', ', keys %fileperms) if %fileperms;
156
157 foreach $link (keys %linktargs) {
158     mkparents($link);
159     $targ= $linktargs{$link};
160     if (lstat $home.$link) {
161         -l _ or die "$link is not a link!";
162         defined($rl= readlink $home.$link) or die $!;
163     } else {
164         die unless $!==&ENOENT;
165         $rl= undef;
166     }
167     if ($rl ne $targ) {
168         would($link, "symlink $targ <-");
169         if ($action) {
170             unlink $home.$link if defined $rl;
171             symlink $targ,$home.$link or die $!;
172         }
173     }
174 }
175
176 foreach $dir (keys %dirperms) {
177     ensuredir($dir);
178 }
179
180 sub would ($$) {
181     my ($obj,$what) = @_;
182     return if $would_done{$obj}++;
183     print STDOUT "*** $what $obj\n" or die $!;
184     $changes++;
185 }
186
187 if ($changes) {
188     print STDOUT "=== $changes changes\n" or die $!;
189 } else {
190     print STDOUT "=== no changes\n" or die $!;
191 }
192
193 prep_proc('execute','new/,execute');
194 if ($action) {
195     chmod 0700,'new/,execute' or die $!;
196     system 'new/,execute'; $? and die $?;
197 }
198
199 close STDOUT or die $!;