/[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 - (hide annotations) (download)
Thu Oct 10 13:18:45 2002 UTC (10 years, 7 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 rabbi 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 weaselp 354 $Id: util.c,v 1.2.2.4 2002/10/10 13:18:45 weaselp Exp $ */
10 rabbi 1
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 weaselp 354 #include <signal.h>
21     #include <errno.h>
22 rabbi 1 #include <unistd.h>
23     #include <sys/file.h>
24     #include <termios.h>
25 weaselp 327 #else /* end of POSIX */
26 rabbi 1 #include <io.h>
27 weaselp 327 #endif /* else if not POSIX */
28 rabbi 1 #ifdef HAVE_GETKEY
29     #include <pc.h>
30 weaselp 327 #endif /* HAVE_GETKEY */
31 rabbi 1 #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 rabbi 11 if (name[0] == DIRSEP || (isalpha(name[0]) && name[1] == ':') || MIXDIR == NULL)
118 rabbi 1 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 weaselp 327 #endif /* POSIX */
141 rabbi 11 #ifdef _MSC
142     p = _popen(prog, "w");
143 weaselp 327 #endif /* _MSC */
144 rabbi 1
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 weaselp 327 #elif defined(_MSC) /* end of POSIX */
172 rabbi 11 return (_pclose(p));
173 weaselp 327 #else /* end of defined(_MSC) */
174 rabbi 1 return -1;
175 weaselp 327 #endif /* else if not defined(_MSC), POSIX */
176 rabbi 1 }
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 weaselp 331 u = ((unsigned long) b[i] << 16) | ((unsigned long) b[i + 1] << 8) |
264 rabbi 1 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 rabbi 306 register byte c0 = 0, c1 = 0, c2 = 0, c3 = 0;
298 rabbi 1 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 rabbi 306 } else if (a[0] == '=' && a[1] == '4' && a[2] == '6' && !(asctobin[a[5]] & 0x80) ) {
325 rabbi 1 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 weaselp 327 #endif /* 1 */
350 rabbi 1 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 rabbi 11 if (strchr(filename, DIRSEP))
383     strcatn(name, strrchr(filename, DIRSEP), LINELEN);
384 rabbi 1 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 weaselp 327 #else /* end of WIN32 */
419 rabbi 1 return (0);
420 weaselp 327 #endif /* else if not WIN32 */
421 rabbi 1 }
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 weaselp 327 #else /* end of not WIN32 */
435 rabbi 1 return (0);
436 weaselp 327 #endif /* else if WIN32 */
437 rabbi 1 }
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 weaselp 327 #endif /* HAVE_TERMIOS */
451 rabbi 1
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 weaselp 327 #else /* end of HAVE_GETKEY */
464 rabbi 1 scanf("%127s", p);
465 weaselp 327 #endif /* else if not HAVE_GETKEY */
466     #else /* end of not UNIX */
467 rabbi 1 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 weaselp 327 #endif /* else if UNIX */
485 rabbi 1 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 weaselp 354 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 rabbi 1 /* functions missing on some systems *************************************/
598    
599     #ifdef __RSXNT__
600     int fileno(FILE *f)
601     {
602     return (f->_handle);
603     }
604    
605 weaselp 327 #endif /* __RSXNT__ */
606 rabbi 1
607     #ifdef _MSC /* Visual C lacks dirent */
608    
609     DIR *opendir(const char *name)
610     {
611     DIR *dir;
612 rabbi 11 WIN32_FIND_DATA d;
613     char path[PATHMAX];
614 rabbi 1
615     dir = malloc(sizeof(HANDLE));
616    
617 rabbi 11 sprintf(path, "%s%c*", name, DIRSEP);
618     *dir = FindFirstFile(path, &d);
619 rabbi 1 /* 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 rabbi 11 WIN32_FIND_DATA d;
632 rabbi 1 int ok;
633    
634 rabbi 11 ok = FindNextFile(*dir, &d);
635 rabbi 1 if (ok) {
636 rabbi 11 strncpy(e.d_name, d.cFileName, PATHMAX);
637 rabbi 1 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 weaselp 327 #endif /* _MSC */

  ViewVC Help
Powered by ViewVC 1.1.5