/*
 *  stuff -- ハードディスク消去のための詰め物データを作成
 *
 *  revision history:
 *	0.0:	Apr. 30, 2004 by Dai ISHIJIMA
 *	0.1:	May   1, 2004
 */

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

#define BSIZ 1024
#define STDIN 0
#define STDOUT 1
#define STDERR 2

#define ZERO 'z'
#define FILL 'f'
#define RAND 'r'

#define shift --argc; ++argv


#define swap(t,a,b) {t _swap_tmp; _swap_tmp=(a); a=b; b=_swap_tmp;}


/* 一文字出力 */
void putch(int fd, unsigned char ch)
{
    write(fd, &ch, 1);
}


/* 文字列出力 */
void myputs(int fd, char *s)
{
    while (*s) {
	putch(fd, *s);
	++s;
    }
}


/* 乱数でデータをかきまぜる */
void stair(int len, unsigned char *buf)
{
    int i, n;

    for (i = 0; i < len; i++) {
	n = random() & (len - 1);		/* len は 2^n と仮定 */
	swap(unsigned char, buf[i], buf[n]);
    }
}


/* 書き込み用データの初期化 */
void init(int len, unsigned char *buf, int mode)
{
    int i;

    if (mode == ZERO) {
	for (i = 0; i < len; i++) {
	    buf[i] = 0;
	}
    }
    else if (mode == FILL) {
	for (i = 0; i < len; i++) {
	    buf[i] = 0xff;
	}
    }
    else if (mode == RAND) {
	srandom(time(NULL));
	for (i = 0; i < len; i++) {
	    buf[i] = i;
	}
	stair(len, buf);
    }
}


/* コマンドライン指定に基づいて、0, 1, ランダムデータを出力 */    
int main(int argc, char *argv[])
{
    int mode;
    unsigned char buf[BSIZ];

    mode = ZERO;
    shift;
    while ((argc > 0) && (argv[0][0] == '-')) {
	if (argv[0][1] == 'z') {
	    mode = ZERO;
	}
	else if (argv[0][1] == 'f') {
	    mode = FILL;
	}
	else if (argv[0][1] == 'r') {
	    mode = RAND;
	}
	else if (argv[0][1] == '0') {
	    mode = ZERO;
	}
	else if (argv[0][1] == '1') {
	    mode = FILL;
	}
	else if (argv[0][1] == 'R') {
	    mode = RAND;
	}
	else {
	    myputs(STDERR, "Usage: stuff [-z|-f|-r]\n");
	    exit(1);
	}
	shift;
    }
    if (argc > 0) {
	myputs(STDERR, "Usage: stuff [-z|-f|-r]\n");
	exit(1);
    }
    init(BSIZ, buf, mode);
    for (;;) {
	if (mode == RAND) {
	    stair(BSIZ, buf);
	}
	write(STDOUT, buf, BSIZ);
    }
    exit(0);
}

/* Local Variables: */
/* compile-command:"cc -Wall -O -s -static -o stuff stuff.c" */
/* End: */
