jutil.cpp 67 KB

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