jutil.cpp 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #pragma warning(disable: 4996)
  15. #ifdef _WIN32
  16. #include "winprocess.hpp"
  17. #include <conio.h>
  18. #endif
  19. #include "platform.h"
  20. #include "jmisc.hpp"
  21. #include "jutil.hpp"
  22. #include "jexcept.hpp"
  23. #include "jmutex.hpp"
  24. #include "jfile.hpp"
  25. #include "jprop.hpp"
  26. #ifdef _WIN32
  27. #include <mmsystem.h> // for timeGetTime
  28. #else
  29. #include <unistd.h> // read()
  30. #include <sys/wait.h>
  31. #include <pwd.h>
  32. #ifdef __linux__
  33. #include <crypt.h>
  34. #include <shadow.h>
  35. #endif
  36. #include <time.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <termios.h>
  40. #include <signal.h>
  41. #include <paths.h>
  42. #include "build-config.h"
  43. #endif
  44. static SpinLock * cvtLock;
  45. #ifdef _WIN32
  46. static IRandomNumberGenerator * protectedGenerator;
  47. static CriticalSection * protectedGeneratorCs;
  48. #endif
  49. MODULE_INIT(INIT_PRIORITY_SYSTEM)
  50. {
  51. cvtLock = new SpinLock;
  52. #ifdef _WIN32
  53. protectedGenerator = createRandomNumberGenerator();
  54. protectedGeneratorCs = new CriticalSection;
  55. #endif
  56. return true;
  57. }
  58. MODULE_EXIT()
  59. {
  60. delete cvtLock;
  61. #ifdef _WIN32
  62. protectedGenerator->Release();
  63. delete protectedGeneratorCs;
  64. #endif
  65. }
  66. //===========================================================================
  67. bool safe_ecvt(size_t len, char * buffer, double value, int numDigits, int * decimal, int * sign)
  68. {
  69. #ifdef _WIN32
  70. return _ecvt_s(buffer, len, value, numDigits, decimal, sign) == 0;
  71. #elif defined(__FreeBSD__) || defined (__APPLE__)
  72. UNIMPLEMENTED;
  73. #else
  74. SpinBlock block(*cvtLock);
  75. const char * result = ecvt(value, numDigits, decimal, sign);
  76. if (!result)
  77. return false;
  78. strncpy(buffer, result, len);
  79. return true;
  80. #endif
  81. }
  82. bool safe_fcvt(size_t len, char * buffer, double value, int numPlaces, int * decimal, int * sign)
  83. {
  84. #ifdef _WIN32
  85. return _fcvt_s(buffer, len, value, numPlaces, decimal, sign) == 0;
  86. #elif defined(__FreeBSD__) || defined (__APPLE__)
  87. UNIMPLEMENTED;
  88. #else
  89. SpinBlock block(*cvtLock);
  90. const char * result = fcvt(value, numPlaces, decimal, sign);
  91. if (!result)
  92. return false;
  93. strncpy(buffer, result, len);
  94. return true;
  95. #endif
  96. }
  97. //===========================================================================
  98. #ifdef _WIN32
  99. void MilliSleep(unsigned milli)
  100. {
  101. Sleep(milli);
  102. }
  103. #else
  104. void MilliSleep(unsigned milli)
  105. {
  106. if (milli) {
  107. unsigned target = msTick()+milli;
  108. loop {
  109. timespec sleepTime;
  110. if (milli>=1000)
  111. {
  112. sleepTime.tv_sec = milli/1000;
  113. milli %= 1000;
  114. }
  115. else
  116. sleepTime.tv_sec = 0;
  117. sleepTime.tv_nsec = milli * 1000000;
  118. if (nanosleep(&sleepTime, NULL)==0)
  119. break;
  120. if (errno!=EINTR) {
  121. PROGLOG("MilliSleep err %d",errno);
  122. break;
  123. }
  124. milli = target-msTick();
  125. if ((int)milli<=0)
  126. break;
  127. }
  128. }
  129. else
  130. ThreadYield(); // 0 means yield
  131. }
  132. #endif
  133. long atolong_l(const char * s,int l)
  134. {
  135. char t[32];
  136. memcpy(t,s,l);
  137. t[l]=0;
  138. return atol(t);
  139. }
  140. int atoi_l(const char * s,int l)
  141. {
  142. char t[32];
  143. memcpy(t,s,l);
  144. t[l]=0;
  145. return atoi(t);
  146. }
  147. __int64 atoi64_l(const char * s,int l)
  148. {
  149. __int64 result = 0;
  150. char sign = '+';
  151. while (l>0 && isspace(*s))
  152. {
  153. l--;
  154. s++;
  155. }
  156. if (l>0 && (*s == '-' || *s == '+'))
  157. {
  158. sign = *s;
  159. l--;
  160. s++;
  161. }
  162. while (l>0 && isdigit(*s))
  163. {
  164. result = 10 * result + ((*s) - '0');
  165. l--;
  166. s++;
  167. }
  168. if (sign == '-')
  169. return -result;
  170. else
  171. return result;
  172. }
  173. #ifndef _WIN32
  174. static char *_itoa(unsigned long n, char *str, int b, bool sign)
  175. {
  176. char *s = str;
  177. if (sign)
  178. n = -n;
  179. do
  180. {
  181. byte d = n % b;
  182. *(s++) = d+((d<10)?'0':('a'-10));
  183. }
  184. while ((n /= b) > 0);
  185. if (sign)
  186. *(s++) = '-';
  187. *s = '\0';
  188. // reverse
  189. char *s2 = str;
  190. s--;
  191. while (s2<s)
  192. {
  193. char tc = *s2;
  194. *(s2++) = *s;
  195. *(s--) = tc;
  196. }
  197. return str;
  198. }
  199. char *itoa(int n, char *str, int b)
  200. {
  201. return _itoa(n, str, b, (n<0));
  202. }
  203. char *ltoa(long n, char *str, int b)
  204. {
  205. return _itoa(n, str, b, (n<0));
  206. }
  207. char *ultoa(unsigned long n, char *str, int b)
  208. {
  209. return _itoa(n, str, b, false);
  210. }
  211. #endif
  212. void packNumber(char * target, const char * source, unsigned slen)
  213. {
  214. unsigned next = 0;
  215. while (slen)
  216. {
  217. unsigned c = *source++;
  218. if (c == ' ') c = '0';
  219. next = (next << 4) + (c - '0');
  220. slen--;
  221. if ((slen & 1) == 0)
  222. {
  223. *target++ = next;
  224. next = 0;
  225. }
  226. }
  227. }
  228. void unpackNumber(char * target, const char * source, unsigned tlen)
  229. {
  230. if (tlen & 1)
  231. {
  232. *target = '0' + *source++;
  233. tlen--;
  234. }
  235. while (tlen)
  236. {
  237. unsigned char next = *source++;
  238. *target++ = (next >> 4) + '0';
  239. *target++ = (next & 15) + '0';
  240. tlen -= 2;
  241. }
  242. }
  243. //-----------------------------------------------------------------------
  244. HINSTANCE LoadSharedObject(const char *name, bool isGlobal, bool raiseOnError)
  245. {
  246. #if defined(_WIN32)
  247. UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  248. #else
  249. // don't think anything to do here.
  250. #endif
  251. DynamicScopeCtx scope;
  252. StringBuffer tmp;
  253. if (name&&isPathSepChar(*name)&&isPathSepChar(name[1])) {
  254. RemoteFilename rfn;
  255. rfn.setRemotePath(name);
  256. SocketEndpoint ep;
  257. if (!rfn.isLocal()) {
  258. // I guess could copy to a temporary location but currently just fail
  259. throw MakeStringException(-1,"LoadSharedObject: %s is not a local file",name);
  260. }
  261. name = rfn.getLocalPath(tmp).str();
  262. }
  263. #if defined(_WIN32)
  264. HINSTANCE h = LoadLibrary(name);
  265. if (!LoadSucceeded(h))
  266. {
  267. int errcode = GetLastError();
  268. StringBuffer errmsg;
  269. formatSystemError(errmsg, errcode);
  270. //Strip trailing newlines - makes output/errors messages cleaner
  271. unsigned len = errmsg.length();
  272. while (len)
  273. {
  274. char c = errmsg.charAt(len-1);
  275. if ((c != '\r') && (c != '\n'))
  276. break;
  277. len--;
  278. }
  279. errmsg.setLength(len);
  280. DBGLOG("Error loading %s: %d - %s", name, errcode, errmsg.str());
  281. if (raiseOnError)
  282. throw MakeStringException(0, "Error loading %s: %d - %s", name, errcode, errmsg.str());
  283. }
  284. #else
  285. HINSTANCE h = dlopen((char *)name, isGlobal ? RTLD_NOW|RTLD_GLOBAL : RTLD_NOW);
  286. if(h == NULL)
  287. {
  288. StringBuffer dlErrorMsg(dlerror());
  289. DBGLOG("Error loading %s: %s", name, dlErrorMsg.str());
  290. if (raiseOnError)
  291. throw MakeStringException(0, "Error loading %s: %s", name, dlErrorMsg.str());
  292. }
  293. #endif
  294. scope.setSoContext(h);
  295. #if defined(_WIN32)
  296. SetErrorMode(oldMode);
  297. #else
  298. // don't think anything to do here.
  299. #endif
  300. return h;
  301. }
  302. void FreeSharedObject(HINSTANCE h)
  303. {
  304. ExitModuleObjects(h);
  305. #if defined(_WIN32)
  306. FreeLibrary(h);
  307. #else
  308. dlclose(h);
  309. #endif
  310. }
  311. bool SharedObject::load(const char * dllName, bool isGlobal, bool raiseOnError)
  312. {
  313. unload();
  314. #ifdef _WIN32
  315. UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  316. if (dllName)
  317. {
  318. h=LoadSharedObject(dllName, isGlobal, raiseOnError);
  319. bRefCounted = true;
  320. }
  321. else
  322. {
  323. h=GetModuleHandle(NULL);
  324. bRefCounted = false;
  325. }
  326. SetErrorMode(oldMode);
  327. #else
  328. h=LoadSharedObject(dllName, isGlobal, raiseOnError);
  329. bRefCounted = true;
  330. #endif
  331. if (!LoadSucceeded(h))
  332. {
  333. h = 0;
  334. return false;
  335. }
  336. return true;
  337. }
  338. bool SharedObject::loadCurrentExecutable()
  339. {
  340. unload();
  341. #ifdef _WIN32
  342. h=GetModuleHandle(NULL);
  343. bRefCounted = false;
  344. #else
  345. h=dlopen(NULL, RTLD_NOW);
  346. bRefCounted = true;
  347. #endif
  348. return true;
  349. }
  350. void SharedObject::unload()
  351. {
  352. if (h && bRefCounted) FreeSharedObject(h);
  353. h = 0;
  354. }
  355. //-----------------------------------------------------------------------
  356. /*
  357. We use a 64 bit number for generating temporaries so that we are unlikely to get any
  358. clashes (being paranoid). This should mean if a temporary ID is allocated 1,000,000,000
  359. times a second, then we won't repeat until 400 years later - assuming the machine stays
  360. alive for that long.
  361. Using a 32 bit number we loop after about an hour if we allocated 1,000,000 a second -
  362. not an unreasonable estimate for the future.
  363. */
  364. static unique_id_t nextTemporaryId;
  365. StringBuffer & appendUniqueId(StringBuffer & target, unique_id_t value)
  366. {
  367. //Just generate a temporary name from the __int64 -
  368. //Don't care about the format, therfore use base 32 in reverse order.
  369. while (value)
  370. {
  371. unsigned next = ((unsigned)value) & 31;
  372. value = value >> 5;
  373. if (next < 10)
  374. target.append((char)(next+'0'));
  375. else
  376. target.append((char)(next+'A'-10));
  377. }
  378. return target;
  379. }
  380. unique_id_t getUniqueId()
  381. {
  382. return ++nextTemporaryId;
  383. }
  384. StringBuffer & getUniqueId(StringBuffer & target)
  385. {
  386. return appendUniqueId(target, ++nextTemporaryId);
  387. }
  388. void resetUniqueId()
  389. {
  390. nextTemporaryId = 0;
  391. }
  392. //-----------------------------------------------------------------------
  393. #define make_numtostr(VTYPE) \
  394. int numtostr(char *dst, VTYPE _value) \
  395. { \
  396. int c; \
  397. unsigned VTYPE value; \
  398. if (_value<0) \
  399. { \
  400. *(dst++) = '-'; \
  401. value = (unsigned VTYPE) -_value; \
  402. c = 1; \
  403. } \
  404. else \
  405. { \
  406. c = 0; \
  407. value = _value; \
  408. } \
  409. char temp[11], *end = temp+10; \
  410. char *tmp = end; \
  411. *tmp = '\0'; \
  412. \
  413. while (value>=10) \
  414. { \
  415. unsigned VTYPE next = value / 10; \
  416. *(--tmp) = ((char)(value-next*10))+'0'; \
  417. value = next; \
  418. } \
  419. *(--tmp) = ((char)value)+'0'; \
  420. \
  421. int diff = (int)(end-tmp); \
  422. int i=diff+1; \
  423. while (i--) *(dst++) = *(tmp++); \
  424. \
  425. return c+diff; \
  426. }
  427. #define make_unumtostr(VTYPE) \
  428. int numtostr(char *dst, unsigned VTYPE value) \
  429. { \
  430. char temp[11], *end = temp+10; \
  431. char *tmp = end; \
  432. *tmp = '\0'; \
  433. \
  434. while (value>=10) \
  435. { \
  436. unsigned VTYPE next = value / 10; \
  437. *(--tmp) = ((char)(value-next*10))+'0'; \
  438. value = next; \
  439. } \
  440. *(--tmp) = ((char)value)+'0'; \
  441. \
  442. int diff = (int)(end-tmp); \
  443. int i=diff+1; \
  444. while (i--) *(dst++) = *(tmp++); \
  445. \
  446. return diff; \
  447. }
  448. make_numtostr(char);
  449. make_numtostr(short);
  450. make_numtostr(int);
  451. make_numtostr(long);
  452. make_unumtostr(char);
  453. make_unumtostr(short);
  454. make_unumtostr(int);
  455. make_unumtostr(long);
  456. int numtostr(char *dst, __int64 _value)
  457. {
  458. int c;
  459. unsigned __int64 value;
  460. if (_value<0)
  461. {
  462. *(dst++) = '-';
  463. value = (unsigned __int64) -_value;
  464. c = 1;
  465. }
  466. else
  467. {
  468. value = _value;
  469. c = 0;
  470. }
  471. char temp[24], *end = temp+23, *tmp = end;
  472. *tmp = '\0';
  473. unsigned __int32 v3 = (unsigned __int32)(value / LLC(10000000000));
  474. unsigned __int64 vv = value - ((unsigned __int64)v3*LLC(10000000000));
  475. unsigned __int32 v2 = (unsigned __int32)(vv / 100000);
  476. unsigned __int32 v1 = (unsigned __int32) (vv - (v2 * 100000));
  477. unsigned __int32 next;
  478. while (v1>=10)
  479. {
  480. next = v1/10;
  481. *(--tmp) = ((char)(v1-next*10))+'0';
  482. v1 = next;
  483. }
  484. *(--tmp) = ((char)v1)+'0';
  485. if (v2)
  486. {
  487. char *d = end-5;
  488. while (d != tmp)
  489. *(--tmp) = '0';
  490. while (v2>=10)
  491. {
  492. next = v2/10;
  493. *(--tmp) = ((char)(v2-next*10))+'0';
  494. v2 = next;
  495. }
  496. *(--tmp) = ((char)v2)+'0';
  497. }
  498. if (v3)
  499. {
  500. char *d = end-10;
  501. while (d != tmp)
  502. *(--tmp) = '0';
  503. while (v3>=10)
  504. {
  505. next = v3/10;
  506. *(--tmp) = ((char)(v3-next*10))+'0';
  507. v3 = next;
  508. }
  509. *(--tmp) = ((char)v3)+'0';
  510. }
  511. int diff = (int)(end-tmp);
  512. #ifdef USEMEMCPY
  513. memcpy(dst, tmp, diff+1);
  514. #else
  515. int i=diff+1;
  516. while (i--)
  517. { *(dst++) = *(tmp++);
  518. }
  519. #endif
  520. return c+diff;
  521. }
  522. int numtostr(char *dst, unsigned __int64 value)
  523. {
  524. char temp[24], *end = temp+23, *tmp = end;
  525. *tmp = '\0';
  526. unsigned __int32 v3 = (unsigned __int32)(value / LLC(10000000000));
  527. unsigned __int64 vv = value - ((unsigned __int64)v3*LLC(10000000000));
  528. unsigned __int32 v2 = (unsigned __int32)(vv / 100000);
  529. unsigned __int32 v1 = (unsigned __int32) (vv - (v2 * 100000));
  530. unsigned __int32 next;
  531. while (v1>=10)
  532. {
  533. next = v1/10;
  534. *(--tmp) = ((char)(v1-next*10))+'0';
  535. v1 = next;
  536. }
  537. *(--tmp) = ((char)v1)+'0';
  538. if (v2)
  539. {
  540. char *d = end-5;
  541. while (d != tmp)
  542. *(--tmp) = '0';
  543. while (v2>=10)
  544. {
  545. next = v2/10;
  546. *(--tmp) = ((char)(v2-next*10))+'0';
  547. v2 = next;
  548. }
  549. *(--tmp) = ((char)v2)+'0';
  550. }
  551. if (v3)
  552. {
  553. char *d = end-10;
  554. while (d != tmp)
  555. *(--tmp) = '0';
  556. while (v3>=10)
  557. {
  558. next = v3/10;
  559. *(--tmp) = ((char)(v3-next*10))+'0';
  560. v3 = next;
  561. }
  562. *(--tmp) = ((char)v3)+'0';
  563. }
  564. int diff = (int)(end-tmp);
  565. #ifdef USEMEMCPY
  566. memcpy(dst, tmp, diff+1);
  567. #else
  568. int i=diff+1;
  569. while (i--)
  570. { *(dst++) = *(tmp++);
  571. }
  572. #endif
  573. return diff;
  574. }
  575. class CRandom: public CInterface, public IRandomNumberGenerator
  576. {
  577. // from Knuth if I remember correctly
  578. #define HISTORYSIZE 55
  579. #define HISTORYMAX (HISTORYSIZE-1)
  580. unsigned history[HISTORYSIZE];
  581. unsigned ptr;
  582. unsigned lower;
  583. public:
  584. IMPLEMENT_IINTERFACE;
  585. CRandom()
  586. {
  587. seed((unsigned)get_cycles_now());
  588. }
  589. void seed(unsigned su)
  590. {
  591. ptr = HISTORYMAX;
  592. lower = 23;
  593. double s = 91648253+su;
  594. double a = 1389796;
  595. double m = 2147483647;
  596. unsigned i;
  597. for (i=0;i<HISTORYSIZE;i++) { // just used for initialization
  598. s *= a;
  599. int q = (int)(s/m);
  600. s -= q*m;
  601. history[i] = (unsigned)s;
  602. }
  603. }
  604. unsigned next()
  605. {
  606. if (ptr==0) {
  607. ptr = HISTORYMAX;
  608. lower--;
  609. }
  610. else {
  611. ptr--;
  612. if (lower==0)
  613. lower = HISTORYMAX;
  614. else
  615. lower--;
  616. }
  617. unsigned ret = history[ptr]+history[lower];
  618. history[ptr] = ret;
  619. return ret;
  620. }
  621. } RandomMain;
  622. static CriticalSection gobalRandomSect;
  623. unsigned getRandom()
  624. {
  625. CriticalBlock block(gobalRandomSect); // this is a shame but it is not thread-safe without
  626. return RandomMain.next();
  627. }
  628. void seedRandom(unsigned seed)
  629. {
  630. CriticalBlock block(gobalRandomSect);
  631. RandomMain.seed(seed);
  632. }
  633. IRandomNumberGenerator *createRandomNumberGenerator()
  634. {
  635. return new CRandom();
  636. }
  637. #ifdef WIN32
  638. // This function has the same prototype for rand_r, but seed is ignored.
  639. jlib_decl int rand_r(unsigned int *seed)
  640. {
  641. CriticalBlock procedure(*protectedGeneratorCs);
  642. return (protectedGenerator->next() & RAND_R_MAX);
  643. }
  644. #if ((RAND_R_MAX & (RAND_R_MAX+1)) != 0)
  645. #error RAND_R_MAX expected to be 2^n-1
  646. #endif
  647. #endif
  648. class CShuffledIterator: public CInterface, implements IShuffledIterator
  649. {
  650. CRandom rand;
  651. unsigned *seq;
  652. unsigned idx;
  653. unsigned num;
  654. public:
  655. IMPLEMENT_IINTERFACE;
  656. CShuffledIterator(unsigned _num)
  657. {
  658. num = _num;
  659. idx = 0;
  660. seq = NULL;
  661. }
  662. ~CShuffledIterator()
  663. {
  664. delete [] seq;
  665. }
  666. bool first()
  667. {
  668. if (!seq)
  669. seq = new unsigned[num];
  670. idx = 0;
  671. if (!num)
  672. return false;
  673. unsigned i;
  674. for (i=0;i<num;i++)
  675. seq[i] = i;
  676. while (i>1) {
  677. unsigned j = rand.next()%i; // NB i is correct here
  678. i--;
  679. unsigned t = seq[j];
  680. seq[j] = seq[i];
  681. seq[i] = t;
  682. }
  683. return true;
  684. }
  685. bool isValid()
  686. {
  687. return idx<num;
  688. }
  689. bool next()
  690. {
  691. if (idx<num)
  692. idx++;
  693. return isValid();
  694. }
  695. unsigned get()
  696. {
  697. return lookup(idx);
  698. }
  699. unsigned lookup(unsigned i)
  700. {
  701. if (!seq)
  702. first();
  703. return seq[i%num];
  704. }
  705. void seed(unsigned su)
  706. {
  707. rand.seed(su);
  708. }
  709. };
  710. extern jlib_decl IShuffledIterator *createShuffledIterator(unsigned n)
  711. {
  712. return new CShuffledIterator(n);
  713. }
  714. /* Check whether a string is a valid C identifier. */
  715. bool isCIdentifier(const char* id)
  716. {
  717. if (id==NULL || *id==0)
  718. return false;
  719. if (!isalpha(*id) && *id!='_')
  720. return false;
  721. for (++id; *id != 0; id++)
  722. if (!isalnum(*id) && *id!='_')
  723. return false;
  724. return true;
  725. }
  726. //-------------------------------------------------------------------
  727. static const char BASE64_enc[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  728. "abcdefghijklmnopqrstuvwxyz"
  729. "0123456789+/";
  730. static const unsigned char BASE64_dec[256] =
  731. {
  732. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  733. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  734. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f,
  735. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  736. 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
  737. 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
  738. 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
  739. 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
  740. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  741. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  742. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  743. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  744. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  745. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  746. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  747. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  748. static const char pad = '=';
  749. //
  750. // Encode the input in a base64 format
  751. //
  752. // const void * data -> data to be encoded
  753. // long length -> length in bytes of this data
  754. // IIOStream &out -> Write the result into this stream
  755. //
  756. void JBASE64_Encode(const void *data, long length, IIOStream &out, bool addLineBreaks/*=true*/)
  757. {
  758. const unsigned char *in = static_cast<const unsigned char *>(data);
  759. unsigned char one;
  760. unsigned char two;
  761. unsigned char three;
  762. long i;
  763. for(i = 0; i < length && length - i >= 3;)
  764. {
  765. one = *(in + i++);
  766. two = *(in + i++);
  767. three = *(in + i++);
  768. // 0x30 -> 0011 0000 b
  769. // 0x3c -> 0011 1100 b
  770. // 0x3f -> 0011 1111 b
  771. //
  772. writeCharToStream(out, BASE64_enc[one >> 2]);
  773. writeCharToStream(out, BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  774. writeCharToStream(out, BASE64_enc[((two << 2) & 0x3c) | (three >> 6)]);
  775. writeCharToStream(out, BASE64_enc[three & 0x3f]);
  776. if(addLineBreaks && (i % 54 == 0))
  777. {
  778. writeCharToStream(out, '\n');
  779. }
  780. }
  781. switch(length - i)
  782. {
  783. case 2:
  784. one = *(in + i++);
  785. two = *(in + i++);
  786. writeCharToStream(out, BASE64_enc[one >> 2]);
  787. writeCharToStream(out, BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  788. writeCharToStream(out, BASE64_enc[(two << 2) & 0x3c]);
  789. writeCharToStream(out, pad);
  790. break;
  791. case 1:
  792. one = *(in + i++);
  793. writeCharToStream(out, BASE64_enc[one >> 2]);
  794. writeCharToStream(out, BASE64_enc[(one << 4) & 0x30]);
  795. writeCharToStream(out, pad);
  796. writeCharToStream(out, pad);
  797. break;
  798. }
  799. }
  800. // JCSMORE could have IIOStream StringBuffer adapter inplace of below.
  801. void JBASE64_Encode(const void *data, long length, StringBuffer &out, bool addLineBreaks/*=true*/)
  802. {
  803. const unsigned char *in = static_cast<const unsigned char *>(data);
  804. unsigned char one;
  805. unsigned char two;
  806. unsigned char three;
  807. long i;
  808. for(i = 0; i < length && length - i >= 3;)
  809. {
  810. one = *(in + i++);
  811. two = *(in + i++);
  812. three = *(in + i++);
  813. // 0x30 -> 0011 0000 b
  814. // 0x3c -> 0011 1100 b
  815. // 0x3f -> 0011 1111 b
  816. //
  817. out.append(BASE64_enc[one >> 2]);
  818. out.append(BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  819. out.append(BASE64_enc[((two << 2) & 0x3c) | (three >> 6)]);
  820. out.append(BASE64_enc[three & 0x3f]);
  821. if(addLineBreaks && (i % 54 == 0))
  822. {
  823. out.append('\n');
  824. }
  825. }
  826. switch(length - i)
  827. {
  828. case 2:
  829. one = *(in + i++);
  830. two = *(in + i++);
  831. out.append(BASE64_enc[one >> 2]);
  832. out.append(BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  833. out.append(BASE64_enc[(two << 2) & 0x3c]);
  834. out.append(pad);
  835. break;
  836. case 1:
  837. one = *(in + i++);
  838. out.append(BASE64_enc[one >> 2]);
  839. out.append(BASE64_enc[(one << 4) & 0x30]);
  840. out.append(pad);
  841. out.append(pad);
  842. break;
  843. }
  844. }
  845. //
  846. // Decode the input in a base64 format
  847. //
  848. // const char *in -> The string to be decoded
  849. // StringBuffer & out -> Decoded string here
  850. //
  851. StringBuffer &JBASE64_Decode(ISimpleReadStream &in, StringBuffer &out)
  852. {
  853. unsigned char c1, cs[3];
  854. unsigned char &c2 = *cs;
  855. unsigned char &c3 = *(cs+1);
  856. unsigned char &c4 = *(cs+2);
  857. unsigned char d1, d2, d3, d4;
  858. for(;;)
  859. {
  860. if (in.read(1, &c1))
  861. break;
  862. if (!c1)
  863. break;
  864. else if (!isspace(c1))
  865. {
  866. in.read(3, cs);
  867. d1 = BASE64_dec[c1];
  868. d2 = BASE64_dec[c2];
  869. d3 = BASE64_dec[c3];
  870. d4 = BASE64_dec[c4];
  871. out.append((char)((d1 << 2) | (d2 >> 4)));
  872. if(c3 == pad)
  873. break;
  874. out.append((char)((d2 << 4) | (d3 >> 2)));
  875. if(c4 == pad)
  876. break;
  877. out.append((char)((d3 << 6) | d4));
  878. }
  879. }
  880. return out;
  881. }
  882. MemoryBuffer &JBASE64_Decode(ISimpleReadStream &in, MemoryBuffer &out)
  883. {
  884. unsigned char c1, cs[3];
  885. unsigned char &c2 = *cs;
  886. unsigned char &c3 = *(cs+1);
  887. unsigned char &c4 = *(cs+2);
  888. unsigned char d1, d2, d3, d4;
  889. for(;;)
  890. {
  891. if (in.read(1, &c1) != 1)
  892. break;
  893. if (!c1)
  894. break;
  895. else if (!isspace(c1))
  896. {
  897. in.read(3, cs);
  898. d1 = BASE64_dec[c1];
  899. d2 = BASE64_dec[c2];
  900. d3 = BASE64_dec[c3];
  901. d4 = BASE64_dec[c4];
  902. out.append((char)((d1 << 2) | (d2 >> 4)));
  903. if(c3 == pad)
  904. break;
  905. out.append((char)((d2 << 4) | (d3 >> 2)));
  906. if(c4 == pad)
  907. break;
  908. out.append((char)((d3 << 6) | d4));
  909. }
  910. }
  911. return out;
  912. }
  913. StringBuffer &JBASE64_Decode(const char *incs, StringBuffer &out)
  914. {
  915. unsigned char c1, c2, c3, c4;
  916. unsigned char d1, d2, d3, d4;
  917. for(;;)
  918. {
  919. c1 = *incs++;
  920. if (!c1)
  921. break;
  922. else if (!isspace(c1))
  923. {
  924. c2 = *incs++;
  925. c3 = *incs++;
  926. c4 = *incs++;
  927. d1 = BASE64_dec[c1];
  928. d2 = BASE64_dec[c2];
  929. d3 = BASE64_dec[c3];
  930. d4 = BASE64_dec[c4];
  931. out.append((char)((d1 << 2) | (d2 >> 4)));
  932. if(c3 == pad)
  933. break;
  934. out.append((char)((d2 << 4) | (d3 >> 2)));
  935. if(c4 == pad)
  936. break;
  937. out.append((char)((d3 << 6) | d4));
  938. }
  939. }
  940. return out;
  941. }
  942. MemoryBuffer &JBASE64_Decode(const char *incs, MemoryBuffer &out)
  943. {
  944. unsigned char c1, c2, c3, c4;
  945. unsigned char d1, d2, d3, d4;
  946. for(;;)
  947. {
  948. c1 = *incs++;
  949. if (!c1)
  950. break;
  951. else if (!isspace(c1))
  952. {
  953. c2 = *incs++;
  954. c3 = *incs++;
  955. c4 = *incs++;
  956. d1 = BASE64_dec[c1];
  957. d2 = BASE64_dec[c2];
  958. d3 = BASE64_dec[c3];
  959. d4 = BASE64_dec[c4];
  960. out.append((char)((d1 << 2) | (d2 >> 4)));
  961. if(c3 == pad)
  962. break;
  963. out.append((char)((d2 << 4) | (d3 >> 2)));
  964. if(c4 == pad)
  965. break;
  966. out.append((char)((d3 << 6) | d4));
  967. }
  968. }
  969. return out;
  970. }
  971. static inline void encode5_32(const byte *in,StringBuffer &out)
  972. {
  973. // 5 bytes in 8 out
  974. static const char enc[33] =
  975. "abcdefghijklmnopqrstuvwxyz"
  976. "234567";
  977. out.append(enc[(in[0] >> 3)]);
  978. out.append(enc[((in[0] & 0x07) << 2) | (in[1] >> 6)]);
  979. out.append(enc[(in[1] >> 1) & 0x1f]);
  980. out.append(enc[((in[1] & 0x01) << 4) | (in[2] >> 4)]);
  981. out.append(enc[((in[2] & 0x0f) << 1) | (in[3] >> 7)]);
  982. out.append(enc[(in[3] >> 2) & 0x1f]);
  983. out.append(enc[((in[3] & 0x03) << 3) | (in[4] >> 5)]);
  984. out.append(enc[in[4] & 0x1f]);
  985. }
  986. void JBASE32_Encode(const char *in,StringBuffer &out)
  987. {
  988. size32_t len = (size32_t)strlen(in);
  989. while (len>=5) {
  990. encode5_32((const byte *)in,out);
  991. in += 5;
  992. len -= 5;
  993. }
  994. byte rest[5];
  995. memcpy(rest,in,len);
  996. memset(rest+len,0,5-len);
  997. encode5_32(rest,out);
  998. }
  999. static inline byte decode_32c(char c)
  1000. {
  1001. byte b = (byte)c;
  1002. if (b>=97) {
  1003. if (b<=122)
  1004. return b-97;
  1005. }
  1006. else if ((b>=50)&&(b<=55))
  1007. return b-24;
  1008. return 0;
  1009. }
  1010. void JBASE32_Decode(const char *bi,StringBuffer &out)
  1011. {
  1012. loop {
  1013. byte b[8];
  1014. for (unsigned i=0;i<8;i++)
  1015. b[i] = decode_32c(*(bi++));
  1016. byte o;
  1017. o = ((b[0] & 0x1f) << 3) | ((b[1] & 0x1c) >> 2);
  1018. if (!o) return;
  1019. out.append(o);
  1020. o = ((b[1] & 0x03) << 6) | ((b[2] & 0x1f) << 1) | ((b[3] & 0x10) >> 4);
  1021. if (!o) return;
  1022. out.append(o);
  1023. o = ((b[3] & 0x0f) << 4) | ((b[4] & 0x1e) >> 1);
  1024. if (!o) return;
  1025. out.append(o);
  1026. o = ((b[4] & 0x01) << 7) | ((b[5] & 0x1f) << 2) | ((b[6] & 0x18) >> 3);
  1027. if (!o) return;
  1028. out.append(o);
  1029. o = ((b[6] & 0x07) << 5) | (b[7] & 0x1f);
  1030. if (!o) return;
  1031. out.append(o);
  1032. }
  1033. }
  1034. void DelimToStringArray(const char *csl, StringArray &dst, const char * delim,bool deldup)
  1035. {
  1036. if (!csl)
  1037. return;
  1038. const char *s = csl;
  1039. char c;
  1040. if (!delim)
  1041. c = ',';
  1042. else if (*delim&&!delim[1])
  1043. c = *delim;
  1044. else
  1045. c = 0;
  1046. StringBuffer str;
  1047. unsigned dstlen=dst.ordinality();
  1048. loop {
  1049. while (isspace(*s))
  1050. s++;
  1051. if (!*s&&(dst.ordinality()==dstlen)) // this check is to allow trailing separators (e.g. ",," is 3 (NULL) entries) but not generate an entry for ""
  1052. break;
  1053. const char *e = s;
  1054. while (*e) {
  1055. if (c) {
  1056. if (*e==c)
  1057. break;
  1058. }
  1059. else if (strchr(delim,*e))
  1060. break;
  1061. e++;
  1062. }
  1063. str.clear().append((size32_t)(e-s),s).clip();
  1064. if (deldup) {
  1065. const char *s1 = str.str();
  1066. unsigned i;
  1067. for (i=0;i<dst.ordinality();i++)
  1068. if (strcmp(s1,dst.item(i))==0)
  1069. break;
  1070. if (i>=dst.ordinality())
  1071. dst.append(s1);
  1072. }
  1073. else
  1074. dst.append(str.str());
  1075. if (!*e)
  1076. break;
  1077. s = e+1;
  1078. }
  1079. }
  1080. void CslToStringArray(const char *csl, StringArray &dst,bool deldup)
  1081. {
  1082. DelimToStringArray(csl, dst, NULL , deldup);
  1083. }
  1084. #ifdef _WIN32
  1085. unsigned msTick() { return timeGetTime(); }
  1086. unsigned usTick()
  1087. {
  1088. static __int64 freq=0;
  1089. LARGE_INTEGER v;
  1090. if (!freq) {
  1091. if (QueryPerformanceFrequency(&v))
  1092. freq=v.QuadPart;
  1093. if (!freq)
  1094. return 0;
  1095. }
  1096. if (!QueryPerformanceCounter(&v))
  1097. return 0;
  1098. return (unsigned) ((v.QuadPart*1000000)/freq); // hope dividend doesn't overflow though it might
  1099. }
  1100. #else
  1101. #ifdef CLOCK_MONOTONIC
  1102. static bool use_gettimeofday=false;
  1103. unsigned msTick()
  1104. {
  1105. if (!use_gettimeofday) {
  1106. timespec tm;
  1107. if (clock_gettime(CLOCK_MONOTONIC, &tm)>=0)
  1108. return tm.tv_sec*1000+(tm.tv_nsec/1000000);
  1109. use_gettimeofday = true;
  1110. fprintf(stderr,"clock_gettime CLOCK_MONOTONIC returns %d",errno); // don't use PROGLOG
  1111. }
  1112. struct timeval tm;
  1113. gettimeofday(&tm,NULL);
  1114. return tm.tv_sec*1000+(tm.tv_usec/1000);
  1115. }
  1116. unsigned usTick()
  1117. {
  1118. if (!use_gettimeofday) {
  1119. timespec tm;
  1120. if (clock_gettime(CLOCK_MONOTONIC, &tm)>=0)
  1121. return tm.tv_sec*1000000+(tm.tv_nsec/1000);
  1122. use_gettimeofday = true;
  1123. fprintf(stderr,"clock_gettime CLOCK_MONOTONIC returns %d",errno); // don't use PROGLOG
  1124. }
  1125. struct timeval tm;
  1126. gettimeofday(&tm,NULL);
  1127. return tm.tv_sec*1000000+tm.tv_usec;
  1128. }
  1129. #else
  1130. #warning "clock_gettime(CLOCK_MONOTONIC) not supported"
  1131. unsigned msTick()
  1132. {
  1133. struct timeval tm;
  1134. gettimeofday(&tm,NULL);
  1135. return tm.tv_sec*1000+(tm.tv_usec/1000);
  1136. }
  1137. unsigned usTick()
  1138. {
  1139. struct timeval tm;
  1140. gettimeofday(&tm,NULL);
  1141. return tm.tv_sec*1000000+tm.tv_usec;
  1142. }
  1143. #endif
  1144. #endif
  1145. int make_daemon(bool printpid)
  1146. {
  1147. #ifndef _WIN32
  1148. pid_t pid, sid;
  1149. pid = fork();
  1150. if (pid < 0) {
  1151. PrintLog("fork failed\n");
  1152. return(EXIT_FAILURE);
  1153. }
  1154. if (pid > 0) {
  1155. if (printpid) {
  1156. int status;
  1157. waitpid(pid, &status, 0);
  1158. if (WEXITSTATUS(status)!=0)
  1159. return EXIT_FAILURE;
  1160. }
  1161. exit(EXIT_SUCCESS);
  1162. }
  1163. if ((sid = setsid()) < 0) {
  1164. PrintLog("error: set sid failed\n");
  1165. return(EXIT_FAILURE);
  1166. }
  1167. umask(0);
  1168. pid = fork(); // To prevent zombies
  1169. if (pid < 0) {
  1170. PrintLog("fork failed (2)\n");
  1171. return(EXIT_FAILURE);
  1172. }
  1173. if (pid > 0) {
  1174. if (printpid)
  1175. fprintf(stdout,"%d\n",pid);
  1176. exit(EXIT_SUCCESS);
  1177. }
  1178. freopen("/dev/null", "r", stdin);
  1179. freopen("/dev/null", "w", stdout);
  1180. freopen("/dev/null", "w", stderr);
  1181. return(EXIT_SUCCESS);
  1182. #else
  1183. return 0;
  1184. #endif
  1185. }
  1186. #ifndef _WIN32
  1187. static int exec(const char* _command)
  1188. {
  1189. const char* tok=" \t";
  1190. size32_t sz=16, count=0;
  1191. char* command = strdup(_command);
  1192. char **args=(char**)malloc(sz*sizeof(char*));
  1193. for(char *temp, *p=strtok_r(command,tok,&temp);;p=strtok_r(NULL,tok,&temp))
  1194. {
  1195. if(count>=sz)
  1196. args=(char**)realloc(args,(sz*=2)*sizeof(char*));
  1197. args[count++]=p;
  1198. if(!p)
  1199. break;
  1200. }
  1201. int ret=execv(*args,args);
  1202. free(args);
  1203. free(command);
  1204. return ret;
  1205. }
  1206. #endif
  1207. bool callExternalProgram(const char *progname, const StringBuffer &input, StringBuffer &output, StringArray *env_in)
  1208. {
  1209. #ifdef _WIN32
  1210. StringBuffer envp;
  1211. if (env_in)
  1212. {
  1213. ForEachItemIn(index, *env_in)
  1214. envp.append(env_in->item(index)).append('\0');
  1215. }
  1216. win32::ProcessPipe p(progname, envp.length() ? envp.str() : NULL);
  1217. p.Write(input.str(), input.length());
  1218. p.CloseWrite();
  1219. char buf[4096];
  1220. for(;;)
  1221. {
  1222. // Read program output
  1223. DWORD bread = (DWORD)p.Read(buf, sizeof(buf));
  1224. if(!bread)
  1225. {
  1226. break;
  1227. }
  1228. output.append(bread, buf);
  1229. }
  1230. #else
  1231. struct Pipe
  1232. {
  1233. Pipe()
  1234. {
  1235. p[0]=p[1]=-1;
  1236. if(pipe(p))
  1237. throw MakeStringException(-1,"Pipe create failed: %d",errno);
  1238. }
  1239. ~Pipe()
  1240. {
  1241. if(p[0]>=0)
  1242. close(p[0]);
  1243. if(p[1]>=0)
  1244. close(p[1]);
  1245. }
  1246. int Read(void *buf, size32_t nbyte)
  1247. {
  1248. return read(p[0],buf,nbyte);
  1249. }
  1250. int Write(const void *buf, size32_t nbyte)
  1251. {
  1252. return write(p[1],buf,nbyte);
  1253. }
  1254. void SetStdout()
  1255. {
  1256. if(p[1]!=STDOUT_FILENO)
  1257. {
  1258. if(dup2(p[1],STDOUT_FILENO)<0)
  1259. throw MakeStringException(-1,"stdout failed: %d",errno);
  1260. close(p[1]);
  1261. }
  1262. }
  1263. void SetStdin()
  1264. {
  1265. if(p[0]!=STDIN_FILENO)
  1266. {
  1267. if(dup2(p[0],STDIN_FILENO)<0)
  1268. throw MakeStringException(-1,"stdin failed: %d",errno);
  1269. close(p[0]);
  1270. }
  1271. }
  1272. void CloseRead()
  1273. {
  1274. close(p[0]);
  1275. p[0]=-1;
  1276. }
  1277. void CloseWrite()
  1278. {
  1279. close(p[1]);
  1280. p[1]=-1;
  1281. }
  1282. int p[2];
  1283. } pipe1, pipe2;
  1284. struct ChildProc
  1285. {
  1286. ChildProc()
  1287. {
  1288. if((pid=fork())<0)
  1289. throw MakeStringException(-1,"Fork failed: %d",errno);
  1290. }
  1291. ~ChildProc()
  1292. {
  1293. if(!inChild())
  1294. {
  1295. for(;;)
  1296. {
  1297. if(waitpid(pid,0,0)>=0)
  1298. break;
  1299. else if (errno==EINTR)
  1300. {
  1301. }
  1302. }
  1303. }
  1304. }
  1305. bool inChild()
  1306. {
  1307. return pid==0;
  1308. }
  1309. int pid;
  1310. } fchild;
  1311. if(fchild.inChild())
  1312. {
  1313. pipe1.CloseWrite();
  1314. pipe1.SetStdin();
  1315. pipe2.CloseRead();
  1316. pipe2.SetStdout();
  1317. if (env_in)
  1318. {
  1319. const char *cmd[] = { progname, (char *)0 };
  1320. const char *envp[256]={0};
  1321. ForEachItemIn(index, *env_in)
  1322. envp[index]=env_in->item(index);
  1323. if(execve(progname, (char * const *)cmd, (char * const *)envp)<0)
  1324. {
  1325. ERRLOG("Exec failed %s %d",progname,errno);
  1326. exit(EXIT_FAILURE);
  1327. }
  1328. }
  1329. else
  1330. {
  1331. if(exec(progname)<0)
  1332. {
  1333. ERRLOG("Exec failed %s %d",progname,errno);
  1334. exit(EXIT_FAILURE);
  1335. }
  1336. }
  1337. }
  1338. else
  1339. {
  1340. pipe1.CloseRead();
  1341. pipe2.CloseWrite();
  1342. const char* data=input.str();
  1343. size32_t count=input.length();
  1344. for(;count>0;)
  1345. {
  1346. size32_t w=pipe1.Write(data,count);
  1347. if(w<0 && errno!=EINTR)
  1348. throw MakeStringException(-1,"Pipe write failed: %d",errno);
  1349. data+=w;
  1350. count-=w;
  1351. }
  1352. pipe1.CloseWrite();
  1353. char buf[4096];
  1354. for(;;)
  1355. {
  1356. size32_t r=pipe2.Read(buf, sizeof(buf));
  1357. if(r>0)
  1358. {
  1359. output.append(r, buf);
  1360. }
  1361. else if(r==0)
  1362. break;
  1363. else if(errno!=EINTR)
  1364. throw MakeStringException(-1,"Pipe read failed: %d",errno);
  1365. }
  1366. }
  1367. #endif
  1368. return true;
  1369. }
  1370. //Calculate the greatest common divisor using Euclid's method
  1371. unsigned __int64 greatestCommonDivisor(unsigned __int64 left, unsigned __int64 right)
  1372. {
  1373. loop
  1374. {
  1375. if (left > right)
  1376. {
  1377. if (right == 0)
  1378. return left;
  1379. left = left % right;
  1380. }
  1381. else
  1382. {
  1383. if (left == 0)
  1384. return right;
  1385. right = right % left;
  1386. }
  1387. }
  1388. }
  1389. //In a separate module to stop optimizer removing the surrounding catch.
  1390. void doStackProbe()
  1391. {
  1392. byte local;
  1393. const volatile byte * x = (const byte *)&local;
  1394. x[-4096];
  1395. }
  1396. #ifdef _WIN32
  1397. DWORD dwTlsIndex = -1;
  1398. CriticalSection tlscrit;
  1399. void initThreadLocal(int len, void* val)
  1400. {
  1401. {
  1402. CriticalBlock b(tlscrit);
  1403. if(dwTlsIndex == -1)
  1404. {
  1405. if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
  1406. throw MakeStringException(-1, "TlsAlloc failed");
  1407. }
  1408. }
  1409. LPVOID lpvData;
  1410. lpvData = TlsGetValue(dwTlsIndex);
  1411. if (lpvData != 0)
  1412. LocalFree((HLOCAL) lpvData);
  1413. // Initialize the TLS index for this thread.
  1414. lpvData = (LPVOID) LocalAlloc(LPTR, len);
  1415. memcpy((char*)lpvData, val, len);
  1416. if (! TlsSetValue(dwTlsIndex, lpvData))
  1417. throw MakeStringException(-1, "TlsSetValue error");
  1418. }
  1419. void* getThreadLocalVal()
  1420. {
  1421. if(dwTlsIndex == -1)
  1422. return NULL;
  1423. return TlsGetValue(dwTlsIndex);
  1424. }
  1425. void clearThreadLocal()
  1426. {
  1427. if(dwTlsIndex == -1)
  1428. return;
  1429. LPVOID lpvData = TlsGetValue(dwTlsIndex);
  1430. if (lpvData != 0)
  1431. {
  1432. LocalFree((HLOCAL) lpvData);
  1433. if (! TlsSetValue(dwTlsIndex, NULL))
  1434. throw MakeStringException(-1, "TlsSetValue error");
  1435. }
  1436. }
  1437. #else
  1438. // Key for the thread-specific buffer
  1439. static pthread_key_t buffer_key;
  1440. // Once-only initialisation of the key
  1441. static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
  1442. // Free the thread-specific buffer
  1443. static void buffer_destroy(void * buf)
  1444. {
  1445. if(buf)
  1446. free(buf);
  1447. }
  1448. // Allocate the key
  1449. static void buffer_key_alloc()
  1450. {
  1451. pthread_key_create(&buffer_key, buffer_destroy);
  1452. DBGLOG("buffer_key=%d", buffer_key);
  1453. }
  1454. // Allocate the thread-specific buffer
  1455. void initThreadLocal(int len, void* val)
  1456. {
  1457. pthread_once(&buffer_key_once, buffer_key_alloc);
  1458. void* valbuf = malloc(len);
  1459. memcpy(valbuf, val, len);
  1460. pthread_setspecific(buffer_key, valbuf);
  1461. }
  1462. // Return the thread-specific buffer
  1463. void* getThreadLocalVal()
  1464. {
  1465. return (char *) pthread_getspecific(buffer_key);
  1466. }
  1467. void clearThreadLocal()
  1468. {
  1469. }
  1470. #endif
  1471. StringBuffer &expandMask(StringBuffer &buf, const char *mask, unsigned p, unsigned n)
  1472. {
  1473. const char *s=mask;
  1474. if (s)
  1475. while (*s) {
  1476. char next = *(s++);
  1477. if (next=='$') {
  1478. char pc = toupper(s[0]);
  1479. if (pc&&(s[1]=='$')) {
  1480. if (pc=='P') {
  1481. buf.append(p+1);
  1482. next = 0;
  1483. s+=2;
  1484. }
  1485. else if (pc=='N') {
  1486. buf.append(n);
  1487. next = 0;
  1488. s+=2;
  1489. }
  1490. }
  1491. }
  1492. if (next)
  1493. buf.append(next);
  1494. }
  1495. return buf;
  1496. }
  1497. static const char *findExtension(const char *fn)
  1498. {
  1499. if (!fn)
  1500. return NULL;
  1501. const char *ret = strchr(fn,'.');
  1502. if (ret) {
  1503. loop {
  1504. ret++;
  1505. const char *s = strchr(ret,'.');
  1506. if (!s)
  1507. break;
  1508. ret = s;
  1509. }
  1510. }
  1511. return ret;
  1512. }
  1513. bool matchesMask(const char *fn, const char *mask, unsigned p, unsigned n)
  1514. {
  1515. StringBuffer match;
  1516. expandMask(match,mask,p,n);
  1517. return (stricmp(fn,match.str())==0);
  1518. }
  1519. bool constructMask(StringAttr &attr, const char *fn, unsigned p, unsigned n)
  1520. {
  1521. StringBuffer buf;
  1522. const char *ext = findExtension(fn);
  1523. if (!ext)
  1524. return false;
  1525. buf.append((size32_t)(ext-fn),fn).append("_$P$_of_$N$");
  1526. if (matchesMask(fn,buf.str(),p,n)) {
  1527. attr.set(buf.str());
  1528. return true;
  1529. }
  1530. return false;
  1531. }
  1532. bool deduceMask(const char *fn, bool expandN, StringAttr &mask, unsigned &pret, unsigned &nret)
  1533. {
  1534. const char *e = findExtension(fn);
  1535. if (!e)
  1536. return false;
  1537. loop {
  1538. const char *s=e;
  1539. if (*s=='_') {
  1540. s++;
  1541. unsigned p = 0;
  1542. while (isdigit(*s))
  1543. p = p*10+*(s++)-'0';
  1544. if (p&&(memcmp(s,"_of_",4)==0)) {
  1545. s += 4;
  1546. pret = p-1;
  1547. p = 0;
  1548. while (isdigit(*s))
  1549. p = p*10+*(s++)-'0';
  1550. nret = p;
  1551. if (((*s==0)||(*s=='.'))&&(p>pret)) {
  1552. StringBuffer buf;
  1553. if (expandN)
  1554. buf.append((size32_t)(e-fn),fn).append("_$P$_of_").append(p);
  1555. else
  1556. buf.append((size32_t)(e-fn),fn).append("_$P$_of_$N$");
  1557. if (*s=='.')
  1558. buf.append(s);
  1559. mask.set(buf);
  1560. return true;
  1561. }
  1562. }
  1563. }
  1564. e--;
  1565. loop {
  1566. if (e==fn)
  1567. return false;
  1568. if (*(e-1)=='.')
  1569. break;
  1570. e--;
  1571. }
  1572. }
  1573. return false;
  1574. }
  1575. //==============================================================
  1576. #ifdef _WIN32
  1577. class CWindowsAuthenticatedUser: public CInterface, implements IAuthenticatedUser
  1578. {
  1579. StringAttr name;
  1580. HANDLE usertoken;
  1581. public:
  1582. IMPLEMENT_IINTERFACE;
  1583. CWindowsAuthenticatedUser()
  1584. {
  1585. usertoken = (HANDLE)-1;
  1586. }
  1587. ~CWindowsAuthenticatedUser()
  1588. {
  1589. if (usertoken != (HANDLE)-1)
  1590. CloseHandle(usertoken);
  1591. }
  1592. bool login(const char *user, const char *passwd)
  1593. {
  1594. name.clear();
  1595. if (usertoken != (HANDLE)-1)
  1596. CloseHandle(usertoken);
  1597. StringBuffer domain("");
  1598. const char *ut = strchr(user,'\\');
  1599. if (ut) {
  1600. domain.clear().append((size32_t)(ut-user),user);
  1601. user = ut+1;
  1602. }
  1603. BOOL res = LogonUser((LPTSTR)user,(LPTSTR)(domain.length()==0?NULL:domain.str()),(LPTSTR)passwd,LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,&usertoken);
  1604. if (res==0)
  1605. return false;
  1606. name.set(user);
  1607. return true;
  1608. }
  1609. void impersonate()
  1610. {
  1611. if (!ImpersonateLoggedOnUser(usertoken))
  1612. throw MakeOsException(GetLastError());
  1613. }
  1614. void revert()
  1615. {
  1616. RevertToSelf();
  1617. }
  1618. const char *username()
  1619. {
  1620. return name.get();
  1621. }
  1622. };
  1623. IAuthenticatedUser *createAuthenticatedUser() { return new CWindowsAuthenticatedUser; }
  1624. #elif defined(__linux__)
  1625. class CLinuxAuthenticatedUser: public CInterface, implements IAuthenticatedUser
  1626. {
  1627. StringAttr name;
  1628. uid_t uid;
  1629. gid_t gid;
  1630. uid_t saveuid;
  1631. gid_t savegid;
  1632. int saveegrplen;
  1633. gid_t *saveegrp;
  1634. public:
  1635. IMPLEMENT_IINTERFACE;
  1636. bool login(const char *user, const char *passwd)
  1637. {
  1638. name.clear();
  1639. const char *ut = strchr(user,'\\');
  1640. if (ut)
  1641. user = ut+1; // remove windows domain
  1642. struct passwd *pw;
  1643. char *epasswd;
  1644. if ((pw = getpwnam(user)) == NULL)
  1645. return false;
  1646. struct spwd *spwd = getspnam(user);
  1647. if (spwd)
  1648. epasswd = spwd->sp_pwdp;
  1649. else
  1650. epasswd = pw->pw_passwd;
  1651. if (!epasswd||!*epasswd)
  1652. return false;
  1653. if (strcmp(crypt(passwd,epasswd),epasswd)!=0)
  1654. return false;
  1655. uid = pw->pw_uid;
  1656. gid = pw->pw_gid;
  1657. name.set(pw->pw_name);
  1658. return true;
  1659. }
  1660. void impersonate()
  1661. {
  1662. saveuid = geteuid();
  1663. savegid = getegid();
  1664. setegid(gid);
  1665. seteuid(uid);
  1666. }
  1667. void revert()
  1668. {
  1669. seteuid(saveuid);
  1670. setegid(savegid);
  1671. }
  1672. const char *username()
  1673. {
  1674. return name.get();
  1675. }
  1676. };
  1677. IAuthenticatedUser *createAuthenticatedUser() { return new CLinuxAuthenticatedUser; }
  1678. #elif defined(__FreeBSD__) || defined (__APPLE__)
  1679. IAuthenticatedUser *createAuthenticatedUser() { UNIMPLEMENTED; }
  1680. #endif
  1681. extern jlib_decl void serializeAtom(MemoryBuffer & target, _ATOM name)
  1682. {
  1683. StringBuffer lower(name->str());
  1684. lower.toLowerCase();
  1685. serialize(target, lower.toCharArray());
  1686. }
  1687. extern jlib_decl _ATOM deserializeAtom(MemoryBuffer & source)
  1688. {
  1689. StringAttr text;
  1690. deserialize(source, text);
  1691. if (text)
  1692. return createAtom(text);
  1693. return NULL;
  1694. }
  1695. //==============================================================
  1696. static inline void encode3_64(byte *in,StringBuffer &out)
  1697. {
  1698. // 3 bytes in 4 out
  1699. static const char enc[65] =
  1700. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1701. "abcdefghijklmnopqrstuvwxyz"
  1702. "0123456789-_";
  1703. out.append(enc[in[0]>>2]);
  1704. out.append(enc[((in[0] << 4) & 0x30) | (in[1] >> 4)]);
  1705. out.append(enc[((in[1] << 2) & 0x3c) | (in[2] >> 6)]);
  1706. out.append(enc[in[2] & 0x3f]);
  1707. }
  1708. StringBuffer &genUUID(StringBuffer &out, bool nocase)
  1709. { // returns a 24 char UUID for nocase=false or 32 char for nocase=true
  1710. static NonReentrantSpinLock lock;
  1711. lock.enter();
  1712. // could be quicker using statics
  1713. static unsigned uuidbin[5] = {0,0,0,0,0};
  1714. if (uuidbin[0]==0) {
  1715. queryHostIP().getNetAddress(sizeof(uuidbin[0]),uuidbin);
  1716. uuidbin[1] = (unsigned)GetCurrentProcessId();
  1717. }
  1718. time_t t;
  1719. time(&t);
  1720. uuidbin[2] = (unsigned)t;
  1721. uuidbin[3] = msTick();
  1722. uuidbin[4]++;
  1723. byte *in = (byte *)uuidbin;
  1724. if (nocase) {
  1725. encode5_32(in,out);
  1726. encode5_32(in+5,out);
  1727. encode5_32(in+10,out);
  1728. encode5_32(in+15,out);
  1729. }
  1730. else {
  1731. encode3_64(in,out);
  1732. encode3_64(in+3,out);
  1733. encode3_64(in+6,out);
  1734. encode3_64(in+9,out);
  1735. byte tmp[3]; // drop two msb bytes from msec time
  1736. tmp[0] = in[12];
  1737. tmp[1] = in[13];
  1738. tmp[2] = in[16];
  1739. encode3_64(tmp,out);
  1740. encode3_64(in+17,out);
  1741. }
  1742. lock.leave();
  1743. return out;
  1744. }
  1745. //==============================================================
  1746. class jlib_decl CNameCountTable : public AtomRefTable
  1747. {
  1748. public:
  1749. CNameCountTable(bool _nocase=false) : AtomRefTable(_nocase) { }
  1750. StringBuffer &dump(StringBuffer &str)
  1751. {
  1752. SuperHashIteratorOf<HashKeyElement> iter(*this);
  1753. CriticalBlock b(crit);
  1754. ForEach (iter)
  1755. {
  1756. HashKeyElement &elem = iter.query();
  1757. str.append(elem.get()).append(", count = ").append(elem.queryReferences()).newline();
  1758. }
  1759. return str;
  1760. }
  1761. };
  1762. static CNameCountTable *namedCountHT;
  1763. MODULE_INIT(INIT_PRIORITY_SYSTEM)
  1764. {
  1765. namedCountHT = new CNameCountTable;
  1766. return true;
  1767. }
  1768. MODULE_EXIT()
  1769. {
  1770. delete namedCountHT;
  1771. }
  1772. NamedCount::NamedCount()
  1773. {
  1774. ht = NULL;
  1775. }
  1776. NamedCount::~NamedCount()
  1777. {
  1778. if (ht) namedCountHT->releaseKey(ht);
  1779. }
  1780. void NamedCount::set(const char *name)
  1781. {
  1782. ht = namedCountHT->queryCreate(name);
  1783. }
  1784. StringBuffer &dumpNamedCounts(StringBuffer &str)
  1785. {
  1786. return namedCountHT->dump(str);
  1787. }
  1788. //==============================================================
  1789. // class OffsetToString
  1790. OffsetToString::OffsetToString(offset_t offset)
  1791. {
  1792. #if defined(_MSC_VER) && !defined (_POSIX_) && (__STDC__ || _INTEGRAL_MAX_BITS < 64)
  1793. // fpos_t is defined as struct (see <stdio.h> in VC)
  1794. __int64 v = offset.lopart + (offset.hipart<<32);
  1795. m_buffer.append(v);
  1796. #else
  1797. m_buffer.append(offset);
  1798. #endif
  1799. }
  1800. /* Gentoo libc version omits these symbols which are directly */
  1801. /* referenced by some 3rd party libraries (sybase, Hasp). Until these */
  1802. /* libs get updated, provide linkable symbols within jlib for these... */
  1803. #if defined(__linux__) && (__GNUC__ >= 3)
  1804. const jlib_decl unsigned short int *__ctype_b = *__ctype_b_loc ();
  1805. const jlib_decl __int32_t *__ctype_tolower = *__ctype_tolower_loc();
  1806. const jlib_decl __int32_t *__ctype_toupper = *__ctype_toupper_loc();
  1807. // There seems to be some debate about whether these are needed
  1808. //#elif (__GNUC__ >= 3)
  1809. //const unsigned short int *__ctype_b = *__ctype_b_loc ();
  1810. //const unsigned int *__ctype_tolower = *__ctype_tolower_loc();
  1811. //const unsigned int *__ctype_toupper = *__ctype_toupper_loc();
  1812. #endif
  1813. //==============================================================
  1814. // URL Password, username handling
  1815. /*
  1816. From ftp://ftp.isi.edu/in-notes/rfc1738.txt:
  1817. http://<user>:<password>@<host>:<port>/<url-path>
  1818. Some or all of the parts "<user>:<password>@", ":<password>",
  1819. ":<port>", and "/<url-path>" may be excluded.
  1820. The user name (and password), if present, are followed by a
  1821. commercial at-sign "@". Within the user and password field, any ":",
  1822. "@", or "/" must be encoded.
  1823. */
  1824. jlib_decl StringBuffer& encodeUrlUseridPassword(StringBuffer& out, const char* in)
  1825. {
  1826. for (const char* p = in; *p; p++)
  1827. {
  1828. switch(*p)
  1829. {
  1830. // mentioned in rfc1738
  1831. case ':': out.append("%3A"); break;
  1832. case '@': out.append("%40"); break;
  1833. case '/': out.append("%2F"); break;
  1834. // these are not in the spec, but IE/Firefox has trouble if left un-encoded
  1835. case '%': out.append("%25"); break;
  1836. // these are not necessary: both IE and firefox handle them correctly
  1837. /*
  1838. case '&': out.append("%26"); break;
  1839. case ' ': out.append("%20"); break;
  1840. */
  1841. default: out.append(*p); break;
  1842. }
  1843. }
  1844. return out;
  1845. }
  1846. inline bool isHexChar(char c)
  1847. {
  1848. return (c>='0' && c<='9')
  1849. || (c>='A' && c<='F')
  1850. || (c>='a' && c<='f');
  1851. }
  1852. int hexValue(char c)
  1853. {
  1854. return (c>='0' && c<='9') ? c-'0' :
  1855. ((c>='A' && (c<='F') ? c-'A'+10 : c-'a'+10));
  1856. }
  1857. jlib_decl StringBuffer& decodeUrlUseridPassword(StringBuffer& out, const char* in)
  1858. {
  1859. for (const char* p = in; *p; p++)
  1860. {
  1861. if (*p=='%' && isHexChar(*(p+1)) && isHexChar(*(p+2)) )
  1862. {
  1863. char c1 = *(p+1), c2 = *(p+2);
  1864. int x = (hexValue(c1)<<4) + hexValue(c2);
  1865. out.appendf("%c",x);
  1866. p += 2;
  1867. }
  1868. else
  1869. out.appendf("%c",*p);
  1870. }
  1871. return out;
  1872. }
  1873. StringBuffer jlib_decl passwordInput(const char* prompt, StringBuffer& passwd)
  1874. {
  1875. #ifdef _WIN32
  1876. printf("%s", prompt);
  1877. size32_t entrylen = passwd.length();
  1878. loop {
  1879. char c = getch();
  1880. if (c == '\r')
  1881. break;
  1882. if (c == '\b') {
  1883. if (passwd.length()>entrylen) {
  1884. printf("\b \b");
  1885. passwd.setLength(passwd.length()-1);
  1886. }
  1887. }
  1888. else {
  1889. passwd.append(c);
  1890. printf("*");
  1891. }
  1892. }
  1893. printf("\n");
  1894. #else
  1895. // unfortuantely linux tty can't easily support using '*' hiding
  1896. sigset_t saved_signals;
  1897. sigset_t set_signals;
  1898. struct termios saved_term;
  1899. struct termios set_term;
  1900. FILE *term = fopen(_PATH_TTY, "w+");
  1901. if (!term)
  1902. term = stdin;
  1903. int termfd = fileno(term);
  1904. fprintf(stdout, "%s", prompt);
  1905. fflush(stdout);
  1906. sigemptyset(&set_signals);
  1907. sigaddset(&set_signals, SIGINT);
  1908. sigaddset(&set_signals, SIGTSTP);
  1909. sigprocmask(SIG_BLOCK, &set_signals, &saved_signals);
  1910. tcgetattr(termfd, &saved_term);
  1911. set_term = saved_term;
  1912. set_term.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL);
  1913. tcsetattr(termfd, TCSAFLUSH, &set_term);
  1914. char c = EOF;
  1915. int rd = ::read(termfd,&c,1);
  1916. while ((rd==1)&&(c!='\r')&&(c!='\n')&&(c!=EOF)) {
  1917. passwd.append(c);
  1918. rd = ::read(termfd,&c,1);
  1919. }
  1920. int err = (rd<0)?errno:0;
  1921. tcsetattr(termfd, TCSAFLUSH, &saved_term);
  1922. sigprocmask(SIG_SETMASK, &saved_signals, 0);
  1923. if (term!=stdin)
  1924. fclose(term);
  1925. if (err)
  1926. throw MakeOsException(err);
  1927. #endif
  1928. return passwd;
  1929. }
  1930. StringBuffer & fillConfigurationDirectoryEntry(const char *dir,const char *name, const char *component, const char *instance, StringBuffer &dirout)
  1931. {
  1932. while (*dir) {
  1933. if (*dir=='[') {
  1934. if (memicmp(dir+1,"NAME]",5)==0) {
  1935. dirout.append(name);
  1936. dir += 5;
  1937. }
  1938. else if (memicmp(dir+1,"COMPONENT]",10)==0) {
  1939. dirout.append(component);
  1940. dir += 10;
  1941. }
  1942. else if (memicmp(dir+1,"INST]",5)==0){
  1943. dirout.append(instance);
  1944. dir += 5;
  1945. }
  1946. else
  1947. dirout.append('[');
  1948. }
  1949. else
  1950. dirout.append(*dir);
  1951. dir++;
  1952. }
  1953. return dirout;
  1954. }
  1955. IPropertyTree *getHPCCenvironment(const char *confloc)
  1956. {
  1957. StringBuffer configFileSpec(confloc);
  1958. if (!configFileSpec.length())
  1959. #ifdef _WIN32
  1960. return NULL;
  1961. #else
  1962. configFileSpec.set(CONFIG_DIR).append(PATHSEPSTR).append("environment.conf");
  1963. #endif
  1964. Owned<IProperties> props = createProperties(configFileSpec.str());
  1965. if (props) {
  1966. StringBuffer envfile;
  1967. if (props->getProp("environment",envfile)&&envfile.length()) {
  1968. if (!isAbsolutePath(envfile.str())) {
  1969. StringBuffer tail(envfile);
  1970. splitDirTail(configFileSpec.str(),envfile.clear());
  1971. addPathSepChar(envfile).append(tail);
  1972. }
  1973. Owned<IFile> file = createIFile(envfile.str());
  1974. if (file) {
  1975. Owned<IFileIO> fileio = file->open(IFOread);
  1976. if (fileio)
  1977. return createPTree(*fileio);
  1978. }
  1979. }
  1980. }
  1981. return NULL;
  1982. }
  1983. static IPropertyTree *getOSSdirTree()
  1984. {
  1985. Owned<IPropertyTree> envtree = getHPCCenvironment();
  1986. if (envtree) {
  1987. IPropertyTree *ret = envtree->queryPropTree("Software/Directories");
  1988. if (ret)
  1989. return createPTreeFromIPT(ret);
  1990. }
  1991. return NULL;
  1992. }
  1993. bool getConfigurationDirectory(const IPropertyTree *dirtree,const char *category, const char *component,const char *instance, StringBuffer &dirout)
  1994. {
  1995. if (!dirtree)
  1996. dirtree = getOSSdirTree();
  1997. if (dirtree&&category&&*category) {
  1998. const char *name = dirtree->queryProp("@name");
  1999. if (name&&*name) {
  2000. StringBuffer q("Category[@name=\"");
  2001. q.append(category).append("\"]");
  2002. IPropertyTree *cat = dirtree->queryPropTree(q.str()); // assume only 1
  2003. if (cat) {
  2004. IPropertyTree *over = NULL;
  2005. if (instance&&*instance) {
  2006. q.clear().append("Override[@instance=\"").append(instance).append("\"]");
  2007. Owned<IPropertyTreeIterator> it1 = cat->getElements(q.str());
  2008. ForEach(*it1) {
  2009. IPropertyTree &o1 = it1->query();
  2010. if ((!component||!*component)) {
  2011. if (!over)
  2012. over = &o1;
  2013. }
  2014. else {
  2015. const char *comp = o1.queryProp("@component");
  2016. if (!comp||!*comp) {
  2017. if (!over)
  2018. over = &o1;
  2019. }
  2020. else if (strcmp(comp,component)==0) {
  2021. over = &o1;
  2022. break;
  2023. }
  2024. }
  2025. }
  2026. }
  2027. if (!over&&component&&*component) {
  2028. q.clear().append("Override[@component=\"").append(component).append("\"]");
  2029. Owned<IPropertyTreeIterator> it2 = cat->getElements(q.str());
  2030. ForEach(*it2) {
  2031. IPropertyTree &o2 = it2->query();
  2032. if ((!instance||!*instance)) {
  2033. over = &o2;
  2034. break;
  2035. }
  2036. else {
  2037. const char *inst = o2.queryProp("@instance");
  2038. if (!inst||!*inst) {
  2039. over = &o2;
  2040. break;
  2041. }
  2042. }
  2043. }
  2044. }
  2045. const char *dir = over?over->queryProp("@dir"):cat->queryProp("@dir");
  2046. if (dir&&*dir) {
  2047. fillConfigurationDirectoryEntry(dir,name,component,instance,dirout);
  2048. return true;
  2049. }
  2050. }
  2051. }
  2052. }
  2053. return false;
  2054. }
  2055. const char * matchConfigurationDirectoryEntry(const char *path,const char *mask,StringBuffer &name, StringBuffer &component, StringBuffer &instance)
  2056. {
  2057. // first check matches from (and set any values)
  2058. // only handles simple masks currently
  2059. StringBuffer var;
  2060. PointerArray val;
  2061. const char *m = mask;
  2062. const char *p = path;
  2063. loop {
  2064. char c = *m;
  2065. if (!c)
  2066. break;
  2067. m++;
  2068. StringBuffer *out=NULL;
  2069. if (c=='[') {
  2070. if (memicmp(m,"NAME]",5)==0) {
  2071. out = &name;
  2072. m += 5;
  2073. }
  2074. else if (memicmp(m,"COMPONENT]",10)==0) {
  2075. out = &component;
  2076. m += 10;
  2077. }
  2078. else if (memicmp(m,"INST]",5)==0) {
  2079. out = &instance;
  2080. m += 5;
  2081. }
  2082. }
  2083. if (out) {
  2084. StringBuffer mtail;
  2085. while (*m&&!isPathSepChar(*m)&&(*m!='['))
  2086. mtail.append(*(m++));
  2087. StringBuffer ptail;
  2088. while (*p&&!isPathSepChar(*p))
  2089. ptail.append(*(p++));
  2090. if (ptail.length()<mtail.length())
  2091. return NULL;
  2092. size32_t l = ptail.length()-mtail.length();
  2093. if (l&&(memcmp(ptail.str()+l,mtail.str(),mtail.length())!=0))
  2094. return NULL;
  2095. out->clear().append(l,ptail.str());
  2096. }
  2097. else if (c!=*(p++))
  2098. return NULL;
  2099. }
  2100. if (!*p)
  2101. return p;
  2102. if (isPathSepChar(*p))
  2103. return p+1;
  2104. return NULL;
  2105. }
  2106. bool replaceConfigurationDirectoryEntry(const char *path,const char *frommask,const char *tomask,StringBuffer &out)
  2107. {
  2108. StringBuffer name;
  2109. StringBuffer comp;
  2110. StringBuffer inst;
  2111. const char *tail = matchConfigurationDirectoryEntry(path,frommask,name,comp,inst);
  2112. if (!tail)
  2113. return false;
  2114. fillConfigurationDirectoryEntry(tomask,name,comp,inst,out);
  2115. if (*tail)
  2116. addPathSepChar(out).append(tail);
  2117. return true;
  2118. }
  2119. const char * queryCurrentProcessName()
  2120. {
  2121. static CriticalSection sect;
  2122. static StringAttr processName;
  2123. CriticalBlock block(sect);
  2124. if (processName.isEmpty())
  2125. {
  2126. #if defined(WIN32)
  2127. const char *cmdline = GetCommandLine();
  2128. if (!cmdline) return false;
  2129. StringArray argv;
  2130. DelimToStringArray(cmdline, argv, " ");
  2131. if (0 == argv.ordinality())
  2132. return "";
  2133. const char *processPath = argv.item(0);
  2134. #elif defined(__linux__)
  2135. char link[PATH_MAX];
  2136. ssize_t len = readlink("/proc/self/exe", link, PATH_MAX);
  2137. if (len == -1)
  2138. return "";
  2139. link[len] = '\0';
  2140. const char *processPath = link;
  2141. #else
  2142. const char *processPath = NULL;
  2143. return "";
  2144. #endif
  2145. if (!processPath)
  2146. return NULL;
  2147. StringBuffer path;
  2148. const char *tail = splitDirTail(processPath, path);
  2149. if (!tail)
  2150. return NULL;
  2151. processName.set(tail);
  2152. }
  2153. return processName.sget();
  2154. }
  2155. inline bool isOctChar(char c)
  2156. {
  2157. return (c>='0' && c<'8');
  2158. }
  2159. inline int octValue(char c)
  2160. {
  2161. return c-'0';
  2162. }
  2163. int parseCommandLine(const char * cmdline, MemoryBuffer &mb, const char** &argvout)
  2164. {
  2165. mb.append((char)0);
  2166. size32_t arg[256];
  2167. int argc = 0;
  2168. arg[0] = 0;
  2169. char quotechar = 0;
  2170. loop {
  2171. char c = *(cmdline++);
  2172. switch(c) {
  2173. case ' ':
  2174. case '\t':
  2175. if (quotechar)
  2176. break;
  2177. // fall through
  2178. case 0: {
  2179. if (arg[argc]) {
  2180. while (mb.length()>arg[argc]) {
  2181. size32_t l = mb.length()-1;
  2182. const byte * b = ((const byte *)mb.bufferBase())+l;
  2183. if ((*b!=' ')&&(*b!='\t'))
  2184. break;
  2185. mb.setLength(l);
  2186. }
  2187. if (mb.length()>arg[argc]) {
  2188. mb.append((char)0);
  2189. argc++;
  2190. }
  2191. if (c) {
  2192. if (argc==256)
  2193. throw MakeStringException(-1,"parseCommandLine: too many arguments");
  2194. arg[argc] = 0;
  2195. }
  2196. }
  2197. if (c)
  2198. continue;
  2199. argvout = (const char **)mb.reserve(argc*sizeof(const char *));
  2200. for (int i=0;i<argc;i++)
  2201. argvout[i] = arg[i]+(const char *)mb.bufferBase();
  2202. return argc;
  2203. }
  2204. break;
  2205. case '\'':
  2206. case '"':
  2207. if (c==quotechar) {
  2208. quotechar = 0;
  2209. continue;
  2210. }
  2211. if (quotechar)
  2212. break;
  2213. quotechar = c;
  2214. continue;
  2215. case '\\': {
  2216. if (*cmdline&&!quotechar) {
  2217. c = *(cmdline++);
  2218. switch (c) {
  2219. case 'a': c = '\a'; break;
  2220. case 'b': c = '\b'; break;
  2221. case 'f': c = '\f'; break;
  2222. case 'n': c = '\n'; break;
  2223. case 'r': c = '\r'; break;
  2224. case 't': c = '\t'; break;
  2225. case 'v': c = '\v'; break;
  2226. case 'x': case 'X': {
  2227. c = 0;
  2228. if (isHexChar(*cmdline)) {
  2229. c = hexValue(*(cmdline++));
  2230. if (isHexChar(*cmdline))
  2231. c = ((byte)c*16)+hexValue(*(cmdline++));
  2232. }
  2233. }
  2234. break;
  2235. case '0': case '1': case '2': case '3':
  2236. case '4': case '5': case '6': case '7': {
  2237. c = octValue(c);
  2238. if (isOctChar(*cmdline)) {
  2239. c = ((byte)c*8)+octValue(*(cmdline++));
  2240. if (isOctChar(*cmdline))
  2241. c = ((byte)c*8)+octValue(*(cmdline++));
  2242. }
  2243. }
  2244. break;
  2245. }
  2246. }
  2247. }
  2248. break;
  2249. }
  2250. if (!arg[argc])
  2251. arg[argc] = mb.length();
  2252. mb.append(c);
  2253. }
  2254. return 0;
  2255. }
  2256. //#define TESTURL
  2257. #ifdef TESTURL
  2258. static int doTests()
  2259. {
  2260. const char* ps[] = {
  2261. "ABCD", "@BCD", "%BCD","&BCD","A CD","A/CD", "A@@%%A","A&%/@"
  2262. };
  2263. const int N = sizeof(ps)/sizeof(char*);
  2264. for (int i=0; i<N; i++)
  2265. {
  2266. StringBuffer raw, encoded;
  2267. encodeUrlUseridPassword(encoded,ps[i]);
  2268. printf("Encoded: %s\n", encoded.str());
  2269. decodeUrlUseridPassword(raw,encoded);
  2270. if (strcmp(raw.str(),ps[i])!=0)
  2271. assert(!"decoding error");
  2272. }
  2273. return 0;
  2274. }
  2275. int gDummy = doTests();
  2276. #endif