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

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/util.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5