misc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. /*
  2. * Platform-independent routines shared between all PuTTY programs.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdarg.h>
  7. #include <limits.h>
  8. #include <ctype.h>
  9. #include <assert.h>
  10. #include "putty.h"
  11. /*
  12. * Parse a string block size specification. This is approximately a
  13. * subset of the block size specs supported by GNU fileutils:
  14. * "nk" = n kilobytes
  15. * "nM" = n megabytes
  16. * "nG" = n gigabytes
  17. * All numbers are decimal, and suffixes refer to powers of two.
  18. * Case-insensitive.
  19. */
  20. __int64 parse_blocksize64(const char *bs)
  21. {
  22. char *suf;
  23. __int64 r = strtoul(bs, &suf, 10);
  24. if (*suf != '\0') {
  25. while (*suf && isspace((unsigned char)*suf)) suf++;
  26. switch (*suf) {
  27. case 'k': case 'K':
  28. r *= 1024ul;
  29. break;
  30. case 'm': case 'M':
  31. r *= 1024ul * 1024ul;
  32. break;
  33. case 'g': case 'G':
  34. r *= 1024ul * 1024ul * 1024ul;
  35. break;
  36. case '\0':
  37. default:
  38. break;
  39. }
  40. }
  41. return r;
  42. }
  43. unsigned long parse_blocksize(const char *bs)
  44. {
  45. return (unsigned long)parse_blocksize64(bs);
  46. }
  47. /*
  48. * Parse a ^C style character specification.
  49. * Returns NULL in `next' if we didn't recognise it as a control character,
  50. * in which case `c' should be ignored.
  51. * The precise current parsing is an oddity inherited from the terminal
  52. * answerback-string parsing code. All sequences start with ^; all except
  53. * ^<123> are two characters. The ones that are worth keeping are probably:
  54. * ^? 127
  55. * ^@A-Z[\]^_ 0-31
  56. * a-z 1-26
  57. * <num> specified by number (decimal, 0octal, 0xHEX)
  58. * ~ ^ escape
  59. */
  60. char ctrlparse(char *s, char **next)
  61. {
  62. char c = 0;
  63. if (*s != '^') {
  64. *next = NULL;
  65. } else {
  66. s++;
  67. if (*s == '\0') {
  68. *next = NULL;
  69. } else if (*s == '<') {
  70. s++;
  71. c = (char)strtol(s, next, 0);
  72. if ((*next == s) || (**next != '>')) {
  73. c = 0;
  74. *next = NULL;
  75. } else
  76. (*next)++;
  77. } else if (*s >= 'a' && *s <= 'z') {
  78. c = (*s - ('a' - 1));
  79. *next = s+1;
  80. } else if ((*s >= '@' && *s <= '_') || *s == '?' || (*s & 0x80)) {
  81. c = ('@' ^ *s);
  82. *next = s+1;
  83. } else if (*s == '~') {
  84. c = '^';
  85. *next = s+1;
  86. }
  87. }
  88. return c;
  89. }
  90. prompts_t *new_prompts(void *frontend)
  91. {
  92. prompts_t *p = snew(prompts_t);
  93. p->prompts = NULL;
  94. p->n_prompts = 0;
  95. p->frontend = frontend;
  96. p->data = NULL;
  97. p->to_server = TRUE; /* to be on the safe side */
  98. p->name = p->instruction = NULL;
  99. p->name_reqd = p->instr_reqd = FALSE;
  100. return p;
  101. }
  102. void add_prompt(prompts_t *p, char *promptstr, int echo)
  103. {
  104. prompt_t *pr = snew(prompt_t);
  105. pr->prompt = promptstr;
  106. pr->echo = echo;
  107. pr->result = NULL;
  108. pr->resultsize = 0;
  109. p->n_prompts++;
  110. p->prompts = sresize(p->prompts, p->n_prompts, prompt_t *);
  111. p->prompts[p->n_prompts-1] = pr;
  112. }
  113. void prompt_ensure_result_size(prompt_t *pr, int newlen)
  114. {
  115. if ((int)pr->resultsize < newlen) {
  116. char *newbuf;
  117. newlen = newlen * 5 / 4 + 512; /* avoid too many small allocs */
  118. /*
  119. * We don't use sresize / realloc here, because we will be
  120. * storing sensitive stuff like passwords in here, and we want
  121. * to make sure that the data doesn't get copied around in
  122. * memory without the old copy being destroyed.
  123. */
  124. newbuf = snewn(newlen, char);
  125. memcpy(newbuf, pr->result, pr->resultsize);
  126. smemclr(pr->result, pr->resultsize);
  127. sfree(pr->result);
  128. pr->result = newbuf;
  129. pr->resultsize = newlen;
  130. }
  131. }
  132. void prompt_set_result(prompt_t *pr, const char *newstr)
  133. {
  134. prompt_ensure_result_size(pr, strlen(newstr) + 1);
  135. strcpy(pr->result, newstr);
  136. }
  137. void free_prompts(prompts_t *p)
  138. {
  139. size_t i;
  140. for (i=0; i < p->n_prompts; i++) {
  141. prompt_t *pr = p->prompts[i];
  142. smemclr(pr->result, pr->resultsize); /* burn the evidence */
  143. sfree(pr->result);
  144. sfree(pr->prompt);
  145. sfree(pr);
  146. }
  147. sfree(p->prompts);
  148. sfree(p->name);
  149. sfree(p->instruction);
  150. sfree(p);
  151. }
  152. /* ----------------------------------------------------------------------
  153. * String handling routines.
  154. */
  155. char *dupstr(const char *s)
  156. {
  157. char *p = NULL;
  158. if (s) {
  159. int len = strlen(s);
  160. p = snewn(len + 1, char);
  161. strcpy(p, s);
  162. }
  163. return p;
  164. }
  165. /* Allocate the concatenation of N strings. Terminate arg list with NULL. */
  166. char *dupcat(const char *s1, ...)
  167. {
  168. int len;
  169. char *p, *q, *sn;
  170. va_list ap;
  171. len = strlen(s1);
  172. va_start(ap, s1);
  173. while (1) {
  174. sn = va_arg(ap, char *);
  175. if (!sn)
  176. break;
  177. len += strlen(sn);
  178. }
  179. va_end(ap);
  180. p = snewn(len + 1, char);
  181. strcpy(p, s1);
  182. q = p + strlen(p);
  183. va_start(ap, s1);
  184. while (1) {
  185. sn = va_arg(ap, char *);
  186. if (!sn)
  187. break;
  188. strcpy(q, sn);
  189. q += strlen(q);
  190. }
  191. va_end(ap);
  192. return p;
  193. }
  194. void burnstr(char *string) /* sfree(str), only clear it first */
  195. {
  196. if (string) {
  197. smemclr(string, strlen(string));
  198. sfree(string);
  199. }
  200. }
  201. int toint(unsigned u)
  202. {
  203. /*
  204. * Convert an unsigned to an int, without running into the
  205. * undefined behaviour which happens by the strict C standard if
  206. * the value overflows. You'd hope that sensible compilers would
  207. * do the sensible thing in response to a cast, but actually I
  208. * don't trust modern compilers not to do silly things like
  209. * assuming that _obviously_ you wouldn't have caused an overflow
  210. * and so they can elide an 'if (i < 0)' test immediately after
  211. * the cast.
  212. *
  213. * Sensible compilers ought of course to optimise this entire
  214. * function into 'just return the input value'!
  215. */
  216. if (u <= (unsigned)INT_MAX)
  217. return (int)u;
  218. else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
  219. return INT_MIN + (int)(u - (unsigned)INT_MIN);
  220. else
  221. return INT_MIN; /* fallback; should never occur on binary machines */
  222. }
  223. /*
  224. * Do an sprintf(), but into a custom-allocated buffer.
  225. *
  226. * Currently I'm doing this via vsnprintf. This has worked so far,
  227. * but it's not good, because vsnprintf is not available on all
  228. * platforms. There's an ifdef to use `_vsnprintf', which seems
  229. * to be the local name for it on Windows. Other platforms may
  230. * lack it completely, in which case it'll be time to rewrite
  231. * this function in a totally different way.
  232. *
  233. * The only `properly' portable solution I can think of is to
  234. * implement my own format string scanner, which figures out an
  235. * upper bound for the length of each formatting directive,
  236. * allocates the buffer as it goes along, and calls sprintf() to
  237. * actually process each directive. If I ever need to actually do
  238. * this, some caveats:
  239. *
  240. * - It's very hard to find a reliable upper bound for
  241. * floating-point values. %f, in particular, when supplied with
  242. * a number near to the upper or lower limit of representable
  243. * numbers, could easily take several hundred characters. It's
  244. * probably feasible to predict this statically using the
  245. * constants in <float.h>, or even to predict it dynamically by
  246. * looking at the exponent of the specific float provided, but
  247. * it won't be fun.
  248. *
  249. * - Don't forget to _check_, after calling sprintf, that it's
  250. * used at most the amount of space we had available.
  251. *
  252. * - Fault any formatting directive we don't fully understand. The
  253. * aim here is to _guarantee_ that we never overflow the buffer,
  254. * because this is a security-critical function. If we see a
  255. * directive we don't know about, we should panic and die rather
  256. * than run any risk.
  257. */
  258. char *dupprintf(const char *fmt, ...)
  259. {
  260. char *ret;
  261. va_list ap;
  262. va_start(ap, fmt);
  263. ret = dupvprintf(fmt, ap);
  264. va_end(ap);
  265. return ret;
  266. }
  267. char *dupvprintf(const char *fmt, va_list ap)
  268. {
  269. char *buf;
  270. int len, size;
  271. buf = snewn(512, char);
  272. size = 512;
  273. while (1) {
  274. #ifdef _WINDOWS
  275. #define vsnprintf _vsnprintf
  276. #endif
  277. #ifdef va_copy
  278. /* Use the `va_copy' macro mandated by C99, if present.
  279. * XXX some environments may have this as __va_copy() */
  280. va_list aq;
  281. va_copy(aq, ap);
  282. len = vsnprintf(buf, size, fmt, aq);
  283. va_end(aq);
  284. #else
  285. /* Ugh. No va_copy macro, so do something nasty.
  286. * Technically, you can't reuse a va_list like this: it is left
  287. * unspecified whether advancing a va_list pointer modifies its
  288. * value or something it points to, so on some platforms calling
  289. * vsnprintf twice on the same va_list might fail hideously
  290. * (indeed, it has been observed to).
  291. * XXX the autoconf manual suggests that using memcpy() will give
  292. * "maximum portability". */
  293. len = vsnprintf(buf, size, fmt, ap);
  294. #endif
  295. if (len >= 0 && len < size) {
  296. /* This is the C99-specified criterion for snprintf to have
  297. * been completely successful. */
  298. return buf;
  299. } else if (len > 0) {
  300. /* This is the C99 error condition: the returned length is
  301. * the required buffer size not counting the NUL. */
  302. size = len + 1;
  303. } else {
  304. /* This is the pre-C99 glibc error condition: <0 means the
  305. * buffer wasn't big enough, so we enlarge it a bit and hope. */
  306. size += 512;
  307. }
  308. buf = sresize(buf, size, char);
  309. }
  310. }
  311. /*
  312. * Read an entire line of text from a file. Return a buffer
  313. * malloced to be as big as necessary (caller must free).
  314. */
  315. char *fgetline(FILE *fp)
  316. {
  317. char *ret = snewn(512, char);
  318. int size = 512, len = 0;
  319. while (fgets(ret + len, size - len, fp)) {
  320. len += strlen(ret + len);
  321. if (ret[len-1] == '\n')
  322. break; /* got a newline, we're done */
  323. size = len + 512;
  324. ret = sresize(ret, size, char);
  325. }
  326. if (len == 0) { /* first fgets returned NULL */
  327. sfree(ret);
  328. return NULL;
  329. }
  330. ret[len] = '\0';
  331. return ret;
  332. }
  333. /* ----------------------------------------------------------------------
  334. * Base64 encoding routine. This is required in public-key writing
  335. * but also in HTTP proxy handling, so it's centralised here.
  336. */
  337. void base64_encode_atom(unsigned char *data, int n, char *out)
  338. {
  339. static const char base64_chars[] =
  340. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  341. unsigned word;
  342. word = data[0] << 16;
  343. if (n > 1)
  344. word |= data[1] << 8;
  345. if (n > 2)
  346. word |= data[2];
  347. out[0] = base64_chars[(word >> 18) & 0x3F];
  348. out[1] = base64_chars[(word >> 12) & 0x3F];
  349. if (n > 1)
  350. out[2] = base64_chars[(word >> 6) & 0x3F];
  351. else
  352. out[2] = '=';
  353. if (n > 2)
  354. out[3] = base64_chars[word & 0x3F];
  355. else
  356. out[3] = '=';
  357. }
  358. /* ----------------------------------------------------------------------
  359. * Generic routines to deal with send buffers: a linked list of
  360. * smallish blocks, with the operations
  361. *
  362. * - add an arbitrary amount of data to the end of the list
  363. * - remove the first N bytes from the list
  364. * - return a (pointer,length) pair giving some initial data in
  365. * the list, suitable for passing to a send or write system
  366. * call
  367. * - retrieve a larger amount of initial data from the list
  368. * - return the current size of the buffer chain in bytes
  369. */
  370. /* MP:
  371. * Default granule of 512 leads to low performance.
  372. */
  373. #define BUFFER_MIN_GRANULE 512*2*32
  374. struct bufchain_granule {
  375. struct bufchain_granule *next;
  376. char *bufpos, *bufend, *bufmax;
  377. };
  378. void bufchain_init(bufchain *ch)
  379. {
  380. ch->head = ch->tail = NULL;
  381. ch->buffersize = 0;
  382. }
  383. void bufchain_clear(bufchain *ch)
  384. {
  385. struct bufchain_granule *b;
  386. while (ch->head) {
  387. b = ch->head;
  388. ch->head = ch->head->next;
  389. sfree(b);
  390. }
  391. ch->tail = NULL;
  392. ch->buffersize = 0;
  393. }
  394. int bufchain_size(bufchain *ch)
  395. {
  396. return ch->buffersize;
  397. }
  398. void bufchain_add(bufchain *ch, const void *data, int len)
  399. {
  400. const char *buf = (const char *)data;
  401. if (len == 0) return;
  402. ch->buffersize += len;
  403. while (len > 0) {
  404. if (ch->tail && ch->tail->bufend < ch->tail->bufmax) {
  405. int copylen = min(len, ch->tail->bufmax - ch->tail->bufend);
  406. memcpy(ch->tail->bufend, buf, copylen);
  407. buf += copylen;
  408. len -= copylen;
  409. ch->tail->bufend += copylen;
  410. }
  411. if (len > 0) {
  412. int grainlen =
  413. max(sizeof(struct bufchain_granule) + len, BUFFER_MIN_GRANULE);
  414. struct bufchain_granule *newbuf;
  415. newbuf = smalloc(grainlen);
  416. newbuf->bufpos = newbuf->bufend =
  417. (char *)newbuf + sizeof(struct bufchain_granule);
  418. newbuf->bufmax = (char *)newbuf + grainlen;
  419. newbuf->next = NULL;
  420. if (ch->tail)
  421. ch->tail->next = newbuf;
  422. else
  423. ch->head = newbuf;
  424. ch->tail = newbuf;
  425. }
  426. }
  427. }
  428. void bufchain_consume(bufchain *ch, int len)
  429. {
  430. struct bufchain_granule *tmp;
  431. assert(ch->buffersize >= len);
  432. while (len > 0) {
  433. int remlen = len;
  434. assert(ch->head != NULL);
  435. if (remlen >= ch->head->bufend - ch->head->bufpos) {
  436. remlen = ch->head->bufend - ch->head->bufpos;
  437. tmp = ch->head;
  438. ch->head = tmp->next;
  439. if (!ch->head)
  440. ch->tail = NULL;
  441. sfree(tmp);
  442. } else
  443. ch->head->bufpos += remlen;
  444. ch->buffersize -= remlen;
  445. len -= remlen;
  446. }
  447. }
  448. void bufchain_prefix(bufchain *ch, void **data, int *len)
  449. {
  450. *len = ch->head->bufend - ch->head->bufpos;
  451. *data = ch->head->bufpos;
  452. }
  453. void bufchain_fetch(bufchain *ch, void *data, int len)
  454. {
  455. struct bufchain_granule *tmp;
  456. char *data_c = (char *)data;
  457. tmp = ch->head;
  458. assert(ch->buffersize >= len);
  459. while (len > 0) {
  460. int remlen = len;
  461. assert(tmp != NULL);
  462. if (remlen >= tmp->bufend - tmp->bufpos)
  463. remlen = tmp->bufend - tmp->bufpos;
  464. memcpy(data_c, tmp->bufpos, remlen);
  465. tmp = tmp->next;
  466. len -= remlen;
  467. data_c += remlen;
  468. }
  469. }
  470. /* ----------------------------------------------------------------------
  471. * My own versions of malloc, realloc and free. Because I want
  472. * malloc and realloc to bomb out and exit the program if they run
  473. * out of memory, realloc to reliably call malloc if passed a NULL
  474. * pointer, and free to reliably do nothing if passed a NULL
  475. * pointer. We can also put trace printouts in, if we need to; and
  476. * we can also replace the allocator with an ElectricFence-like
  477. * one.
  478. */
  479. #ifdef MINEFIELD
  480. void *minefield_c_malloc(size_t size);
  481. void minefield_c_free(void *p);
  482. void *minefield_c_realloc(void *p, size_t size);
  483. #endif
  484. #ifdef MALLOC_LOG
  485. static FILE *fp = NULL;
  486. static char *mlog_file = NULL;
  487. static int mlog_line = 0;
  488. void mlog(char *file, int line)
  489. {
  490. mlog_file = file;
  491. mlog_line = line;
  492. if (!fp) {
  493. fp = fopen("putty_mem.log", "w");
  494. setvbuf(fp, NULL, _IONBF, BUFSIZ);
  495. }
  496. if (fp)
  497. fprintf(fp, "%s:%d: ", file, line);
  498. }
  499. #endif
  500. void *safemalloc(size_t n, size_t size)
  501. {
  502. void *p;
  503. if (n > INT_MAX / size) {
  504. p = NULL;
  505. } else {
  506. size *= n;
  507. if (size == 0) size = 1;
  508. #ifdef MINEFIELD
  509. p = minefield_c_malloc(size);
  510. #else
  511. p = malloc(size);
  512. #endif
  513. }
  514. if (!p) {
  515. char str[200];
  516. #ifdef MALLOC_LOG
  517. sprintf(str, "Out of memory! (%s:%d, size=%d)",
  518. mlog_file, mlog_line, size);
  519. fprintf(fp, "*** %s\n", str);
  520. fclose(fp);
  521. #else
  522. strcpy(str, "Out of memory!");
  523. #endif
  524. modalfatalbox(str);
  525. }
  526. #ifdef MALLOC_LOG
  527. if (fp)
  528. fprintf(fp, "malloc(%d) returns %p\n", size, p);
  529. #endif
  530. return p;
  531. }
  532. void *saferealloc(void *ptr, size_t n, size_t size)
  533. {
  534. void *p;
  535. if (n > INT_MAX / size) {
  536. p = NULL;
  537. } else {
  538. size *= n;
  539. if (!ptr) {
  540. #ifdef MINEFIELD
  541. p = minefield_c_malloc(size);
  542. #else
  543. p = malloc(size);
  544. #endif
  545. } else {
  546. #ifdef MINEFIELD
  547. p = minefield_c_realloc(ptr, size);
  548. #else
  549. p = realloc(ptr, size);
  550. #endif
  551. }
  552. }
  553. if (!p) {
  554. char str[200];
  555. #ifdef MALLOC_LOG
  556. sprintf(str, "Out of memory! (%s:%d, size=%d)",
  557. mlog_file, mlog_line, size);
  558. fprintf(fp, "*** %s\n", str);
  559. fclose(fp);
  560. #else
  561. strcpy(str, "Out of memory!");
  562. #endif
  563. modalfatalbox(str);
  564. }
  565. #ifdef MALLOC_LOG
  566. if (fp)
  567. fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
  568. #endif
  569. return p;
  570. }
  571. void safefree(void *ptr)
  572. {
  573. if (ptr) {
  574. #ifdef MALLOC_LOG
  575. if (fp)
  576. fprintf(fp, "free(%p)\n", ptr);
  577. #endif
  578. #ifdef MINEFIELD
  579. minefield_c_free(ptr);
  580. #else
  581. free(ptr);
  582. #endif
  583. }
  584. #ifdef MALLOC_LOG
  585. else if (fp)
  586. fprintf(fp, "freeing null pointer - no action taken\n");
  587. #endif
  588. }
  589. /* ----------------------------------------------------------------------
  590. * Debugging routines.
  591. */
  592. #ifdef DEBUG
  593. extern void dputs(char *); /* defined in per-platform *misc.c */
  594. void debug_printf(char *fmt, ...)
  595. {
  596. char *buf;
  597. va_list ap;
  598. va_start(ap, fmt);
  599. buf = dupvprintf(fmt, ap);
  600. dputs(buf);
  601. sfree(buf);
  602. va_end(ap);
  603. }
  604. void debug_memdump(void *buf, int len, int L)
  605. {
  606. int i;
  607. unsigned char *p = buf;
  608. char foo[17];
  609. if (L) {
  610. int delta;
  611. debug_printf("\t%d (0x%x) bytes:\n", len, len);
  612. delta = 15 & (unsigned long int) p;
  613. p -= delta;
  614. len += delta;
  615. }
  616. for (; 0 < len; p += 16, len -= 16) {
  617. dputs(" ");
  618. if (L)
  619. debug_printf("%p: ", p);
  620. strcpy(foo, "................"); /* sixteen dots */
  621. for (i = 0; i < 16 && i < len; ++i) {
  622. if (&p[i] < (unsigned char *) buf) {
  623. dputs(" "); /* 3 spaces */
  624. foo[i] = ' ';
  625. } else {
  626. debug_printf("%c%02.2x",
  627. &p[i] != (unsigned char *) buf
  628. && i % 4 ? '.' : ' ', p[i]
  629. );
  630. if (p[i] >= ' ' && p[i] <= '~')
  631. foo[i] = (char) p[i];
  632. }
  633. }
  634. foo[i] = '\0';
  635. debug_printf("%*s%s\n", (16 - i) * 3 + 2, "", foo);
  636. }
  637. }
  638. #endif /* def DEBUG */
  639. /*
  640. * Determine whether or not a Conf represents a session which can
  641. * sensibly be launched right now.
  642. */
  643. int conf_launchable(Conf *conf)
  644. {
  645. if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
  646. return conf_get_str(conf, CONF_serline)[0] != 0;
  647. else
  648. return conf_get_str(conf, CONF_host)[0] != 0;
  649. }
  650. char const *conf_dest(Conf *conf)
  651. {
  652. if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
  653. return conf_get_str(conf, CONF_serline);
  654. else
  655. return conf_get_str(conf, CONF_host);
  656. }
  657. #ifndef PLATFORM_HAS_SMEMCLR
  658. /*
  659. * Securely wipe memory.
  660. *
  661. * The actual wiping is no different from what memset would do: the
  662. * point of 'securely' is to try to be sure over-clever compilers
  663. * won't optimise away memsets on variables that are about to be freed
  664. * or go out of scope. See
  665. * https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/771-BSI.html
  666. *
  667. * Some platforms (e.g. Windows) may provide their own version of this
  668. * function.
  669. */
  670. void smemclr(void *b, size_t n) {
  671. volatile char *vp;
  672. if (b && n > 0) {
  673. /*
  674. * Zero out the memory.
  675. */
  676. memset(b, 0, n);
  677. /*
  678. * Perform a volatile access to the object, forcing the
  679. * compiler to admit that the previous memset was important.
  680. *
  681. * This while loop should in practice run for zero iterations
  682. * (since we know we just zeroed the object out), but in
  683. * theory (as far as the compiler knows) it might range over
  684. * the whole object. (If we had just written, say, '*vp =
  685. * *vp;', a compiler could in principle have 'helpfully'
  686. * optimised the memset into only zeroing out the first byte.
  687. * This should be robust.)
  688. */
  689. vp = b;
  690. while (*vp) vp++;
  691. }
  692. }
  693. #endif