811bae2000-03-30Leif Stensson #!bin/pike -m lib/pike/master.pike /* buildenv.pike -- build an environment setup file for Roxen. * * This script tries to build an environment setup file for * Roxen, making sure Roxen has LD_LIBRARY_PATH and other * essential variables set, to keep dynamic libraries and * various other external stuff happy. */
0917d32013-03-04Anders Johansson string cvs_version = "$Id$";
811bae2000-03-30Leif Stensson  class Environment {
fc40392008-08-15Martin Stjernholm  protected string filename; protected mapping(string:array(string)) env, oldenv;
811bae2000-03-30Leif Stensson 
fc40392008-08-15Martin Stjernholm  protected void read()
811bae2000-03-30Leif Stensson  { string var, def; multiset(string) exports = (<>);
3e3bab2001-01-19Per Hedbor  Stdio.File f;
811bae2000-03-30Leif Stensson  env = ([]); oldenv = ([]); if (catch (f = Stdio.File(filename, "r"))) return; foreach(f->read()/"\n", string line) if (sscanf(line-"\r", "%[A-Za-z0-9_]=%s", var, def)==2) {
abad5d2010-07-08Henrik Grubbström (Grubba)  string pre, post, sep = ":"; // Get rid of quotes. if (has_prefix(def, "\"") && has_suffix(def, "\"")) { def = def[1..sizeof(def)-2]; } /* The line is on one of the following formats: * * var=DEF ==> DEF * var=${var}${var:+SEP}POST ==> SEP, POST * var=PRE${var:+SEP}${var} ==> PRE, SEP * var=PRE${var:+SEP}${var}SEPPOST ==> PRE, SEP, POST */
811bae2000-03-30Leif Stensson  if(2==sscanf(def, "%s${"+var+"}%s", pre, post) || 2==sscanf(def, "%s$"+var+"%s", pre, post)) { if (pre=="") pre = 0; else if (pre[-1]==':') pre = pre[..sizeof(pre)-2];
abad5d2010-07-08Henrik Grubbström (Grubba)  else sscanf(pre, "%s${" + var + ":+%s}", pre, sep);
811bae2000-03-30Leif Stensson  if (post=="") post = 0;
abad5d2010-07-08Henrik Grubbström (Grubba)  else if (has_prefix(post, sep)) post = post[sizeof(sep)..];
811bae2000-03-30Leif Stensson  else
abad5d2010-07-08Henrik Grubbström (Grubba)  sscanf(post, "${" + var + ":+%s}%s", sep, post); env[var] = ({ pre, 0, post, sep });
811bae2000-03-30Leif Stensson  } else
abad5d2010-07-08Henrik Grubbström (Grubba)  env[var] = ({ 0, def, 0, ":" }); werror("Read definition for %s: %O\n" "%O\n", var, line, env[var]);
811bae2000-03-30Leif Stensson  } else if (sscanf(line, "export %s", var)) foreach((replace(var, ({"\t","\r"}),({" "," "}))/" ")-({""}), string v) exports[v] = 1; foreach(indices(env), string e) if (!exports[e]) m_delete(env, e); oldenv = copy_value(env); }
fc40392008-08-15Martin Stjernholm  protected void write()
811bae2000-03-30Leif Stensson  {
3e3bab2001-01-19Per Hedbor  Stdio.File f = Stdio.File(filename, "cwt");
811bae2000-03-30Leif Stensson  if (!f) { error("Failed to write "+filename+"\n"); return; } f->write("# This file is automatically generated by the buildenv.pike\n");
1ba6e72000-04-01Stefan Wallström  f->write("# script. Generated on " + replace(ctime(time()),"\n","") + ".\n");
d75beb2005-05-23Fredrik Noring  f->write("#\n# Automatically generated. Please edit environment2 instead.\n");
811bae2000-03-30Leif Stensson  foreach(sort(indices(env)), string var) { array(string) v = env[var]; if (v && (v[0]||v[1]||v[2])) {
abad5d2010-07-08Henrik Grubbström (Grubba)  f->write(var+"=\"");
811bae2000-03-30Leif Stensson  if(v[1])
abad5d2010-07-08Henrik Grubbström (Grubba)  f->write((v[0]? v[0]+v[3]:"")+v[1]+(v[2]? v[3]+v[2]:""));
811bae2000-03-30Leif Stensson  else if (!v[0]) // Append only
abad5d2010-07-08Henrik Grubbström (Grubba)  f->write("${"+var+"}${"+var+":+" + v[3] + "}"+v[2]);
811bae2000-03-30Leif Stensson  else if (!v[2]) // Prepend only
abad5d2010-07-08Henrik Grubbström (Grubba)  f->write(v[0]+"${"+var+":+" + v[3] + "}${"+var+"}");
811bae2000-03-30Leif Stensson  else // Prepend and append
abad5d2010-07-08Henrik Grubbström (Grubba)  f->write(v[0]+"${"+var+":+" + v[3] + "}${"+var+"}"+v[3]+v[2]); f->write("\"\nexport "+var+"\n");
811bae2000-03-30Leif Stensson  } } f->close(); }
fc40392008-08-15Martin Stjernholm  protected int changed()
811bae2000-03-30Leif Stensson  { return !equal(env, oldenv); }
abad5d2010-07-08Henrik Grubbström (Grubba)  void set_separator(string var, string sep) { array(string) v = env[var]; if (!v) v = env[var] = ({ 0, 0, 0, ":" }); v[3] = sep; }
811bae2000-03-30Leif Stensson  void append(string var, string val) { array(string) v = env[var]; if (!v)
abad5d2010-07-08Henrik Grubbström (Grubba)  v = env[var] = ({ 0, 0, 0, ":" }); foreach(val/v[3], string comp) if ((!v[2]) || search(v[2]/v[3], comp)<0) v[2] = (v[2]? v[2]+v[3]:"")+comp;
811bae2000-03-30Leif Stensson  } void prepend(string var, string val) { array(string) v = env[var]; if (!v)
abad5d2010-07-08Henrik Grubbström (Grubba)  v = env[var] = ({ 0, 0, 0, ":" }); foreach(val/v[3], string comp) if ((!v[0]) || search(v[0]/v[3], comp)<0) v[0] = comp+(v[0]? v[3]+v[0]:"");
811bae2000-03-30Leif Stensson  } void set(string var, string val) { array(string) v = env[var]; if (!v)
abad5d2010-07-08Henrik Grubbström (Grubba)  v = env[var] = ({ 0, 0, 0, ":" }); // Compat with old scripts. if (has_prefix(val, "\"") && has_suffix(val, "\"")) val = val[1..sizeof(val)-2];
811bae2000-03-30Leif Stensson  v[1] = val; }
1705022002-02-14Marcus Wellhardh  void remove(string var) { m_delete(env, var); }
811bae2000-03-30Leif Stensson  string get(string var) { array(string) v = env[var];
abad5d2010-07-08Henrik Grubbström (Grubba)  return v && (v[..2]-({0}))*v[3]; } string get_separator(string var) { array(string) v = env[var]; return v && v[3];
811bae2000-03-30Leif Stensson  } int finalize() { if (!changed()) return 0; write(); return 1; } void create(string fn) { filename = fn; read(); } } void config_env(object(Environment) env) {
3e3bab2001-01-19Per Hedbor  string dir = "etc/env.d"; program p; object eo;
811bae2000-03-30Leif Stensson  foreach(glob("*.pike", get_dir(dir)||({})), string e)
9d7abc2000-08-31Fredrik Noring  { string name = (e/".")[0];
811bae2000-03-30Leif Stensson  if (!catch (p = compile_file(dir+"/"+e))) { if (eo = p()) eo->run(env); else
9d7abc2000-08-31Fredrik Noring  write(" Skipping %O.\n", name);
811bae2000-03-30Leif Stensson  } else
9d7abc2000-08-31Fredrik Noring  write(" Test script %O failed to compile.\n", name);
811bae2000-03-30Leif Stensson  } } void main(int argc, array argv) {
de01122005-12-21Fredrik Noring  string localdir = getenv("LOCALDIR") || combine_path(getcwd(), "../local");
811bae2000-03-30Leif Stensson 
de01122005-12-21Fredrik Noring  write(" Setting up environment in %s.\n", localdir);
abad5d2010-07-08Henrik Grubbström (Grubba)  if (!Stdio.is_dir(localdir)) { if (!Stdio.is_dir("bin") || !Stdio.is_dir("modules"))
9d7abc2000-08-31Fredrik Noring  { write(" "+argv[0]+": " "should be run in the Roxen 'server' directory.\n");
811bae2000-03-30Leif Stensson  exit(1); }
de01122005-12-21Fredrik Noring  if (!mkdir(localdir, 0775))
811bae2000-03-30Leif Stensson  {
de01122005-12-21Fredrik Noring  write(" Failed to create %s!\n", localdir);
811bae2000-03-30Leif Stensson  exit(1); } }
de01122005-12-21Fredrik Noring  Environment envobj = Environment(combine_path(localdir, "environment"));
811bae2000-03-30Leif Stensson  config_env(envobj); if (envobj->finalize()) {
b973a02000-08-31Fredrik Noring  write(" Environment updated.\n\n");
811bae2000-03-30Leif Stensson  } else {
b973a02000-08-31Fredrik Noring  write(" Environment didn't need updating.\n\n");
811bae2000-03-30Leif Stensson  } }