util.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * mbsync - mailbox synchronizer
  3. * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
  4. * Copyright (C) 2002-2004 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 <stdlib.h>
  25. #include <unistd.h>
  26. #include <fcntl.h>
  27. #include <string.h>
  28. #include <pwd.h>
  29. #include <ctype.h>
  30. int DFlags, Ontty;
  31. static int need_nl;
  32. void
  33. debug( const char *msg, ... )
  34. {
  35. va_list va;
  36. if (DFlags & DEBUG) {
  37. va_start( va, msg );
  38. vprintf( msg, va );
  39. va_end( va );
  40. fflush( stdout );
  41. }
  42. }
  43. void
  44. debugn( const char *msg, ... )
  45. {
  46. va_list va;
  47. if (DFlags & DEBUG) {
  48. va_start( va, msg );
  49. vprintf( msg, va );
  50. va_end( va );
  51. fflush( stdout );
  52. need_nl = Ontty;
  53. }
  54. }
  55. void
  56. info( const char *msg, ... )
  57. {
  58. va_list va;
  59. if (!(DFlags & QUIET)) {
  60. va_start( va, msg );
  61. vprintf( msg, va );
  62. va_end( va );
  63. fflush( stdout );
  64. }
  65. }
  66. void
  67. infon( const char *msg, ... )
  68. {
  69. va_list va;
  70. if (!(DFlags & QUIET)) {
  71. va_start( va, msg );
  72. vprintf( msg, va );
  73. va_end( va );
  74. fflush( stdout );
  75. need_nl = Ontty;
  76. }
  77. }
  78. void
  79. infoc( char c )
  80. {
  81. if (!(DFlags & QUIET)) {
  82. putchar( c );
  83. fflush( stdout );
  84. need_nl = Ontty;
  85. }
  86. }
  87. void
  88. warn( const char *msg, ... )
  89. {
  90. va_list va;
  91. if (!(DFlags & VERYQUIET)) {
  92. if (need_nl) {
  93. putchar( '\n' );
  94. need_nl = 0;
  95. }
  96. va_start( va, msg );
  97. vfprintf( stderr, msg, va );
  98. va_end( va );
  99. }
  100. }
  101. void
  102. error( const char *msg, ... )
  103. {
  104. va_list va;
  105. if (need_nl) {
  106. putchar( '\n' );
  107. need_nl = 0;
  108. }
  109. va_start( va, msg );
  110. vfprintf( stderr, msg, va );
  111. va_end( va );
  112. }
  113. char *
  114. next_arg( char **s )
  115. {
  116. char *ret;
  117. if (!s || !*s)
  118. return 0;
  119. while (isspace( (unsigned char) **s ))
  120. (*s)++;
  121. if (!**s) {
  122. *s = 0;
  123. return 0;
  124. }
  125. if (**s == '"') {
  126. ++*s;
  127. ret = *s;
  128. *s = strchr( *s, '"' );
  129. } else {
  130. ret = *s;
  131. while (**s && !isspace( (unsigned char) **s ))
  132. (*s)++;
  133. }
  134. if (*s) {
  135. if (**s)
  136. *(*s)++ = 0;
  137. if (!**s)
  138. *s = 0;
  139. }
  140. return ret;
  141. }
  142. void
  143. add_string_list( string_list_t **list, const char *str )
  144. {
  145. string_list_t *elem;
  146. int len;
  147. len = strlen( str );
  148. elem = nfmalloc( sizeof(*elem) + len );
  149. elem->next = *list;
  150. *list = elem;
  151. memcpy( elem->string, str, len + 1 );
  152. }
  153. void
  154. free_string_list( string_list_t *list )
  155. {
  156. string_list_t *tlist;
  157. for (; list; list = tlist) {
  158. tlist = list->next;
  159. free( list );
  160. }
  161. }
  162. void
  163. free_generic_messages( message_t *msgs )
  164. {
  165. message_t *tmsg;
  166. for (; msgs; msgs = tmsg) {
  167. tmsg = msgs->next;
  168. free( msgs );
  169. }
  170. }
  171. #ifndef HAVE_VASPRINTF
  172. static int
  173. vasprintf( char **strp, const char *fmt, va_list ap )
  174. {
  175. int len;
  176. char tmp[1024];
  177. if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 )))
  178. return -1;
  179. if (len >= (int)sizeof(tmp))
  180. vsprintf( *strp, fmt, ap );
  181. else
  182. memcpy( *strp, tmp, len + 1 );
  183. return len;
  184. }
  185. #endif
  186. void
  187. oob( void )
  188. {
  189. fputs( "Fatal: buffer too small. Please report a bug.\n", stderr );
  190. abort();
  191. }
  192. int
  193. nfsnprintf( char *buf, int blen, const char *fmt, ... )
  194. {
  195. int ret;
  196. va_list va;
  197. va_start( va, fmt );
  198. if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen)
  199. oob();
  200. va_end( va );
  201. return ret;
  202. }
  203. static void ATTR_NORETURN
  204. oom( void )
  205. {
  206. fputs( "Fatal: Out of memory\n", stderr );
  207. abort();
  208. }
  209. void *
  210. nfmalloc( size_t sz )
  211. {
  212. void *ret;
  213. if (!(ret = malloc( sz )))
  214. oom();
  215. return ret;
  216. }
  217. void *
  218. nfcalloc( size_t sz )
  219. {
  220. void *ret;
  221. if (!(ret = calloc( sz, 1 )))
  222. oom();
  223. return ret;
  224. }
  225. void *
  226. nfrealloc( void *mem, size_t sz )
  227. {
  228. char *ret;
  229. if (!(ret = realloc( mem, sz )) && sz)
  230. oom();
  231. return ret;
  232. }
  233. char *
  234. nfstrdup( const char *str )
  235. {
  236. char *ret;
  237. if (!(ret = strdup( str )))
  238. oom();
  239. return ret;
  240. }
  241. int
  242. nfvasprintf( char **str, const char *fmt, va_list va )
  243. {
  244. int ret = vasprintf( str, fmt, va );
  245. if (ret < 0)
  246. oom();
  247. return ret;
  248. }
  249. int
  250. nfasprintf( char **str, const char *fmt, ... )
  251. {
  252. int ret;
  253. va_list va;
  254. va_start( va, fmt );
  255. ret = nfvasprintf( str, fmt, va );
  256. va_end( va );
  257. return ret;
  258. }
  259. /*
  260. static struct passwd *
  261. cur_user( void )
  262. {
  263. char *p;
  264. struct passwd *pw;
  265. uid_t uid;
  266. uid = getuid();
  267. if ((!(p = getenv("LOGNAME")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  268. (!(p = getenv("USER")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) &&
  269. !(pw = getpwuid( uid )))
  270. {
  271. fputs ("Cannot determinate current user\n", stderr);
  272. return 0;
  273. }
  274. return pw;
  275. }
  276. */
  277. static char *
  278. my_strndup( const char *s, size_t nchars )
  279. {
  280. char *r = nfmalloc( nchars + 1 );
  281. memcpy( r, s, nchars );
  282. r[nchars] = 0;
  283. return r;
  284. }
  285. char *
  286. expand_strdup( const char *s )
  287. {
  288. struct passwd *pw;
  289. const char *p, *q;
  290. char *r;
  291. if (*s == '~') {
  292. s++;
  293. if (!*s) {
  294. p = 0;
  295. q = Home;
  296. } else if (*s == '/') {
  297. p = s;
  298. q = Home;
  299. } else {
  300. if ((p = strchr( s, '/' ))) {
  301. r = my_strndup( s, (int)(p - s) );
  302. pw = getpwnam( r );
  303. free( r );
  304. } else
  305. pw = getpwnam( s );
  306. if (!pw)
  307. return 0;
  308. q = pw->pw_dir;
  309. }
  310. nfasprintf( &r, "%s%s", q, p ? p : "" );
  311. return r;
  312. } else
  313. return nfstrdup( s );
  314. }
  315. static int
  316. compare_ints( const void *l, const void *r )
  317. {
  318. return *(int *)l - *(int *)r;
  319. }
  320. void
  321. sort_ints( int *arr, int len )
  322. {
  323. qsort( arr, len, sizeof(int), compare_ints );
  324. }
  325. static struct {
  326. unsigned char i, j, s[256];
  327. } rs;
  328. void
  329. arc4_init( void )
  330. {
  331. int i, fd;
  332. unsigned char j, si, dat[128];
  333. if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) {
  334. error( "Fatal: no random number source available.\n" );
  335. exit( 3 );
  336. }
  337. if (read( fd, dat, 128 ) != 128) {
  338. error( "Fatal: cannot read random number source.\n" );
  339. exit( 3 );
  340. }
  341. close( fd );
  342. for (i = 0; i < 256; i++)
  343. rs.s[i] = i;
  344. for (i = j = 0; i < 256; i++) {
  345. si = rs.s[i];
  346. j += si + dat[i & 127];
  347. rs.s[i] = rs.s[j];
  348. rs.s[j] = si;
  349. }
  350. rs.i = rs.j = 0;
  351. for (i = 0; i < 256; i++)
  352. arc4_getbyte();
  353. }
  354. unsigned char
  355. arc4_getbyte( void )
  356. {
  357. unsigned char si, sj;
  358. rs.i++;
  359. si = rs.s[rs.i];
  360. rs.j += si;
  361. sj = rs.s[rs.j];
  362. rs.s[rs.i] = sj;
  363. rs.s[rs.j] = si;
  364. return rs.s[(si + sj) & 0xff];
  365. }