/**$Id:roxen.pike,v1.3291999/10/0623:07:36grubbaExp$**TheRoxenChallengermainprogram.**PerHedbor
,HenrikGrubbström,PontusHagland,DavidHedborandothers.*///ABSandsuicidesystemscontributedfreelyb
yFrancescoChemolliconstantcvs_version="$Id:roxen.pike,v1.3291999/10/0623:07:36grubbaExp$";objec
tbackend_thread;objectargcache;//Someheaderfiles#defineIN_ROXEN#includeroxen.h#includeconfig.h#
includemodule.h#includevariables.h#includestat.h//Inheritsinherit"global_variables";inherit"hos
ts";inherit"disk_cache";inherit"language";inherit"supports";/**Versioninformation*/constant__ro
xen_version__="1.4";constant__roxen_build__="0";#ifdef__NT__stringreal_version="RoxenChallenger
/"+__roxen_version__+"."+__roxen_build__+"NT";#elsestringreal_version="RoxenChallenger/"+__roxe
n_version__+"."+__roxen_build__;#endif//Prototypesforotherpartsofroxen.classRequestID{objectcon
f;//ReallyConfiguration,butthat'ssortofrecursive.inttime;stringraw_url;intdo_not_disconnect;map
ping(string:string)variables;mapping(string:mixed)misc;mapping(string:string)cookies;mapping(st
ring:string)request_headers;multiset(string)prestate;multiset(string)config;multiset(string)sup
ports;multiset(string)pragma;array(string)client;array(string)referer;Stdio.Filemy_fd;stringpro
t;stringclientprot;stringmethod;stringrealfile;stringvirtfile;stringrest_query;stringraw;string
query;stringnot_query;stringextra_extension;stringdata;stringleftovers;array(int|string)auth;st
ringrawauth;stringrealauth;stringsince;stringremoteaddr;stringhost;voidcreate(object|voidmaster
_request_id);voidsend(string|objectwhat,int|voidlen);stringscan_for_query(stringin);voidend(str
ing|voids,int|voidkeepit);voidready_to_receive();voidsend_result(mapping|voidresult);RequestIDc
lone_me();};stringfilename(objecto){returnsearch(master()-programs,object_program(o));}#ifdefTH
READS//ThismutexisusedbyPrivsobjecteuid_egid_lock=Thread.Mutex();#endif/*THREADS*//**Theprivile
gechanger.**Basedonprivs.pike,v1.36.*/intprivs_level;staticclassPrivs{#ifefun(seteuid)intsaved_
uid;intsaved_gid;intnew_uid;intnew_gid;#defineLOGP(variablesvariables-auditGLOBVAR(audit))#ifco
nstant(geteuid)constant(getegid)constant(seteuid)constant(setegid)#defineHAVE_EFFECTIVE_USER#en
difstaticprivatestring_getcwd(){if(catch{return(getcwd());}){return("Unknowndirectory(nox-biton
currentdirectory?)");}}staticprivatestringdbt(arrayt){if(!arrayp(t)||(sizeof(t)2))return"";retu
rn(((t[0]||"Unknownprogram")-(_getcwd()+"/"))-"base_server/")+":"+t[1]+"\n";}#ifdefTHREADSstati
cmixedmutex_key;//Onlyonethreadmaymodifytheeuid/egidatatime.staticobjectthreads_disabled;#endif
/*THREADS*/intp_level;voidcreate(stringreason,int|string|voiduid,int|string|voidgid){#ifdefPRIV
S_DEBUGwerror(sprintf("Privs(%O,%O,%O)\n""privs_level:%O\n",reason,uid,gid,privs_level));#endif
/*PRIVS_DEBUG*/#ifdefHAVE_EFFECTIVE_USERarrayu;#ifdefTHREADSif(euid_egid_lock){catch{mutex_key=
euid_egid_lock-lock();};}threads_disabled=_disable_threads();#endif/*THREADS*/p_level=privs_lev
el++;if(getuid())return;/*Needstobeheresinceroot-priviligesmaybeneededto*usegetpw{uid,nam}.*/sa
ved_uid=geteuid();saved_gid=getegid();seteuid(0);/*Astringofdigits?*/if(stringp(uid)(replace(ui
d,"0123456789"/"",({""})*10)==""))uid=(int)uid;if(stringp(gid)(replace(gid,"0123456789"/"",({""
})*10=="")))gid=(int)gid;if(!stringp(uid))u=getpwuid(uid);else{u=getpwnam(uid);if(u)uid=u[2];}i
f(u!gid)gid=u[3];if(!u){if(uid(uid!="root")){if(intp(uid)(uid=60000)){report_warning(sprintf("P
rivs:User%disnotinthepassworddatabase.\n""Assumingnobody.\n",uid));//Nobody.gid=gid||uid;//Fake
agidalso.u=({"fake-nobody","x",uid,gid,"Arealnobody","/","/sbin/sh"});}else{error("Unknownuser:
"+uid+"\n");}}else{u=({"root","x",0,gid,"Thesuper-user","/","/sbin/sh"});}}if(LOGP)report_notic
e(sprintf("Changeto%s(%d):%dprivswanted(%s),from%s",(string)u[0],(int)uid,(int)gid,(string)reas
on,(string)dbt(backtrace()[-2])));#ifefun(cleargroups)catch{cleargroups();};#endif/*cleargroups
*/#ifefun(initgroups)catch{initgroups(u[0],u[3]);};#endifgid=gid||getgid();interr=(int)setegid(
new_gid=gid);if(err0){report_debug(sprintf("Privs:WARNING:Failedtosettheeffectivegroupidto%d!\n
""Checkthatyourpassworddatabaseiscorrectforuser%s(%d),\n""andthatyourgroupdatabaseiscorrect.\n"
,gid,(string)u[0],(int)uid));intgid2=gid;#ifdefHPUX_KLUDGEif(gid=60000){/*HPUXhasdoesn'tlikegro
upshigherthan60000,*buthasassignednobodytogroup60001(whichisn'teven*in/etc/group!).**HPUX'slibc
alsoinsistsonfillingnumericfieldsitdoesn'tlike*withthevalue60001!*/perror("Privs:WARNING:Assumi
ngnobody-group.\n""Tryingsomealternatives...\n");//Assumewewantthenobodygroup,andtryacoupleofal
ternativesforeach(({60001,65534,-2}),gid2){perror("%d...",gid2);if(initgroups(u[0],gid2)=0){if(
(err=setegid(new_gid=gid2))=0){perror("Success!\n");break;}}}}#endif/*HPUX_KLUDGE*/if(err0){per
ror("Privs:Failed\n");throw(({sprintf("FailedtosetEGIDto%d\n",gid),backtrace()}));}perror("Priv
s:WARNING:Setegidto%dinsteadof%d.\n",gid2,gid);gid=gid2;}if(getgid()!=gid)setgid(gid||getgid())
;seteuid(new_uid=uid);#endif/*HAVE_EFFECTIVE_USER*/}voiddestroy(){#ifdefPRIVS_DEBUGwerror(sprin
tf("Privs-destroy()\n""privs_level:%O\n",privs_level));#endif/*PRIVS_DEBUG*/#ifdefHAVE_EFFECTIV
E_USER/*Checkthatwedon'tincreasetheprivslevel*/if(p_level=privs_level){report_error(sprintf("Ch
angebacktouid#%dgid#%dfromuid#%dgid#%d\n""inwrongorder!Savedlevel:%dCurrentlevel:%d\n""Occursin
:\n%s\n",saved_uid,saved_gid,new_uid,new_gid,p_level,privs_level,describe_backtrace(backtrace()
)));return(0);}if(p_level!=privs_level-1){report_error(sprintf("Changebacktouid#%dgid#%dfromuid
#%dgid#%d\n""Skipsprivslevel.Savedlevel:%dCurrentlevel:%d\n""Occursin:\n%s\n",saved_uid,saved_g
id,new_uid,new_gid,p_level,privs_level,describe_backtrace(backtrace())));}privs_level=p_level;i
f(LOGP){catch{arraybt=backtrace();if(sizeof(bt)=2){report_notice(sprintf("Changebacktouid#%dgid
#%d,from%s\n",saved_uid,saved_gid,dbt(bt[-2])));}else{report_notice(sprintf("Changebacktouid#%d
gid#%d,frombackend\n",saved_uid,saved_gid));}};}if(getuid())return;#ifdefDEBUGintuid=geteuid();
if(uid!=new_uid){report_warning(sprintf("Privs:UID#%ddiffersfromexpected#%d\n""%s\n",uid,new_ui
d,describe_backtrace(backtrace())));}intgid=getegid();if(gid!=new_gid){report_warning(sprintf("
Privs:GID#%ddiffersfromexpected#%d\n""%s\n",gid,new_gid,describe_backtrace(backtrace())));}#end
if/*DEBUG*/seteuid(0);arrayu=getpwuid(saved_uid);#ifefun(cleargroups)catch{cleargroups();};#end
if/*cleargroups*/if(u(sizeof(u)3)){catch{initgroups(u[0],u[3]);};}setegid(saved_gid);seteuid(sa
ved_uid);#endif/*HAVE_EFFECTIVE_USER*/}#endif/*efun(seteuid)*/}/*Usedbyread_config.pike,sinceth
ereseemstobeproblemswith*overloadingotherwise.*/staticobjectPRIVS(stringr,int|string|voidu,int|
string|voidg){returnPrivs(r,u,g);}#ifdefMODULE_DEBUG#defineMD_PERROR(X)roxen_perrorX;#else#defi
neMD_PERROR(X)#endif/*MODULE_DEBUG*/#ifndefTHREADSclasscontainer{mixedvalue;mixedset(mixedto){r
eturnvalue=to;}mixedget(){returnvalue;}}#endif//LocalesupportLocale.Roxen.standarddefault_local
e=Locale.Roxen.standard;objectfonts;#ifconstant(thread_local)objectlocale=thread_local();#elseo
bjectlocale=container();#endif/*THREADS*/#defineLOCALELOW_LOCALE-base_serverprogramConfiguratio
n;/*setincreate*/arrayconfigurations=({});intdie_die_die;//FunctionthatactuallyshutsdownRoxen.(
seelow_shutdown).privatestaticvoidreally_low_shutdown(intexit_code){//Dienicely.#ifdefTHREADSca
tch(stop_handler_threads());#endif/*THREADS*/exit(exit_code);//Nowwedie...}//ShutdownRoxen//exi
t_code=0Trueshutdown//exit_code=-1Restartprivatestaticvoidlow_shutdown(intexit_code){catch{conf
igurations-stop();intpid;if(exit_code){roxen_perror("RestartingRoxen.\n");}else{roxen_perror("S
huttingdownRoxen.\n");//exit(0);}};call_out(really_low_shutdown,0.01,exit_code);}//Perhapssomew
hatmisnamed,really...Thisfunctionwillcloseall//listenportsandthenquit.The'start'scriptshouldthe
nstarta//newcopyofroxenautomatically.voidrestart(){low_shutdown(-1);}voidshutdown(){low_shutdow
n(0);}/**handle()stuff*/#ifndefTHREADS//handlefunctionusedwhenTHREADSisnotenabled.voidunthreade
d_handle(functionf,mixed...args){f(@args);}functionhandle=unthreaded_handle;#elsefunctionhandle
=threaded_handle;#endif/**THREADScodestartshere*/#ifdefTHREADS//#defineTHREAD_DEBUGobjectdo_thr
ead_create(stringid,functionf,mixed...args){objectt=thread_create(f,@args);catch(t-set_name(id)
);#ifdefTHREAD_DEBUGroxen_perror(id+"started\n");#endifreturnt;}//Queueofthingstohandle.//Anent
ryconsistsofanarray(functionfp,arrayargs)staticobject(Thread.Queue)handle_queue=Thread.Queue();
//Numberofhandlerthreadsthatarealive.staticintthread_reap_cnt;voidhandler_thread(intid){array(m
ixed)h,q;while(!die_die_die){