+ int rc;
+
+ /* --- Spit out random data --- */
+
+ last = time(0);
+ bp = baton;
+ if (flags & f_progress) {
+ char *errbuf = xmalloc(BUFSIZ);
+ setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
+ if (outsz)
+ fprintf(stderr, "[%*s] 0%% 0\r[/\b", 50, "");
+ else
+ fputs("[ ] 0\r[/\b", stderr);
+ fflush(stderr);
+ }
+
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ for (;;) {
+ octet buf[BUFSIZ];
+ size_t sz = sizeof(buf);
+
+ /* --- Emit a bufferful (or less) of data --- */
+
+ if (outsz) {
+ if (sz > outsz - kb)
+ sz = outsz - kb;
+ }
+ r->ops->fill(r, buf, sz);
+ if ((rc = func(buf, sz, p)) != 0)
+ return (rc);
+ kb += sz;
+
+ /* --- Update the display --- */
+
+ if (flags & f_progress) {
+ time_t t = time(0);
+ unsigned up = 0;
+
+ if (percent > 100)
+ up = 1;
+
+ if (!outsz) {
+ if (difftime(t, last) > 1.0) {
+ up = 1;
+ }
+ if (up)
+ fputs(" ] ", stderr);
+ } else {
+ unsigned pc = kb * 100.0 / outsz;
+ if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
+ if (percent > 100)
+ percent = 0;
+ percent &= ~1;
+ for (; percent < (pc & ~1); percent += 2)
+ putc('.', stderr);
+ percent = pc;
+ for (; pc < 100; pc += 2)
+ putc(' ', stderr);
+ fprintf(stderr, "] %3i%% ", percent);
+ up = 1;
+ }
+ }
+
+ if (up) {
+ size_t q = kb;
+ char *suff = " KMG";
+ while (q > 8192 && suff[1]) {
+ q >>= 10;
+ suff++;
+ }
+ fprintf(stderr, "%4i%c\r[", q, *suff);
+ if (outsz) {
+ unsigned pc;
+ for (pc = 0; pc < (percent & ~1); pc += 2)
+ putc('.', stderr);
+ }
+ last = t;
+ }
+
+ if (percent > 100)
+ percent = 0;
+
+ if (percent < 100) {
+ putc(*bp++, stderr);
+ putc('\b', stderr);
+ if (!*bp)
+ bp = baton;
+ }
+ fflush(stderr);
+ }
+
+ /* --- Terminate the loop --- */
+
+ if (outsz && kb >= outsz)
+ break;
+ }
+
+ if (flags & f_progress)
+ fputc('\n', stderr);
+ return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int ac, char *av[])
+{
+ gen *g = &optsg;
+ grand *r;