Imported upstream version 0.59.3
[hcoop/debian/courier-authlib.git] / random128 / random128.c
1 /*
2 ** Copyright 1998 - 2006 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #if HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #if HAVE_FCNTL_H
14 #include <fcntl.h>
15 #endif
16 #include <time.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22
23 #define MD5_INTERNAL
24 #include "md5/md5.h"
25
26 #include "random128.h"
27
28 static const char rcsid[]="$Id: random128.c,v 1.6 2006/05/28 15:29:52 mrsam Exp $";
29
30 const char *random128()
31 {
32 static char randombuf[sizeof(MD5_DIGEST)*2+1];
33
34 #ifdef RANDOM
35 {
36 int fd=open(RANDOM, O_RDONLY);
37 char buf2[sizeof(MD5_DIGEST)];
38 int i;
39
40 if (fd >= 0)
41 {
42 if (read(fd, buf2, sizeof(buf2)) == sizeof(buf2))
43 {
44 for (i=0; i<sizeof(buf2); i++)
45 sprintf(randombuf+i*2,
46 "%02X",
47 (int)(unsigned char)buf2[i]);
48 close(fd);
49 return (randombuf);
50 }
51 close(fd);
52 }
53 }
54 #endif
55
56 /* /dev/urandom not available or broken? Create some noise */
57
58 {
59 int pipefd[2];
60 int s;
61 char buf[512];
62 struct MD5_CONTEXT context;
63 MD5_DIGEST digest;
64 int n;
65 time_t t;
66 pid_t p, p2;
67 unsigned long l;
68
69 time(&t);
70 p=getpid();
71
72 if (pipe(pipefd)) return (0);
73 while ((p=fork()) == -1)
74 {
75 sleep (5);
76 }
77 if (p == 0)
78 {
79 dup2(pipefd[1], 1);
80 dup2(pipefd[1], 2);
81 close(pipefd[0]);
82 close(pipefd[1]);
83
84 #ifdef W
85 while ((p=fork()) == -1)
86 {
87 sleep (5);
88 }
89 if (p == 0)
90 {
91 execl(W, W, (char *)0);
92 perror(W);
93 _exit(0);
94 }
95 while (wait(&s) >= 0)
96 ;
97 #endif
98
99 execl(PS, PS, PS_OPTIONS, (char *)0);
100 perror(PS);
101 _exit(0);
102 }
103 close(pipefd[1]);
104 md5_context_init(&context);
105 md5_context_hashstream(&context, &t, sizeof(t));
106 md5_context_hashstream(&context, &p, sizeof(p));
107 l=sizeof(t)+sizeof(p);
108
109 while ((n=read(pipefd[0], buf, sizeof(buf))) > 0)
110 {
111 md5_context_hashstream(&context, buf, n);
112 l += n;
113 }
114 md5_context_endstream(&context, l);
115 md5_context_digest(&context, digest);
116 close(pipefd[0]);
117 while ((p2=wait(&s)) >= 0 && p != p2)
118 ;
119
120 for (n=0; n<sizeof(digest); n++)
121 sprintf(randombuf+n*2,
122 "%02X", (int)(unsigned char)digest[n]);
123 }
124
125 return (randombuf);
126 }