roxen.lists.roxen.general

Subject Author Date
[PATCH 17/17] Support LOCALDIR preset everywhere Stephen R. van den Berg <srb[at]cuci[dot]nl> 20-01-2009
---

 server/base_server/config_userdb.pike              |    7 +++--
 server/base_server/read_config.pike                |   22 ++++++++------
 server/base_server/roxen.pike                      |   31 ++++++++------------
 server/base_server/roxenloader.pike                |   13 ++++++--
 .../config_interface/actions/change_version.pike   |    7 +++--
 server/config_interface/actions/debug_summary.pike |    6 +++-
 server/config_interface/actions/make_rsa_csr.pike  |    2 +
 .../actions/make_selfsigned_dsa.pike               |    3 +-
 .../actions/make_selfsigned_rsa.pike               |    3 +-
 .../actions/make_site_template.pike                |   13 ++++----
 server/config_interface/actions/ssl_common.pike    |    4 +--
 .../sites/create_site_with_template.pike           |   16 ++++++----
 server/config_interface/sites/drop_site.pike       |    2 +
 server/etc/modules/RoxenPatch.pmod                 |    4 +--
 server/etc/test/tests/RoxenTest_base.pike          |   10 ------
 .../modules/configuration/config_filesystem.pike   |    2 +
 server/modules/tags/rxmltags.pike                  |   12 +++++---
 server/start                                       |    3 +-
 server/tools/init.d_roxen                          |    3 ++
 19 files changed, 86 insertions(+), 77 deletions(-)

diff --git a/server/base_server/config_userdb.pike
b/server/base_server/config_userdb.pike
index f94eeaa..d07883e 100644
--- a/server/base_server/config_userdb.pike
+++ b/server/base_server/config_userdb.pike
@@ -14,7 +14,6 @@ inherit "language";
 //<locale-token project="roxen_config"> SLOCALE </locale-token>
 #define LOCALE(X,Y)	_DEF_LOCALE("roxen_config",X,Y)
 #define SLOCALE(X,Y)	_STR_LOCALE("roxen_config",X,Y)
-string query_configuration_dir();
 
 // Settings used by the various administration interface modules etc.
 class ConfigIFCache
@@ -32,7 +31,8 @@ class ConfigIFCache
   {
     if( _settings )
     {
-      dir = query_configuration_dir() + "_configinterface/" + name + "/";
+      dir = roxenloader.query_configuration_dir() + "_configinterface/"
+       + name + "/";
       mkdirhier( dir );
     }
     else
@@ -146,7 +146,8 @@ class ConfigurationSettings
     protected array(string) all_themes( )
     {
       return filter((get_dir( "config_interface/themes/" ) + 
-		     (get_dir( "../local/config_interface/themes/" )||({}))-
+		     (get_dir( roxenloader.query_local_dir()
+		      +"/config_interface/themes/" )||({}))-
 		     ()),
 		    lambda(string theme) {
 		      catch {
diff --git a/server/base_server/read_config.pike
b/server/base_server/read_config.pike
index 8aab1c4..dc4c936 100644
--- a/server/base_server/read_config.pike
+++ b/server/base_server/read_config.pike
@@ -17,20 +17,20 @@ import spider;
 #define COPY( X ) ((X||([])) + ([]))
 
 mapping (string:Stdio.Stat) config_stat_cache = ([]);
-string configuration_dir; // Set by Roxen.
 
 array(string) list_all_configurations()
 {
   array (string) fii;
-  fii=get_dir(configuration_dir);
+  fii=get_dir(roxenloader.query_configuration_dir());
   if(!fii)
   {
-    mkdirhier(configuration_dir+"test"); // removes the last element..
-    fii=get_dir(configuration_dir);
+    // removes the last element..
+    mkdirhier(roxenloader.query_configuration_dir()+"test");
+    fii=get_dir(roxenloader.query_configuration_dir());
     if(!fii)
     {
       report_fatal("I cannot read from the configurations directory ("+
-		   combine_path(getcwd(), configuration_dir)+")\n");
+	   combine_path(getcwd(), roxenloader.query_configuration_dir())+")\n");
       roxenloader.real_exit(-1); // Restart.
     }
     return ({});
@@ -79,7 +79,8 @@ private void really_save_it( string cl, mapping data, int
counter )
 	       cl, counter);
 #endif
 
-  f = configuration_dir + replace(string_to_utf8(cl), " ", "_");
+  f = roxenloader.query_configuration_dir()
+   + replace(string_to_utf8(cl), " ", "_");
   new = f + ".new~";
   fd = open(new, "wct");
 
@@ -176,7 +177,8 @@ private void really_save_it( string cl, mapping data, int
counter )
 
 Stat config_is_modified(string cl)
 {
-  Stat st = file_stat(configuration_dir + replace(cl, " ", "_"));
+  Stat st = file_stat(roxenloader.query_configuration_dir()
+   + replace(cl, " ", "_"));
   if(st)
     if( !config_stat_cache[ cl ] )
       return st;
@@ -202,7 +204,7 @@ mapping read_it(string cl)
   report_debug("CONFIG: Read configuration file for cl "+cl+"\n");
 #endif
 
-  string base = configuration_dir + replace(cl, " ", "_");
+  string base = roxenloader.query_configuration_dir() + replace(cl, " ", "_");
   Stdio.File fd;
   mixed err = catch {
     fd = open(base, "r");
@@ -258,9 +260,9 @@ void remove( string reg , Configuration
current_configuration )
 void remove_configuration( string name )
 {
   string f;
-  f = configuration_dir + replace(name, " ", "_");
+  f = roxenloader.query_configuration_dir() + replace(name, " ", "_");
   if(!file_stat( f ))   
-    f = configuration_dir+name;
+    f = roxenloader.query_configuration_dir()+name;
 #ifdef DEBUG_CONFIG
   report_debug("CONFIG: Remove "+f+"\n");
 #endif
diff --git a/server/base_server/roxen.pike b/server/base_server/roxen.pike
index 5c21b57..745b0cc 100644
--- a/server/base_server/roxen.pike
+++ b/server/base_server/roxen.pike
@@ -85,9 +85,9 @@ string md5( string what )
   return Gmp.mpz(Crypto.MD5.hash( what ),256)->digits(32);
 }
   
-string query_configuration_dir()
+string query_local_dir()
 {
-  return configuration_dir;
+  return roxenloader.query_local_dir();
 }
 
 array(string|int) filename_2 (program|object o)
@@ -2135,8 +2135,8 @@ class Protocol
 
     restore();
     if (sizeof(requesthandlerfile)) {
-      if( file_stat( "../local/"+requesthandlerfile ) )
-	rrhf = "../local/"+requesthandlerfile;
+      if( file_stat( query_local_dir()+"/"+requesthandlerfile ) )
+	rrhf = query_local_dir()+"/"+requesthandlerfile;
       else
 	rrhf = requesthandlerfile;
       DDUMP( rrhf );
@@ -2387,7 +2387,7 @@ class SSLProtocol
     string doc()
     {
       return sprintf(::doc() + "\n",
-		     combine_path(getcwd(), "../local"),
+		     combine_path(getcwd(), query_local_dir()),
 		     getcwd());
     }
   }
@@ -2399,7 +2399,7 @@ class SSLProtocol
     string doc()
     {
       return sprintf(::doc() + "\n",
-		     combine_path(getcwd(), "../local"),
+		     combine_path(getcwd(), query_local_dir()),
 		     getcwd());
     }
   }
@@ -2499,7 +2499,8 @@ mapping(string:program/*(Protocol)*/)
build_protocols_mapping()
 #endif
     };
   }
-  foreach( glob("prot_*.pike",get_dir("../local/protocols")||({})), string s )
+  foreach( glob("prot_*.pike",
+   get_dir(query_local_dir()+"/protocols")||({})), string s )
   {
     sscanf( s, "prot_%s.pike", s );
 #if !constant(SSL.sslfile)
@@ -2513,9 +2514,9 @@ mapping(string:program/*(Protocol)*/)
build_protocols_mapping()
     report_debug( "\b%s \b", s );
     catch {
 #ifdef DEBUG
-      protocols[ s ] = (program)("../local/protocols/prot_"+s+".pike");
+      protocols[ s ] =
(program)(query_local_dir()+"/protocols/prot_"+s+".pike");
 #else
-      protocols[ s ] = lazy_load( ("../local/protocols/prot_"+s+".pike"),s );
+      protocols[ s ] = lazy_load(
(query_local_dir()+"/protocols/prot_"+s+".pike"),s );
 #endif
     };
   }
@@ -3004,7 +3005,8 @@ 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");
+    current_user_id_file
+     = open(roxenloader.query_configuration_dir() + "LASTUSER~", "rwc");
   if(!current_user_id_file)
   {
     call_out(restore_current_user_id_number, 2);
@@ -4329,7 +4331,7 @@ class ArgCache
   protected void get_plugins()
   {
     plugins = ({});
-    foreach( ({ "../local/arg_cache_plugins", "arg_cache_plugins" }), string d)
+    foreach( ({ query_local_dir()+"/arg_cache_plugins", "arg_cache_plugins" }),
string d)
       if( file_stat( d  ) )
 	foreach( glob("*.pike", get_dir( d )), string f )
 	{
@@ -5376,13 +5378,6 @@ int main(int argc, array tmp)
 
   once_mode = (int)Getopt.find_option(argv, "o", "once");
 
-  configuration_dir =
-    Getopt.find_option(argv, "d",({"config-dir","configuration-directory" }),
-	     ({ "ROXEN_CONFIGDIR", "CONFIGURATIONS" }), "../configurations");
-
-  if(configuration_dir[-1] != '/')
-    configuration_dir += "/";
-
   restore_global_variables(); // restore settings...
 
   if( query("replicate" ) )
diff --git a/server/base_server/roxenloader.pike
b/server/base_server/roxenloader.pike
index 6318e2a..bd082e8 100644
--- a/server/base_server/roxenloader.pike
+++ b/server/base_server/roxenloader.pike
@@ -31,7 +31,8 @@ constant s = spider; // compatibility
 //#define ENABLE_MYSQL_UNICODE_MODE
 
 int      remove_dumped;
-string   configuration_dir;
+protected string configuration_dir;
+protected string local_dir;
 
 #define werror roxen_perror
 
@@ -1030,7 +1031,7 @@ string roxen_path( string filename )
 {
   filename = replace( filename, (),
                       ({"$VARDIR/"+roxen_version(),
-                        getenv ("LOCALDIR") || "../local",
+                        query_local_dir(),
 			getenv ("LOGFILE") || "$LOGDIR/debug/default.1" }) );
   if( roxen )
     filename = replace( filename, 
@@ -1251,6 +1252,7 @@ Roxen 5.0 should be run with Pike 7.8 or newer.
   configuration_dir =
     Getopt.find_option(av, "d",({"config-dir","configuration-directory" }),
 	     ({ "ROXEN_CONFIGDIR", "CONFIGURATIONS" }), "../configurations");
+  local_dir = getenv("LOCALDIR") || "../local";
 
   remove_dumped =
     Getopt.find_option(av, "remove-dumped",({"remove-dumped", }), 0 );
@@ -1270,7 +1272,7 @@ Roxen 5.0 should be run with Pike 7.8 or newer.
     dist_version = roxen_version();
 
   // Get package directories.
-  add_package(getenv("LOCALDIR") || "../local");
+  add_package(query_local_dir());
   foreach(package_directories + ({ "." }), string dir) {
     dir = combine_path(dir, "packages");
     foreach(sort(get_dir(dir) || ({})), string fname) {
@@ -1365,6 +1367,11 @@ string query_configuration_dir()
   return configuration_dir;
 }
 
+string query_local_dir()
+{
+  return local_dir;
+}
+
 protected mapping(string:array(SQLTimeout)) sql_free_list = ([ ]);
 mapping(string:int) sql_active_list = ([ ]);
 
diff --git a/server/config_interface/actions/change_version.pike
b/server/config_interface/actions/change_version.pike
index 09fec15..d85f810 100644
--- a/server/config_interface/actions/change_version.pike
+++ b/server/config_interface/actions/change_version.pike
@@ -104,9 +104,10 @@ string parse( RequestID id )
 
   if( id->variables->server )
   {
+    string locenv = roxenloader.query_local_dir()+ "/environment";
+    mv(locenv, locenv + "~");
     werror("Change to "+id->variables->server+"\n" );
-    mv("../local/environment", "../local/environment~");
-    Stdio.write_file( combine_path(roxen.configuration_dir,
+    Stdio.write_file( combine_path(roxenloader.query_configuration_dir(),
 				   "server_version"),
 		      id->variables->server );
        roxen->shutdown(0.5);
@@ -173,7 +174,7 @@ string parse( RequestID id )
 	"instead have to edit the file %O manually, shutdown the server, "
 	"and execute %O again"),
 	      combine_path(getcwd(),
-			   roxen.configuration_dir,
+			   roxenloader.query_configuration_dir(),
 			   "server_version"),
 	      combine_path(getcwd(),"../start") )
       +"</td></tr></table>";
diff --git a/server/config_interface/actions/debug_summary.pike
b/server/config_interface/actions/debug_summary.pike
index 3391f8c..3dfb8c5 100644
--- a/server/config_interface/actions/debug_summary.pike
+++ b/server/config_interface/actions/debug_summary.pike
@@ -85,9 +85,11 @@ string make_environment_summary()
   res += "\n";
   res += make_headline("Local environment variables");
 #ifdef __NT__
-  res += indent(Stdio.read_file("../local/environment.ini")||"", 1);
+  res += indent(
+   Stdio.read_file(roxenloader.query_local_dir()+"/environment.ini")||"", 1);
 #else
-  res += indent(Stdio.read_file("../local/environment")||"", 1);
+  res += indent(
+   Stdio.read_file(roxenloader.query_local_dir()+"/environment")||"", 1);
 #endif
 
   res += "\n";
diff --git a/server/config_interface/actions/make_rsa_csr.pike
b/server/config_interface/actions/make_rsa_csr.pike
index c27acee..7741c2e 100644
--- a/server/config_interface/actions/make_rsa_csr.pike
+++ b/server/config_interface/actions/make_rsa_csr.pike
@@ -171,7 +171,7 @@ mapping wizard_done( object id )
 {
   object privs = Privs("Storing CSR request.");
   mv( id->variables->save_in_file, id->variables->save_in_file+"~" );
-  string fname = combine_path(getcwd(), "../local",
+  string fname = combine_path(getcwd(), roxenloader.query_local_dir(),
 			      id->variables->save_in_file);
   Stdio.File file = open(fname, "cwx", 0644);
   privs = 0;
diff --git a/server/config_interface/actions/make_selfsigned_dsa.pike
b/server/config_interface/actions/make_selfsigned_dsa.pike
index 7fdf412..2250982 100644
--- a/server/config_interface/actions/make_selfsigned_dsa.pike
+++ b/server/config_interface/actions/make_selfsigned_dsa.pike
@@ -222,7 +222,8 @@ mixed wizard_done(object id, object mc)
   return http_string_answer( sprintf("<p>"+LOCALE(131,"Wrote %d bytes to %s.")+
 				     "</p>\n<p><cf-ok/></p>\n",
 				     strlen(id->variables->certificate),
-				     combine_path(getcwd(), "../local", 
+				     combine_path(getcwd(),
+						 roxenloader.query_local_dir(), 
 						  id->variables->cert_file)) );
 }
 
diff --git a/server/config_interface/actions/make_selfsigned_rsa.pike
b/server/config_interface/actions/make_selfsigned_rsa.pike
index 63479bd..e2299fc 100644
--- a/server/config_interface/actions/make_selfsigned_rsa.pike
+++ b/server/config_interface/actions/make_selfsigned_rsa.pike
@@ -158,7 +158,8 @@ mixed wizard_done(object id, object mc)
   return http_string_answer( sprintf("<p>"+LOCALE(131,"Wrote %d bytes to %s.")+
 				     "</p>\n<p><cf-ok/></p>\n",
 				     strlen(id->variables->certificate),
-				     combine_path(getcwd(), "../local/",
+				     combine_path(getcwd(),
+						 roxenloader.query_local_dir(),
 						  id->variables->cert_file)) );
 }
 
diff --git a/server/config_interface/actions/make_site_template.pike
b/server/config_interface/actions/make_site_template.pike
index 6714074..bc38547 100644
--- a/server/config_interface/actions/make_site_template.pike
+++ b/server/config_interface/actions/make_site_template.pike
@@ -184,19 +184,19 @@ string parse(RequestID id)
       }
 
       object st;
-      if (!(st = file_stat("../local/" SITE_TEMPLATES))) {
-	if (!mkdir("../local/" SITE_TEMPLATES, 0755)) {
+      string templates = roxenloader.query_local_dir() + "/" SITE_TEMPLATES;
+      if (!(st = file_stat(templates))) {
+	if (!mkdir(templates, 0755)) {
 	  res += sprintf("<p><font color='&usr.warncolor'>%s: %O</font></p>\n",
 			 LOCALE(149, "Coundn't create directory"),
-			 "../local/" SITE_TEMPLATES);
+			 templates);
 	}
       }
       Stdio.File f = lopen(SITE_TEMPLATES + fname + ".pike", "cw", 0644);
       if (!f) {
 	res += sprintf("<p><font color='&usr.warncolor'>%s: %O</font></p>\n",
 		       LOCALE(150, "Failed to create template file"),
-		       "../local/" SITE_TEMPLATES +
-		       Roxen.html_encode_string(fname));
+		       templates + Roxen.html_encode_string(fname));
       } else {
 	int n = f->write(template);
 	f->close();
@@ -204,8 +204,7 @@ string parse(RequestID id)
 	if (n != sizeof(template)) {
 	  res += sprintf("<p><font color='&usr.warncolor'>%s: %O</font></p>\n",
 			 LOCALE(151, "Failed to write template file"),
-			 "../local/" SITE_TEMPLATES +
-			 Roxen.html_encode_string(fname));
+			 templates + Roxen.html_encode_string(fname));
 	} else {
 	  res += sprintf("<p>%s</p>\n",
 			 LOCALE(152, "Site template created successfully."));
diff --git a/server/config_interface/actions/ssl_common.pike
b/server/config_interface/actions/ssl_common.pike
index 5d12d81..0e4373e 100644
--- a/server/config_interface/actions/ssl_common.pike
+++ b/server/config_interface/actions/ssl_common.pike
@@ -133,7 +133,7 @@ string key_file_form (string filename)
     "<var name='key_file' type='string' default='"+filename+"'/><blockquote>\n"+
     sprintf(LOCALE(97, 
 		   "Where to store the file, may be relative to %s."),
-	    combine_path(getcwd(), "../local/")) +
+	    combine_path(getcwd(), roxenloader.query_local_dir())) +
     "\n<help><p>" +
     LOCALE(98, 
 	   "A filename in the real filesystem, where the secret key should "
@@ -223,7 +223,7 @@ string save_certificate_form (string name, string filename)
     "<var type='string' name='"+name+"' default='"+filename+"'/>"
     "<br />"+ 
     sprintf(LOCALE(97, "Where to store the file, may be relative to %s."),
-	    combine_path(getcwd(), "../local/")) +
+	    combine_path(getcwd(), roxenloader.query_local_dir())) +
     "</blockquote>";
 }
 
diff --git a/server/config_interface/sites/create_site_with_template.pike
b/server/config_interface/sites/create_site_with_template.pike
index c082361..89eaf8f 100644
--- a/server/config_interface/sites/create_site_with_template.pike
+++ b/server/config_interface/sites/create_site_with_template.pike
@@ -85,13 +85,14 @@ string|mapping parse( RequestID id )
     master()->clear_compilation_failures();
 
     object b;
-    if (file_stat("../local/"+id->variables->site_template)) {
-      b = ((program)("../local/"+id->variables->site_template))();
+    string q = roxenloader.query_local_dir() + id->variables->site_template;
+    if (file_stat(q)) {
+      b = ((program)q)();
     } else {
       b = ((program)id->variables->site_template)();
     }
     
-    string q = b->parse( id );
+    q = b->parse( id );
     if( !stringp( q ) ) 
       return q;
 
@@ -108,18 +109,18 @@ string|mapping parse( RequestID id )
 
   roxenloader.ErrorContainer e = roxenloader.ErrorContainer( );
   master()->set_inhibit_compile_errors( e );
-  string res = "";
+  string res = roxenloader.query_local_dir();
   array sts = ({});
   foreach( glob( "*.pike", get_dir( SITE_TEMPLATES ) |
-		           (get_dir( "../local/"+SITE_TEMPLATES )||({}))),
+		           (get_dir( res+SITE_TEMPLATES )||({}))),
 	   string st )
   {
     st = SITE_TEMPLATES+st;
     mixed err = catch {
       program p;
       object q;
-      if (file_stat("../local/"+st))
-	p = (program)("../local/"+st);
+      if (file_stat(res+st))
+	p = (program)(res+st);
       else
 	p = (program)(st);
       if(!p) {
@@ -183,6 +184,7 @@ string|mapping parse( RequestID id )
     }
   }
 
+  res = "";
   string last_group;
   sort( sts );
   foreach( sts, array q ) {
diff --git a/server/config_interface/sites/drop_site.pike
b/server/config_interface/sites/drop_site.pike
index 042b0d4..9535196 100644
--- a/server/config_interface/sites/drop_site.pike
+++ b/server/config_interface/sites/drop_site.pike
@@ -121,7 +121,7 @@ string|mapping parse( RequestID id )
     d = d[7..];
     DBManager.drop_db( d );
   }
-  string cfname = roxen.configuration_dir + "/" + cf->name;
+  string cfname = roxenloader.query_configuration_dir() + "/" + cf->name;
   mv (cfname, cfname + "~");
   roxen->remove_configuration( cf->name );
   cf->stop();
diff --git a/server/etc/modules/RoxenPatch.pmod
b/server/etc/modules/RoxenPatch.pmod
index f3061d1..71c0cfb 100644
--- a/server/etc/modules/RoxenPatch.pmod
+++ b/server/etc/modules/RoxenPatch.pmod
@@ -108,10 +108,10 @@ class Patcher
   //! @param error_callback
   //!   A callback function which is used for status callback.
   //! @param server_dir
-  //!   Path the the roxen server directory 
+  //!   Path to the roxen server directory 
   //!   I.e. @tt
   //! @param local_dir
-  //!   Path the the roxen local directory 
+  //!   Path to the roxen local directory 
   //!   Defaults to @tt relative the server path.
   //! @param temp_dir
   //!   Path the the system temp dir. Depending on operating system it
diff --git a/server/etc/test/tests/RoxenTest_base.pike
b/server/etc/test/tests/RoxenTest_base.pike
index 5124133..84654ff 100644
--- a/server/etc/test/tests/RoxenTest_base.pike
+++ b/server/etc/test/tests/RoxenTest_base.pike
@@ -139,16 +139,6 @@ void test_spawn_pike( array args,
 
 void run_tests( Configuration c )
 {
-  // Test (some) public APIs in the 'roxen' and 'roxenloader' objects.
-
-  // Should we really test this? I don't know, but for now (as long as
-  // both functions exists) verify that they return the same value...
-  test( roxen.query_configuration_dir );
-  test( roxenloader.query_configuration_dir );
-  test_equal( roxen.query_configuration_dir(),
-	      roxenloader.query_configuration_dir );
-
-
   test_spawn_pike( ({combine_path( __FILE__,"../echo.pike" )}),
 		     "Testing testing\n",
 		     "\nTesting testing\n" );
diff --git a/server/modules/configuration/config_filesystem.pike
b/server/modules/configuration/config_filesystem.pike
index 7cf2de5..4a0e0d1 100644
--- a/server/modules/configuration/config_filesystem.pike
+++ b/server/modules/configuration/config_filesystem.pike
@@ -54,7 +54,7 @@ array(string|Stat) low_stat_file(string f, object id)
 #define of f
 #endif
 
-  foreach( ({ "../local/"+path, path }), string path )
+  foreach( ({ roxenloader.query_local_dir()+"/"+path, path }), string path )
   {
     Stat ret;
     string p;
diff --git a/server/modules/tags/rxmltags.pike
b/server/modules/tags/rxmltags.pike
index 40f1303..79c11ca 100644
--- a/server/modules/tags/rxmltags.pike
+++ b/server/modules/tags/rxmltags.pike
@@ -4089,11 +4089,13 @@ class TagUse {
   array(RXML.Type) result_types = (); // No result.
 
   private array(string) list_packages() { 
-    return filter(((get_dir("../local/rxml_packages")||({}))
+    return filter(((get_dir(roxenloader.query_local_dir()
+		    +"/rxml_packages")||({}))
 		   |(get_dir("rxml_packages")||({}))),
 		  lambda( string s ) {
 		    return s!=".cvsignore" &&
-		      (Stdio.file_size("../local/rxml_packages/"+s)+
+		      (Stdio.file_size(roxenloader.query_local_dir()
+			+"/rxml_packages/"+s)+
 		       Stdio.file_size( "rxml_packages/"+s )) > 0;
 		  });
   }
@@ -4101,8 +4103,10 @@ class TagUse {
   private string read_package( string p ) {
     string data;
     p = combine_path("/", p);
-    if(file_stat( "../local/rxml_packages/"+p ))
-      catch(data=Stdio.File( "../local/rxml_packages/"+p, "r" )->read());
+    if(file_stat( roxenloader.query_local_dir()+"/rxml_packages/"+p ))
+      catch(data=Stdio.File( roxenloader.query_local_dir()
+	+"/rxml_packages/"+p, "r" )
+       ->read());
     if(!data && file_stat( "rxml_packages/"+p ))
       catch(data=Stdio.File( "rxml_packages/"+p, "r" )->read());
     return data;
diff --git a/server/start b/server/start
index 24e8cfe..3f76949 100755
--- a/server/start
+++ b/server/start
@@ -80,7 +80,8 @@ fi
 FILES="default"
 program=base_server/roxenloader.pike
 VARDIR=../var
-LOCALDIR=../local
+test -z "$LOCALDIR" && LOCALDIR=../local
+export LOCALDIR
 if [ ! "x$ROXEN_DATADIR" = "x" ]
 then
     VARDIR="$ROXEN_DATADIR"/var
diff --git a/server/tools/init.d_roxen b/server/tools/init.d_roxen
index 0c2e253..dda8972 100755
--- a/server/tools/init.d_roxen
+++ b/server/tools/init.d_roxen
@@ -12,6 +12,9 @@ roxenconfdirs=/etc/roxen
 #
 roxenhome=/usr/local/roxen
 
+LOCALDIR=../local
+export LOCALDIR
+
 # Set these to kill all processes owned by wwwuser on stop. Useful to
 # reap CGI scripts.
 #