#!/usr/local/bin/pike |
|
inherit Stdio.Port; |
|
#if !constant(Stdio.PROP_IPC) |
#define NO_IPC |
#endif |
|
// Bugfix for some older versions of Pike.. |
string combine_path(string s, string ... rest) |
{ |
for(int e=0;e<sizeof(rest);e++) |
{ |
if(sscanf(rest[e],"%*[a-zA-Z]:%*s")==2) |
{ |
s=rest[e]; |
}else{ |
s=predef::combine_path(s,rest[e]); |
} |
} |
return s; |
} |
|
// Bugfix for some older versions of Pike.. |
#define BLOCK 65536 |
int cp(string from, string to) |
{ |
if(!Stdio.cp(from,to)) |
{ |
werror("Backup cp function in effect.\n"); |
|
string data; |
object tmp=Stdio.File(); |
if(!tmp->open(from,"r")) |
{ |
werror(sprintf("Open %s for reading failed.\n",from)); |
return 0; |
} |
function r=tmp->read; |
tmp=Stdio.File(); |
if(!tmp->open(to,"wct")) |
{ |
werror(sprintf("Open %s for writing failed.\n",to)); |
return 0; |
} |
function w=tmp->write; |
do |
{ |
data=r(BLOCK); |
if(!data) |
{ |
werror("Read failed.\n"); |
return 0; |
} |
if(w(data)!=strlen(data)) |
{ |
werror("Write failed.\n"); |
return 0; |
} |
}while(strlen(data) == BLOCK); |
} |
return 1; |
} |
|
void monitor(object(Stdio.File) io, object proc) |
{ |
proc->wait(); |
if(io) |
{ |
io->close("rw"); |
io->close(); |
destruct(io); |
} |
} |
|
#ifdef WINE |
void my_proxy(Stdio.File from, Stdio.File to) |
{ |
while(string s=from->read(128,1)) |
if(to->write(s)!=strlen(s)) |
return; |
|
} |
#endif |
|
void handle_incoming_connection(object(Stdio.File) io) |
{ |
object p; |
sscanf(io->read(4),"%4c",int args); |
string *cmd=allocate(args); |
for(int e=0;e<args;e++) |
{ |
sscanf(io->read(4),"%4c",int len); |
cmd[e]=io->read(len); |
} |
|
object pi=Stdio.File(); |
#ifdef NO_IPC |
object p2=pi->pipe(); |
#else |
object p2=pi->pipe(Stdio.PROP_IPC); |
#endif |
string dir=cmd[0]; |
cmd=cmd[1..]; |
|
write("Doing %s in %s\n",cmd*" ",dir); |
|
switch(lower_case(cmd[0])) |
{ |
case "mkdir": |
{ |
string dir=combine_path(combine_path(getcwd(),dir),cmd[1]); |
int ret; |
if(Stdio.file_size(dir)!=-2) |
ret=mkdir(dir); |
else |
ret=1; |
if(!ret) |
{ |
string x=sprintf("MKDIR %s failed, errno=%d\n",dir,errno()); |
io->write(sprintf("%4c%s",strlen(x),x)); |
} |
io->write(sprintf("%4c",0)); |
io->write(sprintf("%4c",!ret)); |
break; |
} |
|
case "copy": |
{ |
string from=combine_path(combine_path(getcwd(),dir),cmd[1]); |
string to=combine_path(combine_path(getcwd(),dir),cmd[2]); |
|
if(mixed stat=file_stat(to)) |
{ |
if(stat[1]==-2) |
{ |
to=combine_path(to,basename(cmd[1])); |
} |
} |
|
|
int ret=cp(from,to); |
if(!ret) |
{ |
string x=sprintf("Errno is %d\n" |
"CWD=%s\n" |
"from=%s\n" |
"to=%s\n" |
"dir=%s (%s)\n", |
errno(), |
getcwd(), |
from, |
to, |
dir, combine_path(getcwd(),dir)); |
io->write(sprintf("%4c%s",strlen(x),x)); |
} |
io->write(sprintf("%4c",0)); |
io->write(sprintf("%4c",!ret)); |
break; |
} |
case "getenv": |
{ |
string s=getenv(cmd[1])+"\n"; |
io->write(sprintf("%4c%s",strlen(s),s)); |
io->write(sprintf("%4c",0)); |
io->write(sprintf("%4c",0)); |
break; |
} |
|
default: |
#ifdef WINE |
{ |
werror("Proxying.....\n"); |
object p3=Stdio.File(); |
#ifdef NO_IPC |
object p4=p3->pipe(); |
#else |
object p4=p3->pipe(Stdio.PROP_IPC); |
#endif |
thread_create(my_proxy,io,p4); |
io=p3; |
} |
#endif |
|
mixed err=catch { |
p=Process.create_process(cmd, |
([ |
#ifndef WINE |
"stdin":io, |
"stdout":p2, |
"stderr":p2, |
#endif |
"cwd":dir, |
])); |
}; |
destruct(p2); |
if(!err) |
{ |
#ifdef NO_IPC |
thread_create(monitor,p2,p); |
#endif |
while(1) |
{ |
string s=pi->read(1000,1); |
if(!s || !strlen(s)) break; |
io->write(sprintf("%4c%s",strlen(s),s)); |
} |
|
io->write(sprintf("%4c",0)); |
io->write(sprintf("%4c",p->wait())); |
}else{ |
werror("dir=%s\n",dir); |
werror(master()->describe_backtrace(err)); |
destruct(p2); |
io->write(sprintf("%4c",0)); |
io->write(sprintf("%4c",69)); |
} |
} |
#ifdef WINE |
io->close("rw"); |
#else |
io->close("w"); |
#endif |
destruct(io); |
} |
|
void handle_connections(string *hosts) |
{ |
while(1) |
{ |
if(object io=accept()) |
{ |
sscanf(io->query_address(),"%s ",string ip); |
if(search(hosts, ip)==-1) |
{ |
destruct(io); |
continue; |
} |
thread_create(handle_incoming_connection,io); |
}else{ |
werror("Accept failed "+errno()+"\n"); |
} |
} |
} |
|
int main(int argc, string *argv) |
{ |
#ifdef WINE |
werror("Running in WINE mode.\n"); |
#endif |
if(argc<2) |
{ |
werror("Usage: sprshd <port> <hosts to accept connections from>\n"); |
exit(1); |
} |
if(!bind((int)argv[1])) |
{ |
werror("Failed to bind port.\n"); |
exit(1); |
} |
|
string *hosts=({}); |
for(int e=2;e<sizeof(argv);e++) |
{ |
if(sscanf(argv[e],"%*d.%*d")==2) |
{ |
hosts+=({argv[e]}); |
continue; |
} |
mixed tmp=gethostbyname(argv[e]); |
if(!tmp) |
{ |
werror("Gethostbyname("+argv[e]+") failed.\n"); |
exit(1); |
} |
hosts+=tmp[1]; |
} |
|
write("Ready ("+version()+").\n"); |
|
#ifdef WINE |
thread_create(handle_connections,hosts); |
werror("main returning...\n"); |
return -1; |
#else |
handle_connections(hosts); |
return 0; |
#endif |
} |
|