util.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  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 <stddef.h>
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #include <fcntl.h>
  28. #include <errno.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <pwd.h>
  32. static int need_nl;
  33. void
  34. flushn( void )
  35. {
  36. if (need_nl) {
  37. putchar( '\n' );
  38. fflush( stdout );
  39. need_nl = 0;
  40. }
  41. }
  42. static void ATTR_PRINTFLIKE(1, 0)
  43. printn( const char *msg, va_list va )
  44. {
  45. if (*msg == '\v')
  46. msg++;
  47. else
  48. flushn();
  49. vprintf( msg, va );
  50. fflush( stdout );
  51. }
  52. void
  53. vdebug( int cat, const char *msg, va_list va )
  54. {
  55. if (DFlags & cat) {
  56. vprintf( msg, va );
  57. fflush( stdout );
  58. need_nl = 0;
  59. }
  60. }
  61. void
  62. vdebugn( int cat, const char *msg, va_list va )
  63. {
  64. if (DFlags & cat) {
  65. vprintf( msg, va );
  66. fflush( stdout );
  67. need_nl = 1;
  68. }
  69. }
  70. void
  71. progress( const char *msg, ... )
  72. {
  73. va_list va;
  74. va_start( va, msg );
  75. vprintf( msg, va );
  76. va_end( va );
  77. fflush( stdout );
  78. need_nl = 1;
  79. }
  80. void
  81. info( const char *msg, ... )
  82. {
  83. va_list va;
  84. if (DFlags & VERBOSE) {
  85. va_start( va, msg );
  86. printn( msg, va );
  87. va_end( va );
  88. need_nl = 0;
  89. }
  90. }
  91. void
  92. infon( const char *msg, ... )
  93. {
  94. va_list va;
  95. if (DFlags & VERBOSE) {
  96. va_start( va, msg );
  97. printn( msg, va );
  98. va_end( va );
  99. need_nl = 1;
  100. }
  101. }
  102. void
  103. notice( const char *msg, ... )
  104. {
  105. va_list va;
  106. if (!(DFlags & QUIET)) {
  107. va_start( va, msg );
  108. printn( msg, va );
  109. va_end( va );
  110. need_nl = 0;
  111. }
  112. }
  113. void
  114. warn( const char *msg, ... )
  115. {
  116. va_list va;
  117. if (!(DFlags & VERYQUIET)) {
  118. flushn();
  119. va_start( va, msg );
  120. vfprintf( stderr, msg, va );
  121. va_end( va );
  122. }
  123. }
  124. void
  125. error( const char *msg, ... )
  126. {
  127. va_list va;
  128. flushn();
  129. va_start( va, msg );
  130. vfprintf( stderr, msg, va );
  131. va_end( va );
  132. }
  133. void
  134. vsys_error( const char *msg, va_list va )
  135. {
  136. char buf[1024];
  137. int errno_bak = errno;
  138. flushn();
  139. if ((uint)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
  140. oob();
  141. errno = errno_bak;
  142. perror( buf );
  143. }
  144. void
  145. sys_error( const char *msg, ... )
  146. {
  147. va_list va;
  148. va_start( va, msg );
  149. vsys_error( msg, va );
  150. va_end( va );
  151. }
  152. void
  153. add_string_list_n( string_list_t **list, const char *str, uint len )
  154. {
  155. string_list_t *elem;
  156. elem = nfmalloc( offsetof(string_list_t, string) + len + 1 );
  157. elem->next = *list;
  158. *list = elem;
  159. memcpy( elem->string, str, len );
  160. elem->string[len] = 0;
  161. }
  162. void
  163. add_string_list( string_list_t **list, const char *str )
  164. {
  165. add_string_list_n( list, str, strlen( str ) );
  166. }
  167. void
  168. free_string_list( string_list_t *list )
  169. {
  170. string_list_t *tlist;
  171. for (; list; list = tlist) {
  172. tlist = list->next;
  173. free( list );
  174. }
  175. }
  176. #ifndef HAVE_VASPRINTF
  177. static int
  178. vasprintf( char **strp, const char *fmt, va_list ap )
  179. {
  180. int len;
  181. char tmp[1024];
  182. if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 )))
  183. return -1;
  184. if (len >= (int)sizeof(tmp))
  185. vsprintf( *strp, fmt, ap );
  186. else
  187. memcpy( *strp, tmp, (size_t)len + 1 );
  188. return len;
  189. }
  190. #endif
  191. #ifndef HAVE_MEMRCHR
  192. void *
  193. memrchr( const void *s, int c, size_t n )
  194. {
  195. u_char *b = (u_char *)s, *e = b + n;
  196. while (--e >= b)
  197. if (*e == c)
  198. return (void *)e;
  199. return 0;
  200. }
  201. #endif
  202. #ifndef HAVE_STRNLEN
  203. size_t
  204. strnlen( const char *str, size_t maxlen )
  205. {
  206. const char *estr = memchr( str, 0, maxlen );
  207. return estr ? (size_t)(estr - str) : maxlen;
  208. }
  209. #endif
  210. int
  211. starts_with( const char *str, int strl, const char *cmp, uint cmpl )
  212. {
  213. if (strl < 0)
  214. strl = strnlen( str, cmpl + 1 );
  215. return ((uint)strl >= cmpl) && !memcmp( str, cmp, cmpl );
  216. }
  217. int
  218. starts_with_upper( const char *str, int strl, const char *cmp, uint cmpl )
  219. {
  220. if (strl < 0)
  221. strl = strnlen( str, cmpl + 1 );
  222. if ((uint)strl < cmpl)
  223. return 0;
  224. for (uint i = 0; i < cmpl; i++)
  225. if (str[i] != cmp[i] && toupper( str[i] ) != cmp[i])
  226. return 0;
  227. return 1;
  228. }
  229. int
  230. equals( const char *str, int strl, const char *cmp, uint cmpl )
  231. {
  232. if (strl < 0)
  233. strl = strnlen( str, cmpl + 1 );
  234. return ((uint)strl == cmpl) && !memcmp( str, cmp, cmpl );
  235. }
  236. #ifndef HAVE_TIMEGM
  237. /*
  238. Converts struct tm to time_t, assuming the data in tm is UTC rather
  239. than local timezone.
  240. mktime is similar but assumes struct tm, also known as the
  241. "broken-down" form of time, is in local time zone. timegm
  242. uses mktime to make the conversion understanding that an offset
  243. will be introduced by the local time assumption.
  244. mktime_from_utc then measures the introduced offset by applying
  245. gmtime to the initial result and applying mktime to the resulting
  246. "broken-down" form. The difference between the two mktime results
  247. is the measured offset which is then subtracted from the initial
  248. mktime result to yield a calendar time which is the value returned.
  249. tm_isdst in struct tm is set to 0 to force mktime to introduce a
  250. consistent offset (the non DST offset) since tm and tm+o might be
  251. on opposite sides of a DST change.
  252. Some implementations of mktime return -1 for the nonexistent
  253. localtime hour at the beginning of DST. In this event, use
  254. mktime(tm - 1hr) + 3600.
  255. Schematically
  256. mktime(tm) --> t+o
  257. gmtime(t+o) --> tm+o
  258. mktime(tm+o) --> t+2o
  259. t+o - (t+2o - t+o) = t
  260. Contributed by Roger Beeman <beeman@cisco.com>, with the help of
  261. Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO.
  262. Further improved by Roger with assistance from Edward J. Sabol
  263. based on input by Jamie Zawinski.
  264. */
  265. static time_t
  266. my_mktime( struct tm *t )
  267. {
  268. time_t tl = mktime( t );
  269. if (tl == -1) {
  270. t->tm_hour--;
  271. tl = mktime( t );
  272. if (tl != -1)
  273. tl += 3600;
  274. }
  275. return tl;
  276. }
  277. time_t
  278. timegm( struct tm *t )
  279. {
  280. time_t tl, tb;
  281. struct tm *tg;
  282. if ((tl = my_mktime( t )) == -1)
  283. return tl;
  284. tg = gmtime( &tl );
  285. tg->tm_isdst = 0;
  286. if ((tb = my_mktime( tg )) == -1)
  287. return tb;
  288. return tl - (tb - tl);
  289. }
  290. #endif
  291. void
  292. oob( void )
  293. {
  294. fputs( "Fatal: buffer too small. Please report a bug.\n", stderr );
  295. abort();
  296. }
  297. int
  298. nfsnprintf( char *buf, int blen, const char *fmt, ... )
  299. {
  300. int ret;
  301. va_list va;
  302. va_start( va, fmt );
  303. if (blen <= 0 || (uint)(ret = vsnprintf( buf, (size_t)blen, fmt, va )) >= (uint)blen)
  304. oob();
  305. va_end( va );
  306. return ret;
  307. }
  308. void
  309. oom( void )
  310. {
  311. fputs( "Fatal: Out of memory\n", stderr );
  312. abort();
  313. }
  314. void *
  315. nfmalloc( size_t sz )
  316. {
  317. void *ret;
  318. if (!(ret = malloc( sz )))
  319. oom();
  320. return ret;
  321. }
  322. void *
  323. nfcalloc( size_t sz )
  324. {
  325. void *ret;
  326. if (!(ret = calloc( sz, 1 )))
  327. oom();
  328. return ret;
  329. }
  330. void *
  331. nfrealloc( void *mem, size_t sz )
  332. {
  333. char *ret;
  334. if (!(ret = realloc( mem, sz )) && sz)
  335. oom();
  336. return ret;
  337. }
  338. char *
  339. nfstrndup( const char *str, size_t nchars )
  340. {
  341. char *ret = nfmalloc( nchars + 1 );
  342. memcpy( ret, str, nchars );
  343. ret[nchars] = 0;
  344. return ret;
  345. }
  346. char *
  347. nfstrdup( const char *str )
  348. {
  349. return nfstrndup( str, strlen( str ) );
  350. }
  351. int
  352. nfvasprintf( char **str, const char *fmt, va_list va )
  353. {
  354. int ret = vasprintf( str, fmt, va );
  355. if (ret < 0)
  356. oom();
  357. return ret;
  358. }
  359. int
  360. nfasprintf( char **str, const char *fmt, ... )
  361. {
  362. int ret;
  363. va_list va;
  364. va_start( va, fmt );
  365. ret = nfvasprintf( str, fmt, va );
  366. va_end( va );
  367. return ret;
  368. }
  369. /*
  370. static struct passwd *
  371. cur_user( void )
  372. {
  373. char *p;
  374. struct passwd *pw;
  375. uid_t uid;
  376. uid = getuid();
  377. if ((!(p = getenv("LOGNAME")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  378. (!(p = getenv("USER")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  379. !(pw = getpwuid( uid )))
  380. {
  381. fputs ("Cannot determinate current user\n", stderr);
  382. return 0;
  383. }
  384. return pw;
  385. }
  386. */
  387. char *
  388. expand_strdup( const char *s )
  389. {
  390. struct passwd *pw;
  391. const char *p, *q;
  392. char *r;
  393. if (*s == '~') {
  394. s++;
  395. if (!*s) {
  396. p = NULL;
  397. q = Home;
  398. } else if (*s == '/') {
  399. p = s;
  400. q = Home;
  401. } else {
  402. if ((p = strchr( s, '/' ))) {
  403. r = nfstrndup( s, (size_t)(p - s) );
  404. pw = getpwnam( r );
  405. free( r );
  406. } else
  407. pw = getpwnam( s );
  408. if (!pw)
  409. return NULL;
  410. q = pw->pw_dir;
  411. }
  412. nfasprintf( &r, "%s%s", q, p ? p : "" );
  413. return r;
  414. } else
  415. return nfstrdup( s );
  416. }
  417. /* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */
  418. int
  419. map_name( const char *arg, char **result, uint reserve, const char *in, const char *out )
  420. {
  421. char *p;
  422. uint i, l, ll, num, inl, outl;
  423. assert( arg );
  424. l = strlen( arg );
  425. assert( in );
  426. inl = strlen( in );
  427. if (!inl) {
  428. copy:
  429. *result = nfmalloc( reserve + l + 1 );
  430. memcpy( *result + reserve, arg, l + 1 );
  431. return 0;
  432. }
  433. assert( out );
  434. outl = strlen( out );
  435. if (equals( in, (int)inl, out, outl ))
  436. goto copy;
  437. for (num = 0, i = 0; i < l; ) {
  438. for (ll = 0; ll < inl; ll++)
  439. if (arg[i + ll] != in[ll])
  440. goto fout;
  441. num++;
  442. i += inl;
  443. continue;
  444. fout:
  445. if (outl) {
  446. for (ll = 0; ll < outl; ll++)
  447. if (arg[i + ll] != out[ll])
  448. goto fnexti;
  449. return -1;
  450. }
  451. fnexti:
  452. i++;
  453. }
  454. if (!num)
  455. goto copy;
  456. if (!outl)
  457. return -2;
  458. *result = nfmalloc( reserve + l + num * (outl - inl) + 1 );
  459. p = *result + reserve;
  460. for (i = 0; i < l; ) {
  461. for (ll = 0; ll < inl; ll++)
  462. if (arg[i + ll] != in[ll])
  463. goto rnexti;
  464. memcpy( p, out, outl );
  465. p += outl;
  466. i += inl;
  467. continue;
  468. rnexti:
  469. *p++ = arg[i++];
  470. }
  471. *p = 0;
  472. return 0;
  473. }
  474. static int
  475. compare_uints( const void *l, const void *r )
  476. {
  477. uint li = *(const uint *)l, ri = *(const uint *)r;
  478. if (li != ri) // Can't subtract, the result might not fit into signed int.
  479. return li > ri ? 1 : -1;
  480. return 0;
  481. }
  482. void
  483. sort_uint_array( uint_array_t array )
  484. {
  485. qsort( array.data, array.size, sizeof(uint), compare_uints );
  486. }
  487. int
  488. find_uint_array( uint_array_t array, uint value )
  489. {
  490. uint bot = 0, top = array.size;
  491. while (bot < top) {
  492. uint i = (bot + top) / 2;
  493. uint elt = array.data[i];
  494. if (elt == value)
  495. return 1;
  496. if (elt < value)
  497. bot = i + 1;
  498. else
  499. top = i;
  500. }
  501. return 0;
  502. }
  503. static struct {
  504. uchar i, j, s[256];
  505. } rs;
  506. void
  507. arc4_init( void )
  508. {
  509. int i, fd;
  510. uchar j, si, dat[128];
  511. if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) {
  512. error( "Fatal: no random number source available.\n" );
  513. exit( 3 );
  514. }
  515. if (read( fd, dat, 128 ) != 128) {
  516. error( "Fatal: cannot read random number source.\n" );
  517. exit( 3 );
  518. }
  519. close( fd );
  520. for (i = 0; i < 256; i++)
  521. rs.s[i] = (uchar)i;
  522. for (i = j = 0; i < 256; i++) {
  523. si = rs.s[i];
  524. j += si + dat[i & 127];
  525. rs.s[i] = rs.s[j];
  526. rs.s[j] = si;
  527. }
  528. rs.i = rs.j = 0;
  529. for (i = 0; i < 256; i++)
  530. arc4_getbyte();
  531. }
  532. uchar
  533. arc4_getbyte( void )
  534. {
  535. uchar si, sj;
  536. rs.i++;
  537. si = rs.s[rs.i];
  538. rs.j += si;
  539. sj = rs.s[rs.j];
  540. rs.s[rs.i] = sj;
  541. rs.s[rs.j] = si;
  542. return rs.s[(si + sj) & 0xff];
  543. }
  544. static const uchar prime_deltas[] = {
  545. 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3,
  546. 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0
  547. };
  548. uint
  549. bucketsForSize( uint size )
  550. {
  551. uint base = 4, bits = 2;
  552. for (;;) {
  553. uint prime = base + prime_deltas[bits];
  554. if (prime >= size)
  555. return prime;
  556. base <<= 1;
  557. bits++;
  558. }
  559. }
  560. static void
  561. list_prepend( list_head_t *head, list_head_t *to )
  562. {
  563. assert( !head->next );
  564. assert( to->next );
  565. assert( to->prev->next == to );
  566. head->next = to;
  567. head->prev = to->prev;
  568. head->prev->next = head;
  569. to->prev = head;
  570. }
  571. static void
  572. list_unlink( list_head_t *head )
  573. {
  574. assert( head->next );
  575. assert( head->next->prev == head);
  576. assert( head->prev->next == head);
  577. head->next->prev = head->prev;
  578. head->prev->next = head->next;
  579. head->next = head->prev = NULL;
  580. }
  581. static notifier_t *notifiers;
  582. static int changed; /* Iterator may be invalid now. */
  583. #ifdef HAVE_POLL_H
  584. static struct pollfd *pollfds;
  585. static uint npolls, rpolls;
  586. #else
  587. # ifdef HAVE_SYS_SELECT_H
  588. # include <sys/select.h>
  589. # endif
  590. #endif
  591. void
  592. init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void *aux )
  593. {
  594. #ifdef HAVE_POLL_H
  595. uint idx = npolls++;
  596. if (rpolls < npolls) {
  597. rpolls = npolls;
  598. pollfds = nfrealloc( pollfds, npolls * sizeof(*pollfds) );
  599. }
  600. pollfds[idx].fd = fd;
  601. pollfds[idx].events = 0; /* POLLERR & POLLHUP implicit */
  602. sn->index = idx;
  603. #else
  604. sn->fd = fd;
  605. sn->events = 0;
  606. #endif
  607. sn->cb = cb;
  608. sn->aux = aux;
  609. sn->next = notifiers;
  610. notifiers = sn;
  611. }
  612. void
  613. conf_notifier( notifier_t *sn, short and_events, short or_events )
  614. {
  615. #ifdef HAVE_POLL_H
  616. uint idx = sn->index;
  617. pollfds[idx].events = (pollfds[idx].events & and_events) | or_events;
  618. #else
  619. sn->events = (sn->events & and_events) | or_events;
  620. #endif
  621. }
  622. short
  623. notifier_config( notifier_t *sn )
  624. {
  625. #ifdef HAVE_POLL_H
  626. return pollfds[sn->index].events;
  627. #else
  628. return sn->events;
  629. #endif
  630. }
  631. void
  632. wipe_notifier( notifier_t *sn )
  633. {
  634. notifier_t **snp;
  635. #ifdef HAVE_POLL_H
  636. uint idx;
  637. #endif
  638. for (snp = &notifiers; *snp != sn; snp = &(*snp)->next)
  639. assert( *snp );
  640. *snp = sn->next;
  641. sn->next = NULL;
  642. changed = 1;
  643. #ifdef HAVE_POLL_H
  644. idx = sn->index;
  645. memmove( pollfds + idx, pollfds + idx + 1, (--npolls - idx) * sizeof(*pollfds) );
  646. for (sn = notifiers; sn; sn = sn->next) {
  647. if (sn->index > idx)
  648. sn->index--;
  649. }
  650. #endif
  651. }
  652. static time_t
  653. get_now( void )
  654. {
  655. return time( NULL );
  656. }
  657. static list_head_t timers = { &timers, &timers };
  658. void
  659. init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux )
  660. {
  661. tmr->cb = cb;
  662. tmr->aux = aux;
  663. tmr->links.next = tmr->links.prev = NULL;
  664. }
  665. void
  666. wipe_wakeup( wakeup_t *tmr )
  667. {
  668. if (tmr->links.next)
  669. list_unlink( &tmr->links );
  670. }
  671. void
  672. conf_wakeup( wakeup_t *tmr, int to )
  673. {
  674. list_head_t *head, *succ;
  675. if (to < 0) {
  676. if (tmr->links.next)
  677. list_unlink( &tmr->links );
  678. } else {
  679. time_t timeout = to;
  680. if (!to) {
  681. /* We always prepend null timers, to cluster related events. */
  682. succ = timers.next;
  683. } else {
  684. timeout += get_now();
  685. /* We start at the end in the expectation that the newest timer is likely to fire last
  686. * (which will be true only if all timeouts are equal, but it's an as good guess as any). */
  687. for (succ = &timers; (head = succ->prev) != &timers; succ = head) {
  688. if (head != &tmr->links && timeout > ((wakeup_t *)head)->timeout)
  689. break;
  690. }
  691. assert( head != &tmr->links );
  692. }
  693. tmr->timeout = timeout;
  694. if (succ != &tmr->links) {
  695. if (tmr->links.next)
  696. list_unlink( &tmr->links );
  697. list_prepend( &tmr->links, succ );
  698. }
  699. }
  700. }
  701. static void
  702. event_wait( void )
  703. {
  704. list_head_t *head;
  705. notifier_t *sn;
  706. int m;
  707. #ifdef HAVE_POLL_H
  708. int timeout = -1;
  709. if ((head = timers.next) != &timers) {
  710. wakeup_t *tmr = (wakeup_t *)head;
  711. time_t delta = tmr->timeout;
  712. if (!delta || (delta -= get_now()) <= 0) {
  713. list_unlink( head );
  714. tmr->cb( tmr->aux );
  715. return;
  716. }
  717. timeout = (int)delta * 1000;
  718. }
  719. switch (poll( pollfds, npolls, timeout )) {
  720. case 0:
  721. return;
  722. case -1:
  723. perror( "poll() failed in event loop" );
  724. abort();
  725. default:
  726. break;
  727. }
  728. for (sn = notifiers; sn; sn = sn->next) {
  729. uint n = sn->index;
  730. if ((m = pollfds[n].revents)) {
  731. assert( !(m & POLLNVAL) );
  732. sn->cb( m | shifted_bit( m, POLLHUP, POLLIN ), sn->aux );
  733. if (changed) {
  734. changed = 0;
  735. break;
  736. }
  737. }
  738. }
  739. #else
  740. struct timeval *timeout = 0;
  741. struct timeval to_tv;
  742. fd_set rfds, wfds, efds;
  743. int fd;
  744. if ((head = timers.next) != &timers) {
  745. wakeup_t *tmr = (wakeup_t *)head;
  746. time_t delta = tmr->timeout;
  747. if (!delta || (delta -= get_now()) <= 0) {
  748. list_unlink( head );
  749. tmr->cb( tmr->aux );
  750. return;
  751. }
  752. to_tv.tv_sec = delta;
  753. to_tv.tv_usec = 0;
  754. timeout = &to_tv;
  755. }
  756. FD_ZERO( &rfds );
  757. FD_ZERO( &wfds );
  758. FD_ZERO( &efds );
  759. m = -1;
  760. for (sn = notifiers; sn; sn = sn->next) {
  761. fd = sn->fd;
  762. if (sn->events & POLLIN)
  763. FD_SET( fd, &rfds );
  764. if (sn->events & POLLOUT)
  765. FD_SET( fd, &wfds );
  766. FD_SET( fd, &efds );
  767. if (fd > m)
  768. m = fd;
  769. }
  770. switch (select( m + 1, &rfds, &wfds, &efds, timeout )) {
  771. case 0:
  772. return;
  773. case -1:
  774. perror( "select() failed in event loop" );
  775. abort();
  776. default:
  777. break;
  778. }
  779. for (sn = notifiers; sn; sn = sn->next) {
  780. fd = sn->fd;
  781. m = 0;
  782. if (FD_ISSET( fd, &rfds ))
  783. m |= POLLIN;
  784. if (FD_ISSET( fd, &wfds ))
  785. m |= POLLOUT;
  786. if (FD_ISSET( fd, &efds ))
  787. m |= POLLERR;
  788. if (m) {
  789. sn->cb( m, sn->aux );
  790. if (changed) {
  791. changed = 0;
  792. break;
  793. }
  794. }
  795. }
  796. #endif
  797. }
  798. void
  799. main_loop( void )
  800. {
  801. while (notifiers || timers.next != &timers)
  802. event_wait();
  803. }