diff --git a/examples/uclient/uclient.cpp b/examples/uclient/uclient.cpp index baa7bfd2..95111f55 100644 --- a/examples/uclient/uclient.cpp +++ b/examples/uclient/uclient.cpp @@ -67,7 +67,7 @@ public: // manage arg operation - p = argv[optind++]; + p = argv[optind]; UString url(p, strlen(p)); diff --git a/include/ulib/base/base.h b/include/ulib/base/base.h index 0b1977fe..2c6d5c47 100644 --- a/include/ulib/base/base.h +++ b/include/ulib/base/base.h @@ -108,8 +108,11 @@ U_DO_PRAGMA(message ("Sorry I was compiled with http2 enabled so I cannot suppor # undef U_HTTP_INOTIFY_SUPPORT U_DO_PRAGMA(message ("Sorry I was compiled with server captive portal mode enabled so I cannot support http inotify")) #endif +#if defined(HAVE_CXX17) && defined(__GNUC__) && !defined(HAVE_CONFIG_H) +U_DO_PRAGMA(message ("ULib is configured with C++17 support, so you must use the -std=gnu++17 g++ option for compilation")) +#endif #if defined(USE_HARDWARE_CRC32) && defined(__GNUC__) && !defined(HAVE_CONFIG_H) /* The built-in functions __builtin_ia32_crc32 are available when -mcrc32 is used */ -U_DO_PRAGMA(message ("ULib is configured with support for crc32 intrinsics, so you must use the -mcrc32 g++ option for compilation")) +U_DO_PRAGMA(message ("ULib is configured with crc32 intrinsics support, so you must use the -mcrc32 g++ option for compilation")) #endif #include diff --git a/include/ulib/file.h b/include/ulib/file.h index 7adffa28..b8024ea2 100644 --- a/include/ulib/file.h +++ b/include/ulib/file.h @@ -764,7 +764,8 @@ public: UString getContent( bool brdonly = true, bool bstat = false, bool bmap = false); UString _getContent(bool bsize = true, bool brdonly = false, bool bmap = false); - static UString contentOf(const UString& _pathname, int flags = O_RDONLY, bool bstat = false, const UString* environment = U_NULLPTR); + static UString contentOf(const UString& pathname, const UString& pinclude); + static UString contentOf(const UString& pathname, int flags = O_RDONLY, bool bstat = false, const UString* environment = U_NULLPTR); static char* mmap(uint32_t* plength, int _fd = -1, int prot = PROT_READ | PROT_WRITE, int flags = MAP_SHARED | MAP_ANONYMOUS, uint32_t offset = 0); diff --git a/src/ulib/file.cpp b/src/ulib/file.cpp index 52d95e79..d7df6bc4 100644 --- a/src/ulib/file.cpp +++ b/src/ulib/file.cpp @@ -894,6 +894,35 @@ UString UFile::contentOf(const UString& _pathname, int flags, bool bstat, const U_RETURN_STRING(content); } +UString UFile::contentOf(const UString& _pathname, const UString& pinclude) +{ + U_TRACE(0, "UFile::contentOf(%V,%V)", _pathname.rep, pinclude.rep) + + UFile file; + UString content; + + file.reset(); + file.setPath(_pathname); + + if (file.open(O_RDONLY)) + { + content = file.getContent(); + + U_RETURN_STRING(content); + } + + if (pinclude) + { + file.reset(); + + file.setPath(pinclude + '/' + UStringExt::basename(_pathname)); + + if (file.open(O_RDONLY)) content = file.getContent(); + } + + U_RETURN_STRING(content); +} + void UFile::printf(const char* format, uint32_t fmt_size, ...) { U_TRACE(0, "UFile::printf(%.*S,%u)", fmt_size, format, fmt_size) diff --git a/src/ulib/net/server/plugin/usp/test.usp b/src/ulib/net/server/plugin/usp/test.usp index a46d574b..07dcd221 100644 --- a/src/ulib/net/server/plugin/usp/test.usp +++ b/src/ulib/net/server/plugin/usp/test.usp @@ -1,2 +1 @@ - - + diff --git a/src/ulib/net/server/plugin/usp/usp_compile.sh.in b/src/ulib/net/server/plugin/usp/usp_compile.sh.in index f0180e42..714da1e2 100755 --- a/src/ulib/net/server/plugin/usp/usp_compile.sh.in +++ b/src/ulib/net/server/plugin/usp/usp_compile.sh.in @@ -59,7 +59,7 @@ test "$libsuffix" || libsuffix=so export UMEMPOOL="0,0,0,48,-20,-20,-20,-20,0" export PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin" -@ULIB_PREFIXDIR@/bin/usp_translator $file.usp && +@ULIB_PREFIXDIR@/bin/usp_translator ${local_includedir} $file.usp && @ULIB_PREFIXDIR@/bin/usp_libtool.sh --silent --tag=CXX --mode=compile \ @CXX@ ${local_includedir} -IULIB_PREFIXDIR@/include -DHAVE_CONFIG_H @CPPFLAGS@ @CXXFLAGS@ @USP_FLAGS@ -MT $basen.lo -MD -MP -c -o $basen.lo $basen.cpp && @ULIB_PREFIXDIR@/bin/usp_libtool.sh --silent --tag=CXX --mode=link \ diff --git a/src/ulib/net/server/plugin/usp/usp_translator.cpp b/src/ulib/net/server/plugin/usp/usp_translator.cpp index 2b8dbb49..fbac5d89 100644 --- a/src/ulib/net/server/plugin/usp/usp_translator.cpp +++ b/src/ulib/net/server/plugin/usp/usp_translator.cpp @@ -24,8 +24,9 @@ #undef ARGS #define ARGS "[filename usp]" -#define U_OPTIONS "" #define U_PURPOSE "program for dynamic page translation ([xxx].usp => [xxx].cpp)" +#define U_OPTIONS \ +"option I include 1 \"path of local include directory\" \"\"\n" #include @@ -221,30 +222,30 @@ public: if (bdefine || binclude) { - uint32_t pos; - const char* ptr; - UString block(100U + token.size()); + const char* ptr = usp.data(); + UString content, x(U_CAPACITY); + uint32_t pos2 = t.getDistance(), + pos1 = pos2 - token.size() - U_CONSTANT_SIZE(""); - block.snprintf(U_CONSTANT_TO_PARAM(""), token.rep); + U_INTERNAL_DUMP("pos1(%u) = %.10S pos2(%u) = %.10S", pos1, usp.c_pointer(pos1), pos2, t.getPointer()) - pos = t.getDistance() - block.size(); + U_INTERNAL_ASSERT_MAJOR(pos2, 0) - U_INTERNAL_DUMP("usp(%u) = %.10S", pos, t.getPointer()) + if (pos1) (void) x.append(ptr, pos1); - for (ptr = t.getPointer(); u__isspace(*ptr); ++ptr) block.push_back(*ptr); + ptr += pos2; if (bdefine) { - vdefine.push_back(block); - vdefine.push_back(UString::getStringNull()); - setDirectiveItem(directive, U_CONSTANT_SIZE("define")); - ptr = token.data(); + U_INTERNAL_ASSERT(token) - do { ++ptr; } while (u__isspace(*ptr) == false); + const char* ptr1 = token.data(); - pos = token.distance(ptr); + do { ++ptr1; } while (u__isspace(*ptr1) == false); + + uint32_t pos = token.distance(ptr1); UString id(token, 0, pos), value(token, pos); @@ -256,23 +257,27 @@ public: { setDirectiveItem(directive, U_CONSTANT_SIZE("include")); - UString content = UFile::contentOf(token); + U_INTERNAL_ASSERT(token) + + content = UFile::contentOf(token, pinclude); if (content.empty()) { - U_WARNING("load of include usp %V failed", token.rep); + U_ERROR("load of include usp %V failed: path = %V", token.rep, pinclude.rep); } - else - { -# ifdef DEBUG - token.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... -# endif - t.setData((usp = UStringExt::substitute(usp, block, content))); - - t.setDistance(pos); - } + (void) x.append(content); } + + (void) x.append(ptr, usp.remain(ptr)); + +# ifdef DEBUG + token.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... +# endif + + t.setData((usp = x)); + + t.setDistance(pos1); } return; @@ -286,6 +291,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("declaration")); + U_INTERNAL_ASSERT(token) + declaration = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); } else if (strncmp(directive, U_CONSTANT_TO_PARAM("session")) == 0) @@ -357,6 +364,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("vcode")); + U_INTERNAL_ASSERT(token) + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); vcode.setBuffer(20U + token.size()); @@ -369,6 +378,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("pcode")); + U_INTERNAL_ASSERT(token) + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); (void) output0.reserve(20U + token.size()); @@ -383,6 +394,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("lcode")); + U_INTERNAL_ASSERT(token) + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); (void) output0.reserve(20U + token.size()); @@ -401,6 +414,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("code")); + U_INTERNAL_ASSERT(token) + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); (void) output0.reserve(20U + token.size()); @@ -413,6 +428,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("number")); + U_INTERNAL_ASSERT(token) + (void) output0.reserve(100U + token.size()); output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUStringExt::appendNumber32(*UClientImage_Base::wbuffer, (%v));\n\t"), token.rep); @@ -423,6 +440,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("puts")); + U_INTERNAL_ASSERT(token) + (void) output0.reserve(100U + token.size()); output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t(void) UClientImage_Base::wbuffer->append((%v));\n\t"), token.rep); @@ -433,6 +452,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("xmlputs")); + U_INTERNAL_ASSERT(token) + (void) output0.reserve(100U + token.size()); output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_XML_PUTS((%v));\n\t"), token.rep); @@ -445,6 +466,8 @@ public: setDirectiveItem(directive, U_CONSTANT_SIZE("cout")); + U_INTERNAL_ASSERT(token) + (void) output0.reserve(200U + token.size()); output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tusp_sz = UObject2String((%v), usp_buffer, sizeof(usp_buffer));" @@ -460,6 +483,8 @@ public: setDirectiveItem(directive, (bfor ? U_CONSTANT_SIZE("printfor") : U_CONSTANT_SIZE("print"))); + U_INTERNAL_ASSERT(token) + (void) output0.reserve(200U + token.size()); UVector vec(token, ';'); @@ -584,9 +609,15 @@ loop: distance = t.getDistance(); UApplication::run(argc, argv, env); - if (argv[1] == U_NULLPTR) U_ERROR("filename usp not specified"); + // manage options - UString filename(argv[1]); + if (UApplication::isOptions()) pinclude = opt['I']; + + // manage arg + + if (argv[optind] == U_NULLPTR) U_ERROR("filename usp not specified"); + + UString filename(argv[optind]); usp = UFile::contentOf(filename); @@ -764,7 +795,7 @@ loop: distance = t.getDistance(); private: UTokenizer t; UVector vdefine; - UString usp, token, output0, output1, declaration, vcode, http_header; + UString pinclude, usp, token, output0, output1, declaration, vcode, http_header; bool bvar, bsession, bstorage, bfirst_pass, is_html, test_if_html, bpreprocessing_failed; U_DISALLOW_COPY_AND_ASSIGN(Application) diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index 6c6e044f..1a0a94f1 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -4105,6 +4105,14 @@ void UServer_Base::runLoop(const char* user) { # if !defined(U_LOG_DISABLE) && defined(DEBUG) last_event = u_now->tv_sec; + +# ifndef _MSWINDOWS_ + if (monitoring_process && + U_SYSCALL_NO_PARAM(getppid) == 1) + { + U_ERROR("the monitoring process has crashed, exiting..."); + } +# endif # endif UTimer::updateTimeToExpire(ptime); @@ -4274,7 +4282,7 @@ void UServer_Base::run() UInterrupt::setHandlerForSignal(SIGHUP, (sighandler_t)SIG_IGN); // NB: we can't use UInterrupt::erase() because it restore the old action (UInterrupt::init)... # ifdef U_LINUX - (void) U_SYSCALL(prctl, "%d,%lu", PR_SET_PDEATHSIG, SIGINT); + (void) U_SYSCALL(prctl, "%d,%lu", PR_SET_PDEATHSIG, SIGTERM); # endif runLoop(user); diff --git a/src/ulib/utility/string_ext.cpp b/src/ulib/utility/string_ext.cpp index 3b6eed46..74d2b5d1 100644 --- a/src/ulib/utility/string_ext.cpp +++ b/src/ulib/utility/string_ext.cpp @@ -318,8 +318,8 @@ UString UStringExt::substitute(const char* s, uint32_t len, UVector& ve char c; int32_t i; UString item; - bool breserve = false, bdigit = false, bspace = false; - uint32_t n1 = 0, n2 = 0, capacity, mask_lower = 0, mask_upper = 0; + bool breserve = false, bdigit = false, bspace = false, bdollar; + uint32_t n1 = 0, n2 = 0, capacity, mask_lower = 0, mask_upper = 0, dollar = 0; uint32_t maskFirstChar[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, @@ -337,13 +337,23 @@ UString UStringExt::substitute(const char* s, uint32_t len, UVector& ve c = item.first_char(); + if (c == '$') + { + ++dollar; + + continue; + } + if (u__islower(c)) mask_lower |= maskFirstChar[c-'a']; else if (u__isupper(c)) mask_upper |= maskFirstChar[c-'A']; - else if (u__isdigit(c)) bdigit = true; - else if (u__isspace(c)) bspace = true; + else if (u__isdigit(c)) bdigit = true; + else if (u__isspace(c)) bspace = true; } - U_INTERNAL_DUMP("n1 = %u n2 = %u mask_lower = %B mask_upper = %B bdigit = %b bspace = %b", n1, n2, mask_lower, mask_upper, bdigit, bspace) + bdollar = (dollar == n); + + U_INTERNAL_DUMP("n1 = %u n2 = %u mask_lower = %B mask_upper = %B bdigit = %b bspace = %b dollar = %u bdollar = %b", + n1, n2, mask_lower, mask_upper, bdigit, bspace, dollar, bdollar) if (n2 <= n1) capacity = len; else @@ -364,19 +374,26 @@ loop: { c = *p1; - if ((u__islower(c) && - (mask_lower & maskFirstChar[c-'a']) == 0) || - (u__isupper(c) && - (mask_upper & maskFirstChar[c-'A']) == 0) || - (u__isdigit(c) && - bdigit == false) || - (u__isspace(c) && - bspace == false)) + U_INTERNAL_DUMP("c = %C p1 = %.10S", c, p1) + + if (c == '$') + { + if (dollar) goto chk; + + continue; + } + + if (bdollar) continue; + + if ((u__isdigit(c) && bdigit == false) || + (u__isspace(c) && bspace == false) || + (u__islower(c) && (mask_lower & maskFirstChar[c-'a']) == 0) || + (u__isupper(c) && (mask_upper & maskFirstChar[c-'A']) == 0)) { continue; } - for (i = 0; i < (int32_t)n; i += 2) +chk: for (i = 0; i < (int32_t)n; i += 2) { item = vec[i]; diff --git a/tests/examples/ok/usp_include.ok b/tests/examples/ok/usp_include.ok index ea82418c..7b0c524f 100644 --- a/tests/examples/ok/usp_include.ok +++ b/tests/examples/ok/usp_include.ok @@ -1,9 +1,17 @@ HTTP/1.1 200 OK -Date: Thu, 12 Oct 2017 15:11:29 GMT +Date: Fri, 13 Oct 2017 16:14:16 GMT Server: ULib -Content-Type: text/html; charset=UTF-8 -Content-Length: 332 +Content-Type: text/plain; charset=UTF-8 +Content-Length: 340 + + + + + + + + @@ -26,11 +34,19 @@ Content-Length: 332 HTTP/1.1 200 OK -Date: Thu, 12 Oct 2017 15:11:29 GMT +Date: Fri, 13 Oct 2017 16:14:16 GMT Server: ULib -Content-Type: text/html; charset=UTF-8 -Content-Length: 332 +Content-Type: text/plain; charset=UTF-8 +Content-Length: 340 + + + + + + + + diff --git a/tests/examples/usp_include.test b/tests/examples/usp_include.test index 7579beed..bd510051 100755 --- a/tests/examples/usp_include.test +++ b/tests/examples/usp_include.test @@ -48,11 +48,12 @@ wait_server_ready localhost 8080 #echo "PID = `cat /var/run/userver_tcp.pid`" #exit 0 +$SLEEP send_req $NCAT localhost 8080 inp/http/usp_include.req usp_include 2 kill kill_server userver_tcp -mv err/userver_tcp.err err/one.err +mv err/userver_tcp.err err/usp_include.err # Test against expected output test_output_wc l usp_include