diff options
-rw-r--r-- | README | 22 | ||||
-rw-r--r-- | interface.ccl | 2 | ||||
-rw-r--r-- | param.ccl | 42 | ||||
-rw-r--r-- | src/announce.cc | 97 | ||||
-rw-r--r-- | src/make.code.defn | 2 | ||||
-rw-r--r-- | src/make.code.deps | 34 | ||||
-rw-r--r-- | src/make.configuration.deps | 2 | ||||
-rw-r--r-- | src/portal.cc | 6 | ||||
-rw-r--r-- | src/rdf.cc | 494 | ||||
-rw-r--r-- | src/rdf.hh | 60 | ||||
-rwxr-xr-x | src/util/gethostname.pl | 38 |
11 files changed, 758 insertions, 41 deletions
@@ -39,8 +39,6 @@ IOUtil should not depend on anything use a configuration script to amend all thorns' make.code.deps files to create the tarballs when the thorns are compiled -use perl instead of C for makeblob and makemetablob - put arrangement name into thorn source name use subdirectories for arrangements use strings instead of chars for data @@ -68,6 +66,19 @@ does not have to wait make max_warn_level and output_info steerable +register with Portal/Announce as information provider +[Tom/Ian want to make Announce accept a table instead of XMLRPC] + +prevent connecting to the wrong simulation, if a simulation is +outdated, and a new simulation uses the same hostname/port +combination: the portal can store the job id, and if there is a new +port id for the same hostname/port combination, deactivate the old +link. + +Rebuild the flesh tarball when the ThornList changes + +factor out relaying into its own class + RSS: add RSS feed @@ -84,3 +95,10 @@ a simple example is: </item> </channel> </rss> + + + +Give each value a type. The type should describe the content, not the +presentation. E.g.: "scalar double value, normal range [0..1]", or +"keyword", or "keyword, possible values are ...", or "integer value, +value range is [1..10]". diff --git a/interface.ccl b/interface.ccl index c963e8f..9a447c8 100644 --- a/interface.ccl +++ b/interface.ccl @@ -6,6 +6,8 @@ IMPLEMENTS: Formaline # for HTTP_Port() USES INCLUDE HEADER: http_Content.h +USES INCLUDE HEADER: Announce.h + # Return a pointer to an unmodifiable C string @@ -16,6 +16,14 @@ REAL update_interval "Update interval for the meta information (in seconds)" STE +# Parameters for creating files containing the build and job ids + +BOOLEAN create_id_files "Create files from the build and job ids" +{ +} yes + + + # Parameters for announcing meta information to the portal BOOLEAN announce_to_portal "Announce meta information to the portal" STEERABLE=always @@ -37,15 +45,23 @@ STRING portal_username "User name on the portal" STEERABLE=always "" :: "" } "" -BOOLEAN use_relay_host "Use a relay host for connecting to the portal" STEERABLE=always + + +# Parameters for storing as RDF + +BOOLEAN send_as_rdf "Send meta as RDF to a server" STEERABLE=always { -} yes +} no -STRING relay_host "Relay host for connecting to the portal" STEERABLE=always +STRING rdf_hostname "RDF server host name" STEERABLE=always { - ".+" :: "host name" - "" :: "try to determine a relay host automatically" -} "" + "" :: "" +} "rdf.cct.lsu.edu" + +INT rdf_port "RDF server port" STEERABLE=always +{ + 1:65535 :: "" +} 9296 @@ -62,6 +78,20 @@ STRING storage_filename "File name for meta information" STEERABLE=always +# Parameters for relaying to remote servers + +BOOLEAN use_relay_host "Use a relay host for connecting to the portal" STEERABLE=always +{ +} yes + +STRING relay_host "Relay host for connecting to the portal" STEERABLE=always +{ + ".+" :: "host name" + "" :: "try to determine a relay host automatically" +} "" + + + # Parameters for storing the source tree in the executable BOOLEAN output_source "Output a tarball with the cactus source tree" STEERABLE=recover diff --git a/src/announce.cc b/src/announce.cc index 3ebf384..fe3911e 100644 --- a/src/announce.cc +++ b/src/announce.cc @@ -47,6 +47,7 @@ #include "file.hh" #include "multistorage.hh" #include "portal.hh" +#include "rdf.hh" @@ -169,6 +170,29 @@ namespace Formaline create_job_id (cctkGH); + if (create_id_files) { + // Create files from the build id and job id + // (This shows what jobs were run in the output directory) + { + ostringstream filenamebuf; + filenamebuf << out_dir << "/formaline-" << build_id; + string const filenamestring = filenamebuf.str(); + ofstream fil; + fil.open (filenamestring.c_str(), ios::trunc); + fil << build_id << endl; + fil.close (); + } + { + ostringstream filenamebuf; + filenamebuf << out_dir << "/formaline-" << job_id; + string const filenamestring = filenamebuf.str(); + ofstream fil; + fil.open (filenamestring.c_str(), ios::trunc); + fil << job_id << endl; + fil.close (); + } + } + // Announce { @@ -179,6 +203,11 @@ namespace Formaline stores.add_storage (new portal (job_id, storage::initial)); } + if (send_as_rdf) + { + stores.add_storage (new rdf (job_id, storage::initial)); + } + if (store_into_file) { stores.add_storage (new file (job_id, storage::initial)); @@ -309,19 +338,19 @@ namespace Formaline { // PBS logname char const * const pbs_logname = getenv ("PBS_LOGNAME"); - stores.store ("PBS logname", pbs_logname); + stores.store ("PBS_LOGNAME", pbs_logname); } { // PBS host char const * const pbs_host = getenv ("PBS_HOST"); - stores.store ("PBS host", pbs_host); + stores.store ("PBS_HOST", pbs_host); } { // PBS workdir char const * const pbs_workdir = getenv ("PBS_WORKDIR"); - stores.store ("PBS workdir", pbs_workdir); + stores.store ("PBS_WORKDIR", pbs_workdir); } @@ -330,7 +359,7 @@ namespace Formaline { char const * const cactus_version = CCTK_FullVersion(); - stores.store ("Cactus version", cactus_version); + stores.store ("Cactus_version", cactus_version); } @@ -338,24 +367,24 @@ namespace Formaline // Compiling { - stores.store ("build id", build_id); + stores.store ("build_id", build_id); } #if 0 { char const * const compile_user = CCTK_CompileUser(); - stores.store ("compile user", compile_user); + stores.store ("compile_user", compile_user); } #endif { char const * const compile_date = CCTK_CompileDate(); - stores.store ("compile date", compile_date); + stores.store ("compile_date", compile_date); } { char const * const compile_time = CCTK_CompileTime(); - stores.store ("compile time", compile_time); + stores.store ("compile_time", compile_time); } @@ -365,31 +394,31 @@ namespace Formaline #if 0 { char const * const run_user = CCTK_RunUser(); - stores.store ("run user", run_user); + stores.store ("run_user", run_user); } #else { char const * const run_user = getenv ("USER"); - stores.store ("run user", run_user); + stores.store ("run_user", run_user); } #endif { char run_date [1000]; Util_CurrentDate (sizeof run_date, run_date); - stores.store ("run date", run_date); + stores.store ("run_date", run_date); } { char run_time [1000]; Util_CurrentTime (sizeof run_time, run_time); - stores.store ("run time", run_time); + stores.store ("run_time", run_time); } { char run_host [1000]; Util_GetHostName (run_host, sizeof run_host); - stores.store ("run host", run_host); + stores.store ("run_host", run_host); } { @@ -399,7 +428,7 @@ namespace Formaline assert (type == PARAMETER_STRING); char const * const run_title = * static_cast<char const * const *> (ptr); - stores.store ("run title", run_title); + stores.store ("run_title", run_title); } @@ -424,7 +453,7 @@ namespace Formaline { char parameter_filename [10000]; CCTK_ParameterFilename (sizeof parameter_filename, parameter_filename); - stores.store ("parameter filename", parameter_filename); + stores.store ("parameter_filename", parameter_filename); } // This is superfluous, and it does not look nice @@ -440,7 +469,7 @@ namespace Formaline fclose (file); assert (count < sizeof parameter_file - 1); parameter_file [count] = '\0'; - stores.store ("parameter file", parameter_file); + stores.store ("parameter_file", parameter_file); } #endif @@ -448,11 +477,11 @@ namespace Formaline char cwd [10000]; getcwd (cwd, sizeof cwd); cwd [sizeof cwd - 1] = '\0'; // just to be sure - stores.store ("current dir", cwd); + stores.store ("current_dir", cwd); } { - stores.store ("out dir", out_dir); + stores.store ("out_dir", out_dir); } { @@ -669,6 +698,11 @@ namespace Formaline stores.add_storage (new portal (job_id, storage::update)); } + if (send_as_rdf) + { + stores.add_storage (new rdf (job_id, storage::initial)); + } + if (store_into_file) { stores.add_storage (new file (job_id, storage::update)); @@ -683,13 +717,13 @@ namespace Formaline { char run_date [1000]; Util_CurrentDate (sizeof run_date, run_date); - stores.store ("run date", run_date); + stores.store ("run_date", run_date); } { char run_time [1000]; Util_CurrentTime (sizeof run_time, run_time); - stores.store ("run time", run_time); + stores.store ("run_time", run_time); } @@ -858,6 +892,11 @@ namespace Formaline stores.add_storage (new portal (job_id, storage::final)); } + if (send_as_rdf) + { + stores.add_storage (new rdf (job_id, storage::initial)); + } + if (store_into_file) { stores.add_storage (new file (job_id, storage::final)); @@ -872,13 +911,13 @@ namespace Formaline { char run_date [1000]; Util_CurrentDate (sizeof run_date, run_date); - stores.store ("run date", run_date); + stores.store ("run_date", run_date); } { char run_time [1000]; Util_CurrentTime (sizeof run_time, run_time); - stores.store ("run time", run_time); + stores.store ("run_time", run_time); } @@ -982,7 +1021,12 @@ namespace Formaline { stores.add_storage (new portal (job_id, storage::update)); } - + + if (send_as_rdf) + { + stores.add_storage (new rdf (job_id, storage::initial)); + } + if (store_into_file) { stores.add_storage (new file (job_id, storage::update)); @@ -1053,7 +1097,12 @@ namespace Formaline { stores.add_storage (new portal (job_id, storage::update)); } - + + if (send_as_rdf) + { + stores.add_storage (new rdf (job_id, storage::initial)); + } + if (store_into_file) { stores.add_storage (new file (job_id, storage::update)); diff --git a/src/make.code.defn b/src/make.code.defn index ca1a706..9b4f9e1 100644 --- a/src/make.code.defn +++ b/src/make.code.defn @@ -2,7 +2,7 @@ # $Header$ # Source files in this directory -SRCS = announce.cc file.cc multistorage.cc output_source.c portal.cc storage.cc +SRCS = announce.cc file.cc multistorage.cc output_source.c portal.cc rdf.cc storage.cc # Subdirectories containing source files SUBDIRS = diff --git a/src/make.code.deps b/src/make.code.deps index a1bfdb0..04c3713 100644 --- a/src/make.code.deps +++ b/src/make.code.deps @@ -1,21 +1,47 @@ # make.code.deps file for thorn Formaline -*-Makefile-*- # $Header$ -# Store the "makeblob" utilities in the scratch directory of this -# configuration. +# Store the utilities in the scratch directory of this configuration. # This has to live here in the file make.code.deps instead of in the # file make.configuration.deps because only here the location of the -# source file makeblob.c is known. +# source directory is known. TARBALL_DIR = $(SCRATCH_BUILD) -$(CCTK_TARGET): $(TARBALL_DIR)/makeblob.pl $(TARBALL_DIR)/makemetablob.pl +$(CCTK_TARGET): $(TARBALL_DIR)/gethostname.pl $(TARBALL_DIR)/makeblob.pl $(TARBALL_DIR)/makemetablob.pl +$(TARBALL_DIR)/gethostname.pl: $(SRCDIR)/util/gethostname.pl + cd $(TARBALL_DIR) && cp $^ $@ + $(TARBALL_DIR)/makeblob.pl: $(SRCDIR)/util/makeblob.pl cd $(TARBALL_DIR) && cp $^ $@ $(TARBALL_DIR)/makemetablob.pl: $(SRCDIR)/util/makemetablob.pl cd $(TARBALL_DIR) && cp $^ $@ + + + + + + +# Unique ID for the build +$(TARBALL_DIR)/build-id.o: $(TARBALL_DIR)/build-id.c + $(CC) $(CFLAGS) -c -o $@ $^ + +# (force a new ID to be created every time) +.PHONY: $(TARBALL_DIR)/build-id.c +$(TARBALL_DIR)/build-id.c: + { \ + echo '/* This is an auto-generated file -- do not edit */'; \ + hostname=`hostname`; \ + user="$$USER"; \ + timestamp=`date +%Y%m%d-%H%M%S`; \ + pid="$$$$"; \ + id="build-$$hostname-$$user-$$timestamp-$$pid"; \ + echo 'char const build_id[] = "'$$id'";'; \ + } > $@ + +.PRECIOUS: $(TARBALL_DIR)/build-id.c $(TARBALL_DIR)/build-id.o diff --git a/src/make.configuration.deps b/src/make.configuration.deps index ca933e4..ada35c9 100644 --- a/src/make.configuration.deps +++ b/src/make.configuration.deps @@ -45,7 +45,7 @@ $(TARBALL_DIR)/build-id.o: $(TARBALL_DIR)/build-id.c $(TARBALL_DIR)/build-id.c: { \ echo '/* This is an auto-generated file -- do not edit */'; \ - hostname=`hostname`; \ + hostname=`$(TARBALL_DIR)/gethostname.pl`; \ user="$$USER"; \ timestamp=`date +%Y%m%d-%H%M%S`; \ pid="$$$$"; \ diff --git a/src/portal.cc b/src/portal.cc index b5f79a9..e2acea5 100644 --- a/src/portal.cc +++ b/src/portal.cc @@ -30,7 +30,7 @@ namespace Formaline static bool - is_clean_for_shell (char const * string); + is_clean_for_shell (char const * str); @@ -398,9 +398,9 @@ namespace Formaline static bool - is_clean_for_shell (char const * const string) + is_clean_for_shell (char const * const str) { - for (char const * p = string; * p; ++ p) + for (char const * p = str; * p; ++ p) { if (! isalnum (* p)) { diff --git a/src/rdf.cc b/src/rdf.cc new file mode 100644 index 0000000..028f54b --- /dev/null +++ b/src/rdf.cc @@ -0,0 +1,494 @@ +// $Header$ + +#include <cassert> +#include <cctype> +#include <cerrno> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <list> +#include <string> +#include <sstream> + +#include <unistd.h> + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "util_Network.h" + +#include "rdf.hh" + + + +namespace Formaline +{ + + using namespace std; + + + + static bool + is_clean_for_shell (char const * str); + + static list<string> + parse (string const str); + + + + rdf:: + rdf (char const * const id, + enum state const st) + : storage (st) + { + msgbuf +<< "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl +<< "<!DOCTYPE owl [" << endl +<< " <!ENTITY dc 'http://purl.org/dc/elements/1.1/'>" << endl +<< " <!ENTITY doap 'http://usefulinc.com/ns/doap#'>" << endl +<< " <!ENTITY foaf 'http://xmlns.com/foaf/0.1/'>" << endl +<< " <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>" << endl +<< " <!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>" << endl +<< "" << endl +<< " <!ENTITY cctk 'http://www.cct.lsu.edu/~dstark/cctk/0.1/'>" << endl +<< " <!ENTITY form 'http://www.aei.mpg.de/form#'>" << endl +<< "]>" << endl +<< "<rdf:RDF" << endl +<< " xmlns:dc=\"&dc;\"" << endl +<< " xmlns:doap=\"&doap;\"" << endl +<< " xmlns:foaf=\"&foaf;\"" << endl +<< " xmlns:rdf=\"&rdf;\"" << endl +<< " xmlns:rdfs=\"&rdfs;\"" << endl +<< " xmlns:cctk=\"&cctk;\"" << endl +<< " xmlns:form=\"&form;\"" << endl +<< ">" << endl +<< endl +<< "<form:Simulation>" << endl; + } + + + + rdf:: + ~ rdf () + { + DECLARE_CCTK_PARAMETERS; + + string const socket_script = "socket-client.pl"; + string const socket_data = "socket-data"; + + + + // Write the data + msgbuf +<< "</form:Simulation" << endl; + string const msgstr = msgbuf.str(); + + ostringstream databuf; + databuf << "POST HTTP/1.0 200\r\n" + << "Content-Type: text/xml\r\n" + << "Content-Length: " << msgstr.length() << "\r\n" + << "\r\n" + << msgstr + << "\r\n" + << "\r\n"; + string const datastr = databuf.str(); + + ostringstream datafilenamebuf; + datafilenamebuf << out_dir << "/" << socket_data; + string const datafilenamestr = datafilenamebuf.str(); + char const * const datafilename = datafilenamestr.c_str(); + + ofstream datafile; + datafile.open (datafilename, ios::out); + datafile << datastr; + datafile.close (); + + + + // Write the script + ostringstream scriptbuf; + scriptbuf +<< "#! /usr/bin/perl -w" << endl +<< endl +<< "use strict;" << endl +<< "use Socket;" << endl +<< endl +<< "my $input = '" << datafilename << "';" << endl +<< "my $host = '" << rdf_hostname << "';" << endl +<< "my $port = '" << rdf_port << "';" << endl +<< endl +<< "open (my $FH, '<' . $input);" << endl +<< endl +<< "socket (my $SH, PF_INET, SOCK_STREAM, getprotobyname ('tcp'));" << endl +<< "my $sin = sockaddr_in ($port, inet_aton ($host));" << endl +<< "connect ($SH, $sin) || exit -1;" << endl +<< endl +<< "while (my $line = <$FH>)" << endl +<< "{" << endl +<< " print $SH $line;" << endl +<< "}" << endl +<< endl +<< "close $SH;" << endl; + string const scriptstr = scriptbuf.str(); + + ostringstream scriptfilenamebuf; + scriptfilenamebuf << out_dir << "/" << socket_script; + string const scriptfilenamestr = scriptfilenamebuf.str(); + char const * const scriptfilename = scriptfilenamestr.c_str(); + + ofstream scriptfile; + scriptfile.open (scriptfilename, ios::out); + scriptfile << scriptstr; + scriptfile.close (); + + + + // Check that the file name is sane + if (! is_clean_for_shell (scriptfilename)) + { + static bool did_complain = false; + if (! did_complain) + { + did_complain = true; + CCTK_WARN (1, "Strange character in file name -- not calling system()"); + return; + } + } + + + + // Make the script executable + ostringstream chmodbuf; + chmodbuf << "chmod a+x " << scriptfilenamestr + << " < /dev/null > /dev/null 2> /dev/null"; + string const chmodstr = chmodbuf.str(); + char const * const chmod = chmodstr.c_str(); + system (chmod); + + + + bool my_use_relay_host = use_relay_host; + char const * my_relay_host = 0; + if (my_use_relay_host) + { + my_relay_host = relay_host; + if (strcmp (my_relay_host, "") == 0) + { + // Determine a good relay host + char run_host [1000]; + Util_GetHostName (run_host, sizeof run_host); + if (strncmp (run_host, "ic", 2) == 0 && strlen (run_host) == 6) + { + // Peyote or Lagavulin + int const node = atoi (run_host + 2); + if (node < 192) + { + // Peyote + my_relay_host = "peyote"; + } + else + { + // Lagavulin + my_relay_host = "lagavulin"; + } + } + else if (strncmp (run_host, "mike", 4) == 0 && strlen (run_host) == 7) + { + // Supermike + my_use_relay_host = false; + } + else + { + // Don't know a good relay host; try without + my_use_relay_host = false; + } + + if (verbose) + { + if (my_use_relay_host) + { + CCTK_VInfo (CCTK_THORNSTRING, + "Using \"%s\" as relay host", my_relay_host); + } + else + { + CCTK_INFO ("Announcing without relay host"); + } + } + } + } + + if (my_use_relay_host) + { + // Check that the relay host name is sane + if (! is_clean_for_shell (my_relay_host)) + { + static bool did_complain = false; + if (! did_complain) + { + did_complain = true; + CCTK_WARN (1, "Strange character in relay host name -- not calling system()"); + return; + } + } + } + + + + char cwd[10000]; + if (my_use_relay_host) + { + // Get the current directory + char * const cwderr = getcwd (cwd, sizeof cwd); + if (cwderr == NULL) { + static bool did_complain = false; + if (! did_complain) + { + did_complain = true; + CCTK_WARN (1, "Cannot determine current working directory"); + return; + } + } + + // Check that the current directory name is sane + if (! is_clean_for_shell (cwd)) + { + static bool did_complain = false; + if (! did_complain) + { + did_complain = true; + CCTK_WARN (1, "Strange character in current directory -- not calling system()"); + return; + } + } + } + else + { + cwd[0] = '\0'; + } + + + + // Send the data + ostringstream cmdbuf; + if (my_use_relay_host) + { + cmdbuf << "ssh " << my_relay_host << " '" + << "cd " << cwd << " && "; + } + cmdbuf << scriptfilenamestr << " < /dev/null > /dev/null 2> /dev/null"; + if (my_use_relay_host) + { + cmdbuf << "'"; + } + string const cmdstr = cmdbuf.str(); + char const * const cmd = cmdstr.c_str(); + + int const ierr = system (cmd); + if (ierr != 0) + { + static bool did_complain = false; + if (! did_complain) + { + did_complain = true; + CCTK_WARN (1, "Failed to send data to the rdf"); + } + } + + remove (datafilename); + remove (scriptfilename); + } + + + + void rdf:: + store (char const * const key, + bool const value) + { + assert (key); + + ostringstream keybuf; + keybuf << key; + ostringstream valuebuf; + valuebuf << (value ? "true" : "false"); + + list<string> const keys = parse (keybuf.str()); + + msgbuf << " "; + for (list<string>::const_iterator lsi = keys.begin(); + lsi != keys.end(); ++ lsi) + { + msgbuf << "<form:" << * lsi << ">"; + } + msgbuf << clean (valuebuf.str()); + for (list<string>::const_reverse_iterator lsi = keys.rbegin(); + lsi != keys.rend(); ++ lsi) + { + msgbuf << "</form:" << * lsi << ">"; + } + msgbuf << endl; + } + + + + void rdf:: + store (char const * const key, + int const value) + { + assert (key); + + ostringstream keybuf; + keybuf << key; + ostringstream valuebuf; + valuebuf << value; + + list<string> const keys = parse (keybuf.str()); + + msgbuf << " "; + for (list<string>::const_iterator lsi = keys.begin(); + lsi != keys.end(); ++ lsi) + { + msgbuf << "<form:" << * lsi << ">"; + } + msgbuf << clean (valuebuf.str()); + for (list<string>::const_reverse_iterator lsi = keys.rbegin(); + lsi != keys.rend(); ++ lsi) + { + msgbuf << "</form:" << * lsi << ">"; + } + msgbuf << endl; + } + + + + void rdf:: + store (char const * const key, + double const value) + { + assert (key); + + ostringstream keybuf; + keybuf << key; + ostringstream valuebuf; + valuebuf << setprecision(15) << value; + + list<string> const keys = parse (keybuf.str()); + + msgbuf << " "; + for (list<string>::const_iterator lsi = keys.begin(); + lsi != keys.end(); ++ lsi) + { + msgbuf << "<form:" << * lsi << ">"; + } + msgbuf << clean (valuebuf.str()); + for (list<string>::const_reverse_iterator lsi = keys.rbegin(); + lsi != keys.rend(); ++ lsi) + { + msgbuf << "</form:" << * lsi << ">"; + } + msgbuf << endl; + } + + + + void rdf:: + store (char const * const key, + char const * const value) + { + assert (key); + + ostringstream keybuf; + keybuf << key; + ostringstream valuebuf; + valuebuf << value; + + list<string> const keys = parse (keybuf.str()); + + msgbuf << " "; + for (list<string>::const_iterator lsi = keys.begin(); + lsi != keys.end(); ++ lsi) + { + msgbuf << "<form:" << * lsi << ">"; + } + msgbuf << clean (valuebuf.str()); + for (list<string>::const_reverse_iterator lsi = keys.rbegin(); + lsi != keys.rend(); ++ lsi) + { + msgbuf << "</form:" << * lsi << ">"; + } + msgbuf << endl; + } + + + + string rdf:: + clean (string const & txt) + const + { + ostringstream buf; + + for (string::const_iterator p = txt.begin(); p != txt.end(); ++ p) + { + switch (* p) + { + case '<': buf << "<"; break; + case '&': buf << "&"; break; + default: buf << * p; + } + } + + return buf.str(); + } + + + + static bool + is_clean_for_shell (char const * const str) + { + for (char const * p = str; * p; ++ p) + { + if (! isalnum (* p)) + { + // Allow only certain characters + switch (* p) + { + case '+': + case ',': + case '-': + case '.': + case '/': + case ':': + case '_': + case '~': + break; + default: + // We don't like this character + return false; + } + } + } + return true; + } + + + + static list<string> + parse (string const str) + { + list<string> strs; + size_t p = 0; + for (;;) { + size_t const s = str.find ("/", p); + if (s == string::npos) break; + strs.push_back (str.substr (p, s - p)); + p = s + 1; + } + strs.push_back (str.substr (p)); + return strs; + } + + + +} // namespace Formaline diff --git a/src/rdf.hh b/src/rdf.hh new file mode 100644 index 0000000..610842f --- /dev/null +++ b/src/rdf.hh @@ -0,0 +1,60 @@ +// $Header$ + +#ifndef FORMALINE_RDF_HH +#define FORMALINE_RDF_HH + +#include <sstream> +#include <string> + +#include "storage.hh" + + + +namespace Formaline +{ + + + + class rdf : public storage + { + + std::ostringstream msgbuf; + + public: + + rdf (char const * id, + enum state st); + + virtual + ~ rdf (); + + virtual void + store (char const * key, + bool value); + + virtual void + store (char const * key, + int value); + + virtual void + store (char const * key, + double value); + + virtual void + store (char const * key, + char const * value); + + private: + + std::string + clean (std::string const & txt) + const; + }; + + + +} // namespace Formaline + + + +#endif // ifndef FORMALINE_RDF_HH diff --git a/src/util/gethostname.pl b/src/util/gethostname.pl new file mode 100755 index 0000000..d403e05 --- /dev/null +++ b/src/util/gethostname.pl @@ -0,0 +1,38 @@ +#! /usr/bin/perl -w + +# Find the host name of this machine + +# 2006-05-02 Erik Schnetter <schnetter@cct.lsu.edu> + +# Search through the host name and all aliases. +# Use the first name that contains dots, indicating that this name is +# a long host name that includes a domain name. +# If there is no name that includes a domain name, use whatever the +# system calls "host name". + +use strict; + +# Get the system's idea of its host name +my $hostname = `hostname`; +chomp $hostname; + +# Find its host name and all aliases +my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname ($hostname); + +# Split the aliases +my @names = ($name, split (' ', $aliases)); + +# Use the host name as fallback +my $goodname = $name; + +# Search for a name that contains a dot +foreach my $maybename (@names) +{ + if ($maybename =~ /[.]/) + { + $goodname = $maybename; + last; + } +} + +print "$goodname\n"; |