PageRenderTime 28ms CodeModel.GetById 6ms RepoModel.GetById 1ms app.codeStats 0ms

/Client/psiclient/3rdParty/polipo/util.c

https://bitbucket.org/psiphon/psiphon-circumvention-system/
C | 808 lines | 688 code | 87 blank | 33 comment | 155 complexity | 6c108c45263570bf030a559150769115 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (c) 2003-2007 by Juliusz Chroboczek
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "polipo.h"
  20. /* Note that this is different from GNU's strndup(3). */
  21. char *
  22. strdup_n(const char *restrict buf, int n)
  23. {
  24. char *s;
  25. s = malloc(n + 1);
  26. if(s == NULL)
  27. return NULL;
  28. memcpy(s, buf, n);
  29. s[n] = '\0';
  30. return s;
  31. }
  32. int
  33. snnprintf(char *restrict buf, int n, int len, const char *format, ...)
  34. {
  35. va_list args;
  36. int rc;
  37. va_start(args, format);
  38. rc = snnvprintf(buf, n, len, format, args);
  39. va_end(args);
  40. return rc;
  41. }
  42. int
  43. snnvprintf(char *restrict buf, int n, int len, const char *format, va_list args)
  44. {
  45. int rc = -1;
  46. if(n < 0) return -2;
  47. if(n < len)
  48. rc = vsnprintf(buf + n, len - n, format, args);
  49. if(rc >= 0 && n + rc <= len)
  50. return n + rc;
  51. else
  52. return -1;
  53. }
  54. int
  55. snnprint_n(char *restrict buf, int n, int len, const char *s, int slen)
  56. {
  57. int i = 0;
  58. if(n < 0) return -2;
  59. while(i < slen && n < len)
  60. buf[n++] = s[i++];
  61. if(n < len)
  62. return n;
  63. else
  64. return -1;
  65. }
  66. int
  67. strcmp_n(const char *string, const char *buf, int n)
  68. {
  69. int i;
  70. i = 0;
  71. while(string[i] != '\0' && i < n) {
  72. if(string[i] < buf[i])
  73. return -1;
  74. else if(string[i] > buf[i])
  75. return 1;
  76. i++;
  77. }
  78. if(string[i] == '\0' || i == n)
  79. return 0;
  80. else if(i == n)
  81. return 1;
  82. else
  83. return -1;
  84. }
  85. int
  86. letter(char c)
  87. {
  88. if(c >= 'A' && c <= 'Z') return 1;
  89. if(c >= 'a' && c <= 'z') return 1;
  90. return 0;
  91. }
  92. int
  93. digit(char c)
  94. {
  95. if(c >= '0' && c <= '9')
  96. return 1;
  97. return 0;
  98. }
  99. char
  100. lwr(char a)
  101. {
  102. if(a >= 'A' && a <= 'Z')
  103. return a | 0x20;
  104. else
  105. return a;
  106. }
  107. char *
  108. lwrcpy(char *restrict dst, const char *restrict src, int n)
  109. {
  110. int i;
  111. for(i = 0; i < n; i++)
  112. dst[i] = lwr(src[i]);
  113. return dst;
  114. }
  115. int
  116. lwrcmp(const char *as, const char *bs, int n)
  117. {
  118. int i;
  119. for(i = 0; i < n; i++) {
  120. char a = lwr(as[i]), b = lwr(bs[i]);
  121. if(a < b)
  122. return -1;
  123. else if(a > b)
  124. return 1;
  125. }
  126. return 0;
  127. }
  128. int
  129. strcasecmp_n(const char *string, const char *buf, int n)
  130. {
  131. int i;
  132. i = 0;
  133. while(string[i] != '\0' && i < n) {
  134. char a = lwr(string[i]), b = lwr(buf[i]);
  135. if(a < b)
  136. return -1;
  137. else if(a > b)
  138. return 1;
  139. i++;
  140. }
  141. if(string[i] == '\0' && i == n)
  142. return 0;
  143. else if(i == n)
  144. return 1;
  145. else
  146. return -1;
  147. }
  148. int
  149. atoi_n(const char *restrict string, int n, int len, int *value_return)
  150. {
  151. int i = n;
  152. int val = 0;
  153. if(i >= len || !digit(string[i]))
  154. return -1;
  155. while(i < len && digit(string[i])) {
  156. val = val * 10 + (string[i] - '0');
  157. i++;
  158. }
  159. *value_return = val;
  160. return i;
  161. }
  162. int
  163. isWhitespace(const char *string)
  164. {
  165. while(*string != '\0') {
  166. if(*string == ' ' || *string == '\t')
  167. string++;
  168. else
  169. return 0;
  170. }
  171. return 1;
  172. }
  173. #ifndef HAVE_MEMRCHR
  174. void *
  175. memrchr(const void *s, int c, size_t n)
  176. {
  177. const unsigned char *ss = s;
  178. unsigned char cc = c;
  179. size_t i;
  180. for(i = n - 1; i >= 0; i--)
  181. if(ss[i] == cc)
  182. return (void*)(ss + i);
  183. return NULL;
  184. }
  185. #endif
  186. int
  187. h2i(char h)
  188. {
  189. if(h >= '0' && h <= '9')
  190. return h - '0';
  191. else if(h >= 'a' && h <= 'f')
  192. return h - 'a' + 10;
  193. else if(h >= 'A' && h <= 'F')
  194. return h - 'A' + 10;
  195. else
  196. return -1;
  197. }
  198. char
  199. i2h(int i)
  200. {
  201. if(i < 0 || i >= 16)
  202. return '?';
  203. if(i < 10)
  204. return i + '0';
  205. else
  206. return i - 10 + 'A';
  207. }
  208. /* floor(log2(x)) */
  209. int
  210. log2_floor(int x)
  211. {
  212. int i, j;
  213. assert(x > 0);
  214. i = 0;
  215. j = 1;
  216. while(2 * j <= x) {
  217. i++;
  218. j *= 2;
  219. }
  220. return i;
  221. }
  222. /* ceil(log2(x)) */
  223. int
  224. log2_ceil(int x)
  225. {
  226. int i, j;
  227. assert(x > 0);
  228. i = 0;
  229. j = 1;
  230. while(j < x) {
  231. i++;
  232. j *= 2;
  233. }
  234. return i;
  235. }
  236. #ifdef HAVE_ASPRINTF
  237. char *
  238. vsprintf_a(const char *f, va_list args)
  239. {
  240. char *r;
  241. int rc;
  242. rc = vasprintf(&r, f, args);
  243. if(rc < 0)
  244. return NULL;
  245. return r;
  246. }
  247. #else
  248. char*
  249. vsprintf_a(const char *f, va_list args)
  250. {
  251. int n, size;
  252. char buf[64];
  253. char *string;
  254. n = vsnprintf(buf, 64, f, args);
  255. if(n >= 0 && n < 64) {
  256. return strdup_n(buf, n);
  257. }
  258. if(n >= 64)
  259. size = n + 1;
  260. else
  261. size = 96;
  262. while(1) {
  263. string = malloc(size);
  264. if(!string)
  265. return NULL;
  266. n = vsnprintf(string, size, f, args);
  267. if(n >= 0 && n < size)
  268. return string;
  269. else if(n >= size)
  270. size = n + 1;
  271. else
  272. size = size * 3 / 2;
  273. free(string);
  274. if(size > 16 * 1024)
  275. return NULL;
  276. }
  277. /* NOTREACHED */
  278. }
  279. #endif
  280. char*
  281. sprintf_a(const char *f, ...)
  282. {
  283. char *s;
  284. va_list args;
  285. va_start(args, f);
  286. s = vsprintf_a(f, args);
  287. va_end(args);
  288. return s;
  289. }
  290. unsigned int
  291. hash(unsigned int seed, const void *restrict key, int key_size,
  292. unsigned int hash_size)
  293. {
  294. int i;
  295. unsigned int h;
  296. h = seed;
  297. for(i = 0; i < key_size; i++)
  298. h = (h << 5) + (h >> (hash_size - 5)) +
  299. ((unsigned char*)key)[i];
  300. return h & ((1 << hash_size) - 1);
  301. }
  302. char *
  303. pstrerror(int e)
  304. {
  305. char *s;
  306. static char buf[20];
  307. switch(e) {
  308. case EDOSHUTDOWN: s = "Immediate shutdown requested"; break;
  309. case EDOGRACEFUL: s = "Graceful shutdown requested"; break;
  310. case EDOTIMEOUT: s = "Timeout"; break;
  311. case ECLIENTRESET: s = "Connection reset by client"; break;
  312. case ESYNTAX: s = "Incorrect syntax"; break;
  313. case EREDIRECTOR: s = "Redirector error"; break;
  314. case EDNS_HOST_NOT_FOUND: s = "Host not found"; break;
  315. case EDNS_NO_ADDRESS: s = "No address"; break;
  316. case EDNS_NO_RECOVERY: s = "Permanent name server failure"; break;
  317. case EDNS_TRY_AGAIN: s = "Temporary name server failure"; break;
  318. case EDNS_INVALID: s = "Invalid reply from name server"; break;
  319. case EDNS_UNSUPPORTED: s = "Unsupported DNS reply"; break;
  320. case EDNS_FORMAT: s = "Invalid DNS query"; break;
  321. case EDNS_REFUSED: s = "DNS query refused by server"; break;
  322. case EDNS_CNAME_LOOP: s = "DNS CNAME loop"; break;
  323. #ifndef NO_SOCKS
  324. case ESOCKS_PROTOCOL: s = "SOCKS protocol error"; break;
  325. case ESOCKS_REJECT_FAIL: s = "SOCKS request rejected or failed"; break;
  326. case ESOCKS_REJECT_IDENTD: s = "SOCKS request rejected: "
  327. "server couldn't connect to identd";
  328. case ESOCKS_REJECT_UID_MISMATCH: s = "SOCKS request rejected: "
  329. "uid mismatch";
  330. break;
  331. case ESOCKS5_BASE: s = "SOCKS success"; break;
  332. case ESOCKS5_BASE + 1: s = "General SOCKS server failure"; break;
  333. case ESOCKS5_BASE + 2: s = "SOCKS connection not allowed"; break;
  334. case ESOCKS5_BASE + 3: s = "SOCKS error: network unreachable"; break;
  335. case ESOCKS5_BASE + 4: s = "SOCKS error: host unreachable"; break;
  336. case ESOCKS5_BASE + 5: s = "SOCKS error: connection refused"; break;
  337. case ESOCKS5_BASE + 6: s = "SOCKS error: TTL expired"; break;
  338. case ESOCKS5_BASE + 7: s = "SOCKS command not supported"; break;
  339. case ESOCKS5_BASE + 8: s = "SOCKS error: address type not supported";
  340. break;
  341. #endif
  342. case EUNKNOWN: s = "Unknown error"; break;
  343. default: s = NULL; break;
  344. }
  345. if(!s) s = strerror(e);
  346. #ifdef MINGW
  347. if(!s) {
  348. if(e >= WSABASEERR && e <= WSABASEERR + 2000) {
  349. /* This should be okay, as long as the caller discards the
  350. pointer before another error occurs. */
  351. snprintf(buf, 20, "Winsock error %d", e);
  352. s = buf;
  353. }
  354. }
  355. #endif
  356. if(!s) {
  357. snprintf(buf, 20, "Unknown error %d", e);
  358. s = buf;
  359. }
  360. return s;
  361. }
  362. /* Like mktime(3), but UTC rather than local time */
  363. #if defined(HAVE_TIMEGM)
  364. time_t
  365. mktime_gmt(struct tm *tm)
  366. {
  367. return timegm(tm);
  368. }
  369. #elif defined(HAVE_TM_GMTOFF)
  370. time_t
  371. mktime_gmt(struct tm *tm)
  372. {
  373. time_t t;
  374. struct tm *ltm;
  375. t = mktime(tm);
  376. if(t < 0)
  377. return -1;
  378. ltm = localtime(&t);
  379. if(ltm == NULL)
  380. return -1;
  381. return t + ltm->tm_gmtoff;
  382. }
  383. #elif defined(HAVE_TZSET)
  384. #ifdef HAVE_SETENV
  385. /* Taken from the Linux timegm(3) man page. */
  386. time_t
  387. mktime_gmt(struct tm *tm)
  388. {
  389. time_t t;
  390. char *tz;
  391. tz = getenv("TZ");
  392. setenv("TZ", "", 1);
  393. tzset();
  394. t = mktime(tm);
  395. if(tz)
  396. setenv("TZ", tz, 1);
  397. else
  398. unsetenv("TZ");
  399. tzset();
  400. return t;
  401. }
  402. #else
  403. time_t
  404. mktime_gmt(struct tm *tm)
  405. {
  406. time_t t;
  407. char *tz;
  408. static char *old_tz = NULL;
  409. tz = getenv("TZ");
  410. putenv("TZ=");
  411. tzset();
  412. t = mktime(tm);
  413. if(old_tz)
  414. free(old_tz);
  415. if(tz)
  416. old_tz = sprintf_a("TZ=%s", tz);
  417. else
  418. old_tz = strdup("TZ"); /* XXX - non-portable? */
  419. if(old_tz)
  420. putenv(old_tz);
  421. tzset();
  422. return t;
  423. }
  424. #endif
  425. #else
  426. #error no mktime_gmt implementation on this platform
  427. #endif
  428. AtomPtr
  429. expandTilde(AtomPtr filename)
  430. {
  431. char *buf;
  432. char *home;
  433. int len;
  434. AtomPtr ret;
  435. if(filename == NULL || filename->length < 1 ||
  436. filename->string[0] != '~' || filename->string[1] != '/')
  437. return filename;
  438. home = getenv("HOME");
  439. if(home == NULL) {
  440. return NULL;
  441. }
  442. len = strlen(home);
  443. buf = malloc(len + 1 + 1 + filename->length - 2);
  444. if(buf == NULL) {
  445. do_log(L_ERROR, "Could not allocate buffer.\n");
  446. return NULL;
  447. }
  448. memcpy(buf, home, len);
  449. if(buf[len - 1] != '/')
  450. buf[len++] = '/';
  451. memcpy(buf + len, filename->string + 2, filename->length - 2);
  452. len += filename->length - 2;
  453. ret = internAtomN(buf, len);
  454. free(buf);
  455. if(ret != NULL)
  456. releaseAtom(filename);
  457. return ret;
  458. }
  459. #ifdef HAVE_FORK
  460. void
  461. do_daemonise(int noclose)
  462. {
  463. int rc;
  464. fflush(stdout);
  465. fflush(stderr);
  466. rc = fork();
  467. if(rc < 0) {
  468. do_log_error(L_ERROR, errno, "Couldn't fork");
  469. exit(1);
  470. }
  471. if(rc > 0)
  472. exit(0);
  473. if(!noclose) {
  474. close(0);
  475. close(1);
  476. close(2);
  477. }
  478. rc = setsid();
  479. if(rc < 0) {
  480. do_log_error(L_ERROR, errno, "Couldn't create new session");
  481. exit(1);
  482. }
  483. }
  484. #else
  485. void
  486. do_daemonise(int noclose)
  487. {
  488. do_log(L_ERROR, "Cannot daemonise on this platform");
  489. exit(1);
  490. }
  491. #endif
  492. void
  493. writePid(char *pidfile)
  494. {
  495. int fd, n, rc;
  496. char buf[16];
  497. fd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
  498. if(fd < 0) {
  499. do_log_error(L_ERROR, errno,
  500. "Couldn't create pid file %s", pidfile);
  501. exit(1);
  502. }
  503. n = snprintf(buf, 16, "%ld\n", (long)getpid());
  504. if(n < 0 || n >= 16) {
  505. close(fd);
  506. unlink(pidfile);
  507. do_log(L_ERROR, "Couldn't format pid.\n");
  508. exit(1);
  509. }
  510. rc = write(fd, buf, n);
  511. if(rc != n) {
  512. close(fd);
  513. unlink(pidfile);
  514. do_log_error(L_ERROR, errno, "Couldn't write pid");
  515. exit(1);
  516. }
  517. close(fd);
  518. return;
  519. }
  520. static const char b64[64] =
  521. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  522. /* "/" replaced with "-" */
  523. static const char b64fss[64] =
  524. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
  525. int
  526. b64cpy(char *restrict dst, const char *restrict src, int n, int fss)
  527. {
  528. const char *b = fss ? b64fss: b64;
  529. int i, j;
  530. j = 0;
  531. for(i = 0; i < n; i += 3) {
  532. unsigned char a0, a1, a2;
  533. a0 = src[i];
  534. a1 = i < n - 1 ? src[i + 1] : 0;
  535. a2 = i < n - 2 ? src[i + 2] : 0;
  536. dst[j++] = b[(a0 >> 2) & 0x3F];
  537. dst[j++] = b[((a0 << 4) & 0x30) | ((a1 >> 4) & 0x0F)];
  538. if(i < n - 1)
  539. dst[j++] = b[((a1 << 2) & 0x3C) | ((a2 >> 6) & 0x03)];
  540. else
  541. dst[j++] = '=';
  542. if(i < n - 2)
  543. dst[j++] = b[a2 & 0x3F];
  544. else
  545. dst[j++] = '=';
  546. }
  547. return j;
  548. }
  549. int
  550. b64cmp(const char *restrict a, int an, const char *restrict b, int bn)
  551. {
  552. char *buf;
  553. int r;
  554. if(an % 4 != 0)
  555. return -1;
  556. if((bn + 2) / 3 != an / 4)
  557. return -1;
  558. buf = malloc(an);
  559. if(buf == NULL)
  560. return -1;
  561. b64cpy(buf, b, bn, 0);
  562. r = memcmp(buf, a, an);
  563. free(buf);
  564. return r;
  565. }
  566. IntListPtr
  567. makeIntList(int size)
  568. {
  569. IntListPtr list;
  570. if(size <= 0)
  571. size = 4;
  572. list = malloc(sizeof(IntListRec));
  573. if(list == NULL)
  574. return NULL;
  575. list->ranges = malloc(size * sizeof(IntRangeRec));
  576. if(list->ranges == NULL) {
  577. free(list);
  578. return NULL;
  579. }
  580. list->length = 0;
  581. list->size = size;
  582. return list;
  583. }
  584. void
  585. destroyIntList(IntListPtr list)
  586. {
  587. free(list->ranges);
  588. free(list);
  589. }
  590. int
  591. intListMember(int n, IntListPtr list)
  592. {
  593. int lo = 0, hi = list->length - 1;
  594. int mid;
  595. while(hi >= lo) {
  596. mid = (hi + lo) / 2;
  597. if(list->ranges[mid].from > n)
  598. hi = mid - 1;
  599. else if(list->ranges[mid].to < n)
  600. lo = mid + 1;
  601. else
  602. return 1;
  603. }
  604. return 0;
  605. }
  606. static int
  607. deleteRange(IntListPtr list, int i)
  608. {
  609. assert(list->length > i);
  610. if(list->length > i + 1)
  611. memmove(list->ranges + i, list->ranges + i + 1,
  612. (list->length - i - 1) * sizeof(IntRangeRec));
  613. list->length--;
  614. return 1;
  615. }
  616. static int
  617. insertRange(int from, int to, IntListPtr list, int i)
  618. {
  619. assert(i >= 0 && i <= list->length);
  620. assert(i == 0 || list->ranges[i - 1].to < from - 1);
  621. assert(i == list->length || list->ranges[i].from > to + 1);
  622. if(list->length >= list->size) {
  623. int newsize = list->size * 2 + 1;
  624. IntRangePtr newranges =
  625. realloc(list->ranges, newsize * sizeof(IntRangeRec));
  626. if(newranges == NULL)
  627. return -1;
  628. list->size = newsize;
  629. list->ranges = newranges;
  630. }
  631. if(i < list->length)
  632. memmove(list->ranges + i + 1, list->ranges + i,
  633. list->length - i);
  634. list->length++;
  635. list->ranges[i].from = from;
  636. list->ranges[i].to = to;
  637. return 1;
  638. }
  639. static int
  640. maybeMergeRanges(IntListPtr list, int i)
  641. {
  642. int rc;
  643. while(i > 0 && list->ranges[i].from <= list->ranges[i - 1].to + 1) {
  644. list->ranges[i - 1].from =
  645. MIN(list->ranges[i - 1].from, list->ranges[i].from);
  646. list->ranges[i - 1].to =
  647. MAX(list->ranges[i - 1].to, list->ranges[i].to);
  648. rc = deleteRange(list, i);
  649. if(rc < 0) return -1;
  650. i--;
  651. }
  652. while(i < list->length - 1 &&
  653. list->ranges[i].to >= list->ranges[i + 1].from - 1) {
  654. list->ranges[i + 1].from =
  655. MIN(list->ranges[i + 1].from, list->ranges[i].from);
  656. list->ranges[i - 1].to =
  657. MAX(list->ranges[i + 1].to, list->ranges[i].to);
  658. rc = deleteRange(list, i);
  659. if(rc < 0) return -1;
  660. }
  661. return 1;
  662. }
  663. int
  664. intListCons(int from, int to, IntListPtr list)
  665. {
  666. int i;
  667. /* Don't bother with the dichotomy. */
  668. for(i = 0; i < list->length; i++) {
  669. if(list->ranges[i].to >= from - 1)
  670. break;
  671. }
  672. if(i < list->length &&
  673. (from >= list->ranges[i].from - 1 || to <= list->ranges[i].to + 1)) {
  674. if(from <= list->ranges[i].from)
  675. list->ranges[i].from = from;
  676. if(to >= list->ranges[i].to)
  677. list->ranges[i].to = to;
  678. return maybeMergeRanges(list, i);
  679. }
  680. return insertRange(from, to, list, i);
  681. }
  682. /* Return the amount of physical memory on the box, -1 if unknown or
  683. over two gigs. */
  684. #if defined(__linux__)
  685. #include <sys/sysinfo.h>
  686. int
  687. physicalMemory()
  688. {
  689. int rc;
  690. struct sysinfo info;
  691. rc = sysinfo(&info);
  692. if(rc < 0)
  693. return -1;
  694. if(info.totalram <= 0x7fffffff / info.mem_unit)
  695. return (int)(info.totalram * info.mem_unit);
  696. return -1;
  697. }
  698. #elif defined(__FreeBSD__)
  699. #include <sys/sysctl.h>
  700. int
  701. physicalMemory()
  702. {
  703. int membytes;
  704. size_t len;
  705. int res;
  706. len = sizeof(membytes);
  707. res = sysctlbyname("hw.physmem", &membytes, &len, NULL, 0);
  708. if (res)
  709. return -1;
  710. return membytes;
  711. }
  712. #else
  713. int
  714. physicalMemory()
  715. {
  716. return -1;
  717. }
  718. #endif