util.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /*
  2. * mbsync - mailbox synchronizer
  3. * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
  4. * Copyright (C) 2002-2006,2011,2012 Oswald Buddenhagen <ossi@users.sf.net>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. * As a special exception, mbsync may be linked with the OpenSSL library,
  20. * despite that library's more restrictive license.
  21. */
  22. #include "common.h"
  23. #include <assert.h>
  24. #include <stdlib.h>
  25. #include <unistd.h>
  26. #include <fcntl.h>
  27. #include <string.h>
  28. #include <pwd.h>
  29. static int need_nl;
  30. void
  31. flushn( void )
  32. {
  33. if (need_nl) {
  34. putchar( '\n' );
  35. fflush( stdout );
  36. need_nl = 0;
  37. }
  38. }
  39. static void
  40. printn( const char *msg, va_list va )
  41. {
  42. if (*msg == '\v')
  43. msg++;
  44. else
  45. flushn();
  46. vprintf( msg, va );
  47. fflush( stdout );
  48. }
  49. void
  50. debug( const char *msg, ... )
  51. {
  52. va_list va;
  53. if (DFlags & DEBUG) {
  54. va_start( va, msg );
  55. vprintf( msg, va );
  56. va_end( va );
  57. fflush( stdout );
  58. need_nl = 0;
  59. }
  60. }
  61. void
  62. debugn( const char *msg, ... )
  63. {
  64. va_list va;
  65. if (DFlags & DEBUG) {
  66. va_start( va, msg );
  67. vprintf( msg, va );
  68. va_end( va );
  69. fflush( stdout );
  70. need_nl = 1;
  71. }
  72. }
  73. void
  74. info( const char *msg, ... )
  75. {
  76. va_list va;
  77. if (!(DFlags & QUIET)) {
  78. va_start( va, msg );
  79. printn( msg, va );
  80. va_end( va );
  81. need_nl = 0;
  82. }
  83. }
  84. void
  85. infon( const char *msg, ... )
  86. {
  87. va_list va;
  88. if (!(DFlags & QUIET)) {
  89. va_start( va, msg );
  90. printn( msg, va );
  91. va_end( va );
  92. need_nl = 1;
  93. }
  94. }
  95. void
  96. warn( const char *msg, ... )
  97. {
  98. va_list va;
  99. if (!(DFlags & VERYQUIET)) {
  100. flushn();
  101. va_start( va, msg );
  102. vfprintf( stderr, msg, va );
  103. va_end( va );
  104. }
  105. }
  106. void
  107. error( const char *msg, ... )
  108. {
  109. va_list va;
  110. flushn();
  111. va_start( va, msg );
  112. vfprintf( stderr, msg, va );
  113. va_end( va );
  114. }
  115. void
  116. sys_error( const char *msg, ... )
  117. {
  118. va_list va;
  119. char buf[1024];
  120. flushn();
  121. va_start( va, msg );
  122. if ((uint)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
  123. oob();
  124. va_end( va );
  125. perror( buf );
  126. }
  127. void
  128. add_string_list_n( string_list_t **list, const char *str, int len )
  129. {
  130. string_list_t *elem;
  131. elem = nfmalloc( sizeof(*elem) + len );
  132. elem->next = *list;
  133. *list = elem;
  134. memcpy( elem->string, str, len );
  135. elem->string[len] = 0;
  136. }
  137. void
  138. add_string_list( string_list_t **list, const char *str )
  139. {
  140. add_string_list_n( list, str, strlen( str ) );
  141. }
  142. void
  143. free_string_list( string_list_t *list )
  144. {
  145. string_list_t *tlist;
  146. for (; list; list = tlist) {
  147. tlist = list->next;
  148. free( list );
  149. }
  150. }
  151. #ifndef HAVE_VASPRINTF
  152. static int
  153. vasprintf( char **strp, const char *fmt, va_list ap )
  154. {
  155. int len;
  156. char tmp[1024];
  157. if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 )))
  158. return -1;
  159. if (len >= (int)sizeof(tmp))
  160. vsprintf( *strp, fmt, ap );
  161. else
  162. memcpy( *strp, tmp, len + 1 );
  163. return len;
  164. }
  165. #endif
  166. #ifndef HAVE_MEMRCHR
  167. void *
  168. memrchr( const void *s, int c, size_t n )
  169. {
  170. u_char *b = (u_char *)s, *e = b + n;
  171. while (--e >= b)
  172. if (*e == c)
  173. return (void *)e;
  174. return 0;
  175. }
  176. #endif
  177. #ifndef HAVE_STRNLEN
  178. int
  179. strnlen( const char *str, size_t maxlen )
  180. {
  181. size_t len;
  182. /* It's tempting to use memchr(), but it's allowed to read past the end of the actual string. */
  183. for (len = 0; len < maxlen && str[len]; len++) {}
  184. return len;
  185. }
  186. #endif
  187. int
  188. starts_with( const char *str, int strl, const char *cmp, int cmpl )
  189. {
  190. if (strl < 0)
  191. strl = strnlen( str, cmpl + 1 );
  192. return (strl >= cmpl) && !memcmp( str, cmp, cmpl );
  193. }
  194. int
  195. equals( const char *str, int strl, const char *cmp, int cmpl )
  196. {
  197. if (strl < 0)
  198. strl = strnlen( str, cmpl + 1 );
  199. return (strl == cmpl) && !memcmp( str, cmp, cmpl );
  200. }
  201. #ifndef HAVE_TIMEGM
  202. /*
  203. Converts struct tm to time_t, assuming the data in tm is UTC rather
  204. than local timezone.
  205. mktime is similar but assumes struct tm, also known as the
  206. "broken-down" form of time, is in local time zone. timegm
  207. uses mktime to make the conversion understanding that an offset
  208. will be introduced by the local time assumption.
  209. mktime_from_utc then measures the introduced offset by applying
  210. gmtime to the initial result and applying mktime to the resulting
  211. "broken-down" form. The difference between the two mktime results
  212. is the measured offset which is then subtracted from the initial
  213. mktime result to yield a calendar time which is the value returned.
  214. tm_isdst in struct tm is set to 0 to force mktime to introduce a
  215. consistent offset (the non DST offset) since tm and tm+o might be
  216. on opposite sides of a DST change.
  217. Some implementations of mktime return -1 for the nonexistent
  218. localtime hour at the beginning of DST. In this event, use
  219. mktime(tm - 1hr) + 3600.
  220. Schematically
  221. mktime(tm) --> t+o
  222. gmtime(t+o) --> tm+o
  223. mktime(tm+o) --> t+2o
  224. t+o - (t+2o - t+o) = t
  225. Contributed by Roger Beeman <beeman@cisco.com>, with the help of
  226. Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO.
  227. Further improved by Roger with assistance from Edward J. Sabol
  228. based on input by Jamie Zawinski.
  229. */
  230. static time_t
  231. my_mktime( struct tm *t )
  232. {
  233. time_t tl = mktime( t );
  234. if (tl == -1) {
  235. t->tm_hour--;
  236. tl = mktime( t );
  237. if (tl != -1)
  238. tl += 3600;
  239. }
  240. return tl;
  241. }
  242. time_t
  243. timegm( struct tm *t )
  244. {
  245. time_t tl, tb;
  246. struct tm *tg;
  247. if ((tl = my_mktime( t )) == -1)
  248. return tl;
  249. tg = gmtime( &tl );
  250. tg->tm_isdst = 0;
  251. if ((tb = my_mktime( tg )) == -1)
  252. return tb;
  253. return tl - (tb - tl);
  254. }
  255. #endif
  256. void
  257. oob( void )
  258. {
  259. fputs( "Fatal: buffer too small. Please report a bug.\n", stderr );
  260. abort();
  261. }
  262. int
  263. nfsnprintf( char *buf, int blen, const char *fmt, ... )
  264. {
  265. int ret;
  266. va_list va;
  267. va_start( va, fmt );
  268. if (blen <= 0 || (uint)(ret = vsnprintf( buf, blen, fmt, va )) >= (uint)blen)
  269. oob();
  270. va_end( va );
  271. return ret;
  272. }
  273. static void ATTR_NORETURN
  274. oom( void )
  275. {
  276. fputs( "Fatal: Out of memory\n", stderr );
  277. abort();
  278. }
  279. void *
  280. nfmalloc( size_t sz )
  281. {
  282. void *ret;
  283. if (!(ret = malloc( sz )))
  284. oom();
  285. return ret;
  286. }
  287. void *
  288. nfcalloc( size_t sz )
  289. {
  290. void *ret;
  291. if (!(ret = calloc( sz, 1 )))
  292. oom();
  293. return ret;
  294. }
  295. void *
  296. nfrealloc( void *mem, size_t sz )
  297. {
  298. char *ret;
  299. if (!(ret = realloc( mem, sz )) && sz)
  300. oom();
  301. return ret;
  302. }
  303. char *
  304. nfstrdup( const char *str )
  305. {
  306. char *ret;
  307. if (!(ret = strdup( str )))
  308. oom();
  309. return ret;
  310. }
  311. int
  312. nfvasprintf( char **str, const char *fmt, va_list va )
  313. {
  314. int ret = vasprintf( str, fmt, va );
  315. if (ret < 0)
  316. oom();
  317. return ret;
  318. }
  319. int
  320. nfasprintf( char **str, const char *fmt, ... )
  321. {
  322. int ret;
  323. va_list va;
  324. va_start( va, fmt );
  325. ret = nfvasprintf( str, fmt, va );
  326. va_end( va );
  327. return ret;
  328. }
  329. /*
  330. static struct passwd *
  331. cur_user( void )
  332. {
  333. char *p;
  334. struct passwd *pw;
  335. uid_t uid;
  336. uid = getuid();
  337. if ((!(p = getenv("LOGNAME")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  338. (!(p = getenv("USER")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  339. !(pw = getpwuid( uid )))
  340. {
  341. fputs ("Cannot determinate current user\n", stderr);
  342. return 0;
  343. }
  344. return pw;
  345. }
  346. */
  347. static char *
  348. my_strndup( const char *s, size_t nchars )
  349. {
  350. char *r = nfmalloc( nchars + 1 );
  351. memcpy( r, s, nchars );
  352. r[nchars] = 0;
  353. return r;
  354. }
  355. char *
  356. expand_strdup( const char *s )
  357. {
  358. struct passwd *pw;
  359. const char *p, *q;
  360. char *r;
  361. if (*s == '~') {
  362. s++;
  363. if (!*s) {
  364. p = 0;
  365. q = Home;
  366. } else if (*s == '/') {
  367. p = s;
  368. q = Home;
  369. } else {
  370. if ((p = strchr( s, '/' ))) {
  371. r = my_strndup( s, (int)(p - s) );
  372. pw = getpwnam( r );
  373. free( r );
  374. } else
  375. pw = getpwnam( s );
  376. if (!pw)
  377. return 0;
  378. q = pw->pw_dir;
  379. }
  380. nfasprintf( &r, "%s%s", q, p ? p : "" );
  381. return r;
  382. } else
  383. return nfstrdup( s );
  384. }
  385. /* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */
  386. int
  387. map_name( const char *arg, char **result, int reserve, const char *in, const char *out )
  388. {
  389. char *p;
  390. int i, l, ll, num, inl, outl;
  391. l = strlen( arg );
  392. if (!in) {
  393. copy:
  394. *result = nfmalloc( reserve + l + 1 );
  395. memcpy( *result + reserve, arg, l + 1 );
  396. return 0;
  397. }
  398. inl = strlen( in );
  399. if (out) {
  400. outl = strlen( out );
  401. if (inl == outl && !memcmp( in, out, inl ))
  402. goto copy;
  403. }
  404. for (num = 0, i = 0; i < l; ) {
  405. for (ll = 0; ll < inl; ll++)
  406. if (arg[i + ll] != in[ll])
  407. goto fout;
  408. num++;
  409. i += inl;
  410. continue;
  411. fout:
  412. if (out) {
  413. for (ll = 0; ll < outl; ll++)
  414. if (arg[i + ll] != out[ll])
  415. goto fnexti;
  416. return -1;
  417. }
  418. fnexti:
  419. i++;
  420. }
  421. if (!num)
  422. goto copy;
  423. if (!out)
  424. return -2;
  425. *result = nfmalloc( reserve + l + num * (outl - inl) + 1 );
  426. p = *result + reserve;
  427. for (i = 0; i < l; ) {
  428. for (ll = 0; ll < inl; ll++)
  429. if (arg[i + ll] != in[ll])
  430. goto rnexti;
  431. memcpy( p, out, outl );
  432. p += outl;
  433. i += inl;
  434. continue;
  435. rnexti:
  436. *p++ = arg[i++];
  437. }
  438. *p = 0;
  439. return 0;
  440. }
  441. static int
  442. compare_ints( const void *l, const void *r )
  443. {
  444. return *(int *)l - *(int *)r;
  445. }
  446. void
  447. sort_ints( int *arr, int len )
  448. {
  449. qsort( arr, len, sizeof(int), compare_ints );
  450. }
  451. static struct {
  452. uchar i, j, s[256];
  453. } rs;
  454. void
  455. arc4_init( void )
  456. {
  457. int i, fd;
  458. uchar j, si, dat[128];
  459. if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) {
  460. error( "Fatal: no random number source available.\n" );
  461. exit( 3 );
  462. }
  463. if (read( fd, dat, 128 ) != 128) {
  464. error( "Fatal: cannot read random number source.\n" );
  465. exit( 3 );
  466. }
  467. close( fd );
  468. for (i = 0; i < 256; i++)
  469. rs.s[i] = i;
  470. for (i = j = 0; i < 256; i++) {
  471. si = rs.s[i];
  472. j += si + dat[i & 127];
  473. rs.s[i] = rs.s[j];
  474. rs.s[j] = si;
  475. }
  476. rs.i = rs.j = 0;
  477. for (i = 0; i < 256; i++)
  478. arc4_getbyte();
  479. }
  480. uchar
  481. arc4_getbyte( void )
  482. {
  483. uchar si, sj;
  484. rs.i++;
  485. si = rs.s[rs.i];
  486. rs.j += si;
  487. sj = rs.s[rs.j];
  488. rs.s[rs.i] = sj;
  489. rs.s[rs.j] = si;
  490. return rs.s[(si + sj) & 0xff];
  491. }
  492. static const uchar prime_deltas[] = {
  493. 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3,
  494. 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0
  495. };
  496. int
  497. bucketsForSize( int size )
  498. {
  499. int base = 4, bits = 2;
  500. for (;;) {
  501. int prime = base + prime_deltas[bits];
  502. if (prime >= size)
  503. return prime;
  504. base <<= 1;
  505. bits++;
  506. }
  507. }
  508. static notifier_t *notifiers;
  509. static int changed; /* Iterator may be invalid now. */
  510. #ifdef HAVE_SYS_POLL_H
  511. static struct pollfd *pollfds;
  512. static int npolls, rpolls;
  513. #else
  514. # ifdef HAVE_SYS_SELECT_H
  515. # include <sys/select.h>
  516. # endif
  517. #endif
  518. void
  519. init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void *aux )
  520. {
  521. #ifdef HAVE_SYS_POLL_H
  522. int idx = npolls++;
  523. if (rpolls < npolls) {
  524. rpolls = npolls;
  525. pollfds = nfrealloc( pollfds, npolls * sizeof(*pollfds) );
  526. }
  527. pollfds[idx].fd = fd;
  528. pollfds[idx].events = 0; /* POLLERR & POLLHUP implicit */
  529. sn->index = idx;
  530. #else
  531. sn->fd = fd;
  532. sn->events = 0;
  533. #endif
  534. sn->cb = cb;
  535. sn->aux = aux;
  536. sn->faked = 0;
  537. sn->next = notifiers;
  538. notifiers = sn;
  539. }
  540. void
  541. conf_notifier( notifier_t *sn, int and_events, int or_events )
  542. {
  543. #ifdef HAVE_SYS_POLL_H
  544. int idx = sn->index;
  545. pollfds[idx].events = (pollfds[idx].events & and_events) | or_events;
  546. #else
  547. sn->events = (sn->events & and_events) | or_events;
  548. #endif
  549. }
  550. void
  551. wipe_notifier( notifier_t *sn )
  552. {
  553. notifier_t **snp;
  554. #ifdef HAVE_SYS_POLL_H
  555. int idx;
  556. #endif
  557. for (snp = &notifiers; *snp != sn; snp = &(*snp)->next)
  558. assert( *snp );
  559. *snp = sn->next;
  560. sn->next = 0;
  561. changed = 1;
  562. #ifdef HAVE_SYS_POLL_H
  563. idx = sn->index;
  564. memmove( pollfds + idx, pollfds + idx + 1, (--npolls - idx) * sizeof(*pollfds) );
  565. for (sn = notifiers; sn; sn = sn->next) {
  566. if (sn->index > idx)
  567. sn->index--;
  568. }
  569. #endif
  570. }
  571. #define shifted_bit(in, from, to) \
  572. (((uint)(in) & from) \
  573. / (from > to ? from / to : 1) \
  574. * (to > from ? to / from : 1))
  575. static void
  576. event_wait( void )
  577. {
  578. notifier_t *sn;
  579. int m;
  580. #ifdef HAVE_SYS_POLL_H
  581. int timeout = -1;
  582. for (sn = notifiers; sn; sn = sn->next)
  583. if (sn->faked) {
  584. timeout = 0;
  585. break;
  586. }
  587. if (poll( pollfds, npolls, timeout ) < 0) {
  588. perror( "poll() failed in event loop" );
  589. abort();
  590. }
  591. for (sn = notifiers; sn; sn = sn->next) {
  592. int n = sn->index;
  593. if ((m = pollfds[n].revents | sn->faked)) {
  594. assert( !(m & POLLNVAL) );
  595. sn->faked = 0;
  596. sn->cb( m | shifted_bit( m, POLLHUP, POLLIN ), sn->aux );
  597. if (changed) {
  598. changed = 0;
  599. break;
  600. }
  601. }
  602. }
  603. #else
  604. struct timeval *timeout = 0;
  605. static struct timeval null_tv;
  606. fd_set rfds, wfds, efds;
  607. int fd;
  608. FD_ZERO( &rfds );
  609. FD_ZERO( &wfds );
  610. FD_ZERO( &efds );
  611. m = -1;
  612. for (sn = notifiers; sn; sn = sn->next) {
  613. if (sn->faked)
  614. timeout = &null_tv;
  615. fd = sn->fd;
  616. if (sn->events & POLLIN)
  617. FD_SET( fd, &rfds );
  618. if (sn->events & POLLOUT)
  619. FD_SET( fd, &wfds );
  620. FD_SET( fd, &efds );
  621. if (fd > m)
  622. m = fd;
  623. }
  624. if (select( m + 1, &rfds, &wfds, &efds, timeout ) < 0) {
  625. perror( "select() failed in event loop" );
  626. abort();
  627. }
  628. for (sn = notifiers; sn; sn = sn->next) {
  629. fd = sn->fd;
  630. m = sn->faked;
  631. if (FD_ISSET( fd, &rfds ))
  632. m |= POLLIN;
  633. if (FD_ISSET( fd, &wfds ))
  634. m |= POLLOUT;
  635. if (FD_ISSET( fd, &efds ))
  636. m |= POLLERR;
  637. if (m) {
  638. sn->faked = 0;
  639. sn->cb( m, sn->aux );
  640. if (changed) {
  641. changed = 0;
  642. break;
  643. }
  644. }
  645. }
  646. #endif
  647. }
  648. void
  649. main_loop( void )
  650. {
  651. while (notifiers)
  652. event_wait();
  653. }