jutil.cpp 66 KB

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