2 * Copyright (C) 2003 Sean Chittenden <seanc@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/games/random/randomize_fd.c,v 1.2.2.1 2003/02/15 10:34:35 seanc Exp $
29 #include <sys/types.h>
30 #include <sys/param.h>
39 #include "randomize_fd.h"
41 static struct rand_node
*rand_root
;
42 static struct rand_node
*rand_tail
;
44 static struct rand_node
*
45 rand_node_allocate(void)
49 n
= (struct rand_node
*)malloc(sizeof(struct rand_node
));
60 rand_node_free(struct rand_node
*n
)
71 rand_node_free_rec(struct rand_node
*n
)
75 rand_node_free_rec(n
->next
);
82 rand_node_append(struct rand_node
*n
)
84 if (rand_root
== NULL
)
85 rand_root
= rand_tail
= n
;
93 randomize_fd(int fd
, int type
, int unique
, double denom
)
96 u_int numnode
, j
, selected
, slen
;
97 struct rand_node
*n
, *prev
;
98 int bufleft
, eof
, fndstr
, ret
;
99 size_t bufc
, buflen
, i
;
102 rand_root
= rand_tail
= NULL
;
104 bufleft
= eof
= fndstr
= numnode
= ret
= 0;
106 if (type
== RANDOM_TYPE_UNSET
)
107 type
= RANDOM_TYPE_LINES
;
109 buflen
= sizeof(u_char
) * MAXBSIZE
;
110 buf
= (u_char
*)malloc(buflen
);
115 /* Check to see if we have bits in the buffer */
117 len
= read(fd
, buf
, buflen
);
123 } else if ((size_t)len
< buflen
)
124 buflen
= (size_t)len
;
129 /* Look for a newline */
130 for (i
= bufc
; i
<= buflen
&& bufleft
>= 0; i
++, bufleft
--) {
134 memmove(buf
, &buf
[bufc
], i
- bufc
);
137 len
= read(fd
, &buf
[i
], buflen
- i
);
143 } else if (len
< (ssize_t
)(buflen
- i
))
144 buflen
= i
+ (size_t)len
;
150 p
= (u_char
*)realloc(buf
, buflen
* 2);
156 len
= read(fd
, &buf
[i
], buflen
);
162 } else if (len
< (ssize_t
)(buflen
- i
))
163 buflen
= (size_t)len
;
172 if ((type
== RANDOM_TYPE_LINES
&& buf
[i
] == '\n') ||
173 (type
== RANDOM_TYPE_WORDS
&& isspace((int)buf
[i
])) ||
174 (eof
&& i
== buflen
- 1)) {
176 n
= rand_node_allocate();
178 slen
= i
- (u_long
)bufc
;
180 n
->cp
= (u_char
*)malloc(slen
+ 2);
184 memmove(n
->cp
, &buf
[bufc
], slen
);
185 n
->cp
[slen
] = buf
[i
];
186 n
->cp
[slen
+ 1] = '\0';
198 /* Necessary evil to compensate for files that don't end with a newline */
204 for (i
= numnode
; i
> 0; i
--) {
205 selected
= ((int)denom
* random())/(((double)RAND_MAX
+ 1) / numnode
);
207 for (j
= 0, prev
= n
= rand_root
; n
!= NULL
; j
++, prev
= n
, n
= n
->next
) {
212 ret
= printf("%.*s", (int)n
->len
- 1, n
->cp
);
221 prev
->next
= n
->next
;
233 rand_node_free_rec(rand_root
);