util.c 6.6 KB

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