Back to index

tor  0.2.3.19-rc
util.c
Go to the documentation of this file.
00001 /* Copyright (c) 2003, Roger Dingledine
00002  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00003  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00004 /* See LICENSE for licensing information */
00005 
00012 /* This is required on rh7 to make strptime not complain.
00013  */
00014 #define _GNU_SOURCE
00015 
00016 #include "orconfig.h"
00017 #ifdef HAVE_FCNTL_H
00018 #include <fcntl.h>
00019 #endif
00020 #define UTIL_PRIVATE
00021 #include "util.h"
00022 #include "torlog.h"
00023 #undef log
00024 #include "crypto.h"
00025 #include "torint.h"
00026 #include "container.h"
00027 #include "address.h"
00028 
00029 #ifdef _WIN32
00030 #include <io.h>
00031 #include <direct.h>
00032 #include <process.h>
00033 #include <tchar.h>
00034 #include <winbase.h>
00035 #else
00036 #include <dirent.h>
00037 #include <pwd.h>
00038 #include <grp.h>
00039 #endif
00040 
00041 /* math.h needs this on Linux */
00042 #ifndef __USE_ISOC99
00043 #define __USE_ISOC99 1
00044 #endif
00045 #include <math.h>
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <assert.h>
00050 #include <signal.h>
00051 
00052 #ifdef HAVE_NETINET_IN_H
00053 #include <netinet/in.h>
00054 #endif
00055 #ifdef HAVE_ARPA_INET_H
00056 #include <arpa/inet.h>
00057 #endif
00058 #ifdef HAVE_ERRNO_H
00059 #include <errno.h>
00060 #endif
00061 #ifdef HAVE_SYS_SOCKET_H
00062 #include <sys/socket.h>
00063 #endif
00064 #ifdef HAVE_SYS_TIME_H
00065 #include <sys/time.h>
00066 #endif
00067 #ifdef HAVE_UNISTD_H
00068 #include <unistd.h>
00069 #endif
00070 #ifdef HAVE_SYS_STAT_H
00071 #include <sys/stat.h>
00072 #endif
00073 #ifdef HAVE_SYS_FCNTL_H
00074 #include <sys/fcntl.h>
00075 #endif
00076 #ifdef HAVE_TIME_H
00077 #include <time.h>
00078 #endif
00079 #ifdef HAVE_MALLOC_MALLOC_H
00080 #include <malloc/malloc.h>
00081 #endif
00082 #ifdef HAVE_MALLOC_H
00083 #if !defined(OPENBSD) && !defined(__FreeBSD__)
00084 /* OpenBSD has a malloc.h, but for our purposes, it only exists in order to
00085  * scold us for being so stupid as to autodetect its presence.  To be fair,
00086  * they've done this since 1996, when autoconf was only 5 years old. */
00087 #include <malloc.h>
00088 #endif
00089 #endif
00090 #ifdef HAVE_MALLOC_NP_H
00091 #include <malloc_np.h>
00092 #endif
00093 #ifdef HAVE_SYS_WAIT_H
00094 #include <sys/wait.h>
00095 #endif
00096 
00097 /* =====
00098  * Memory management
00099  * ===== */
00100 #ifdef USE_DMALLOC
00101  #undef strndup
00102  #include <dmalloc.h>
00103  /* Macro to pass the extra dmalloc args to another function. */
00104  #define DMALLOC_FN_ARGS , file, line
00105 
00106  #if defined(HAVE_DMALLOC_STRDUP)
00107  /* the dmalloc_strdup should be fine as defined */
00108  #elif defined(HAVE_DMALLOC_STRNDUP)
00109  #define dmalloc_strdup(file, line, string, xalloc_b) \
00110          dmalloc_strndup(file, line, (string), -1, xalloc_b)
00111  #else
00112  #error "No dmalloc_strdup or equivalent"
00113  #endif
00114 
00115 #else /* not using dmalloc */
00116 
00117  #define DMALLOC_FN_ARGS
00118 #endif
00119 
00127 void *
00128 _tor_malloc(size_t size DMALLOC_PARAMS)
00129 {
00130   void *result;
00131 
00132   tor_assert(size < SIZE_T_CEILING);
00133 
00134 #ifndef MALLOC_ZERO_WORKS
00135   /* Some libc mallocs don't work when size==0. Override them. */
00136   if (size==0) {
00137     size=1;
00138   }
00139 #endif
00140 
00141 #ifdef USE_DMALLOC
00142   result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
00143 #else
00144   result = malloc(size);
00145 #endif
00146 
00147   if (PREDICT_UNLIKELY(result == NULL)) {
00148     log_err(LD_MM,"Out of memory on malloc(). Dying.");
00149     /* If these functions die within a worker process, they won't call
00150      * spawn_exit, but that's ok, since the parent will run out of memory soon
00151      * anyway. */
00152     exit(1);
00153   }
00154   return result;
00155 }
00156 
00161 void *
00162 _tor_malloc_zero(size_t size DMALLOC_PARAMS)
00163 {
00164   /* You may ask yourself, "wouldn't it be smart to use calloc instead of
00165    * malloc+memset?  Perhaps libc's calloc knows some nifty optimization trick
00166    * we don't!"  Indeed it does, but its optimizations are only a big win when
00167    * we're allocating something very big (it knows if it just got the memory
00168    * from the OS in a pre-zeroed state).  We don't want to use tor_malloc_zero
00169    * for big stuff, so we don't bother with calloc. */
00170   void *result = _tor_malloc(size DMALLOC_FN_ARGS);
00171   memset(result, 0, size);
00172   return result;
00173 }
00174 
00186 void *
00187 _tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS)
00188 {
00189   /* You may ask yourself, "wouldn't it be smart to use calloc instead of
00190    * malloc+memset?  Perhaps libc's calloc knows some nifty optimization trick
00191    * we don't!"  Indeed it does, but its optimizations are only a big win when
00192    * we're allocating something very big (it knows if it just got the memory
00193    * from the OS in a pre-zeroed state).  We don't want to use tor_malloc_zero
00194    * for big stuff, so we don't bother with calloc. */
00195   void *result;
00196   size_t max_nmemb = (size == 0) ? SIZE_MAX : SIZE_MAX/size;
00197 
00198   tor_assert(nmemb < max_nmemb);
00199 
00200   result = _tor_malloc_zero((nmemb * size) DMALLOC_FN_ARGS);
00201   return result;
00202 }
00203 
00208 void *
00209 _tor_realloc(void *ptr, size_t size DMALLOC_PARAMS)
00210 {
00211   void *result;
00212 
00213   tor_assert(size < SIZE_T_CEILING);
00214 
00215 #ifdef USE_DMALLOC
00216   result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
00217 #else
00218   result = realloc(ptr, size);
00219 #endif
00220 
00221   if (PREDICT_UNLIKELY(result == NULL)) {
00222     log_err(LD_MM,"Out of memory on realloc(). Dying.");
00223     exit(1);
00224   }
00225   return result;
00226 }
00227 
00232 char *
00233 _tor_strdup(const char *s DMALLOC_PARAMS)
00234 {
00235   char *dup;
00236   tor_assert(s);
00237 
00238 #ifdef USE_DMALLOC
00239   dup = dmalloc_strdup(file, line, s, 0);
00240 #else
00241   dup = strdup(s);
00242 #endif
00243   if (PREDICT_UNLIKELY(dup == NULL)) {
00244     log_err(LD_MM,"Out of memory on strdup(). Dying.");
00245     exit(1);
00246   }
00247   return dup;
00248 }
00249 
00256 char *
00257 _tor_strndup(const char *s, size_t n DMALLOC_PARAMS)
00258 {
00259   char *dup;
00260   tor_assert(s);
00261   tor_assert(n < SIZE_T_CEILING);
00262   dup = _tor_malloc((n+1) DMALLOC_FN_ARGS);
00263   /* Performance note: Ordinarily we prefer strlcpy to strncpy.  But
00264    * this function gets called a whole lot, and platform strncpy is
00265    * much faster than strlcpy when strlen(s) is much longer than n.
00266    */
00267   strncpy(dup, s, n);
00268   dup[n]='\0';
00269   return dup;
00270 }
00271 
00274 void *
00275 _tor_memdup(const void *mem, size_t len DMALLOC_PARAMS)
00276 {
00277   char *dup;
00278   tor_assert(len < SIZE_T_CEILING);
00279   tor_assert(mem);
00280   dup = _tor_malloc(len DMALLOC_FN_ARGS);
00281   memcpy(dup, mem, len);
00282   return dup;
00283 }
00284 
00287 void
00288 _tor_free(void *mem)
00289 {
00290   tor_free(mem);
00291 }
00292 
00293 #if defined(HAVE_MALLOC_GOOD_SIZE) && !defined(HAVE_MALLOC_GOOD_SIZE_PROTOTYPE)
00294 /* Some version of Mac OSX have malloc_good_size in their libc, but not
00295  * actually defined in malloc/malloc.h.  We detect this and work around it by
00296  * prototyping.
00297  */
00298 extern size_t malloc_good_size(size_t size);
00299 #endif
00300 
00304 void *
00305 _tor_malloc_roundup(size_t *sizep DMALLOC_PARAMS)
00306 {
00307 #ifdef HAVE_MALLOC_GOOD_SIZE
00308   tor_assert(*sizep < SIZE_T_CEILING);
00309   *sizep = malloc_good_size(*sizep);
00310   return _tor_malloc(*sizep DMALLOC_FN_ARGS);
00311 #elif 0 && defined(HAVE_MALLOC_USABLE_SIZE) && !defined(USE_DMALLOC)
00312   /* Never use malloc_usable_size(); it makes valgrind really unhappy,
00313    * and doesn't win much in terms of usable space where it exists. */
00314   void *result;
00315   tor_assert(*sizep < SIZE_T_CEILING);
00316   result = _tor_malloc(*sizep DMALLOC_FN_ARGS);
00317   *sizep = malloc_usable_size(result);
00318   return result;
00319 #else
00320   return _tor_malloc(*sizep DMALLOC_FN_ARGS);
00321 #endif
00322 }
00323 
00326 void
00327 tor_log_mallinfo(int severity)
00328 {
00329 #ifdef HAVE_MALLINFO
00330   struct mallinfo mi;
00331   memset(&mi, 0, sizeof(mi));
00332   mi = mallinfo();
00333   tor_log(severity, LD_MM,
00334       "mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, "
00335       "hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, "
00336       "keepcost=%d",
00337       mi.arena, mi.ordblks, mi.smblks, mi.hblks,
00338       mi.hblkhd, mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks,
00339       mi.keepcost);
00340 #else
00341   (void)severity;
00342 #endif
00343 #ifdef USE_DMALLOC
00344   dmalloc_log_changed(0, /* Since the program started. */
00345                       1, /* Log info about non-freed pointers. */
00346                       0, /* Do not log info about freed pointers. */
00347                       0  /* Do not log individual pointers. */
00348                       );
00349 #endif
00350 }
00351 
00352 /* =====
00353  * Math
00354  * ===== */
00355 
00360 double
00361 tor_mathlog(double d)
00362 {
00363   return log(d);
00364 }
00365 
00369 long
00370 tor_lround(double d)
00371 {
00372 #if defined(HAVE_LROUND)
00373   return lround(d);
00374 #elif defined(HAVE_RINT)
00375   return (long)rint(d);
00376 #else
00377   return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
00378 #endif
00379 }
00380 
00382 int
00383 tor_log2(uint64_t u64)
00384 {
00385   int r = 0;
00386   if (u64 >= (U64_LITERAL(1)<<32)) {
00387     u64 >>= 32;
00388     r = 32;
00389   }
00390   if (u64 >= (U64_LITERAL(1)<<16)) {
00391     u64 >>= 16;
00392     r += 16;
00393   }
00394   if (u64 >= (U64_LITERAL(1)<<8)) {
00395     u64 >>= 8;
00396     r += 8;
00397   }
00398   if (u64 >= (U64_LITERAL(1)<<4)) {
00399     u64 >>= 4;
00400     r += 4;
00401   }
00402   if (u64 >= (U64_LITERAL(1)<<2)) {
00403     u64 >>= 2;
00404     r += 2;
00405   }
00406   if (u64 >= (U64_LITERAL(1)<<1)) {
00407     u64 >>= 1;
00408     r += 1;
00409   }
00410   return r;
00411 }
00412 
00414 uint64_t
00415 round_to_power_of_2(uint64_t u64)
00416 {
00417   int lg2 = tor_log2(u64);
00418   uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1);
00419   if (high - u64 < u64 - low)
00420     return high;
00421   else
00422     return low;
00423 }
00424 
00427 unsigned
00428 round_to_next_multiple_of(unsigned number, unsigned divisor)
00429 {
00430   number += divisor - 1;
00431   number -= number % divisor;
00432   return number;
00433 }
00434 
00437 uint32_t
00438 round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor)
00439 {
00440   number += divisor - 1;
00441   number -= number % divisor;
00442   return number;
00443 }
00444 
00447 uint64_t
00448 round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
00449 {
00450   number += divisor - 1;
00451   number -= number % divisor;
00452   return number;
00453 }
00454 
00456 int
00457 n_bits_set_u8(uint8_t v)
00458 {
00459   static const int nybble_table[] = {
00460     0, /* 0000 */
00461     1, /* 0001 */
00462     1, /* 0010 */
00463     2, /* 0011 */
00464     1, /* 0100 */
00465     2, /* 0101 */
00466     2, /* 0110 */
00467     3, /* 0111 */
00468     1, /* 1000 */
00469     2, /* 1001 */
00470     2, /* 1010 */
00471     3, /* 1011 */
00472     2, /* 1100 */
00473     3, /* 1101 */
00474     3, /* 1110 */
00475     4, /* 1111 */
00476   };
00477 
00478   return nybble_table[v & 15] + nybble_table[v>>4];
00479 }
00480 
00481 /* =====
00482  * String manipulation
00483  * ===== */
00484 
00487 void
00488 tor_strstrip(char *s, const char *strip)
00489 {
00490   char *read = s;
00491   while (*read) {
00492     if (strchr(strip, *read)) {
00493       ++read;
00494     } else {
00495       *s++ = *read++;
00496     }
00497   }
00498   *s = '\0';
00499 }
00500 
00506 const char *
00507 hex_str(const char *from, size_t fromlen)
00508 {
00509   static char buf[65];
00510   if (fromlen>(sizeof(buf)-1)/2)
00511     fromlen = (sizeof(buf)-1)/2;
00512   base16_encode(buf,sizeof(buf),from,fromlen);
00513   return buf;
00514 }
00515 
00518 void
00519 tor_strlower(char *s)
00520 {
00521   while (*s) {
00522     *s = TOR_TOLOWER(*s);
00523     ++s;
00524   }
00525 }
00526 
00529 void
00530 tor_strupper(char *s)
00531 {
00532   while (*s) {
00533     *s = TOR_TOUPPER(*s);
00534     ++s;
00535   }
00536 }
00537 
00540 int
00541 tor_strisprint(const char *s)
00542 {
00543   while (*s) {
00544     if (!TOR_ISPRINT(*s))
00545       return 0;
00546     s++;
00547   }
00548   return 1;
00549 }
00550 
00553 int
00554 tor_strisnonupper(const char *s)
00555 {
00556   while (*s) {
00557     if (TOR_ISUPPER(*s))
00558       return 0;
00559     s++;
00560   }
00561   return 1;
00562 }
00563 
00566 int
00567 strcmp_opt(const char *s1, const char *s2)
00568 {
00569   if (!s1) {
00570     if (!s2)
00571       return 0;
00572     else
00573       return -1;
00574   } else if (!s2) {
00575     return 1;
00576   } else {
00577     return strcmp(s1, s2);
00578   }
00579 }
00580 
00584 int
00585 strcmpstart(const char *s1, const char *s2)
00586 {
00587   size_t n = strlen(s2);
00588   return strncmp(s1, s2, n);
00589 }
00590 
00595 int
00596 strcmp_len(const char *s1, const char *s2, size_t s1_len)
00597 {
00598   size_t s2_len = strlen(s2);
00599   if (s1_len < s2_len)
00600     return -1;
00601   if (s1_len > s2_len)
00602     return 1;
00603   return fast_memcmp(s1, s2, s2_len);
00604 }
00605 
00609 int
00610 strcasecmpstart(const char *s1, const char *s2)
00611 {
00612   size_t n = strlen(s2);
00613   return strncasecmp(s1, s2, n);
00614 }
00615 
00619 int
00620 strcmpend(const char *s1, const char *s2)
00621 {
00622   size_t n1 = strlen(s1), n2 = strlen(s2);
00623   if (n2>n1)
00624     return strcmp(s1,s2);
00625   else
00626     return strncmp(s1+(n1-n2), s2, n2);
00627 }
00628 
00632 int
00633 strcasecmpend(const char *s1, const char *s2)
00634 {
00635   size_t n1 = strlen(s1), n2 = strlen(s2);
00636   if (n2>n1) /* then they can't be the same; figure out which is bigger */
00637     return strcasecmp(s1,s2);
00638   else
00639     return strncasecmp(s1+(n1-n2), s2, n2);
00640 }
00641 
00648 int
00649 fast_memcmpstart(const void *mem, size_t memlen,
00650                 const char *prefix)
00651 {
00652   size_t plen = strlen(prefix);
00653   if (memlen < plen)
00654     return -1;
00655   return fast_memcmp(mem, prefix, plen);
00656 }
00657 
00661 const char *
00662 eat_whitespace(const char *s)
00663 {
00664   tor_assert(s);
00665 
00666   while (1) {
00667     switch (*s) {
00668     case '\0':
00669     default:
00670       return s;
00671     case ' ':
00672     case '\t':
00673     case '\n':
00674     case '\r':
00675       ++s;
00676       break;
00677     case '#':
00678       ++s;
00679       while (*s && *s != '\n')
00680         ++s;
00681     }
00682   }
00683 }
00684 
00688 const char *
00689 eat_whitespace_eos(const char *s, const char *eos)
00690 {
00691   tor_assert(s);
00692   tor_assert(eos && s <= eos);
00693 
00694   while (s < eos) {
00695     switch (*s) {
00696     case '\0':
00697     default:
00698       return s;
00699     case ' ':
00700     case '\t':
00701     case '\n':
00702     case '\r':
00703       ++s;
00704       break;
00705     case '#':
00706       ++s;
00707       while (s < eos && *s && *s != '\n')
00708         ++s;
00709     }
00710   }
00711   return s;
00712 }
00713 
00716 const char *
00717 eat_whitespace_no_nl(const char *s)
00718 {
00719   while (*s == ' ' || *s == '\t' || *s == '\r')
00720     ++s;
00721   return s;
00722 }
00723 
00726 const char *
00727 eat_whitespace_eos_no_nl(const char *s, const char *eos)
00728 {
00729   while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r'))
00730     ++s;
00731   return s;
00732 }
00733 
00737 const char *
00738 find_whitespace(const char *s)
00739 {
00740   /* tor_assert(s); */
00741   while (1) {
00742     switch (*s)
00743     {
00744     case '\0':
00745     case '#':
00746     case ' ':
00747     case '\r':
00748     case '\n':
00749     case '\t':
00750       return s;
00751     default:
00752       ++s;
00753     }
00754   }
00755 }
00756 
00759 const char *
00760 find_whitespace_eos(const char *s, const char *eos)
00761 {
00762   /* tor_assert(s); */
00763   while (s < eos) {
00764     switch (*s)
00765     {
00766     case '\0':
00767     case '#':
00768     case ' ':
00769     case '\r':
00770     case '\n':
00771     case '\t':
00772       return s;
00773     default:
00774       ++s;
00775     }
00776   }
00777   return s;
00778 }
00779 
00784 const char *
00785 find_str_at_start_of_line(const char *haystack, const char *needle)
00786 {
00787   size_t needle_len = strlen(needle);
00788 
00789   do {
00790     if (!strncmp(haystack, needle, needle_len))
00791       return haystack;
00792 
00793     haystack = strchr(haystack, '\n');
00794     if (!haystack)
00795       return NULL;
00796     else
00797       ++haystack;
00798   } while (*haystack);
00799 
00800   return NULL;
00801 }
00802 
00807 int
00808 string_is_C_identifier(const char *string)
00809 {
00810   size_t iter;
00811   size_t length = strlen(string);
00812   if (!length)
00813     return 0;
00814 
00815   for (iter = 0; iter < length ; iter++) {
00816     if (iter == 0) {
00817       if (!(TOR_ISALPHA(string[iter]) ||
00818             string[iter] == '_'))
00819         return 0;
00820     } else {
00821       if (!(TOR_ISALPHA(string[iter]) ||
00822             TOR_ISDIGIT(string[iter]) ||
00823             string[iter] == '_'))
00824         return 0;
00825     }
00826   }
00827 
00828   return 1;
00829 }
00830 
00832 int
00833 tor_mem_is_zero(const char *mem, size_t len)
00834 {
00835   static const char ZERO[] = {
00836     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
00837   };
00838   while (len >= sizeof(ZERO)) {
00839     /* It's safe to use fast_memcmp here, since the very worst thing an
00840      * attacker could learn is how many initial bytes of a secret were zero */
00841     if (fast_memcmp(mem, ZERO, sizeof(ZERO)))
00842       return 0;
00843     len -= sizeof(ZERO);
00844     mem += sizeof(ZERO);
00845   }
00846   /* Deal with leftover bytes. */
00847   if (len)
00848     return fast_memeq(mem, ZERO, len);
00849 
00850   return 1;
00851 }
00852 
00854 int
00855 tor_digest_is_zero(const char *digest)
00856 {
00857   static const uint8_t ZERO_DIGEST[] = {
00858     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
00859   };
00860   return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
00861 }
00862 
00864 int
00865 tor_digest256_is_zero(const char *digest)
00866 {
00867   return tor_mem_is_zero(digest, DIGEST256_LEN);
00868 }
00869 
00870 /* Helper: common code to check whether the result of a strtol or strtoul or
00871  * strtoll is correct. */
00872 #define CHECK_STRTOX_RESULT()                           \
00873   /* Did an overflow occur? */                          \
00874   if (errno == ERANGE)                                  \
00875     goto err;                                           \
00876   /* Was at least one character converted? */           \
00877   if (endptr == s)                                      \
00878     goto err;                                           \
00879   /* Were there unexpected unconverted characters? */   \
00880   if (!next && *endptr)                                 \
00881     goto err;                                           \
00882   /* Is r within limits? */                             \
00883   if (r < min || r > max)                               \
00884     goto err;                                           \
00885   if (ok) *ok = 1;                                      \
00886   if (next) *next = endptr;                             \
00887   return r;                                             \
00888  err:                                                   \
00889   if (ok) *ok = 0;                                      \
00890   if (next) *next = endptr;                             \
00891   return 0
00892 
00905 long
00906 tor_parse_long(const char *s, int base, long min, long max,
00907                int *ok, char **next)
00908 {
00909   char *endptr;
00910   long r;
00911 
00912   if (base < 0) {
00913     if (ok)
00914       *ok = 0;
00915     return 0;
00916   }
00917 
00918   errno = 0;
00919   r = strtol(s, &endptr, base);
00920   CHECK_STRTOX_RESULT();
00921 }
00922 
00924 unsigned long
00925 tor_parse_ulong(const char *s, int base, unsigned long min,
00926                 unsigned long max, int *ok, char **next)
00927 {
00928   char *endptr;
00929   unsigned long r;
00930 
00931   if (base < 0) {
00932     if (ok)
00933       *ok = 0;
00934     return 0;
00935   }
00936 
00937   errno = 0;
00938   r = strtoul(s, &endptr, base);
00939   CHECK_STRTOX_RESULT();
00940 }
00941 
00943 double
00944 tor_parse_double(const char *s, double min, double max, int *ok, char **next)
00945 {
00946   char *endptr;
00947   double r;
00948 
00949   errno = 0;
00950   r = strtod(s, &endptr);
00951   CHECK_STRTOX_RESULT();
00952 }
00953 
00956 uint64_t
00957 tor_parse_uint64(const char *s, int base, uint64_t min,
00958                  uint64_t max, int *ok, char **next)
00959 {
00960   char *endptr;
00961   uint64_t r;
00962 
00963   if (base < 0) {
00964     if (ok)
00965       *ok = 0;
00966     return 0;
00967   }
00968 
00969   errno = 0;
00970 #ifdef HAVE_STRTOULL
00971   r = (uint64_t)strtoull(s, &endptr, base);
00972 #elif defined(_WIN32)
00973 #if defined(_MSC_VER) && _MSC_VER < 1300
00974   tor_assert(base <= 10);
00975   r = (uint64_t)_atoi64(s);
00976   endptr = (char*)s;
00977   while (TOR_ISSPACE(*endptr)) endptr++;
00978   while (TOR_ISDIGIT(*endptr)) endptr++;
00979 #else
00980   r = (uint64_t)_strtoui64(s, &endptr, base);
00981 #endif
00982 #elif SIZEOF_LONG == 8
00983   r = (uint64_t)strtoul(s, &endptr, base);
00984 #else
00985 #error "I don't know how to parse 64-bit numbers."
00986 #endif
00987 
00988   CHECK_STRTOX_RESULT();
00989 }
00990 
00995 void
00996 base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
00997 {
00998   const char *end;
00999   char *cp;
01000 
01001   tor_assert(destlen >= srclen*2+1);
01002   tor_assert(destlen < SIZE_T_CEILING);
01003 
01004   cp = dest;
01005   end = src+srclen;
01006   while (src<end) {
01007     *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) >> 4 ];
01008     *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) & 0xf ];
01009     ++src;
01010   }
01011   *cp = '\0';
01012 }
01013 
01015 static INLINE int
01016 _hex_decode_digit(char c)
01017 {
01018   switch (c) {
01019     case '0': return 0;
01020     case '1': return 1;
01021     case '2': return 2;
01022     case '3': return 3;
01023     case '4': return 4;
01024     case '5': return 5;
01025     case '6': return 6;
01026     case '7': return 7;
01027     case '8': return 8;
01028     case '9': return 9;
01029     case 'A': case 'a': return 10;
01030     case 'B': case 'b': return 11;
01031     case 'C': case 'c': return 12;
01032     case 'D': case 'd': return 13;
01033     case 'E': case 'e': return 14;
01034     case 'F': case 'f': return 15;
01035     default:
01036       return -1;
01037   }
01038 }
01039 
01041 int
01042 hex_decode_digit(char c)
01043 {
01044   return _hex_decode_digit(c);
01045 }
01046 
01050 int
01051 base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
01052 {
01053   const char *end;
01054 
01055   int v1,v2;
01056   if ((srclen % 2) != 0)
01057     return -1;
01058   if (destlen < srclen/2 || destlen > SIZE_T_CEILING)
01059     return -1;
01060   end = src+srclen;
01061   while (src<end) {
01062     v1 = _hex_decode_digit(*src);
01063     v2 = _hex_decode_digit(*(src+1));
01064     if (v1<0||v2<0)
01065       return -1;
01066     *(uint8_t*)dest = (v1<<4)|v2;
01067     ++dest;
01068     src+=2;
01069   }
01070   return 0;
01071 }
01072 
01085 char *
01086 esc_for_log(const char *s)
01087 {
01088   const char *cp;
01089   char *result, *outp;
01090   size_t len = 3;
01091   if (!s) {
01092     return tor_strdup("(null)");
01093   }
01094 
01095   for (cp = s; *cp; ++cp) {
01096     switch (*cp) {
01097       case '\\':
01098       case '\"':
01099       case '\'':
01100       case '\r':
01101       case '\n':
01102       case '\t':
01103         len += 2;
01104         break;
01105       default:
01106         if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
01107           ++len;
01108         else
01109           len += 4;
01110         break;
01111     }
01112   }
01113 
01114   result = outp = tor_malloc(len);
01115   *outp++ = '\"';
01116   for (cp = s; *cp; ++cp) {
01117     switch (*cp) {
01118       case '\\':
01119       case '\"':
01120       case '\'':
01121         *outp++ = '\\';
01122         *outp++ = *cp;
01123         break;
01124       case '\n':
01125         *outp++ = '\\';
01126         *outp++ = 'n';
01127         break;
01128       case '\t':
01129         *outp++ = '\\';
01130         *outp++ = 't';
01131         break;
01132       case '\r':
01133         *outp++ = '\\';
01134         *outp++ = 'r';
01135         break;
01136       default:
01137         if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
01138           *outp++ = *cp;
01139         } else {
01140           tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
01141           outp += 4;
01142         }
01143         break;
01144     }
01145   }
01146 
01147   *outp++ = '\"';
01148   *outp++ = 0;
01149 
01150   return result;
01151 }
01152 
01160 const char *
01161 escaped(const char *s)
01162 {
01163   static char *_escaped_val = NULL;
01164   tor_free(_escaped_val);
01165 
01166   if (s)
01167     _escaped_val = esc_for_log(s);
01168   else
01169     _escaped_val = NULL;
01170 
01171   return _escaped_val;
01172 }
01173 
01180 /* This uses a stupid greedy wrapping algorithm right now:
01181  *  - For each line:
01182  *    - Try to fit as much stuff as possible, but break on a space.
01183  *    - If the first "word" of the line will extend beyond the allowable
01184  *      width, break the word at the end of the width.
01185  */
01186 void
01187 wrap_string(smartlist_t *out, const char *string, size_t width,
01188             const char *prefix0, const char *prefixRest)
01189 {
01190   size_t p0Len, pRestLen, pCurLen;
01191   const char *eos, *prefixCur;
01192   tor_assert(out);
01193   tor_assert(string);
01194   tor_assert(width);
01195   if (!prefix0)
01196     prefix0 = "";
01197   if (!prefixRest)
01198     prefixRest = "";
01199 
01200   p0Len = strlen(prefix0);
01201   pRestLen = strlen(prefixRest);
01202   tor_assert(width > p0Len && width > pRestLen);
01203   eos = strchr(string, '\0');
01204   tor_assert(eos);
01205   pCurLen = p0Len;
01206   prefixCur = prefix0;
01207 
01208   while ((eos-string)+pCurLen > width) {
01209     const char *eol = string + width - pCurLen;
01210     while (eol > string && *eol != ' ')
01211       --eol;
01212     /* eol is now the last space that can fit, or the start of the string. */
01213     if (eol > string) {
01214       size_t line_len = (eol-string) + pCurLen + 2;
01215       char *line = tor_malloc(line_len);
01216       memcpy(line, prefixCur, pCurLen);
01217       memcpy(line+pCurLen, string, eol-string);
01218       line[line_len-2] = '\n';
01219       line[line_len-1] = '\0';
01220       smartlist_add(out, line);
01221       string = eol + 1;
01222     } else {
01223       size_t line_len = width + 2;
01224       char *line = tor_malloc(line_len);
01225       memcpy(line, prefixCur, pCurLen);
01226       memcpy(line+pCurLen, string, width - pCurLen);
01227       line[line_len-2] = '\n';
01228       line[line_len-1] = '\0';
01229       smartlist_add(out, line);
01230       string += width-pCurLen;
01231     }
01232     prefixCur = prefixRest;
01233     pCurLen = pRestLen;
01234   }
01235 
01236   if (string < eos) {
01237     size_t line_len = (eos-string) + pCurLen + 2;
01238     char *line = tor_malloc(line_len);
01239     memcpy(line, prefixCur, pCurLen);
01240     memcpy(line+pCurLen, string, eos-string);
01241     line[line_len-2] = '\n';
01242     line[line_len-1] = '\0';
01243     smartlist_add(out, line);
01244   }
01245 }
01246 
01247 /* =====
01248  * Time
01249  * ===== */
01250 
01256 double
01257 tv_to_double(const struct timeval *tv)
01258 {
01259   double conv = tv->tv_sec;
01260   conv += tv->tv_usec/1000000.0;
01261   return conv;
01262 }
01263 
01267 int64_t
01268 tv_to_msec(const struct timeval *tv)
01269 {
01270   int64_t conv = ((int64_t)tv->tv_sec)*1000L;
01271   /* Round ghetto-style */
01272   conv += ((int64_t)tv->tv_usec+500)/1000L;
01273   return conv;
01274 }
01275 
01279 int64_t
01280 tv_to_usec(const struct timeval *tv)
01281 {
01282   int64_t conv = ((int64_t)tv->tv_sec)*1000000L;
01283   conv += tv->tv_usec;
01284   return conv;
01285 }
01286 
01289 long
01290 tv_udiff(const struct timeval *start, const struct timeval *end)
01291 {
01292   long udiff;
01293   long secdiff = end->tv_sec - start->tv_sec;
01294 
01295   if (labs(secdiff+1) > LONG_MAX/1000000) {
01296     log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
01297              "apart: %ld seconds", secdiff);
01298     return LONG_MAX;
01299   }
01300 
01301   udiff = secdiff*1000000L + (end->tv_usec - start->tv_usec);
01302   return udiff;
01303 }
01304 
01307 long
01308 tv_mdiff(const struct timeval *start, const struct timeval *end)
01309 {
01310   long mdiff;
01311   long secdiff = end->tv_sec - start->tv_sec;
01312 
01313   if (labs(secdiff+1) > LONG_MAX/1000) {
01314     log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
01315              "apart: %ld seconds", secdiff);
01316     return LONG_MAX;
01317   }
01318 
01319   /* Subtract and round */
01320   mdiff = secdiff*1000L +
01321       ((long)end->tv_usec - (long)start->tv_usec + 500L) / 1000L;
01322   return mdiff;
01323 }
01324 
01326 #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
01327 
01328 static int
01329 n_leapdays(int y1, int y2)
01330 {
01331   --y1;
01332   --y2;
01333   return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
01334 }
01336 static const int days_per_month[] =
01337   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
01338 
01342 time_t
01343 tor_timegm(struct tm *tm)
01344 {
01345   /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
01346    * It's way more brute-force than fiddling with tzset().
01347    */
01348   time_t year, days, hours, minutes, seconds;
01349   int i;
01350   year = tm->tm_year + 1900;
01351   if (year < 1970 || tm->tm_mon < 0 || tm->tm_mon > 11) {
01352     log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
01353     return -1;
01354   }
01355   tor_assert(year < INT_MAX);
01356   days = 365 * (year-1970) + n_leapdays(1970,(int)year);
01357   for (i = 0; i < tm->tm_mon; ++i)
01358     days += days_per_month[i];
01359   if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
01360     ++days;
01361   days += tm->tm_mday - 1;
01362   hours = days*24 + tm->tm_hour;
01363 
01364   minutes = hours*60 + tm->tm_min;
01365   seconds = minutes*60 + tm->tm_sec;
01366   return seconds;
01367 }
01368 
01369 /* strftime is locale-specific, so we need to replace those parts */
01370 
01372 static const char *WEEKDAY_NAMES[] =
01373   { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
01375 static const char *MONTH_NAMES[] =
01376   { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
01377     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
01378 
01384 void
01385 format_rfc1123_time(char *buf, time_t t)
01386 {
01387   struct tm tm;
01388 
01389   tor_gmtime_r(&t, &tm);
01390 
01391   strftime(buf, RFC1123_TIME_LEN+1, "___, %d ___ %Y %H:%M:%S GMT", &tm);
01392   tor_assert(tm.tm_wday >= 0);
01393   tor_assert(tm.tm_wday <= 6);
01394   memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3);
01395   tor_assert(tm.tm_mon >= 0);
01396   tor_assert(tm.tm_mon <= 11);
01397   memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
01398 }
01399 
01405 int
01406 parse_rfc1123_time(const char *buf, time_t *t)
01407 {
01408   struct tm tm;
01409   char month[4];
01410   char weekday[4];
01411   int i, m;
01412   unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
01413 
01414   if (strlen(buf) != RFC1123_TIME_LEN)
01415     return -1;
01416   memset(&tm, 0, sizeof(tm));
01417   if (tor_sscanf(buf, "%3s, %2u %3s %u %2u:%2u:%2u GMT", weekday,
01418              &tm_mday, month, &tm_year, &tm_hour,
01419              &tm_min, &tm_sec) < 7) {
01420     char *esc = esc_for_log(buf);
01421     log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
01422     tor_free(esc);
01423     return -1;
01424   }
01425   if (tm_mday < 1 || tm_mday > 31 || tm_hour > 23 || tm_min > 59 ||
01426       tm_sec > 60) {
01427     char *esc = esc_for_log(buf);
01428     log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
01429     tor_free(esc);
01430     return -1;
01431   }
01432   tm.tm_mday = (int)tm_mday;
01433   tm.tm_year = (int)tm_year;
01434   tm.tm_hour = (int)tm_hour;
01435   tm.tm_min = (int)tm_min;
01436   tm.tm_sec = (int)tm_sec;
01437 
01438   m = -1;
01439   for (i = 0; i < 12; ++i) {
01440     if (!strcmp(month, MONTH_NAMES[i])) {
01441       m = i;
01442       break;
01443     }
01444   }
01445   if (m<0) {
01446     char *esc = esc_for_log(buf);
01447     log_warn(LD_GENERAL, "Got invalid RFC1123 time %s: No such month", esc);
01448     tor_free(esc);
01449     return -1;
01450   }
01451   tm.tm_mon = m;
01452 
01453   if (tm.tm_year < 1970) {
01454     char *esc = esc_for_log(buf);
01455     log_warn(LD_GENERAL,
01456              "Got invalid RFC1123 time %s. (Before 1970)", esc);
01457     tor_free(esc);
01458     return -1;
01459   }
01460   tm.tm_year -= 1900;
01461 
01462   *t = tor_timegm(&tm);
01463   return 0;
01464 }
01465 
01471 void
01472 format_local_iso_time(char *buf, time_t t)
01473 {
01474   struct tm tm;
01475   strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_localtime_r(&t, &tm));
01476 }
01477 
01481 void
01482 format_iso_time(char *buf, time_t t)
01483 {
01484   struct tm tm;
01485   strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
01486 }
01487 
01490 void
01491 format_iso_time_nospace(char *buf, time_t t)
01492 {
01493   format_iso_time(buf, t);
01494   buf[10] = 'T';
01495 }
01496 
01500 void
01501 format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
01502 {
01503   tor_assert(tv);
01504   format_iso_time_nospace(buf, tv->tv_sec);
01505   tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec);
01506 }
01507 
01512 int
01513 parse_iso_time(const char *cp, time_t *t)
01514 {
01515   struct tm st_tm;
01516   unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
01517   if (tor_sscanf(cp, "%u-%2u-%2u %2u:%2u:%2u", &year, &month,
01518                 &day, &hour, &minute, &second) < 6) {
01519     char *esc = esc_for_log(cp);
01520     log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
01521     tor_free(esc);
01522     return -1;
01523   }
01524   if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
01525           hour > 23 || minute > 59 || second > 60) {
01526     char *esc = esc_for_log(cp);
01527     log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc);
01528     tor_free(esc);
01529     return -1;
01530   }
01531   st_tm.tm_year = year-1900;
01532   st_tm.tm_mon = month-1;
01533   st_tm.tm_mday = day;
01534   st_tm.tm_hour = hour;
01535   st_tm.tm_min = minute;
01536   st_tm.tm_sec = second;
01537 
01538   if (st_tm.tm_year < 70) {
01539     char *esc = esc_for_log(cp);
01540     log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
01541     tor_free(esc);
01542     return -1;
01543   }
01544   *t = tor_timegm(&st_tm);
01545   return 0;
01546 }
01547 
01550 int
01551 parse_http_time(const char *date, struct tm *tm)
01552 {
01553   const char *cp;
01554   char month[4];
01555   char wkday[4];
01556   int i;
01557   unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
01558 
01559   tor_assert(tm);
01560   memset(tm, 0, sizeof(*tm));
01561 
01562   /* First, try RFC1123 or RFC850 format: skip the weekday.  */
01563   if ((cp = strchr(date, ','))) {
01564     ++cp;
01565     if (*cp != ' ')
01566       return -1;
01567     ++cp;
01568     if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT",
01569                &tm_mday, month, &tm_year,
01570                &tm_hour, &tm_min, &tm_sec) == 6) {
01571       /* rfc1123-date */
01572       tm_year -= 1900;
01573     } else if (tor_sscanf(cp, "%2u-%3s-%2u %2u:%2u:%2u GMT",
01574                       &tm_mday, month, &tm_year,
01575                       &tm_hour, &tm_min, &tm_sec) == 6) {
01576       /* rfc850-date */
01577     } else {
01578       return -1;
01579     }
01580   } else {
01581     /* No comma; possibly asctime() format. */
01582     if (tor_sscanf(date, "%3s %3s %2u %2u:%2u:%2u %4u",
01583                wkday, month, &tm_mday,
01584                &tm_hour, &tm_min, &tm_sec, &tm_year) == 7) {
01585       tm_year -= 1900;
01586     } else {
01587       return -1;
01588     }
01589   }
01590   tm->tm_mday = (int)tm_mday;
01591   tm->tm_year = (int)tm_year;
01592   tm->tm_hour = (int)tm_hour;
01593   tm->tm_min = (int)tm_min;
01594   tm->tm_sec = (int)tm_sec;
01595 
01596   month[3] = '\0';
01597   /* Okay, now decode the month. */
01598   /* set tm->tm_mon to dummy value so the check below fails. */
01599   tm->tm_mon = -1;
01600   for (i = 0; i < 12; ++i) {
01601     if (!strcasecmp(MONTH_NAMES[i], month)) {
01602       tm->tm_mon = i;
01603     }
01604   }
01605 
01606   if (tm->tm_year < 0 ||
01607       tm->tm_mon < 0  || tm->tm_mon > 11 ||
01608       tm->tm_mday < 1 || tm->tm_mday > 31 ||
01609       tm->tm_hour < 0 || tm->tm_hour > 23 ||
01610       tm->tm_min < 0  || tm->tm_min > 59 ||
01611       tm->tm_sec < 0  || tm->tm_sec > 60)
01612     return -1; /* Out of range, or bad month. */
01613 
01614   return 0;
01615 }
01616 
01621 int
01622 format_time_interval(char *out, size_t out_len, long interval)
01623 {
01624   /* We only report seconds if there's no hours. */
01625   long sec = 0, min = 0, hour = 0, day = 0;
01626   if (interval < 0)
01627     interval = -interval;
01628 
01629   if (interval >= 86400) {
01630     day = interval / 86400;
01631     interval %= 86400;
01632   }
01633   if (interval >= 3600) {
01634     hour = interval / 3600;
01635     interval %= 3600;
01636   }
01637   if (interval >= 60) {
01638     min = interval / 60;
01639     interval %= 60;
01640   }
01641   sec = interval;
01642 
01643   if (day) {
01644     return tor_snprintf(out, out_len, "%ld days, %ld hours, %ld minutes",
01645                         day, hour, min);
01646   } else if (hour) {
01647     return tor_snprintf(out, out_len, "%ld hours, %ld minutes", hour, min);
01648   } else if (min) {
01649     return tor_snprintf(out, out_len, "%ld minutes, %ld seconds", min, sec);
01650   } else {
01651     return tor_snprintf(out, out_len, "%ld seconds", sec);
01652   }
01653 }
01654 
01655 /* =====
01656  * Cached time
01657  * ===== */
01658 
01659 #ifndef TIME_IS_FAST
01660 
01664 static time_t cached_approx_time = 0;
01665 
01670 time_t
01671 approx_time(void)
01672 {
01673   return cached_approx_time;
01674 }
01675 
01679 void
01680 update_approx_time(time_t now)
01681 {
01682   cached_approx_time = now;
01683 }
01684 #endif
01685 
01686 /* =====
01687  * Rate limiting
01688  * ===== */
01689 
01693 static int
01694 rate_limit_is_ready(ratelim_t *lim, time_t now)
01695 {
01696   if (lim->rate + lim->last_allowed <= now) {
01697     int res = lim->n_calls_since_last_time + 1;
01698     lim->last_allowed = now;
01699     lim->n_calls_since_last_time = 0;
01700     return res;
01701   } else {
01702     ++lim->n_calls_since_last_time;
01703     return 0;
01704   }
01705 }
01706 
01710 char *
01711 rate_limit_log(ratelim_t *lim, time_t now)
01712 {
01713   int n;
01714   if ((n = rate_limit_is_ready(lim, now))) {
01715     if (n == 1) {
01716       return tor_strdup("");
01717     } else {
01718       char *cp=NULL;
01719       tor_asprintf(&cp,
01720                    " [%d similar message(s) suppressed in last %d seconds]",
01721                    n-1, lim->rate);
01722       return cp;
01723     }
01724   } else {
01725     return NULL;
01726   }
01727 }
01728 
01729 /* =====
01730  * File helpers
01731  * ===== */
01732 
01737 ssize_t
01738 write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket)
01739 {
01740   size_t written = 0;
01741   ssize_t result;
01742   tor_assert(count < SSIZE_T_MAX);
01743 
01744   while (written != count) {
01745     if (isSocket)
01746       result = tor_socket_send(fd, buf+written, count-written, 0);
01747     else
01748       result = write((int)fd, buf+written, count-written);
01749     if (result<0)
01750       return -1;
01751     written += result;
01752   }
01753   return (ssize_t)count;
01754 }
01755 
01761 ssize_t
01762 read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
01763 {
01764   size_t numread = 0;
01765   ssize_t result;
01766 
01767   if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
01768     return -1;
01769 
01770   while (numread != count) {
01771     if (isSocket)
01772       result = tor_socket_recv(fd, buf+numread, count-numread, 0);
01773     else
01774       result = read((int)fd, buf+numread, count-numread);
01775     if (result<0)
01776       return -1;
01777     else if (result == 0)
01778       break;
01779     numread += result;
01780   }
01781   return (ssize_t)numread;
01782 }
01783 
01784 /*
01785  *    Filesystem operations.
01786  */
01787 
01791 static void
01792 clean_name_for_stat(char *name)
01793 {
01794 #ifdef _WIN32
01795   size_t len = strlen(name);
01796   if (!len)
01797     return;
01798   if (name[len-1]=='\\' || name[len-1]=='/') {
01799     if (len == 1 || (len==3 && name[1]==':'))
01800       return;
01801     name[len-1]='\0';
01802   }
01803 #else
01804   (void)name;
01805 #endif
01806 }
01807 
01811 file_status_t
01812 file_status(const char *fname)
01813 {
01814   struct stat st;
01815   char *f;
01816   int r;
01817   f = tor_strdup(fname);
01818   clean_name_for_stat(f);
01819   r = stat(f, &st);
01820   tor_free(f);
01821   if (r) {
01822     if (errno == ENOENT) {
01823       return FN_NOENT;
01824     }
01825     return FN_ERROR;
01826   }
01827   if (st.st_mode & S_IFDIR)
01828     return FN_DIR;
01829   else if (st.st_mode & S_IFREG)
01830     return FN_FILE;
01831   else
01832     return FN_ERROR;
01833 }
01834 
01846 int
01847 check_private_dir(const char *dirname, cpd_check_t check,
01848                   const char *effective_user)
01849 {
01850   int r;
01851   struct stat st;
01852   char *f;
01853 #ifndef _WIN32
01854   int mask;
01855   struct passwd *pw = NULL;
01856   uid_t running_uid;
01857   gid_t running_gid;
01858 #else
01859   (void)effective_user;
01860 #endif
01861 
01862   tor_assert(dirname);
01863   f = tor_strdup(dirname);
01864   clean_name_for_stat(f);
01865   r = stat(f, &st);
01866   tor_free(f);
01867   if (r) {
01868     if (errno != ENOENT) {
01869       log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
01870                strerror(errno));
01871       return -1;
01872     }
01873     if (check & CPD_CREATE) {
01874       log_info(LD_GENERAL, "Creating directory %s", dirname);
01875 #if defined (_WIN32) && !defined (WINCE)
01876       r = mkdir(dirname);
01877 #else
01878       r = mkdir(dirname, 0700);
01879 #endif
01880       if (r) {
01881         log_warn(LD_FS, "Error creating directory %s: %s", dirname,
01882             strerror(errno));
01883         return -1;
01884       }
01885     } else if (!(check & CPD_CHECK)) {
01886       log_warn(LD_FS, "Directory %s does not exist.", dirname);
01887       return -1;
01888     }
01889     /* XXXX In the case where check==CPD_CHECK, we should look at the
01890      * parent directory a little harder. */
01891     return 0;
01892   }
01893   if (!(st.st_mode & S_IFDIR)) {
01894     log_warn(LD_FS, "%s is not a directory", dirname);
01895     return -1;
01896   }
01897 #ifndef _WIN32
01898   if (effective_user) {
01899     /* Look up the user and group information.
01900      * If we have a problem, bail out. */
01901     pw = getpwnam(effective_user);
01902     if (pw == NULL) {
01903       log_warn(LD_CONFIG, "Error setting configured user: %s not found",
01904                effective_user);
01905       return -1;
01906     }
01907     running_uid = pw->pw_uid;
01908     running_gid = pw->pw_gid;
01909   } else {
01910     running_uid = getuid();
01911     running_gid = getgid();
01912   }
01913 
01914   if (st.st_uid != running_uid) {
01915     struct passwd *pw = NULL;
01916     char *process_ownername = NULL;
01917 
01918     pw = getpwuid(running_uid);
01919     process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>");
01920 
01921     pw = getpwuid(st.st_uid);
01922 
01923     log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
01924         "%s (%d). Perhaps you are running Tor as the wrong user?",
01925                          dirname, process_ownername, (int)running_uid,
01926                          pw ? pw->pw_name : "<unknown>", (int)st.st_uid);
01927 
01928     tor_free(process_ownername);
01929     return -1;
01930   }
01931   if ((check & CPD_GROUP_OK) && st.st_gid != running_gid) {
01932     struct group *gr;
01933     char *process_groupname = NULL;
01934     gr = getgrgid(running_gid);
01935     process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
01936     gr = getgrgid(st.st_gid);
01937 
01938     log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
01939              "%s (%d).  Are you running Tor as the wrong user?",
01940              dirname, process_groupname, (int)running_gid,
01941              gr ?  gr->gr_name : "<unknown>", (int)st.st_gid);
01942 
01943     tor_free(process_groupname);
01944     return -1;
01945   }
01946   if (check & CPD_GROUP_OK) {
01947     mask = 0027;
01948   } else {
01949     mask = 0077;
01950   }
01951   if (st.st_mode & mask) {
01952     unsigned new_mode;
01953     if (check & CPD_CHECK_MODE_ONLY) {
01954       log_warn(LD_FS, "Permissions on directory %s are too permissive.",
01955                dirname);
01956       return -1;
01957     }
01958     log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
01959     new_mode = st.st_mode;
01960     new_mode |= 0700; /* Owner should have rwx */
01961     new_mode &= ~mask; /* Clear the other bits that we didn't want set...*/
01962     if (chmod(dirname, new_mode)) {
01963       log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
01964           strerror(errno));
01965       return -1;
01966     } else {
01967       return 0;
01968     }
01969   }
01970 #endif
01971   return 0;
01972 }
01973 
01981 int
01982 write_str_to_file(const char *fname, const char *str, int bin)
01983 {
01984 #ifdef _WIN32
01985   if (!bin && strchr(str, '\r')) {
01986     log_warn(LD_BUG,
01987              "We're writing a text string that already contains a CR.");
01988   }
01989 #endif
01990   return write_bytes_to_file(fname, str, strlen(str), bin);
01991 }
01992 
01996 struct open_file_t {
01997   char *tempname; 
01998   char *filename; 
01999   unsigned rename_on_close:1; 
02000   unsigned binary:1; 
02001   int fd; 
02002   FILE *stdio_file; 
02003 };
02004 
02023 int
02024 start_writing_to_file(const char *fname, int open_flags, int mode,
02025                       open_file_t **data_out)
02026 {
02027   open_file_t *new_file = tor_malloc_zero(sizeof(open_file_t));
02028   const char *open_name;
02029   int append = 0;
02030 
02031   tor_assert(fname);
02032   tor_assert(data_out);
02033 #if (O_BINARY != 0 && O_TEXT != 0)
02034   tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
02035 #endif
02036   new_file->fd = -1;
02037   new_file->filename = tor_strdup(fname);
02038   if (open_flags & O_APPEND) {
02039     open_name = fname;
02040     new_file->rename_on_close = 0;
02041     append = 1;
02042     open_flags &= ~O_APPEND;
02043   } else {
02044     tor_asprintf(&new_file->tempname, "%s.tmp", fname);
02045     open_name = new_file->tempname;
02046     /* We always replace an existing temporary file if there is one. */
02047     open_flags |= O_CREAT|O_TRUNC;
02048     open_flags &= ~O_EXCL;
02049     new_file->rename_on_close = 1;
02050   }
02051   if (open_flags & O_BINARY)
02052     new_file->binary = 1;
02053 
02054   new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
02055   if (new_file->fd < 0) {
02056     log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
02057         open_name, fname, strerror(errno));
02058     goto err;
02059   }
02060   if (append) {
02061     if (tor_fd_seekend(new_file->fd) < 0) {
02062       log_warn(LD_FS, "Couldn't seek to end of file \"%s\": %s", open_name,
02063                strerror(errno));
02064       goto err;
02065     }
02066   }
02067 
02068   *data_out = new_file;
02069 
02070   return new_file->fd;
02071 
02072  err:
02073   if (new_file->fd >= 0)
02074     close(new_file->fd);
02075   *data_out = NULL;
02076   tor_free(new_file->filename);
02077   tor_free(new_file->tempname);
02078   tor_free(new_file);
02079   return -1;
02080 }
02081 
02085 FILE *
02086 fdopen_file(open_file_t *file_data)
02087 {
02088   tor_assert(file_data);
02089   if (file_data->stdio_file)
02090     return file_data->stdio_file;
02091   tor_assert(file_data->fd >= 0);
02092   if (!(file_data->stdio_file = fdopen(file_data->fd,
02093                                        file_data->binary?"ab":"a"))) {
02094     log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
02095              file_data->fd, strerror(errno));
02096   }
02097   return file_data->stdio_file;
02098 }
02099 
02102 FILE *
02103 start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
02104                             open_file_t **data_out)
02105 {
02106   FILE *res;
02107   if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
02108     return NULL;
02109   if (!(res = fdopen_file(*data_out))) {
02110     abort_writing_to_file(*data_out);
02111     *data_out = NULL;
02112   }
02113   return res;
02114 }
02115 
02120 static int
02121 finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
02122 {
02123   int r = 0;
02124   tor_assert(file_data && file_data->filename);
02125   if (file_data->stdio_file) {
02126     if (fclose(file_data->stdio_file)) {
02127       log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
02128                strerror(errno));
02129       abort_write = r = -1;
02130     }
02131   } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
02132     log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
02133              strerror(errno));
02134     abort_write = r = -1;
02135   }
02136 
02137   if (file_data->rename_on_close) {
02138     tor_assert(file_data->tempname && file_data->filename);
02139     if (abort_write) {
02140       unlink(file_data->tempname);
02141     } else {
02142       tor_assert(strcmp(file_data->filename, file_data->tempname));
02143       if (replace_file(file_data->tempname, file_data->filename)) {
02144         log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
02145                  strerror(errno));
02146         r = -1;
02147       }
02148     }
02149   }
02150 
02151   tor_free(file_data->filename);
02152   tor_free(file_data->tempname);
02153   tor_free(file_data);
02154 
02155   return r;
02156 }
02157 
02161 int
02162 finish_writing_to_file(open_file_t *file_data)
02163 {
02164   return finish_writing_to_file_impl(file_data, 0);
02165 }
02166 
02169 int
02170 abort_writing_to_file(open_file_t *file_data)
02171 {
02172   return finish_writing_to_file_impl(file_data, 1);
02173 }
02174 
02179 static int
02180 write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
02181                           int open_flags)
02182 {
02183   open_file_t *file = NULL;
02184   int fd;
02185   ssize_t result;
02186   fd = start_writing_to_file(fname, open_flags, 0600, &file);
02187   if (fd<0)
02188     return -1;
02189   SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
02190   {
02191     result = write_all(fd, chunk->bytes, chunk->len, 0);
02192     if (result < 0) {
02193       log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
02194           strerror(errno));
02195       goto err;
02196     }
02197     tor_assert((size_t)result == chunk->len);
02198   });
02199 
02200   return finish_writing_to_file(file);
02201  err:
02202   abort_writing_to_file(file);
02203   return -1;
02204 }
02205 
02208 int
02209 write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin)
02210 {
02211   int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
02212   return write_chunks_to_file_impl(fname, chunks, flags);
02213 }
02214 
02217 static int
02218 write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
02219                          int flags)
02220 {
02221   int r;
02222   sized_chunk_t c = { str, len };
02223   smartlist_t *chunks = smartlist_new();
02224   smartlist_add(chunks, &c);
02225   r = write_chunks_to_file_impl(fname, chunks, flags);
02226   smartlist_free(chunks);
02227   return r;
02228 }
02229 
02232 int
02233 write_bytes_to_file(const char *fname, const char *str, size_t len,
02234                     int bin)
02235 {
02236   return write_bytes_to_file_impl(fname, str, len,
02237                                   OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
02238 }
02239 
02242 int
02243 append_bytes_to_file(const char *fname, const char *str, size_t len,
02244                      int bin)
02245 {
02246   return write_bytes_to_file_impl(fname, str, len,
02247                                   OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
02248 }
02249 
02252 int
02253 write_bytes_to_new_file(const char *fname, const char *str, size_t len,
02254                         int bin)
02255 {
02256   return write_bytes_to_file_impl(fname, str, len,
02257                                   OPEN_FLAGS_DONT_REPLACE|
02258                                   (bin?O_BINARY:O_TEXT));
02259 }
02260 
02271 /*
02272  * This function <em>may</em> return an erroneous result if the file
02273  * is modified while it is running, but must not crash or overflow.
02274  * Right now, the error case occurs when the file length grows between
02275  * the call to stat and the call to read_all: the resulting string will
02276  * be truncated.
02277  */
02278 char *
02279 read_file_to_str(const char *filename, int flags, struct stat *stat_out)
02280 {
02281   int fd; /* router file */
02282   struct stat statbuf;
02283   char *string;
02284   ssize_t r;
02285   int bin = flags & RFTS_BIN;
02286 
02287   tor_assert(filename);
02288 
02289   fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
02290   if (fd<0) {
02291     int severity = LOG_WARN;
02292     int save_errno = errno;
02293     if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
02294       severity = LOG_INFO;
02295     log_fn(severity, LD_FS,"Could not open \"%s\": %s",filename,
02296            strerror(errno));
02297     errno = save_errno;
02298     return NULL;
02299   }
02300 
02301   if (fstat(fd, &statbuf)<0) {
02302     int save_errno = errno;
02303     close(fd);
02304     log_warn(LD_FS,"Could not fstat \"%s\".",filename);
02305     errno = save_errno;
02306     return NULL;
02307   }
02308 
02309   if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING)
02310     return NULL;
02311 
02312   string = tor_malloc((size_t)(statbuf.st_size+1));
02313 
02314   r = read_all(fd,string,(size_t)statbuf.st_size,0);
02315   if (r<0) {
02316     int save_errno = errno;
02317     log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
02318              strerror(errno));
02319     tor_free(string);
02320     close(fd);
02321     errno = save_errno;
02322     return NULL;
02323   }
02324   string[r] = '\0'; /* NUL-terminate the result. */
02325 
02326 #ifdef _WIN32
02327   if (!bin && strchr(string, '\r')) {
02328     log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
02329               "when reading %s. Coping.",
02330               filename);
02331     tor_strstrip(string, "\r");
02332     r = strlen(string);
02333   }
02334   if (!bin) {
02335     statbuf.st_size = (size_t) r;
02336   } else
02337 #endif
02338     if (r != statbuf.st_size) {
02339       /* Unless we're using text mode on win32, we'd better have an exact
02340        * match for size. */
02341       int save_errno = errno;
02342       log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
02343                (int)r, (long)statbuf.st_size,filename);
02344       tor_free(string);
02345       close(fd);
02346       errno = save_errno;
02347       return NULL;
02348     }
02349   close(fd);
02350   if (stat_out) {
02351     memcpy(stat_out, &statbuf, sizeof(struct stat));
02352   }
02353 
02354   return string;
02355 }
02356 
02357 #define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
02358 
02365 static const char *
02366 unescape_string(const char *s, char **result, size_t *size_out)
02367 {
02368   const char *cp;
02369   char *out;
02370   if (s[0] != '\"')
02371     return NULL;
02372   cp = s+1;
02373   while (1) {
02374     switch (*cp) {
02375       case '\0':
02376       case '\n':
02377         return NULL;
02378       case '\"':
02379         goto end_of_loop;
02380       case '\\':
02381         if (cp[1] == 'x' || cp[1] == 'X') {
02382           if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
02383             return NULL;
02384           cp += 4;
02385         } else if (TOR_ISODIGIT(cp[1])) {
02386           cp += 2;
02387           if (TOR_ISODIGIT(*cp)) ++cp;
02388           if (TOR_ISODIGIT(*cp)) ++cp;
02389         } else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"'
02390                    || cp[1] == '\\' || cp[1] == '\'') {
02391           cp += 2;
02392         } else {
02393           return NULL;
02394         }
02395         break;
02396       default:
02397         ++cp;
02398         break;
02399     }
02400   }
02401  end_of_loop:
02402   out = *result = tor_malloc(cp-s + 1);
02403   cp = s+1;
02404   while (1) {
02405     switch (*cp)
02406       {
02407       case '\"':
02408         *out = '\0';
02409         if (size_out) *size_out = out - *result;
02410         return cp+1;
02411       case '\0':
02412         tor_fragile_assert();
02413         tor_free(*result);
02414         return NULL;
02415       case '\\':
02416         switch (cp[1])
02417           {
02418           case 'n': *out++ = '\n'; cp += 2; break;
02419           case 'r': *out++ = '\r'; cp += 2; break;
02420           case 't': *out++ = '\t'; cp += 2; break;
02421           case 'x': case 'X':
02422             {
02423               int x1, x2;
02424 
02425               x1 = hex_decode_digit(cp[2]);
02426               x2 = hex_decode_digit(cp[3]);
02427               if (x1 == -1 || x2 == -1) {
02428                   tor_free(*result);
02429                   return NULL;
02430               }
02431 
02432               *out++ = ((x1<<4) + x2);
02433               cp += 4;
02434             }
02435             break;
02436           case '0': case '1': case '2': case '3': case '4': case '5':
02437           case '6': case '7':
02438             {
02439               int n = cp[1]-'0';
02440               cp += 2;
02441               if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
02442               if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
02443               if (n > 255) { tor_free(*result); return NULL; }
02444               *out++ = (char)n;
02445             }
02446             break;
02447           case '\'':
02448           case '\"':
02449           case '\\':
02450           case '\?':
02451             *out++ = cp[1];
02452             cp += 2;
02453             break;
02454           default:
02455             tor_free(*result); return NULL;
02456           }
02457         break;
02458       default:
02459         *out++ = *cp++;
02460       }
02461   }
02462 }
02463 
02472 const char *
02473 parse_config_line_from_str(const char *line, char **key_out, char **value_out)
02474 {
02475   /* I believe the file format here is supposed to be:
02476      FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)?
02477 
02478      EMPTYLASTLINE = SPACE* | COMMENT
02479      EMPTYLINE = EMPTYLASTLINE NL
02480      SPACE = ' ' | '\r' | '\t'
02481      COMMENT = '#' NOT-NL*
02482      NOT-NL = Any character except '\n'
02483      NL = '\n'
02484 
02485      LASTLINE = SPACE* KEY SPACE* VALUES
02486      LINE = LASTLINE NL
02487      KEY = KEYCHAR+
02488      KEYCHAR = Any character except ' ', '\r', '\n', '\t', '#', "\"
02489 
02490      VALUES = QUOTEDVALUE | NORMALVALUE
02491      QUOTEDVALUE = QUOTE QVCHAR* QUOTE EOLSPACE?
02492      QUOTE = '"'
02493      QVCHAR = KEYCHAR | ESC ('n' | 't' | 'r' | '"' | ESC |'\'' | OCTAL | HEX)
02494      ESC = "\\"
02495      OCTAL = ODIGIT (ODIGIT ODIGIT?)?
02496      HEX = ('x' | 'X') HEXDIGIT HEXDIGIT
02497      ODIGIT = '0' .. '7'
02498      HEXDIGIT = '0'..'9' | 'a' .. 'f' | 'A' .. 'F'
02499      EOLSPACE = SPACE* COMMENT?
02500 
02501      NORMALVALUE = (VALCHAR | ESC ESC_IGNORE | CONTINUATION)* EOLSPACE?
02502      VALCHAR = Any character except ESC, '#', and '\n'
02503      ESC_IGNORE = Any character except '#' or '\n'
02504      CONTINUATION = ESC NL ( COMMENT NL )*
02505    */
02506 
02507   const char *key, *val, *cp;
02508   int continuation = 0;
02509 
02510   tor_assert(key_out);
02511   tor_assert(value_out);
02512 
02513   *key_out = *value_out = NULL;
02514   key = val = NULL;
02515   /* Skip until the first keyword. */
02516   while (1) {
02517     while (TOR_ISSPACE(*line))
02518       ++line;
02519     if (*line == '#') {
02520       while (*line && *line != '\n')
02521         ++line;
02522     } else {
02523       break;
02524     }
02525   }
02526 
02527   if (!*line) { /* End of string? */
02528     *key_out = *value_out = NULL;
02529     return line;
02530   }
02531 
02532   /* Skip until the next space or \ followed by newline. */
02533   key = line;
02534   while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
02535          ! (line[0] == '\\' && line[1] == '\n'))
02536     ++line;
02537   *key_out = tor_strndup(key, line-key);
02538 
02539   /* Skip until the value. */
02540   while (*line == ' ' || *line == '\t')
02541     ++line;
02542 
02543   val = line;
02544 
02545   /* Find the end of the line. */
02546   if (*line == '\"') { // XXX No continuation handling is done here
02547     if (!(line = unescape_string(line, value_out, NULL)))
02548        return NULL;
02549     while (*line == ' ' || *line == '\t')
02550       ++line;
02551     if (*line && *line != '#' && *line != '\n')
02552       return NULL;
02553   } else {
02554     /* Look for the end of the line. */
02555     while (*line && *line != '\n' && (*line != '#' || continuation)) {
02556       if (*line == '\\' && line[1] == '\n') {
02557         continuation = 1;
02558         line += 2;
02559       } else if (*line == '#') {
02560         do {
02561           ++line;
02562         } while (*line && *line != '\n');
02563         if (*line == '\n')
02564           ++line;
02565       } else {
02566         ++line;
02567       }
02568     }
02569 
02570     if (*line == '\n') {
02571       cp = line++;
02572     } else {
02573       cp = line;
02574     }
02575     /* Now back cp up to be the last nonspace character */
02576     while (cp>val && TOR_ISSPACE(*(cp-1)))
02577       --cp;
02578 
02579     tor_assert(cp >= val);
02580 
02581     /* Now copy out and decode the value. */
02582     *value_out = tor_strndup(val, cp-val);
02583     if (continuation) {
02584       char *v_out, *v_in;
02585       v_out = v_in = *value_out;
02586       while (*v_in) {
02587         if (*v_in == '#') {
02588           do {
02589             ++v_in;
02590           } while (*v_in && *v_in != '\n');
02591           if (*v_in == '\n')
02592             ++v_in;
02593         } else if (v_in[0] == '\\' && v_in[1] == '\n') {
02594           v_in += 2;
02595         } else {
02596           *v_out++ = *v_in++;
02597         }
02598       }
02599       *v_out = '\0';
02600     }
02601   }
02602 
02603   if (*line == '#') {
02604     do {
02605       ++line;
02606     } while (*line && *line != '\n');
02607   }
02608   while (TOR_ISSPACE(*line)) ++line;
02609 
02610   return line;
02611 }
02612 
02615 char *
02616 expand_filename(const char *filename)
02617 {
02618   tor_assert(filename);
02619 #ifdef _WIN32
02620   return tor_strdup(filename);
02621 #else
02622   if (*filename == '~') {
02623     char *home, *result=NULL;
02624     const char *rest;
02625 
02626     if (filename[1] == '/' || filename[1] == '\0') {
02627       home = getenv("HOME");
02628       if (!home) {
02629         log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
02630                  "expanding \"%s\"; defaulting to \"\".", filename);
02631         home = tor_strdup("");
02632       } else {
02633         home = tor_strdup(home);
02634       }
02635       rest = strlen(filename)>=2?(filename+2):"";
02636     } else {
02637 #ifdef HAVE_PWD_H
02638       char *username, *slash;
02639       slash = strchr(filename, '/');
02640       if (slash)
02641         username = tor_strndup(filename+1,slash-filename-1);
02642       else
02643         username = tor_strdup(filename+1);
02644       if (!(home = get_user_homedir(username))) {
02645         log_warn(LD_CONFIG,"Couldn't get homedir for \"%s\"",username);
02646         tor_free(username);
02647         return NULL;
02648       }
02649       tor_free(username);
02650       rest = slash ? (slash+1) : "";
02651 #else
02652       log_warn(LD_CONFIG, "Couldn't expend homedir on system without pwd.h");
02653       return tor_strdup(filename);
02654 #endif
02655     }
02656     tor_assert(home);
02657     /* Remove trailing slash. */
02658     if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
02659       home[strlen(home)-1] = '\0';
02660     }
02661     tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest);
02662     tor_free(home);
02663     return result;
02664   } else {
02665     return tor_strdup(filename);
02666   }
02667 #endif
02668 }
02669 
02670 #define MAX_SCANF_WIDTH 9999
02671 
02674 static int
02675 digit_to_num(char d)
02676 {
02677   int num = ((int)d) - (int)'0';
02678   tor_assert(num <= 9 && num >= 0);
02679   return num;
02680 }
02681 
02686 static int
02687 scan_unsigned(const char **bufp, unsigned *out, int width, int base)
02688 {
02689   unsigned result = 0;
02690   int scanned_so_far = 0;
02691   const int hex = base==16;
02692   tor_assert(base == 10 || base == 16);
02693   if (!bufp || !*bufp || !out)
02694     return -1;
02695   if (width<0)
02696     width=MAX_SCANF_WIDTH;
02697 
02698   while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
02699          && scanned_so_far < width) {
02700     int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
02701     unsigned new_result = result * base + digit;
02702     if (new_result > UINT32_MAX || new_result < result)
02703       return -1; /* over/underflow. */
02704     result = new_result;
02705     ++scanned_so_far;
02706   }
02707 
02708   if (!scanned_so_far) /* No actual digits scanned */
02709     return -1;
02710 
02711   *out = result;
02712   return 0;
02713 }
02714 
02718 static int
02719 scan_string(const char **bufp, char *out, int width)
02720 {
02721   int scanned_so_far = 0;
02722   if (!bufp || !out || width < 0)
02723     return -1;
02724   while (**bufp && ! TOR_ISSPACE(**bufp) && scanned_so_far < width) {
02725     *out++ = *(*bufp)++;
02726     ++scanned_so_far;
02727   }
02728   *out = '\0';
02729   return 0;
02730 }
02731 
02735 int
02736 tor_vsscanf(const char *buf, const char *pattern, va_list ap)
02737 {
02738   int n_matched = 0;
02739 
02740   while (*pattern) {
02741     if (*pattern != '%') {
02742       if (*buf == *pattern) {
02743         ++buf;
02744         ++pattern;
02745         continue;
02746       } else {
02747         return n_matched;
02748       }
02749     } else {
02750       int width = -1;
02751       ++pattern;
02752       if (TOR_ISDIGIT(*pattern)) {
02753         width = digit_to_num(*pattern++);
02754         while (TOR_ISDIGIT(*pattern)) {
02755           width *= 10;
02756           width += digit_to_num(*pattern++);
02757           if (width > MAX_SCANF_WIDTH)
02758             return -1;
02759         }
02760         if (!width) /* No zero-width things. */
02761           return -1;
02762       }
02763       if (*pattern == 'u' || *pattern == 'x') {
02764         unsigned *u = va_arg(ap, unsigned *);
02765         const int base = (*pattern == 'u') ? 10 : 16;
02766         if (!*buf)
02767           return n_matched;
02768         if (scan_unsigned(&buf, u, width, base)<0)
02769           return n_matched;
02770         ++pattern;
02771         ++n_matched;
02772       } else if (*pattern == 's') {
02773         char *s = va_arg(ap, char *);
02774         if (width < 0)
02775           return -1;
02776         if (scan_string(&buf, s, width)<0)
02777           return n_matched;
02778         ++pattern;
02779         ++n_matched;
02780       } else if (*pattern == 'c') {
02781         char *ch = va_arg(ap, char *);
02782         if (width != -1)
02783           return -1;
02784         if (!*buf)
02785           return n_matched;
02786         *ch = *buf++;
02787         ++pattern;
02788         ++n_matched;
02789       } else if (*pattern == '%') {
02790         if (*buf != '%')
02791           return n_matched;
02792         ++buf;
02793         ++pattern;
02794       } else {
02795         return -1; /* Unrecognized pattern component. */
02796       }
02797     }
02798   }
02799 
02800   return n_matched;
02801 }
02802 
02813 int
02814 tor_sscanf(const char *buf, const char *pattern, ...)
02815 {
02816   int r;
02817   va_list ap;
02818   va_start(ap, pattern);
02819   r = tor_vsscanf(buf, pattern, ap);
02820   va_end(ap);
02821   return r;
02822 }
02823 
02826 void
02827 smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
02828 {
02829   va_list ap;
02830   va_start(ap, pattern);
02831   smartlist_add_vasprintf(sl, pattern, ap);
02832   va_end(ap);
02833 }
02834 
02836 void
02837 smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
02838                         va_list args)
02839 {
02840   char *str = NULL;
02841 
02842   tor_vasprintf(&str, pattern, args);
02843   tor_assert(str != NULL);
02844 
02845   smartlist_add(sl, str);
02846 }
02847 
02851 smartlist_t *
02852 tor_listdir(const char *dirname)
02853 {
02854   smartlist_t *result;
02855 #ifdef _WIN32
02856   char *pattern=NULL;
02857   TCHAR tpattern[MAX_PATH] = {0};
02858   char name[MAX_PATH*2+1] = {0};
02859   HANDLE handle;
02860   WIN32_FIND_DATA findData;
02861   tor_asprintf(&pattern, "%s\\*", dirname);
02862 #ifdef UNICODE
02863   mbstowcs(tpattern,pattern,MAX_PATH);
02864 #else
02865   strlcpy(tpattern, pattern, MAX_PATH);
02866 #endif
02867   if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
02868     tor_free(pattern);
02869     return NULL;
02870   }
02871   result = smartlist_new();
02872   while (1) {
02873 #ifdef UNICODE
02874     wcstombs(name,findData.cFileName,MAX_PATH);
02875     name[sizeof(name)-1] = '\0';
02876 #else
02877     strlcpy(name,findData.cFileName,sizeof(name));
02878 #endif
02879     if (strcmp(name, ".") &&
02880         strcmp(name, "..")) {
02881       smartlist_add(result, tor_strdup(name));
02882     }
02883     if (!FindNextFile(handle, &findData)) {
02884       DWORD err;
02885       if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
02886         char *errstr = format_win32_error(err);
02887         log_warn(LD_FS, "Error reading directory '%s': %s", dirname, errstr);
02888         tor_free(errstr);
02889       }
02890       break;
02891     }
02892   }
02893   FindClose(handle);
02894   tor_free(pattern);
02895 #else
02896   DIR *d;
02897   struct dirent *de;
02898   if (!(d = opendir(dirname)))
02899     return NULL;
02900 
02901   result = smartlist_new();
02902   while ((de = readdir(d))) {
02903     if (!strcmp(de->d_name, ".") ||
02904         !strcmp(de->d_name, ".."))
02905       continue;
02906     smartlist_add(result, tor_strdup(de->d_name));
02907   }
02908   closedir(d);
02909 #endif
02910   return result;
02911 }
02912 
02914 int
02915 path_is_relative(const char *filename)
02916 {
02917   if (filename && filename[0] == '/')
02918     return 0;
02919 #ifdef _WIN32
02920   else if (filename && filename[0] == '\\')
02921     return 0;
02922   else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
02923            filename[1] == ':' && filename[2] == '\\')
02924     return 0;
02925 #endif
02926   else
02927     return 1;
02928 }
02929 
02930 /* =====
02931  * Process helpers
02932  * ===== */
02933 
02934 #ifndef _WIN32
02935 /* Based on code contributed by christian grothoff */
02937 static int start_daemon_called = 0;
02939 static int finish_daemon_called = 0;
02942 static int daemon_filedes[2];
02948 void
02949 start_daemon(void)
02950 {
02951   pid_t pid;
02952 
02953   if (start_daemon_called)
02954     return;
02955   start_daemon_called = 1;
02956 
02957   if (pipe(daemon_filedes)) {
02958     log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
02959     exit(1);
02960   }
02961   pid = fork();
02962   if (pid < 0) {
02963     log_err(LD_GENERAL,"fork failed. Exiting.");
02964     exit(1);
02965   }
02966   if (pid) {  /* Parent */
02967     int ok;
02968     char c;
02969 
02970     close(daemon_filedes[1]); /* we only read */
02971     ok = -1;
02972     while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
02973       if (c == '.')
02974         ok = 1;
02975     }
02976     fflush(stdout);
02977     if (ok == 1)
02978       exit(0);
02979     else
02980       exit(1); /* child reported error */
02981   } else { /* Child */
02982     close(daemon_filedes[0]); /* we only write */
02983 
02984     pid = setsid(); /* Detach from controlling terminal */
02985     /*
02986      * Fork one more time, so the parent (the session group leader) can exit.
02987      * This means that we, as a non-session group leader, can never regain a
02988      * controlling terminal.   This part is recommended by Stevens's
02989      * _Advanced Programming in the Unix Environment_.
02990      */
02991     if (fork() != 0) {
02992       exit(0);
02993     }
02994     set_main_thread(); /* We are now the main thread. */
02995 
02996     return;
02997   }
02998 }
02999 
03005 void
03006 finish_daemon(const char *desired_cwd)
03007 {
03008   int nullfd;
03009   char c = '.';
03010   if (finish_daemon_called)
03011     return;
03012   if (!start_daemon_called)
03013     start_daemon();
03014   finish_daemon_called = 1;
03015 
03016   if (!desired_cwd)
03017     desired_cwd = "/";
03018    /* Don't hold the wrong FS mounted */
03019   if (chdir(desired_cwd) < 0) {
03020     log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
03021     exit(1);
03022   }
03023 
03024   nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
03025   if (nullfd < 0) {
03026     log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
03027     exit(1);
03028   }
03029   /* close fds linking to invoking terminal, but
03030    * close usual incoming fds, but redirect them somewhere
03031    * useful so the fds don't get reallocated elsewhere.
03032    */
03033   if (dup2(nullfd,0) < 0 ||
03034       dup2(nullfd,1) < 0 ||
03035       dup2(nullfd,2) < 0) {
03036     log_err(LD_GENERAL,"dup2 failed. Exiting.");
03037     exit(1);
03038   }
03039   if (nullfd > 2)
03040     close(nullfd);
03041   /* signal success */
03042   if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
03043     log_err(LD_GENERAL,"write failed. Exiting.");
03044   }
03045   close(daemon_filedes[1]);
03046 }
03047 #else
03048 /* defined(_WIN32) */
03049 void
03050 start_daemon(void)
03051 {
03052 }
03053 void
03054 finish_daemon(const char *cp)
03055 {
03056   (void)cp;
03057 }
03058 #endif
03059 
03062 void
03063 write_pidfile(char *filename)
03064 {
03065   FILE *pidfile;
03066 
03067   if ((pidfile = fopen(filename, "w")) == NULL) {
03068     log_warn(LD_FS, "Unable to open \"%s\" for writing: %s", filename,
03069              strerror(errno));
03070   } else {
03071 #ifdef _WIN32
03072     fprintf(pidfile, "%d\n", (int)_getpid());
03073 #else
03074     fprintf(pidfile, "%d\n", (int)getpid());
03075 #endif
03076     fclose(pidfile);
03077   }
03078 }
03079 
03080 #ifdef _WIN32
03081 HANDLE
03082 load_windows_system_library(const TCHAR *library_name)
03083 {
03084   TCHAR path[MAX_PATH];
03085   unsigned n;
03086   n = GetSystemDirectory(path, MAX_PATH);
03087   if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
03088     return 0;
03089   _tcscat(path, TEXT("\\"));
03090   _tcscat(path, library_name);
03091   return LoadLibrary(path);
03092 }
03093 #endif
03094 
03097 static char *
03098 format_win_cmdline_argument(const char *arg)
03099 {
03100   char *formatted_arg;
03101   char need_quotes;
03102   const char *c;
03103   int i;
03104   int bs_counter = 0;
03105   /* Backslash we can point to when one is inserted into the string */
03106   const char backslash = '\\';
03107 
03108   /* Smartlist of *char */
03109   smartlist_t *arg_chars;
03110   arg_chars = smartlist_new();
03111 
03112   /* Quote string if it contains whitespace or is empty */
03113   need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
03114 
03115   /* Build up smartlist of *chars */
03116   for (c=arg; *c != '\0'; c++) {
03117     if ('"' == *c) {
03118       /* Double up backslashes preceding a quote */
03119       for (i=0; i<(bs_counter*2); i++)
03120         smartlist_add(arg_chars, (void*)&backslash);
03121       bs_counter = 0;
03122       /* Escape the quote */
03123       smartlist_add(arg_chars, (void*)&backslash);
03124       smartlist_add(arg_chars, (void*)c);
03125     } else if ('\\' == *c) {
03126       /* Count backslashes until we know whether to double up */
03127       bs_counter++;
03128     } else {
03129       /* Don't double up slashes preceding a non-quote */
03130       for (i=0; i<bs_counter; i++)
03131         smartlist_add(arg_chars, (void*)&backslash);
03132       bs_counter = 0;
03133       smartlist_add(arg_chars, (void*)c);
03134     }
03135   }
03136   /* Don't double up trailing backslashes */
03137   for (i=0; i<bs_counter; i++)
03138     smartlist_add(arg_chars, (void*)&backslash);
03139 
03140   /* Allocate space for argument, quotes (if needed), and terminator */
03141   formatted_arg = tor_malloc(sizeof(char) *
03142       (smartlist_len(arg_chars) + (need_quotes?2:0) + 1));
03143 
03144   /* Add leading quote */
03145   i=0;
03146   if (need_quotes)
03147     formatted_arg[i++] = '"';
03148 
03149   /* Add characters */
03150   SMARTLIST_FOREACH(arg_chars, char*, c,
03151   {
03152     formatted_arg[i++] = *c;
03153   });
03154 
03155   /* Add trailing quote */
03156   if (need_quotes)
03157     formatted_arg[i++] = '"';
03158   formatted_arg[i] = '\0';
03159 
03160   smartlist_free(arg_chars);
03161   return formatted_arg;
03162 }
03163 
03168 char *
03169 tor_join_win_cmdline(const char *argv[])
03170 {
03171   smartlist_t *argv_list;
03172   char *joined_argv;
03173   int i;
03174 
03175   /* Format each argument and put the result in a smartlist */
03176   argv_list = smartlist_new();
03177   for (i=0; argv[i] != NULL; i++) {
03178     smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
03179   }
03180 
03181   /* Join the arguments with whitespace */
03182   joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
03183 
03184   /* Free the newly allocated arguments, and the smartlist */
03185   SMARTLIST_FOREACH(argv_list, char *, arg,
03186   {
03187     tor_free(arg);
03188   });
03189   smartlist_free(argv_list);
03190 
03191   return joined_argv;
03192 }
03193 
03215 int
03216 format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
03217                                          int max_len)
03218 {
03219   int len;
03220   unsigned int tmp;
03221   char *cur;
03222 
03223   /* Sanity check */
03224   if (!buf || max_len <= 0)
03225     return 0;
03226 
03227   /* How many chars do we need for x? */
03228   if (x > 0) {
03229     len = 0;
03230     tmp = x;
03231     while (tmp > 0) {
03232       tmp >>= 4;
03233       ++len;
03234     }
03235   } else {
03236     len = 1;
03237   }
03238 
03239   /* Bail if we would go past the end of the buffer */
03240   if (len > max_len)
03241     return 0;
03242 
03243   /* Point to last one */
03244   cur = buf + len - 1;
03245 
03246   /* Convert x to hex */
03247   do {
03248     *cur-- = "0123456789ABCDEF"[x & 0xf];
03249     x >>= 4;
03250   } while (x != 0 && cur >= buf);
03251 
03252   /* Return len */
03253   return len;
03254 }
03255 
03271 int
03272 format_helper_exit_status(unsigned char child_state, int saved_errno,
03273                           char *hex_errno)
03274 {
03275   unsigned int unsigned_errno;
03276   int written, left;
03277   char *cur;
03278   size_t i;
03279   int res = -1;
03280 
03281   /* Fill hex_errno with spaces, and a trailing newline (memset may
03282      not be signal handler safe, so we can't use it) */
03283   for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
03284     hex_errno[i] = ' ';
03285   hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
03286 
03287   /* Convert errno to be unsigned for hex conversion */
03288   if (saved_errno < 0) {
03289     unsigned_errno = (unsigned int) -saved_errno;
03290   } else {
03291     unsigned_errno = (unsigned int) saved_errno;
03292   }
03293 
03294   /*
03295    * Count how many chars of space we have left, and keep a pointer into the
03296    * current point in the buffer.
03297    */
03298   left = HEX_ERRNO_SIZE;
03299   cur = hex_errno;
03300 
03301   /* Emit child_state */
03302   written = format_hex_number_for_helper_exit_status(child_state,
03303                                                      cur, left);
03304   if (written <= 0)
03305     goto err;
03306 
03307   /* Adjust left and cur */
03308   left -= written;
03309   cur += written;
03310   if (left <= 0)
03311     goto err;
03312 
03313   /* Now the '/' */
03314   *cur = '/';
03315 
03316   /* Adjust left and cur */
03317   ++cur;
03318   --left;
03319   if (left <= 0)
03320     goto err;
03321 
03322   /* Need minus? */
03323   if (saved_errno < 0) {
03324     *cur = '-';
03325     ++cur;
03326     --left;
03327     if (left <= 0)
03328       goto err;
03329   }
03330 
03331   /* Emit unsigned_errno */
03332   written = format_hex_number_for_helper_exit_status(unsigned_errno,
03333                                                      cur, left);
03334 
03335   if (written <= 0)
03336     goto err;
03337 
03338   /* Adjust left and cur */
03339   left -= written;
03340   cur += written;
03341 
03342   /* Check that we have enough space left for a newline */
03343   if (left <= 0)
03344     goto err;
03345 
03346   /* Emit the newline and NUL */
03347   *cur++ = '\n';
03348   *cur++ = '\0';
03349 
03350   res = (int)(cur - hex_errno - 1);
03351 
03352   goto done;
03353 
03354  err:
03355   /*
03356    * In error exit, just write a '\0' in the first char so whatever called
03357    * this at least won't fall off the end.
03358    */
03359   *hex_errno = '\0';
03360 
03361  done:
03362   return res;
03363 }
03364 
03365 /* Maximum number of file descriptors, if we cannot get it via sysconf() */
03366 #define DEFAULT_MAX_FD 256
03367 
03370 int
03371 tor_terminate_process(process_handle_t *process_handle)
03372 {
03373 #ifdef _WIN32
03374   if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) {
03375     HANDLE handle;
03376     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
03377        attempt to open and terminate the process. */
03378     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE,
03379                          process_handle->pid.dwProcessId);
03380     if (!handle)
03381       return -1;
03382 
03383     if (!TerminateProcess(handle, 0))
03384       return -1;
03385     else
03386       return 0;
03387   }
03388 #else /* Unix */
03389   return kill(process_handle->pid, SIGTERM);
03390 #endif
03391 
03392   return -1;
03393 }
03394 
03396 int
03397 tor_process_get_pid(process_handle_t *process_handle)
03398 {
03399 #ifdef _WIN32
03400   return (int) process_handle->pid.dwProcessId;
03401 #else
03402   return (int) process_handle->pid;
03403 #endif
03404 }
03405 
03406 #ifdef _WIN32
03407 HANDLE
03408 tor_process_get_stdout_pipe(process_handle_t *process_handle)
03409 {
03410   return process_handle->stdout_pipe;
03411 }
03412 #else
03413 /* DOCDOC tor_process_get_stdout_pipe */
03414 FILE *
03415 tor_process_get_stdout_pipe(process_handle_t *process_handle)
03416 {
03417   return process_handle->stdout_handle;
03418 }
03419 #endif
03420 
03421 /* DOCDOC process_handle_new */
03422 static process_handle_t *
03423 process_handle_new(void)
03424 {
03425   process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
03426 
03427 #ifdef _WIN32
03428   out->stdout_pipe = INVALID_HANDLE_VALUE;
03429   out->stderr_pipe = INVALID_HANDLE_VALUE;
03430 #else
03431   out->stdout_pipe = -1;
03432   out->stderr_pipe = -1;
03433 #endif
03434 
03435   return out;
03436 }
03437 
03447 #define CHILD_STATE_INIT 0
03448 #define CHILD_STATE_PIPE 1
03449 #define CHILD_STATE_MAXFD 2
03450 #define CHILD_STATE_FORK 3
03451 #define CHILD_STATE_DUPOUT 4
03452 #define CHILD_STATE_DUPERR 5
03453 #define CHILD_STATE_REDIRECT 6
03454 #define CHILD_STATE_CLOSEFD 7
03455 #define CHILD_STATE_EXEC 8
03456 #define CHILD_STATE_FAILEXEC 9
03457 
03477 int
03478 tor_spawn_background(const char *const filename, const char **argv,
03479                      process_environment_t *env,
03480                      process_handle_t **process_handle_out)
03481 {
03482 #ifdef _WIN32
03483   HANDLE stdout_pipe_read = NULL;
03484   HANDLE stdout_pipe_write = NULL;
03485   HANDLE stderr_pipe_read = NULL;
03486   HANDLE stderr_pipe_write = NULL;
03487   process_handle_t *process_handle;
03488   int status;
03489 
03490   STARTUPINFOA siStartInfo;
03491   BOOL retval = FALSE;
03492 
03493   SECURITY_ATTRIBUTES saAttr;
03494   char *joined_argv;
03495 
03496   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
03497   saAttr.bInheritHandle = TRUE;
03498   /* TODO: should we set explicit security attributes? (#2046, comment 5) */
03499   saAttr.lpSecurityDescriptor = NULL;
03500 
03501   /* Assume failure to start process */
03502   status = PROCESS_STATUS_ERROR;
03503 
03504   /* Set up pipe for stdout */
03505   if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
03506     log_warn(LD_GENERAL,
03507       "Failed to create pipe for stdout communication with child process: %s",
03508       format_win32_error(GetLastError()));
03509     return status;
03510   }
03511   if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
03512     log_warn(LD_GENERAL,
03513       "Failed to configure pipe for stdout communication with child "
03514       "process: %s", format_win32_error(GetLastError()));
03515     return status;
03516   }
03517 
03518   /* Set up pipe for stderr */
03519   if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
03520     log_warn(LD_GENERAL,
03521       "Failed to create pipe for stderr communication with child process: %s",
03522       format_win32_error(GetLastError()));
03523     return status;
03524   }
03525   if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
03526     log_warn(LD_GENERAL,
03527       "Failed to configure pipe for stderr communication with child "
03528       "process: %s", format_win32_error(GetLastError()));
03529     return status;
03530   }
03531 
03532   /* Create the child process */
03533 
03534   /* Windows expects argv to be a whitespace delimited string, so join argv up
03535    */
03536   joined_argv = tor_join_win_cmdline(argv);
03537 
03538   process_handle = process_handle_new();
03539   process_handle->status = status;
03540 
03541   ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
03542   ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
03543   siStartInfo.cb = sizeof(STARTUPINFO);
03544   siStartInfo.hStdError = stderr_pipe_write;
03545   siStartInfo.hStdOutput = stdout_pipe_write;
03546   siStartInfo.hStdInput = NULL;
03547   siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
03548 
03549   /* Create the child process */
03550 
03551   retval = CreateProcessA(filename,      // module name
03552                  joined_argv,   // command line
03553   /* TODO: should we set explicit security attributes? (#2046, comment 5) */
03554                  NULL,          // process security attributes
03555                  NULL,          // primary thread security attributes
03556                  TRUE,          // handles are inherited
03557   /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
03558    * work?) */
03559                  0,             // creation flags
03560                  (env==NULL) ? NULL : env->windows_environment_block,
03561                  NULL,          // use parent's current directory
03562                  &siStartInfo,  // STARTUPINFO pointer
03563                  &(process_handle->pid));  // receives PROCESS_INFORMATION
03564 
03565   tor_free(joined_argv);
03566 
03567   if (!retval) {
03568     log_warn(LD_GENERAL,
03569       "Failed to create child process %s: %s", filename?filename:argv[0],
03570       format_win32_error(GetLastError()));
03571     tor_free(process_handle);
03572   } else  {
03573     /* TODO: Close hProcess and hThread in process_handle->pid? */
03574     process_handle->stdout_pipe = stdout_pipe_read;
03575     process_handle->stderr_pipe = stderr_pipe_read;
03576     status = process_handle->status = PROCESS_STATUS_RUNNING;
03577   }
03578 
03579   /* TODO: Close pipes on exit */
03580   *process_handle_out = process_handle;
03581   return status;
03582 #else // _WIN32
03583   pid_t pid;
03584   int stdout_pipe[2];
03585   int stderr_pipe[2];
03586   int fd, retval;
03587   ssize_t nbytes;
03588   process_handle_t *process_handle;
03589   int status;
03590 
03591   const char *error_message = SPAWN_ERROR_MESSAGE;
03592   size_t error_message_length;
03593 
03594   /* Represents where in the process of spawning the program is;
03595      this is used for printing out the error message */
03596   unsigned char child_state = CHILD_STATE_INIT;
03597 
03598   char hex_errno[HEX_ERRNO_SIZE];
03599 
03600   static int max_fd = -1;
03601 
03602   status = PROCESS_STATUS_ERROR;
03603 
03604   /* We do the strlen here because strlen() is not signal handler safe,
03605      and we are not allowed to use unsafe functions between fork and exec */
03606   error_message_length = strlen(error_message);
03607 
03608   child_state = CHILD_STATE_PIPE;
03609 
03610   /* Set up pipe for redirecting stdout and stderr of child */
03611   retval = pipe(stdout_pipe);
03612   if (-1 == retval) {
03613     log_warn(LD_GENERAL,
03614       "Failed to set up pipe for stdout communication with child process: %s",
03615        strerror(errno));
03616     return status;
03617   }
03618 
03619   retval = pipe(stderr_pipe);
03620   if (-1 == retval) {
03621     log_warn(LD_GENERAL,
03622       "Failed to set up pipe for stderr communication with child process: %s",
03623       strerror(errno));
03624 
03625     close(stdout_pipe[0]);
03626     close(stdout_pipe[1]);
03627 
03628     return status;
03629   }
03630 
03631   child_state = CHILD_STATE_MAXFD;
03632 
03633 #ifdef _SC_OPEN_MAX
03634   if (-1 != max_fd) {
03635     max_fd = (int) sysconf(_SC_OPEN_MAX);
03636     if (max_fd == -1)
03637       max_fd = DEFAULT_MAX_FD;
03638       log_warn(LD_GENERAL,
03639                "Cannot find maximum file descriptor, assuming %d", max_fd);
03640   }
03641 #else
03642   max_fd = DEFAULT_MAX_FD;
03643 #endif
03644 
03645   child_state = CHILD_STATE_FORK;
03646 
03647   pid = fork();
03648   if (0 == pid) {
03649     /* In child */
03650 
03651     child_state = CHILD_STATE_DUPOUT;
03652 
03653     /* Link child stdout to the write end of the pipe */
03654     retval = dup2(stdout_pipe[1], STDOUT_FILENO);
03655     if (-1 == retval)
03656         goto error;
03657 
03658     child_state = CHILD_STATE_DUPERR;
03659 
03660     /* Link child stderr to the write end of the pipe */
03661     retval = dup2(stderr_pipe[1], STDERR_FILENO);
03662     if (-1 == retval)
03663         goto error;
03664 
03665     child_state = CHILD_STATE_REDIRECT;
03666 
03667     /* Link stdin to /dev/null */
03668     fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
03669     if (fd != -1)
03670       dup2(fd, STDIN_FILENO);
03671     else
03672       goto error;
03673 
03674     child_state = CHILD_STATE_CLOSEFD;
03675 
03676     close(stderr_pipe[0]);
03677     close(stderr_pipe[1]);
03678     close(stdout_pipe[0]);
03679     close(stdout_pipe[1]);
03680     close(fd);
03681 
03682     /* Close all other fds, including the read end of the pipe */
03683     /* XXX: We should now be doing enough FD_CLOEXEC setting to make
03684      * this needless. */
03685     for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
03686       close(fd);
03687     }
03688 
03689     child_state = CHILD_STATE_EXEC;
03690 
03691     /* Call the requested program. We need the cast because
03692        execvp doesn't define argv as const, even though it
03693        does not modify the arguments */
03694     if (env)
03695       execve(filename, (char *const *) argv, env->unixoid_environment_block);
03696     else
03697       execvp(filename, (char *const *) argv);
03698 
03699     /* If we got here, the exec or open(/dev/null) failed */
03700 
03701     child_state = CHILD_STATE_FAILEXEC;
03702 
03703   error:
03704     {
03705       /* XXX: are we leaking fds from the pipe? */
03706       int n;
03707 
03708       n = format_helper_exit_status(child_state, errno, hex_errno);
03709 
03710       if (n >= 0) {
03711         /* Write the error message. GCC requires that we check the return
03712            value, but there is nothing we can do if it fails */
03713         /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
03714         nbytes = write(STDOUT_FILENO, error_message, error_message_length);
03715         nbytes = write(STDOUT_FILENO, hex_errno, n);
03716       }
03717     }
03718 
03719     (void) nbytes;
03720 
03721     _exit(255);
03722     /* Never reached, but avoids compiler warning */
03723     return status;
03724   }
03725 
03726   /* In parent */
03727 
03728   if (-1 == pid) {
03729     log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
03730     close(stdout_pipe[0]);
03731     close(stdout_pipe[1]);
03732     close(stderr_pipe[0]);
03733     close(stderr_pipe[1]);
03734     return status;
03735   }
03736 
03737   process_handle = process_handle_new();
03738   process_handle->status = status;
03739   process_handle->pid = pid;
03740 
03741   /* TODO: If the child process forked but failed to exec, waitpid it */
03742 
03743   /* Return read end of the pipes to caller, and close write end */
03744   process_handle->stdout_pipe = stdout_pipe[0];
03745   retval = close(stdout_pipe[1]);
03746 
03747   if (-1 == retval) {
03748     log_warn(LD_GENERAL,
03749             "Failed to close write end of stdout pipe in parent process: %s",
03750             strerror(errno));
03751   }
03752 
03753   process_handle->stderr_pipe = stderr_pipe[0];
03754   retval = close(stderr_pipe[1]);
03755 
03756   if (-1 == retval) {
03757     log_warn(LD_GENERAL,
03758             "Failed to close write end of stderr pipe in parent process: %s",
03759             strerror(errno));
03760   }
03761 
03762   status = process_handle->status = PROCESS_STATUS_RUNNING;
03763   /* Set stdout/stderr pipes to be non-blocking */
03764   fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK);
03765   fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK);
03766   /* Open the buffered IO streams */
03767   process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r");
03768   process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r");
03769 
03770   *process_handle_out = process_handle;
03771   return process_handle->status;
03772 #endif // _WIN32
03773 }
03774 
03779 void
03780 tor_process_handle_destroy(process_handle_t *process_handle,
03781                            int also_terminate_process)
03782 {
03783   if (!process_handle)
03784     return;
03785 
03786   if (also_terminate_process) {
03787     if (tor_terminate_process(process_handle) < 0) {
03788       log_notice(LD_GENERAL, "Failed to terminate process with PID '%d'",
03789                  tor_process_get_pid(process_handle));
03790     } else {
03791       log_info(LD_GENERAL, "Terminated process with PID '%d'",
03792                tor_process_get_pid(process_handle));
03793     }
03794   }
03795 
03796   process_handle->status = PROCESS_STATUS_NOTRUNNING;
03797 
03798 #ifdef _WIN32
03799   if (process_handle->stdout_pipe)
03800     CloseHandle(process_handle->stdout_pipe);
03801 
03802   if (process_handle->stderr_pipe)
03803     CloseHandle(process_handle->stderr_pipe);
03804 #else
03805   if (process_handle->stdout_handle)
03806     fclose(process_handle->stdout_handle);
03807 
03808   if (process_handle->stderr_handle)
03809     fclose(process_handle->stderr_handle);
03810 #endif
03811 
03812   memset(process_handle, 0x0f, sizeof(process_handle_t));
03813   tor_free(process_handle);
03814 }
03815 
03826 int
03827 tor_get_exit_code(const process_handle_t *process_handle,
03828                   int block, int *exit_code)
03829 {
03830 #ifdef _WIN32
03831   DWORD retval;
03832   BOOL success;
03833 
03834   if (block) {
03835     /* Wait for the process to exit */
03836     retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE);
03837     if (retval != WAIT_OBJECT_0) {
03838       log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
03839               (int)retval, format_win32_error(GetLastError()));
03840       return PROCESS_EXIT_ERROR;
03841     }
03842   } else {
03843     retval = WaitForSingleObject(process_handle->pid.hProcess, 0);
03844     if (WAIT_TIMEOUT == retval) {
03845       /* Process has not exited */
03846       return PROCESS_EXIT_RUNNING;
03847     } else if (retval != WAIT_OBJECT_0) {
03848       log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
03849                (int)retval, format_win32_error(GetLastError()));
03850       return PROCESS_EXIT_ERROR;
03851     }
03852   }
03853 
03854   if (exit_code != NULL) {
03855     success = GetExitCodeProcess(process_handle->pid.hProcess,
03856                                  (PDWORD)exit_code);
03857     if (!success) {
03858       log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
03859                format_win32_error(GetLastError()));
03860       return PROCESS_EXIT_ERROR;
03861     }
03862   }
03863 #else
03864   int stat_loc;
03865   int retval;
03866 
03867   retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
03868   if (!block && 0 == retval) {
03869     /* Process has not exited */
03870     return PROCESS_EXIT_RUNNING;
03871   } else if (retval != process_handle->pid) {
03872     log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
03873              process_handle->pid, strerror(errno));
03874     return PROCESS_EXIT_ERROR;
03875   }
03876 
03877   if (!WIFEXITED(stat_loc)) {
03878     log_warn(LD_GENERAL, "Process %d did not exit normally",
03879              process_handle->pid);
03880     return PROCESS_EXIT_ERROR;
03881   }
03882 
03883   if (exit_code != NULL)
03884     *exit_code = WEXITSTATUS(stat_loc);
03885 #endif // _WIN32
03886 
03887   return PROCESS_EXIT_EXITED;
03888 }
03889 
03893 static INLINE size_t
03894 str_num_before(const char *s, char ch)
03895 {
03896   const char *cp = strchr(s, ch);
03897   if (cp)
03898     return cp - s;
03899   else
03900     return strlen(s);
03901 }
03902 
03905 int
03906 environment_variable_names_equal(const char *s1, const char *s2)
03907 {
03908   size_t s1_name_len = str_num_before(s1, '=');
03909   size_t s2_name_len = str_num_before(s2, '=');
03910 
03911   return (s1_name_len == s2_name_len &&
03912           tor_memeq(s1, s2, s1_name_len));
03913 }
03914 
03917 void
03918 process_environment_free(process_environment_t *env)
03919 {
03920   if (env == NULL) return;
03921 
03922   /* As both an optimization hack to reduce consing on Unixoid systems
03923    * and a nice way to ensure that some otherwise-Windows-specific
03924    * code will always get tested before changes to it get merged, the
03925    * strings which env->unixoid_environment_block points to are packed
03926    * into env->windows_environment_block. */
03927   tor_free(env->unixoid_environment_block);
03928   tor_free(env->windows_environment_block);
03929 
03930   tor_free(env);
03931 }
03932 
03936 process_environment_t *
03937 process_environment_make(struct smartlist_t *env_vars)
03938 {
03939   process_environment_t *env = tor_malloc_zero(sizeof(process_environment_t));
03940   size_t n_env_vars = smartlist_len(env_vars);
03941   size_t i;
03942   size_t total_env_length;
03943   smartlist_t *env_vars_sorted;
03944 
03945   tor_assert(n_env_vars + 1 != 0);
03946   env->unixoid_environment_block = tor_calloc(n_env_vars + 1, sizeof(char *));
03947   /* env->unixoid_environment_block is already NULL-terminated,
03948    * because we assume that NULL == 0 (and check that during compilation). */
03949 
03950   total_env_length = 1; /* terminating NUL of terminating empty string */
03951   for (i = 0; i < n_env_vars; ++i) {
03952     const char *s = smartlist_get(env_vars, i);
03953     size_t slen = strlen(s);
03954 
03955     tor_assert(slen + 1 != 0);
03956     tor_assert(slen + 1 < SIZE_MAX - total_env_length);
03957     total_env_length += slen + 1;
03958   }
03959 
03960   env->windows_environment_block = tor_malloc_zero(total_env_length);
03961   /* env->windows_environment_block is already
03962    * (NUL-terminated-empty-string)-terminated. */
03963 
03964   /* Some versions of Windows supposedly require that environment
03965    * blocks be sorted.  Or maybe some Windows programs (or their
03966    * runtime libraries) fail to look up strings in non-sorted
03967    * environment blocks.
03968    *
03969    * Also, sorting strings makes it easy to find duplicate environment
03970    * variables and environment-variable strings without an '=' on all
03971    * OSes, and they can cause badness.  Let's complain about those. */
03972   env_vars_sorted = smartlist_new();
03973   smartlist_add_all(env_vars_sorted, env_vars);
03974   smartlist_sort_strings(env_vars_sorted);
03975 
03976   /* Now copy the strings into the environment blocks. */
03977   {
03978     char *cp = env->windows_environment_block;
03979     const char *prev_env_var = NULL;
03980 
03981     for (i = 0; i < n_env_vars; ++i) {
03982       const char *s = smartlist_get(env_vars_sorted, i);
03983       size_t slen = strlen(s);
03984       size_t s_name_len = str_num_before(s, '=');
03985 
03986       if (s_name_len == slen) {
03987         log_warn(LD_GENERAL,
03988                  "Preparing an environment containing a variable "
03989                  "without a value: %s",
03990                  s);
03991       }
03992       if (prev_env_var != NULL &&
03993           environment_variable_names_equal(s, prev_env_var)) {
03994         log_warn(LD_GENERAL,
03995                  "Preparing an environment containing two variables "
03996                  "with the same name: %s and %s",
03997                  prev_env_var, s);
03998       }
03999 
04000       prev_env_var = s;
04001 
04002       /* Actually copy the string into the environment. */
04003       memcpy(cp, s, slen+1);
04004       env->unixoid_environment_block[i] = cp;
04005       cp += slen+1;
04006     }
04007 
04008     tor_assert(cp == env->windows_environment_block + total_env_length - 1);
04009   }
04010 
04011   smartlist_free(env_vars_sorted);
04012 
04013   return env;
04014 }
04015 
04024 struct smartlist_t *
04025 get_current_process_environment_variables(void)
04026 {
04027   smartlist_t *sl = smartlist_new();
04028 
04029   char **environ_tmp; /* Not const char ** ? Really? */
04030   for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
04031     smartlist_add(sl, tor_strdup(*environ_tmp));
04032   }
04033 
04034   return sl;
04035 }
04036 
04041 void
04042 set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
04043                                       const char *new_var,
04044                                       void (*free_old)(void*),
04045                                       int free_p)
04046 {
04047   SMARTLIST_FOREACH_BEGIN(env_vars, const char *, s) {
04048     if (environment_variable_names_equal(s, new_var)) {
04049       SMARTLIST_DEL_CURRENT(env_vars, s);
04050       if (free_p) {
04051         free_old((void *)s);
04052       }
04053     }
04054   } SMARTLIST_FOREACH_END(s);
04055 
04056   if (strchr(new_var, '=') != NULL) {
04057     smartlist_add(env_vars, (void *)new_var);
04058   }
04059 }
04060 
04061 #ifdef _WIN32
04062 
04068 ssize_t
04069 tor_read_all_handle(HANDLE h, char *buf, size_t count,
04070                     const process_handle_t *process)
04071 {
04072   size_t numread = 0;
04073   BOOL retval;
04074   DWORD byte_count;
04075   BOOL process_exited = FALSE;
04076 
04077   if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
04078     return -1;
04079 
04080   while (numread != count) {
04081     /* Check if there is anything to read */
04082     retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
04083     if (!retval) {
04084       log_warn(LD_GENERAL,
04085         "Failed to peek from handle: %s",
04086         format_win32_error(GetLastError()));
04087       return -1;
04088     } else if (0 == byte_count) {
04089       /* Nothing available: process exited or it is busy */
04090 
04091       /* Exit if we don't know whether the process is running */
04092       if (NULL == process)
04093         break;
04094 
04095       /* The process exited and there's nothing left to read from it */
04096       if (process_exited)
04097         break;
04098 
04099       /* If process is not running, check for output one more time in case
04100          it wrote something after the peek was performed. Otherwise keep on
04101          waiting for output */
04102       tor_assert(process != NULL);
04103       byte_count = WaitForSingleObject(process->pid.hProcess, 0);
04104       if (WAIT_TIMEOUT != byte_count)
04105         process_exited = TRUE;
04106 
04107       continue;
04108     }
04109 
04110     /* There is data to read; read it */
04111     retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
04112     tor_assert(byte_count + numread <= count);
04113     if (!retval) {
04114       log_warn(LD_GENERAL, "Failed to read from handle: %s",
04115         format_win32_error(GetLastError()));
04116       return -1;
04117     } else if (0 == byte_count) {
04118       /* End of file */
04119       break;
04120     }
04121     numread += byte_count;
04122   }
04123   return (ssize_t)numread;
04124 }
04125 #else
04126 
04132 ssize_t
04133 tor_read_all_handle(FILE *h, char *buf, size_t count,
04134                     const process_handle_t *process,
04135                     int *eof)
04136 {
04137   size_t numread = 0;
04138   char *retval;
04139 
04140   if (eof)
04141     *eof = 0;
04142 
04143   if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
04144     return -1;
04145 
04146   while (numread != count) {
04147     /* Use fgets because that is what we use in log_from_pipe() */
04148     retval = fgets(buf+numread, (int)(count-numread), h);
04149     if (NULL == retval) {
04150       if (feof(h)) {
04151         log_debug(LD_GENERAL, "fgets() reached end of file");
04152         if (eof)
04153           *eof = 1;
04154         break;
04155       } else {
04156         if (EAGAIN == errno) {
04157           if (process)
04158             continue;
04159           else
04160             break;
04161         } else {
04162           log_warn(LD_GENERAL, "fgets() from handle failed: %s",
04163                    strerror(errno));
04164           return -1;
04165         }
04166       }
04167     }
04168     tor_assert(retval != NULL);
04169     tor_assert(strlen(retval) + numread <= count);
04170     numread += strlen(retval);
04171   }
04172 
04173   log_debug(LD_GENERAL, "fgets() read %d bytes from handle", (int)numread);
04174   return (ssize_t)numread;
04175 }
04176 #endif
04177 
04179 ssize_t
04180 tor_read_all_from_process_stdout(const process_handle_t *process_handle,
04181                                  char *buf, size_t count)
04182 {
04183 #ifdef _WIN32
04184   return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
04185                              process_handle);
04186 #else
04187   return tor_read_all_handle(process_handle->stdout_handle, buf, count,
04188                              process_handle, NULL);
04189 #endif
04190 }
04191 
04193 ssize_t
04194 tor_read_all_from_process_stderr(const process_handle_t *process_handle,
04195                                  char *buf, size_t count)
04196 {
04197 #ifdef _WIN32
04198   return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
04199                              process_handle);
04200 #else
04201   return tor_read_all_handle(process_handle->stderr_handle, buf, count,
04202                              process_handle, NULL);
04203 #endif
04204 }
04205 
04211 int
04212 tor_split_lines(smartlist_t *sl, char *buf, int len)
04213 {
04214   /* Index in buf of the start of the current line */
04215   int start = 0;
04216   /* Index in buf of the current character being processed */
04217   int cur = 0;
04218   /* Are we currently in a line */
04219   char in_line = 0;
04220 
04221   /* Loop over string */
04222   while (cur < len) {
04223     /* Loop until end of line or end of string */
04224     for (; cur < len; cur++) {
04225       if (in_line) {
04226         if ('\r' == buf[cur] || '\n' == buf[cur]) {
04227           /* End of line */
04228           buf[cur] = '\0';
04229           /* Point cur to the next line */
04230           cur++;
04231           /* Line starts at start and ends with a nul */
04232           break;
04233         } else {
04234           if (!TOR_ISPRINT(buf[cur]))
04235             buf[cur] = '.';
04236         }
04237       } else {
04238         if ('\r' == buf[cur] || '\n' == buf[cur]) {
04239           /* Skip leading vertical space */
04240           ;
04241         } else {
04242           in_line = 1;
04243           start = cur;
04244           if (!TOR_ISPRINT(buf[cur]))
04245             buf[cur] = '.';
04246         }
04247       }
04248     }
04249     /* We are at the end of the line or end of string. If in_line is true there
04250      * is a line which starts at buf+start and ends at a NUL. cur points to
04251      * the character after the NUL. */
04252     if (in_line)
04253       smartlist_add(sl, (void *)(buf+start));
04254     in_line = 0;
04255   }
04256   return smartlist_len(sl);
04257 }
04258 
04259 #ifdef _WIN32
04260 
04266 static int
04267 log_from_handle(HANDLE *pipe, int severity)
04268 {
04269   char buf[256];
04270   int pos;
04271   smartlist_t *lines;
04272 
04273   pos = tor_read_all_handle(pipe, buf, sizeof(buf) - 1, NULL);
04274   if (pos < 0) {
04275     /* Error */
04276     log_warn(LD_GENERAL, "Failed to read data from subprocess");
04277     return -1;
04278   }
04279 
04280   if (0 == pos) {
04281     /* There's nothing to read (process is busy or has exited) */
04282     log_debug(LD_GENERAL, "Subprocess had nothing to say");
04283     return 0;
04284   }
04285 
04286   /* End with a null even if there isn't a \r\n at the end */
04287   /* TODO: What if this is a partial line? */
04288   buf[pos] = '\0';
04289   log_debug(LD_GENERAL, "Subprocess had %d bytes to say", pos);
04290 
04291   /* Split up the buffer */
04292   lines = smartlist_new();
04293   tor_split_lines(lines, buf, pos);
04294 
04295   /* Log each line */
04296   SMARTLIST_FOREACH(lines, char *, line,
04297   {
04298     log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", line);
04299   });
04300   smartlist_free(lines);
04301 
04302   return 0;
04303 }
04304 
04305 #else
04306 
04312 static int
04313 log_from_pipe(FILE *stream, int severity, const char *executable,
04314               int *child_status)
04315 {
04316   char buf[256];
04317   enum stream_status r;
04318 
04319   for (;;) {
04320     r = get_string_from_pipe(stream, buf, sizeof(buf) - 1);
04321 
04322     if (r == IO_STREAM_CLOSED) {
04323       return 1;
04324     } else if (r == IO_STREAM_EAGAIN) {
04325       return 0;
04326     } else if (r == IO_STREAM_TERM) {
04327       return -1;
04328     }
04329 
04330     tor_assert(r == IO_STREAM_OKAY);
04331 
04332     /* Check if buf starts with SPAWN_ERROR_MESSAGE */
04333     if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) {
04334       /* Parse error message */
04335       int retval, child_state, saved_errno;
04336       retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x",
04337                           &child_state, &saved_errno);
04338       if (retval == 2) {
04339         log_warn(LD_GENERAL,
04340                  "Failed to start child process \"%s\" in state %d: %s",
04341                  executable, child_state, strerror(saved_errno));
04342         if (child_status)
04343           *child_status = 1;
04344       } else {
04345         /* Failed to parse message from child process, log it as a
04346            warning */
04347         log_warn(LD_GENERAL,
04348                  "Unexpected message from port forwarding helper \"%s\": %s",
04349                  executable, buf);
04350       }
04351     } else {
04352       log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf);
04353     }
04354   }
04355 
04356   /* We should never get here */
04357   return -1;
04358 }
04359 #endif
04360 
04376 enum stream_status
04377 get_string_from_pipe(FILE *stream, char *buf_out, size_t count)
04378 {
04379   char *retval;
04380   size_t len;
04381 
04382   tor_assert(count <= INT_MAX);
04383 
04384   retval = fgets(buf_out, (int)count, stream);
04385 
04386   if (!retval) {
04387     if (feof(stream)) {
04388       /* Program has closed stream (probably it exited) */
04389       /* TODO: check error */
04390       return IO_STREAM_CLOSED;
04391     } else {
04392       if (EAGAIN == errno) {
04393         /* Nothing more to read, try again next time */
04394         return IO_STREAM_EAGAIN;
04395       } else {
04396         /* There was a problem, abandon this child process */
04397         return IO_STREAM_TERM;
04398       }
04399     }
04400   } else {
04401     len = strlen(buf_out);
04402     if (len == 0) {
04403       /* this probably means we got a NUL at the start of the string. */
04404       return IO_STREAM_EAGAIN;
04405     }
04406 
04407     if (buf_out[len - 1] == '\n') {
04408       /* Remove the trailing newline */
04409       buf_out[len - 1] = '\0';
04410     } else {
04411       /* No newline; check whether we overflowed the buffer */
04412       if (!feof(stream))
04413         log_info(LD_GENERAL,
04414                  "Line from stream was truncated: %s", buf_out);
04415       /* TODO: What to do with this error? */
04416     }
04417 
04418     return IO_STREAM_OKAY;
04419   }
04420 
04421   /* We should never get here */
04422   return IO_STREAM_TERM;
04423 }
04424 
04425 /* DOCDOC tor_check_port_forwarding */
04426 void
04427 tor_check_port_forwarding(const char *filename, int dir_port, int or_port,
04428                           time_t now)
04429 {
04430 /* When fw-helper succeeds, how long do we wait until running it again */
04431 #define TIME_TO_EXEC_FWHELPER_SUCCESS 300
04432 /* When fw-helper failed to start, how long do we wait until running it again
04433  */
04434 #define TIME_TO_EXEC_FWHELPER_FAIL 60
04435 
04436   /* Static variables are initialized to zero, so child_handle.status=0
04437    * which corresponds to it not running on startup */
04438   static process_handle_t *child_handle=NULL;
04439 
04440   static time_t time_to_run_helper = 0;
04441   int stdout_status, stderr_status, retval;
04442   const char *argv[10];
04443   char s_dirport[6], s_orport[6];
04444 
04445   tor_assert(filename);
04446 
04447   /* Set up command line for tor-fw-helper */
04448   snprintf(s_dirport, sizeof s_dirport, "%d", dir_port);
04449   snprintf(s_orport, sizeof s_orport, "%d", or_port);
04450 
04451   /* TODO: Allow different internal and external ports */
04452   argv[0] = filename;
04453   argv[1] = "--internal-or-port";
04454   argv[2] = s_orport;
04455   argv[3] = "--external-or-port";
04456   argv[4] = s_orport;
04457   argv[5] = "--internal-dir-port";
04458   argv[6] = s_dirport;
04459   argv[7] = "--external-dir-port";
04460   argv[8] = s_dirport;
04461   argv[9] = NULL;
04462 
04463   /* Start the child, if it is not already running */
04464   if ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) &&
04465       time_to_run_helper < now) {
04466     int status;
04467 
04468     /* Assume tor-fw-helper will succeed, start it later*/
04469     time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS;
04470 
04471     if (child_handle) {
04472       tor_process_handle_destroy(child_handle, 1);
04473       child_handle = NULL;
04474     }
04475 
04476 #ifdef _WIN32
04477     /* Passing NULL as lpApplicationName makes Windows search for the .exe */
04478     status = tor_spawn_background(NULL, argv, NULL, &child_handle);
04479 #else
04480     status = tor_spawn_background(filename, argv, NULL, &child_handle);
04481 #endif
04482 
04483     if (PROCESS_STATUS_ERROR == status) {
04484       log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
04485               filename);
04486       time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
04487       return;
04488     }
04489 
04490     log_info(LD_GENERAL,
04491              "Started port forwarding helper (%s) with pid '%d'",
04492              filename, tor_process_get_pid(child_handle));
04493   }
04494 
04495   /* If child is running, read from its stdout and stderr) */
04496   if (child_handle && PROCESS_STATUS_RUNNING == child_handle->status) {
04497     /* Read from stdout/stderr and log result */
04498     retval = 0;
04499 #ifdef _WIN32
04500     stdout_status = log_from_handle(child_handle->stdout_pipe, LOG_INFO);
04501     stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_WARN);
04502     /* If we got this far (on Windows), the process started */
04503     retval = 0;
04504 #else
04505     stdout_status = log_from_pipe(child_handle->stdout_handle,
04506                     LOG_INFO, filename, &retval);
04507     stderr_status = log_from_pipe(child_handle->stderr_handle,
04508                     LOG_WARN, filename, &retval);
04509 #endif
04510     if (retval) {
04511       /* There was a problem in the child process */
04512       time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
04513     }
04514 
04515     /* Combine the two statuses in order of severity */
04516     if (-1 == stdout_status || -1 == stderr_status)
04517       /* There was a failure */
04518       retval = -1;
04519 #ifdef _WIN32
04520     else if (!child_handle || tor_get_exit_code(child_handle, 0, NULL) !=
04521              PROCESS_EXIT_RUNNING) {
04522       /* process has exited or there was an error */
04523       /* TODO: Do something with the process return value */
04524       /* TODO: What if the process output something since
04525        * between log_from_handle and tor_get_exit_code? */
04526       retval = 1;
04527     }
04528 #else
04529     else if (1 == stdout_status || 1 == stderr_status)
04530       /* stdout or stderr was closed, the process probably
04531        * exited. It will be reaped by waitpid() in main.c */
04532       /* TODO: Do something with the process return value */
04533       retval = 1;
04534 #endif
04535     else
04536       /* Both are fine */
04537       retval = 0;
04538 
04539     /* If either pipe indicates a failure, act on it */
04540     if (0 != retval) {
04541       if (1 == retval) {
04542         log_info(LD_GENERAL, "Port forwarding helper terminated");
04543         child_handle->status = PROCESS_STATUS_NOTRUNNING;
04544       } else {
04545         log_warn(LD_GENERAL, "Failed to read from port forwarding helper");
04546         child_handle->status = PROCESS_STATUS_ERROR;
04547       }
04548 
04549       /* TODO: The child might not actually be finished (maybe it failed or
04550          closed stdout/stderr), so maybe we shouldn't start another? */
04551     }
04552   }
04553 }
04554