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 
random128()29 const char *random128()
30 {
31 static char randombuf[sizeof(MD5_DIGEST)*2+1];
32 
33 #ifdef	RANDOM
34 	{
35 	int	fd=open(RANDOM, O_RDONLY);
36 	char	buf2[sizeof(MD5_DIGEST)];
37 	int	i;
38 
39 		if (fd >= 0)
40 		{
41 			if (read(fd, buf2, sizeof(buf2)) == sizeof(buf2))
42 			{
43 				for (i=0; i<sizeof(buf2); i++)
44 					sprintf(randombuf+i*2,
45 						"%02X",
46 						(int)(unsigned char)buf2[i]);
47 				close(fd);
48 				return (randombuf);
49 			}
50 			close(fd);
51 		}
52 	}
53 #endif
54 
55 	/* /dev/urandom not available or broken?  Create some noise */
56 
57 	{
58 	int pipefd[2];
59 	int s;
60 	char	buf[512];
61 	struct MD5_CONTEXT context;
62 	MD5_DIGEST	digest;
63 	int	n;
64 	time_t	t;
65 	pid_t	p, p2;
66 	unsigned long l;
67 
68 		time(&t);
69 		p=getpid();
70 
71 		if (pipe(pipefd))	return (0);
72 		while ((p=fork()) == -1)
73 		{
74 			sleep (5);
75 		}
76 		if (p == 0)
77 		{
78 			dup2(pipefd[1], 1);
79 			dup2(pipefd[1], 2);
80 			close(pipefd[0]);
81 			close(pipefd[1]);
82 
83 #ifdef	W
84 			while ((p=fork()) == -1)
85 			{
86 				sleep (5);
87 			}
88 			if (p == 0)
89 			{
90 				execl(W, W, (char *)0);
91 				perror(W);
92 				_exit(0);
93 			}
94 			while (wait(&s) >= 0)
95 				;
96 #endif
97 
98 			execl(PS, PS, PS_OPTIONS, (char *)0);
99 			perror(PS);
100 			_exit(0);
101 		}
102 		close(pipefd[1]);
103 		md5_context_init(&context);
104 		md5_context_hashstream(&context, &t, sizeof(t));
105 		md5_context_hashstream(&context, &p, sizeof(p));
106 		l=sizeof(t)+sizeof(p);
107 
108 		while ((n=read(pipefd[0], buf, sizeof(buf))) > 0)
109 		{
110 			md5_context_hashstream(&context, buf, n);
111 			l += n;
112 		}
113 		md5_context_endstream(&context, l);
114 		md5_context_digest(&context, digest);
115 		close(pipefd[0]);
116 		while ((p2=wait(&s)) >= 0 && p != p2)
117 			;
118 
119 		for (n=0; n<sizeof(digest); n++)
120 			sprintf(randombuf+n*2,
121 				"%02X", (int)(unsigned char)digest[n]);
122 	}
123 
124 	return (randombuf);
125 }
126