delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / kioslave / fish / fish.pl
blob1ba539f9fffce93047f2514b6ee5aee2c002f23f
1 #!/usr/bin/perl
2 # This program is free software; you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, version 2 of the License
5 =pod
6 This file was transferred by kio_fish, a network client part of the
7 KDE project. You may safely delete it, it will be transferred again
8 when needed. It's only purpose is to make kio_fish access faster and
9 more reliable.
10 =cut
12 use Fcntl;
14 $|++;
15 #open(DEBUG,">/tmp/kio_fish.debug.$$.log");
16 # save code in initial directory if just transferred
17 if (defined $code) {
18 unlink('.fishsrv.pl');
19 sysopen(FH,'.fishsrv.pl',O_WRONLY|O_CREAT|O_EXCL);
20 print FH $code;
21 close(FH);
22 chmod(0444,'.fishsrv.pl');
23 # request new code if it changed (checksum mismatch)
24 # for automatic upgrades
25 } elsif ($ARGV[0] ne "{CHECKSUM}") {
26 $|=1;
27 print "### 100 transfer fish server\n";
28 while(<STDIN>) {
29 last if /^__END__/;
30 $code.=$_;
32 exit(eval($code));
35 # we are up and running.
36 print "### 200\n";
37 use strict;
38 use POSIX qw(getcwd dup2 strftime);
39 $SIG{'CHLD'} = 'IGNORE';
40 $| = 1;
41 MAIN: while (<STDIN>) {
42 chomp;
43 chomp;
44 next if !length($_) || substr($_,0,1) ne '#';
45 #print DEBUG "$_\n";
46 s/^#//;
47 /^VER / && do {
48 # We do not advertise "append" capability anymore, as "write" is
49 # as fast in perl mode and more reliable (overlapping writes)
50 print "VER 0.0.3 copy lscount lslinks lsmime exec stat\n### 200\n";
51 next;
53 /^PWD$/ && do {
54 print getcwd(),"\n### 200\n";
55 next;
57 /^SYMLINK\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
58 my $ofn = unquote($1);
59 my $fn = unquote($2);
60 print (symlink($ofn,$fn)?"### 200\n":"### 500 $!\n");
61 next;
63 /^COPY\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
64 my $ofn = unquote($1);
65 my $fn = unquote($2);
66 my ($size) = (stat($ofn))[7];
67 my $read = 1;
68 if (-l $ofn) {
69 my $dest = readlink($ofn);
70 unlink($fn);
71 symlink($dest,$fn) || ($read = 0);
72 } else {
73 sysopen(FH,$ofn,O_RDONLY) || do { print "### 500 $!\n"; next; };
74 sysopen(OFH,$fn,O_WRONLY|O_CREAT|O_TRUNC) || do { close(FH); print "### 500 $!\n"; next; };
75 local $/ = undef;
76 my $buffer = '';
77 while ($size > 32768 && ($read = sysread(FH,$buffer,32768)) > 0) {
78 $size -= $read;
79 if (syswrite(OFH,$buffer,$read) != $read) {
80 close(FH); close(OFH);
81 print "### 500 $!\n";
82 next MAIN;
86 while ($size > 0 && ($read = sysread(FH,$buffer,$size)) > 0) {
87 $size -= $read;
88 if (syswrite(OFH,$buffer,$read) != $read) {
89 close(FH); close(OFH);
90 print "### 500 $!\n";
91 next MAIN;
94 close(FH);
95 close(OFH);
97 if ($read > 0) {
98 print "### 200\n";
99 } else {
100 print "### 500 $!\n";
102 next;
104 /^LINK\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
105 my $ofn = unquote($1);
106 my $fn = unquote($2);
107 print (link($ofn,$fn)?"### 200\n":"### 500 $!\n");
108 next;
110 /^RENAME\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
111 my $ofn = unquote($1);
112 my $fn = unquote($2);
113 print (rename($ofn,$fn)?"### 200\n":"### 500 $!\n");
114 next;
116 /^CHGRP\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
117 my $fn = unquote($2);
118 print (chown(-1,int($1),$fn)?"### 200\n":"### 500 $!\n");
119 next;
121 /^CHOWN\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
122 my $fn = unquote($2);
123 print (chown(int($1),-1,$fn)?"### 200\n":"### 500 $!\n");
124 next;
126 /^CHMOD\s+([0-7]+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
127 my $fn = unquote($2);
128 print (chmod(oct($1),$fn)?"### 200\n":"### 500 $!\n");
129 next;
131 /^DELE\s+((?:\\.|[^\\])*?)\s*$/ && do {
132 my $fn = unquote($1);
133 print (unlink($fn)?"### 200\n":"### 500 $!\n");
134 next;
136 /^RMD\s+((?:\\.|[^\\])*?)\s*$/ && do {
137 my $dn = unquote($1);
138 print (rmdir($dn)?"### 200\n":"### 500 $!\n");
139 next;
141 /^MKD\s+((?:\\.|[^\\])*?)\s*$/ && do {
142 my $dn = unquote($1);
143 if (mkdir($dn,0777)) {
144 print "### 200\n";
145 } else {
146 my $err = $!;
147 print (chdir($dn)?"### 501 $err\n":"### 500 $err\n");
149 next;
151 /^CWD\s+((?:\\.|[^\\])*?)\s*$/ && do {
152 my $dn = unquote($1);
153 print (chdir($dn)?"### 200\n":"### 500 $!\n");
154 next;
156 /^LIST\s+((?:\\.|[^\\])*?)\s*$/ && do {
157 list($1, 1);
158 next;
160 /^STAT\s+((?:\\.|[^\\])*?)\s*$/ && do {
161 list($1, 0);
162 next;
164 /^WRITE\s+(\d+)\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
165 write_loop($2,$3,O_WRONLY|O_CREAT,$1);
166 next;
168 /^APPEND\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
169 write_loop($1,$2,O_WRONLY|O_APPEND);
170 next;
172 /^STOR\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
173 write_loop($1,$2,O_WRONLY|O_CREAT|O_TRUNC);
174 next;
176 /^RETR\s+((?:\\.|[^\\])*?)\s*$/ && do {
177 read_loop($1);
178 next;
180 /^READ\s+(\d+)\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
181 read_loop($3,$2,$1);
182 next;
184 /^EXEC\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
185 my $tempfile = unquote($2);
186 my $command = unquote($1);
187 $command = $command . ";echo \"###RESULT: \$?\"";
188 print("### 500 $!\n"), next
189 if (!sysopen(FH,$tempfile,O_CREAT|O_EXCL|O_WRONLY,0600));
190 my $pid = fork();
191 print("### 500 $!\n"), next
192 if (!defined $pid);
193 if ($pid == 0) {
194 open(STDOUT,'>>&FH');
195 open(STDERR,'>>&FH');
196 open(STDIN,'</dev/null'); # not sure here, ms windows anyone?
197 exec('/bin/sh','-c',$command);
198 print STDERR "Couldn't exec /bin/sh: $!\n";
199 exit(255);
201 waitpid($pid,0);
202 close(FH);
203 print "### 200\n";
204 next;
207 exit(0);
209 sub list {
210 my $dn = unquote($_[0]);
211 my @entries;
212 if (!-e $dn) {
213 print "### 404 File does not exist\n";
214 return;
215 } elsif ($_[1] && -d _) {
216 opendir(DIR,$dn) || do { print "### 500 $!\n"; return; };
217 @entries = readdir(DIR);
218 closedir(DIR);
219 } else {
220 ($dn, @entries) = $dn =~ m{(.*)/(.*)};
221 $dn = '/' if (!length($dn));
223 print scalar(@entries),"\n### 100\n";
224 my $cwd = getcwd();
225 chdir($dn) || do { print "### 500 $!\n"; return; };
226 foreach (@entries) {
227 my $link = readlink;
228 my ($mode,$uid,$gid,$size,$mtime) = (lstat)[2,4,5,7,9];
229 print filetype($mode,$link,$uid,$gid);
230 print "S$size\n";
231 print strftime("D%Y %m %d %H %M %S\n",localtime($mtime));
232 print ":$_\n";
233 print "L$link\n" if defined $link;
234 print mimetype($_);
235 print "\n";
237 chdir($cwd);
238 print "### 200\n";
241 sub read_loop {
242 my $fn = unquote($_[0]);
243 my ($size) = ($_[1]?int($_[1]):(stat($fn))[7]);
244 my $error = '';
245 print "### 501 Is directory\n" and return if -d $fn;
246 sysopen(FH,$fn,O_RDONLY) || ($error = $!);
247 if ($_[2]) {
248 sysseek(FH,int($_[2]),0) || do { close(FH); $error ||= $!; };
250 print "### 500 $error\n" and return if $error;
251 if (@_ < 2) {
252 print "$size\n";
254 print "### 100\n";
255 my $buffer = '';
256 my $read = 1;
257 while ($size > 32768 && ($read = sysread(FH,$buffer,32768)) > 0) {
258 #print DEBUG "$size left, $read read\n";
259 $size -= $read;
260 print $buffer;
262 while ($size > 0 && ($read = sysread(FH,$buffer,$size)) > 0) {
263 #print DEBUG "$size left, $read read\n";
264 $size -= $read;
265 print $buffer;
267 while ($size > 0) {
268 print ' ';
269 $size--;
271 $error ||= $! if $read <= 0;
272 close(FH);
273 if (!$error) {
274 print "### 200\n";
275 } else {
276 print "### 500 $error\n";
280 sub write_loop {
281 my $size = int($_[0]);
282 my $fn = unquote($_[1]);
283 #print DEBUG "write_loop called $size size, $fn fn, $_[2]\n";
284 my $error = '';
285 sysopen(FH,$fn,$_[2]) || do { print "### 400 $!\n"; return; };
286 eval { flock(FH,2); };
287 if ($_[3]) {
288 sysseek(FH,int($_[3]),0) || do { close(FH);print "### 400 $!\n"; return; };
290 <STDIN>;
291 print "### 100\n";
292 my $buffer = '';
293 my $read = 1;
294 while ($size > 32768 && ($read = read(STDIN,$buffer,32768)) > 0) {
295 #print DEBUG "$size left, $read read\n";
296 $size -= $read;
297 $error ||= $! if (syswrite(FH,$buffer,$read) != $read);
299 while ($size > 0 && ($read = read(STDIN,$buffer,$size)) > 0) {
300 #print DEBUG "$size left, $read read\n";
301 $size -= $read;
302 $error ||= $! if (syswrite(FH,$buffer,$read) != $read);
304 close(FH);
305 if (!$error) {
306 print "### 200\n";
307 } else {
308 print "### 500 $error\n";
312 sub unquote { $_ = shift; s/\\(.)/$1/g; return $_; }
314 sub filetype {
315 my ($mode,$link,$uid,$gid) = @_;
316 my $result = 'P';
317 while (1) {
318 -f _ && do { $result .= '-'; last; };
319 -d _ && do { $result .= 'd'; last; };
320 defined($link) && do { $result .= 'l'; last; };
321 -c _ && do { $result .= 'c'; last; };
322 -b _ && do { $result .= 'b'; last; };
323 -S _ && do { $result .= 's'; last; };
324 -p _ && do { $result .= 'p'; last; };
325 $result .= '?'; last;
327 $result .= ($mode & 0400?'r':'-');
328 $result .= ($mode & 0200?'w':'-');
329 $result .= ($mode & 0100?($mode&04000?'s':'x'):($mode&04000?'S':'-'));
330 $result .= ($mode & 0040?'r':'-');
331 $result .= ($mode & 0020?'w':'-');
332 $result .= ($mode & 0010?($mode&02000?'s':'x'):($mode&02000?'S':'-'));
333 $result .= ($mode & 0004?'r':'-');
334 $result .= ($mode & 0002?'w':'-');
335 $result .= ($mode & 0001?($mode&01000?'t':'x'):($mode&01000?'T':'-'));
337 $result .= ' ';
338 $result .= (getpwuid($uid)||$uid);
339 $result .= '.';
340 $result .= (getgrgid($gid)||$gid);
341 $result .= "\n";
342 return $result;
345 sub mimetype {
346 my $fn = shift;
347 return "Minode/directory\n" if -d $fn;
348 pipe(IN,OUT);
349 my $pid = fork();
350 return '' if (!defined $pid);
351 if ($pid) {
352 close(OUT);
353 my $type = <IN>;
354 close(IN);
355 chomp $type;
356 chomp $type;
357 $type =~ s/[,; ].*//;
358 return '' if ($type !~ m/\//);
359 return "M$type\n"
361 close(IN);
362 sysopen(NULL,'/dev/null',O_RDWR);
363 dup2(fileno(NULL),fileno(STDIN));
364 dup2(fileno(OUT),fileno(STDOUT));
365 dup2(fileno(NULL),fileno(STDERR));
366 exec('/usr/bin/file','-i','-b','-L',$fn);
367 exit(0);
369 __END__