
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

int luck = 5000;		// bad luck actually, higher makes more errors
int Verbose = 0;

long errcnt = 0;
long bytcnt = 0;
long lastbytcnt = 0;
char buf[10];

/* called by signal interrupt or terminate to clean things up */
void
bpipe(n)
{
	fprintf (stderr, "Chsim: Broken Pipe at %ld bytes  errcnt = %ld error rate = %G\n",
	    bytcnt, errcnt, (double)errcnt/bytcnt);
	exit(128+n);
}
void
bibi(n)
{
	fprintf (stderr, "Chsim: Broken Pipe at %ld bytes  errcnt = %ld error rate = %G\n",
	    bytcnt, errcnt, (double)errcnt/bytcnt);
	exit(128+n);
}
void
usage()
{
	fprintf(stderr, "Usage: chsim -v -l NN\n");
	exit(-1);
}

void
areport(s)
char *s;
{
	if (Verbose == 0)
		return;
	fprintf(stderr, "%ld: %s  %ld since last hit\n", bytcnt, s, bytcnt-lastbytcnt);
	lastbytcnt = bytcnt;
}

main(argc, argv)
char *argv[];
{
	register c;
	char *cp;

	while (--argc) {
		cp = *++argv;
		if (*cp++ == '-' && *cp) {
			while ( *cp) {
				switch(*cp++) {
				case 'l':
					if (--argc < 1)
						exit(-1);
					luck = atoi(*++argv);
					break;
				case 'v':
					++Verbose; break;
				default:
					usage();
				}
			}
		}
	}
	signal(SIGPIPE, bpipe);
	signal(SIGINT, bibi);
	while (read(0, buf, 1)) {
		++bytcnt;
		c = buf[0];
		if (random() < luck) {		// lose one
			areport("delete byte");
			++errcnt;
			continue;
		}
		if (random() < luck) {		// add one
			areport("add byte");
			++errcnt; putchar ((int) random());
		}
		if (random() < luck) { 	// invert one
			areport("invert byte");
			++errcnt; c = ~c;
		}
		if (random () < luck)  {	// increment one
			areport("increment byte");
			++errcnt; ++c;
		}
		putchar(c); fflush(stdout);
	}
	fprintf (stderr, "Chsim: EOF at %ld bytes  errcnt = %ld error rate = %G\n",
	    bytcnt, errcnt, (double)errcnt/bytcnt);
	exit(0);
}
