/[pkg-mixmaster]/trunk/Mix/Src/util.c
ViewVC logotype

Contents of /trunk/Mix/Src/util.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations) (download)
Tue Nov 6 23:41:58 2001 UTC (11 years, 6 months ago) by rabbi
File MIME type: text/plain
File size: 12186 byte(s)
First round of changes adding support for Mixmaster as a service under
Windows NT.
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Utility functions
9 $Id: util.c,v 1.2 2001/11/06 23:41:58 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <fcntl.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #ifdef POSIX
20 #include <unistd.h>
21 #include <sys/file.h>
22 #include <termios.h>
23 #else
24 #include <io.h>
25 #endif
26 #ifdef HAVE_GETKEY
27 #include <pc.h>
28 #endif
29 #include <assert.h>
30
31 /** string comparison functions. return 1 on match, 0 otherwise ********/
32
33 int strileft(const char *string, const char *keyword)
34 {
35 register unsigned int i;
36
37 for (i = 0; keyword[i] != '\0'; i++)
38 if (tolower(string[i]) != tolower(keyword[i]))
39 return 0;
40 return 1;
41 }
42
43 int striright(const char *string, const char *keyword)
44 {
45 int l;
46 l = strlen(string) - strlen(keyword);
47 return (l >= 0 ? strieq(string + l, keyword) : -1);
48 }
49
50 int strleft(const char *string, const char *keyword)
51 {
52 register unsigned int i;
53
54 for (i = 0; keyword[i] != '\0'; i++)
55 if (string[i] != keyword[i])
56 return 0;
57 return 1;
58 }
59
60 int strifind(const char *string, const char *keyword)
61 {
62 register unsigned int i, j;
63 char k;
64
65 k = tolower(keyword[0]);
66 for (i = 0; string[i] != '\0'; i++) {
67 if (tolower(string[i]) == k) {
68 for (j = 1; keyword[j] != '\0'; j++)
69 if (tolower(string[i + j]) != tolower(keyword[j]))
70 goto next;
71 return 1;
72 }
73 next:
74 ;
75 }
76 return 0;
77 }
78
79 int strieq(const char *s1, const char *s2)
80 {
81 register unsigned int i = 0;
82
83 do
84 if (tolower(s1[i]) != tolower(s2[i]))
85 return 0;
86 while (s1[i++] != '\0') ;
87 return 1;
88 }
89
90 int streq(const char *a, const char *b)
91 {
92 return (strcmp(a, b) == 0);
93 }
94
95 int strfind(const char *a, const char *keyword)
96 {
97 return (strstr(a, keyword) != NULL);
98 }
99
100 void strcatn(char *dest, const char *src, int n)
101 {
102 int l;
103 l = strlen(dest);
104 if (l < n)
105 strncpy(dest + l, src, n - l - 1);
106 dest[n-1] = '\0';
107 }
108
109 /** files **************************************************************/
110
111 int mixfile(char *path, const char *name)
112 {
113 assert(path != NULL && name != NULL);
114
115 if (name[0] == DIRSEP || (isalpha(name[0]) && name[1] == ':') || MIXDIR == NULL)
116 strncpy(path, name, PATHMAX);
117 else {
118 strncpy(path, MIXDIR, PATHMAX);
119 strcatn(path, name, PATHMAX);
120 }
121 return (0);
122 }
123
124 FILE *mix_openfile(const char *name, const char *a)
125 {
126 char path[PATHMAX];
127
128 mixfile(path, name);
129 return (fopen(path, a));
130 }
131
132 FILE *openpipe(const char *prog)
133 {
134 FILE *p = NULL;
135
136 #ifdef POSIX
137 p = popen(prog, "w");
138 #endif
139 #ifdef _MSC
140 p = _popen(prog, "w");
141 #endif
142
143 if (p == NULL)
144 errlog(ERRORMSG, "Unable to open pipe to %s\n", prog);
145 return p;
146 }
147
148 int
149 file_to_out(const char *filename)
150 {
151 int len;
152 FILE *fp;
153 char chunk[1024];
154
155 if ((fp = mix_openfile(filename, "r")) == NULL)
156 return -1;
157 while ((len = fread(chunk, 1, sizeof(chunk), fp)) > 0)
158 {
159 fwrite(chunk, 1, len, stdout);
160 }
161 fclose (fp);
162 return (len == 0 ? 0 : (-1));
163 }
164
165 int closepipe(FILE *p)
166 {
167 #ifdef POSIX
168 return (pclose(p));
169 #elif defined(_MSC)
170 return (_pclose(p));
171 #else
172 return -1;
173 #endif
174 }
175
176 /** Base 64 encoding ****************************************************/
177
178 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
179 static byte asctobin[] =
180 {
181 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
182 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
183 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
184 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
185 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
186 0x80, 0x80, 0x80, 0076, 0x80, 0x80, 0x80, 0077,
187 0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073,
188 0074, 0075, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
189 0x80, 0000, 0001, 0002, 0003, 0004, 0005, 0006,
190 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016,
191 0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026,
192 0027, 0030, 0031, 0x80, 0x80, 0x80, 0x80, 0x80,
193 0x80, 0032, 0033, 0034, 0035, 0036, 0037, 0040,
194 0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050,
195 0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060,
196 0061, 0062, 0063, 0x80, 0x80, 0x80, 0x80, 0x80,
197
198 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
199 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
200 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
201 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
202 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
203 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
204 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
205 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
206 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
207 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
208 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
209 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
210 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
211 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
212 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
213 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
214 };
215
216 void id_encode(byte id[], byte *s)
217 {
218 sprintf
219 (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
220 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9],
221 id[10], id[11], id[12], id[13], id[14], id[15]);
222 }
223
224 void id_decode(byte *s, byte id[])
225 {
226 int i, x[16];
227
228 sscanf
229 (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
230 x, x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7, x + 8,
231 x + 9, x + 10, x + 11, x + 12, x + 13, x + 14, x + 15);
232 for (i = 0; i < 16; i++)
233 id[i] = x[i];
234 }
235
236 int encode(BUFFER *in, int linelen)
237 {
238 byte *b, *e;
239 int i, l, m;
240 unsigned long u;
241 BUFFER *out;
242
243 out = buf_new();
244
245 l = in->length;
246 if (l % 3 != 0)
247 l += 2;
248 l = l / 3 * 4;
249
250 if (linelen) {
251 l += l / linelen + (l % linelen > 0 ? 1 : 0);
252 }
253 linelen /= 4; /* blocks of 4 characters */
254
255 buf_prepare(out, l);
256
257 b = in->data;
258 e = out->data;
259 m = in->length - 2;
260 for (i = 0, l = 0; i < m; i += 3) {
261 u = ((unsigned long) b[i] << 16) | ((unsigned long) b[i + 1] << 8) |
262 b[i + 2];
263 *e++ = bintoasc[(u >> 18) & 0x3f];
264 *e++ = bintoasc[(u >> 12) & 0x3f];
265 *e++ = bintoasc[(u >> 6) & 0x3f];
266 *e++ = bintoasc[u & 0x3f];
267 if (linelen && ++l >= linelen) {
268 l = 0;
269 *e++ = '\n';
270 }
271 }
272 if (i < in->length) {
273 *e++ = bintoasc[b[i] >> 2];
274 *e++ = bintoasc[((b[i] << 4) & 0x30) | ((b[i + 1] >> 4) & 0x0f)];
275 if (i + 1 == in->length)
276 *e++ = '=';
277 else
278 *e++ = bintoasc[((b[i + 1] << 2) & 0x3c) | ((b[i + 2] >> 6) & 0x03)];
279 *e++ = '=';
280 ++l;
281 }
282 if (linelen && l != 0)
283 *e++ = '\n';
284 *e = '\0';
285
286 assert(out->data + out->length == e);
287 buf_move(in, out);
288 buf_free(out);
289 return (0);
290 }
291
292 int decode(BUFFER *in, BUFFER *out)
293 {
294 int err = 0;
295 register byte c0, c1, c2, c3;
296 register byte *a, *d, *end;
297 int tempbuf = 0;
298 int i;
299
300 if (in == out) {
301 out = buf_new();
302 tempbuf = 1;
303 }
304 buf_prepare(out, 3 * (in->length - in->ptr) / 4);
305
306 a = in->data + in->ptr;
307 end = in->data + in->length - 3;
308 d = out->data;
309 i = 0;
310
311 while (a < end) {
312 if ((c0 = asctobin[a[0]]) & 0x80 ||
313 (c1 = asctobin[a[1]]) & 0x80 ||
314 (c2 = asctobin[a[2]]) & 0x80 ||
315 (c3 = asctobin[a[3]]) & 0x80) {
316 if (a[0] == '\n') { /* ignore newline */
317 a++;
318 continue;
319 } else if (a[0] == '\r' && a[1] == '\n') { /* ignore crlf */
320 a += 2;
321 continue;
322 } else if (a[0] == '=' && a[1] == '4' && a[2] == '6') {
323 a += 2; /* '=46' at the left of a line really is 'F' */
324 *a = 'F'; /* fix in memory ... */
325 continue;
326 } else if (a[2] == '=' || a[3] == '=') {
327 if (a[0] & 0x80 || (c0 = asctobin[a[0]]) & 0x80 ||
328 a[1] & 0x80 || (c1 = asctobin[a[1]]) & 0x80)
329 err = -1;
330 else if (a[2] == '=')
331 c2 = 0, i += 1;
332 else if (a[2] & 0x80 || (c2 = asctobin[a[2]]) & 0x80)
333 err = -1;
334 else
335 i += 2;
336 if (err == 0) {
337 /* read the correct final block */
338 *d++ = (byte) ((c0 << 2) | (c1 >> 4));
339 *d++ = (byte) ((c1 << 4) | (c2 >> 2));
340 if (a[3] != '=')
341 *d++ = (byte) ((c2 << 6));
342 #if 1
343 if (a + 4 < in->data + in->length) {
344 a += 4;
345 continue; /* support Mixmaster 2.0.3 encoding */
346 }
347 #endif
348 break;
349 }
350 }
351 err = -1;
352 break;
353 }
354 a += 4;
355
356 *d++ = (byte) ((c0 << 2) | (c1 >> 4));
357 *d++ = (byte) ((c1 << 4) | (c2 >> 2));
358 *d++ = (byte) ((c2 << 6) | c3);
359 i += 3;
360 }
361
362 in->ptr = a - in->data;
363
364 assert(i <= out->length);
365 out->length = i;
366
367 if (tempbuf) {
368 buf_move(in, out);
369 buf_free(out);
370 }
371 return (err);
372 }
373
374 LOCK *lockfile(char *filename)
375 {
376 LOCK *l;
377 char name[LINELEN];
378
379 strcpy(name, "lck");
380 if (strchr(filename, DIRSEP))
381 strcatn(name, strrchr(filename, DIRSEP), LINELEN);
382 else
383 strcatn(name, filename, LINELEN);
384 l = malloc(sizeof(LOCK));
385
386 l->name = malloc(PATHMAX);
387 mixfile(l->name, name);
388 l->f = mix_openfile(l->name, "w+");
389 if (l->f)
390 lock(l->f);
391 return (l);
392 }
393
394 int unlockfile(LOCK *l)
395 {
396 if (l->f) {
397 unlock(l->f);
398 fclose(l->f);
399 }
400 unlink(l->name);
401 free(l->name);
402 free(l);
403 return (0);
404 }
405
406 int lock(FILE *f)
407 {
408 #ifndef WIN32
409 struct flock lockstruct;
410
411 lockstruct.l_type = F_WRLCK;
412 lockstruct.l_whence = 0;
413 lockstruct.l_start = 0;
414 lockstruct.l_len = 0;
415 return (fcntl(fileno(f), F_SETLKW, &lockstruct));
416 #else
417 return (0);
418 #endif
419 }
420
421 int unlock(FILE *f)
422 {
423 #ifndef WIN32
424
425 struct flock lockstruct;
426
427 lockstruct.l_type = F_UNLCK;
428 lockstruct.l_whence = 0;
429 lockstruct.l_start = 0;
430 lockstruct.l_len = 0;
431 return (fcntl(fileno(f), F_SETLKW, &lockstruct));
432 #else
433 return (0);
434 #endif
435 }
436
437 /* get passphrase ******************************************************/
438
439 static int getuserpass(BUFFER *b, int mode)
440 {
441 char p[LINELEN];
442 int fd;
443 int n;
444
445 #ifdef HAVE_TERMIOS
446 struct termios attr;
447
448 #endif
449
450 if (mode == 0)
451 fprintf(stderr, "enter passphrase: ");
452 else
453 fprintf(stderr, "re-enter passphrase: ");
454 fflush(stderr);
455 #ifndef UNIX
456 #ifdef HAVE_GETKEY
457 for (n = 0; p[n] != '\n' && n < LINELEN; n++) {
458 p[n] = getkey();
459 }
460 p[n] = 0;
461 #else
462 scanf("%127s", p);
463 #endif
464 #else
465 fd = open("/dev/tty", O_RDONLY);
466 if (tcgetattr(fd, &attr) != 0)
467 return (-1);
468 attr.c_lflag &= ~ECHO;
469 attr.c_lflag |= ICANON;
470 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
471 return (-1);
472
473 n = read(fd, p, LINELEN);
474
475 attr.c_lflag |= ECHO;
476 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
477 return (-1);
478
479 close(fd);
480 fprintf(stderr, "\n");
481 p[n - 1] = 0;
482 #endif
483 if (mode == 0)
484 buf_appends(b, p);
485 else
486 return (bufeq(b, p));
487 return (0);
488 }
489
490 static BUFFER *userpass = NULL;
491
492 int user_pass(BUFFER *key)
493 {
494 if (userpass == NULL) {
495 userpass = buf_new();
496 userpass->sensitive = 1;
497 if (getenv("MIXPASS"))
498 buf_sets(userpass, getenv("MIXPASS"));
499 else if (menu_getuserpass(userpass, 0) == -1)
500 getuserpass(userpass, 0);
501 }
502 buf_set(key, userpass);
503 key->sensitive = 1;
504 return (0);
505 }
506
507 int user_confirmpass(BUFFER *key)
508 {
509 int ok;
510
511 ok = menu_getuserpass(key, 1);
512 if (ok == -1)
513 ok = getuserpass(key, 1);
514 return (ok);
515 }
516
517 void user_delpass(void)
518 {
519 if (userpass)
520 buf_free(userpass);
521 userpass = NULL;
522 }
523
524 /* functions missing on some systems *************************************/
525
526 #ifdef __RSXNT__
527 int fileno(FILE *f)
528 {
529 return (f->_handle);
530 }
531
532 #endif
533
534 #ifdef _MSC /* Visual C lacks dirent */
535
536 DIR *opendir(const char *name)
537 {
538 DIR *dir;
539 WIN32_FIND_DATA d;
540 char path[PATHMAX];
541
542 dir = malloc(sizeof(HANDLE));
543
544 sprintf(path, "%s%c*", name, DIRSEP);
545 *dir = FindFirstFile(path, &d);
546 /* first file found is "." -- can be safely ignored here */
547
548 if (*dir == INVALID_HANDLE_VALUE) {
549 free(dir);
550 return (NULL);
551 } else
552 return (dir);
553 }
554
555 struct dirent e;
556 struct dirent *readdir(DIR *dir)
557 {
558 WIN32_FIND_DATA d;
559 int ok;
560
561 ok = FindNextFile(*dir, &d);
562 if (ok) {
563 strncpy(e.d_name, d.cFileName, PATHMAX);
564 return (&e);
565 } else
566 return (NULL);
567 }
568
569 int closedir(DIR *dir)
570 {
571 if (dir) {
572 FindClose(*dir);
573 free(dir);
574 return (0);
575 }
576 return (-1);
577 }
578
579 #endif

  ViewVC Help
Powered by ViewVC 1.1.5