123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097 |
- const char util_c_id[] = "$Id$";
- #define _GNU_SOURCE
- #include "orconfig.h"
- #include "util.h"
- #include "log.h"
- #include "crypto.h"
- #include "torint.h"
- #include "container.h"
- #ifdef MS_WINDOWS
- #include <io.h>
- #include <direct.h>
- #include <process.h>
- #else
- #include <dirent.h>
- #include <pwd.h>
- #endif
- #ifdef HAVE_CTYPE_H
- #include <ctype.h>
- #endif
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #ifdef HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #ifdef HAVE_ARPA_INET_H
- #include <arpa/inet.h>
- #endif
- #ifdef HAVE_ERRNO_H
- #include <errno.h>
- #endif
- #ifdef HAVE_SYS_SOCKET_H
- #include <sys/socket.h>
- #endif
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #ifdef HAVE_SYS_FCNTL_H
- #include <sys/fcntl.h>
- #endif
- #ifdef HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #ifdef HAVE_TIME_H
- #include <time.h>
- #endif
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
- #ifndef O_TEXT
- #define O_TEXT 0
- #endif
- #ifdef USE_DMALLOC
- #include <dmalloc.h>
- #define DMALLOC_FN_ARGS , file, line
- #else
- #define dmalloc_strdup(file, line, string, xalloc_b) strdup(string)
- #define dmalloc_malloc(file, line, size, func_id, alignment, xalloc_b) \
- malloc(size)
- #define DMALLOC_FUNC_MALLOC 0
- #define dmalloc_realloc(file, line, old_pnt, new_size, func_id, xalloc_b) \
- realloc((old_pnt), (new_size))
- #define DMALLOC_FUNC_REALLOC 0
- #define DMALLOC_FN_ARGS
- #endif
- void *
- _tor_malloc(size_t size DMALLOC_PARAMS)
- {
- void *result;
- #ifndef MALLOC_ZERO_WORKS
-
- if (size==0) {
- size=1;
- }
- #endif
- result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
- if (PREDICT_UNLIKELY(result == NULL)) {
- log_err(LD_MM,"Out of memory on malloc(). Dying.");
-
- exit(1);
- }
- return result;
- }
- void *
- _tor_malloc_zero(size_t size DMALLOC_PARAMS)
- {
- void *result = _tor_malloc(size DMALLOC_FN_ARGS);
- memset(result, 0, size);
- return result;
- }
- void *
- _tor_realloc(void *ptr, size_t size DMALLOC_PARAMS)
- {
- void *result;
- result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
- if (PREDICT_UNLIKELY(result == NULL)) {
- log_err(LD_MM,"Out of memory on realloc(). Dying.");
- exit(1);
- }
- return result;
- }
- char *
- _tor_strdup(const char *s DMALLOC_PARAMS)
- {
- char *dup;
- tor_assert(s);
- dup = dmalloc_strdup(file, line, s, 0);
- if (PREDICT_UNLIKELY(dup == NULL)) {
- log_err(LD_MM,"Out of memory on strdup(). Dying.");
- exit(1);
- }
- return dup;
- }
- char *
- _tor_strndup(const char *s, size_t n DMALLOC_PARAMS)
- {
- char *dup;
- tor_assert(s);
- dup = _tor_malloc((n+1) DMALLOC_FN_ARGS);
-
- strncpy(dup, s, n);
- dup[n]='\0';
- return dup;
- }
- void *
- _tor_memdup(const void *mem, size_t len DMALLOC_PARAMS)
- {
- char *dup;
- tor_assert(mem);
- dup = _tor_malloc(len DMALLOC_FN_ARGS);
- memcpy(dup, mem, len);
- return dup;
- }
- void
- _tor_free(void *mem)
- {
- tor_free(mem);
- }
- int
- tor_strstrip(char *s, const char *strip)
- {
- char *read = s;
- while (*read) {
- if (strchr(strip, *read)) {
- ++read;
- } else {
- *s++ = *read++;
- }
- }
- *s = '\0';
- return read-s;
- }
- int
- tor_strpartition(char *dest, size_t dest_len,
- const char *s, const char *insert, size_t n)
- {
- char *destp;
- size_t len_in, len_out, len_ins;
- int is_even, remaining;
- tor_assert(s);
- tor_assert(insert);
- tor_assert(n > 0);
- tor_assert(n < SIZE_T_CEILING);
- tor_assert(dest_len < SIZE_T_CEILING);
- len_in = strlen(s);
- len_ins = strlen(insert);
- tor_assert(len_in < SIZE_T_CEILING);
- tor_assert(len_in/n < SIZE_T_CEILING/len_ins);
- len_out = len_in + (len_in/n)*len_ins;
- is_even = (len_in%n) == 0;
- if (is_even && len_in)
- len_out -= len_ins;
- if (dest_len < len_out+1)
- return -1;
- destp = dest;
- remaining = len_in;
- while (remaining) {
- strncpy(destp, s, n);
- remaining -= n;
- if (remaining < 0) {
- break;
- } else if (remaining == 0) {
- *(destp+n) = '\0';
- break;
- }
- strncpy(destp+n, insert, len_ins+1);
- s += n;
- destp += n+len_ins;
- }
- tor_assert(len_out == strlen(dest));
- return 0;
- }
- const char *
- hex_str(const char *from, size_t fromlen)
- {
- static char buf[65];
- if (fromlen>(sizeof(buf)-1)/2)
- fromlen = (sizeof(buf)-1)/2;
- base16_encode(buf,sizeof(buf),from,fromlen);
- return buf;
- }
- void
- tor_strlower(char *s)
- {
- while (*s) {
- *s = TOR_TOLOWER(*s);
- ++s;
- }
- }
- void
- tor_strupper(char *s)
- {
- while (*s) {
- *s = TOR_TOUPPER(*s);
- ++s;
- }
- }
- int
- tor_strisprint(const char *s)
- {
- while (*s) {
- if (!TOR_ISPRINT(*s))
- return 0;
- s++;
- }
- return 1;
- }
- int
- tor_strisnonupper(const char *s)
- {
- while (*s) {
- if (TOR_ISUPPER(*s))
- return 0;
- s++;
- }
- return 1;
- }
- int
- strcmpstart(const char *s1, const char *s2)
- {
- size_t n = strlen(s2);
- return strncmp(s1, s2, n);
- }
- int
- strcasecmpstart(const char *s1, const char *s2)
- {
- size_t n = strlen(s2);
- return strncasecmp(s1, s2, n);
- }
- int
- strcmpend(const char *s1, const char *s2)
- {
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1)
- return strcmp(s1,s2);
- else
- return strncmp(s1+(n1-n2), s2, n2);
- }
- int
- strcasecmpend(const char *s1, const char *s2)
- {
- size_t n1 = strlen(s1), n2 = strlen(s2);
- if (n2>n1)
- return strcasecmp(s1,s2);
- else
- return strncasecmp(s1+(n1-n2), s2, n2);
- }
- const char *
- eat_whitespace(const char *s)
- {
- tor_assert(s);
- while (1) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
- while (*s && *s != '\n')
- ++s;
- }
- }
- }
- const char *
- eat_whitespace_no_nl(const char *s)
- {
- while (*s == ' ' || *s == '\t')
- ++s;
- return s;
- }
- const char *
- find_whitespace(const char *s)
- {
-
- while (1) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
- }
- int
- tor_mem_is_zero(const char *mem, size_t len)
- {
- static const char ZERO[] = {
- 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,
- };
- while (len >= sizeof(ZERO)) {
- if (memcmp(mem, ZERO, sizeof(ZERO)))
- return 0;
- len -= sizeof(ZERO);
- mem += sizeof(ZERO);
- }
-
- if (len)
- return ! memcmp(mem, ZERO, len);
- return 1;
- }
- int
- tor_digest_is_zero(const char *digest)
- {
- return tor_mem_is_zero(digest, DIGEST_LEN);
- }
- #define CHECK_STRTOX_RESULT() \
- \
- if (endptr == s) \
- goto err; \
- \
- if (!next && *endptr) \
- goto err; \
- \
- if (r < min || r > max) \
- goto err; \
- if (ok) *ok = 1; \
- if (next) *next = endptr; \
- return r; \
- err: \
- if (ok) *ok = 0; \
- if (next) *next = endptr; \
- return 0
- long
- tor_parse_long(const char *s, int base, long min, long max,
- int *ok, char **next)
- {
- char *endptr;
- long r;
- r = strtol(s, &endptr, base);
- CHECK_STRTOX_RESULT();
- }
- unsigned long
- tor_parse_ulong(const char *s, int base, unsigned long min,
- unsigned long max, int *ok, char **next)
- {
- char *endptr;
- unsigned long r;
- r = strtoul(s, &endptr, base);
- CHECK_STRTOX_RESULT();
- }
- uint64_t
- tor_parse_uint64(const char *s, int base, uint64_t min,
- uint64_t max, int *ok, char **next)
- {
- char *endptr;
- uint64_t r;
- #ifdef HAVE_STRTOULL
- r = (uint64_t)strtoull(s, &endptr, base);
- #elif defined(MS_WINDOWS)
- #if defined(_MSC_VER) && _MSC_VER < 1300
- tor_assert(base <= 10);
- r = (uint64_t)_atoi64(s);
- endptr = (char*)s;
- while (TOR_ISSPACE(*endptr)) endptr++;
- while (TOR_ISDIGIT(*endptr)) endptr++;
- #else
- r = (uint64_t)_strtoui64(s, &endptr, base);
- #endif
- #elif SIZEOF_LONG == 8
- r = (uint64_t)strtoul(s, &endptr, base);
- #else
- #error "I don't know how to parse 64-bit numbers."
- #endif
- CHECK_STRTOX_RESULT();
- }
- void
- base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
- {
- const char *end;
- char *cp;
- tor_assert(destlen >= srclen*2+1);
- tor_assert(destlen < SIZE_T_CEILING);
- cp = dest;
- end = src+srclen;
- while (src<end) {
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) >> 4 ];
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) & 0xf ];
- ++src;
- }
- *cp = '\0';
- }
- static INLINE int
- hex_decode_digit(char c)
- {
- switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'A': case 'a': return 10;
- case 'B': case 'b': return 11;
- case 'C': case 'c': return 12;
- case 'D': case 'd': return 13;
- case 'E': case 'e': return 14;
- case 'F': case 'f': return 15;
- default:
- return -1;
- }
- }
- int
- base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
- {
- const char *end;
- int v1,v2;
- if ((srclen % 2) != 0)
- return -1;
- if (destlen < srclen/2 || destlen > SIZE_T_CEILING)
- return -1;
- end = src+srclen;
- while (src<end) {
- v1 = hex_decode_digit(*src);
- v2 = hex_decode_digit(*(src+1));
- if (v1<0||v2<0)
- return -1;
- *(uint8_t*)dest = (v1<<4)|v2;
- ++dest;
- src+=2;
- }
- return 0;
- }
- char *
- esc_for_log(const char *s)
- {
- const char *cp;
- char *result, *outp;
- size_t len = 3;
- if (!s) {
- return tor_strdup("");
- }
- for (cp = s; *cp; ++cp) {
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- len += 2;
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
- ++len;
- else
- len += 4;
- break;
- }
- }
- result = outp = tor_malloc(len);
- *outp++ = '\"';
- for (cp = s; *cp; ++cp) {
- switch (*cp) {
- case '\\':
- case '\"':
- case '\'':
- *outp++ = '\\';
- *outp++ = *cp;
- break;
- case '\n':
- *outp++ = '\\';
- *outp++ = 'n';
- break;
- case '\t':
- *outp++ = '\\';
- *outp++ = 't';
- break;
- case '\r':
- *outp++ = '\\';
- *outp++ = 'r';
- break;
- default:
- if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
- *outp++ = *cp;
- } else {
- tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
- outp += 4;
- }
- break;
- }
- }
- *outp++ = '\"';
- *outp++ = 0;
- return result;
- }
- const char *
- escaped(const char *s)
- {
- static char *_escaped_val = NULL;
- if (_escaped_val)
- tor_free(_escaped_val);
- if (s)
- _escaped_val = esc_for_log(s);
- else
- _escaped_val = NULL;
- return _escaped_val;
- }
- void
- wrap_string(smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest)
- {
- size_t p0Len, pRestLen, pCurLen;
- const char *eos, *prefixCur;
- tor_assert(out);
- tor_assert(string);
- tor_assert(width);
- if (!prefix0)
- prefix0 = "";
- if (!prefixRest)
- prefixRest = "";
- p0Len = strlen(prefix0);
- pRestLen = strlen(prefixRest);
- tor_assert(width > p0Len && width > pRestLen);
- eos = strchr(string, '\0');
- tor_assert(eos);
- pCurLen = p0Len;
- prefixCur = prefix0;
- while ((eos-string)+pCurLen > width) {
- const char *eol = string + width - pCurLen;
- while (eol > string && *eol != ' ')
- --eol;
-
- if (eol > string) {
- size_t line_len = (eol-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eol-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string = eol + 1;
- } else {
- size_t line_len = width + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, width - pCurLen);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string += width-pCurLen;
- }
- prefixCur = prefixRest;
- pCurLen = pRestLen;
- }
- if (string < eos) {
- size_t line_len = (eos-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eos-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- }
- }
- long
- tv_udiff(const struct timeval *start, const struct timeval *end)
- {
- long udiff;
- long secdiff = end->tv_sec - start->tv_sec;
- if (labs(secdiff+1) > LONG_MAX/1000000) {
- log_warn(LD_GENERAL, "comparing times too far apart.");
- return LONG_MAX;
- }
- udiff = secdiff*1000000L + (end->tv_usec - start->tv_usec);
- return udiff;
- }
- int
- tv_cmp(const struct timeval *a, const struct timeval *b)
- {
- if (a->tv_sec > b->tv_sec)
- return 1;
- if (a->tv_sec < b->tv_sec)
- return -1;
- if (a->tv_usec > b->tv_usec)
- return 1;
- if (a->tv_usec < b->tv_usec)
- return -1;
- return 0;
- }
- void
- tv_add(struct timeval *a, const struct timeval *b)
- {
- a->tv_usec += b->tv_usec;
- a->tv_sec += b->tv_sec + (a->tv_usec / 1000000);
- a->tv_usec %= 1000000;
- }
- void
- tv_addms(struct timeval *a, long ms)
- {
- a->tv_usec += (ms * 1000) % 1000000;
- a->tv_sec += ((ms * 1000) / 1000000) + (a->tv_usec / 1000000);
- a->tv_usec %= 1000000;
- }
- #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
- static int
- n_leapdays(int y1, int y2)
- {
- --y1;
- --y2;
- return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
- }
- static const int days_per_month[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- time_t
- tor_timegm(struct tm *tm)
- {
-
- time_t ret;
- unsigned long year, days, hours, minutes;
- int i;
- year = tm->tm_year + 1900;
- if (year < 1970 || tm->tm_mon < 0 || tm->tm_mon > 11) {
- log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
- return -1;
- }
- days = 365 * (year-1970) + n_leapdays(1970,year);
- for (i = 0; i < tm->tm_mon; ++i)
- days += days_per_month[i];
- if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
- ++days;
- days += tm->tm_mday - 1;
- hours = days*24 + tm->tm_hour;
- minutes = hours*60 + tm->tm_min;
- ret = minutes*60 + tm->tm_sec;
- return ret;
- }
- static const char *WEEKDAY_NAMES[] =
- { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
- static const char *MONTH_NAMES[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- void
- format_rfc1123_time(char *buf, time_t t)
- {
- struct tm tm;
- tor_gmtime_r(&t, &tm);
- strftime(buf, RFC1123_TIME_LEN+1, "___, %d ___ %Y %H:%M:%S GMT", &tm);
- tor_assert(tm.tm_wday >= 0);
- tor_assert(tm.tm_wday <= 6);
- memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3);
- tor_assert(tm.tm_wday >= 0);
- tor_assert(tm.tm_mon <= 11);
- memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
- }
- int
- parse_rfc1123_time(const char *buf, time_t *t)
- {
- struct tm tm;
- char month[4];
- char weekday[4];
- int i, m;
- if (strlen(buf) != RFC1123_TIME_LEN)
- return -1;
- memset(&tm, 0, sizeof(tm));
- if (sscanf(buf, "%3s, %d %3s %d %d:%d:%d GMT", weekday,
- &tm.tm_mday, month, &tm.tm_year, &tm.tm_hour,
- &tm.tm_min, &tm.tm_sec) < 7) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
- m = -1;
- for (i = 0; i < 12; ++i) {
- if (!strcmp(month, MONTH_NAMES[i])) {
- m = i;
- break;
- }
- }
- if (m<0) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s: No such month", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mon = m;
- if (tm.tm_year < 1970) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL,
- "Got invalid RFC1123 time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_year -= 1900;
- *t = tor_timegm(&tm);
- return 0;
- }
- void
- format_local_iso_time(char *buf, time_t t)
- {
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_localtime_r(&t, &tm));
- }
- void
- format_iso_time(char *buf, time_t t)
- {
- struct tm tm;
- strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
- }
- int
- parse_iso_time(const char *cp, time_t *t)
- {
- struct tm st_tm;
- #ifdef HAVE_STRPTIME
- if (!strptime(cp, "%Y-%m-%d %H:%M:%S", &st_tm)) {
- log_warn(LD_GENERAL, "ISO time was unparseable by strptime"); return -1;
- }
- #else
- unsigned int year=0, month=0, day=0, hour=100, minute=100, second=100;
- if (sscanf(cp, "%u-%u-%u %u:%u:%u", &year, &month,
- &day, &hour, &minute, &second) < 6) {
- log_warn(LD_GENERAL, "ISO time was unparseable"); return -1;
- }
- if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
- hour > 23 || minute > 59 || second > 61) {
- log_warn(LD_GENERAL, "ISO time was nonsensical"); return -1;
- }
- st_tm.tm_year = year-1900;
- st_tm.tm_mon = month-1;
- st_tm.tm_mday = day;
- st_tm.tm_hour = hour;
- st_tm.tm_min = minute;
- st_tm.tm_sec = second;
- #endif
- if (st_tm.tm_year < 70) {
- char *esc = esc_for_log(cp);
- log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
- tor_free(esc);
- return -1;
- }
- *t = tor_timegm(&st_tm);
- return 0;
- }
- int
- write_all(int fd, const char *buf, size_t count, int isSocket)
- {
- size_t written = 0;
- int result;
- while (written != count) {
- if (isSocket)
- result = tor_socket_send(fd, buf+written, count-written, 0);
- else
- result = write(fd, buf+written, count-written);
- if (result<0)
- return -1;
- written += result;
- }
- return count;
- }
- int
- read_all(int fd, char *buf, size_t count, int isSocket)
- {
- size_t numread = 0;
- int result;
- if (count > SIZE_T_CEILING)
- return -1;
- while (numread != count) {
- if (isSocket)
- result = tor_socket_recv(fd, buf+numread, count-numread, 0);
- else
- result = read(fd, buf+numread, count-numread);
- if (result<0)
- return -1;
- else if (result == 0)
- break;
- numread += result;
- }
- return numread;
- }
- static void
- clean_name_for_stat(char *name)
- {
- #ifdef MS_WINDOWS
- size_t len = strlen(name);
- if (!len)
- return;
- if (name[len-1]=='\\' || name[len-1]=='/') {
- if (len == 1 || (len==3 && name[1]==':'))
- return;
- name[len-1]='\0';
- }
- #else
- (void)name;
- #endif
- }
- file_status_t
- file_status(const char *fname)
- {
- struct stat st;
- char *f;
- int r;
- f = tor_strdup(fname);
- clean_name_for_stat(f);
- r = stat(f, &st);
- tor_free(f);
- if (r) {
- if (errno == ENOENT) {
- return FN_NOENT;
- }
- return FN_ERROR;
- }
- if (st.st_mode & S_IFDIR)
- return FN_DIR;
- else if (st.st_mode & S_IFREG)
- return FN_FILE;
- else
- return FN_ERROR;
- }
- int
- check_private_dir(const char *dirname, cpd_check_t check)
- {
- int r;
- struct stat st;
- char *f;
- tor_assert(dirname);
- f = tor_strdup(dirname);
- clean_name_for_stat(f);
- r = stat(f, &st);
- tor_free(f);
- if (r) {
- if (errno != ENOENT) {
- log(LOG_WARN, LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
- return -1;
- }
- if (check == CPD_NONE) {
- log(LOG_WARN, LD_FS, "Directory %s does not exist.", dirname);
- return -1;
- } else if (check == CPD_CREATE) {
- log_info(LD_GENERAL, "Creating directory %s", dirname);
- #ifdef MS_WINDOWS
- r = mkdir(dirname);
- #else
- r = mkdir(dirname, 0700);
- #endif
- if (r) {
- log(LOG_WARN, LD_FS, "Error creating directory %s: %s", dirname,
- strerror(errno));
- return -1;
- }
- }
-
- return 0;
- }
- if (!(st.st_mode & S_IFDIR)) {
- log(LOG_WARN, LD_FS, "%s is not a directory", dirname);
- return -1;
- }
- #ifndef MS_WINDOWS
- if (st.st_uid != getuid()) {
- struct passwd *pw = NULL;
- char *process_ownername = NULL;
- pw = getpwuid(getuid());
- process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>");
- pw = getpwuid(st.st_uid);
- log(LOG_WARN, LD_FS, "%s is not owned by this user (%s, %d) but by "
- "%s (%d). Perhaps you are running Tor as the wrong user?",
- dirname, process_ownername, (int)getuid(),
- pw ? pw->pw_name : "<unknown>", (int)st.st_uid);
- tor_free(process_ownername);
- return -1;
- }
- if (st.st_mode & 0077) {
- log(LOG_WARN, LD_FS, "Fixing permissions on directory %s", dirname);
- if (chmod(dirname, 0700)) {
- log(LOG_WARN, LD_FS, "Could not chmod directory %s: %s", dirname,
- strerror(errno));
- return -1;
- } else {
- return 0;
- }
- }
- #endif
- return 0;
- }
- int
- write_str_to_file(const char *fname, const char *str, int bin)
- {
- #ifdef MS_WINDOWS
- if (!bin && strchr(str, '\r')) {
- log_warn(LD_BUG,
- "We're writing a text string that already contains a CR.");
- }
- #endif
- return write_bytes_to_file(fname, str, strlen(str), bin);
- }
- static int
- write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
- int open_flags)
- {
- size_t tempname_len;
- char *tempname;
- int fd;
- int result;
- tempname_len = strlen(fname)+16;
- tor_assert(tempname_len > strlen(fname));
- tempname = tor_malloc(tempname_len);
- if (open_flags & O_APPEND) {
- strlcpy(tempname, fname, tempname_len);
- } else {
- if (tor_snprintf(tempname, tempname_len, "%s.tmp", fname)<0) {
- log(LOG_WARN, LD_GENERAL, "Failed to generate filename");
- goto err;
- }
- }
- if ((fd = open(tempname, open_flags, 0600))
- < 0) {
- log(LOG_WARN, LD_FS, "Couldn't open \"%s\" for writing: %s", tempname,
- strerror(errno));
- goto err;
- }
- SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
- {
- result = write_all(fd, chunk->bytes, chunk->len, 0);
- if (result < 0 || (size_t)result != chunk->len) {
- log(LOG_WARN, LD_FS, "Error writing to \"%s\": %s", tempname,
- strerror(errno));
- close(fd);
- goto err;
- }
- });
- if (close(fd)) {
- log(LOG_WARN, LD_FS, "Error flushing to \"%s\": %s", tempname,
- strerror(errno));
- goto err;
- }
- if (!(open_flags & O_APPEND)) {
- if (replace_file(tempname, fname)) {
- log(LOG_WARN, LD_FS, "Error replacing \"%s\": %s", fname,
- strerror(errno));
- goto err;
- }
- }
- tor_free(tempname);
- return 0;
- err:
- tor_free(tempname);
- return -1;
- }
- int
- write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin)
- {
- int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT);
- return write_chunks_to_file_impl(fname, chunks, flags);
- }
- int
- write_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin)
- {
- int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT);
- int r;
- sized_chunk_t c = { str, len };
- smartlist_t *chunks = smartlist_create();
- smartlist_add(chunks, &c);
- r = write_chunks_to_file_impl(fname, chunks, flags);
- smartlist_free(chunks);
- return r;
- }
- int
- append_bytes_to_file(const char *fname, const char *str, size_t len,
- int bin)
- {
- int flags = O_WRONLY|O_CREAT|O_APPEND|(bin?O_BINARY:O_TEXT);
- int r;
- sized_chunk_t c = { str, len };
- smartlist_t *chunks = smartlist_create();
- smartlist_add(chunks, &c);
- r = write_chunks_to_file_impl(fname, chunks, flags);
- smartlist_free(chunks);
- return r;
- }
- char *
- read_file_to_str(const char *filename, int flags, struct stat *stat_out)
- {
- int fd;
- struct stat statbuf;
- char *string;
- int r;
- int bin = flags & RFTS_BIN;
- tor_assert(filename);
- fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
- if (fd<0) {
- int severity = LOG_WARN;
- if (errno == ENOENT && (flags & RFTS_IGNORE_MISSING))
- severity = LOG_INFO;
- log_fn(severity, LD_FS,"Could not open \"%s\": %s ",filename,
- strerror(errno));
- return NULL;
- }
- if (fstat(fd, &statbuf)<0) {
- close(fd);
- log_warn(LD_FS,"Could not fstat \"%s\".",filename);
- return NULL;
- }
- if ((uint64_t)(statbuf.st_size)+1 > SIZE_T_MAX)
- return NULL;
- string = tor_malloc((size_t)(statbuf.st_size+1));
- r = read_all(fd,string,(size_t)statbuf.st_size,0);
- if (r<0) {
- log_warn(LD_FS,"Error reading from file \"%s\": %s", filename,
- strerror(errno));
- tor_free(string);
- close(fd);
- return NULL;
- }
- string[r] = '\0';
- #ifdef MS_WINDOWS
- if (!bin && strchr(string, '\r')) {
- log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped "
- "when reading %s. Coping.",
- filename);
- tor_strstrip(string, "\r");
- r = strlen(string);
- }
- if (!bin) {
- statbuf.st_size = (size_t) r;
- } else
- #endif
- if (r != statbuf.st_size) {
-
- log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".",
- r, (long)statbuf.st_size,filename);
- tor_free(string);
- close(fd);
- return NULL;
- }
- close(fd);
- if (stat_out) {
- memcpy(stat_out, &statbuf, sizeof(struct stat));
- }
- return string;
- }
- char *
- parse_line_from_str(char *line, char **key_out, char **value_out)
- {
- char *key, *val, *cp;
- tor_assert(key_out);
- tor_assert(value_out);
- *key_out = *value_out = key = val = NULL;
-
- while (1) {
- while (TOR_ISSPACE(*line))
- ++line;
- if (*line == '#') {
- while (*line && *line != '\n')
- ++line;
- } else {
- break;
- }
- }
- if (!*line) {
- *key_out = *value_out = NULL;
- return line;
- }
-
- key = line;
- while (*line && !TOR_ISSPACE(*line) && *line != '#')
- ++line;
-
- while (*line == ' ' || *line == '\t')
- *line++ = '\0';
- val = line;
-
- while (*line && *line != '\n' && *line != '#')
- ++line;
- if (*line == '\n')
- cp = line++;
- else {
- cp = line-1;
- }
- while (cp>=val && TOR_ISSPACE(*cp))
- *cp-- = '\0';
- if (*line == '#') {
- do {
- *line++ = '\0';
- } while (*line && *line != '\n');
- if (*line == '\n')
- ++line;
- }
- *key_out = key;
- *value_out = val;
- return line;
- }
- char *
- expand_filename(const char *filename)
- {
- tor_assert(filename);
- if (*filename == '~') {
- size_t len;
- char *home, *result;
- const char *rest;
- if (filename[1] == '/' || filename[1] == '\0') {
- home = getenv("HOME");
- if (!home) {
- log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
- "expanding \"%s\"", filename);
- return NULL;
- }
- home = tor_strdup(home);
- rest = strlen(filename)>=2?(filename+2):NULL;
- } else {
- #ifdef HAVE_PWD_H
- char *username, *slash;
- slash = strchr(filename, '/');
- if (slash)
- username = tor_strndup(filename+1,slash-filename-1);
- else
- username = tor_strdup(filename+1);
- if (!(home = get_user_homedir(username))) {
- log_warn(LD_CONFIG,"Couldn't get homedir for \"%s\"",username);
- tor_free(username);
- return NULL;
- }
- tor_free(username);
- rest = slash ? (slash+1) : NULL;
- #else
- log_warn(LD_CONFIG, "Couldn't expend homedir on system without pwd.h");
- return tor_strdup(filename);
- #endif
- }
- tor_assert(home);
-
- if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
- home[strlen(home)-1] = '\0';
- }
-
- len = strlen(home)+strlen(rest)+16;
- result = tor_malloc(len);
- tor_snprintf(result,len,"%s"PATH_SEPARATOR"%s",home,rest?rest:"");
- tor_free(home);
- return result;
- } else {
- return tor_strdup(filename);
- }
- }
- smartlist_t *
- tor_listdir(const char *dirname)
- {
- smartlist_t *result;
- #ifdef MS_WINDOWS
- char *pattern;
- HANDLE handle;
- WIN32_FIND_DATA findData;
- size_t pattern_len = strlen(dirname)+16;
- pattern = tor_malloc(pattern_len);
- tor_snprintf(pattern, pattern_len, "%s\\*", dirname);
- if (!(handle = FindFirstFile(pattern, &findData))) {
- tor_free(pattern);
- return NULL;
- }
- result = smartlist_create();
- while (1) {
- if (strcmp(findData.cFileName, ".") &&
- strcmp(findData.cFileName, "..")) {
- smartlist_add(result, tor_strdup(findData.cFileName));
- }
- if (!FindNextFile(handle, &findData)) {
- if (GetLastError() != ERROR_NO_MORE_FILES) {
- log_warn(LD_FS, "Error reading directory.");
- }
- break;
- }
- }
- FindClose(handle);
- tor_free(pattern);
- #else
- DIR *d;
- struct dirent *de;
- if (!(d = opendir(dirname)))
- return NULL;
- result = smartlist_create();
- while ((de = readdir(d))) {
- if (!strcmp(de->d_name, ".") ||
- !strcmp(de->d_name, ".."))
- continue;
- smartlist_add(result, tor_strdup(de->d_name));
- }
- closedir(d);
- #endif
- return result;
- }
- int
- path_is_relative(const char *filename)
- {
- if (filename && filename[0] == '/')
- return 0;
- #ifdef MS_WINDOWS
- else if (filename && filename[0] == '\\')
- return 0;
- else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
- filename[1] == ':' && filename[2] == '\\')
- return 0;
- #endif
- else
- return 1;
- }
- int
- is_internal_IP(uint32_t ip, int for_listening)
- {
- if (for_listening && !ip)
- return 0;
- if (((ip & 0xff000000) == 0x0a000000) ||
- ((ip & 0xff000000) == 0x00000000) ||
- ((ip & 0xff000000) == 0x7f000000) ||
- ((ip & 0xffff0000) == 0xa9fe0000) ||
- ((ip & 0xfff00000) == 0xac100000) ||
- ((ip & 0xffff0000) == 0xc0a80000))
- return 1;
- return 0;
- }
- int
- parse_addr_port(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out)
- {
- const char *colon;
- char *_address = NULL;
- int _port;
- int ok = 1;
- tor_assert(addrport);
- colon = strchr(addrport, ':');
- if (colon) {
- _address = tor_strndup(addrport, colon-addrport);
- _port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
- if (!_port) {
- log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1));
- ok = 0;
- }
- if (!port_out) {
- char *esc_addrport = esc_for_log(addrport);
- log_fn(severity, LD_GENERAL,
- "Port %s given on %s when not required",
- escaped(colon+1), esc_addrport);
- tor_free(esc_addrport);
- ok = 0;
- }
- } else {
- _address = tor_strdup(addrport);
- _port = 0;
- }
- if (addr) {
-
- if (tor_lookup_hostname(_address,addr)) {
- log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address));
- ok = 0;
- *addr = 0;
- }
- *addr = ntohl(*addr);
- }
- if (address && ok) {
- *address = _address;
- } else {
- if (address)
- *address = NULL;
- tor_free(_address);
- }
- if (port_out)
- *port_out = ok ? ((uint16_t) _port) : 0;
- return ok ? 0 : -1;
- }
- int
- addr_mask_get_bits(uint32_t mask)
- {
- int i;
- if (mask == 0)
- return 0;
- if (mask == 0xFFFFFFFFu)
- return 32;
- for (i=0; i<=32; ++i) {
- if (mask == (uint32_t) ~((1u<<(32-i))-1)) {
- return i;
- }
- }
- return -1;
- }
- int
- parse_port_range(const char *port, uint16_t *port_min_out,
- uint16_t *port_max_out)
- {
- int port_min, port_max, ok;
- tor_assert(port_min_out);
- tor_assert(port_max_out);
- if (!port || *port == '\0' || strcmp(port, "*") == 0) {
- port_min = 1;
- port_max = 65535;
- } else {
- char *endptr = NULL;
- port_min = tor_parse_long(port, 10, 0, 65535, &ok, &endptr);
- if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- } else if (endptr && *endptr == '-') {
- port = endptr+1;
- endptr = NULL;
- port_max = tor_parse_long(port, 10, 1, 65536, &ok, &endptr);
- if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- }
- } else {
- port_max = port_min;
- }
- if (port_min > port_max) {
- log_warn(LD_GENERAL, "Insane port range on address policy; rejecting.");
- return -1;
- }
- }
- if (port_min < 1)
- port_min = 1;
- if (port_max > 65535)
- port_max = 65535;
- *port_min_out = (uint16_t) port_min;
- *port_max_out = (uint16_t) port_max;
- return 0;
- }
- int
- parse_addr_and_port_range(const char *s, uint32_t *addr_out,
- uint32_t *mask_out, uint16_t *port_min_out,
- uint16_t *port_max_out)
- {
- char *address;
- char *mask, *port, *endptr;
- struct in_addr in;
- int bits;
- tor_assert(s);
- tor_assert(addr_out);
- tor_assert(mask_out);
- tor_assert(port_min_out);
- tor_assert(port_max_out);
- address = tor_strdup(s);
-
- mask = strchr(address,'/');
- port = strchr(mask?mask:address,':');
- if (mask)
- *mask++ = '\0';
- if (port)
- *port++ = '\0';
-
- if (strcmp(address,"*")==0) {
- *addr_out = 0;
- } else if (tor_inet_aton(address, &in) != 0) {
- *addr_out = ntohl(in.s_addr);
- } else {
- log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
- escaped(address));
- goto err;
- }
- if (!mask) {
- if (strcmp(address,"*")==0)
- *mask_out = 0;
- else
- *mask_out = 0xFFFFFFFFu;
- } else {
- endptr = NULL;
- bits = (int) strtol(mask, &endptr, 10);
- if (!*endptr) {
-
- if (bits < 0 || bits > 32) {
- log_warn(LD_GENERAL,
- "Bad number of mask bits on address range; rejecting.");
- goto err;
- }
- *mask_out = ~((1u<<(32-bits))-1);
- } else if (tor_inet_aton(mask, &in) != 0) {
- *mask_out = ntohl(in.s_addr);
- } else {
- log_warn(LD_GENERAL,
- "Malformed mask %s on address range; rejecting.",
- escaped(mask));
- goto err;
- }
- }
- if (parse_port_range(port, port_min_out, port_max_out)<0)
- goto err;
- tor_free(address);
- return 0;
- err:
- tor_free(address);
- return -1;
- }
- int
- tor_inet_ntoa(struct in_addr *in, char *buf, size_t buf_len)
- {
- uint32_t a = ntohl(in->s_addr);
- return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
- (int)(uint8_t)((a>>24)&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a )&0xff));
- }
- char *
- tor_dup_addr(uint32_t addr)
- {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr in;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, buf, sizeof(buf));
- return tor_strdup(buf);
- }
- int
- get_interface_address(int severity, uint32_t *addr)
- {
- int sock=-1, r=-1;
- struct sockaddr_in target_addr, my_addr;
- socklen_t my_addr_len = sizeof(my_addr);
- tor_assert(addr);
- *addr = 0;
- sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
- if (sock < 0) {
- int e = tor_socket_errno(-1);
- log_fn(severity, LD_NET, "unable to create socket: %s",
- tor_socket_strerror(e));
- goto err;
- }
- memset(&target_addr, 0, sizeof(target_addr));
- target_addr.sin_family = AF_INET;
-
- target_addr.sin_port = 9;
-
- target_addr.sin_addr.s_addr = htonl(0x12000001);
- if (connect(sock,(struct sockaddr *)&target_addr,sizeof(target_addr))<0) {
- int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "connect() failed: %s", tor_socket_strerror(e));
- goto err;
- }
- if (getsockname(sock, (struct sockaddr*)&my_addr, &my_addr_len)) {
- int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s",
- tor_socket_strerror(e));
- goto err;
- }
- *addr = ntohl(my_addr.sin_addr.s_addr);
- r=0;
- err:
- if (sock >= 0)
- tor_close_socket(sock);
- return r;
- }
- #ifndef MS_WINDOWS
- static int start_daemon_called = 0;
- static int finish_daemon_called = 0;
- static int daemon_filedes[2];
- void
- start_daemon(void)
- {
- pid_t pid;
- if (start_daemon_called)
- return;
- start_daemon_called = 1;
- pipe(daemon_filedes);
- pid = fork();
- if (pid < 0) {
- log_err(LD_GENERAL,"fork failed. Exiting.");
- exit(1);
- }
- if (pid) {
- int ok;
- char c;
- close(daemon_filedes[1]);
- ok = -1;
- while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
- if (c == '.')
- ok = 1;
- }
- fflush(stdout);
- if (ok == 1)
- exit(0);
- else
- exit(1);
- } else {
- close(daemon_filedes[0]);
- pid = setsid();
-
- if (fork() != 0) {
- exit(0);
- }
- return;
- }
- }
- void
- finish_daemon(const char *desired_cwd)
- {
- int nullfd;
- char c = '.';
- if (finish_daemon_called)
- return;
- if (!start_daemon_called)
- start_daemon();
- finish_daemon_called = 1;
- if (!desired_cwd)
- desired_cwd = "/";
-
- if (chdir(desired_cwd) < 0) {
- log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
- exit(1);
- }
- nullfd = open("/dev/null",
- O_CREAT | O_RDWR | O_APPEND);
- if (nullfd < 0) {
- log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
- exit(1);
- }
-
- if (dup2(nullfd,0) < 0 ||
- dup2(nullfd,1) < 0 ||
- dup2(nullfd,2) < 0) {
- log_err(LD_GENERAL,"dup2 failed. Exiting.");
- exit(1);
- }
- if (nullfd > 2)
- close(nullfd);
- write(daemon_filedes[1], &c, sizeof(char));
- close(daemon_filedes[1]);
- }
- #else
- void
- start_daemon(void)
- {
- }
- void
- finish_daemon(const char *cp)
- {
- (void)cp;
- }
- #endif
- void
- write_pidfile(char *filename)
- {
- FILE *pidfile;
- if ((pidfile = fopen(filename, "w")) == NULL) {
- log_warn(LD_FS, "Unable to open \"%s\" for writing: %s", filename,
- strerror(errno));
- } else {
- #ifdef MS_WINDOWS
- fprintf(pidfile, "%d\n", (int)_getpid());
- #else
- fprintf(pidfile, "%d\n", (int)getpid());
- #endif
- fclose(pidfile);
- }
- }
|