jutil.cpp 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578
  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. if (!confloc)
  1958. #ifdef _WIN32
  1959. return NULL;
  1960. #else
  1961. {
  1962. StringBuffer EnvConfPath(CONFIG_DIR);
  1963. EnvConfPath.append(PATHSEPSTR).append("environment.conf");
  1964. confloc = EnvConfPath.str();
  1965. }
  1966. #endif
  1967. Owned<IProperties> props = createProperties(confloc);
  1968. if (props) {
  1969. StringBuffer envfile;
  1970. if (props->getProp("environment",envfile)&&envfile.length()) {
  1971. if (!isAbsolutePath(envfile.str())) {
  1972. StringBuffer tail(envfile);
  1973. splitDirTail(confloc,envfile.clear());
  1974. addPathSepChar(envfile).append(tail);
  1975. }
  1976. Owned<IFile> file = createIFile(envfile.str());
  1977. if (file) {
  1978. Owned<IFileIO> fileio = file->open(IFOread);
  1979. if (fileio)
  1980. return createPTree(*fileio);
  1981. }
  1982. }
  1983. }
  1984. return NULL;
  1985. }
  1986. static IPropertyTree *getOSSdirTree()
  1987. {
  1988. Owned<IPropertyTree> envtree = getHPCCenvironment();
  1989. if (envtree) {
  1990. IPropertyTree *ret = envtree->queryPropTree("Software/Directories");
  1991. if (ret)
  1992. return createPTreeFromIPT(ret);
  1993. }
  1994. return NULL;
  1995. }
  1996. bool getConfigurationDirectory(const IPropertyTree *dirtree,const char *category, const char *component,const char *instance, StringBuffer &dirout)
  1997. {
  1998. if (!dirtree)
  1999. dirtree = getOSSdirTree();
  2000. if (dirtree&&category&&*category) {
  2001. const char *name = dirtree->queryProp("@name");
  2002. if (name&&*name) {
  2003. StringBuffer q("Category[@name=\"");
  2004. q.append(category).append("\"]");
  2005. IPropertyTree *cat = dirtree->queryPropTree(q.str()); // assume only 1
  2006. if (cat) {
  2007. IPropertyTree *over = NULL;
  2008. if (instance&&*instance) {
  2009. q.clear().append("Override[@instance=\"").append(instance).append("\"]");
  2010. Owned<IPropertyTreeIterator> it1 = cat->getElements(q.str());
  2011. ForEach(*it1) {
  2012. IPropertyTree &o1 = it1->query();
  2013. if ((!component||!*component)) {
  2014. if (!over)
  2015. over = &o1;
  2016. }
  2017. else {
  2018. const char *comp = o1.queryProp("@component");
  2019. if (!comp||!*comp) {
  2020. if (!over)
  2021. over = &o1;
  2022. }
  2023. else if (strcmp(comp,component)==0) {
  2024. over = &o1;
  2025. break;
  2026. }
  2027. }
  2028. }
  2029. }
  2030. if (!over&&component&&*component) {
  2031. q.clear().append("Override[@component=\"").append(component).append("\"]");
  2032. Owned<IPropertyTreeIterator> it2 = cat->getElements(q.str());
  2033. ForEach(*it2) {
  2034. IPropertyTree &o2 = it2->query();
  2035. if ((!instance||!*instance)) {
  2036. over = &o2;
  2037. break;
  2038. }
  2039. else {
  2040. const char *inst = o2.queryProp("@instance");
  2041. if (!inst||!*inst) {
  2042. over = &o2;
  2043. break;
  2044. }
  2045. }
  2046. }
  2047. }
  2048. const char *dir = over?over->queryProp("@dir"):cat->queryProp("@dir");
  2049. if (dir&&*dir) {
  2050. fillConfigurationDirectoryEntry(dir,name,component,instance,dirout);
  2051. return true;
  2052. }
  2053. }
  2054. }
  2055. }
  2056. return false;
  2057. }
  2058. const char * matchConfigurationDirectoryEntry(const char *path,const char *mask,StringBuffer &name, StringBuffer &component, StringBuffer &instance)
  2059. {
  2060. // first check matches from (and set any values)
  2061. // only handles simple masks currently
  2062. StringBuffer var;
  2063. PointerArray val;
  2064. const char *m = mask;
  2065. const char *p = path;
  2066. loop {
  2067. char c = *m;
  2068. if (!c)
  2069. break;
  2070. m++;
  2071. StringBuffer *out=NULL;
  2072. if (c=='[') {
  2073. if (memicmp(m,"NAME]",5)==0) {
  2074. out = &name;
  2075. m += 5;
  2076. }
  2077. else if (memicmp(m,"COMPONENT]",10)==0) {
  2078. out = &component;
  2079. m += 10;
  2080. }
  2081. else if (memicmp(m,"INST]",5)==0) {
  2082. out = &instance;
  2083. m += 5;
  2084. }
  2085. }
  2086. if (out) {
  2087. StringBuffer mtail;
  2088. while (*m&&!isPathSepChar(*m)&&(*m!='['))
  2089. mtail.append(*(m++));
  2090. StringBuffer ptail;
  2091. while (*p&&!isPathSepChar(*p))
  2092. ptail.append(*(p++));
  2093. if (ptail.length()<mtail.length())
  2094. return NULL;
  2095. size32_t l = ptail.length()-mtail.length();
  2096. if (l&&(memcmp(ptail.str()+l,mtail.str(),mtail.length())!=0))
  2097. return NULL;
  2098. out->clear().append(l,ptail.str());
  2099. }
  2100. else if (c!=*(p++))
  2101. return NULL;
  2102. }
  2103. if (!*p)
  2104. return p;
  2105. if (isPathSepChar(*p))
  2106. return p+1;
  2107. return NULL;
  2108. }
  2109. bool replaceConfigurationDirectoryEntry(const char *path,const char *frommask,const char *tomask,StringBuffer &out)
  2110. {
  2111. StringBuffer name;
  2112. StringBuffer comp;
  2113. StringBuffer inst;
  2114. const char *tail = matchConfigurationDirectoryEntry(path,frommask,name,comp,inst);
  2115. if (!tail)
  2116. return false;
  2117. fillConfigurationDirectoryEntry(tomask,name,comp,inst,out);
  2118. if (*tail)
  2119. addPathSepChar(out).append(tail);
  2120. return true;
  2121. }
  2122. const char * queryCurrentProcessName()
  2123. {
  2124. static CriticalSection sect;
  2125. static StringAttr processName;
  2126. CriticalBlock block(sect);
  2127. if (processName.isEmpty())
  2128. {
  2129. #if defined(WIN32)
  2130. const char *cmdline = GetCommandLine();
  2131. if (!cmdline) return false;
  2132. StringArray argv;
  2133. DelimToStringArray(cmdline, argv, " ");
  2134. if (0 == argv.ordinality())
  2135. return "";
  2136. const char *processPath = argv.item(0);
  2137. #elif defined(__linux__)
  2138. char link[PATH_MAX];
  2139. ssize_t len = readlink("/proc/self/exe", link, PATH_MAX);
  2140. if (len == -1)
  2141. return "";
  2142. link[len] = '\0';
  2143. const char *processPath = link;
  2144. #else
  2145. const char *processPath = NULL;
  2146. return "";
  2147. #endif
  2148. if (!processPath)
  2149. return NULL;
  2150. StringBuffer path;
  2151. const char *tail = splitDirTail(processPath, path);
  2152. if (!tail)
  2153. return NULL;
  2154. processName.set(tail);
  2155. }
  2156. return processName.sget();
  2157. }
  2158. inline bool isOctChar(char c)
  2159. {
  2160. return (c>='0' && c<'8');
  2161. }
  2162. inline int octValue(char c)
  2163. {
  2164. return c-'0';
  2165. }
  2166. int parseCommandLine(const char * cmdline, MemoryBuffer &mb, const char** &argvout)
  2167. {
  2168. mb.append((char)0);
  2169. size32_t arg[256];
  2170. int argc = 0;
  2171. arg[0] = 0;
  2172. char quotechar = 0;
  2173. loop {
  2174. char c = *(cmdline++);
  2175. switch(c) {
  2176. case ' ':
  2177. case '\t':
  2178. if (quotechar)
  2179. break;
  2180. // fall through
  2181. case 0: {
  2182. if (arg[argc]) {
  2183. while (mb.length()>arg[argc]) {
  2184. size32_t l = mb.length()-1;
  2185. const byte * b = ((const byte *)mb.bufferBase())+l;
  2186. if ((*b!=' ')&&(*b!='\t'))
  2187. break;
  2188. mb.setLength(l);
  2189. }
  2190. if (mb.length()>arg[argc]) {
  2191. mb.append((char)0);
  2192. argc++;
  2193. }
  2194. if (c) {
  2195. if (argc==256)
  2196. throw MakeStringException(-1,"parseCommandLine: too many arguments");
  2197. arg[argc] = 0;
  2198. }
  2199. }
  2200. if (c)
  2201. continue;
  2202. argvout = (const char **)mb.reserve(argc*sizeof(const char *));
  2203. for (int i=0;i<argc;i++)
  2204. argvout[i] = arg[i]+(const char *)mb.bufferBase();
  2205. return argc;
  2206. }
  2207. break;
  2208. case '\'':
  2209. case '"':
  2210. if (c==quotechar) {
  2211. quotechar = 0;
  2212. continue;
  2213. }
  2214. if (quotechar)
  2215. break;
  2216. quotechar = c;
  2217. continue;
  2218. case '\\': {
  2219. if (*cmdline&&!quotechar) {
  2220. c = *(cmdline++);
  2221. switch (c) {
  2222. case 'a': c = '\a'; break;
  2223. case 'b': c = '\b'; break;
  2224. case 'f': c = '\f'; break;
  2225. case 'n': c = '\n'; break;
  2226. case 'r': c = '\r'; break;
  2227. case 't': c = '\t'; break;
  2228. case 'v': c = '\v'; break;
  2229. case 'x': case 'X': {
  2230. c = 0;
  2231. if (isHexChar(*cmdline)) {
  2232. c = hexValue(*(cmdline++));
  2233. if (isHexChar(*cmdline))
  2234. c = ((byte)c*16)+hexValue(*(cmdline++));
  2235. }
  2236. }
  2237. break;
  2238. case '0': case '1': case '2': case '3':
  2239. case '4': case '5': case '6': case '7': {
  2240. c = octValue(c);
  2241. if (isOctChar(*cmdline)) {
  2242. c = ((byte)c*8)+octValue(*(cmdline++));
  2243. if (isOctChar(*cmdline))
  2244. c = ((byte)c*8)+octValue(*(cmdline++));
  2245. }
  2246. }
  2247. break;
  2248. }
  2249. }
  2250. }
  2251. break;
  2252. }
  2253. if (!arg[argc])
  2254. arg[argc] = mb.length();
  2255. mb.append(c);
  2256. }
  2257. return 0;
  2258. }
  2259. //#define TESTURL
  2260. #ifdef TESTURL
  2261. static int doTests()
  2262. {
  2263. const char* ps[] = {
  2264. "ABCD", "@BCD", "%BCD","&BCD","A CD","A/CD", "A@@%%A","A&%/@"
  2265. };
  2266. const int N = sizeof(ps)/sizeof(char*);
  2267. for (int i=0; i<N; i++)
  2268. {
  2269. StringBuffer raw, encoded;
  2270. encodeUrlUseridPassword(encoded,ps[i]);
  2271. printf("Encoded: %s\n", encoded.str());
  2272. decodeUrlUseridPassword(raw,encoded);
  2273. if (strcmp(raw.str(),ps[i])!=0)
  2274. assert(!"decoding error");
  2275. }
  2276. return 0;
  2277. }
  2278. int gDummy = doTests();
  2279. #endif