1720541998-10-04Henrik Grubbström (Grubba) /*
fb7ef91998-11-02Per Hedbor  * $Id: roxen.pike,v 1.250 1998/11/02 06:53:41 per Exp $
1720541998-10-04Henrik Grubbström (Grubba)  * * The Roxen Challenger main program. * * Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others. */
edc9af1998-07-11David Hedbor  // ABS and suicide systems contributed freely by Francesco Chemolli
fb7ef91998-11-02Per Hedbor constant cvs_version="$Id: roxen.pike,v 1.250 1998/11/02 06:53:41 per Exp $";
1720541998-10-04Henrik Grubbström (Grubba)  // Some headerfiles
4dd97c1996-12-04Per Hedbor #define IN_ROXEN
8540e11997-06-14Francesco Chemolli #include <roxen.h> #include <config.h>
b1fca01996-11-12Per Hedbor #include <module.h> #include <variables.h>
14179b1997-01-29Per Hedbor 
1720541998-10-04Henrik Grubbström (Grubba) // Inherits inherit "read_config";
b1fca01996-11-12Per Hedbor inherit "hosts";
70f2771997-12-15Per Hedbor inherit "module_support";
b1fca01996-11-12Per Hedbor inherit "socket"; inherit "disk_cache"; inherit "language";
1720541998-10-04Henrik Grubbström (Grubba) // The datashuffler program
65bcb11998-05-26Per Hedbor #if constant(spider.shuffle) && (defined(THREADS) || defined(__NT__))
08152b1998-04-24Per Hedbor constant pipe = (program)"smartpipe";
e5bad21998-02-10Per Hedbor #else
08152b1998-04-24Per Hedbor constant pipe = Pipe.pipe;
e5bad21998-02-10Per Hedbor #endif
f2edfb1998-10-16Henrik Grubbström (Grubba) constant __roxen_version__ = "1.4";
23ad8b1998-10-10Peter Bortas constant __roxen_build__ = "37";
d199531998-03-05Henrik Grubbström (Grubba) 
e5bad21998-02-10Per Hedbor #ifdef __NT__
d199531998-03-05Henrik Grubbström (Grubba) constant real_version = "Roxen Challenger/"+__roxen_version__+"."+__roxen_build__+" NT";
e5bad21998-02-10Per Hedbor #else
d199531998-03-05Henrik Grubbström (Grubba) constant real_version = "Roxen Challenger/"+__roxen_version__+"."+__roxen_build__;
e5bad21998-02-10Per Hedbor #endif
603e0a1997-07-20Henrik Grubbström (Grubba) 
3e646f1997-05-15David Hedbor #if _DEBUG_HTTP_OBJECTS mapping httpobjects = ([]); static int idcount; int new_id(){ return idcount++; } #endif
0f8c871997-06-01Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG #define MD_PERROR(X) perror X; #else #define MD_PERROR(X) #endif /* MODULE_DEBUG */
1720541998-10-04Henrik Grubbström (Grubba) // pids of the start-script and ourselves.
b642a21998-09-05Henrik Grubbström (Grubba) int startpid, roxenpid;
b1fca01996-11-12Per Hedbor 
c31f7b1998-10-10Henrik Grubbström (Grubba) // Locale support
f2edfb1998-10-16Henrik Grubbström (Grubba) object(Locale.Roxen.standard) default_locale = Locale.Roxen.svenska; // standard;
fb7ef91998-11-02Per Hedbor object fonts;
59912f1998-10-15Henrik Grubbström (Grubba) #ifdef THREADS object locale = thread_local(); #else object(Locale.Roxen.standard) locale = default_locale; #endif /* THREADS */ #define LOCALE LOW_LOCALE->base_server
c31f7b1998-10-10Henrik Grubbström (Grubba) 
dca5dc1998-09-12Per Hedbor program Configuration; /*set in create*/
b1fca01996-11-12Per Hedbor 
48fa361997-04-05Per Hedbor array configurations = ({});
b1fca01996-11-12Per Hedbor object main_configuration_port;
e493e81997-07-11Per Hedbor mapping allmodules, somemodules=([]);
b1fca01996-11-12Per Hedbor  // A mapping from ports (objects, that is) to an array of information
e5bad21998-02-10Per Hedbor // about that port. This will hopefully be moved to objects cloned // from the configuration object in the future.
b1fca01996-11-12Per Hedbor mapping portno=([]);
beaca01998-02-20Per Hedbor // Function pointer and the root of the configuration interface
b1fca01996-11-12Per Hedbor // object. private function build_root; private object root;
6ce8591997-09-14Henrik Grubbström (Grubba) #ifdef THREADS // This mutex is used by privs.pike object euid_egid_lock = Thread.Mutex();
3107101998-09-01Marcus Comstedt 
6ce8591997-09-14Henrik Grubbström (Grubba) #endif /* THREADS */
506ede1997-11-11Henrik Grubbström (Grubba) int privs_level;
4f4bc11998-02-04Per Hedbor int die_die_die;
506ede1997-11-11Henrik Grubbström (Grubba) 
a9d8111998-09-01Henrik Grubbström (Grubba) void stop_all_modules()
b1fca01996-11-12Per Hedbor {
a9d8111998-09-01Henrik Grubbström (Grubba)  foreach(configurations, object conf) conf->stop(); }
1720541998-10-04Henrik Grubbström (Grubba) // Function that actually shuts down Roxen. (see low_shutdown).
a9d8111998-09-01Henrik Grubbström (Grubba) private static void really_low_shutdown(int exit_code) { // Die nicely.
14179b1997-01-29Per Hedbor 
b1fca01996-11-12Per Hedbor #ifdef SOCKET_DEBUG
a9d8111998-09-01Henrik Grubbström (Grubba)  roxen_perror("SOCKETS: really_low_shutdown\n" " Bye!\n");
b1fca01996-11-12Per Hedbor #endif
abdc631998-01-21Henrik Grubbström (Grubba) 
3107101998-09-01Marcus Comstedt #ifdef THREADS stop_handler_threads(); #endif /* THREADS */
a9d8111998-09-01Henrik Grubbström (Grubba)  // Don't use fork() with threaded servers.
abdc631998-01-21Henrik Grubbström (Grubba) #if constant(fork) && !defined(THREADS)
a9d8111998-09-01Henrik Grubbström (Grubba)  // Fork, and then do a 'slow-quit' in the forked copy. Exit the // original copy, after all listen ports are closed. // Then the forked copy can finish all current connections.
9a05f21998-05-08Henrik Grubbström (Grubba)  if(fork()) {
a9d8111998-09-01Henrik Grubbström (Grubba)  // Kill the parent.
9a05f21998-05-08Henrik Grubbström (Grubba)  add_constant("roxen", 0); // Remove some extra refs...
a9d8111998-09-01Henrik Grubbström (Grubba)  exit(exit_code); // Die...
9a05f21998-05-08Henrik Grubbström (Grubba)  }
3835ca1998-01-16Henrik Grubbström (Grubba)  // Now we're running in the forked copy.
abdc631998-01-21Henrik Grubbström (Grubba)  // FIXME: This probably doesn't work correctly on threaded servers, // since only one thread is left running after the fork().
b1fca01996-11-12Per Hedbor #if efun(_pipe_debug) call_out(lambda() { // Wait for all connections to finish
a9d8111998-09-01Henrik Grubbström (Grubba)  call_out(Simulate.this_function(), 20); if(!_pipe_debug()[0]) exit(0); }, 1);
abdc631998-01-21Henrik Grubbström (Grubba) #endif /* efun(_pipe_debug) */
b1fca01996-11-12Per Hedbor  call_out(lambda(){ exit(0); }, 600); // Slow buggers..
0d00c91998-09-06Henrik Grubbström (Grubba)  array f=indices(portno);
b274d21998-09-06Henrik Grubbström (Grubba)  for(int i=0; i<sizeof(f); i++)
b1fca01996-11-12Per Hedbor  catch(destruct(f[i]));
a9d8111998-09-01Henrik Grubbström (Grubba) #else /* !constant(fork) || defined(THREADS) */
abdc631998-01-21Henrik Grubbström (Grubba)  // FIXME: // Should probably attempt something similar to the above, // but this should be sufficient for the time being.
9a05f21998-05-08Henrik Grubbström (Grubba)  add_constant("roxen", 0); // Paranoia...
abdc631998-01-21Henrik Grubbström (Grubba) 
a9d8111998-09-01Henrik Grubbström (Grubba)  exit(exit_code); // Now we die... #endif /* constant(fork) && !defined(THREADS) */ } // Shutdown Roxen // exit_code = 0 True shutdown // exit_code = -1 Restart private static void low_shutdown(int exit_code) { // Change to root user if possible ( to kill the start script... ) #if efun(seteuid) seteuid(getuid()); setegid(getgid()); #endif #if efun(setuid) setuid(0); #endif stop_all_modules(); if(main_configuration_port && objectp(main_configuration_port)) { // Only _really_ do something in the main process. int pid; if (exit_code) { roxen_perror("Restarting Roxen.\n"); } else { roxen_perror("Shutting down Roxen.\n"); // This has to be refined in some way. It is not all that nice to do // it like this (write a file in /tmp, and then exit.) The major part // of code to support this is in the 'start' script. #ifndef __NT__ #ifdef USE_SHUTDOWN_FILE // Fallback for systems without geteuid, Roxen will (probably) // not be able to kill the start-script if this is the case. rm("/tmp/Roxen_Shutdown_"+startpid); object f; f=open("/tmp/Roxen_Shutdown_"+startpid, "wc"); if(!f) roxen_perror("cannot open shutdown file.\n"); else f->write(""+getpid()); #endif /* USE_SHUTDOWN_FILE */ // Try to kill the start-script. if(startpid != getpid()) { kill(startpid, signum("SIGINTR")); kill(startpid, signum("SIGHUP")); kill(getppid(), signum("SIGINTR")); kill(getppid(), signum("SIGHUP")); } #endif /* !__NT__ */ } } call_out(really_low_shutdown, 5, exit_code);
b1fca01996-11-12Per Hedbor }
a9d8111998-09-01Henrik Grubbström (Grubba) // Perhaps somewhat misnamed, really... This function will close all // listen ports, fork a new copy to handle the last connections, and // then quit the original process. The 'start' script should then // start a new copy of roxen automatically. mapping restart() { low_shutdown(-1); return ([ "data": replace(Stdio.read_bytes("etc/restart.html"),
6ca8f61998-10-13Per Hedbor  ({"$docurl", "$PWD"}), ({docurl, getcwd()})),
a9d8111998-09-01Henrik Grubbström (Grubba)  "type":"text/html" ]); } mapping shutdown() { low_shutdown(0); return ([ "data":replace(Stdio.read_bytes("etc/shutdown.html"),
6ca8f61998-10-13Per Hedbor  ({"$docurl", "$PWD"}), ({docurl, getcwd()})),
a9d8111998-09-01Henrik Grubbström (Grubba)  "type":"text/html" ]); }
b1fca01996-11-12Per Hedbor // This is called for each incoming connection. private static void accept_callback( object port ) { object file;
06583f1997-09-03Per Hedbor  int q=QUERY(NumAccept);
14179b1997-01-29Per Hedbor  array pn=portno[port];
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor #ifdef DEBUG if(!pn)
b1fca01996-11-12Per Hedbor  { destruct(port->accept()); perror("$&$$& Garbage Collector bug!!\n"); return; }
14179b1997-01-29Per Hedbor #endif
b1fca01996-11-12Per Hedbor  while(q--) { catch { file = port->accept(); };
14179b1997-01-29Per Hedbor #ifdef SOCKET_DEBUG if(!pn[-1])
b1fca01996-11-12Per Hedbor  { report_error("In accept: Illegal protocol handler for port.\n"); if(file) destruct(file); return; } perror(sprintf("SOCKETS: accept_callback(CONF(%s))\n",
14179b1997-01-29Per Hedbor  pn[1]&&pn[1]->name||"Configuration"));
b1fca01996-11-12Per Hedbor #endif if(!file) { switch(port->errno()) { case 0: case 11: return; default: #ifdef DEBUG perror("Accept failed.\n");
4f4bc11998-02-04Per Hedbor #if constant(real_perror)
b1fca01996-11-12Per Hedbor  real_perror();
4f4bc11998-02-04Per Hedbor #endif
95e2b41997-05-25Wilhelm Köhler #endif /* DEBUG */
b1fca01996-11-12Per Hedbor  return; case 24:
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_fatal(LOCALE->out_of_sockets());
a9d8111998-09-01Henrik Grubbström (Grubba)  low_shutdown(-1);
b1fca01996-11-12Per Hedbor  return; } }
3235691998-03-26Per Hedbor #ifdef FD_DEBUG
c31f7b1998-10-10Henrik Grubbström (Grubba)  mark_fd( file->query_fd(), LOCALE->out_of_sockets(file->query_address()));
14179b1997-01-29Per Hedbor #endif pn[-1](file,pn[1]);
b1fca01996-11-12Per Hedbor #ifdef SOCKET_DEBUG perror(sprintf("SOCKETS: Ok. Connect on %O:%O from %O\n",
14179b1997-01-29Per Hedbor  pn[2], pn[0], file->query_address())); #endif } }
1720541998-10-04Henrik Grubbström (Grubba) // handle function used when THREADS is not enabled.
3aaaa71997-06-12Wilhelm Köhler void unthreaded_handle(function f, mixed ... args) { f(@args); }
34fbbc1998-02-05Henrik Grubbström (Grubba) function handle = unthreaded_handle;
1720541998-10-04Henrik Grubbström (Grubba) /* * THREADS code starts here */
34fbbc1998-02-05Henrik Grubbström (Grubba) #ifdef THREADS #define THREAD_DEBUG
4f4bc11998-02-04Per Hedbor object do_thread_create(string id, function f, mixed ... args) { object t = thread_create(f, @args); catch(t->set_name( id ));
dca5dc1998-09-12Per Hedbor  roxen_perror(id+" started\n");
4f4bc11998-02-04Per Hedbor  return t; }
1720541998-10-04Henrik Grubbström (Grubba) // Queue of things to handle. // An entry consists of an array(function fp, array args)
3107101998-09-01Marcus Comstedt static object (Thread.Queue) handle_queue = Thread.Queue();
1720541998-10-04Henrik Grubbström (Grubba)  // Number of handler threads that are alive.
3107101998-09-01Marcus Comstedt static int thread_reap_cnt;
14179b1997-01-29Per Hedbor  void handler_thread(int id) {
4f4bc11998-02-04Per Hedbor  array (mixed) h, q;
b8811d1997-09-01Per Hedbor  while(1)
4f4bc11998-02-04Per Hedbor  {
59912f1998-10-15Henrik Grubbström (Grubba)  SET_LOCALE(default_locale);
4f4bc11998-02-04Per Hedbor  if(q=catch {
45cae31998-03-06Henrik Grubbström (Grubba)  do {
3107101998-09-01Marcus Comstedt  if((h=handle_queue->read()) && h[0]) {
45cae31998-03-06Henrik Grubbström (Grubba)  h[0](@h[1]); h=0;
3107101998-09-01Marcus Comstedt  } else if(!h) { // Roxen is shutting down. werror("Handle thread ["+id+"] stopped\n"); thread_reap_cnt--; return;
45cae31998-03-06Henrik Grubbström (Grubba)  } } while(1); }) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->uncaught_error(describe_backtrace(q)));
45cae31998-03-06Henrik Grubbström (Grubba)  if (q = catch {h = 0;}) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE-> uncaught_error(describe_backtrace(q)));
45cae31998-03-06Henrik Grubbström (Grubba)  } }
4f4bc11998-02-04Per Hedbor  }
b1fca01996-11-12Per Hedbor }
3aaaa71997-06-12Wilhelm Köhler void threaded_handle(function f, mixed ... args) {
b42e621998-04-21Henrik Grubbström (Grubba)  // trace(100);
3aaaa71997-06-12Wilhelm Köhler  handle_queue->write(({f, args })); }
14179b1997-01-29Per Hedbor int number_of_threads; void start_handler_threads() {
a60c4c1997-07-03Henrik Grubbström (Grubba)  if (QUERY(numthreads) <= 1) { QUERY(numthreads) = 1; perror("Starting 1 thread to handle requests.\n"); } else { perror("Starting "+QUERY(numthreads)+" threads to handle requests.\n"); }
14179b1997-01-29Per Hedbor  for(; number_of_threads < QUERY(numthreads); number_of_threads++)
4f4bc11998-02-04Per Hedbor  do_thread_create( "Handle thread ["+number_of_threads+"]", handler_thread, number_of_threads );
3aaaa71997-06-12Wilhelm Köhler  if(number_of_threads > 0) handle = threaded_handle;
14179b1997-01-29Per Hedbor }
06583f1997-09-03Per Hedbor 
3107101998-09-01Marcus Comstedt void stop_handler_threads() { int timeout=30; perror("Stopping all request handler threads.\n"); while(number_of_threads>0) { number_of_threads--; handle_queue->write(0); thread_reap_cnt++; } while(thread_reap_cnt) { if(--timeout<=0) { perror("Giving up waiting on threads!\n"); return; } sleep(1); } }
4f4bc11998-02-04Per Hedbor mapping accept_threads = ([]);
06583f1997-09-03Per Hedbor void accept_thread(object port,array pn) {
4f4bc11998-02-04Per Hedbor  accept_threads[port] = this_thread();
06583f1997-09-03Per Hedbor  program port_program = pn[-1]; mixed foo = pn[1]; array err; object o;
4f4bc11998-02-04Per Hedbor  while(!die_die_die) { o = port->accept(); err = catch { if(o) port_program(o,foo); }; if(err) perror("Error in accept_thread: %O\n",describe_backtrace(err)); }
06583f1997-09-03Per Hedbor }
95e2b41997-05-25Wilhelm Köhler #endif /* THREADS */
14179b1997-01-29Per Hedbor 
06583f1997-09-03Per Hedbor 
b1fca01996-11-12Per Hedbor // Listen to a port, connected to the configuration 'conf', binding // only to the netinterface 'ether', using 'requestprogram' as a // protocol handled. // If you think that the argument order is quite unintuitive and odd, // you are right, the order is the same as the implementation order. // Old spinners only listened to a port number, then the // configurations came, then the need to bind to a specific // ethernetinterface, and then the need to have more than one concurrent // protocol (http, ftp, ssl, etc.)
14179b1997-01-29Per Hedbor 
b1fca01996-11-12Per Hedbor object create_listen_socket(mixed port_no, object conf,
9f46de1997-04-08Per Hedbor  string|void ether, program requestprogram, array prt)
b1fca01996-11-12Per Hedbor { object port; #ifdef SOCKET_DEBUG perror(sprintf("SOCKETS: create_listen_socket(%d,CONF(%s),%s)\n", port_no, conf?conf->name:"Configuration port", ether)); #endif if(!requestprogram) error("No request handling module passed to create_listen_socket()\n"); if(!port_no) {
7ed1021998-01-28Henrik Grubbström (Grubba)  port = Stdio.Port( "stdin", accept_callback );
c79b261998-02-05Johan Schön  port->set_id(port);
c31f7b1998-10-10Henrik Grubbström (Grubba)  if(port->errno()) { report_error(LOCALE->stdin_is_quiet(port->errno()));
b1fca01996-11-12Per Hedbor  } } else {
7ed1021998-01-28Henrik Grubbström (Grubba)  port = Stdio.Port();
c79b261998-02-05Johan Schön  port->set_id(port);
b1fca01996-11-12Per Hedbor  if(!stringp(ether) || (lower_case(ether) == "any")) ether=0; if(ether) sscanf(ether, "addr:%s", ether);
9dcc101998-03-10David Hedbor #if defined(THREADS) && 0
06583f1997-09-03Per Hedbor  if(!port->bind(port_no, 0, ether)) #else
b1fca01996-11-12Per Hedbor  if(!port->bind(port_no, accept_callback, ether))
06583f1997-09-03Per Hedbor #endif
b1fca01996-11-12Per Hedbor  { #ifdef SOCKET_DEBUG
581bf11997-09-06Per Hedbor  perror("SOCKETS: -> Failed.\n");
b1fca01996-11-12Per Hedbor #endif
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_warning(LOCALE-> socket_already_bound_retry(ether, port_no, port->errno()));
4ba6fc1998-04-03Henrik Grubbström (Grubba)  sleep(1); #if defined(THREADS) && 0 if(!port->bind(port_no, 0, ether)) #else if(!port->bind(port_no, accept_callback, ether)) #endif {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_warning(LOCALE-> socket_already_bound(ether, port_no, port->errno()));
4ba6fc1998-04-03Henrik Grubbström (Grubba)  return 0; }
b1fca01996-11-12Per Hedbor  } }
14179b1997-01-29Per Hedbor  portno[port]=({ port_no, conf, ether||"Any", 0, requestprogram });
9dcc101998-03-10David Hedbor #if defined(THREADS) && 0
4f4bc11998-02-04Per Hedbor  call_out(do_thread_create,0,"Accept thread ["+port_no+":"+(ether||"ANY]"), accept_thread, port,portno[port]);
06583f1997-09-03Per Hedbor #endif
b1fca01996-11-12Per Hedbor #ifdef SOCKET_DEBUG perror("SOCKETS: -> Ok.\n"); #endif return port; } // The configuration interface is loaded dynamically for faster // startup-time, and easier coding in the configuration interface (the // Roxen environment is already finished when it is loaded) object configuration_interface_obj; int loading_config_interface; int enabling_configurations; object configuration_interface() { if(enabling_configurations) return 0; if(loading_config_interface) { perror("Recursive calls to configuration_interface()\n" + describe_backtrace(backtrace())+"\n"); } if(!configuration_interface_obj) { perror("Loading configuration interface.\n");
039ce41997-08-21Henrik Grubbström (Grubba)  loading_config_interface = 1;
2740711997-08-21Henrik Grubbström (Grubba)  array err = catch {
0f28da1997-08-13Per Hedbor  configuration_interface_obj=((program)"mainconfig")();
d24d291997-08-19Per Hedbor  root = configuration_interface_obj->root;
0f28da1997-08-13Per Hedbor  };
039ce41997-08-21Henrik Grubbström (Grubba)  loading_config_interface = 0;
2740711997-08-21Henrik Grubbström (Grubba)  if(!configuration_interface_obj) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE-> configuration_interface_failed(describe_backtrace(err)));
2740711997-08-21Henrik Grubbström (Grubba)  }
b1fca01996-11-12Per Hedbor  } return configuration_interface_obj; }
1668b21998-04-23Henrik Grubbström (Grubba) // Unload the configuration interface void unload_configuration_interface() {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->unload_configuration_interface());
1668b21998-04-23Henrik Grubbström (Grubba)  configuration_interface_obj = 0; loading_config_interface = 0; enabling_configurations = 0; build_root = 0; catch{root->dest();}; root = 0; }
b1fca01996-11-12Per Hedbor  // Create a new configuration from scratch. // 'type' is as in the form. 'none' for a empty configuration. int add_new_configuration(string name, string type) { return configuration_interface()->low_enable_configuration(name, type); } // Call the configuration interface function. This is more or less // equivalent to a virtual configuration with the configurationinterface // mounted on '/'. This will probably be the case in future versions
fb74971997-09-16Per Hedbor #ifdef THREADS object configuration_lock = Thread.Mutex(); #endif
b1fca01996-11-12Per Hedbor mixed configuration_parse(mixed ... args) {
fb74971997-09-16Per Hedbor #ifdef THREADS object key; catch(key = configuration_lock->lock()); #endif
b1fca01996-11-12Per Hedbor  if(args) return configuration_interface()->configuration_parse(@args); }
025d221997-06-01Henrik Grubbström (Grubba) mapping(string:array(int)) error_log=([]);
ec2fe11997-06-09Henrik Grubbström (Grubba) string last_error="";
b1fca01996-11-12Per Hedbor // Write a string to the configuration interface error log and to stderr.
9b9f701997-08-12Per Hedbor void nwrite(string s, int|void perr, int|void type)
b1fca01996-11-12Per Hedbor {
ec2fe11997-06-09Henrik Grubbström (Grubba)  last_error = s;
9b9f701997-08-12Per Hedbor  if (!error_log[type+","+s]) { error_log[type+","+s] = ({ time() });
025d221997-06-01Henrik Grubbström (Grubba)  } else {
9b9f701997-08-12Per Hedbor  error_log[type+","+s] += ({ time() });
025d221997-06-01Henrik Grubbström (Grubba)  }
17834a1998-04-09Henrik Grubbström (Grubba)  if(type>=1) roxen_perror(s);
b1fca01996-11-12Per Hedbor } // When was Roxen started?
60ecef1998-06-13Henrik Grubbström (Grubba) int boot_time;
b1fca01996-11-12Per Hedbor int start_time; string version() {
71a11e1997-08-13Henrik Grubbström (Grubba)  return QUERY(default_ident)?real_version:QUERY(ident);
b1fca01996-11-12Per Hedbor } // The db for the nice '<if supports=..>' tag. mapping (string:array (array (object|multiset))) supports; private multiset default_supports = (< >); private static inline array positive_supports(array from) { array res = copy_value(from); int i; for(i=0; i<sizeof(res); i++) if(res[i][0] == '-') res[i] = 0; return res - ({ 0 }); } private inline array negative_supports(array from) { array res = copy_value(from); int i; for(i=0; i<sizeof(res); i++) if(res[i][0] != '-') res[i] = 0; else res[i] = res[i][1..]; return res - ({ 0 }); } private static mapping foo_defines = ([ ]); // '#define' in the 'supports' file. static private string current_section; // Used below. // '#section' in the 'supports' file. private void parse_supports_string(string what) { string foo; array lines; int i; lines=replace(what, "\\\n", " ")/"\n"-({""}); foreach(lines, foo) { array bar, gazonk; if(foo[0] == '#') { string file; string name, to; if(sscanf(foo, "#include <%s>", file)) {
5e89211997-02-13Per Hedbor  if(foo=Stdio.read_bytes(file))
b1fca01996-11-12Per Hedbor  parse_supports_string(foo); else
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->supports_bad_include(file));
b1fca01996-11-12Per Hedbor  } else if(sscanf(foo, "#define %[^ ] %s", name, to)) { name -= "\t"; foo_defines[name] = to; // perror("#defining '"+name+"' to "+to+"\n"); } else if(sscanf(foo, "#section %[^ ] {", name)) { // perror("Entering section "+name+"\n"); current_section = name; if(!supports[name]) supports[name] = ({}); } else if((foo-" ") == "#}") { // perror("Leaving section "+current_section+"\n"); current_section = 0; } else { // perror("Comment: "+foo+"\n"); } } else { int rec = 10; string q=replace(foo,",", " "); foo=""; // Handle all defines. while((strlen(foo)!=strlen(q)) && --rec) { foo=q; q = replace(q, indices(foo_defines), values(foo_defines)); } foo=q; if(!rec) perror("Too deep recursion while replacing defines.\n"); // perror("Parsing supports line '"+foo+"'\n"); bar = replace(foo, ({"\t",","}), ({" "," "}))/" " -({ "" }); foo=""; if(sizeof(bar) < 2) continue; if(bar[0] == "default")
01d0811996-11-12Mirar (Pontus Hagland)  default_supports = aggregate_multiset(@bar[1..]);
b1fca01996-11-12Per Hedbor  else { gazonk = bar[1..];
bfbd4d1998-04-07Henrik Grubbström (Grubba)  mixed err; if (err = catch { supports[current_section] += ({ ({ Regexp(bar[0])->match,
01d0811996-11-12Mirar (Pontus Hagland)  aggregate_multiset(@positive_supports(gazonk)), aggregate_multiset(@negative_supports(gazonk)),
bfbd4d1998-04-07Henrik Grubbström (Grubba)  })}); }) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->supports_bad_regexp(describe_backtrace(err)));
bfbd4d1998-04-07Henrik Grubbström (Grubba)  }
b1fca01996-11-12Per Hedbor  } } } } public void initiate_supports() { supports = ([ 0:({ }) ]); foo_defines = ([ ]); current_section = 0; parse_supports_string(QUERY(Supports)); foo_defines = 0; } array _new_supports = ({}); void done_with_roxen_com() { string new, old; new = _new_supports * "";
8942801997-11-28Henrik Grubbström (Grubba)  new = (new/"\r\n\r\n")[1..]*"\r\n\r\n";
5e89211997-02-13Per Hedbor  old = Stdio.read_bytes( "etc/supports" );
b1fca01996-11-12Per Hedbor  if(strlen(new) < strlen(old)-200) // Error in transfer? return; if(old != new) {
a60c4c1997-07-03Henrik Grubbström (Grubba)  perror("Got new supports data from www.roxen.com\n");
b1fca01996-11-12Per Hedbor  perror("Replacing old file with new data.\n");
8afc811998-02-04Per Hedbor #ifndef THREADS
c31f7b1998-10-10Henrik Grubbström (Grubba)  object privs=Privs(LOCALE->replacing_supports());
8afc811998-02-04Per Hedbor #endif
b1fca01996-11-12Per Hedbor  mv("etc/supports", "etc/supports~");
5e89211997-02-13Per Hedbor  Stdio.write_file("etc/supports", new); old = Stdio.read_bytes( "etc/supports" );
8afc811998-02-04Per Hedbor #if efun(chmod)
c79b261998-02-05Johan Schön #if efun(geteuid)
8afc811998-02-04Per Hedbor  if(geteuid() != getuid()) chmod("etc/supports",0660);
c79b261998-02-05Johan Schön #endif
8afc811998-02-04Per Hedbor #endif
b1fca01996-11-12Per Hedbor  if(old != new) { perror("FAILED to update the supports file.\n"); mv("etc/supports~", "etc/supports");
8afc811998-02-04Per Hedbor #ifndef THREADS
5c6bc51997-06-04Henrik Grubbström (Grubba)  privs = 0;
8afc811998-02-04Per Hedbor #endif
5c6bc51997-06-04Henrik Grubbström (Grubba)  } else {
8afc811998-02-04Per Hedbor #ifndef THREADS
5c6bc51997-06-04Henrik Grubbström (Grubba)  privs = 0;
8afc811998-02-04Per Hedbor #endif
b1fca01996-11-12Per Hedbor  initiate_supports();
5c6bc51997-06-04Henrik Grubbström (Grubba)  }
b1fca01996-11-12Per Hedbor  } #ifdef DEBUG else perror("No change to the supports file.\n"); #endif } void got_data_from_roxen_com(object this, string foo) { if(!foo) return; _new_supports += ({ foo }); } void connected_to_roxen_com(object port) { if(!port) { #ifdef DEBUG
a60c4c1997-07-03Henrik Grubbström (Grubba)  perror("Failed to connect to www.roxen.com:80.\n");
b1fca01996-11-12Per Hedbor #endif return 0; } #ifdef DEBUG
a60c4c1997-07-03Henrik Grubbström (Grubba)  perror("Connected to www.roxen.com.:80\n");
b1fca01996-11-12Per Hedbor #endif _new_supports = ({}); port->set_id(port);
47f2cf1997-11-27Henrik Grubbström (Grubba)  string v = version(); if (v != real_version) { v = v + " (" + real_version + ")"; }
99864e1997-11-26Henrik Grubbström (Grubba)  port->write("GET /supports HTTP/1.0\r\n"
47f2cf1997-11-27Henrik Grubbström (Grubba)  "User-Agent: " + v + "\r\n" "Host: www.roxen.com:80\r\n" "Pragma: no-cache\r\n"
99864e1997-11-26Henrik Grubbström (Grubba)  "\r\n");
b1fca01996-11-12Per Hedbor  port->set_nonblocking(got_data_from_roxen_com, got_data_from_roxen_com, done_with_roxen_com); } public void update_supports_from_roxen_com() {
37ec6c1997-09-15Henrik Grubbström (Grubba)  // FIXME: // This code has a race-condition, but it only occurs once a week...
f6d62d1997-03-26Per Hedbor  if(QUERY(next_supports_update) <= time())
b1fca01996-11-12Per Hedbor  {
f6d62d1997-03-26Per Hedbor  if(QUERY(AutoUpdate)) {
bc42561997-06-12Henrik Grubbström (Grubba)  async_connect("www.roxen.com.", 80, connected_to_roxen_com);
b1fca01996-11-12Per Hedbor #ifdef DEBUG
bc42561997-06-12Henrik Grubbström (Grubba)  perror("Connecting to www.roxen.com.:80\n");
b1fca01996-11-12Per Hedbor #endif
f6d62d1997-03-26Per Hedbor  } remove_call_out( update_supports_from_roxen_com );
b1fca01996-11-12Per Hedbor  // Check again in one week.
f6d62d1997-03-26Per Hedbor  QUERY(next_supports_update)=3600*24*7 + time(); store("Variables", variables, 0, 0); } call_out(update_supports_from_roxen_com, QUERY(next_supports_update)-time());
b1fca01996-11-12Per Hedbor } // Return a list of 'supports' values for the current connection.
64b0501998-04-02David Hedbor public multiset find_supports(string from, void|multiset existing_sup)
b1fca01996-11-12Per Hedbor {
64b0501998-04-02David Hedbor  multiset (string) sup = existing_sup || (< >);
b1fca01996-11-12Per Hedbor  multiset (string) nsup = (< >); array (function|multiset) s; string v; array f;
3835ca1998-01-16Henrik Grubbström (Grubba)  if(!(< "unknown", "" >)[from])
b1fca01996-11-12Per Hedbor  { foreach(indices(supports), v) { if(!v || !search(from, v)) { // perror("Section "+v+" match "+from+"\n"); f = supports[v]; foreach(f, s) if(s[0](from)) { sup |= s[1]; nsup |= s[2]; } } } if(!sizeof(sup)) { sup = default_supports; #ifdef DEBUG
3835ca1998-01-16Henrik Grubbström (Grubba)  perror("Unknown client: \""+from+"\"\n");
b1fca01996-11-12Per Hedbor #endif } } else { sup = default_supports; } return sup - nsup; } public void log(mapping file, object request_id) {
14179b1997-01-29Per Hedbor  if(!request_id->conf) return; request_id->conf->log(file, request_id);
b1fca01996-11-12Per Hedbor } // Support for unique user id's private object current_user_id_file; private int current_user_id_number, current_user_id_file_last_mod; private void restore_current_user_id_number() { if(!current_user_id_file) current_user_id_file = open(configuration_dir + "LASTUSER~", "rwc"); if(!current_user_id_file) { call_out(restore_current_user_id_number, 2); return; } current_user_id_number = (int)current_user_id_file->read(100); current_user_id_file_last_mod = current_user_id_file->stat()[2]; perror("Restoring unique user ID information. (" + current_user_id_number + ")\n");
3235691998-03-26Per Hedbor #ifdef FD_DEBUG
c31f7b1998-10-10Henrik Grubbström (Grubba)  mark_fd(current_user_id_file->query_fd(), LOCALE->unique_uid_logfile());
3235691998-03-26Per Hedbor #endif
b1fca01996-11-12Per Hedbor }
f6d62d1997-03-26Per Hedbor 
b1fca01996-11-12Per Hedbor int increase_id() { if(!current_user_id_file) { restore_current_user_id_number(); return current_user_id_number+time(); } if(current_user_id_file->stat()[2] != current_user_id_file_last_mod) restore_current_user_id_number(); current_user_id_number++; //perror("New unique id: "+current_user_id_number+"\n"); current_user_id_file->seek(0); current_user_id_file->write((string)current_user_id_number); current_user_id_file_last_mod = current_user_id_file->stat()[2]; return current_user_id_number; } public string full_status() { int tmp; string res=""; array foo = ({0.0, 0.0, 0.0, 0.0, 0}); if(!sizeof(configurations))
c31f7b1998-10-10Henrik Grubbström (Grubba)  return LOCALE->no_servers_enabled();
b1fca01996-11-12Per Hedbor 
5281751997-11-26Henrik Grubbström (Grubba)  foreach(configurations, object conf)
b1fca01996-11-12Per Hedbor  {
88e1cb1996-12-07David Hedbor  if(!conf->sent ||!conf->received ||!conf->hsent) continue;
5281751997-11-26Henrik Grubbström (Grubba)  foo[0] += conf->sent->mb()/(float)(time(1)-start_time+1); foo[1] += conf->sent->mb(); foo[2] += conf->hsent->mb(); foo[3] += conf->received->mb(); foo[4] += conf->requests;
b1fca01996-11-12Per Hedbor  }
5281751997-11-26Henrik Grubbström (Grubba) 
b1fca01996-11-12Per Hedbor  for(tmp = 1; tmp < 4; tmp ++) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  // FIXME: LOCALE?
b1fca01996-11-12Per Hedbor  if(foo[tmp] < 1024.0)
27b0e11996-11-26Per Hedbor  foo[tmp] = sprintf("%.2f MB", foo[tmp]);
b1fca01996-11-12Per Hedbor  else
27b0e11996-11-26Per Hedbor  foo[tmp] = sprintf("%.2f GB", foo[tmp]/1024.0);
b1fca01996-11-12Per Hedbor  }
60ecef1998-06-13Henrik Grubbström (Grubba)  int uptime = time()-start_time; int days = uptime/(24*60*60); int hrs = uptime/(60*60); int min = uptime/60 - hrs*60; hrs -= days*24;
053e9a1998-08-20Per Hedbor  tmp=(int)((foo[4]*600.0)/(uptime+1));
b1fca01996-11-12Per Hedbor 
c31f7b1998-10-10Henrik Grubbström (Grubba)  return(LOCALE->full_status(real_version, boot_time, start_time-boot_time, days, hrs, min, uptime%60, foo[1], foo[0] * 8192.0, foo[2], foo[4], (float)tmp/(float)10, foo[3]));
b1fca01996-11-12Per Hedbor }
4f4bc11998-02-04Per Hedbor int config_ports_changed = 0;
b1fca01996-11-12Per Hedbor 
1c30601998-07-07Henrik Grubbström (Grubba) static string MKPORTKEY(array(string) p) { if (sizeof(p[3])) { return(sprintf("%s://%s:%s/(%s)", p[1], p[2], (string)p[0], replace(p[3], ({"\n", "\r"}), ({ " ", " " })))); } else { return(sprintf("%s://%s:%s/", p[1], p[2], (string)p[0])); } }
23620b1998-04-09Henrik Grubbström (Grubba) // Is this only used to hold the config-ports? // Seems like it. Changed to a mapping. private mapping(string:object) configuration_ports = ([]);
14179b1997-01-29Per Hedbor 
efa11c1998-04-29Henrik Grubbström (Grubba) // Used by openports.pike array(object) get_configuration_ports() { return(values(configuration_ports)); }
602f7e1998-04-11Henrik Grubbström (Grubba) string docurl;
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor // I will remove this in a future version of roxen. private program __p;
08152b1998-04-24Per Hedbor mapping my_loaded = ([]);
14179b1997-01-29Per Hedbor program last_loaded() { return __p; }
b1fca01996-11-12Per Hedbor 
68a0a21997-06-12Henrik Grubbström (Grubba) string last_module_name;
08152b1998-04-24Per Hedbor string filename(object|program o)
14179b1997-01-29Per Hedbor {
08152b1998-04-24Per Hedbor  if(objectp(o)) o = object_program(o); return my_loaded[(program)o]||last_module_name;
14179b1997-01-29Per Hedbor }
b1fca01996-11-12Per Hedbor 
34447f1998-03-20Per Hedbor program my_compile_file(string file) { return compile_file( file ); }
e382ed1997-07-16Henrik Grubbström (Grubba) // ([ filename:stat_array ]) mapping(string:array) module_stat_cache = ([]);
8c62221997-08-06Henrik Grubbström (Grubba) object load(string s, object conf) // Should perhaps be renamed to 'reload'.
14179b1997-01-29Per Hedbor {
08065d1997-05-27Per Hedbor  string cvs;
e493e81997-07-11Per Hedbor  array st;
08065d1997-05-27Per Hedbor  sscanf(s, "/cvs:%s", cvs);
82f5191997-03-02Per Hedbor // perror("Module is "+s+"?");
e493e81997-07-11Per Hedbor  if(st=file_stat(s+".pike"))
5e89211997-02-13Per Hedbor  {
82f5191997-03-02Per Hedbor // perror("Yes, compile "+s+"?");
08065d1997-05-27Per Hedbor  if((cvs?(__p=master()->cvs_load_file( cvs+".pike" ))
34447f1998-03-20Per Hedbor  :(__p=my_compile_file(s+".pike"))))
14179b1997-01-29Per Hedbor  {
82f5191997-03-02Per Hedbor // perror("Yes.");
14179b1997-01-29Per Hedbor  my_loaded[__p]=s+".pike";
e493e81997-07-11Per Hedbor  module_stat_cache[s-dirname(s)]=st;
8c62221997-08-06Henrik Grubbström (Grubba)  return __p(conf);
5e89211997-02-13Per Hedbor  } else perror(s+".pike exists, but compilation failed.\n"); }
e493e81997-07-11Per Hedbor  if(st=file_stat(s+".lpc"))
08065d1997-05-27Per Hedbor  if(cvs?(__p=master()->cvs_load_file( cvs+".lpc" )):
34447f1998-03-20Per Hedbor  (__p=my_compile_file(s+".lpc")))
2a2a5b1996-12-01Per Hedbor  { my_loaded[__p]=s+".lpc";
e493e81997-07-11Per Hedbor  module_stat_cache[s-dirname(s)]=st;
8c62221997-08-06Henrik Grubbström (Grubba)  return __p(conf);
5e89211997-02-13Per Hedbor  } else perror(s+".lpc exists, but compilation failed.\n");
e493e81997-07-11Per Hedbor  if(st=file_stat(s+".module"))
5e89211997-02-13Per Hedbor  if(__p=load_module(s+".so"))
2a2a5b1996-12-01Per Hedbor  {
5e89211997-02-13Per Hedbor  my_loaded[__p]=s+".so";
e493e81997-07-11Per Hedbor  module_stat_cache[s-dirname(s)]=st;
8c62221997-08-06Henrik Grubbström (Grubba)  return __p(conf);
5e89211997-02-13Per Hedbor  } else perror(s+".so exists, but compilation failed.\n");
b1fca01996-11-12Per Hedbor  return 0; // FAILED.. }
ab2f671996-11-12Mirar (Pontus Hagland) array(string) expand_dir(string d)
5e4ede1996-11-12Per Hedbor { string nd;
ab2f671996-11-12Mirar (Pontus Hagland)  array(string) dirs=({d});
5e4ede1996-11-12Per Hedbor 
5e89211997-02-13Per Hedbor //perror("Expand dir "+d+"\n");
82f5191997-03-02Per Hedbor  catch { foreach((get_dir(d) || ({})) - ({"CVS"}) , nd) if(file_stat(d+nd)[1]==-2) dirs+=expand_dir(d+nd+"/"); }; // This catch is needed....
ab2f671996-11-12Mirar (Pontus Hagland)  return dirs;
5e4ede1996-11-12Per Hedbor }
ab2f671996-11-12Mirar (Pontus Hagland) array(string) last_dirs=0,last_dirs_expand;
8c62221997-08-06Henrik Grubbström (Grubba) object load_from_dirs(array dirs, string f, object conf)
14179b1997-01-29Per Hedbor { string dir; object o;
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  if (dirs!=last_dirs) {
5e89211997-02-13Per Hedbor  last_dirs_expand=({}); foreach(dirs, dir) last_dirs_expand+=expand_dir(dir);
14179b1997-01-29Per Hedbor  }
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  foreach (last_dirs_expand,dir)
8c62221997-08-06Henrik Grubbström (Grubba)  if ( (o=load(dir+f, conf)) ) return o;
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  return 0; }
6ca8f61998-10-13Per Hedbor 
ee8b201998-07-13David Hedbor static int abs_started;
6ca8f61998-10-13Per Hedbor  void restart_if_stuck (int force) {
ee8b201998-07-13David Hedbor  remove_call_out(restart_if_stuck); if (!(QUERY(abs_engage) || force))
edc9af1998-07-11David Hedbor  return;
6ca8f61998-10-13Per Hedbor  if(!abs_started) {
ee8b201998-07-13David Hedbor  abs_started = 1;
dca5dc1998-09-12Per Hedbor  roxen_perror("Anti-Block System Enabled.\n");
ee8b201998-07-13David Hedbor  } call_out (restart_if_stuck,10);
6ca8f61998-10-13Per Hedbor  signal(signum("SIGALRM"), lambda( int n ) { roxen_perror(master()->describe_backtrace( ({ sprintf("**** %s: ABS engaged! Trying to dump backlog: \n", ctime(time()) - "\n"), backtrace() }) ) ); _exit(1); // It might now quit correctly otherwise, if it's // locked up });
ee8b201998-07-13David Hedbor  alarm (60*QUERY(abs_timeout)+10);
edc9af1998-07-11David Hedbor }
6ca8f61998-10-13Per Hedbor void post_create () {
ee8b201998-07-13David Hedbor  if (QUERY(abs_engage)) call_out (restart_if_stuck,10);
edc9af1998-07-11David Hedbor  if (QUERY(suicide_engage))
ee8b201998-07-13David Hedbor  call_out (restart,60*60*24*QUERY(suicide_timeout));
edc9af1998-07-11David Hedbor }
14179b1997-01-29Per Hedbor void create()
b1fca01996-11-12Per Hedbor {
59912f1998-10-15Henrik Grubbström (Grubba)  SET_LOCALE(default_locale);
9b9f701997-08-12Per Hedbor  catch { module_stat_cache = decode_value(Stdio.read_bytes(".module_stat_cache")); allmodules = decode_value(Stdio.read_bytes(".allmodules")); };
5e89211997-02-13Per Hedbor  add_constant("roxen", this_object());
aaef2a1997-03-02Henrik Grubbström (Grubba)  add_constant("load", load);
82f5191997-03-02Per Hedbor  (object)"color.pike";
fb7ef91998-11-02Per Hedbor  fonts = (object)"fonts.pike";
14179b1997-01-29Per Hedbor  Configuration = (program)"configuration";
ee8b201998-07-13David Hedbor  call_out(post_create,1); //we just want to delay some things a little
b1fca01996-11-12Per Hedbor } // Get the current domain. This is not as easy as one could think.
2674801998-04-11Henrik Grubbström (Grubba) string get_domain(int|void l)
b1fca01996-11-12Per Hedbor { array f; string t, s; // ConfigurationURL is set by the 'install' script. if(!(!l && sscanf(QUERY(ConfigurationURL), "http://%s:%*s", s))) {
6ca8f61998-10-13Per Hedbor #if constant(gethostbyname) && constant(gethostname)
b1fca01996-11-12Per Hedbor  f = gethostbyname(gethostname()); // First try.. if(f)
ea9a311997-03-01Henrik Grubbström (Grubba)  foreach(f, f) if (arrayp(f)) { foreach(f, t) if(search(t, ".") != -1 && !(int)t) if(!s || strlen(s) < strlen(t)) s=t; }
b1fca01996-11-12Per Hedbor #endif if(!s) {
e5bad21998-02-10Per Hedbor  t = Stdio.read_bytes("/etc/resolv.conf");
b1fca01996-11-12Per Hedbor  if(t) { if(!sscanf(t, "domain %s\n", s)) if(!sscanf(t, "search %s%*[ \t\n]", s)) s="nowhere"; } else { s="nowhere"; } s = "host."+s; } } sscanf(s, "%*s.%s", s); if(s && strlen(s)) { if(s[-1] == '.') s=s[..strlen(s)-2]; if(s[0] == '.') s=s[1..]; } else { s="unknown"; } return s; } // This is the most likely URL for a virtual server. Again, this // should move into the actual 'configuration' object. It is not all // that nice to have all this code lying around in here. private string get_my_url() { string s;
6ca8f61998-10-13Per Hedbor #if constant(gethostname)
b1fca01996-11-12Per Hedbor  s = (gethostname()/".")[0] + "." + query("Domain");
c79b261998-02-05Johan Schön #else s = "localhost"; #endif
b1fca01996-11-12Per Hedbor  s -= "\n"; return "http://" + s + "/"; }
14179b1997-01-29Per Hedbor // Set the uid and gid to the ones requested by the user. If the sete* // functions are available, and the define SET_EFFECTIVE is enabled, // the euid and egid is set. This might be a minor security hole, but // it will enable roxen to start CGI scripts with the correct // permissions (the ones the owner of that script have).
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor int set_u_and_gid()
b1fca01996-11-12Per Hedbor {
c79b261998-02-05Johan Schön #ifndef __NT__
14179b1997-01-29Per Hedbor  string u, g; array pw;
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  u=QUERY(User);
8662771997-08-12Per Hedbor  sscanf(u, "%s:%s", u, g); if(strlen(u))
14179b1997-01-29Per Hedbor  { if(getuid()) { perror("It is not possible to change uid and gid if the server\n" "is not started as root.\n"); } else {
8662771997-08-12Per Hedbor  if(pw = getpwnam(u)) { u = (string)pw[2]; if(!g) g = (string)pw[3]; } else pw = getpwuid((int)u);
6ca8f61998-10-13Per Hedbor #if constant(initgroups)
d0da251997-09-08David Hedbor  catch { if(pw) initgroups(pw[0], (int)g); // Doesn't always work - David. };
b1fca01996-11-12Per Hedbor #endif
6ca8f61998-10-13Per Hedbor #if constant(setuid)
08152b1998-04-24Per Hedbor  if(QUERY(permanent_uid)) {
6ca8f61998-10-13Per Hedbor #if constant(setgid)
08152b1998-04-24Per Hedbor  setgid((int)g); #endif setuid((int)u);
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->setting_uid_gid_permanently((int)u, (int)g));
08152b1998-04-24Per Hedbor  } else { #endif
6ca8f61998-10-13Per Hedbor #if constant(setegid)
08152b1998-04-24Per Hedbor  setegid((int)g);
14179b1997-01-29Per Hedbor #else
08152b1998-04-24Per Hedbor  setgid((int)g);
14179b1997-01-29Per Hedbor #endif
6ca8f61998-10-13Per Hedbor #if constant(seteuid)
08152b1998-04-24Per Hedbor  seteuid((int)u);
14179b1997-01-29Per Hedbor #else
08152b1998-04-24Per Hedbor  setuid((int)u); #endif
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->setting_uid_gid((int)u, (int)g));
08152b1998-04-24Per Hedbor  return 1;
6ca8f61998-10-13Per Hedbor #if constant(setuid)
08152b1998-04-24Per Hedbor  }
14179b1997-01-29Per Hedbor #endif } }
c79b261998-02-05Johan Schön #endif
14179b1997-01-29Per Hedbor }
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor static mapping __vars = ([ ]);
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor // These two should be documented somewhere. They are to be used to // set global, but non-persistent, variables in Roxen. By using // these functions modules can "communicate" with one-another. This is // not really possible otherwise. mixed set_var(string var, mixed to) {
29527f1998-05-04Marcus Comstedt  return __vars[var] = to;
14179b1997-01-29Per Hedbor }
ba73a21996-12-10Per Hedbor 
14179b1997-01-29Per Hedbor mixed query_var(string var) { return __vars[var]; }
b1fca01996-11-12Per Hedbor 
65924d1998-07-24David Hedbor void reload_all_configurations() { object conf; array (object) new_confs = ({}); mapping config_cache = ([]);
6ca8f61998-10-13Per Hedbor  // werror(sprintf("%O\n", config_stat_cache));
65924d1998-07-24David Hedbor  int modified;
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->reloading_config_interface());
6ca8f61998-10-13Per Hedbor  configs = ([]); setvars(retrieve("Variables", 0)); initiate_configuration_port( 0 );
65924d1998-07-24David Hedbor 
6ca8f61998-10-13Per Hedbor  foreach(list_all_configurations(), string config)
65924d1998-07-24David Hedbor  { array err, st;
6ca8f61998-10-13Per Hedbor  foreach(configurations, conf)
65924d1998-07-24David Hedbor  { if(lower_case(conf->name) == lower_case(config)) { break; } else conf = 0; }
6ca8f61998-10-13Per Hedbor  if(!(st = config_is_modified(config))) {
65924d1998-07-24David Hedbor  if(conf) {
6ca8f61998-10-13Per Hedbor  config_cache[config] = config_stat_cache[config];
65924d1998-07-24David Hedbor  new_confs += ({ conf }); } continue; } modified = 1; config_cache[config] = st; if(conf) { // Closing ports... if (conf->server_ports) { // Roxen 1.2.26 or later
6ca8f61998-10-13Per Hedbor  Array.map(values(conf->server_ports), destruct);
65924d1998-07-24David Hedbor  } else {
6ca8f61998-10-13Per Hedbor  Array.map(indices(conf->open_ports), destruct);
65924d1998-07-24David Hedbor  } conf->stop(); conf->invalidate_cache(); conf->modules = ([]); conf->create(conf->name); } else { if(err = catch {
6ca8f61998-10-13Per Hedbor  conf = enable_configuration(config);
65924d1998-07-24David Hedbor  }) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE-> error_enabling_configuration(config, describe_backtrace(err)));
65924d1998-07-24David Hedbor  continue; } } if(err = catch { conf->start(); conf->enable_all_modules(); }) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE-> error_enabling_configuration(config, describe_backtrace(err)));
65924d1998-07-24David Hedbor  continue; } new_confs += ({ conf }); }
6ca8f61998-10-13Per Hedbor  foreach(configurations - new_confs, conf)
65924d1998-07-24David Hedbor  { modified = 1;
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->disabling_configuration(conf->name));
65924d1998-07-24David Hedbor  if (conf->server_ports) { // Roxen 1.2.26 or later
6ca8f61998-10-13Per Hedbor  Array.map(values(conf->server_ports), destruct);
65924d1998-07-24David Hedbor  } else {
6ca8f61998-10-13Per Hedbor  Array.map(indices(conf->open_ports), destruct);
65924d1998-07-24David Hedbor  } conf->stop(); destruct(conf); } if(modified) {
6ca8f61998-10-13Per Hedbor  configurations = new_confs; config_stat_cache = config_cache; unload_configuration_interface();
65924d1998-07-24David Hedbor  } }
14179b1997-01-29Per Hedbor object enable_configuration(string name) { object cf = Configuration(name); configurations += ({ cf });
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->enabled_server(name));
ce4ac81997-09-08David Hedbor 
14179b1997-01-29Per Hedbor  return cf;
b1fca01996-11-12Per Hedbor } // Enable all configurations
8662771997-08-12Per Hedbor void enable_configurations()
b1fca01996-11-12Per Hedbor {
14179b1997-01-29Per Hedbor  array err;
b1fca01996-11-12Per Hedbor  enabling_configurations = 1;
48fa361997-04-05Per Hedbor  configurations = ({}); foreach(list_all_configurations(), string config) { if(err=catch { enable_configuration(config)->start(); })
ce4ac81997-09-08David Hedbor  perror("Error while loading configuration "+config+":\n"+ describe_backtrace(err)+"\n"); }; foreach(configurations, object config) { if(err=catch { config->enable_all_modules(); }) perror("Error while loading modules in configuration "+config->name+":\n"+
48fa361997-04-05Per Hedbor  describe_backtrace(err)+"\n");
b1fca01996-11-12Per Hedbor  }; enabling_configurations = 0; } // return the URL of the configuration interface. This is not as easy // as it sounds, unless the administrator has entered it somewhere. public string config_url() { if(strlen(QUERY(ConfigurationURL)-" ")) return QUERY(ConfigurationURL)-" "; array ports = QUERY(ConfigPorts), port, tmp; if(!sizeof(ports)) return "CONFIG"; int p; string prot; string host; foreach(ports, tmp)
9f46de1997-04-08Per Hedbor  if(tmp[1][0..2]=="ssl")
b1fca01996-11-12Per Hedbor  { port=tmp; break; } if(!port) foreach(ports, tmp) if(tmp[1]=="http") { port=tmp; break; } if(!port) port=ports[0]; if(port[2] == "ANY") // host = quick_ip_to_host( port[2] ); // else { #if efun(gethostname) host = gethostname(); #else host = "127.0.0.1"; #endif }
4ba6fc1998-04-03Henrik Grubbström (Grubba)  switch(port[1][..2]) { case "ssl": prot = "https"; break; case "ftp": prot = "ftp"; break; default: prot = port[1]; break; }
b1fca01996-11-12Per Hedbor  p = port[0]; return (prot+"://"+host+":"+p+"/"); } // The following three functions are used to hide variables when they // are not used. This makes the user-interface clearer and quite a lot // less clobbered. int cache_disabled_p() { return !QUERY(cache); } int syslog_disabled() { return QUERY(LogA)!="syslog"; }
71a11e1997-08-13Henrik Grubbström (Grubba) private int ident_disabled_p() { return QUERY(default_ident); }
b1fca01996-11-12Per Hedbor  private void define_global_variables( int argc, array (string) argv ) { int p;
c31f7b1998-10-10Henrik Grubbström (Grubba)  // FIXME: LOCALE!
9b9f701997-08-12Per Hedbor  globvar("set_cookie", 0, "Set unique user id cookies", TYPE_FLAG,
89786e1997-10-09Peter Bortas  "If set to Yes, all users of your server whose clients support "
b1fca01996-11-12Per Hedbor  "cookies will get a unique 'user-id-cookie', this can then be " "used in the log and in scripts to track individual users.");
9b9f701997-08-12Per Hedbor  globvar("set_cookie_only_once",1,"Set ID cookies only once",TYPE_FLAG,
89786e1997-10-09Peter Bortas  "If set to Yes, Roxen will attempt to set unique user ID cookies " "only upon receiving the first request (and again after some " "minutes). Thus, if the user doesn't allow the cookie to be set, "
b2d16e1998-09-17Martin Stjernholm  "he won't be bothered with multiple requests.",0,
a773c61997-07-06Henrik Grubbström (Grubba)  lambda() {return !QUERY(set_cookie);});
b1fca01996-11-12Per Hedbor  globvar("show_internals", 1, "Show the internals", TYPE_FLAG, "Show 'Internal server error' messages to the user. " "This is very useful if you are debugging your own modules "
d8aa651996-12-09David Hedbor  "or writing Pike scripts.");
b1fca01996-11-12Per Hedbor 
1e5ee81997-08-21Per Hedbor  // Hidden variables (compatibility ones, or internal or too // dangerous
edc9af1998-07-11David Hedbor  /* globvar("BS", 0, "Configuration interface: Compact layout",*/ /* TYPE_FLAG|VAR_EXPERT,*/ /* "Sick and tired of all those images? Set this variable to 'Yes'!");*/ /* globvar("BG", 1, "Configuration interface: Background",*/ /* TYPE_FLAG|VAR_EXPERT,*/ /* "Should the background be set by the configuration interface?");*/
1e5ee81997-08-21Per Hedbor 
dca5dc1998-09-12Per Hedbor // globvar("_v", CONFIGURATION_FILE_LEVEL, 0, TYPE_INT, 0, 0, 1);
8e727d1997-03-11Per Hedbor  globvar("default_font_size", 32, 0, TYPE_INT, 0, 0, 1);
1e5ee81997-08-21Per Hedbor 
8e727d1997-03-11Per Hedbor  globvar("default_font", "lucida", "Fonts: Default font", TYPE_FONT, "The default font to use when modules request a font.");
06f6b01997-09-03Henrik Grubbström (Grubba)  globvar("font_dirs", ({"../local/nfonts/", "nfonts/" }),
85a2e51997-06-23Per Hedbor  "Fonts: Font directories", TYPE_DIR_LIST,
8e727d1997-03-11Per Hedbor  "This is where the fonts are located.");
e4bc531996-11-15Per Hedbor 
9b9f701997-08-12Per Hedbor  globvar("logdirprefix", "../logs/", "Log directory prefix", TYPE_DIR|VAR_MORE,
e4bc531996-11-15Per Hedbor  "This is the default file path that will be prepended to the log " " file path in all the default modules and the virtual server.");
b1fca01996-11-12Per Hedbor  // Cache variables. The actual code recides in the file // 'disk_cache.pike' globvar("cache", 0, "Proxy disk cache: Enabled", TYPE_FLAG,
89786e1997-10-09Peter Bortas  "If set to Yes, caching will be enabled.");
b1fca01996-11-12Per Hedbor  globvar("garb_min_garb", 1, "Proxy disk cache: Clean size", TYPE_INT,
b2d16e1998-09-17Martin Stjernholm  "Minimum number of Megabytes removed when a garbage collect is done.",
b1fca01996-11-12Per Hedbor  0, cache_disabled_p); globvar("cache_minimum_left", 5, "Proxy disk cache: Minimum "
f8978c1997-03-20Wilhelm Köhler  "available free space and inodes (in %)", TYPE_INT, "If less than this amount of disk space or inodes (in %) is left, "
89786e1997-10-09Peter Bortas  "the cache will remove a few files. This check may work " "half-hearted if the diskcache is spread over several filesystems.",
3aaaa71997-06-12Wilhelm Köhler  0,
6ca8f61998-10-13Per Hedbor #if constant(filesystem_stat)
3aaaa71997-06-12Wilhelm Köhler  cache_disabled_p #else 1 #endif /* filesystem_stat */ );
b1fca01996-11-12Per Hedbor  globvar("cache_size", 25, "Proxy disk cache: Size", TYPE_INT,
edc9af1998-07-11David Hedbor  "How many MB may the cache grow to before a garbage collect is done?",
b1fca01996-11-12Per Hedbor  0, cache_disabled_p);
f8978c1997-03-20Wilhelm Köhler  globvar("cache_max_num_files", 0, "Proxy disk cache: Maximum number " "of files", TYPE_INT, "How many cache files (inodes) may " "be on disk before a garbage collect is done ? May be left " "zero to disable this check.", 0, cache_disabled_p);
b1fca01996-11-12Per Hedbor  globvar("bytes_per_second", 50, "Proxy disk cache: Bytes per second", TYPE_INT, "How file size should be treated during garbage collect. " " Each X bytes counts as a second, so that larger files will" " be removed first.", 0, cache_disabled_p);
88e1cb1996-12-07David Hedbor  globvar("cachedir", "/tmp/roxen_cache/", "Proxy disk cache: Base Cache Dir",
b1fca01996-11-12Per Hedbor  TYPE_DIR, "This is the base directory where cached files will reside. " "To avoid mishaps, 'roxen_cache/' is always prepended to this " "variable.", 0, cache_disabled_p);
e4bc531996-11-15Per Hedbor  globvar("hash_num_dirs", 500, "Proxy disk cache: Number of hash directories", TYPE_INT, "This is the number of directories to hash the contents of the disk " "cache into. Changing this value currently invalidates the whole " "cache, since the cache cannot find the old files. In the future, "
88e1cb1996-12-07David Hedbor  " the cache will be recalculated when this value is changed.", 0, cache_disabled_p);
e4bc531996-11-15Per Hedbor 
f8978c1997-03-20Wilhelm Köhler  globvar("cache_keep_without_content_length", 1, "Proxy disk cache: " "Keep without Content-Length", TYPE_FLAG, "Keep files "
b2d16e1998-09-17Martin Stjernholm  "without Content-Length header information in the cache?",
f8978c1997-03-20Wilhelm Köhler  0, cache_disabled_p); globvar("cache_check_last_modified", 0, "Proxy disk cache: "
89786e1997-10-09Peter Bortas  "Refresh on Last-Modified", TYPE_FLAG, "If set, refreshes files without Expire header information " "when they have reached double the age they had when they got " "cached. This may be useful for some regularly updated docs as " "online newspapers.",
f8978c1997-03-20Wilhelm Köhler  0, cache_disabled_p);
a0b4fd1997-08-15Henrik Grubbström (Grubba)  globvar("cache_last_resort", 0, "Proxy disk cache: "
89786e1997-10-09Peter Bortas  "Last resort (in days)", TYPE_INT, "How many days shall files without Expires and without "
b2d16e1998-09-17Martin Stjernholm  "Last-Modified header information be kept?",
f8978c1997-03-20Wilhelm Köhler  0, cache_disabled_p); globvar("cache_gc_logfile", "", "Proxy disk cache: " "Garbage collector logfile", TYPE_FILE, "Information about garbage collector runs, removed and refreshed " "files, cache and disk status goes here.",
48fa361997-04-05Per Hedbor  0, cache_disabled_p);
f8978c1997-03-20Wilhelm Köhler 
e4bc531996-11-15Per Hedbor  /// End of cache variables..
b1fca01996-11-12Per Hedbor 
953ca31997-08-18Per Hedbor  globvar("docurl2", "http://www.roxen.com/documentation/context.pike?page=", "Documentation URL", TYPE_STRING|VAR_MORE,
edc9af1998-07-11David Hedbor  "The URL to prepend to all documentation urls throughout the " "server. This URL should _not_ end with a '/'.");
b1fca01996-11-12Per Hedbor  globvar("pidfile", "/tmp/roxen_pid:$uid", "PID file",
9b9f701997-08-12Per Hedbor  TYPE_FILE|VAR_MORE,
b1fca01996-11-12Per Hedbor  "In this file, the server will write out it's PID, and the PID " "of the start script. $pid will be replaced with the pid, and " "$uid with the uid of the user running the process.");
71a11e1997-08-13Henrik Grubbström (Grubba)  globvar("default_ident", 1, "Identify: Use default identification string", TYPE_FLAG|VAR_MORE,
89786e1997-10-09Peter Bortas  "Setting this variable to No will display the \"Identify as\" node " "where you can state what Roxen should call itself when talking " "to clients, otherwise it will present it self as \""+ real_version +"\".<br>" "It is possible to disable this so that you can enter an "
71a11e1997-08-13Henrik Grubbström (Grubba)  "identification-string that does not include the actual version of " "Roxen, as recommended by the HTTP/1.0 draft 03:<p><blockquote><i>"
b1fca01996-11-12Per Hedbor  "Note: Revealing the specific software version of the server " "may allow the server machine to become more vulnerable to " "attacks against software that is known to contain security " "holes. Server implementors are encouraged to make this field " "a configurable option.</i></blockquote>");
89786e1997-10-09Peter Bortas 
71a11e1997-08-13Henrik Grubbström (Grubba)  globvar("ident", replace(real_version," ","·"), "Identify: Identify as", TYPE_STRING /* |VAR_MORE */,
89786e1997-10-09Peter Bortas  "Enter the name that Roxen should use when talking to clients. ",
71a11e1997-08-13Henrik Grubbström (Grubba)  0, ident_disabled_p);
b1fca01996-11-12Per Hedbor 
9b9f701997-08-12Per Hedbor  globvar("DOC", 1, "Configuration interface: Help texts", TYPE_FLAG|VAR_MORE,
b1fca01996-11-12Per Hedbor  "Do you want documentation? (this is an example of documentation)");
89786e1997-10-09Peter Bortas  globvar("NumAccept", 1, "Number of accepts to attempt", TYPE_INT_LIST|VAR_MORE, "You can here state the maximum number of accepts to attempt for " "each read callback from the main socket. <p> Increasing this value " "will make the server " "faster for users making many simultaneous connections to it, or"
b1fca01996-11-12Per Hedbor  " if you have a very busy server. <p> It won't work on some systems" ", though, eg. IBM AIX 3.2<p> To see if it works, change this" " variable, <b> but don't press save</b>, and then try connecting to" " your server. If it works, come back here and press the save button"
89786e1997-10-09Peter Bortas  ". <p> If it doesn't work, just restart the server and be happy "
b1fca01996-11-12Per Hedbor  "with having '1' in this field.<p>"
89786e1997-10-09Peter Bortas  "The higher you set this value, the less load balancing between " "virtual servers. (If there are 256 more or less simultaneous "
b1fca01996-11-12Per Hedbor  "requests to server 1, and one to server 2, and this variable is "
89786e1997-10-09Peter Bortas  "set to 256, the 256 accesses to the first server might very well " "be handled before the one to the second server.)",
14179b1997-01-29Per Hedbor  ({ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 }));
b1fca01996-11-12Per Hedbor  globvar("ConfigPorts", ({ ({ 22202, "http", "ANY", "" }) }), "Configuration interface: Ports", TYPE_PORTS,
b2d16e1998-09-17Martin Stjernholm  "These are the ports through which you can configure the "
89786e1997-10-09Peter Bortas  "server.<br>Note that you should at least have one open port, since " "otherwise you won't be able to configure your server.");
b1fca01996-11-12Per Hedbor  globvar("ConfigurationURL", "", "Configuration interface: URL", TYPE_STRING, "The URL of the configuration interface. This is used to " "generate redirects now and then (when you press save, when " "a module is added, etc.)."); globvar("ConfigurationPassword", "", "Configuration interface: Password",
8662771997-08-12Per Hedbor  TYPE_PASSWORD|VAR_EXPERT,
b1fca01996-11-12Per Hedbor  "The password you will have to enter to use the configuration " "interface. Please note that changing this password in the " "configuration interface will _not_ require an additional entry " "of the password, so it is easy to make a typo. It is recommended " "that you use the <a href=/(changepass)/Globals/>form instead</a>."); globvar("ConfigurationUser", "", "Configuration interface: User",
8662771997-08-12Per Hedbor  TYPE_STRING|VAR_EXPERT,
b1fca01996-11-12Per Hedbor  "The username you will have to enter to use the configuration " "interface");
8662771997-08-12Per Hedbor  globvar("ConfigurationIPpattern","*", "Configuration interface: IP-Pattern",
9b9f701997-08-12Per Hedbor  TYPE_STRING|VAR_MORE,
b2d16e1998-09-17Martin Stjernholm  "Only clients running on computers with IP numbers matching " "this pattern will be able to use the configuration "
89786e1997-10-09Peter Bortas  "interface.");
b1fca01996-11-12Per Hedbor  globvar("User", "", "Change uid and gid to", TYPE_STRING, "When roxen is run as root, to be able to open port 80 "
8662771997-08-12Per Hedbor  "for listening, change to this user-id and group-id when the port "
1e5ee81997-08-21Per Hedbor  " has been opened. If you specify a symbolic username, the " "default group of that user will be used. " "The syntax is user[:group].");
70f2771997-12-15Per Hedbor 
08152b1998-04-24Per Hedbor  globvar("permanent_uid", 0, "Change uid and gid permanently", TYPE_FLAG, "If this variable is set, roxen will set it's uid and gid " "permanently. This disables the 'exec script as user' fetures " "for CGI, and also access files as user in the filesystems, but " "it gives better security.");
06f6b01997-09-03Henrik Grubbström (Grubba)  globvar("ModuleDirs", ({ "../local/modules/", "modules/" }),
bbff021997-08-26Henrik Grubbström (Grubba)  "Module directories", TYPE_DIR_LIST,
89786e1997-10-09Peter Bortas  "This is a list of directories where Roxen should look for " "modules. Can be relative paths, from the "
01d0811996-11-12Mirar (Pontus Hagland)  "directory you started roxen, " + getcwd() + " this time."
b1fca01996-11-12Per Hedbor  " The directories are searched in order for modules."); globvar("Supports", "#include <etc/supports>\n",
9b9f701997-08-12Per Hedbor  "Client supports regexps", TYPE_TEXT_FIELD|VAR_MORE,
b1fca01996-11-12Per Hedbor  "What do the different clients support?\n<br>" "The default information is normally fetched from the file "+
01d0811996-11-12Mirar (Pontus Hagland)  getcwd()+"etc/supports, and the format is:<pre>"
b1fca01996-11-12Per Hedbor  "<a href=$docurl/configuration/regexp.html>regular-expression</a>" " feature, -feature, ...\n" "</pre>" "If '-' is prepended to the name of the feature, it will be removed" " from the list of features of that client. All patterns that match" " each given client-name are combined to form the final feature list" ". See the file etc/supports for examples.");
ba73a21996-12-10Per Hedbor  globvar("audit", 0, "Audit trail", TYPE_FLAG,
52dc091998-02-28Johan Schön  "If Audit trail is set to Yes, all changes of uid will be "
89786e1997-10-09Peter Bortas  "logged in the Event log.");
ba73a21996-12-10Per Hedbor 
b1fca01996-11-12Per Hedbor #if efun(syslog)
9b9f701997-08-12Per Hedbor  globvar("LogA", "file", "Logging method", TYPE_STRING_LIST|VAR_MORE,
b1fca01996-11-12Per Hedbor  "What method to use for logging, default is file, but " "syslog is also available. When using file, the output is really" " sent to stdout and stderr, but this is handled by the "
b2d16e1998-09-17Martin Stjernholm  "start script.",
b1fca01996-11-12Per Hedbor  ({ "file", "syslog" })); globvar("LogSP", 1, "Syslog: Log PID", TYPE_FLAG,
b2d16e1998-09-17Martin Stjernholm  "If set, the PID will be included in the syslog.", 0,
b1fca01996-11-12Per Hedbor  syslog_disabled); globvar("LogCO", 0, "Syslog: Log to system console", TYPE_FLAG, "If set and syslog is used, the error/debug message will be printed"
b2d16e1998-09-17Martin Stjernholm  " to the system console as well as to the system log.",
b1fca01996-11-12Per Hedbor  0, syslog_disabled); globvar("LogST", "Daemon", "Syslog: Log type", TYPE_STRING_LIST,
b2d16e1998-09-17Martin Stjernholm  "When using SYSLOG, which log type should be used.",
b1fca01996-11-12Per Hedbor  ({ "Daemon", "Local 0", "Local 1", "Local 2", "Local 3", "Local 4", "Local 5", "Local 6", "Local 7", "User" }), syslog_disabled); globvar("LogWH", "Errors", "Syslog: Log what", TYPE_STRING_LIST, "When syslog is used, how much should be sent to it?<br><hr>" "Fatal: Only messages about fatal errors<br>"+ "Errors: Only error or fatal messages<br>"+ "Warning: Warning messages as well<br>"+ "Debug: Debug messager as well<br>"+ "All: Everything<br>", ({ "Fatal", "Errors", "Warnings", "Debug", "All" }), syslog_disabled);
9b9f701997-08-12Per Hedbor  globvar("LogNA", "Roxen", "Syslog: Log as", TYPE_STRING,
b2d16e1998-09-17Martin Stjernholm  "When syslog is used, this will be the identification of the "
89786e1997-10-09Peter Bortas  "Roxen daemon. The entered value will be appended to all logs.", 0, syslog_disabled);
b1fca01996-11-12Per Hedbor #endif
14179b1997-01-29Per Hedbor #ifdef THREADS globvar("numthreads", 5, "Number of threads to run", TYPE_INT, "The number of simultaneous threads roxen will use.\n" "<p>Please note that even if this is one, Roxen will still "
3aaaa71997-06-12Wilhelm Köhler  "be able to serve multiple requests, using a select loop based " "system.\n"
b1fca01996-11-12Per Hedbor  "<i>This is quite useful if you have more than one CPU in " "your machine, or if you have a lot of slow NFS accesses.</i>");
14179b1997-01-29Per Hedbor #endif
b1fca01996-11-12Per Hedbor  globvar("AutoUpdate", 1, "Update the supports database automatically", TYPE_FLAG,
89786e1997-10-09Peter Bortas  "If set to Yes, the etc/supports file will be updated automatically "
a60c4c1997-07-03Henrik Grubbström (Grubba)  "from www.roxen.com now and then. This is recomended, since "
89786e1997-10-09Peter Bortas  "you will then automatically get supports information for new "
b1fca01996-11-12Per Hedbor  "clients, and new versions of old ones."); globvar("next_supports_update", time()+3600, "", TYPE_INT,"",0,1);
892c1c1997-10-08Henrik Grubbström (Grubba) 
ee8b201998-07-13David Hedbor  globvar("abs_engage", 0, "Anti-Block-System: Enable", TYPE_FLAG|VAR_MORE,
edc9af1998-07-11David Hedbor  "If set, it will enable the anti-block-system. " "This will restart the server after a configurable number of minutes if it " "locks up. If you are running in a single threaded environment heavy calculations " "will also halt the server. In multi-threaded mode bugs as eternal loops will not " "cause the server to reboot, since only one thread is blocked. In general there is " "no harm in having this option enabled. ");
ffa4a81998-07-21David Hedbor  globvar("abs_timeout", 5, "Anti-Block-System: Timeout", TYPE_INT_LIST | VAR_MORE,
edc9af1998-07-11David Hedbor  "If the server is unable to accept connection for this many " "minutes, it will be restarted. You need to find a balance: " "if set too low, the server will be restarted even if it's doing " "legal things (like generating many images), if set too high you will " "have long downtimes.", ({1,2,3,4,5,10,15}),
ee8b201998-07-13David Hedbor  lambda() {return !QUERY(abs_engage);}
edc9af1998-07-11David Hedbor  ); globvar ("suicide_engage", 0, "Automatic Restart: Enable", TYPE_FLAG|VAR_MORE, "If set, Roxen will automatically restart after a configurable number " "of days. Since Roxen uses a monolith, non-forking server " "model the process tends to grow in size over time. This is mainly due to " "heap fragmentation but also because of memory leaks." ); globvar("suicide_timeout", 7, "Automatic Restart: Timeout",
ffa4a81998-07-21David Hedbor  TYPE_INT_LIST|VAR_MORE,
edc9af1998-07-11David Hedbor  "Automatically restart the server after this many days.", ({1,2,3,4,5,6,7,14,30}), lambda(){return !QUERY(suicide_engage);} );
ee8b201998-07-13David Hedbor  setvars(retrieve("Variables", 0)); for(p = 1; p < argc; p++) { string c, v; if(sscanf(argv[p],"%s=%s", c, v) == 2) if(variables[c]) variables[c][VAR_VALUE]=compat_decode_value(v); else perror("Unknown variable: "+c+"\n"); } docurl=QUERY(docurl2);
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor 
88ba641997-12-04Per Hedbor // return all available fonts. Taken from the font_dirs list.
291a801997-07-10Per Hedbor array font_cache; array available_fonts(int cache) {
fb7ef91998-11-02Per Hedbor  if(cache && font_cache) return font_cache; return font_cache = fonts->available_fonts();
291a801997-07-10Per Hedbor }
14179b1997-01-29Per Hedbor 
b1fca01996-11-12Per Hedbor // Somewhat misnamed, since there can be more then one // configuration-interface port nowdays. But, anyway, this function // opens and listens to all configuration interface ports. void initiate_configuration_port( int|void first ) { object o; array port;
4f4bc11998-02-04Per Hedbor  // Hm. if(!first && !config_ports_changed ) return 0; config_ports_changed = 0;
23620b1998-04-09Henrik Grubbström (Grubba)  // First find out if we have any new ports. mapping(string:array(string)) new_ports = ([]); foreach(QUERY(ConfigPorts), port) {
72022f1998-07-07Henrik Grubbström (Grubba)  if ((< "ssl", "ssleay" >)[port[1]]) { // Obsolete versions of the SSL protocol.
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_warning(LOCALE->obsolete_ssl(port[1]));
72022f1998-07-07Henrik Grubbström (Grubba)  port[1] = "ssl3"; }
1c30601998-07-07Henrik Grubbström (Grubba)  string key = MKPORTKEY(port);
23620b1998-04-09Henrik Grubbström (Grubba)  if (!configuration_ports[key]) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->new_config_port(key));
23620b1998-04-09Henrik Grubbström (Grubba)  new_ports[key] = port; } else { // This is needed not to delete old unchanged ports. new_ports[key] = 0; } } // Then disable the old ones that are no more. foreach(indices(configuration_ports), string key) { if (zero_type(new_ports[key])) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->disable_config_port(key));
23620b1998-04-09Henrik Grubbström (Grubba)  object o = configuration_ports[key]; if (main_configuration_port == o) { main_configuration_port = 0; } m_delete(configuration_ports, key); mixed err; if (err = catch{ destruct(o); }) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_warning(LOCALE-> error_disabling_config_port(key, describe_backtrace(err)));
23620b1998-04-09Henrik Grubbström (Grubba)  } o = 0; // Be sure that there are no references left... } } // Now we can create the new ports. foreach(indices(new_ports), string key)
b1fca01996-11-12Per Hedbor  {
23620b1998-04-09Henrik Grubbström (Grubba)  port = new_ports[key]; if (port) {
39edcd1997-08-25Henrik Grubbström (Grubba)  array old = port; mixed erro; erro = catch { program requestprogram = (program)(getcwd()+"/protocols/"+port[1]); function rp; array tmp; if(!requestprogram) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->no_request_program(port[1]));
39edcd1997-08-25Henrik Grubbström (Grubba)  continue; } if(rp = requestprogram()->real_port) if(tmp = rp(port, 0)) port = tmp;
23620b1998-04-09Henrik Grubbström (Grubba)  // FIXME: For SSL3 we might need to be root to read our // secret files.
39edcd1997-08-25Henrik Grubbström (Grubba)  object privs; if(port[0] < 1024)
c31f7b1998-10-10Henrik Grubbström (Grubba)  privs = Privs(LOCALE->opening_low_port());
39edcd1997-08-25Henrik Grubbström (Grubba)  if(o=create_listen_socket(port[0],0,port[2],requestprogram,port)) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->opening_config_port(key));
23620b1998-04-09Henrik Grubbström (Grubba)  if (!main_configuration_port) { main_configuration_port = o; } configuration_ports[key] = o;
39edcd1997-08-25Henrik Grubbström (Grubba)  } else {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->could_not_open_config_port(key));
39edcd1997-08-25Henrik Grubbström (Grubba)  } }; if (erro) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->open_config_port_failed(key,
23620b1998-04-09Henrik Grubbström (Grubba)  (stringp(erro)?erro:describe_backtrace(erro))));
b1fca01996-11-12Per Hedbor  } }
727f701998-06-13Henrik Grubbström (Grubba)  } if(!main_configuration_port) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->no_config_port());
727f701998-06-13Henrik Grubbström (Grubba)  if(first) exit( -1 ); // Restart.
b1fca01996-11-12Per Hedbor  } }
e493e81997-07-11Per Hedbor #include <stat.h>
b1fca01996-11-12Per Hedbor // Find all modules, so a list of them can be presented to the // user. This is not needed when the server is started. void scan_module_dir(string d) {
6ad3161997-08-20Per Hedbor  if(sscanf(d, "%*s.pmod")!=0) return;
e493e81997-07-11Per Hedbor  MD_PERROR(("\n\nLooking for modules in "+d+" "));
01d0811996-11-12Mirar (Pontus Hagland)  string file,path=d; mixed err;
990b441997-07-18Per Hedbor  array q = (get_dir( d )||({})) - ({".","..","CVS","RCS" }); if(!sizeof(q)) {
3912ec1997-09-05Henrik Grubbström (Grubba)  MD_PERROR(("No modules in here. Continuing elsewhere\n"));
990b441997-07-18Per Hedbor  return; }
3bba751997-08-20Per Hedbor  if(search(q, ".no_modules")!=-1) {
3912ec1997-09-05Henrik Grubbström (Grubba)  MD_PERROR(("No modules in here. Continuing elsewhere\n"));
3bba751997-08-20Per Hedbor  return; }
e493e81997-07-11Per Hedbor  MD_PERROR(("There are "+language("en","number")(sizeof(q))+" files.\n"));
01d0811996-11-12Mirar (Pontus Hagland) 
e493e81997-07-11Per Hedbor  foreach( q, file )
b1fca01996-11-12Per Hedbor  {
0f8c871997-06-01Henrik Grubbström (Grubba)  _master->set_inhibit_compile_errors("");
fd0b6f1996-12-02Per Hedbor  if ( file[0]!='.' && !backup_extension(file) && (file[-1]!='z'))
b1fca01996-11-12Per Hedbor  {
e493e81997-07-11Per Hedbor  array stat = file_stat(path+file); if(!stat || (stat[ST_SIZE] < 0))
5e4ede1996-11-12Per Hedbor  {
e493e81997-07-11Per Hedbor  if(err = catch ( scan_module_dir(path+file+"/") )) MD_PERROR((sprintf("Error in module rescanning directory code:" " %s\n",describe_backtrace(err))));
0f8c871997-06-01Henrik Grubbström (Grubba)  } else {
e493e81997-07-11Per Hedbor  MD_PERROR(("Considering "+file+" - ")); if((module_stat_cache[path+file] && module_stat_cache[path+file][ST_MTIME])==stat[ST_MTIME]) { MD_PERROR(("Already tried this one.\n")); continue; } module_stat_cache[path+file]=stat;
28d38d1997-03-12Per Hedbor  switch(extension(file)) {
0f8c871997-06-01Henrik Grubbström (Grubba)  case "pike": case "lpc":
dd47911997-04-12Per Hedbor  if(catch{
0f8c871997-06-01Henrik Grubbström (Grubba)  if((open(path+file,"r")->read(4))=="#!NO") {
e382ed1997-07-16Henrik Grubbström (Grubba)  MD_PERROR(("Not a module\n"));
e493e81997-07-11Per Hedbor  file=0;
28d38d1997-03-12Per Hedbor  }
0f8c871997-06-01Henrik Grubbström (Grubba)  }) {
f1cee51997-06-06Henrik Grubbström (Grubba)  MD_PERROR(("Couldn't open file\n"));
e493e81997-07-11Per Hedbor  file=0;
0f8c871997-06-01Henrik Grubbström (Grubba)  }
e493e81997-07-11Per Hedbor  if(!file) break;
0f8c871997-06-01Henrik Grubbström (Grubba)  case "mod": case "so":
28d38d1997-03-12Per Hedbor  string *module_info; if (!(err=catch( module_info = lambda ( string file ) { array foo; object o;
6193221997-05-31Henrik Grubbström (Grubba)  program p;
0f8c871997-06-01Henrik Grubbström (Grubba) 
34447f1998-03-20Per Hedbor  if (catch(p = my_compile_file(file)) || (!p)) {
0f8c871997-06-01Henrik Grubbström (Grubba)  MD_PERROR((" compilation failed"));
3d0e7c1997-06-01Henrik Grubbström (Grubba)  throw("Compilation failed.\n");
6193221997-05-31Henrik Grubbström (Grubba)  }
68a0a21997-06-12Henrik Grubbström (Grubba)  // Set the module-filename, so that create in the // new object can get it.
6ca8f61998-10-13Per Hedbor  last_module_name = file;
68a0a21997-06-12Henrik Grubbström (Grubba) 
6193221997-05-31Henrik Grubbström (Grubba)  array err = catch(o = p());
6ca8f61998-10-13Per Hedbor  last_module_name = 0;
68a0a21997-06-12Henrik Grubbström (Grubba) 
6193221997-05-31Henrik Grubbström (Grubba)  if (err) {
0f8c871997-06-01Henrik Grubbström (Grubba)  MD_PERROR((" load failed"));
6193221997-05-31Henrik Grubbström (Grubba)  throw(err); } else if (!o) {
0f8c871997-06-01Henrik Grubbström (Grubba)  MD_PERROR((" load failed")); throw("Failed to initialize module.\n"); } else { MD_PERROR((" load ok - ")); if (!o->register_module) { MD_PERROR(("register_module missing")); throw("No registration function in module.\n"); }
6193221997-05-31Henrik Grubbström (Grubba)  } foo = o->register_module(); if (!foo) {
9957351998-10-11Peter Bortas  MD_PERROR(("registration failed.\n"));
566fdf1998-08-18Henrik Grubbström (Grubba)  return 0;
6193221997-05-31Henrik Grubbström (Grubba)  } else {
0f8c871997-06-01Henrik Grubbström (Grubba)  MD_PERROR(("registered."));
6193221997-05-31Henrik Grubbström (Grubba)  }
0f8c871997-06-01Henrik Grubbström (Grubba)  return({ foo[1], foo[2]+"<p><i>"+ replace(o->file_name_and_stuff(), "0<br>", file+"<br>") +"</i>", foo[0] }); }(path + file)))) { // Load OK
566fdf1998-08-18Henrik Grubbström (Grubba)  if (module_info) { // Module load OK. allmodules[ file-("."+extension(file)) ] = module_info; } else { // Disabled module.
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->disabled_module(path+file));
566fdf1998-08-18Henrik Grubbström (Grubba)  }
28d38d1997-03-12Per Hedbor  } else {
0f8c871997-06-01Henrik Grubbström (Grubba)  // Load failed.
9b9f701997-08-12Per Hedbor  module_stat_cache[path+file]=0;
28d38d1997-03-12Per Hedbor  _master->errors += "\n";
6193221997-05-31Henrik Grubbström (Grubba)  if (arrayp(err)) {
0f8c871997-06-01Henrik Grubbström (Grubba)  _master->errors += path + file + ": " + describe_backtrace(err) + "\n";
6193221997-05-31Henrik Grubbström (Grubba)  } else {
0f8c871997-06-01Henrik Grubbström (Grubba)  _master->errors += path + file + ": " + err;
6193221997-05-31Henrik Grubbström (Grubba)  }
28d38d1997-03-12Per Hedbor  }
b1fca01996-11-12Per Hedbor  }
0f8c871997-06-01Henrik Grubbström (Grubba)  MD_PERROR(("\n"));
b1fca01996-11-12Per Hedbor  } }
0f8c871997-06-01Henrik Grubbström (Grubba)  if(strlen(_master->errors)) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_debug(LOCALE->module_compilation_errors(d, _master->errors));
0f8c871997-06-01Henrik Grubbström (Grubba)  } _master->set_inhibit_compile_errors(0);
b1fca01996-11-12Per Hedbor  } } void rescan_modules() { string file, path; mixed err;
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->scanning_for_modules());
e382ed1997-07-16Henrik Grubbström (Grubba)  if (!allmodules) { allmodules=copy_value(somemodules); }
0f8c871997-06-01Henrik Grubbström (Grubba) 
b1fca01996-11-12Per Hedbor  foreach(QUERY(ModuleDirs), path) {
dd47911997-04-12Per Hedbor  array err; err = catch(scan_module_dir( path ));
6193221997-05-31Henrik Grubbström (Grubba)  if(err) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_error(LOCALE->module_scan_error(path, describe_backtrace(err)));
6193221997-05-31Henrik Grubbström (Grubba)  } }
9b9f701997-08-12Per Hedbor  catch { rm(".module_stat_cache"); rm(".allmodules"); Stdio.write_file(".module_stat_cache", encode_value(module_stat_cache)); Stdio.write_file(".allmodules", encode_value(allmodules)); };
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->module_scan_done(sizeof(allmodules)));
b1fca01996-11-12Per Hedbor } // do the chroot() call. This is not currently recommended, since // roxen dynamically loads modules, all module files must be // available at the new location. private void fix_root(string to) {
c79b261998-02-05Johan Schön #ifndef __NT__
b1fca01996-11-12Per Hedbor  if(getuid()) { perror("It is impossible to chroot() if the server is not run as root.\n"); return; } if(!chroot(to)) { perror("Roxen: Cannot chroot to "+to+": "); #if efun(real_perror) real_perror(); #endif return; } perror("Root is now "+to+".\n");
c79b261998-02-05Johan Schön #endif
b1fca01996-11-12Per Hedbor } void create_pid_file(string where) {
c79b261998-02-05Johan Schön #ifndef __NT__
b1fca01996-11-12Per Hedbor  if(!where) return; where = replace(where, ({ "$pid", "$uid" }), ({ (string)getpid(), (string)getuid() })); rm(where);
5e89211997-02-13Per Hedbor  if(catch(Stdio.write_file(where, sprintf("%d\n%d", getpid(), getppid()))))
b1fca01996-11-12Per Hedbor  perror("I cannot create the pid file ("+where+").\n");
c79b261998-02-05Johan Schön #endif
b1fca01996-11-12Per Hedbor }
6ca8f61998-10-13Per Hedbor 
beaca01998-02-20Per Hedbor void shuffle(object from, object to,
95e2b41997-05-25Wilhelm Köhler  object|void to2, function(:void)|void callback)
14179b1997-01-29Per Hedbor {
beaca01998-02-20Per Hedbor #if efun(spider.shuffle) if(!to2)
5bc1991997-01-29Per Hedbor  {
beaca01998-02-20Per Hedbor  object p = pipe(); p->input(from);
95e2b41997-05-25Wilhelm Köhler  p->set_done_callback(callback);
beaca01998-02-20Per Hedbor  p->output(to);
a60c4c1997-07-03Henrik Grubbström (Grubba)  } else {
beaca01998-02-20Per Hedbor #endif // 'smartpipe' does not support multiple outputs. object p = Pipe.pipe(); if (callback) p->set_done_callback(callback); p->output(to);
33b7701998-03-20Johan Schön  if(to2) p->output(to2);
beaca01998-02-20Per Hedbor  p->input(from); #if efun(spider.shuffle)
b1fca01996-11-12Per Hedbor  }
beaca01998-02-20Per Hedbor #endif
b1fca01996-11-12Per Hedbor }
3aaaa71997-06-12Wilhelm Köhler 
4f4bc11998-02-04Per Hedbor 
b1fca01996-11-12Per Hedbor static private int _recurse;
a9d8111998-09-01Henrik Grubbström (Grubba) // FIXME: Ought to use the shutdown code.
b1fca01996-11-12Per Hedbor void exit_when_done() { object o; int i;
c31f7b1998-10-10Henrik Grubbström (Grubba)  roxen_perror("Interrupt request received. Exiting,\n");
4f4bc11998-02-04Per Hedbor  die_die_die=1; // trace(9);
b1fca01996-11-12Per Hedbor  if(++_recurse > 4)
38dca81996-12-10Per Hedbor  {
dca5dc1998-09-12Per Hedbor  roxen_perror("Exiting roxen (spurious signals received).\n");
38dca81996-12-10Per Hedbor  stop_all_modules();
1f79ba1998-09-01Marcus Comstedt #ifdef THREADS stop_handler_threads(); #endif /* THREADS */
f6f0921998-05-08Henrik Grubbström (Grubba)  add_constant("roxen", 0); // Paranoia...
03af431998-07-14Henrik Grubbström (Grubba)  add_constant("roxenp", 0); // Paranoia...
3835ca1998-01-16Henrik Grubbström (Grubba)  exit(-1); // Restart. // kill(getpid(), 9); // kill(0, -9);
38dca81996-12-10Per Hedbor  }
14179b1997-01-29Per Hedbor 
b1fca01996-11-12Per Hedbor  // First kill off all listening sockets..
4f4bc11998-02-04Per Hedbor  foreach(indices(portno)||({}), o) { #ifdef THREADS
bfbd4d1998-04-07Henrik Grubbström (Grubba)  object fd = Stdio.File();
4f4bc11998-02-04Per Hedbor  fd->connect( portno[o][2]!="Any"?portno[o][2]:"127.0.0.1", portno[o][0] ); destruct(fd); #endif
6ca8f61998-10-13Per Hedbor  destruct(o);
4f4bc11998-02-04Per Hedbor  }
b1fca01996-11-12Per Hedbor  // Then wait for all sockets, but maximum 10 minutes.. call_out(lambda() {
aaef2a1997-03-02Henrik Grubbström (Grubba)  call_out(Simulate.this_function(), 5);
38dca81996-12-10Per Hedbor  if(!_pipe_debug()[0]) {
dca5dc1998-09-12Per Hedbor  roxen_perror("Exiting roxen (all connections closed).\n");
38dca81996-12-10Per Hedbor  stop_all_modules();
1f79ba1998-09-01Marcus Comstedt #ifdef THREADS stop_handler_threads(); #endif /* THREADS */
f6f0921998-05-08Henrik Grubbström (Grubba)  add_constant("roxen", 0); // Paranoia...
3835ca1998-01-16Henrik Grubbström (Grubba)  exit(-1); // Restart.
c31f7b1998-10-10Henrik Grubbström (Grubba)  roxen_perror("Odd. I am not dead yet.\n");
38dca81996-12-10Per Hedbor  } }, 0.1); call_out(lambda(){
dca5dc1998-09-12Per Hedbor  roxen_perror("Exiting roxen (timeout).\n");
38dca81996-12-10Per Hedbor  stop_all_modules();
1f79ba1998-09-01Marcus Comstedt #ifdef THREADS stop_handler_threads(); #endif /* THREADS */
f6f0921998-05-08Henrik Grubbström (Grubba)  add_constant("roxen", 0); // Paranoia...
a9d8111998-09-01Henrik Grubbström (Grubba)  exit(-1); // Restart.
38dca81996-12-10Per Hedbor  }, 600, 0); // Slow buggers..
b1fca01996-11-12Per Hedbor } void exit_it() { perror("Recursive signals.\n");
3835ca1998-01-16Henrik Grubbström (Grubba)  exit(-1); // Restart.
b1fca01996-11-12Per Hedbor } // And then we have the main function, this is the oldest function in // Roxen :) It has not changed all that much since Spider 2.0.
c856841998-01-21Henrik Grubbström (Grubba) int main(int|void argc, array (string)|void argv)
b1fca01996-11-12Per Hedbor {
59912f1998-10-15Henrik Grubbström (Grubba)  SET_LOCALE(default_locale);
c245691997-10-25Per Hedbor  initiate_languages();
b1fca01996-11-12Per Hedbor  mixed tmp;
60ecef1998-06-13Henrik Grubbström (Grubba)  start_time = boot_time = time();
b1fca01996-11-12Per Hedbor 
5e89211997-02-13Per Hedbor  add_constant("write", perror);
9b9f701997-08-12Per Hedbor 
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->starting_roxen());
b1fca01996-11-12Per Hedbor  mark_fd(0, "Stdin"); mark_fd(1, "Stdout"); mark_fd(2, "Stderr");
51643e1997-08-21Per Hedbor  configuration_dir =
6ca8f61998-10-13Per Hedbor  Getopt.find_option(argv, "d",({"config-dir","configuration-directory" }),
51643e1997-08-21Per Hedbor  ({ "ROXEN_CONFIGDIR", "CONFIGURATIONS" }), "../configurations");
b1fca01996-11-12Per Hedbor 
a92b951997-08-05Martin Stjernholm  if(configuration_dir[-1] != '/')
b1fca01996-11-12Per Hedbor  configuration_dir += "/";
0978ee1997-09-08David Hedbor  startpid = getppid();
e145221997-10-10David Hedbor  roxenpid = getpid();
6ca8f61998-10-13Per Hedbor  create_pid_file(Getopt.find_option(argv, "p", "pid-file", "ROXEN_PID_FILE"));
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  // Dangerous...
6ca8f61998-10-13Per Hedbor  if(tmp = Getopt.find_option(argv, "r", "root")) fix_root(tmp);
b1fca01996-11-12Per Hedbor  argv -= ({ 0 });
51643e1997-08-21Per Hedbor  argc = sizeof(argv);
b1fca01996-11-12Per Hedbor 
c31f7b1998-10-10Henrik Grubbström (Grubba)  roxen_perror("Restart initiated at "+ctime(time()));
af97431997-08-21Per Hedbor 
b1fca01996-11-12Per Hedbor  define_global_variables(argc, argv);
6420831997-08-21Per Hedbor 
b1fca01996-11-12Per Hedbor  create_pid_file(QUERY(pidfile)); #if efun(syslog) init_logger(); #endif init_garber(); initiate_supports();
0f28da1997-08-13Per Hedbor  initiate_configuration_port( 1 );
b1fca01996-11-12Per Hedbor  enable_configurations(); // Rebuild the configuration interface tree if the interface was // loaded before the configurations was enabled (a configuration is a // virtual server, perhaps the name should be changed internally as // well.. :-)
14179b1997-01-29Per Hedbor  if(root) { destruct(configuration_interface());
b1fca01996-11-12Per Hedbor  configuration_interface()->build_root(root);
14179b1997-01-29Per Hedbor  }
b1fca01996-11-12Per Hedbor  call_out(update_supports_from_roxen_com, QUERY(next_supports_update)-time()); if(set_u_and_gid())
c31f7b1998-10-10Henrik Grubbström (Grubba)  roxen_perror("Setting UID and GID ...\n");
b1fca01996-11-12Per Hedbor 
48fa361997-04-05Per Hedbor #ifdef THREADS start_handler_threads();
4f4bc11998-02-04Per Hedbor  catch( this_thread()->set_name("Backend") );
3aaaa71997-06-12Wilhelm Köhler #if efun(thread_set_concurrency)
41d0f91998-02-20Per Hedbor  thread_set_concurrency(QUERY(numthreads)+1);
48fa361997-04-05Per Hedbor #endif
4f4bc11998-02-04Per Hedbor 
34fbbc1998-02-05Henrik Grubbström (Grubba) #endif /* THREADS */
990cbb1997-08-12David Hedbor 
3835ca1998-01-16Henrik Grubbström (Grubba)  // Signals which cause a restart (exitcode != 0)
59912f1998-10-15Henrik Grubbström (Grubba)  foreach( ({ "SIGUSR1", "SIGUSR2", "SIGTERM" }), string sig) {
9b9f701997-08-12Per Hedbor  catch { signal(signum(sig), exit_when_done); };
b399651997-07-22Henrik Grubbström (Grubba)  }
65924d1998-07-24David Hedbor  catch { signal(signum("SIGHUP"), reload_all_configurations); };
3835ca1998-01-16Henrik Grubbström (Grubba)  // Signals which cause a shutdown (exitcode == 0)
59912f1998-10-15Henrik Grubbström (Grubba)  foreach( ({ "SIGINT" }), string sig) {
a9d8111998-09-01Henrik Grubbström (Grubba)  catch { signal(signum(sig), shutdown); };
3835ca1998-01-16Henrik Grubbström (Grubba)  }
0f28da1997-08-13Per Hedbor 
c31f7b1998-10-10Henrik Grubbström (Grubba)  report_notice(LOCALE->roxen_started(time()-start_time));
4f4bc11998-02-04Per Hedbor #ifdef __RUN_TRACE trace(1); #endif
08152b1998-04-24Per Hedbor  start_time=time(); // Used by the "uptime" info later on.
b1fca01996-11-12Per Hedbor  return -1; }
7a61de1998-03-26Per Hedbor  string diagnose_error(array from) { }
edc9af1998-07-11David Hedbor  // Called from the configuration interface.
ee8b201998-07-13David Hedbor string check_variable(string name, mixed value)
edc9af1998-07-11David Hedbor { switch(name) { case "ConfigPorts":
ee8b201998-07-13David Hedbor  config_ports_changed = 1; break;
edc9af1998-07-11David Hedbor  case "cachedir": if(!sscanf(value, "%*s/roxen_cache")) {
c31f7b1998-10-10Henrik Grubbström (Grubba)  // FIXME: LOCALE?
edc9af1998-07-11David Hedbor  object node; node = (configuration_interface()->root->descend("Globals", 1)-> descend("Proxy disk cache: Base Cache Dir", 1)); if(node && !node->changed) node->change(1); mkdirhier(value+"roxen_cache/foo"); call_out(set, 0, "cachedir", value+"roxen_cache/"); } break; case "ConfigurationURL": case "MyWorldLocation": if(strlen(value)<7 || value[-1] != '/' || !(sscanf(value,"%*s://%*s/")==2))
c31f7b1998-10-10Henrik Grubbström (Grubba)  return(LOCALE->url_format());
ee8b201998-07-13David Hedbor  break; case "abs_engage": if (value) restart_if_stuck(1); else remove_call_out(restart_if_stuck); break; case "suicide_engage": if (value) call_out(restart,60*60*24*QUERY(suicide_timeout)); else remove_call_out(restart); break;
edc9af1998-07-11David Hedbor  } }