c08fd02000-10-04Per Hedbor object mm=(object)"/master"; inherit "/master": master;
4f74c82001-08-09Per Hedbor  mixed sql_query( string q, mixed ... e ) {
3114c62001-08-09Per Hedbor  return connect_to_my_mysql( 0, "local" )->query( q, @e );
4f74c82001-08-09Per Hedbor }
c08fd02000-10-04Per Hedbor 
a45b711997-03-07Henrik Grubbström (Grubba) /*
0c4ea12000-09-16Martin Nilsson  * Roxen's customized master.
a45b711997-03-07Henrik Grubbström (Grubba)  */
1250d11997-09-17Henrik Grubbström (Grubba) 
0917d32013-03-04Anders Johansson constant cvs_version = "$Id$";
63a8fe1997-03-01Henrik Grubbström (Grubba) 
ca2cb01999-12-09Henrik Grubbström (Grubba) // Disable the precompiled file is out of date warning. constant out_of_date_warning = 0;
8fe9062000-10-30Per Hedbor 
342c0f2001-09-03Marcus Comstedt #if !constant(PIKE_MODULE_RELOC) #define relocate_module(x) (x) #define unrelocate_module(x) (x) #endif
cb80e82009-12-28Martin Stjernholm protected string _sprintf (int flag) { return flag == 'O' && "roxen_master()"; }
8fe9062000-10-30Per Hedbor #define SECURITY_DEBUG 1 #include <security.h>
7ed6242009-06-10Henrik Grubbström (Grubba) #if !constant(master.master_file_stat) constant master_file_stat = predef::file_stat; constant master_get_dir = predef::get_dir; #endif
8fe9062000-10-30Per Hedbor  #ifdef SECURITY #if constant(thread_local)
fc40392008-08-15Martin Stjernholm protected object chroot_dir = thread_local();
8fe9062000-10-30Per Hedbor #else
fc40392008-08-15Martin Stjernholm protected string chroot_dir = "";
8fe9062000-10-30Per Hedbor #endif
fc40392008-08-15Martin Stjernholm protected void low_set_chroot_dir( string to )
8fe9062000-10-30Per Hedbor { #if constant(thread_local) chroot_dir->set( to ); #else chroot_dir = to; #endif }
fc40392008-08-15Martin Stjernholm protected string low_get_chroot_dir( )
8fe9062000-10-30Per Hedbor { #if constant(thread_local) return chroot_dir->get( ); #else return chroot_dir; #endif } class ChrootKey( string old_dir ) { void destroy( ) { low_set_chroot_dir( old_dir ); } } ChrootKey chroot( string to ) { CHECK_SECURITY_BIT( SECURITY ); ChrootKey key = ChrootKey( low_get_chroot_dir() ); low_set_chroot_dir( to ); return key; } class UID { inherit Creds;
fc40392008-08-15Martin Stjernholm  protected string _name; protected string _rname; protected int _uid, _gid; protected int _data_bits, _allow_bits; protected int io_bits = BIT_IO_CHROOT | BIT_IO_CAN_READ | BIT_IO_CAN_WRITE | BIT_IO_CAN_CREATE; protected string always_chroot;
8fe9062000-10-30Per Hedbor  constant modetobits = (["read":2, "write":4, ]); UID set_io_bits( int to ) { CHECK_SECURITY_BIT( SECURITY ); io_bits = to; return this_object(); } string chroot( string dir ) { always_chroot = dir; if( dir ) io_bits |= BIT_IO_CHROOT; // enforced chroot else io_bits &= BIT_IO_CHROOT; // enforced not chroot } int gid() { return _gid; } int uid() { return _uid; } /* Callback functions */ int valid_open( string dir, object current_object, string file, string mode, int access ) { string chroot_dir; file = combine_path( getcwd(), file ); #ifdef SECURITY_DEBUG werror("Security: valid_open( %O, %O, %o ) from %O\n", file, mode, access, current_object ); #endif if( (io_bits & BIT_IO_CHROOT) &&
e95e422000-11-02Per Hedbor  ((chroot_dir=always_chroot) || (chroot_dir=low_get_chroot_dir()))
8fe9062000-10-30Per Hedbor  && search( file, chroot_dir ) ) { #ifdef SECURITY_DEBUG werror("Security error: Chroot set, but this file is not in it\n"); #endif return 3; } if( !(io_bits & modetobits[ dir ] ) ) { #ifdef SECURITY_DEBUG werror("Security error: Lacks bit for %O\n", dir ); #endif return 3; } mixed stat; if( !(io_bits & BIT_IO_CAN_CREATE) && !(stat = file_stat( file ) ) ) { #ifdef SECURITY_DEBUG werror("Security error: File does not exist, and user lacks permisson for create\n"); #endif return 0; // No such file } else if( !stat ) stat = file_stat( file ); #ifndef __NT__ if( stat ) { if( (io_bits & BIT_IO_ONLY_OWNED) && (stat->uid != _uid) ) { #ifdef SECURITY_DEBUG werror("Security error: ONLY_OWNED but file not owned\n"); #endif return 3; } if( (io_bits & BIT_IO_OWNED_AND_GROUP) && (stat->uid != _uid) && (stat->gid != _gid) ) { #ifdef SECURITY_DEBUG werror("Security error: ONLY_GROUP_AND_OWNED but file not owned/nor group\n"); #endif return 3; } } if( !(io_bits & BIT_IO_USER_OK) ) { if( !stat ) { dir = "create"; stat = file_stat( dirname( file ) ); } if(!stat) { #ifdef SECURITY_DEBUG werror("Security error: File and directory both missing.\n"); #endif return 2; // Not possible... } // check permission for the operation here, using more or less // normal unix semantics. } #endif #ifdef SECURITY_DEBUG werror("Security: Open of %O ok\n", file ); #endif return 2; } int valid_io( string operation, string dir, mixed ... args ) { #ifdef SECURITY_DEBUG werror("valid_io( "+operation+", "+dir+" )\n" ); #endif if( !(io_bits & modetobits[ dir ] ) ) { #ifdef SECURITY_DEBUG werror("Security error: Lacks bit for %O\n", dir ); #endif return 0; } // switch( operation ) // { // // ... // } #ifdef SECURITY_DEBUG werror("Security: IO ok\n" ); #endif return 2; } Creds own( mixed what, int|void bits ) { Creds creds; if( !zero_type(bits) && (bits != get_data_bits()) ) creds = Creds( this_object(), get_allow_bits(), bits ); else creds = this_object(); creds->apply( what ); return creds; } mixed call( function what, mixed ... args ) { return call_with_creds( this_object(), what, @args ); } mixed call_with_bits( function what, int bits, mixed ... args ) { return call_with_creds( Creds( this_object(), bits, get_data_bits() ), what, @args ); } Creds get_new_creds( int allow_bits, int data_bits ) { return Creds( this_object(), allow_bits, data_bits ); } void create( string name, string rname, int uid, int gid, int allow_bits, int data_bits ) { _name = name; _rname = rname; _uid = uid; _gid = gid; ::create( this_object(), allow_bits, data_bits ); }
fc40392008-08-15Martin Stjernholm  protected string _sprintf( )
8fe9062000-10-30Per Hedbor  { return sprintf("UID( %s (%s) )",_name,_rname); } } void init_security() { werror("Initializing security system..."); add_constant( "chroot", chroot ); root->own( this_object() ); // root->call( Stdio.File, "/tmp/foo", "wct"); werror("Done\n"); } // There are three bit groups. // may_always bits // data bits (overridden by may_always of current user) // io bits (used in valid_io and valid_open) // The root user can do everything. But objects owned by it cannot be // destructed by anyone but the root user. UID root = UID( "root", "Supersture",0,0, ~0, ~BIT_DESTRUCT ); // The nobody user cannot do anything, basically (it can read/stat files, though) UID nobody = UID( "nobody", "Nobody", 65535,65535, BIT_CONDITIONAL_IO, ~0 ) ->set_io_bits( BIT_IO_CHROOT | BIT_IO_CAN_READ ); // Default roxen user. Basically the same as the root user, but the IO bits apply. // More specifically, the chroot() function works. UID roxen = UID( "roxen", "Roxen internal user", getuid(), getgid(), ~BIT_SECURITY, ~BIT_DESTRUCT ); // Like nobody, but cannot read files either. UID luser = UID( "luser", "total luser", 65535, 65535, 0, 0 ); #else void init_security() { add_constant( "chroot", lambda(string new){ return class{}(); } ); } #endif
ca2cb01999-12-09Henrik Grubbström (Grubba) 
2cff132008-08-08Martin Stjernholm #ifdef ENABLE_DUMPING
c964de2001-03-29Per Hedbor mapping dump_constants = ([]), dump_constants_rev = ([]);
c11dbc2002-05-06Martin Stjernholm // These reverse mapping are not only for speed; we use mapping // lookups to avoid calling the clever `== that objects might contain. // E.g. Image.Color.black thinks it's equal to 0, which means that // search (all_constants(), Image.Color.black) == "UNDEFINED".
fc40392008-08-15Martin Stjernholm protected mapping(mixed:string) all_constants_rev = ([]); protected mapping(program:string) all_constants_object_program_rev = ([]); protected mapping(mixed:string) __builtin_rev =
c11dbc2002-05-06Martin Stjernholm  mkmapping (values (__builtin), indices (__builtin));
fc40392008-08-15Martin Stjernholm protected mapping(mixed:string) _static_modules_rev =
c11dbc2002-05-06Martin Stjernholm  mkmapping (values (_static_modules), indices (_static_modules));
c964de2001-03-29Per Hedbor  mixed add_dump_constant( string f, mixed what ) { if(!what) return 0; dump_constants_rev[ dump_constants[ f ] = what ] = f; catch(dump_constants_rev[ (program)what ] = f); return what; }
03b0cc2004-08-18Martin Stjernholm void unregister(program p) { m_delete (all_constants_object_program_rev, p); ::unregister (p); }
4cd4122003-09-09Martin Stjernholm #if defined (DUMP_DEBUG_LOG) && !defined (DUMP_DEBUG) #define DUMP_DEBUG #endif
e48d2d2002-05-02Martin Stjernholm #ifdef DUMP_DEBUG
4cd4122003-09-09Martin Stjernholm int dump_debug_indent = 0; #ifdef DUMP_DEBUG_LOG #define DD_MSG(X...) werror (({X}) * "") #else #define DD_MSG(X...) log->add (X) #endif #define DUMP_DEBUG_ENTER(X...) do { \ DD_MSG (" " * dump_debug_indent++, sprintf (X)); \ } while (0) #define DUMP_DEBUG_MSG(X...) do { \ DD_MSG (" " * dump_debug_indent, sprintf (X)); \ } while (0)
e48d2d2002-05-02Martin Stjernholm #define DUMP_DEBUG_RETURN(val) do { \ mixed _v__ = (val); \
4cd4122003-09-09Martin Stjernholm  DD_MSG (" " * --dump_debug_indent, \ "returned ", \ zero_type (_v__) ? "UNDEFINED" : sprintf ("%O", _v__), \ "\n"); \
e48d2d2002-05-02Martin Stjernholm  return _v__; \ } while (0) #else #define DUMP_DEBUG_ENTER(X...) do {} while (0)
4cd4122003-09-09Martin Stjernholm #define DUMP_DEBUG_MSG(X...) do {} while (0)
e48d2d2002-05-02Martin Stjernholm #define DUMP_DEBUG_RETURN(val) do return (val); while (0) #endif
b775a71999-11-24Per Hedbor class MyCodec { program p;
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG mixed last_failed;
e48d2d2002-05-02Martin Stjernholm  String.Buffer log = String.Buffer();
c964de2001-03-29Per Hedbor #endif
e48d2d2002-05-02Martin Stjernholm 
fc40392008-08-15Martin Stjernholm  protected mapping(program:string) nameof_program_cache = ([]); protected string nameof_program(program prog)
df6ec62003-01-15Henrik Grubbström (Grubba)  { string res; DUMP_DEBUG_ENTER("nameof_program(%O)\n", prog); if (prog == p) DUMP_DEBUG_RETURN(UNDEFINED); if (res = nameof_program_cache[prog]) DUMP_DEBUG_RETURN(res); res = sprintf("%O", prog); if (prog == resolv(res)) { DUMP_DEBUG_RETURN("resolv:" + res); }
4cd4122003-09-09Martin Stjernholm  if (res == "master().dirnode") error("Encoding dirnode program.\n");
a8dbf32003-02-03Henrik Grubbström (Grubba) #if constant(function_program)
df6ec62003-01-15Henrik Grubbström (Grubba)  program parent = function_program(prog);
a8dbf32003-02-03Henrik Grubbström (Grubba) #else /* !constant(function_program) */
ec2cda2003-02-04Henrik Grubbström (Grubba)  object parent_obj = functionp(prog) && function_object(prog);
c9a9142003-02-04Henrik Grubbström (Grubba)  program parent = parent_obj && object_program(parent_obj);
a8dbf32003-02-03Henrik Grubbström (Grubba) #endif /* constant(function_program) */
4cd4122003-09-09Martin Stjernholm  DUMP_DEBUG_MSG("parent:%O\n", parent);
df6ec62003-01-15Henrik Grubbström (Grubba)  if (parent && (parent != p)) { string name = function_name(prog);
4cd4122003-09-09Martin Stjernholm  DUMP_DEBUG_MSG("name:%O\n", name);
df6ec62003-01-15Henrik Grubbström (Grubba)  if (name) { if (res = all_constants_object_program_rev[parent]) { res = "efun:" + res + "\0" + name; nameof_program_cache[prog] = res; DUMP_DEBUG_RETURN(res); } if ((objects[parent]) && (res = nameof(objects[parent]))) { res += "\0" + name; nameof_program_cache[prog] = res; DUMP_DEBUG_RETURN(res); } if ((prog == parent[name]) && (res = nameof_program(parent))) { if (programs[res]) { res += "\0" + name; } else { res += "\0" + name; } nameof_program_cache[prog] = res; DUMP_DEBUG_RETURN(res); } } }
03b0cc2004-08-18Martin Stjernholm  if(string tmp = programs_reverse_lookup (prog)) {
df6ec62003-01-15Henrik Grubbström (Grubba)  nameof_program_cache[prog] = tmp; DUMP_DEBUG_RETURN(tmp); } DUMP_DEBUG_RETURN(UNDEFINED); }
b775a71999-11-24Per Hedbor  string nameof(mixed x) {
e48d2d2002-05-02Martin Stjernholm #ifdef DUMP_DEBUG
df6ec62003-01-15Henrik Grubbström (Grubba)  string type_str = ""; if (objectp(x)) type_str="object "; else if (functionp(x)) type_str="function "; else if (programp(x)) type_str="program "; DUMP_DEBUG_ENTER("nameof (%s%O)\n", type_str, x);
e48d2d2002-05-02Martin Stjernholm #endif
b775a71999-11-24Per Hedbor  if(p!=x)
c964de2001-03-29Per Hedbor  { if( string n = dump_constants_rev[ x ] )
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN ("defun:"+n);
e1b32f2002-04-18Henrik Grubbström (Grubba) 
df6ec62003-01-15Henrik Grubbström (Grubba)  if (sizeof (all_constants()) != sizeof (all_constants_rev)) {
c11dbc2002-05-06Martin Stjernholm  // We assume that all_constants() doesn't shrink. all_constants_rev = mkmapping (values (all_constants()), indices (all_constants()));
df6ec62003-01-15Henrik Grubbström (Grubba)  all_constants_object_program_rev = ([]); foreach(indices(all_constants()), string sym) { mixed val = all_constants()[sym]; if (objectp(val)) { all_constants_object_program_rev[object_program(val)] = sym; } } }
e1b32f2002-04-18Henrik Grubbström (Grubba) 
c11dbc2002-05-06Martin Stjernholm  if (string name = all_constants_rev[x]) DUMP_DEBUG_RETURN ("efun:" + name); if (string name = __builtin_rev[x]) DUMP_DEBUG_RETURN ("resolv:__builtin." + name); if (string name = _static_modules_rev[x]) DUMP_DEBUG_RETURN ("resolv:_static_modules." + name);
e1b32f2002-04-18Henrik Grubbström (Grubba) 
c964de2001-03-29Per Hedbor  if ( programp (x) )
4942b72000-03-20Martin Stjernholm  {
df6ec62003-01-15Henrik Grubbström (Grubba)  mixed tmp; if (tmp = nameof_program(x)) { DUMP_DEBUG_RETURN(tmp); }
b775a71999-11-24Per Hedbor 
c964de2001-03-29Per Hedbor  if( (program)x != x )
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN (nameof( (program)x ));
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG last_failed = x; #endif
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN (([])[ 0 ]);
4942b72000-03-20Martin Stjernholm  } }
c964de2001-03-29Per Hedbor  if (objectp (x))
992e152000-04-11Per Hedbor  {
4942b72000-03-20Martin Stjernholm  array(string) ids = ({});
08bb502000-05-13Martin Stjernholm  if(x->is_resolv_dirnode)
992e152000-04-11Per Hedbor  { /* FIXME: this is a bit ad-hoc */ string dirname=x->dirname; dirname-=".pmod"; sscanf(dirname,"%*smodules/%s",dirname); dirname=replace(dirname,"/","."); if(resolv(dirname) == x)
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN ("resolv:"+dirname);
992e152000-04-11Per Hedbor  }
c11dbc2002-05-06Martin Stjernholm  while (1)
992e152000-04-11Per Hedbor  {
03b0cc2004-08-18Martin Stjernholm  if(program p = objects_reverse_lookup (x))
b775a71999-11-24Per Hedbor  {
03b0cc2004-08-18Martin Stjernholm  if(string pname = programs_reverse_lookup (p))
b775a71999-11-24Per Hedbor  {
03b0cc2004-08-18Martin Stjernholm  if (sizeof (ids)) DUMP_DEBUG_RETURN (pname + "\0" + ids * "\0"); else DUMP_DEBUG_RETURN (pname);
4942b72000-03-20Martin Stjernholm  } }
c11dbc2002-05-06Martin Stjernholm 
4942b72000-03-20Martin Stjernholm  object parent; if (!catch (parent = function_object (object_program (x))) && parent) {
c11dbc2002-05-06Martin Stjernholm  mapping(mixed:string) rev = mkmapping (values (parent), indices (parent)); // Use a mapping since objects with tricky `== can fool // search(). (Objects with tricky __hash are a bit more // uncommon and less prone to consider the object to be // equal to a string or an integer or whatnot.) if (string id = rev[x]) {
4942b72000-03-20Martin Stjernholm  x = parent;
c11dbc2002-05-06Martin Stjernholm  ids = ({id}) + ids;
4942b72000-03-20Martin Stjernholm  continue;
b775a71999-11-24Per Hedbor  } } break;
4942b72000-03-20Martin Stjernholm  }
c11dbc2002-05-06Martin Stjernholm 
4942b72000-03-20Martin Stjernholm  if( x == mm )
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN ("/master");
b775a71999-11-24Per Hedbor  }
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG last_failed = x; #endif
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_RETURN (([])[0]);
b775a71999-11-24Per Hedbor  }
fc40392008-08-15Martin Stjernholm  protected mixed low_lookup(string x, void|int is_prog)
b775a71999-11-24Per Hedbor  {
df6ec62003-01-15Henrik Grubbström (Grubba)  array(string) segments = x/"\0";
c11dbc2002-05-06Martin Stjernholm  string s;
df6ec62003-01-15Henrik Grubbström (Grubba)  mixed part = UNDEFINED; x = segments[0];
c11dbc2002-05-06Martin Stjernholm  if (sscanf(x,"defun:%s",s)) {
df6ec62003-01-15Henrik Grubbström (Grubba)  part = dump_constants[s];
c11dbc2002-05-06Martin Stjernholm  } else if (sscanf(x,"efun:%s",s)) {
df6ec62003-01-15Henrik Grubbström (Grubba)  part = all_constants()[s];
c11dbc2002-05-06Martin Stjernholm  } else if (sscanf(x,"resolv:%s",s)) {
df6ec62003-01-15Henrik Grubbström (Grubba)  part = resolv(s); } else {
d863782003-02-04Henrik Grubbström (Grubba)  if (is_prog && sizeof(segments) == 1) { part = (program)x; } else { part = (object)x; }
c11dbc2002-05-06Martin Stjernholm  }
df6ec62003-01-15Henrik Grubbström (Grubba)  foreach(segments[1..], string id) { if (zero_type(part = part[id])) error("Failed to decode symbol %O\n", segments * "\0" ); } return part||UNDEFINED; } function functionof(string x) { DUMP_DEBUG_ENTER ("functionof (%O)\n", x); mixed res = low_lookup(x); if (functionp(res)) DUMP_DEBUG_RETURN(res); error("Failed to decode function %s:%O\n", x, res);
b775a71999-11-24Per Hedbor  } object objectof(string x) {
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_ENTER ("objectof (%O)\n", x);
df6ec62003-01-15Henrik Grubbström (Grubba)  mixed res = low_lookup(x); if (objectp(res)) DUMP_DEBUG_RETURN(res); error("Failed to decode object %s:%O\n", x, res );
b775a71999-11-24Per Hedbor  } program programof(string x) {
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_ENTER ("programof (%O)\n", x);
d863782003-02-04Henrik Grubbström (Grubba)  mixed res = low_lookup(x, 1);
df6ec62003-01-15Henrik Grubbström (Grubba)  if (programp(res) || objectp(res)) DUMP_DEBUG_RETURN(res); error("Failed to decode program %s:%O\n", x, res );
b775a71999-11-24Per Hedbor  } mixed encode_object(object x) {
e48d2d2002-05-02Martin Stjernholm  DUMP_DEBUG_ENTER ("encode_object (%s)\n", objectp (x) ? "object " + Program.defined (object_program (x)) : sprintf ("%O", x)); if(x->_encode) DUMP_DEBUG_RETURN (x->_encode()); error("Cannot encode objects without _encode.\n");
b775a71999-11-24Per Hedbor  }
4cd4122003-09-09Martin Stjernholm  void decode_object(object x, mixed data)
b775a71999-11-24Per Hedbor  {
4cd4122003-09-09Martin Stjernholm  DUMP_DEBUG_MSG ("decode_object (%s, %O)\n", objectp (x) ? "object " + Program.defined (object_program (x)) : sprintf ("%O", x), data);
992e152000-04-11Per Hedbor  if( x->_decode ) x->_decode(data); else
e48d2d2002-05-02Martin Stjernholm  error("Cannot decode objects without _decode.\n");
b775a71999-11-24Per Hedbor  }
7a831d2000-02-14Per Hedbor  void create( program|void q )
b775a71999-11-24Per Hedbor  { p = q; } }
2cff132008-08-08Martin Stjernholm #else // !ENABLE_DUMPING mixed add_dump_constant( string f, mixed what ) { return what; } #endif
16693b1999-10-08Per Hedbor 
2cff132008-08-08Martin Stjernholm #if 0
53a4532000-05-24Martin Stjernholm #ifdef __NT__ string getcwd() { return replace (::getcwd(), "\\", "/"); } #endif
2cff132008-08-08Martin Stjernholm #endif
0ee0851997-02-08Per Hedbor 
58faac1999-12-27Martin Stjernholm mapping(program:string) program_names = set_weak_flag (([]), 1);
2cff132008-08-08Martin Stjernholm #ifdef ENABLE_DUMPING
b775a71999-11-24Per Hedbor string make_ofilename( string from ) {
74e3902000-12-30Per Hedbor  return sprintf( "%s-%x", ((from/"/")[-1]/".")[0],hash(from));
b775a71999-11-24Per Hedbor } void dump_program( string pname, program what ) {
74e3902000-12-30Per Hedbor  string index = make_ofilename( pname );
ee28622000-04-06Leif Stensson  string data;
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG MyCodec cd;
c11dbc2002-05-06Martin Stjernholm  int test_decode = 0;
4cd4122003-09-09Martin Stjernholm  int save_dump_debug_indent = dump_debug_indent; dump_debug_indent = 0;
e1b32f2002-04-18Henrik Grubbström (Grubba)  mixed err;
c11dbc2002-05-06Martin Stjernholm  if (!(err = catch (data = encode_value( what, (cd = MyCodec( what )) ) )) && !(cd->log->add ("****** Encode ok, testing decode:\n"), test_decode = 1, err = catch (decode_value (data, cd))))
31c2ca2000-04-06Leif Stensson #else data = encode_value( what, MyCodec( what ) ); #endif
74e3902000-12-30Per Hedbor  {
4f74c82001-08-09Per Hedbor  sql_query( "DELETE FROM precompiled_files WHERE id=%s",index ); sql_query( "INSERT INTO precompiled_files values (%s,%s,%d)",
49d0912001-08-09Per Hedbor  index, data, time(1) );
c11dbc2002-05-06Martin Stjernholm #ifdef DUMP_DEBUG werror ("Stored in sql with timestamp %d: %O\n", time(1), index); #endif
ee28622000-04-06Leif Stensson  }
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG
ee28622000-04-06Leif Stensson  else
74e3902000-12-30Per Hedbor  { array parts = pname / "/";
ee28622000-04-06Leif Stensson  if (sizeof(parts) > 3) parts = parts[sizeof(parts)-3..];
c11dbc2002-05-06Martin Stjernholm  if (test_decode) werror ("Couldn't decode dump of " + parts * "/" + " \n"); else werror("Couldn't dump " + parts * "/" + "\n");
e48d2d2002-05-02Martin Stjernholm  werror("Codec log:\n%s", cd->log->get());
c11dbc2002-05-06Martin Stjernholm  werror("Last recursively encoded: %O\n", cd->last_failed );
c964de2001-03-29Per Hedbor  mixed w = Describer()->describe( cd->last_failed,10000 ); if( w == "program" ) w = _typeof( cd->last_failed ); werror( " Type: %O\n",w);
c11dbc2002-05-06Martin Stjernholm  werror("Error: %s", describe_backtrace(err));
c964de2001-03-29Per Hedbor  werror("\n");
ee28622000-04-06Leif Stensson  }
4cd4122003-09-09Martin Stjernholm  dump_debug_indent = save_dump_debug_indent;
31c2ca2000-04-06Leif Stensson #endif
f9c95a2000-01-30Per Hedbor }
b775a71999-11-24Per Hedbor 
2cff132008-08-08Martin Stjernholm #endif // ENABLE_DUMPING
0ab5871999-11-24Per Hedbor int loaded_at( program p ) {
58faac1999-12-27Martin Stjernholm  return load_time[ program_name (p) ];
f9c95a2000-01-30Per Hedbor }
0ab5871999-11-24Per Hedbor 
74e3902000-12-30Per Hedbor // array(string) query_precompiled_names(string fname) // { // return ({ make_ofilename(fname) }) + ::query_precompiled_names(fname); // }
5736bf1999-11-26Henrik Grubbström (Grubba) 
74e3902000-12-30Per Hedbor mapping(string:function|int) has_set_on_load = ([]);
8514832000-11-27Per Hedbor void set_on_load( string f, function cb ) { has_set_on_load[ f ] = cb; }
d4bd032003-06-02Martin Stjernholm program low_findprog(string pname, string ext, object|void handler, void|int mkobj)
beb69c1997-04-14Per Hedbor {
a3df231999-11-23Per Hedbor  program ret;
ce4f492003-06-24Henrik Grubbström (Grubba)  Stat s;
a3df231999-11-23Per Hedbor  string fname=pname+ext;
beb69c1997-04-14Per Hedbor 
342c0f2001-09-03Marcus Comstedt #if constant(PIKE_MODULE_RELOC) fname = unrelocate_module(fname); #endif
4291932004-06-17Martin Stjernholm #if 0 // No idea what this is supposed to accomplish, but the effect is // that the ErrorContainer can be stored as handler in dirnodes and // receive error messages long after the function that installed it // have checked for error messages and forgotten about it. /mast
2f79202000-03-27Per Hedbor  if( !handler ) handler = get_inhibit_compile_errors();
4291932004-06-17Martin Stjernholm #endif
2f79202000-03-27Per Hedbor 
342c0f2001-09-03Marcus Comstedt  if( (s=master_file_stat( relocate_module(fname) )) && s[1]>=0 )
beb69c1997-04-14Per Hedbor  {
d930992018-08-21Henrik Grubbström (Grubba)  object compiler_lock = DefaultCompilerEnvironment->lock();
8749922005-11-09Henrik Grubbström (Grubba)  if( load_time[ fname ] >= s[ 3 ] )
25c4991999-12-29Martin Stjernholm  if( !zero_type (ret = programs[fname]) ) return ret;
2a01c71997-02-11Per Hedbor 
a3df231999-11-23Per Hedbor  switch(ext) { case "": case ".pike":
74e3902000-12-30Per Hedbor  // First check in mysql. #ifdef DUMP_DEBUG #define DUMP_WARNING(fname,err) \ werror("Failed to decode dumped file for %s: %s", \ trim_file_name (fname), describe_error(err));
e48d2d2002-05-02Martin Stjernholm #define DDEBUG( X... ) werror( X )
74e3902000-12-30Per Hedbor #else #define DUMP_WARNING(f,e)
e48d2d2002-05-02Martin Stjernholm #define DDEBUG( X... )
74e3902000-12-30Per Hedbor #endif
c11dbc2002-05-06Martin Stjernholm 
2cff132008-08-08Martin Stjernholm #ifdef ENABLE_DUMPING
74e3902000-12-30Per Hedbor #define LOAD_DATA( DATA ) \ do { \ mixed err = catch \ { \
8749922005-11-09Henrik Grubbström (Grubba)  load_time[ fname ] = s[3]; \
74e3902000-12-30Per Hedbor  programs[ fname ] = 0; \ ret = programs[ fname ] = decode_value( DATA, MyCodec() ); \ program_names[ ret ] = fname; \ m_delete(has_set_on_load, fname ); \ return ret; \ }; DUMP_WARNING(fname,err) \ } while(0)
df6ec62003-01-15Henrik Grubbström (Grubba) #define LOAD_OFILE( DATA ) \ do { \ mixed err = catch \ { \
8749922005-11-09Henrik Grubbström (Grubba)  load_time[ fname ] = s[3]; \
df6ec62003-01-15Henrik Grubbström (Grubba)  programs[ fname ] = 0; \ ret = programs[ fname ] = decode_value( DATA, Codec() ); \ program_names[ ret ] = fname; \ m_delete(has_set_on_load, fname ); \ return ret; \ }; DUMP_WARNING(fname,err) \ } while(0)
2cff132008-08-08Martin Stjernholm  array q;
4f74c82001-08-09Per Hedbor  if(sizeof(q=sql_query( "SELECT data,mtime FROM precompiled_files WHERE id=%s",
c11dbc2002-05-06Martin Stjernholm  make_ofilename( fname )))) {
8749922005-11-09Henrik Grubbström (Grubba)  if( (int)q[0]->mtime >= s[3] ) {
c11dbc2002-05-06Martin Stjernholm  DDEBUG ("Loading dump from sql: %O\n", make_ofilename( fname )); LOAD_DATA( q[0]->data ); } else DDEBUG ("Ignored stale dump in sql, timestamp %d vs %d: %O\n", (int)q[0]->mtime, s[3], make_ofilename( fname )); }
74e3902000-12-30Per Hedbor 
f9c95a2000-01-30Per Hedbor  foreach(query_precompiled_names(fname), string ofile )
ce4f492003-06-24Henrik Grubbström (Grubba)  if(Stat s2=master_file_stat( ofile ))
b775a71999-11-24Per Hedbor  if(s2[1]>0 && s2[3]>=s[3])
df6ec62003-01-15Henrik Grubbström (Grubba)  LOAD_OFILE( Stdio.File( ofile,"r")->read() );
74e3902000-12-30Per Hedbor 
2cff132008-08-08Martin Stjernholm #endif // ENABLE_DUMPING
e48d2d2002-05-02Martin Stjernholm  DDEBUG( "Really compile: %O\n", fname );
c964de2001-03-29Per Hedbor #ifdef DUMP_DEBUG int t = gethrtime(); #endif
8749922005-11-09Henrik Grubbström (Grubba)  load_time[fname] = s[3];
d4bd032003-06-02Martin Stjernholm #if constant (__empty_program) programs[fname]=ret=__empty_program(0, fname); #endif if ( mixed e=catch { ret=compile_file(fname, handler, #if constant (__empty_program) ret, mkobj ? (objects[ret] = __null_program()) : 0 #endif ); } )
a3df231999-11-23Per Hedbor  {
8749922005-11-09Henrik Grubbström (Grubba)  // load_time[fname] = s[3]; not here, no.... reload breaks miserably
0cd1892000-07-12Martin Stjernholm  // // Yes indeed here. How else avoid many many recompilations of // a module that's broken and referenced from a gazillion // places? This also avoids the dreaded infinite loop during // compilation that could occur with misspelled identifiers in // pike modules. /mast
d4bd032003-06-02Martin Stjernholm  ret=programs[fname]=0;
7c6f372007-05-09Henrik Grubbström (Grubba)  mixed err = catch { if(arrayp(e) && (sizeof(e)>1) && (<"Compilation failed.\n", "Cpp() failed\n">)[e[0]]) e[1]=({}); }; if (err) { werror("Failed to truncate backtrace!\n"); }
e48d2d2002-05-02Martin Stjernholm  DDEBUG( "Compile FAILED: %O\n",fname );
48e5d92000-01-05Martin Stjernholm  throw(e);
a3df231999-11-23Per Hedbor  }
e48d2d2002-05-02Martin Stjernholm  DDEBUG( "Compile took %dms: %O\n", (gethrtime()-t)/1000, fname );
74e3902000-12-30Per Hedbor  function f; if( functionp( f = has_set_on_load[ fname ] ) ) { has_set_on_load[ fname ] = 1; call_out(f,0.1,fname, ret ); } else has_set_on_load[ fname ] = 1;
a3df231999-11-23Per Hedbor  break; #if constant(load_module) case ".so":
342c0f2001-09-03Marcus Comstedt  ret=load_module(relocate_module(fname));
fb74971997-09-16Per Hedbor #endif
a3df231999-11-23Per Hedbor  }
58faac1999-12-27Martin Stjernholm  program_names[ret] = fname;
d4bd032003-06-02Martin Stjernholm  if( !ret ) m_delete (load_time, fname);
a3df231999-11-23Per Hedbor  return programs[fname] = ret; }
25c4991999-12-29Martin Stjernholm  return 0;
cdf0b91999-11-24Per Hedbor }
c9704c2012-11-08Henrik Grubbström (Grubba) program cast_to_program(string pname, string current_file, object|void handler)
c0e75c2002-03-04Martin Stjernholm {
c9704c2012-11-08Henrik Grubbström (Grubba)  if (has_prefix(pname, "roxen-module://")) { pname = pname[sizeof("roxen-module://")..]; object modinfo = roxenp()->find_module(pname); if (!modinfo) return 0; pname = modinfo->filename; } else if (has_prefix(pname, "roxen-path://")) {
3f3d7d2010-01-13Jonas Wallden  // Expand variables such as $SERVERDIR and $LOCALDIR if we have // roxen_path() available. pname = pname[sizeof("roxen-path://")..];
c9704c2012-11-08Henrik Grubbström (Grubba)  function roxen_path_fn = all_constants()["roxen_path"]; if (!roxen_path_fn) return 0; pname = roxen_path_fn(pname);
3f3d7d2010-01-13Jonas Wallden  }
c9704c2012-11-08Henrik Grubbström (Grubba)  return ::cast_to_program(pname, current_file, handler);
c0e75c2002-03-04Martin Stjernholm }
b599392000-01-05Martin Stjernholm void handle_error(array(mixed)|object trace) {
db6e7d2012-02-18Martin Stjernholm  werror ("Internal server error: ");
b599392000-01-05Martin Stjernholm  ::handle_error (trace); }
218f582009-12-28Martin Stjernholm void compile_warning(string file,int line,string err) { if (!line) { // Ugly way to detect the appropriate warning made by the pike master. int i = search (err, "Decode failed:"); if (i >= 0) { // Can get errors when decoding the dumped modules that come with pike // since there are various resolver differences. E.g. the exit efun is // replaced with a pike function in roxenloader.pike, and decode_value // cannot handle that difference. Let's just make a little bit of noise // in debug mode. #ifdef DEBUG werror ("Debug notice: Failed to decode %s:%s\n", file, err[i + sizeof ("Decode failed:")..]); #endif return; } } ::compile_warning (file, line, err); }
0f61e72000-08-15Martin Stjernholm void clear_compilation_failures() { foreach (indices (programs), string fname) if (!programs[fname]) m_delete (programs, fname); }
6d36e51999-11-24Per Hedbor int refresh( program p, int|void force )
0ee0851997-02-08Per Hedbor {
a3df231999-11-23Per Hedbor  string fname = program_name( p );
2f79202000-03-27Per Hedbor  if(!fname) { return 1; /* Not loaded.. */ }
6d36e51999-11-24Per Hedbor  if( force ) { m_delete( programs, fname );
2f79202000-03-27Per Hedbor  m_delete( load_time, fname );
2cff132008-08-08Martin Stjernholm #ifdef ENABLE_DUMPING
4f74c82001-08-09Per Hedbor  sql_query( "DELETE FROM precompiled_files WHERE id=%s", make_ofilename(fname) );
2cff132008-08-08Martin Stjernholm #endif
6d36e51999-11-24Per Hedbor  return 1; }
ce4f492003-06-24Henrik Grubbström (Grubba)  Stat s=master_file_stat( fname );
6d36e51999-11-24Per Hedbor  if( s && s[1]>=0 ) {
aa9b1c2005-11-14Jonas Wallden  if( load_time[ fname ] >= s[ 3 ] )
a3df231999-11-23Per Hedbor  return 0;
6d36e51999-11-24Per Hedbor  }
2f79202000-03-27Per Hedbor  else return -1; /* No such file... */
6d36e51999-11-24Per Hedbor  m_delete( programs, fname );
2f79202000-03-27Per Hedbor  m_delete( load_time, fname );
2cff132008-08-08Martin Stjernholm #ifdef ENABLE_DUMPING
4f74c82001-08-09Per Hedbor  sql_query( "DELETE FROM precompiled_files WHERE id=%s", make_ofilename(fname));
2cff132008-08-08Martin Stjernholm #endif
a3df231999-11-23Per Hedbor  return 1;
0ee0851997-02-08Per Hedbor }
6d36e51999-11-24Per Hedbor int recursively_check_inherit_time(program root, array up, mapping done) {
b86de82000-11-13Per Hedbor  catch { int res; if( done[ root ]++ ) return 0;
f9c95a2000-01-30Per Hedbor 
b86de82000-11-13Per Hedbor  foreach( Program.inherit_list( root ), program p ) res+=recursively_check_inherit_time( p, up+({root}), done );
6d36e51999-11-24Per Hedbor 
b86de82000-11-13Per Hedbor  if( !res && (refresh( root )>0 )) { res++; map( up+({root}), refresh, 1 ); }
6d36e51999-11-24Per Hedbor 
b86de82000-11-13Per Hedbor  return res; };
6d36e51999-11-24Per Hedbor } int refresh_inherit( program what ) { int ret = recursively_check_inherit_time( what, ({}), ([]) );; return ret; }
a3df231999-11-23Per Hedbor string program_name(program p)
0ee0851997-02-08Per Hedbor {
58faac1999-12-27Martin Stjernholm  return program_names[p];
b1fca01996-11-12Per Hedbor }
6d36e51999-11-24Per Hedbor void name_program( program p, string name ) {
8749922005-11-09Henrik Grubbström (Grubba)  if (programs[name]) { if (programs[name] == p) return; if (rev_programs && (rev_programs[programs[name]] == name)) { m_delete(rev_programs, programs[name]); } m_delete(programs, name); } string t = programs_reverse_lookup(p); load_time[name] = t?load_time[t]:time(1);
6d36e51999-11-24Per Hedbor  programs[name] = p; }
ca2cb01999-12-09Henrik Grubbström (Grubba) constant bt_max_string_len = 99999999;
5b77871999-11-23Per Hedbor string describe_backtrace(mixed trace, void|int linewidth) {
568b812001-12-04Martin Stjernholm  return predef::describe_backtrace(trace, 999999);
5b77871999-11-23Per Hedbor }
63a8fe1997-03-01Henrik Grubbström (Grubba) void create() {
a529d11998-04-29Henrik Grubbström (Grubba)  object o = this_object();
a45b711997-03-07Henrik Grubbström (Grubba)  /* Copy variables from the original master */
9047251997-03-02Henrik Grubbström (Grubba)  foreach(indices(mm), string varname) {
a529d11998-04-29Henrik Grubbström (Grubba)  catch(o[varname] = mm[varname]);
9047251997-03-02Henrik Grubbström (Grubba)  /* Ignore errors when copying functions */ }
a3df231999-11-23Per Hedbor 
8fe9062000-10-30Per Hedbor  init_security();
a3df231999-11-23Per Hedbor  foreach( indices(programs), string f )
8749922005-11-09Henrik Grubbström (Grubba)  load_time[f] = load_time[f] || time(1);
a3df231999-11-23Per Hedbor 
4b62e21998-04-29Henrik Grubbström (Grubba)  programs["/master"] = object_program(o);
58faac1999-12-27Martin Stjernholm  program_names[object_program(o)] = "/master";
a3df231999-11-23Per Hedbor  objects[ object_program(o) ] = o;
a529d11998-04-29Henrik Grubbström (Grubba)  /* Move the old efuns to the new object. */
a3df231999-11-23Per Hedbor 
0968b02007-01-12Martin Stjernholm  // To be able to inherit various classes in the master, e.g. codecs. add_constant ("Master", this);
c964de2001-03-29Per Hedbor  add_constant("add_dump_constant", add_dump_constant);
a3df231999-11-23Per Hedbor  foreach(master_efuns, string e) add_constant(e, o[e]);
ffd9551997-01-20David KÃ¥gedal }
d9c0412008-06-12Henrik Grubbström (Grubba)  #if __REAL_VERSION__ >= 7.7 local object get_compat_master(int major, int minor) { if ((major > __MAJOR__) || ((major == __MAJOR__) && (minor >= __MINOR__))) { // Disable the compat master stuff for the default compatibility level // or better, since otherwise the main Roxen code won't get at our // added functions. return this; } return ::get_compat_master(major, minor); } #endif