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

  ViewVC Help
Powered by ViewVC 1.1.5