util.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * mbsync - mailbox synchronizer
  3. * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
  4. * Copyright (C) 2002-2006 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, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  19. *
  20. * As a special exception, mbsync may be linked with the OpenSSL library,
  21. * despite that library's more restrictive license.
  22. */
  23. #include "isync.h"
  24. #include <assert.h>
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #include <fcntl.h>
  28. #include <string.h>
  29. #include <pwd.h>
  30. #include <ctype.h>
  31. int DFlags;
  32. static int need_nl;
  33. void
  34. flushn( void )
  35. {
  36. if (need_nl) {
  37. putchar( '\n' );
  38. need_nl = 0;
  39. }
  40. }
  41. static void
  42. printn( const char *msg, va_list va )
  43. {
  44. if (*msg == '\v')
  45. msg++;
  46. else
  47. flushn();
  48. vprintf( msg, va );
  49. fflush( stdout );
  50. }
  51. void
  52. debug( const char *msg, ... )
  53. {
  54. va_list va;
  55. if (DFlags & DEBUG) {
  56. va_start( va, msg );
  57. vprintf( msg, va );
  58. va_end( va );
  59. fflush( stdout );
  60. need_nl = 0;
  61. }
  62. }
  63. void
  64. debugn( const char *msg, ... )
  65. {
  66. va_list va;
  67. if (DFlags & DEBUG) {
  68. va_start( va, msg );
  69. vprintf( msg, va );
  70. va_end( va );
  71. fflush( stdout );
  72. need_nl = 1;
  73. }
  74. }
  75. void
  76. info( const char *msg, ... )
  77. {
  78. va_list va;
  79. if (!(DFlags & QUIET)) {
  80. va_start( va, msg );
  81. printn( msg, va );
  82. va_end( va );
  83. need_nl = 0;
  84. }
  85. }
  86. void
  87. infon( const char *msg, ... )
  88. {
  89. va_list va;
  90. if (!(DFlags & QUIET)) {
  91. va_start( va, msg );
  92. printn( msg, va );
  93. va_end( va );
  94. need_nl = 1;
  95. }
  96. }
  97. void
  98. warn( const char *msg, ... )
  99. {
  100. va_list va;
  101. if (!(DFlags & VERYQUIET)) {
  102. flushn();
  103. va_start( va, msg );
  104. vfprintf( stderr, msg, va );
  105. va_end( va );
  106. }
  107. }
  108. void
  109. error( const char *msg, ... )
  110. {
  111. va_list va;
  112. flushn();
  113. va_start( va, msg );
  114. vfprintf( stderr, msg, va );
  115. va_end( va );
  116. }
  117. void
  118. sys_error( const char *msg, ... )
  119. {
  120. va_list va;
  121. char buf[1024];
  122. flushn();
  123. va_start( va, msg );
  124. if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
  125. oob();
  126. va_end( va );
  127. perror( buf );
  128. }
  129. char *
  130. next_arg( char **s )
  131. {
  132. char *ret;
  133. if (!s || !*s)
  134. return 0;
  135. while (isspace( (unsigned char) **s ))
  136. (*s)++;
  137. if (!**s) {
  138. *s = 0;
  139. return 0;
  140. }
  141. if (**s == '"') {
  142. ++*s;
  143. ret = *s;
  144. *s = strchr( *s, '"' );
  145. } else {
  146. ret = *s;
  147. while (**s && !isspace( (unsigned char) **s ))
  148. (*s)++;
  149. }
  150. if (*s) {
  151. if (**s)
  152. *(*s)++ = 0;
  153. if (!**s)
  154. *s = 0;
  155. }
  156. return ret;
  157. }
  158. void
  159. add_string_list( string_list_t **list, const char *str )
  160. {
  161. string_list_t *elem;
  162. int len;
  163. len = strlen( str );
  164. elem = nfmalloc( sizeof(*elem) + len );
  165. elem->next = *list;
  166. *list = elem;
  167. memcpy( elem->string, str, len + 1 );
  168. }
  169. void
  170. free_string_list( string_list_t *list )
  171. {
  172. string_list_t *tlist;
  173. for (; list; list = tlist) {
  174. tlist = list->next;
  175. free( list );
  176. }
  177. }
  178. void
  179. free_generic_messages( message_t *msgs )
  180. {
  181. message_t *tmsg;
  182. for (; msgs; msgs = tmsg) {
  183. tmsg = msgs->next;
  184. free( msgs );
  185. }
  186. }
  187. #ifndef HAVE_VASPRINTF
  188. static int
  189. vasprintf( char **strp, const char *fmt, va_list ap )
  190. {
  191. int len;
  192. char tmp[1024];
  193. if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 )))
  194. return -1;
  195. if (len >= (int)sizeof(tmp))
  196. vsprintf( *strp, fmt, ap );
  197. else
  198. memcpy( *strp, tmp, len + 1 );
  199. return len;
  200. }
  201. #endif
  202. #ifndef HAVE_MEMRCHR
  203. void *
  204. memrchr( const void *s, int c, size_t n )
  205. {
  206. u_char *b = (u_char *)s, *e = b + n;
  207. while (--e >= b)
  208. if (*e == c)
  209. return (void *)e;
  210. return 0;
  211. }
  212. #endif
  213. void
  214. oob( void )
  215. {
  216. fputs( "Fatal: buffer too small. Please report a bug.\n", stderr );
  217. abort();
  218. }
  219. int
  220. nfsnprintf( char *buf, int blen, const char *fmt, ... )
  221. {
  222. int ret;
  223. va_list va;
  224. va_start( va, fmt );
  225. if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen)
  226. oob();
  227. va_end( va );
  228. return ret;
  229. }
  230. static void ATTR_NORETURN
  231. oom( void )
  232. {
  233. fputs( "Fatal: Out of memory\n", stderr );
  234. abort();
  235. }
  236. void *
  237. nfmalloc( size_t sz )
  238. {
  239. void *ret;
  240. if (!(ret = malloc( sz )))
  241. oom();
  242. return ret;
  243. }
  244. void *
  245. nfcalloc( size_t sz )
  246. {
  247. void *ret;
  248. if (!(ret = calloc( sz, 1 )))
  249. oom();
  250. return ret;
  251. }
  252. void *
  253. nfrealloc( void *mem, size_t sz )
  254. {
  255. char *ret;
  256. if (!(ret = realloc( mem, sz )) && sz)
  257. oom();
  258. return ret;
  259. }
  260. char *
  261. nfstrdup( const char *str )
  262. {
  263. char *ret;
  264. if (!(ret = strdup( str )))
  265. oom();
  266. return ret;
  267. }
  268. int
  269. nfvasprintf( char **str, const char *fmt, va_list va )
  270. {
  271. int ret = vasprintf( str, fmt, va );
  272. if (ret < 0)
  273. oom();
  274. return ret;
  275. }
  276. int
  277. nfasprintf( char **str, const char *fmt, ... )
  278. {
  279. int ret;
  280. va_list va;
  281. va_start( va, fmt );
  282. ret = nfvasprintf( str, fmt, va );
  283. va_end( va );
  284. return ret;
  285. }
  286. /*
  287. static struct passwd *
  288. cur_user( void )
  289. {
  290. char *p;
  291. struct passwd *pw;
  292. uid_t uid;
  293. uid = getuid();
  294. if ((!(p = getenv("LOGNAME")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  295. (!(p = getenv("USER")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  296. !(pw = getpwuid( uid )))
  297. {
  298. fputs ("Cannot determinate current user\n", stderr);
  299. return 0;
  300. }
  301. return pw;
  302. }
  303. */
  304. static char *
  305. my_strndup( const char *s, size_t nchars )
  306. {
  307. char *r = nfmalloc( nchars + 1 );
  308. memcpy( r, s, nchars );
  309. r[nchars] = 0;
  310. return r;
  311. }
  312. char *
  313. expand_strdup( const char *s )
  314. {
  315. struct passwd *pw;
  316. const char *p, *q;
  317. char *r;
  318. if (*s == '~') {
  319. s++;
  320. if (!*s) {
  321. p = 0;
  322. q = Home;
  323. } else if (*s == '/') {
  324. p = s;
  325. q = Home;
  326. } else {
  327. if ((p = strchr( s, '/' ))) {
  328. r = my_strndup( s, (int)(p - s) );
  329. pw = getpwnam( r );
  330. free( r );
  331. } else
  332. pw = getpwnam( s );
  333. if (!pw)
  334. return 0;
  335. q = pw->pw_dir;
  336. }
  337. nfasprintf( &r, "%s%s", q, p ? p : "" );
  338. return r;
  339. } else
  340. return nfstrdup( s );
  341. }
  342. /* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */
  343. int
  344. map_name( char *arg, char in, char out )
  345. {
  346. int l, k;
  347. if (!in || in == out)
  348. return 0;
  349. for (l = 0; arg[l]; l++)
  350. if (arg[l] == in) {
  351. if (!out)
  352. return -2;
  353. arg[l] = out;
  354. } else if (arg[l] == out) {
  355. /* restore original name for printing error message */
  356. for (k = 0; k < l; k++)
  357. if (arg[k] == out)
  358. arg[k] = in;
  359. return -1;
  360. }
  361. return 0;
  362. }
  363. static int
  364. compare_ints( const void *l, const void *r )
  365. {
  366. return *(int *)l - *(int *)r;
  367. }
  368. void
  369. sort_ints( int *arr, int len )
  370. {
  371. qsort( arr, len, sizeof(int), compare_ints );
  372. }
  373. static struct {
  374. unsigned char i, j, s[256];
  375. } rs;
  376. void
  377. arc4_init( void )
  378. {
  379. int i, fd;
  380. unsigned char j, si, dat[128];
  381. if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) {
  382. error( "Fatal: no random number source available.\n" );
  383. exit( 3 );
  384. }
  385. if (read( fd, dat, 128 ) != 128) {
  386. error( "Fatal: cannot read random number source.\n" );
  387. exit( 3 );
  388. }
  389. close( fd );
  390. for (i = 0; i < 256; i++)
  391. rs.s[i] = i;
  392. for (i = j = 0; i < 256; i++) {
  393. si = rs.s[i];
  394. j += si + dat[i & 127];
  395. rs.s[i] = rs.s[j];
  396. rs.s[j] = si;
  397. }
  398. rs.i = rs.j = 0;
  399. for (i = 0; i < 256; i++)
  400. arc4_getbyte();
  401. }
  402. unsigned char
  403. arc4_getbyte( void )
  404. {
  405. unsigned char si, sj;
  406. rs.i++;
  407. si = rs.s[rs.i];
  408. rs.j += si;
  409. sj = rs.s[rs.j];
  410. rs.s[rs.i] = sj;
  411. rs.s[rs.j] = si;
  412. return rs.s[(si + sj) & 0xff];
  413. }
  414. #ifdef HAVE_SYS_POLL_H
  415. static struct pollfd *pollfds;
  416. #else
  417. # ifdef HAVE_SYS_SELECT_H
  418. # include <sys/select.h>
  419. # endif
  420. # define pollfds fdparms
  421. #endif
  422. static struct {
  423. void (*cb)( int what, void *aux );
  424. void *aux;
  425. #ifndef HAVE_SYS_POLL_H
  426. int fd, events;
  427. #endif
  428. int faked;
  429. } *fdparms;
  430. static int npolls, rpolls, changed;
  431. static int
  432. find_fd( int fd )
  433. {
  434. int n;
  435. for (n = 0; n < npolls; n++)
  436. if (pollfds[n].fd == fd)
  437. return n;
  438. return -1;
  439. }
  440. void
  441. add_fd( int fd, void (*cb)( int events, void *aux ), void *aux )
  442. {
  443. int n;
  444. assert( find_fd( fd ) < 0 );
  445. n = npolls++;
  446. if (rpolls < npolls) {
  447. rpolls = npolls;
  448. #ifdef HAVE_SYS_POLL_H
  449. pollfds = nfrealloc(pollfds, npolls * sizeof(*pollfds));
  450. #endif
  451. fdparms = nfrealloc(fdparms, npolls * sizeof(*fdparms));
  452. }
  453. pollfds[n].fd = fd;
  454. pollfds[n].events = 0; /* POLLERR & POLLHUP implicit */
  455. fdparms[n].faked = 0;
  456. fdparms[n].cb = cb;
  457. fdparms[n].aux = aux;
  458. changed = 1;
  459. }
  460. void
  461. conf_fd( int fd, int and_events, int or_events )
  462. {
  463. int n = find_fd( fd );
  464. assert( n >= 0 );
  465. pollfds[n].events = (pollfds[n].events & and_events) | or_events;
  466. }
  467. void
  468. fake_fd( int fd, int events )
  469. {
  470. int n = find_fd( fd );
  471. assert( n >= 0 );
  472. fdparms[n].faked |= events;
  473. }
  474. void
  475. del_fd( int fd )
  476. {
  477. int n = find_fd( fd );
  478. assert( n >= 0 );
  479. npolls--;
  480. #ifdef HAVE_SYS_POLL_H
  481. memmove(pollfds + n, pollfds + n + 1, (npolls - n) * sizeof(*pollfds));
  482. #endif
  483. memmove(fdparms + n, fdparms + n + 1, (npolls - n) * sizeof(*fdparms));
  484. changed = 1;
  485. }
  486. #define shifted_bit(in, from, to) \
  487. (((unsigned)(in) & from) \
  488. / (from > to ? from / to : 1) \
  489. * (to > from ? to / from : 1))
  490. static void
  491. event_wait( void )
  492. {
  493. int m, n;
  494. #ifdef HAVE_SYS_POLL_H
  495. int timeout = -1;
  496. for (n = 0; n < npolls; n++)
  497. if (fdparms[n].faked) {
  498. timeout = 0;
  499. break;
  500. }
  501. if (poll( pollfds, npolls, timeout ) < 0) {
  502. perror( "poll() failed in event loop" );
  503. abort();
  504. }
  505. for (n = 0; n < npolls; n++)
  506. if ((m = pollfds[n].revents | fdparms[n].faked)) {
  507. assert( !(m & POLLNVAL) );
  508. fdparms[n].faked = 0;
  509. fdparms[n].cb( m | shifted_bit( m, POLLHUP, POLLIN ), fdparms[n].aux );
  510. if (changed) {
  511. changed = 0;
  512. break;
  513. }
  514. }
  515. #else
  516. struct timeval *timeout = 0;
  517. static struct timeval null_tv;
  518. fd_set rfds, wfds, efds;
  519. int fd;
  520. FD_ZERO( &rfds );
  521. FD_ZERO( &wfds );
  522. FD_ZERO( &efds );
  523. m = -1;
  524. for (n = 0; n < npolls; n++) {
  525. if (fdparms[n].faked)
  526. timeout = &null_tv;
  527. fd = fdparms[n].fd;
  528. if (fdparms[n].events & POLLIN)
  529. FD_SET( fd, &rfds );
  530. if (fdparms[n].events & POLLOUT)
  531. FD_SET( fd, &wfds );
  532. FD_SET( fd, &efds );
  533. if (fd > m)
  534. m = fd;
  535. }
  536. if (select( m + 1, &rfds, &wfds, &efds, timeout ) < 0) {
  537. perror( "select() failed in event loop" );
  538. abort();
  539. }
  540. for (n = 0; n < npolls; n++) {
  541. fd = fdparms[n].fd;
  542. m = fdparms[n].faked;
  543. if (FD_ISSET( fd, &rfds ))
  544. m |= POLLIN;
  545. if (FD_ISSET( fd, &wfds ))
  546. m |= POLLOUT;
  547. if (FD_ISSET( fd, &efds ))
  548. m |= POLLERR;
  549. if (m) {
  550. fdparms[n].faked = 0;
  551. fdparms[n].cb( m, fdparms[n].aux );
  552. if (changed) {
  553. changed = 0;
  554. break;
  555. }
  556. }
  557. }
  558. #endif
  559. }
  560. void
  561. main_loop( void )
  562. {
  563. while (npolls)
  564. event_wait();
  565. }