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 $
27 * $DragonFly: src/games/random/randomize_fd.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
30 #include <sys/types.h>
31 #include <sys/param.h>
40 #include "randomize_fd.h"
42 static struct rand_node
*rand_root
;
43 static struct rand_node
*rand_tail
;
45 static struct rand_node
*
46 rand_node_allocate(void)
50 n
= (struct rand_node
*)malloc(sizeof(struct rand_node
));
61 rand_node_free(struct rand_node
*n
)
72 rand_node_free_rec(struct rand_node
*n
)
76 rand_node_free_rec(n
->next
);
83 rand_node_append(struct rand_node
*n
)
85 if (rand_root
== NULL
)
86 rand_root
= rand_tail
= n
;
94 randomize_fd(int fd
, int type
, int unique
, double denom
)
97 u_int numnode
, j
, selected
, slen
;
98 struct rand_node
*n
, *prev
;
99 int bufleft
, eof
, fndstr
, ret
;
100 size_t bufc
, buflen
, i
;
103 rand_root
= rand_tail
= NULL
;
105 bufleft
= eof
= fndstr
= numnode
= ret
= 0;
107 if (type
== RANDOM_TYPE_UNSET
)
108 type
= RANDOM_TYPE_LINES
;
110 buflen
= sizeof(u_char
) * MAXBSIZE
;
111 buf
= (u_char
*)malloc(buflen
);
116 /* Check to see if we have bits in the buffer */
118 len
= read(fd
, buf
, buflen
);
124 } else if ((size_t)len
< buflen
)
125 buflen
= (size_t)len
;
130 /* Look for a newline */
131 for (i
= bufc
; i
<= buflen
&& bufleft
>= 0; i
++, bufleft
--) {
135 memmove(buf
, &buf
[bufc
], i
- bufc
);
138 len
= read(fd
, &buf
[i
], buflen
- i
);
144 } else if (len
< (ssize_t
)(buflen
- i
))
145 buflen
= i
+ (size_t)len
;
151 p
= (u_char
*)realloc(buf
, buflen
* 2);
157 len
= read(fd
, &buf
[i
], buflen
);
163 } else if (len
< (ssize_t
)(buflen
- i
))
164 buflen
= (size_t)len
;
173 if ((type
== RANDOM_TYPE_LINES
&& buf
[i
] == '\n') ||
174 (type
== RANDOM_TYPE_WORDS
&& isspace((int)buf
[i
])) ||
175 (eof
&& i
== buflen
- 1)) {
177 n
= rand_node_allocate();
179 slen
= i
- (u_long
)bufc
;
181 n
->cp
= (u_char
*)malloc(slen
+ 2);
185 memmove(n
->cp
, &buf
[bufc
], slen
);
186 n
->cp
[slen
] = buf
[i
];
187 n
->cp
[slen
+ 1] = '\0';
199 /* Necessary evil to compensate for files that don't end with a newline */
205 for (i
= numnode
; i
> 0; i
--) {
206 selected
= ((int)denom
* random())/(((double)RAND_MAX
+ 1) / numnode
);
208 for (j
= 0, prev
= n
= rand_root
; n
!= NULL
; j
++, prev
= n
, n
= n
->next
) {
213 ret
= printf("%.*s", (int)n
->len
- 1, n
->cp
);
222 prev
->next
= n
->next
;
234 rand_node_free_rec(rand_root
);