Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:171: Inside #if defined(THREADS)
     void name_thread( object thread, string name )   {    string th_key = sprintf("%O", thread);    if (name)    thread_names[th_key] = name;    else    m_delete(thread_names, th_key);   }    - // This mutex is used by Privs - Thread.Mutex euid_egid_lock = Thread.Mutex(); +    #endif /* THREADS */    - /* -  * The privilege changer. Works like a mutex lock, but changes the UID/GID -  * while held. Blocks all threads. -  * -  * Based on privs.pike,v 1.36. -  */ - int privs_level; -  - protected class Privs - { - #if constant(seteuid) -  -  int saved_uid; -  int saved_gid; -  -  int new_uid; -  int new_gid; -  - #define LOGP (variables && variables->audit && variables->audit->query()) -  - #if constant(geteuid) && constant(getegid) && constant(seteuid) && constant(setegid) - #define HAVE_EFFECTIVE_USER - #endif -  -  private string _getcwd() -  { -  if (catch{return(getcwd());}) { -  return("Unknown directory (no x-bit on current directory?)"); -  } -  } -  -  private string dbt(array t) -  { -  if(!arrayp(t) || (sizeof(t)<2)) return ""; -  return (((t[0]||"Unknown program")-(_getcwd()+"/"))-"base_server/")+":"+t[1]+"\n"; -  } -  - #ifdef THREADS -  protected mixed mutex_key; // Only one thread may modify the euid/egid at a time. -  protected object threads_disabled; - #endif /* THREADS */ -  -  int p_level; -  -  void create(string reason, int|string|void uid, int|string|void gid) -  { -  // No need for Privs if the uid has been changed permanently. -  if(getuid()) return; -  - #ifdef PRIVS_DEBUG -  report_debug(sprintf("Privs(%O, %O, %O)\n" -  "privs_level: %O\n", -  reason, uid, gid, privs_level)); - #endif /* PRIVS_DEBUG */ -  - #ifdef HAVE_EFFECTIVE_USER -  array u; -  - #ifdef THREADS -  if (euid_egid_lock) { -  if (mixed err = catch { mutex_key = euid_egid_lock->lock(); }) -  master()->handle_error (err); -  } -  threads_disabled = _disable_threads(); - #endif /* THREADS */ -  -  p_level = privs_level++; -  -  /* Needs to be here since root-priviliges may be needed to -  * use getpw{uid,nam}. -  */ -  saved_uid = geteuid(); -  saved_gid = getegid(); -  seteuid(0); -  -  /* A string of digits? */ -  if(stringp(uid) && (replace(uid,"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]; -  } -  -  if(u && !gid) -  gid = u[3]; -  -  if(!u) -  { -  if (uid && (uid != "root")) -  { -  if (intp(uid) && (uid >= 60000)) -  { -  report_warning(sprintf("Privs: User %d is not in the password database.\n" -  "Assuming nobody.\n", uid)); -  // Nobody. -  gid = gid || uid; // Fake a gid also. -  u = ({ "fake-nobody", "x", uid, gid, "A real nobody", "/", "/sbin/sh" }); -  } else { -  error("Unknown user: "+uid+"\n"); -  } -  } else { -  u = ({ "root", "x", 0, gid, "The super-user", "/", "/sbin/sh" }); -  } -  } -  -  if(LOGP) -  report_notice(LOC_M(1, "Change to %s(%d):%d privs wanted (%s), from %s"), -  (string)u[0], (int)uid, (int)gid, -  (string)reason, -  (string)dbt(backtrace()[-2])); -  -  if (u[2]) { - #if constant(cleargroups) -  if (mixed err = catch { cleargroups(); }) -  master()->handle_error (err); - #endif /* cleargroups */ - #if constant(initgroups) -  if (mixed err = catch { initgroups(u[0], u[3]); }) -  master()->handle_error (err); - #endif -  } -  gid = gid || getgid(); -  int err = (int)setegid(new_gid = gid); -  if (err < 0) { -  report_warning(LOC_M(2, "Privs: WARNING: Failed to set the " -  "effective group id to %d!\n" -  "Check that your password database is correct " -  "for user %s(%d),\n and that your group " -  "database is correct.\n"), -  gid, (string)u[0], (int)uid); -  int gid2 = gid; - #ifdef HPUX_KLUDGE -  if (gid >= 60000) { -  /* HPUX has doesn't like groups higher than 60000, -  * but has assigned nobody to group 60001 (which isn't even -  * in /etc/group!). -  * -  * HPUX's libc also insists on filling numeric fields it doesn't like -  * with the value 60001! -  */ -  report_debug("Privs: WARNING: Assuming nobody-group.\n" -  "Trying some alternatives...\n"); -  // Assume we want the nobody group, and try a couple of alternatives -  foreach(({ 60001, 65534, -2 }), gid2) { -  report_debug("%d... ", gid2); -  if (initgroups(u[0], gid2) >= 0) { -  if ((err = setegid(new_gid = gid2)) >= 0) { -  report_debug("Success!\n"); -  break; -  } -  } -  } -  } - #endif /* HPUX_KLUDGE */ -  if (err < 0) { -  report_debug("Privs: Failed\n"); -  error ("Failed to set EGID to %d\n", gid); -  } -  report_debug("Privs: WARNING: Set egid to %d instead of %d.\n", -  gid2, gid); -  gid = gid2; -  } -  if(getgid()!=gid) setgid(gid||getgid()); -  seteuid(new_uid = uid); -  enable_coredumps(1); - #endif /* HAVE_EFFECTIVE_USER */ -  } -  -  void destroy() -  { -  // No need for Privs if the uid has been changed permanently. -  if(getuid()) return; -  - #ifdef PRIVS_DEBUG -  report_debug(sprintf("Privs->destroy()\n" -  "privs_level: %O\n", -  privs_level)); - #endif /* PRIVS_DEBUG */ -  - #ifdef HAVE_EFFECTIVE_USER -  /* Check that we don't increase the privs level */ -  if (p_level >= privs_level) { -  report_error(sprintf("Change back to uid#%d gid#%d from uid#%d gid#%d\n" -  "in wrong order! Saved level:%d Current level:%d\n" -  "Occurs in:\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("Change back to uid#%d gid#%d from uid#%d gid#%d\n" -  "Skips privs level. Saved level:%d Current level:%d\n" -  "Occurs in:\n%s\n", -  saved_uid, saved_gid, new_uid, new_gid, -  p_level, privs_level, -  describe_backtrace(backtrace()))); -  } -  privs_level = p_level; -  -  if(LOGP) { -  if (mixed err = catch { -  array bt = backtrace(); -  if (sizeof(bt) >= 2) { -  report_notice(LOC_M(3,"Change back to uid#%d gid#%d, from %s")+"\n", -  saved_uid, saved_gid, dbt(bt[-2])); -  } else { -  report_notice(LOC_M(4,"Change back to uid#%d gid#%d, " -  "from backend")+"\n", saved_uid, saved_gid); -  } -  }) -  master()->handle_error (err); -  } -  - #ifdef PRIVS_DEBUG -  int uid = geteuid(); -  if (uid != new_uid) { -  report_debug("Privs: UID #%d differs from expected #%d\n" -  "%s\n", -  uid, new_uid, describe_backtrace(backtrace())); -  } -  int gid = getegid(); -  if (gid != new_gid) { -  report_debug("Privs: GID #%d differs from expected #%d\n" -  "%s\n", -  gid, new_gid, describe_backtrace(backtrace())); -  } - #endif /* PRIVS_DEBUG */ -  -  seteuid(0); -  array u = getpwuid(saved_uid); - #if constant(cleargroups) -  if (mixed err = catch { cleargroups(); }) -  master()->handle_error (err); - #endif /* cleargroups */ -  if(u && (sizeof(u) > 3)) { -  if (mixed err = catch { initgroups(u[0], u[3]); }) -  master()->handle_error (err); -  } -  setegid(saved_gid); -  seteuid(saved_uid); -  enable_coredumps(1); - #endif /* HAVE_EFFECTIVE_USER */ -  } - #else /* constant(seteuid) */ -  void create(string reason, int|string|void uid, int|string|void gid){} - #endif /* constant(seteuid) */ - } -  +    /* Used by read_config.pike, since there seems to be problems with    * overloading otherwise.    */   protected Privs PRIVS(string r, int|string|void u, int|string|void g)   {    return Privs(r, u, g);   }      // Current Configuration.   Thread.Local current_configuration = Thread.Local();
Roxen.git/server/base_server/roxen.pike:3681:    (now >> 32) & 0xffff,    (now >> 48) & 0xffff,    clock_sequence,    hex_mac_address);   }      mapping(string:array(int)) error_log=([]);      // Write a string to the administration interface error log and to stderr.   void nwrite(string s, int|void perr, int|void errtype, -  object|void mod, object|void conf, bool|void skip_stderr) +  object|void mod, object|void conf)   {    int log_time = time(1);    string reference = (mod ? Roxen.get_modname(mod) : conf && conf->name) || "";    string log_index = sprintf("%d,%s,%s", errtype, reference, s);    if(!error_log[log_index])    error_log[log_index] = ({ log_time });    else    error_log[log_index] += ({ log_time });       if( mod )    {    if( mod->error_log )    mod->error_log[log_index] += ({ log_time });    }    if( conf )    {    if( conf->error_log )    conf->error_log[log_index] += ({ log_time });    }    -  if(errtype >= 1 && !skip_stderr) +  if(errtype >= 1)    report_debug( s );   }      protected BackgroundProcess hourly_maintenance_process;      protected void clean_error_log(mapping(string:array(int)) log,    mapping(string:int) cutoffs)   {    if (!log || !sizeof(log)) return;    foreach(cutoffs; string prefix; int cutoff) {
Roxen.git/server/base_server/roxen.pike:5768:    dump( "base_server/newdecode.pike" );    dump( "base_server/read_config.pike" );    dump( "base_server/global_variables.pike" );    dump( "base_server/module_support.pike" );    dump( "base_server/socket.pike" );    dump( "base_server/cache.pike" );    dump( "base_server/supports.pike" );    dump( "base_server/hosts.pike");    dump( "base_server/language.pike");    - #ifndef __NT__ -  if(!getuid()) -  add_constant("Privs", Privs); -  else - #endif /* !__NT__ */ -  add_constant("Privs", class { -  void create(string reason, int|string|void uid, int|string|void gid) {} -  }); -  -  +     DDUMP( "base_server/roxenlib.pike");    DDUMP( "etc/modules/Dims.pmod");    DDUMP( "config_interface/boxes/Box.pmod" );    dump( "base_server/html.pike");       add_constant( "RoxenModule", RoxenModule);    add_constant( "ModuleInfo", ModuleInfo );       add_constant( "load", load);   
Roxen.git/server/base_server/roxen.pike:6556:   protected class GCTimestamp   {    array self_ref;    protected void create() {self_ref = ({this_object()});}    protected void destroy() {    werror ("GC runs at %s", ctime(time()));    GCTimestamp();    }   }    - protected int gc_start; + int log_gc_timestamps; + int log_gc_histogram; + int log_gc_verbose; + int log_gc_cycles;    - protected mapping(string:int) gc_histogram = ([]); -  - array argv; - int main(int argc, array tmp) + string format_cycle (array(mixed) cycle)   { -  // __builtin.gc_parameters((["enabled": 0])); -  argv = tmp; -  tmp = 0; +  array(string) string_parts = ({}); +  foreach (cycle; int pos; mixed val) { +  /* Idea: identify mapping/array index of the next element in the cycle. +  mixed next_val; +  if (pos < sizeof (cycle) - 1) { +  next_val = cycle[pos + 1]; +  } +  */    - #if 0 -  Thread.thread_create (lambda () { -  while (1) { -  sleep (10); -  describe_all_threads(); +  string formatted; +  +  if (arrayp (val)) { +  formatted = sprintf ("array(%d)", sizeof (val)); +  } else if (mappingp (val)) { +  formatted = sprintf ("mapping(%d)", sizeof (val)); +  } else if (multisetp (val)) { +  formatted = sprintf ("multiset(%d)", sizeof (val)); +  } else { +  formatted = sprintf ("%O", val);    } -  }); - #endif +  string_parts += ({ formatted }); +  }    - #ifdef LOG_GC_TIMESTAMPS -  Pike.gc_parameters(([ "pre_cb": lambda() { +  return string_parts * " -> "; + } +  + void reinstall_gc_callbacks() + { +  mapping(string:mixed) gc_params = ([ "pre_cb": 0, +  "post_cb": 0, +  "destruct_cb": 0, +  "done_cb": 0 ]); +  +  int gc_start; +  +  // mapping from program name (as reported by sprintf/%O) to number of +  // GC-destructed objects. Only valid in the GC's done_cb below. +  mapping(string:int) gc_histogram = ([]); +  +  // mapping from program name (as reported by sprintf/%O) to flag +  // indicating whether a cycle has been reported for this program in +  // the current GC report round. Cleared on every GC restart. +  mapping(string:int(0..1)) reported_cycles = ([]); +  +  if (log_gc_timestamps || log_gc_histogram || log_gc_verbose || +  log_gc_cycles) { +  gc_params->pre_cb = +  lambda() {    gc_start = gethrtime();    gc_histogram = ([]); -  +  reported_cycles = ([]);    werror("GC runs at %s", ctime(time())); -  }, -  "post_cb":lambda() { +  }; +  +  gc_params->post_cb = +  lambda() {    werror("GC done after %dus\n",    gethrtime() - gc_start); -  }, - #ifdef LOG_GC_HISTOGRAM -  "destruct_cb":lambda(object o) { +  }; +  +  if (log_gc_histogram || log_gc_verbose || log_gc_cycles) { +  gc_params->destruct_cb = +  lambda(object o) {    // NB: These calls to sprintf(%O) can    // take significant time. -  gc_histogram[sprintf("%O", object_program(o))]++; - #ifdef LOG_GC_VERBOSE +  string id = +  sprintf("%O", object_program(o)); +  gc_histogram[id]++; +  if (log_gc_verbose) {    werror("GC cyclic reference in %O.\n",    o); - #endif -  }, - #endif /* LOG_GC_HISTOGRAM */ -  "done_cb":lambda(int n) { +  } +  +  if (log_gc_cycles && !reported_cycles[id]) { +  reported_cycles[id] = 1; +  if (array(mixed) cycle = Pike.identify_cycle(o)) { +  werror ("GC cycle:\n%s\n", format_cycle (cycle)); +  } +  } +  }; +  } +  +  gc_params->done_cb = +  lambda(int n) {    if (!n) return;    werror("GC zapped %d things.\n", n); - #ifdef LOG_GC_HISTOGRAM +  +  if (log_gc_histogram) {    mapping h = gc_histogram;    gc_histogram = ([]);    if (!sizeof(h)) return;    array i = indices(h);    array v = values(h);    sort(v, i);    werror("GC histogram:\n");    foreach(reverse(i)[..9], string p) {    werror("GC: %s: %d\n", p, h[p]);    } - #endif /* LOG_GC_HISTOGRAM */ -  }, -  ])); -  if (!Pike.gc_parameters()->pre_cb) { -  // GC callbacks not available. -  GCTimestamp(); +     } -  +  }; +  } +  +  Pike.gc_parameters(gc_params); + } +  + array argv; + int main(int argc, array tmp) + { +  // __builtin.gc_parameters((["enabled": 0])); +  argv = tmp; +  tmp = 0; +  + #if 0 +  Thread.thread_create (lambda () { +  while (1) { +  sleep (10); +  describe_all_threads(); +  } +  });   #endif    -  +  +  + #ifdef LOG_GC_TIMESTAMPS +  log_gc_timestamps = 1; + #endif + #ifdef LOG_GC_HISTOGRAM +  log_gc_histogram = 1; + #endif + #ifdef LOG_GC_VERBOSE +  log_gc_verbose = 1; + #endif + #ifdef LOG_GC_CYCLES +  log_gc_cycles = 1; + #endif +  +  reinstall_gc_callbacks(); +     // For RBF    catch(mkdir(getenv("VARDIR") || "../var"));       dbm_cached_get = master()->resolv( "DBManager.cached_get" );       dbm_cached_get( "local" )->    query( "CREATE TABLE IF NOT EXISTS "    "compiled_formats ("    " md5 CHAR(32) not null primary key,"    " full BLOB not null,"