chiark / gitweb /
mm it works on liberator now
[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     next if $if =~ m/\~$/;
118     $of= $if; 
119     $of =~ s,_,/,g; 
120     $of =~ s,^/,,;
121     $of =~ s,//,_,g;
122     $of =~ s/\\([0-9a-f][0-9a-f]|_|\\)/
123         length $1 eq 1 ? $1 : sprintf '%c', hex $1 
124             /ge;
125
126     next if $exclude{$of};
127
128     mkparents($of);
129     $newf= 'new/'.$if;
130     prep_proc('files/'.$if,$newf);
131
132     $perms= exists $fileperms{$of} ? $fileperms{$of} : 00666&~$umask;
133     chmod $perms, $newf or die $!;
134     
135     if (stat $home.$of) {
136         -f _ or die "$of is not a file!";
137         $nowperms= (stat _)[2] & 07777;
138         if ($nowperms != $perms) {
139             would($of, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
140         }
141         system 'diff','-u',$home.$of,$newf;
142         $?==0 or $?==256 or die $?;
143         $changes++ if $?;
144     } else {
145         die unless $!==&ENOENT;
146         would($of, sprintf 'create %04o', $perms);
147     }
148     if ($action) {
149         rename $newf,$home.$of or die $!;
150     }
151
152     delete $fileperms{$of};
153 }
154 closedir D or die $!;
155
156 die join(', ', keys %fileperms) if %fileperms;
157
158 foreach $link (keys %linktargs) {
159     mkparents($link);
160     $targ= $linktargs{$link};
161     if (lstat $home.$link) {
162         -l _ or die "$link is not a link!";
163         defined($rl= readlink $home.$link) or die $!;
164     } else {
165         die unless $!==&ENOENT;
166         $rl= undef;
167     }
168     if ($rl ne $targ) {
169         would($link, "symlink $targ <-");
170         if ($action) {
171             unlink $home.$link if defined $rl;
172             symlink $targ,$home.$link or die $!;
173         }
174     }
175 }
176
177 foreach $dir (keys %dirperms) {
178     ensuredir($dir);
179 }
180
181 sub would ($$) {
182     my ($obj,$what) = @_;
183     return if $would_done{$obj}++;
184     print STDOUT "*** $what $obj\n" or die $!;
185     $changes++;
186 }
187
188 if ($changes) {
189     print STDOUT "=== $changes changes\n" or die $!;
190 } else {
191     print STDOUT "=== no changes\n" or die $!;
192 }
193
194 prep_proc('execute','new/,execute');
195 if ($action) {
196     chmod 0700,'new/,execute' or die $!;
197     system 'new/,execute'; $? and die $?;
198 }
199
200 close STDOUT or die $!;