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

  ViewVC Help
Powered by ViewVC 1.1.5