-rw-r--r-- | components/exception_dev | 7 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | include/sitecing/sitecing_util.h | 85 | ||||
-rw-r--r-- | lib/component_factory.cc | 31 | ||||
-rw-r--r-- | lib/configuration.cc | 9 | ||||
-rw-r--r-- | lib/sitecing_parser.ll | 13 | ||||
-rw-r--r-- | lib/sitecing_util.cc | 117 | ||||
-rw-r--r-- | lib/sitespace.cc | 3 | ||||
-rw-r--r-- | src/sitecing-build.cc | 5 | ||||
-rw-r--r-- | src/sitecing-fastcgi.cc | 4 | ||||
-rw-r--r-- | src/sitecing-plaincgi.cc | 4 |
11 files changed, 47 insertions, 235 deletions
diff --git a/components/exception_dev b/components/exception_dev index d8c84e1..d62f462 100644 --- a/components/exception_dev +++ b/components/exception_dev @@ -1,44 +1,45 @@ %%decl using namespace std; <%impl> #include <iostream> #include <fstream> #include <sstream> #include <cassert> #include <cstdarg> #include <stdexcept> #include <cxxabi.h> #include <sitecing/sitecing_util.h> #include <sitecing/util.h> #include <sitecing/magic.h> + #include <konforka/util.h> #include <konforka/exception.h> </%impl> %%var string message; %%var string root_source; %%var string root_intermediate; %%var string root_so; %%var string component; %%var int line_number = -1; %%var const exception* exception_caught; <%code> __SCIF->headers.clear(); __SCIF->out->seekp(0); int magic = _magic; va_list va = _args; switch(magic) { case sitecing::__magic_compile_error: message = va_arg(va,const char*); root_source = va_arg(va,const char*); root_intermediate = va_arg(va,const char*); root_so = va_arg(va,const char*); component = va_arg(va,const char*); break; case sitecing::__magic_preprocess_error: message = va_arg(va,const char*); root_source = va_arg(va,const char*); root_intermediate = va_arg(va,const char*); root_so = va_arg(va,const char*); component = va_arg(va,const char*); line_number = va_arg(va,int); break; case sitecing::__magic_generic_exception: message = va_arg(va,const char*); @@ -225,122 +226,122 @@ if(err.bad()) { <%output> Failed to access compiler output </%output> }else{ string cumulative; string error_file; long error_line = -1; while(!err.eof()) { string oef = error_file; long oel = error_line; string line; getline(err,line); if(line[0]!=' ') { string::size_type c = line.find(':'); if(c!=string::npos) { string fn = line.substr(0,c); string::size_type c1 = line.find(':',c+1); if(c1!=string::npos) { string ln = line.substr(c+1,c1-c-1); string::size_type nd = ln.find_first_not_of("0123456789"); if(nd==string::npos) { try { error_file = sitecing::strip_prefix(fn,"In file included from "); }catch(sitecing::utility_no_prefix& unp) { error_file = fn; } error_line = strtol(ln.c_str(),0,10); } } } if((oel>0 && !oef.empty()) && (oel!=error_line || oef!=error_file)) { - string ef = "/"+sitecing::combine_path(root_source+component,oef); + string ef = "/"+konforka::combine_path(root_source+component,oef); report_error(ef,oel,remove_roots(cumulative)); cumulative.clear(); } } if(!cumulative.empty()) cumulative += '\n'; cumulative += line; } if(!(cumulative.empty() || error_file.empty() || error_line<0)) { - error_file = "/"+sitecing::combine_path(root_source+component,error_file); + error_file = "/"+konforka::combine_path(root_source+component,error_file); report_error(error_file,error_line,remove_roots(cumulative)); } } </%code> </div> </%method> <%method void handle_unknown_error() %> <div class="exception-unknown"> <h1>unknown error</h1> </div> </%method> <%method void report_error(const string& file,long line,const string& message) %> <div class="exception-codepoint-report"> <h3><% sitecing::html_escape(strip_roots(file)) %></h3> <%code> if(line>=0) { int firstline = line-5, lastline = line+5; if(firstline<1) firstline = 1; ifstream ifs(file.c_str(),ios::in); if(ifs.bad()) { // TODO: }else{ for(int l=1;l<firstline && !ifs.eof();l++) { ifs.ignore(65536,'\n'); } if(ifs.eof()) { // TODO: no such line in file }else{ <%output><ul></%output> for(int l=firstline;l<=lastline && !ifs.eof();l++) { string str; getline(ifs,str); for(string::size_type t=str.find('\t');t!=string::npos;t=str.find('\t')) { str.replace(t,1,8-(t%8),' '); } char tln[16]; snprintf(tln,sizeof(tln),"%5d",l); <%output> <li class="<% l==line?"focused":"unfocused" %>"><span class="lineno"><% sitecing::html_escape(tln,sitecing::html_escape_nbsp) %></span> <span class="line"><% sitecing::html_escape(str,sitecing::html_escape_nbsp) %></span></li> </%output> } <%output></ul></%output> } } } </%code> <div class="what"> <% sitecing::html_escape(message,sitecing::html_escape_br) %> </div> </div> </%method> <%codemethod string strip_roots(const string& filename) %> - string np = sitecing::normalize_path(filename); + string np = konforka::normalize_path(filename); try{ return sitecing::strip_prefix(np,root_source); }catch(sitecing::utility_no_prefix& e){ } try{ return sitecing::strip_prefix(np,root_intermediate); }catch(sitecing::utility_no_prefix& e){ } </%codemethod> <%codemethod string remove_roots(const string& str) %> string rv = str; string::size_type rp; string::size_type rl = root_source.length(); while((rp=rv.find(root_source))!=string::npos) { rv.erase(rp,rl); } rl = root_intermediate.length(); while((rp=rv.find(root_intermediate))!=string::npos) { rv.erase(rp,rl); } rl = root_so.length(); while((rp=rv.find(root_so))!=string::npos) { rv.erase(rp,rl); } return rv; </%codemethod> % /* vim:set ft=sitecing: */ diff --git a/configure.ac b/configure.ac index a8aa142..fde326b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,54 +1,58 @@ AC_INIT([sitecing], [0.0.1], [sitecing-bugs@klever.net]) AC_CONFIG_SRCDIR([include/sitecing/sitecing_parser.h]) AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE([dist-bzip2]) AC_PROG_INSTALL AC_PROG_AWK AC_PROG_CXX AC_PROG_CC AM_PROG_LEX AC_PROG_LIBTOOL AC_HEADER_STDC AC_CHECK_HEADERS([stdlib.h unistd.h]) AC_C_CONST AC_FUNC_MALLOC AC_FUNC_REALLOC AC_WITH_PKGCONFIG +PKG_CHECK_MODULES([KONFORKA],[konforka >= 0.0.1],,[ + AC_MSG_ERROR([no proper version of konforka library found, get it at http://kin.klever.net/konforka/]) +]) + PKG_CHECK_MODULES([KINGATE],[kingate >= 0.0.1],,[ AC_MSG_ERROR([no kingate library found, get it at http://kin.klever.net/kingate/]) ]) HAVE_FCGI=false HAVE_PLAINCGI=false PKG_CHECK_MODULES([KINGATE_FCGI],[kingate-fcgi >= 0.0.1],[ HAVE_FCGI=true ],[ AC_MSG_NOTICE([no fastcgi support in kingate library]) ]) PKG_CHECK_MODULES([KINGATE_PLAINCGI],[kingate-plaincgi >= 0.0.1],[ HAVE_PLAINCGI=true ],[ AC_MSG_NOTICE([no plaincgi support in kingate library]) ]) if ! (${HAVE_FCGI} || ${HAVE_PLAINCGI}) ; then AC_MSG_ERROR([not a single CGI interface supported in kingate]) fi AM_CONDITIONAL([HAVE_FCGI],[${HAVE_FCGI}]) AM_CONDITIONAL([HAVE_PLAINCGI],[${HAVE_PLAINCGI}]) PKG_CHECK_MODULES([DOTCONF],[dotconf],,[ AC_MSG_ERROR([no dotconf library found]) ]) AC_WITH_PCRE([ AC_WITH_PCREPP(,[ AC_MSG_ERROR([no pcre++ library found]) ]) ],[ AC_MSG_ERROR([no pcre library found]) ]) diff --git a/include/sitecing/sitecing_util.h b/include/sitecing/sitecing_util.h index d1a6c4a..f642c74 100644 --- a/include/sitecing/sitecing_util.h +++ b/include/sitecing/sitecing_util.h @@ -1,99 +1,83 @@ #ifndef __SITECING_SITECING_UTIL_H #define __SITECING_SITECING_UTIL_H #include <sys/types.h> #include <string> #include <konforka/exception.h> +#include <konforka/util.h> /** * @file * @brief utility classes and functions. */ namespace sitecing { using namespace std; /** * Base class for utility exceptions. */ class utility_error : public konforka::exception { public: utility_error(const string& fi,const string& fu,int l,const string& w) : konforka::exception(fi,fu,l,w) { } }; - /** - * Restricted sequence encountered. - */ - class utility_restricted_sequence : public utility_error { - public: - utility_restricted_sequence(const string& fi,const string& fu,int l,const string& w) - : utility_error(fi,fu,l,w) { } - }; + /** * No prefix or suffix found to strip out. */ class utility_no_affix : public utility_error { public: utility_no_affix(const string& fi,const string& fu,int l,const string& w) : utility_error(fi,fu,l,w) { } }; /** * No prefix to strip found. */ class utility_no_prefix : public utility_no_affix { public: utility_no_prefix(const string& fi,const string& fu,int l,const string& w) : utility_no_affix(fi,fu,l,w) { } }; /** * No suffix to strip found. */ class utility_no_suffix : public utility_no_affix { public: utility_no_suffix(const string& fi,const string& fu,int l,const string& w) : utility_no_affix(fi,fu,l,w) { } }; /** - * Went up beyond root. - * @todo TODO: wish I could remember the details -- document me. - */ - class utility_beyond_root : public utility_error { - public: - utility_beyond_root(const string& fi,const string& fu,int l,const string& w) - : utility_error(fi,fu,l,w) { } - }; - - /** * The file lock object. Released at the object destruction. */ class file_lock { public: /** * The file descriptor. */ int fd; file_lock() : fd(-1) { } /** * @param f file name. */ file_lock(const string& f) : fd(-1) { lock(f); } ~file_lock() { unlock(); } /** * Do lock. * @param f file name. */ void lock(const string& f); /** * @todo TODO: wish I could remember the details -- document me. */ void lock(); /** * Release the lock obtained. */ void unlock(); }; @@ -186,144 +170,79 @@ namespace sitecing { /** * @param s pointer to the semaphore. * @param l lock at creation? */ semaphore_lock(semaphore* s,bool l=true) : sem(s), locked(false) { if(l) lock(); } /** * @param s reference to the semaphore. * @param l lock at creation? */ semaphore_lock(semaphore& s,bool l=true) : sem(&s), locked(false) { if(l) lock(); } ~semaphore_lock() { unlock(); } /** * Lock it. */ void lock(); /** * Unlock it. */ void unlock(); }; /** - * normalize_path options enumeration. - * @see normalize_path() - */ - enum normalize_path_options { - /** - * Restrict the /../ sequence. - */ - restrict_dotdot = 1, - /** - * Strip out the leading slash. - */ - strip_leading_slash = 2, - /** - * Strip out the trailing slash. - */ - strip_trailing_slash = 4 - }; - /** - * combine_path options enumeration. - * @see combine_path() - */ - enum combine_path_options { - /** - * The origin is file. Otherwise it is directory. - */ - origin_is_file = 1, - /** - * Fail if we've gone up beyond root. - */ - fail_beyond_root = 2 - }; - - /** - * Normalize pathname by stripping duplicate slashes, etc. - * @param path the path name. - * @param opts options. - * @return the normalized path. - * @see normalize_path_options - * @todo TODO: document exceptions. - */ - string normalize_path(const string& path,int opts=(restrict_dotdot|strip_trailing_slash)); - /** * Strip prefix from the string. * @param str the string. * @param prefix prefix to strip. * @return the string without prefix. * @todo TODO: document exceptions. */ string strip_prefix(const string& str,const string& prefix); /** * Strip suffix from the string. * @param str the string. * @param suffix suffix to strip. * @return the string without suffix. * @todo TODO: document exceptions. */ string strip_suffix(const string& str,const string& suffix); - /** - * Get the directory part of the filename. - * @param filename the full file name. - * @return the directory part. - */ - string dir_name(const string& filename); - /** - * Combine path with the relative path. - * @param origin the origin. - * @param relative relative path to combine origin with. - * @param opts options. - * @return the pathc combined. - * @see combine_path_options - * @todo TODO: document exceptions. - */ - string combine_path(const string& origin,const string& relative,int opts=origin_is_file); - - /** - * Create directory and parent directories if needed. - * @param path the pathname. - * @param mode the mode for newly created directories. - */ - void make_path(const string& path,mode_t mode); /** * Change to the directory and pop back at object's destruction (e.g. when * the object goes out of scope). */ class auto_chdir { public: /** * Saved working directory. */ string saved_pwd; /** * Whether we want to change back automatically. */ bool autopop; auto_chdir() : autopop(false) { } /** * @param td destination path. * @param ap automatically come back? */ auto_chdir(const string& td,bool ap=true) : autopop(false) { pushdir(td,ap); } ~auto_chdir() { if(autopop) popdir(); } /** * Change into directory. * @param td the directory. diff --git a/lib/component_factory.cc b/lib/component_factory.cc index d9692de..af3d911 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc @@ -1,66 +1,67 @@ #ifdef USE_PCH #include "pch.h" #else #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <sys/wait.h> #include <fcntl.h> #include <iostream> #include <fstream> #include <stdexcept> #include <vector> using namespace std; + #include <konforka/util.h> #include "sitecing/component_factory.h" #include "sitecing/sitecing_util.h" #include "sitecing/sitecing_parser.h" #include "sitecing/sitecing_exception.h" #endif namespace sitecing { static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; static const char *cc_targets[] = { ".o", ".d" }; component_factory::component_factory(configuration& c) : config(c), - root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), - root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), - root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { + root_source(konforka::normalize_path(c.root_source,konforka::strip_trailing_slash)+'/'), + root_intermediate(konforka::normalize_path(c.root_intermediate,konforka::strip_trailing_slash)+'/'), + root_so(konforka::normalize_path(c.root_so,konforka::strip_trailing_slash)+'/') { } void component_factory::get_dependencies(const string& dst,file_list_t& deps) { deps.clear(); - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); // source documents try { // XXX: or just compare it off? string noro = strip_prefix(dp,root_source); return; }catch(utility_no_affix& una) { } // .so binaries try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); deps.push_back(root_intermediate+noro+".o"); config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); if(co_so_deps) { for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) deps.push_back(*i); } return; }catch(utility_no_prefix& unp) { throw konforka::exception(CODEPOINT,"component is outside of component root"); }catch(utility_no_suffix& uns) { } try { // preprocessor targets string noro = strip_prefix(dp,root_intermediate); for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); deps.push_back(root_source+nos); // depends on the source ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); if(imports.good()) { string str; while(!imports.eof()) { imports >> str; if(!str.empty()) @@ -69,276 +70,276 @@ namespace sitecing { } ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); if(ancestors.good()) { string str; while(!ancestors.eof()) { ancestors >> str; if(!str.empty()) deps.push_back(root_intermediate+str+".classname"); } } // XXX: intermediate_deps should be broken down config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); if(co_intermediate_deps) { for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) deps.push_back(*i); } return; }catch(utility_no_suffix& uns) { } } // compiler targets for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { try { string nos = strip_suffix(noro,cc_targets[cct]); deps.push_back(root_intermediate+nos+".cc"); config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { ifstream df((root_intermediate+nos+".d").c_str(),ios::in); if(df.good()) { string str; while(!df.eof()) { df >> str; if(str.find_first_of("\\:")==string::npos) - deps.push_back(combine_path(config.root_source+nos,str)); + deps.push_back(konforka::combine_path(config.root_source+nos,str)); } } } // XXX: intermediate_deps should be broken down config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); if(co_intermediate_deps) { for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) deps.push_back(*i); } }catch(utility_no_suffix& uns) { } } }catch(utility_no_prefix& unp) { } } bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); try { string noro = strip_prefix(dp,root_intermediate); for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); }catch(utility_no_suffix& uns) { } } bool rv = file_factory::is_uptodate(dst,deps); return rv; }catch(utility_no_prefix& unp) { } // XXX: or just compare it off, instead of throwing things around. try { strip_prefix(dp,root_so); return file_factory::is_uptodate(dst,deps); }catch(utility_no_prefix& unp) { } return true; } void component_factory::build(const string& dst) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); // sources try { string noro = strip_prefix(dp,root_source); // building the sources is left up to developer return; }catch(utility_no_prefix& unp) { } // .so files try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); string o = root_intermediate+noro+".o"; cerr << "Linking " << noro << endl; if(access(o.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); - make_path(dir_name(root_so+noro),0755); + konforka::make_path(konforka::dir_name(root_so+noro),0755); file_lock lock_cc(root_intermediate+noro+".o.lock"); file_lock lock_so(root_so+noro+".so.lock"); int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdO<0) throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdE<0) { close(stdO); throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); } list<string> args; config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); if(co_ld_flags) { args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); } args.push_back("-shared"); args.push_back(o); file_list_t ancestors; get_ancestors(noro,ancestors); for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { string aso=root_so+*i+".so"; make(aso); args.push_back(aso); } args.push_back("-o"); args.push_back(dp); // TODO: "g++" configurable int rv = execute("g++",args,stdO,stdE); if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) throw link_error(CODEPOINT,"failed to link component",noro); return; }catch(utility_no_prefix& unp) { throw konforka::exception(CODEPOINT,"component is outside of component root"); }catch(utility_no_suffix& uns) { } try { string noro = strip_prefix(dp,root_intermediate); // compiler targets for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { try { string nos = strip_suffix(noro,cc_targets[cct]); string cc = root_intermediate+nos+".cc"; string o = root_intermediate+nos+".o"; cerr << "Compiling " << nos << endl; if(access(cc.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); - make_path(dir_name(cc),0755); - string pwd = dir_name(root_source+nos); + konforka::make_path(konforka::dir_name(cc),0755); + string pwd = konforka::dir_name(root_source+nos); auto_chdir dir_changer(pwd); file_lock lock_source(root_intermediate+nos+".lock"); file_lock lock_cc(root_intermediate+nos+".o.lock"); int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdO<0) throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdE<0) { close(stdO); throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); } list<string> args; config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); if(co_cpp_flags) { args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); } // TODO: maybe move it to separare config option like CoreCPPFLags? args.push_back("-I"+root_intermediate); args.push_back("-I"+root_source); args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); args.push_back("-c"); args.push_back(cc); args.push_back("-o"); args.push_back(o); // TODO: "g++" configurable int rv = execute("g++",args,stdO,stdE); if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) throw compile_error(CODEPOINT,"failed to compile component",nos); return; }catch(utility_no_suffix& uns) { } } // preprocessor targets for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); string src = root_source+nos; cerr << "Preprocessing " << nos << endl; if(access(src.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); - make_path(dir_name(root_intermediate+nos),0755); + konforka::make_path(konforka::dir_name(root_intermediate+nos),0755); file_lock lock(root_intermediate+nos+".lock"); sitecing_parser parser(*this); config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); if(co_skeleton) parser.skeleton = co_skeleton->skeleton; static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); + parser.class_name = konforka::normalize_path(nos,konforka::strip_leading_slash|konforka::strip_trailing_slash); for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { string::size_type lc = parser.class_name.find_first_of(id_chars,illc); int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; parser.class_name.replace(illc,n,n,'_'); } parser.class_name = "_SCC_"+parser.class_name; parser.output_basename = root_intermediate+nos; parser.component_basename = nos; try { parser.preprocess(src); string sf = root_intermediate+nos+".pp_stamp"; ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp }catch(preprocessor_error& pe) { pe.component_name = nos; pe.see(CODEPOINT); throw; } return; }catch(utility_no_suffix& uns) { } } }catch(utility_no_prefix& unp) { } cerr << "ignoring build request for " << dp << endl; } void component_factory::make(const string& dst) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); file_list_t a; get_ancestors(noro,a); for(file_list_t::const_iterator i=a.begin();i!=a.end();++i) { make(root_so+*i+".so"); } }catch(utility_no_affix& una) { } file_factory::make(dst); } int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { // XXX: is it right that we do stdio/stderr tricks outside of the function? // cerr << "executing: " << cmd; vector<const char*> argv(args.size()+2); argv[0]=cmd.c_str(); int an = 1; for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { // cerr << " " << *i ; argv[an++] = i->c_str(); } // cerr << endl; argv[an++]=NULL; pid_t pid = vfork(); if(pid==-1) { close(stdo); close(stde); throw konforka::exception(CODEPOINT,"failed to vfork()"); } if(!pid) { // child if(dup2(stdo,1)!=1) _exit(-1); if(dup2(stde,2)!=2) _exit(-1); close(0); execvp(cmd.c_str(),(char**)&argv.front()); _exit(-1); } // parent close(stdo); close(stde); int rv; if(waitpid(pid,&rv,0)<0) throw konforka::exception(CODEPOINT,"failed to waitpid()"); return rv; } string component_factory::get_classname(const string& component) { - string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".classname"; + string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".classname"; make(cn); ifstream ifs(cn.c_str()); if(!ifs.good()) throw konforka::exception(CODEPOINT,"failed to access component .classname"); ifs >> cn; return cn; } void component_factory::get_ancestors(const string& component,file_list_t& rv) { - string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".ancestors"; + string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".ancestors"; make(cn); ifstream ifs(cn.c_str()); if(!ifs.good()) throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors"); rv.clear(); while(!ifs.eof()) { string a; ifs >> a; if(!a.empty()) rv.push_back(a); } } } diff --git a/lib/configuration.cc b/lib/configuration.cc index 4ee1526..6b21690 100644 --- a/lib/configuration.cc +++ b/lib/configuration.cc @@ -1,40 +1,41 @@ #ifdef USE_PCH #include "pch.h" #else #include <unistd.h> #include <fnmatch.h> #include <cassert> #include <stdexcept> using namespace std; + #include <konforka/util.h> #include <dotconf.h> #include "sitecing/configuration.h" #include "sitecing/sitecing_util.h" #include "sitecing/scoreboard.h" #endif namespace sitecing { configuration::configuration() : flags(0), autobuild(false) { } configuration::configuration(const string& cfile,bool ab) : flags(0), autobuild(ab) { parse(cfile); } enum dc_ctx { DCC_ROOT = 1, DCC_PATH = 2, DCC_SCRC = 4 }; struct dc_context { dc_ctx ctx; configuration* cf; list<config_options*> co; }; static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; dcc->cf->root_source = cmd->data.str; dcc->cf->flags |= configuration::flag_root_source; return NULL; } static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; @@ -275,175 +276,175 @@ namespace sitecing { return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal loaded_specs_t::iterator i = loaded_specs.find(target); if(i==loaded_specs.end() || !i->second.is_valid()) { if(i!=loaded_specs.end()) loaded_specs.erase(i); pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); assert(ii.first!=loaded_specs.end()); ii.first->second.parse(this,scrc); i = ii.first; } assert(i!=loaded_specs.end()); return &(i->second); } config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { if(i->regex.search(target)) return &*i; } return NULL; } string config_options::lookup_http_status_handler(const string& status) { http_status_handlers_t::const_iterator i = http_status_handlers.find(status); string rv; if(i!=http_status_handlers.end()) rv = i->second; return rv; } string configuration::lookup_http_status_handler(const string& target,const string& status) { string t = "/"; - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); string rv; for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { rv = lo->lookup_http_status_handler(status); if(!rv.empty()) return rv; } } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { rv = i->second.lookup_http_status_handler(status); if(!rv.empty()) return rv; } if(t.empty()) return rv; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { string t = "/"; - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_action_handlers) ) { config_options::action_handler_t *rv = lo->lookup_action_handler(target); if(rv) return rv; } } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { config_options::action_handler_t *rv = i->second.lookup_action_handler(target); if(rv) return rv; } if(t.empty()) return NULL; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } config_options* configuration::lookup_config(const string& target,int flag) { string t = "/"; // always assume leading slash - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); // XXX: reconsider precedence for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&flag)==flag ) return lo; } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&flag)==flag ) return &(i->second); if(t.empty()) return NULL; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } bool config_options::match_autobuild_files(const char *fn,bool &rv) { for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { const char *pat = i->c_str(); bool plus = true; if((*pat)=='+') pat++; else if((*pat)=='-') { plus = false; pat++; } if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { rv = plus; return true; } } return false; } bool configuration::match_autobuild_files(const string& target,const char *fn) { string t = "/"; - t += normalize_path(target,strip_leading_slash|strip_trailing_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash); t += "/"; bool rv = false; for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) return rv; } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) return rv; if(t.empty()) return rv; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } void configuration::parse(const string& cfile) { struct dc_context dcc; dcc.cf = this; dcc.ctx = DCC_ROOT; dcc.co.push_front(&root_options()); configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); if(!cf) diff --git a/lib/sitecing_parser.ll b/lib/sitecing_parser.ll index 4fd6709..8dd8d5f 100644 --- a/lib/sitecing_parser.ll +++ b/lib/sitecing_parser.ll @@ -1,41 +1,42 @@ %{ /* * XXX: I have a strong feeling that this parser should be completely rewritten. */ #include <iostream> #include <fstream> #include <cassert> #include <stdexcept> using namespace std; +#include <konforka/util.h> #include "sitecing/sitecing_util.h" #include "sitecing/sitecing_exception.h" using namespace sitecing; #define sitecing_parser_flexlexer_once #include "sitecing/sitecing_parser.h" #include "sitecing/sitecing_enflesher.h" #undef yyFlexLexer #define yyFlexLexer sitecing_parserFlexLexer %} %x SLASHSTAR_COMMENT SLASHSLASH_COMMENT STRING %x CODELINE CLASSLINE DECLLINE IMPLLINE DECLBLOCK IMPLBLOCK VARLINE VARINIT %x IMPORTLINE IMPORTCOMPONENT %x IMPORTTYPELINE IMPORTTYPECOMPONENT %x DERIVELINE DERIVECOMPONENT %x CONSTRUCTOR DESTRUCTOR CODEMETHODLINE CODEMETHODARGS %x CODEMETHODBLOCK INLINE METHODLINE METHODARGS METHODBLOCK CODEBLOCK OUTPUTBLOCK %x PRAGMALINE %option 8bit c++ verbose noyywrap yyclass="sitecing_parser" prefix="sitecing_parser" stack yylineno WHITESPACE [ \t] ID [A-Za-z_][A-Za-z0-9_]* NOIDCHAR [^A-Za-z0-9_] %% <INITIAL>{ ^\%\%class{WHITESPACE}+ { // TODO: signal error if we already have class name acquired from source. modi.push_front(modus_operandi(modus_operandi::flag_devour_comments|modus_operandi::flag_devour_whitespace)); BEGIN(CLASSLINE); } ^\%\%decl{WHITESPACE}+ { @@ -268,134 +269,134 @@ NOIDCHAR [^A-Za-z0-9_] anchor(); BEGIN(CODEMETHODBLOCK); } } <IMPORTLINE>{ {WHITESPACE}+ { } {ID} { modus_operandi& m = M(); if(!m._name.empty()) throw preprocessor_error(CODEPOINT,"syntax error",lineno()); m._name = yytext; } \= { M().output.clear(); BEGIN(IMPORTCOMPONENT); } } <IMPORTCOMPONENT>{ {WHITESPACE}+ { } \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true)); + string c = konforka::combine_path(component_basename,m.output); + member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true)); modi.pop_front(); BEGIN(INITIAL); } } <IMPORTTYPELINE>{ {WHITESPACE}+ { } {ID} { modus_operandi& m = M(); if(!m._name.empty()) throw preprocessor_error(CODEPOINT,"syntax error",lineno()); m._name = yytext; } \= { M().output.clear(); BEGIN(IMPORTTYPECOMPONENT); } } <IMPORTTYPECOMPONENT>{ {WHITESPACE}+ { } \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true,true)); + string c = konforka::combine_path(component_basename,m.output); + member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true,true)); modi.pop_front(); BEGIN(INITIAL); } } <DERIVELINE>{ {WHITESPACE}+ { } {ID} { modus_operandi& m = M(); if(!m._name.empty()) throw preprocessor_error(CODEPOINT,"syntax_error",lineno()); m._name = yytext; } \= { M().output.clear(); BEGIN(DERIVECOMPONENT); } } <DERIVECOMPONENT>{ {WHITESPACE}+ { } \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - ancestor_classes.push_back(ancestor_class(m._name,normalize_path(c,strip_leading_slash))); + string c = konforka::combine_path(component_basename,m.output); + ancestor_classes.push_back(ancestor_class(m._name,konforka::normalize_path(c,konforka::strip_leading_slash))); modi.pop_front(); BEGIN(INITIAL); } } <VARLINE>{ {WHITESPACE}+ { modus_operandi& m = M(); if(!m.output.empty()) { if(!m._lastid.empty()) { if(!m._type.empty()) m._type += ' '; m._type += m._lastid; } m._lastid = m.output; m.output.clear(); } } \* { modus_operandi& m = M(); ECHO; if(!m._lastid.empty()) { if(!m._type.empty()) m._type += ' '; m._type += m._lastid; } m._lastid = m.output; m.output.clear(); } \;|\n|\= { modus_operandi& m = M(); if(m.output.empty()) { m._name=m._lastid; }else{ diff --git a/lib/sitecing_util.cc b/lib/sitecing_util.cc index f892a60..f1432df 100644 --- a/lib/sitecing_util.cc +++ b/lib/sitecing_util.cc @@ -1,128 +1,66 @@ #ifdef USE_PCH #include "pch.h" #else #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/ipc.h> #include <sys/sem.h> #include <errno.h> #include <iostream> #include <fstream> #include <cassert> #include "sitecing/sitecing_util.h" #endif namespace sitecing { /* * XXX: all of these utilities could be sheerly optimized. */ - string normalize_path(const string& path,int opts) { - const char *s = path.c_str(); - string rv; - string::size_type notslash = 0; - if( (*s)=='.' && s[1]=='/' ) - s+=2; - if(opts&strip_leading_slash) - for(;(*s) && (*s)=='/';s++); - for(;*s;s++) { - if( (*s)=='/' ) { - if(s[1]=='/') - continue; - if(s[1]=='.' && s[2]=='/') { - s+=2; - continue; - } - } - if(opts&restrict_dotdot) { - if( - ( rv.empty() && s[0]=='.' && s[1]=='.' && s[2]=='/' ) // "^../" - || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)" - ) - throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered"); - } - rv += *s; - if( (*s) != '/' ) - notslash=rv.length(); - } - if(!(opts&strip_trailing_slash)) - notslash++; - if(notslash<rv.length()) - rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash - return rv; - } - string strip_prefix(const string& str,const string& prefix) { if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) throw utility_no_prefix(CODEPOINT,"no such prefix"); return str.substr(prefix.length()); } string strip_suffix(const string& str,const string& suffix) { if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) throw utility_no_suffix(CODEPOINT,"no such suffix"); return str.substr(0,str.length()-suffix.length()); } - string dir_name(const string& filename) { - string::size_type sl = filename.find_last_of('/'); - if(sl==string::npos) - return ""; // no slashes -- no dir. - string::size_type nosl = filename.find_last_not_of('/',sl); - if(nosl==string::npos) - return ""; // only slashes -- no dir. XXX: only slashes after the last slash... does it mean no dir? - return filename.substr(0,nosl+1); - } - - void make_path(const string& path,mode_t mode) { - struct stat st; - for(string::size_type sl=0;sl!=string::npos;sl=path.find('/',sl+1)) { - if(!sl) - continue; - string p = path.substr(0,sl); - if(stat(p.c_str(),&st) || !S_ISDIR(st.st_mode)) { - if(mkdir(p.c_str(),mode)) - throw konforka::exception(CODEPOINT,"failed to mkdir()"); - } - } - if(stat(path.c_str(),&st) || !S_ISDIR(st.st_mode)) { - if(mkdir(path.c_str(),mode)) - throw konforka::exception(CODEPOINT,"failed to mkdir()"); - } - } - void file_lock::lock(const string& f) { unlock(); fd = open(f.c_str(),O_CREAT|O_RDWR,S_IRUSR|S_IWUSR); if(fd<0) throw konforka::exception(CODEPOINT,"failed to open/create lockfile"); try { lock(); }catch(konforka::exception& ke) { ke.see(CODEPOINT); close(fd); fd=-1; throw; }catch(...) { close(fd); fd=-1; throw; } } void file_lock::lock() { assert(fd>=0); struct flock fl; fl.l_type = F_WRLCK; fl.l_whence=SEEK_SET; fl.l_start=fl.l_len=0; for(int tries=3;tries;tries--) { if(!fcntl(fd,F_SETLK,&fl)) return; sleep(8); } throw konforka::exception(CODEPOINT,"failed to obtain file lock"); } void file_lock::unlock() { if(fd<0) return; @@ -175,105 +113,50 @@ namespace sitecing { if(errno!=EINTR) throw konforka::exception(CODEPOINT,"failed to semop()"); } } void semaphore::off() { assert(semid>=0); struct sembuf sb; sb.sem_num=0; sb.sem_op=1; sb.sem_flg = SEM_UNDO; while(semop(semid,&sb,1)<0) { if(errno!=EINTR) throw konforka::exception(CODEPOINT,"failed to semop()"); } } void semaphore_lock::lock() { assert(sem); if(locked) return; sem->on(); locked = true; } void semaphore_lock::unlock() { if(!sem) return; if(!locked) return; sem->off(); locked=false; } - string combine_path(const string& origin,const string& relative,int opts) { - string r = normalize_path(relative,0); - string rv; - // XXX: what to do if relative is empty is a question, really. - if(r.empty()) { - return normalize_path( (opts&origin_is_file)?dir_name(origin):origin ,strip_leading_slash|restrict_dotdot|strip_trailing_slash); - }else{ - if(r[0]=='/') { - r.erase(0,1); - }else{ - rv = normalize_path((opts&origin_is_file)?dir_name(origin):origin,restrict_dotdot|strip_trailing_slash); - } - } - string::size_type lsl = rv.rfind('/'); - for(string::size_type sl=r.find('/');sl!=string::npos;sl=r.find('/')) { - assert(sl!=0); - if(sl==1 && r[0]=='.') { - // it's a "./" - r.erase(0,2); - }else if(sl==2 && r[0]=='.' && r[1]=='.') { - // we have a "../" - if(lsl==string::npos) { - if(rv.empty() && (opts&fail_beyond_root)) - throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); - rv.clear(); - }else{ - rv.erase(lsl); - lsl = rv.rfind('/'); - } - r.erase(0,3); - }else{ - // we have a "something/" - lsl = rv.length(); - rv += '/'; - rv += r.substr(0,sl); - r.erase(0,sl+1); - } - } - if(r.empty()) - return rv+'/'; - if(r.length()==2 && r[0]=='.' && r[0]=='.') { - if(lsl==string::npos) { - if(rv.empty() & (opts&fail_beyond_root)) - throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); - return "/"; - }else{ - rv.erase(lsl+1); - return rv; - } - } - rv += '/'; - rv += r; - return rv; - } - void auto_chdir::pushdir(const string& td,bool ap) { /* TODO: make use of fchdir(2) instead */ char *tmp = getcwd(0,0); assert(tmp); saved_pwd = tmp; free(tmp); autopop=ap; if(chdir(td.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir()"); } void auto_chdir::popdir() { autopop=false; if(chdir(saved_pwd.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir()"); // XXX: or should it be thrown? after all we call it from destructor... } } diff --git a/lib/sitespace.cc b/lib/sitespace.cc index 0406d11..d5592bf 100644 --- a/lib/sitespace.cc +++ b/lib/sitespace.cc @@ -1,52 +1,53 @@ #ifdef USE_PCH #include "pch.h" #else #include <cassert> + #include <konforka/util.h> #include "sitecing/sitespace.h" #include "sitecing/sitecing_util.h" #endif namespace sitecing { sitespace::sitespace(configuration& c) : config(c), factory(c) { } sitespace::~sitespace() { for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { assert((*i)->chickens_used.empty()); delete *i; } } so_component sitespace::fetch(const string& c,sitecing_interface* scif) { execute_sentenced(); - string sobase = normalize_path(c); + string sobase = konforka::normalize_path(c); string sopath = factory.root_so+sobase+".so"; config_options *co_build = config.lookup_config(sobase,config_options::flag_build); if( (!co_build) || co_build->build ) factory.make(sopath); components_t::iterator i = components.find(sopath); if(i!=components.end()) { if(i->second->is_uptodate()) return so_component(i->second,scif); if(i->second->chickens_used.empty()) { delete i->second; }else{ sentenced.push_back(i->second); } components.erase(i); } pair<components_t::iterator,bool> ins = components.insert(components_t::value_type(sopath,new component_so(sopath))); return so_component(ins.first->second,scif); } void sitespace::execute_sentenced() { for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { if((*i)->chickens_used.empty()) { delete *i; sentenced.erase(i); } } } } diff --git a/src/sitecing-build.cc b/src/sitecing-build.cc index 4cad0a3..887ef83 100644 --- a/src/sitecing-build.cc +++ b/src/sitecing-build.cc @@ -1,41 +1,42 @@ #include <sys/types.h> #include <dirent.h> #include <getopt.h> #include <iostream> #include <memory> #include <fstream> #include <cassert> #include <set> using namespace std; +#include <konforka/util.h> #include "sitecing/sitecing_util.h" #include "sitecing/util.h" #include "sitecing/sitespace.h" #include "sitecing/sitecing_interface_cgi.h" #include "sitecing/cgi_component.h" #include "sitecing/configuration.h" #include "sitecing/magic.h" #include "sitecing/sitecing_exception.h" #include "sitecing/exception.h" using namespace sitecing; #include "config.h" #define PHEADER PACKAGE "-build Version " VERSION #define PCOPY "Copyright (c) 2004 Klever Group" static sitespace* site_space = NULL; typedef pair<dev_t,ino_t> the_inode_t; set<the_inode_t> built_inodes; void build_component(const string& component) { assert(site_space); cerr << "Building " << component << endl; try { site_space->factory.make(site_space->config.root_so+component+".so"); }catch(compile_error& ce) { ce.see(CODEPOINT); ifstream err((site_space->config.root_intermediate+ce.component_path+".stderr").c_str(),ios::in); if(err) { cerr << err.rdbuf(); } throw; }catch(preprocessor_error& pe) { @@ -49,65 +50,65 @@ void build_imports(const string& component); void build_with_imports(const string& component) { assert(site_space); struct stat st; string cp = site_space->config.root_source+component; if(!lstat(cp.c_str(),&st)) { if(built_inodes.find(the_inode_t(st.st_dev,st.st_ino))!=built_inodes.end()) return; built_inodes.insert(the_inode_t(st.st_dev,st.st_ino)); } build_component(component); build_imports(component); } void build_imports(const string& component) { assert(site_space); ifstream ifs((site_space->config.root_intermediate+component+".imports").c_str(),ios::in); cerr << "Building components imported by " << component << endl; if(ifs) { string import; while(!ifs.eof()) { ifs >> import; if(!import.empty()) build_with_imports(import); } } } void build_http_status_handlers(const string& target) { assert(site_space); set<string> stop_list; string t = "/"; - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = site_space->config.lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { for(config_options::http_status_handlers_t::const_iterator i=lo->http_status_handlers.begin();i!=lo->http_status_handlers.end();++i) { if(stop_list.find(i->first)==stop_list.end()) { build_with_imports(i->second); stop_list.insert(i->first); } } } } configuration::specs_t::iterator i=site_space->config.specs.find(t); if( i!=site_space->config.specs.end() && (i->second.flags&config_options::flag_http_status_handlers) ) { for(config_options::http_status_handlers_t::const_iterator ii=i->second.http_status_handlers.begin();ii!=i->second.http_status_handlers.end();++i) { if(stop_list.find(ii->first)==stop_list.end()) { build_with_imports(ii->second); stop_list.insert(ii->first); } } } if(t.empty()) return; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } @@ -118,65 +119,65 @@ void build_target(const string& target) { assert(site_space); string action = target; config_options::action_handler_t *ah = site_space->config.lookup_action_handler(target); if(ah) action = ah->action; build_with_imports(action); } void build(const string& target) { assert(site_space); build_http_status_handlers(target); config_options *co_exception_handler = site_space->config.lookup_config(target,config_options::flag_exception_handler); if(co_exception_handler) { string handler = co_exception_handler->exception_handler; build_with_imports(handler); } string target_source = site_space->config.root_source+target; struct stat st; if(stat(target_source.c_str(),&st)) throw konforka::exception(CODEPOINT,"failed to stat() target"); if(S_ISREG(st.st_mode)) { build_target(target); }else if(S_ISDIR(st.st_mode)) { build_http_status_handlers(target); DIR *d=opendir(target_source.c_str()); if(!d) throw konforka::exception(CODEPOINT,"failed to opendir()"); for(struct dirent *de=readdir(d);de;de=readdir(d)) { if(!strcmp(de->d_name,".")) continue; if(!strcmp(de->d_name,"..")) continue; - string subtarget = normalize_path(target+"/"+de->d_name); + string subtarget = konforka::normalize_path(target+"/"+de->d_name); struct stat sts; if(stat((site_space->config.root_source+subtarget).c_str(),&sts)) throw konforka::exception(CODEPOINT,"failed to stat() subtarget"); if(S_ISDIR(sts.st_mode)) { build(subtarget); }else{ if(site_space->config.match_autobuild_files(target,de->d_name)){ build_target(subtarget); } } } closedir(d); } } int main(int argc,char **argv) { try { string config_file = "sitecing.conf"; while(true) { static struct option opts[] = { { "help", no_argument, 0, 'h' }, { "usage", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "license", no_argument, 0, 'L' }, { "config", required_argument, 0, 'f' }, { NULL, 0, 0, 0 } }; int c = getopt_long(argc,argv,"f:hVL",opts,NULL); if(c==-1) break; switch(c) { case 'h': diff --git a/src/sitecing-fastcgi.cc b/src/sitecing-fastcgi.cc index 756dcee..03587aa 100644 --- a/src/sitecing-fastcgi.cc +++ b/src/sitecing-fastcgi.cc @@ -136,84 +136,84 @@ sitecing_fastcgi_pm::~sitecing_fastcgi_pm() { void sitecing_fastcgi_pm::process(int slot) { signal(SIGINT,SIG_DFL); signal(SIGABRT,SIG_DFL); signal(SIGTERM,SIG_DFL); give_up_privs(); scoreboard_slot *sslot = sboard.get_slot(slot); try { sitespace ss(config); fcgi_socket& fs = *fss; sitecing_interface_cgi scif(&ss); string component_path; string action; config_options::action_handler_t *action_handler; int rpc = 0; if(config.flags&configuration::flag_requests_per_child) rpc = config.requests_per_child; for(int req=0;(rpc<=0) || (req<rpc);rpc++) { semaphore_lock sl; if(multi) { sslot->state = scoreboard_slot::state_idle; sl.sem = &sem; sl.lock(); } sslot->state = scoreboard_slot::state_accept; fcgi_interface fi(fs); sslot->state = scoreboard_slot::state_processing; if(multi) sl.unlock(); cgi_gateway gw(fi); scif.prepare(&gw); try { - component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); + component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash); string full_component_path; string sitecing_path_info; while(true) { full_component_path = config.root_source+'/'+component_path; if(!access(full_component_path.c_str(),F_OK)) break; string::size_type sl = component_path.rfind('/'); if(sl==string::npos) throw konforka::exception(CODEPOINT,"can't find the target component"); sitecing_path_info.insert(0,component_path,sl,string::npos); component_path.erase(sl); } fi.metavars["SITECING_PATH_INFO"]=sitecing_path_info; action = component_path; action_handler = config.lookup_action_handler(component_path); if(action_handler) { action = action_handler->action; } - string pwd = dir_name(full_component_path); + string pwd = konforka::dir_name(full_component_path); if(chdir(pwd.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); so_component soc = ss.fetch(action,&scif); if(action_handler) { soc.ac->run(__magic_action, config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), &(action_handler->args) ); }else{ soc.ac->main(0,NULL); } }catch(http_status& hs) { scif.headers["Status"] = hs.status+" "+hs.message; string hshp = config.lookup_http_status_handler(component_path,hs.status); if(!hshp.empty()) { so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(), config.root_so.c_str(),action.c_str(),&hs); } }catch(compile_error& ce) { config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); if(co_exception_handler) { so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str()); }else{ ce.see(CODEPOINT); throw; } }catch(preprocessor_error& pe) { config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); if(co_exception_handler) { so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. diff --git a/src/sitecing-plaincgi.cc b/src/sitecing-plaincgi.cc index 3bd291a..2f93cc5 100644 --- a/src/sitecing-plaincgi.cc +++ b/src/sitecing-plaincgi.cc @@ -21,84 +21,84 @@ using namespace kingate; #include "sitecing/configuration.h" #include "sitecing/magic.h" #include "sitecing/sitecing_exception.h" #include "sitecing/exception.h" using namespace sitecing; #include "config.h" #define PHEADER PACKAGE " Version " VERSION #define PCOPY "Copyright (c) 2005 Klever Group" class cdummyClass : public acomponent { public: void main(int _magic,va_list _args) {} void *__the_most_derived_this() { return NULL; } } cdummyInstance; class adummyClass : public cgi_component { public: void main(int _magic,va_list _args) {} void *__the_most_derived_this() { return NULL; } } adummyInstance; void process_request(configuration& config) { try { sitespace ss(config); sitecing_interface_cgi scif(&ss); string component_path; string action; config_options::action_handler_t *action_handler; plaincgi_interface ci; cgi_gateway gw(ci); scif.prepare(&gw); try { - component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); + component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash); string full_component_path; string sitecing_path_info; while(true) { full_component_path = config.root_source+'/'+component_path; if(!access(full_component_path.c_str(),F_OK)) break; string::size_type sl = component_path.rfind('/'); if(sl==string::npos) throw konforka::exception(CODEPOINT,"can't find the target component"); sitecing_path_info.insert(0,component_path,sl,string::npos); component_path.erase(sl); } ci.metavars["SITECING_PATH_INFO"]=sitecing_path_info; action = component_path; action_handler = config.lookup_action_handler(component_path); if(action_handler) { action = action_handler->action; } - string pwd = dir_name(full_component_path); + string pwd = konforka::dir_name(full_component_path); if(chdir(pwd.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); so_component soc = ss.fetch(action,&scif); if(action_handler) { soc.ac->run(__magic_action, config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), &(action_handler->args) ); }else{ soc.ac->main(0,NULL); } }catch(http_status& hs) { scif.headers["Status"] = hs.status+" "+hs.message; string hshp = config.lookup_http_status_handler(component_path,hs.status); if(!hshp.empty()) { so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(), config.root_so.c_str(),action.c_str(),&hs); } }catch(compile_error& ce) { config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); if(co_exception_handler) { so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str()); }else{ ce.see(CODEPOINT); throw; } }catch(preprocessor_error& pe) { config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); if(co_exception_handler) { so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. |