util.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  1. /* Copyright 2003 Roger Dingledine */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "orconfig.h"
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #include "util.h"
  10. #include "log.h"
  11. #include "crypto.h"
  12. #include "../or/tree.h"
  13. #ifdef HAVE_UNAME
  14. #include <sys/utsname.h>
  15. #endif
  16. #ifdef HAVE_CTYPE_H
  17. #include <ctype.h>
  18. #endif
  19. #ifdef HAVE_NETINET_IN_H
  20. #include <netinet/in.h>
  21. #endif
  22. #ifdef HAVE_ARPA_INET_H
  23. #include <arpa/inet.h>
  24. #endif
  25. #ifdef HAVE_ERRNO_H
  26. #include <errno.h>
  27. #endif
  28. #ifdef HAVE_SYS_TYPES_H
  29. #include <sys/types.h> /* Must be included before sys/stat.h for Ultrix */
  30. #endif
  31. #ifdef HAVE_SYS_SOCKET_H
  32. #include <sys/socket.h>
  33. #endif
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #ifdef HAVE_SYS_STAT_H
  38. #include <sys/stat.h>
  39. #endif
  40. #ifdef HAVE_SYS_FCNTL_H
  41. #include <sys/fcntl.h>
  42. #endif
  43. #ifdef HAVE_PWD_H
  44. #include <pwd.h>
  45. #endif
  46. #ifdef HAVE_GRP_H
  47. #include <grp.h>
  48. #endif
  49. /* used by inet_addr, not defined on solaris anywhere!? */
  50. #ifndef INADDR_NONE
  51. #define INADDR_NONE ((unsigned long) -1)
  52. #endif
  53. /* in-line the strl functions */
  54. #ifndef HAVE_STRLCPY
  55. #include "strlcpy.c"
  56. #endif
  57. #ifndef HAVE_STRLCAT
  58. #include "strlcat.c"
  59. #endif
  60. /*
  61. * Memory wrappers
  62. */
  63. void *tor_malloc(size_t size) {
  64. void *result;
  65. /* Some libcs don't do the right thing on size==0. Override them. */
  66. if (size==0) {
  67. size=1;
  68. }
  69. result = malloc(size);
  70. if(!result) {
  71. log_fn(LOG_ERR, "Out of memory. Dying.");
  72. exit(1);
  73. }
  74. // memset(result,'X',size); /* deadbeef to encourage bugs */
  75. return result;
  76. }
  77. void *tor_malloc_zero(size_t size) {
  78. void *result = tor_malloc(size);
  79. memset(result, 0, size);
  80. return result;
  81. }
  82. void *tor_realloc(void *ptr, size_t size) {
  83. void *result;
  84. result = realloc(ptr, size);
  85. if (!result) {
  86. log_fn(LOG_ERR, "Out of memory. Dying.");
  87. exit(1);
  88. }
  89. return result;
  90. }
  91. char *tor_strdup(const char *s) {
  92. char *dup;
  93. assert(s);
  94. dup = strdup(s);
  95. if(!dup) {
  96. log_fn(LOG_ERR,"Out of memory. Dying.");
  97. exit(1);
  98. }
  99. return dup;
  100. }
  101. char *tor_strndup(const char *s, size_t n) {
  102. char *dup;
  103. assert(s);
  104. dup = tor_malloc(n+1);
  105. strncpy(dup, s, n);
  106. dup[n] = 0;
  107. return dup;
  108. }
  109. /* Convert s to lowercase. */
  110. void tor_strlower(char *s)
  111. {
  112. while (*s) {
  113. *s = tolower(*s);
  114. ++s;
  115. }
  116. }
  117. #ifndef UNALIGNED_INT_ACCESS_OK
  118. uint16_t get_uint16(char *cp)
  119. {
  120. uint16_t v;
  121. memcpy(&v,cp,2);
  122. return v;
  123. }
  124. uint32_t get_uint32(char *cp)
  125. {
  126. uint32_t v;
  127. memcpy(&v,cp,4);
  128. return v;
  129. }
  130. void set_uint16(char *cp, uint16_t v)
  131. {
  132. memcpy(cp,&v,2);
  133. }
  134. void set_uint32(char *cp, uint32_t v)
  135. {
  136. memcpy(cp,&v,4);
  137. }
  138. #endif
  139. void hex_encode(const char *from, int fromlen, char *to)
  140. {
  141. const unsigned char *fp = from;
  142. static const char TABLE[] = "0123456789abcdef";
  143. assert(from && fromlen>=0 && to);
  144. while (fromlen--) {
  145. *to++ = TABLE[*fp >> 4];
  146. *to++ = TABLE[*fp & 7];
  147. ++fp;
  148. }
  149. *to = '\0';
  150. }
  151. const char *hex_str(const char *from, int fromlen)
  152. {
  153. static char buf[65];
  154. if (fromlen>(sizeof(buf)-1)/2)
  155. fromlen = (sizeof(buf)-1)/2;
  156. hex_encode(from,fromlen,buf);
  157. return buf;
  158. }
  159. /*
  160. * A simple smartlist interface to make an unordered list of acceptable
  161. * nodes and then choose a random one.
  162. * smartlist_create() mallocs the list, _free() frees the list,
  163. * _add() adds an element, _remove() removes an element if it's there,
  164. * _choose() returns a random element.
  165. */
  166. #define SMARTLIST_DEFAULT_CAPACITY 32
  167. struct smartlist_t {
  168. void **list;
  169. int num_used;
  170. int capacity;
  171. };
  172. smartlist_t *smartlist_create() {
  173. smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
  174. sl->num_used = 0;
  175. sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
  176. sl->list = tor_malloc(sizeof(void *) * sl->capacity);
  177. return sl;
  178. }
  179. void smartlist_free(smartlist_t *sl) {
  180. free(sl->list);
  181. free(sl);
  182. }
  183. void smartlist_set_capacity(smartlist_t *sl, int n) {
  184. if (n<0)
  185. n = sl->num_used;
  186. if (sl->capacity != n && sl->num_used < n) {
  187. sl->capacity = n;
  188. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  189. }
  190. }
  191. /* Remove all elements from the list. */
  192. void smartlist_clear(smartlist_t *sl) {
  193. sl->num_used = 0;
  194. }
  195. void smartlist_truncate(smartlist_t *sl, int len)
  196. {
  197. assert(len <= sl->num_used);
  198. sl->num_used = len;
  199. }
  200. /* add element to the list */
  201. void smartlist_add(smartlist_t *sl, void *element) {
  202. if (sl->num_used >= sl->capacity) {
  203. sl->capacity *= 2;
  204. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  205. }
  206. sl->list[sl->num_used++] = element;
  207. }
  208. /* Add all elements from S2 to S1. */
  209. void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2)
  210. {
  211. SMARTLIST_FOREACH(s2, void *, element, smartlist_add(sl, element));
  212. }
  213. void smartlist_remove(smartlist_t *sl, void *element) {
  214. int i;
  215. if(element == NULL)
  216. return;
  217. for(i=0; i < sl->num_used; i++)
  218. if(sl->list[i] == element) {
  219. sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
  220. i--; /* so we process the new i'th element */
  221. }
  222. }
  223. int smartlist_isin(const smartlist_t *sl, void *element) {
  224. int i;
  225. for(i=0; i < sl->num_used; i++)
  226. if(sl->list[i] == element)
  227. return 1;
  228. return 0;
  229. }
  230. int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) {
  231. int i;
  232. for(i=0; i < sl2->num_used; i++)
  233. if(smartlist_isin(sl1, sl2->list[i]))
  234. return 1;
  235. return 0;
  236. }
  237. /* remove elements of sl1 that aren't in sl2 */
  238. void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) {
  239. int i;
  240. for(i=0; i < sl1->num_used; i++)
  241. if(!smartlist_isin(sl2, sl1->list[i])) {
  242. sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
  243. i--; /* so we process the new i'th element */
  244. }
  245. }
  246. /* remove all elements of sl2 from sl1 */
  247. void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) {
  248. int i;
  249. for(i=0; i < sl2->num_used; i++)
  250. smartlist_remove(sl1, sl2->list[i]);
  251. }
  252. void *smartlist_choose(const smartlist_t *sl) {
  253. if(sl->num_used)
  254. return sl->list[crypto_pseudo_rand_int(sl->num_used)];
  255. return NULL; /* no elements to choose from */
  256. }
  257. void *smartlist_get(const smartlist_t *sl, int idx)
  258. {
  259. assert(sl && idx>=0 && idx < sl->num_used);
  260. return sl->list[idx];
  261. }
  262. void *smartlist_set(smartlist_t *sl, int idx, void *val)
  263. {
  264. void *old;
  265. assert(sl && idx>=0 && idx < sl->num_used);
  266. old = sl->list[idx];
  267. sl->list[idx] = val;
  268. return old;
  269. }
  270. void *smartlist_del(smartlist_t *sl, int idx)
  271. {
  272. void *old;
  273. assert(sl && idx>=0 && idx < sl->num_used);
  274. old = sl->list[idx];
  275. sl->list[idx] = sl->list[--sl->num_used];
  276. return old;
  277. }
  278. void *smartlist_del_keeporder(smartlist_t *sl, int idx)
  279. {
  280. void *old;
  281. assert(sl && idx>=0 && idx < sl->num_used);
  282. old = sl->list[idx];
  283. --sl->num_used;
  284. if (idx < sl->num_used)
  285. memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
  286. return old;
  287. }
  288. int smartlist_len(const smartlist_t *sl)
  289. {
  290. return sl->num_used;
  291. }
  292. void smartlist_insert(smartlist_t *sl, int idx, void *val)
  293. {
  294. assert(sl && idx >= 0 && idx <= sl->num_used);
  295. if (idx == sl->num_used) {
  296. smartlist_add(sl, val);
  297. } else {
  298. /* Ensure sufficient capacity */
  299. if (sl->num_used >= sl->capacity) {
  300. sl->capacity *= 2;
  301. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  302. }
  303. /* Move other elements away */
  304. if (idx < sl->num_used)
  305. memmove(sl->list + idx + 1, sl->list + idx,
  306. sizeof(void*)*(sl->num_used-idx));
  307. sl->num_used++;
  308. sl->list[idx] = val;
  309. }
  310. }
  311. /*
  312. * Splay-tree implementation of string-to-void* map
  313. */
  314. struct strmap_entry_t {
  315. SPLAY_ENTRY(strmap_entry_t) node;
  316. char *key;
  317. void *val;
  318. };
  319. struct strmap_t {
  320. SPLAY_HEAD(strmap_tree, strmap_entry_t) head;
  321. };
  322. static int compare_strmap_entries(struct strmap_entry_t *a,
  323. struct strmap_entry_t *b)
  324. {
  325. return strcmp(a->key, b->key);
  326. }
  327. SPLAY_PROTOTYPE(strmap_tree, strmap_entry_t, node, compare_strmap_entries);
  328. SPLAY_GENERATE(strmap_tree, strmap_entry_t, node, compare_strmap_entries);
  329. /* Create a new empty map from strings to void*'s.
  330. */
  331. strmap_t* strmap_new(void)
  332. {
  333. strmap_t *result;
  334. result = tor_malloc(sizeof(strmap_t));
  335. SPLAY_INIT(&result->head);
  336. return result;
  337. }
  338. /* Set the current value for <key> with <val>. Returns the previous
  339. * value for <key> if one was set, or NULL if one was not.
  340. *
  341. * This function makes a copy of 'key' if necessary, but not of 'val'.
  342. */
  343. void* strmap_set(strmap_t *map, const char *key, void *val)
  344. {
  345. strmap_entry_t *resolve;
  346. strmap_entry_t search;
  347. void *oldval;
  348. assert(map && key && val);
  349. search.key = (char*)key;
  350. resolve = SPLAY_FIND(strmap_tree, &map->head, &search);
  351. if (resolve) {
  352. oldval = resolve->val;
  353. resolve->val = val;
  354. return oldval;
  355. } else {
  356. resolve = tor_malloc_zero(sizeof(strmap_entry_t));
  357. resolve->key = tor_strdup(key);
  358. resolve->val = val;
  359. SPLAY_INSERT(strmap_tree, &map->head, resolve);
  360. return NULL;
  361. }
  362. }
  363. /* Return the current value associated with <key>, or NULL if no
  364. * value is set.
  365. */
  366. void* strmap_get(strmap_t *map, const char *key)
  367. {
  368. strmap_entry_t *resolve;
  369. strmap_entry_t search;
  370. assert(map && key);
  371. search.key = (char*)key;
  372. resolve = SPLAY_FIND(strmap_tree, &map->head, &search);
  373. if (resolve) {
  374. return resolve->val;
  375. } else {
  376. return NULL;
  377. }
  378. }
  379. /* Remove the value currently associated with <key> from the map.
  380. * Return the value if one was set, or NULL if there was no entry for
  381. * <key>.
  382. *
  383. * Note: you must free any storage associated with the returned value.
  384. */
  385. void* strmap_remove(strmap_t *map, const char *key)
  386. {
  387. strmap_entry_t *resolve;
  388. strmap_entry_t search;
  389. void *oldval;
  390. assert(map && key);
  391. search.key = (char*)key;
  392. resolve = SPLAY_FIND(strmap_tree, &map->head, &search);
  393. if (resolve) {
  394. oldval = resolve->val;
  395. SPLAY_REMOVE(strmap_tree, &map->head, resolve);
  396. tor_free(resolve->key);
  397. tor_free(resolve);
  398. return oldval;
  399. } else {
  400. return NULL;
  401. }
  402. }
  403. /* Same as strmap_set, but first converts <key> to lowercase. */
  404. void* strmap_set_lc(strmap_t *map, const char *key, void *val)
  405. {
  406. /* We could be a little faster by using strcasecmp instead, and a separate
  407. * type, but I don't think it matters. */
  408. void *v;
  409. char *lc_key = tor_strdup(key);
  410. tor_strlower(lc_key);
  411. v = strmap_set(map,lc_key,val);
  412. tor_free(lc_key);
  413. return v;
  414. }
  415. /* Same as strmap_get, but first converts <key> to lowercase. */
  416. void* strmap_get_lc(strmap_t *map, const char *key)
  417. {
  418. void *v;
  419. char *lc_key = tor_strdup(key);
  420. tor_strlower(lc_key);
  421. v = strmap_get(map,lc_key);
  422. tor_free(lc_key);
  423. return v;
  424. }
  425. /* Same as strmap_remove, but first converts <key> to lowercase */
  426. void* strmap_remove_lc(strmap_t *map, const char *key)
  427. {
  428. void *v;
  429. char *lc_key = tor_strdup(key);
  430. tor_strlower(lc_key);
  431. v = strmap_remove(map,lc_key);
  432. tor_free(lc_key);
  433. return v;
  434. }
  435. /* Invoke fn() on every entry of the map, in order. For every entry,
  436. * fn() is invoked with that entry's key, that entry's value, and the
  437. * value of <data> supplied to strmap_foreach. fn() must return a new
  438. * (possibly unmodified) value for each entry: if fn() returns NULL, the
  439. * entry is removed.
  440. *
  441. * Example:
  442. * static void* upcase_and_remove_empty_vals(const char *key, void *val,
  443. * void* data) {
  444. * char *cp = (char*)val;
  445. * if (!*cp) { // val is an empty string.
  446. * free(val);
  447. * return NULL;
  448. * } else {
  449. * for (; *cp; cp++)
  450. * *cp = toupper(*cp);
  451. * }
  452. * return val;
  453. * }
  454. * }
  455. *
  456. * ...
  457. *
  458. * strmap_foreach(map, upcase_and_remove_empty_vals, NULL);
  459. */
  460. void strmap_foreach(strmap_t *map,
  461. void* (*fn)(const char *key, void *val, void *data),
  462. void *data)
  463. {
  464. strmap_entry_t *ptr, *next;
  465. assert(map && fn);
  466. for (ptr = SPLAY_MIN(strmap_tree, &map->head); ptr != NULL; ptr = next) {
  467. /* This remove-in-place usage is specifically blessed in tree(3). */
  468. next = SPLAY_NEXT(strmap_tree, &map->head, ptr);
  469. ptr->val = fn(ptr->key, ptr->val, data);
  470. if (!ptr->val) {
  471. SPLAY_REMOVE(strmap_tree, &map->head, ptr);
  472. tor_free(ptr->key);
  473. tor_free(ptr);
  474. }
  475. }
  476. }
  477. /* return an 'iterator' pointer to the front of a map.
  478. *
  479. * Iterator example:
  480. *
  481. * // uppercase values in "map", removing empty values.
  482. *
  483. * strmap_iter_t *iter;
  484. * const char *key;
  485. * void *val;
  486. * char *cp;
  487. *
  488. * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) {
  489. * strmap_iter_get(iter, &key, &val);
  490. * cp = (char*)val;
  491. * if (!*cp) {
  492. * iter = strmap_iter_next_rmv(iter);
  493. * free(val);
  494. * } else {
  495. * for(;*cp;cp++) *cp = toupper(*cp);
  496. * iter = strmap_iter_next(iter);
  497. * }
  498. * }
  499. *
  500. */
  501. strmap_iter_t *strmap_iter_init(strmap_t *map)
  502. {
  503. assert(map);
  504. return SPLAY_MIN(strmap_tree, &map->head);
  505. }
  506. /* Advance the iterator 'iter' for map a single step to the next entry.
  507. */
  508. strmap_iter_t *strmap_iter_next(strmap_t *map, strmap_iter_t *iter)
  509. {
  510. assert(map && iter);
  511. return SPLAY_NEXT(strmap_tree, &map->head, iter);
  512. }
  513. /* Advance the iterator 'iter' a single step to the next entry, removing
  514. * the current entry.
  515. */
  516. strmap_iter_t *strmap_iter_next_rmv(strmap_t *map, strmap_iter_t *iter)
  517. {
  518. strmap_iter_t *next;
  519. assert(map && iter);
  520. next = SPLAY_NEXT(strmap_tree, &map->head, iter);
  521. SPLAY_REMOVE(strmap_tree, &map->head, iter);
  522. tor_free(iter->key);
  523. tor_free(iter);
  524. return next;
  525. }
  526. /* Set *keyp and *valp to the current entry pointed to by iter.
  527. */
  528. void strmap_iter_get(strmap_iter_t *iter, const char **keyp, void **valp)
  529. {
  530. assert(iter && keyp && valp);
  531. *keyp = iter->key;
  532. *valp = iter->val;
  533. }
  534. /* Return true iff iter has advanced past the last entry of map.
  535. */
  536. int strmap_iter_done(strmap_iter_t *iter)
  537. {
  538. return iter == NULL;
  539. }
  540. /* Remove all entries from <map>, and deallocate storage for those entries.
  541. * If free_val is provided, it is invoked on every value in <map>.
  542. */
  543. void strmap_free(strmap_t *map, void (*free_val)(void*))
  544. {
  545. strmap_entry_t *ent, *next;
  546. for (ent = SPLAY_MIN(strmap_tree, &map->head); ent != NULL; ent = next) {
  547. next = SPLAY_NEXT(strmap_tree, &map->head, ent);
  548. SPLAY_REMOVE(strmap_tree, &map->head, ent);
  549. tor_free(ent->key);
  550. if (free_val)
  551. tor_free(ent->val);
  552. }
  553. assert(SPLAY_EMPTY(&map->head));
  554. tor_free(map);
  555. }
  556. /*
  557. * String manipulation
  558. */
  559. /* return the first char of s that is not whitespace and not a comment */
  560. const char *eat_whitespace(const char *s) {
  561. assert(s);
  562. while(isspace((int)*s) || *s == '#') {
  563. while(isspace((int)*s))
  564. s++;
  565. if(*s == '#') { /* read to a \n or \0 */
  566. while(*s && *s != '\n')
  567. s++;
  568. if(!*s)
  569. return s;
  570. }
  571. }
  572. return s;
  573. }
  574. const char *eat_whitespace_no_nl(const char *s) {
  575. while(*s == ' ' || *s == '\t')
  576. ++s;
  577. return s;
  578. }
  579. /* return the first char of s that is whitespace or '#' or '\0 */
  580. const char *find_whitespace(const char *s) {
  581. assert(s);
  582. while(*s && !isspace((int)*s) && *s != '#')
  583. s++;
  584. return s;
  585. }
  586. /*
  587. * Time
  588. */
  589. void tor_gettimeofday(struct timeval *timeval) {
  590. #ifdef HAVE_GETTIMEOFDAY
  591. if (gettimeofday(timeval, NULL)) {
  592. log_fn(LOG_ERR, "gettimeofday failed.");
  593. /* If gettimeofday dies, we have either given a bad timezone (we didn't),
  594. or segfaulted.*/
  595. exit(1);
  596. }
  597. #elif defined(HAVE_FTIME)
  598. ftime(timeval);
  599. #else
  600. #error "No way to get time."
  601. #endif
  602. return;
  603. }
  604. long
  605. tv_udiff(struct timeval *start, struct timeval *end)
  606. {
  607. long udiff;
  608. long secdiff = end->tv_sec - start->tv_sec;
  609. if (secdiff+1 > LONG_MAX/1000000) {
  610. log_fn(LOG_WARN, "comparing times too far apart.");
  611. return LONG_MAX;
  612. }
  613. udiff = secdiff*1000000L + (end->tv_usec - start->tv_usec);
  614. if(udiff < 0) {
  615. log_fn(LOG_INFO, "start (%ld.%ld) is after end (%ld.%ld). Returning 0.",
  616. (long)start->tv_sec, (long)start->tv_usec, (long)end->tv_sec, (long)end->tv_usec);
  617. return 0;
  618. }
  619. return udiff;
  620. }
  621. int tv_cmp(struct timeval *a, struct timeval *b) {
  622. if (a->tv_sec > b->tv_sec)
  623. return 1;
  624. if (a->tv_sec < b->tv_sec)
  625. return -1;
  626. if (a->tv_usec > b->tv_usec)
  627. return 1;
  628. if (a->tv_usec < b->tv_usec)
  629. return -1;
  630. return 0;
  631. }
  632. void tv_add(struct timeval *a, struct timeval *b) {
  633. a->tv_usec += b->tv_usec;
  634. a->tv_sec += b->tv_sec + (a->tv_usec / 1000000);
  635. a->tv_usec %= 1000000;
  636. }
  637. void tv_addms(struct timeval *a, long ms) {
  638. a->tv_usec += (ms * 1000) % 1000000;
  639. a->tv_sec += ((ms * 1000) / 1000000) + (a->tv_usec / 1000000);
  640. a->tv_usec %= 1000000;
  641. }
  642. #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
  643. static int n_leapdays(int y1, int y2) {
  644. --y1;
  645. --y2;
  646. return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
  647. }
  648. static const int days_per_month[] =
  649. { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  650. time_t tor_timegm (struct tm *tm) {
  651. /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
  652. * It's way more brute-force than fiddling with tzset().
  653. */
  654. time_t ret;
  655. unsigned long year, days, hours, minutes;
  656. int i;
  657. year = tm->tm_year + 1900;
  658. assert(year >= 1970);
  659. assert(tm->tm_mon >= 0 && tm->tm_mon <= 11);
  660. days = 365 * (year-1970) + n_leapdays(1970,year);
  661. for (i = 0; i < tm->tm_mon; ++i)
  662. days += days_per_month[i];
  663. if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
  664. ++days;
  665. days += tm->tm_mday - 1;
  666. hours = days*24 + tm->tm_hour;
  667. minutes = hours*60 + tm->tm_min;
  668. ret = minutes*60 + tm->tm_sec;
  669. return ret;
  670. }
  671. /*
  672. * Low-level I/O.
  673. */
  674. /* a wrapper for write(2) that makes sure to write all count bytes.
  675. * Only use if fd is a blocking fd. */
  676. int write_all(int fd, const char *buf, size_t count, int isSocket) {
  677. size_t written = 0;
  678. int result;
  679. while(written != count) {
  680. if (isSocket)
  681. result = send(fd, buf+written, count-written, 0);
  682. else
  683. result = write(fd, buf+written, count-written);
  684. if(result<0)
  685. return -1;
  686. written += result;
  687. }
  688. return count;
  689. }
  690. /* a wrapper for read(2) that makes sure to read all count bytes.
  691. * Only use if fd is a blocking fd. */
  692. int read_all(int fd, char *buf, size_t count, int isSocket) {
  693. size_t numread = 0;
  694. int result;
  695. while(numread != count) {
  696. if (isSocket)
  697. result = recv(fd, buf+numread, count-numread, 0);
  698. else
  699. result = read(fd, buf+numread, count-numread);
  700. if(result<=0)
  701. return -1;
  702. numread += result;
  703. }
  704. return count;
  705. }
  706. void set_socket_nonblocking(int socket)
  707. {
  708. #ifdef MS_WINDOWS
  709. /* Yes means no and no means yes. Do you not want to be nonblocking? */
  710. int nonblocking = 0;
  711. ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
  712. #else
  713. fcntl(socket, F_SETFL, O_NONBLOCK);
  714. #endif
  715. }
  716. /*
  717. * Process control
  718. */
  719. /* Minimalist interface to run a void function in the background. On
  720. * unix calls fork, on win32 calls beginthread. Returns -1 on failure.
  721. * func should not return, but rather should call spawn_exit.
  722. */
  723. int spawn_func(int (*func)(void *), void *data)
  724. {
  725. #ifdef MS_WINDOWS
  726. int rv;
  727. rv = _beginthread(func, 0, data);
  728. if (rv == (unsigned long) -1)
  729. return -1;
  730. return 0;
  731. #else
  732. pid_t pid;
  733. pid = fork();
  734. if (pid<0)
  735. return -1;
  736. if (pid==0) {
  737. /* Child */
  738. func(data);
  739. assert(0); /* Should never reach here. */
  740. return 0; /* suppress "control-reaches-end-of-non-void" warning. */
  741. } else {
  742. /* Parent */
  743. return 0;
  744. }
  745. #endif
  746. }
  747. void spawn_exit()
  748. {
  749. #ifdef MS_WINDOWS
  750. _endthread();
  751. #else
  752. exit(0);
  753. #endif
  754. }
  755. /*
  756. * Windows compatibility.
  757. */
  758. int
  759. tor_socketpair(int family, int type, int protocol, int fd[2])
  760. {
  761. #ifdef HAVE_SOCKETPAIR_XXXX
  762. /* For testing purposes, we never fall back to real socketpairs. */
  763. return socketpair(family, type, protocol, fd);
  764. #else
  765. int listener = -1;
  766. int connector = -1;
  767. int acceptor = -1;
  768. struct sockaddr_in listen_addr;
  769. struct sockaddr_in connect_addr;
  770. int size;
  771. if (protocol
  772. #ifdef AF_UNIX
  773. || family != AF_UNIX
  774. #endif
  775. ) {
  776. #ifdef MS_WINDOWS
  777. errno = WSAEAFNOSUPPORT;
  778. #else
  779. errno = EAFNOSUPPORT;
  780. #endif
  781. return -1;
  782. }
  783. if (!fd) {
  784. errno = EINVAL;
  785. return -1;
  786. }
  787. listener = socket(AF_INET, type, 0);
  788. if (listener == -1)
  789. return -1;
  790. memset (&listen_addr, 0, sizeof (listen_addr));
  791. listen_addr.sin_family = AF_INET;
  792. listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  793. listen_addr.sin_port = 0; /* kernel choses port. */
  794. if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
  795. == -1)
  796. goto tidy_up_and_fail;
  797. if (listen(listener, 1) == -1)
  798. goto tidy_up_and_fail;
  799. connector = socket(AF_INET, type, 0);
  800. if (connector == -1)
  801. goto tidy_up_and_fail;
  802. /* We want to find out the port number to connect to. */
  803. size = sizeof (connect_addr);
  804. if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
  805. goto tidy_up_and_fail;
  806. if (size != sizeof (connect_addr))
  807. goto abort_tidy_up_and_fail;
  808. if (connect(connector, (struct sockaddr *) &connect_addr,
  809. sizeof (connect_addr)) == -1)
  810. goto tidy_up_and_fail;
  811. size = sizeof (listen_addr);
  812. acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
  813. if (acceptor == -1)
  814. goto tidy_up_and_fail;
  815. if (size != sizeof(listen_addr))
  816. goto abort_tidy_up_and_fail;
  817. close(listener);
  818. /* Now check we are talking to ourself by matching port and host on the
  819. two sockets. */
  820. if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
  821. goto tidy_up_and_fail;
  822. if (size != sizeof (connect_addr)
  823. || listen_addr.sin_family != connect_addr.sin_family
  824. || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
  825. || listen_addr.sin_port != connect_addr.sin_port) {
  826. goto abort_tidy_up_and_fail;
  827. }
  828. fd[0] = connector;
  829. fd[1] = acceptor;
  830. return 0;
  831. abort_tidy_up_and_fail:
  832. #ifdef MS_WINDOWS
  833. errno = WSAECONNABORTED;
  834. #else
  835. errno = ECONNABORTED; /* I hope this is portable and appropriate. */
  836. #endif
  837. tidy_up_and_fail:
  838. {
  839. int save_errno = errno;
  840. if (listener != -1)
  841. close(listener);
  842. if (connector != -1)
  843. close(connector);
  844. if (acceptor != -1)
  845. close(acceptor);
  846. errno = save_errno;
  847. return -1;
  848. }
  849. #endif
  850. }
  851. #ifdef MS_WINDOWS
  852. int correct_socket_errno(int s)
  853. {
  854. int optval, optvallen=sizeof(optval);
  855. assert(errno == WSAEWOULDBLOCK);
  856. if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
  857. return errno;
  858. if (optval)
  859. return optval;
  860. return WSAEWOULDBLOCK;
  861. }
  862. #endif
  863. /*
  864. * Filesystem operations.
  865. */
  866. /* Return FN_ERROR if filename can't be read, FN_NOENT if it doesn't
  867. * exist, FN_FILE if it is a regular file, or FN_DIR if it's a
  868. * directory. */
  869. file_status_t file_status(const char *fname)
  870. {
  871. struct stat st;
  872. if (stat(fname, &st)) {
  873. if (errno == ENOENT) {
  874. return FN_NOENT;
  875. }
  876. return FN_ERROR;
  877. }
  878. if (st.st_mode & S_IFDIR)
  879. return FN_DIR;
  880. else if (st.st_mode & S_IFREG)
  881. return FN_FILE;
  882. else
  883. return FN_ERROR;
  884. }
  885. /* Check whether dirname exists and is private. If yes returns
  886. 0. Else returns -1. */
  887. int check_private_dir(const char *dirname, int create)
  888. {
  889. int r;
  890. struct stat st;
  891. if (stat(dirname, &st)) {
  892. if (errno != ENOENT) {
  893. log(LOG_WARN, "Directory %s cannot be read: %s", dirname,
  894. strerror(errno));
  895. return -1;
  896. }
  897. if (!create) {
  898. log(LOG_WARN, "Directory %s does not exist.", dirname);
  899. return -1;
  900. }
  901. log(LOG_INFO, "Creating directory %s", dirname);
  902. #ifdef MS_WINDOWS
  903. r = mkdir(dirname);
  904. #else
  905. r = mkdir(dirname, 0700);
  906. #endif
  907. if (r) {
  908. log(LOG_WARN, "Error creating directory %s: %s", dirname,
  909. strerror(errno));
  910. return -1;
  911. } else {
  912. return 0;
  913. }
  914. }
  915. if (!(st.st_mode & S_IFDIR)) {
  916. log(LOG_WARN, "%s is not a directory", dirname);
  917. return -1;
  918. }
  919. #ifndef MS_WINDOWS
  920. if (st.st_uid != getuid()) {
  921. log(LOG_WARN, "%s is not owned by this UID (%d)", dirname, (int)getuid());
  922. return -1;
  923. }
  924. if (st.st_mode & 0077) {
  925. log(LOG_WARN, "Fixing permissions on directory %s", dirname);
  926. if (chmod(dirname, 0700)) {
  927. log(LOG_WARN, "Could not chmod directory %s: %s", dirname,
  928. strerror(errno));
  929. return -1;
  930. } else {
  931. return 0;
  932. }
  933. }
  934. #endif
  935. return 0;
  936. }
  937. int
  938. write_str_to_file(const char *fname, const char *str)
  939. {
  940. char tempname[1024];
  941. int fd;
  942. FILE *file;
  943. if ((strlcpy(tempname,fname,1024) >= 1024) ||
  944. (strlcat(tempname,".tmp",1024) >= 1024)) {
  945. log(LOG_WARN, "Filename %s.tmp too long (>1024 chars)", fname);
  946. return -1;
  947. }
  948. if ((fd = open(tempname, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
  949. log(LOG_WARN, "Couldn't open %s for writing: %s", tempname,
  950. strerror(errno));
  951. return -1;
  952. }
  953. if (!(file = fdopen(fd, "w"))) {
  954. log(LOG_WARN, "Couldn't fdopen %s for writing: %s", tempname,
  955. strerror(errno));
  956. close(fd); return -1;
  957. }
  958. if (fputs(str,file) == EOF) {
  959. log(LOG_WARN, "Error writing to %s: %s", tempname, strerror(errno));
  960. fclose(file); return -1;
  961. }
  962. fclose(file);
  963. if (rename(tempname, fname)) {
  964. log(LOG_WARN, "Error replacing %s: %s", fname, strerror(errno));
  965. return -1;
  966. }
  967. return 0;
  968. }
  969. char *read_file_to_str(const char *filename) {
  970. int fd; /* router file */
  971. struct stat statbuf;
  972. char *string;
  973. assert(filename);
  974. if(strcspn(filename,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) {
  975. log_fn(LOG_WARN,"Filename %s contains illegal characters.",filename);
  976. return NULL;
  977. }
  978. if(stat(filename, &statbuf) < 0) {
  979. log_fn(LOG_INFO,"Could not stat %s.",filename);
  980. return NULL;
  981. }
  982. fd = open(filename,O_RDONLY,0);
  983. if (fd<0) {
  984. log_fn(LOG_WARN,"Could not open %s.",filename);
  985. return NULL;
  986. }
  987. string = tor_malloc(statbuf.st_size+1);
  988. if(read_all(fd,string,statbuf.st_size,0) != statbuf.st_size) {
  989. log_fn(LOG_WARN,"Couldn't read all %ld bytes of file '%s'.",
  990. (long)statbuf.st_size,filename);
  991. free(string);
  992. close(fd);
  993. return NULL;
  994. }
  995. close(fd);
  996. string[statbuf.st_size] = 0; /* null terminate it */
  997. return string;
  998. }
  999. /* read lines from f (no more than maxlen-1 bytes each) until we
  1000. * get a non-whitespace line. If it isn't of the form "key value"
  1001. * (value can have spaces), return -1.
  1002. * Point *key to the first word in line, point *value * to the second.
  1003. * Put a \0 at the end of key, remove everything at the end of value
  1004. * that is whitespace or comment.
  1005. * Return 1 if success, 0 if no more lines, -1 if error.
  1006. */
  1007. int parse_line_from_file(char *line, int maxlen, FILE *f, char **key_out, char **value_out) {
  1008. char *s, *key, *end, *value;
  1009. try_next_line:
  1010. if(!fgets(line, maxlen, f)) {
  1011. if(feof(f))
  1012. return 0;
  1013. return -1; /* real error */
  1014. }
  1015. if((s = strchr(line,'#'))) /* strip comments */
  1016. *s = 0; /* stop the line there */
  1017. /* remove end whitespace */
  1018. s = strchr(line, 0); /* now we're at the null */
  1019. do {
  1020. *s = 0;
  1021. s--;
  1022. } while (s >= line && isspace((int)*s));
  1023. key = line;
  1024. while(isspace((int)*key))
  1025. key++;
  1026. if(*key == 0)
  1027. goto try_next_line; /* this line has nothing on it */
  1028. end = key;
  1029. while(*end && !isspace((int)*end))
  1030. end++;
  1031. value = end;
  1032. while(*value && isspace((int)*value))
  1033. value++;
  1034. if(!*end || !*value) { /* only a key on this line. no value. */
  1035. *end = 0;
  1036. log_fn(LOG_WARN,"Line has keyword '%s' but no value. Failing.",key);
  1037. return -1;
  1038. }
  1039. *end = 0; /* null it out */
  1040. log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
  1041. *key_out = key, *value_out = value;
  1042. return 1;
  1043. }
  1044. int is_internal_IP(uint32_t ip) {
  1045. if (((ip & 0xff000000) == 0x0a000000) || /* 10/8 */
  1046. ((ip & 0xff000000) == 0x00000000) || /* 0/8 */
  1047. ((ip & 0xff000000) == 0x7f000000) || /* 127/8 */
  1048. ((ip & 0xffff0000) == 0xa9fe0000) || /* 169.254/16 */
  1049. ((ip & 0xfff00000) == 0xac100000) || /* 172.16/12 */
  1050. ((ip & 0xffff0000) == 0xc0a80000)) /* 192.168/16 */
  1051. return 1;
  1052. return 0;
  1053. }
  1054. static char uname_result[256];
  1055. static int uname_result_is_set = 0;
  1056. const char *
  1057. get_uname(void)
  1058. {
  1059. #ifdef HAVE_UNAME
  1060. struct utsname u;
  1061. #endif
  1062. if (!uname_result_is_set) {
  1063. #ifdef HAVE_UNAME
  1064. if (uname(&u) != -1) {
  1065. /* (linux says 0 is success, solaris says 1 is success) */
  1066. snprintf(uname_result, 255, "%s %s %s",
  1067. u.sysname, u.nodename, u.machine);
  1068. uname_result[255] = '\0';
  1069. } else
  1070. #endif
  1071. {
  1072. strcpy(uname_result, "Unknown platform");
  1073. }
  1074. uname_result_is_set = 1;
  1075. }
  1076. return uname_result;
  1077. }
  1078. #ifndef MS_WINDOWS
  1079. /* Based on code contributed by christian grothoff */
  1080. static int start_daemon_called = 0;
  1081. static int finish_daemon_called = 0;
  1082. static int daemon_filedes[2];
  1083. void start_daemon(char *desired_cwd)
  1084. {
  1085. pid_t pid;
  1086. if (start_daemon_called)
  1087. return;
  1088. start_daemon_called = 1;
  1089. if(!desired_cwd)
  1090. desired_cwd = "/";
  1091. /* Don't hold the wrong FS mounted */
  1092. if (chdir(desired_cwd) < 0) {
  1093. log_fn(LOG_ERR,"chdir to %s failed. Exiting.",desired_cwd);
  1094. exit(1);
  1095. }
  1096. pipe(daemon_filedes);
  1097. pid = fork();
  1098. if (pid < 0) {
  1099. log_fn(LOG_ERR,"fork failed. Exiting.");
  1100. exit(1);
  1101. }
  1102. if (pid) { /* Parent */
  1103. int ok;
  1104. char c;
  1105. close(daemon_filedes[1]); /* we only read */
  1106. ok = -1;
  1107. while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
  1108. if (c == '.')
  1109. ok = 1;
  1110. }
  1111. fflush(stdout);
  1112. if (ok == 1)
  1113. exit(0);
  1114. else
  1115. exit(1); /* child reported error */
  1116. } else { /* Child */
  1117. close(daemon_filedes[0]); /* we only write */
  1118. pid = setsid(); /* Detach from controlling terminal */
  1119. /*
  1120. * Fork one more time, so the parent (the session group leader) can exit.
  1121. * This means that we, as a non-session group leader, can never regain a
  1122. * controlling terminal. This part is recommended by Stevens's
  1123. * _Advanced Programming in the Unix Environment_.
  1124. */
  1125. if (fork() != 0) {
  1126. exit(0);
  1127. }
  1128. return;
  1129. }
  1130. }
  1131. void finish_daemon(void)
  1132. {
  1133. int nullfd;
  1134. char c = '.';
  1135. if (finish_daemon_called)
  1136. return;
  1137. if (!start_daemon_called)
  1138. start_daemon(NULL);
  1139. finish_daemon_called = 1;
  1140. nullfd = open("/dev/null",
  1141. O_CREAT | O_RDWR | O_APPEND);
  1142. if (nullfd < 0) {
  1143. log_fn(LOG_ERR,"/dev/null can't be opened. Exiting.");
  1144. exit(1);
  1145. }
  1146. /* close fds linking to invoking terminal, but
  1147. * close usual incoming fds, but redirect them somewhere
  1148. * useful so the fds don't get reallocated elsewhere.
  1149. */
  1150. if (dup2(nullfd,0) < 0 ||
  1151. dup2(nullfd,1) < 0 ||
  1152. dup2(nullfd,2) < 0) {
  1153. log_fn(LOG_ERR,"dup2 failed. Exiting.");
  1154. exit(1);
  1155. }
  1156. write(daemon_filedes[1], &c, sizeof(char)); /* signal success */
  1157. close(daemon_filedes[1]);
  1158. }
  1159. #else
  1160. /* defined(MS_WINDOWS) */
  1161. void start_daemon(char *cp) {}
  1162. void finish_daemon(void) {}
  1163. #endif
  1164. void write_pidfile(char *filename) {
  1165. #ifndef MS_WINDOWS
  1166. FILE *pidfile;
  1167. if ((pidfile = fopen(filename, "w")) == NULL) {
  1168. log_fn(LOG_WARN, "unable to open %s for writing: %s", filename,
  1169. strerror(errno));
  1170. } else {
  1171. fprintf(pidfile, "%d", (int)getpid());
  1172. fclose(pidfile);
  1173. }
  1174. #endif
  1175. }
  1176. int switch_id(char *user, char *group) {
  1177. #ifndef MS_WINDOWS
  1178. struct passwd *pw = NULL;
  1179. struct group *gr = NULL;
  1180. if (user) {
  1181. pw = getpwnam(user);
  1182. if (pw == NULL) {
  1183. log_fn(LOG_ERR,"User '%s' not found.", user);
  1184. return -1;
  1185. }
  1186. }
  1187. /* switch the group first, while we still have the privileges to do so */
  1188. if (group) {
  1189. gr = getgrnam(group);
  1190. if (gr == NULL) {
  1191. log_fn(LOG_ERR,"Group '%s' not found.", group);
  1192. return -1;
  1193. }
  1194. if (setgid(gr->gr_gid) != 0) {
  1195. log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
  1196. return -1;
  1197. }
  1198. } else if (user) {
  1199. if (setgid(pw->pw_gid) != 0) {
  1200. log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
  1201. return -1;
  1202. }
  1203. }
  1204. /* now that the group is switched, we can switch users and lose
  1205. privileges */
  1206. if (user) {
  1207. if (setuid(pw->pw_uid) != 0) {
  1208. log_fn(LOG_ERR,"Error setting UID: %s", strerror(errno));
  1209. return -1;
  1210. }
  1211. }
  1212. return 0;
  1213. #endif
  1214. log_fn(LOG_ERR,
  1215. "User or group specified, but switching users is not supported.");
  1216. return -1;
  1217. }
  1218. int tor_inet_aton(const char *c, struct in_addr* addr)
  1219. {
  1220. #ifdef HAVE_INET_ATON
  1221. return inet_aton(c, addr);
  1222. #else
  1223. uint32_t r;
  1224. assert(c && addr);
  1225. if (strcmp(c, "255.255.255.255") == 0) {
  1226. addr->s_addr = 0xFFFFFFFFu;
  1227. return 1;
  1228. }
  1229. r = inet_addr(c);
  1230. if (r == INADDR_NONE)
  1231. return 0;
  1232. addr->s_addr = r;
  1233. return 1;
  1234. #endif
  1235. }
  1236. /*
  1237. Local Variables:
  1238. mode:c
  1239. indent-tabs-mode:nil
  1240. c-basic-offset:2
  1241. End:
  1242. */