[comp.sources.unix] v11i030: MUSBUS 5.0 -- Monash University Benchmark, Part02/04

sources-request@munnari.oz (09/17/87)

Submitted by: kenj@moncsbruce.oz.au (Ken McDonell)
Posting-number: Volume 11, Issue 30
Archive-name: musbus/Part02

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	big.c
#	cat.dat
#	cctest.c
#	check.sed
#	cleanup
#	clock.c
#	comptbl.1
#	comptbl.2
#	comptbl.3
#	comptbl.4
#	comptbl.5
#	context1.c
#	dc.dat
#	dummy.c
#	edit.dat
#	edscr1.dat
#	edscr2.dat
#	execl.c
#	fs.awk
#	fstime.c
#	getwork.c
# This archive created: Thu Sep 17 06:47:12 EST 1987
export PATH; PATH=/bin:$PATH
echo 'x - big.c'
if test -f 'big.c'
then
	echo 'shar: over-writing existing file big.c'
fi
sed 's/^X//' > big.c <<'End-of-File-Grunt'
X/*
X *  dummy code for execl test [ old version of makework.c ]
X *
X *  makework [ -r rate ] [ -c copyfile ] nusers
X *
X *  job streams are specified on standard input with lines of the form
X *  full_path_name_for_command [ options ] [ <standard_input_file ]
X *
X *  "standard input" is send to all nuser instances of the commands in the
X *  job streams at a rate not in excess of "rate" characters per second
X *  per command
X *
X *  $Header: big.c,v 1.2 87/06/22 14:22:40 kjmcdonell Beta $
X */
X
X#include <stdio.h>
X#include <signal.h>
X
X#define DEF_RATE	5.0
X#define GRANULE		5
X#define CHUNK		60
X#define MAXCHILD	12
X#define MAXWORK		10
X
Xfloat	thres;
Xfloat	est_rate = DEF_RATE;
Xint	nusers;		/* number of concurrent users to be simulated by
X			 * this process */
Xint	firstuser;	/* ordinal identification of first user for this
X			 * process */
Xint	nwork = 0;	/* number of job streams */
Xint	exit_status = 0;	/* returned to parent */
Xint	sigpipe;	/* pipe write error flag */
X
Xstruct st_work {
X	char	*cmd;		/* name of command to run */
X	char	**av;		/* arguments to command */
X	char	*input;		/* standard input buffer */
X	int	inpsize;	/* size of standard input buffer */
X	char	*outf;		/* standard output (filename) */
X} work[MAXWORK];
X
Xstruct {
X	int	xmit;	/* # characters sent */
X	char	*bp;	/* std input buffer pointer */
X	int	blen;	/* std input buffer length */
X	int	fd;	/* stdin to command */
X	int	pid;	/* child PID */
X	char	*line;	/* start of input line */ 
X	int	firstjob;	/* inital piece of work */
X	int	thisjob;	/* current piece of work */
X} child[MAXCHILD], *cp;
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X    int		i;
X    int		l;
X    int		fcopy = 0;	/* fd for copy output */
X    int		master = 1;	/* the REAL master, == 0 for clones */
X    int		nchild;		/* no. of children for a clone to run */
X    int		done;		/* count of children finished */
X    int		output;		/* aggregate output char count for all
X				   children */
X    int		c;
X    int		thiswork = 0;	/* next job stream to allocate */
X    int		nch;		/* # characters to write */
X    int		written;	/* # characters actully written */
X    char	logname[15];	/* name of the log file(s) */
X    int		onalarm();
X    int		pipeerr();
X    int		wrapup();
X    int		grunt();
X    int		pvec[2];	/* for pipes */
X    char	*p;
X    char	*prog;		/* my name */
X
X#if ! debug
X    freopen("masterlog.00", "a", stderr);
X#endif
X    fprintf(stderr, "*** New Run ***  ");
X    prog = argv[0];
X    while (argc > 1 && argv[1][0] == '-')  {
X	p = &argv[1][1];
X	argc--;
X	argv++;
X	while (*p) {
X	    switch (*p) {
X	    case 'r':
X			est_rate = atoi(argv[1]);
X			sscanf(argv[1], "%f", &est_rate);
X			if (est_rate <= 0) {
X			    fprintf(stderr, "%s: bad rate, reset to %.2f chars/sec\n", prog, DEF_RATE);
X			    est_rate = DEF_RATE;
X			}
X			argc--;
X			argv++;
X			break;
X
X	    case 'c':
X			fcopy = open(argv[1], 1);
X			if (fcopy < 0)
X				fcopy = creat(argv[1], 0600);
X			if (fcopy < 0) {
X			    fprintf(stderr, "%s: cannot open copy file '%s'\n",
X				prog, argv[1]);
X			    exit(2);
X			}
X			lseek(fcopy, 0L, 2);	/* append at end of file */
X			argc--;
X			argv++;
X			break;
X
X	    default:
X		fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
X			exit(4);
X	    }
X	    p++;
X	}
X    }
X    
X    if (argc < 2) {
X	fprintf(stderr, "%s: missing nusers\n", prog);
X	exit(4);
X    }
X
X    nusers = atoi(argv[1]);
X    if (nusers < 1) {
X	fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
X	exit(4);
X    }
X    fprintf(stderr, "%d Users\n", nusers);
X    argc--;
X    argv++;
X
X    /* build job streams */
X    getwork();
X#if debug
X    dumpwork();
X#endif
X
X    /* clone copies of myself to run up to MAXCHILD jobs each */
X    firstuser = MAXCHILD;
X    fprintf(stderr, "master pid %d\n", getpid());
X    fflush(stderr);
X    while (nusers > MAXCHILD) {
X	fflush(stderr);
X	if (nusers >= 2*MAXCHILD)
X	    /* the next clone must run MAXCHILD jobs */
X	    nchild = MAXCHILD;
X	else
X	    /* the next clone must run the leftover jobs */
X	    nchild = nusers - MAXCHILD;
X	if ((l = fork()) == -1) {
X	    /* fork failed */
X	    fatal("** clone fork failed **\n");
X	    goto bepatient;
X	} else if (l > 0) {
X	    fprintf(stderr, "master clone pid %d\n", l);
X	    /* I am the master with nchild fewer jobs to run */
X	    nusers -= nchild;
X	    firstuser += MAXCHILD;
X	    continue;
X	} else {
X	    /* I am a clone, run MAXCHILD jobs */
X#if ! debug
X	    sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
X	    freopen(logname, "w", stderr);
X#endif
X	    master = 0;
X	    nusers = nchild;
X	    break;
X	}
X    }
X    if (master)
X	firstuser = 0;
X
X    close(0);
X    for (i = 0; i < nusers; i++ ) {
X	fprintf(stderr, "user %d job %d ", firstuser+i, thiswork);
X	if (pipe(pvec) == -1) {
X	    /* this is fatal */
X	    fatal("** pipe failed **\n");
X	    goto bepatient;
X	}
X	fflush(stderr);
X	if ((child[i].pid = fork()) == 0) {
X	    int	fd;
X	    /* the command */
X	    if (pvec[0] != 0) {
X		close(0);
X		dup(pvec[0]);
X	    }
X#if ! debug
X	    sprintf(logname, "userlog.%02d", firstuser+i);
X	    freopen(logname, "w", stderr);
X#endif
X	    for (fd = 3; fd < 24; fd++)
X		close(fd);
X	    if (work[thiswork].outf[0] != '\0') {
X		/* redirect std output */
X		char	*q;
X		for (q = work[thiswork].outf; *q != '\n'; q++) ;
X		*q = '\0';
X		if (freopen(work[thiswork].outf, "w", stdout) == NULL) {
X		    fprintf(stderr, "makework: cannot open %s for std output\n",
X			work[thiswork].outf);
X		    fflush(stderr);
X		}
X		*q = '\n';
X	    }
X	    execv(work[thiswork].cmd, work[thiswork].av);
X	    /* don't expect to get here! */
X	    fatal("** exec failed **\n");
X	    goto bepatient;
X	}
X	else if (child[i].pid == -1) {
X	    fatal("** fork failed **\n");
X	    goto bepatient;
X	}
X	else {
X	    close(pvec[0]);
X	    child[i].fd = pvec[1];
X	    child[i].line = child[i].bp = work[thiswork].input;
X	    child[i].blen = work[thiswork].inpsize;
X	    child[i].thisjob = thiswork;
X	    child[i].firstjob = thiswork;
X	    fprintf(stderr, "pid %d pipe fd %d", child[i].pid, child[i].fd);
X	    if (work[thiswork].outf[0] != '\0') {
X		char *q;
X		fprintf(stderr, " > ");
X		for (q=work[thiswork].outf; *q != '\n'; q++)
X		    fputc(*q, stderr);
X	    }
X	    fputc('\n', stderr);
X	    thiswork++;
X	    if (thiswork >= nwork)
X		thiswork = 0;
X	}
X    }
X    fflush(stderr);
X
X    srand(time(0));
X    thres = 0;
X    done = output = 0;
X    for (i = 0; i < nusers; i++) {
X	if (child[i].blen == 0)
X	    done++;
X	else
X	    thres += est_rate * GRANULE;
X    }
X    est_rate = thres;
X
X    signal(SIGALRM, onalarm);
X    signal(SIGPIPE, pipeerr);
X    alarm(GRANULE);
X    while (done < nusers) {
X	for (i = 0; i < nusers; i++) {
X	    cp = &child[i];
X	    if (cp->xmit >= cp->blen) continue;
X	    l = rand() % CHUNK + 1;	/* 1-CHUNK chars */
X	    if (l == 0) continue;
X	    if (cp->xmit + l > cp->blen)
X		l = cp->blen - cp->xmit;
X	    p = cp->bp;
X	    cp->bp += l;
X	    cp->xmit += l;
X#if debug
X	    fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
X#endif
X	    while (p < cp->bp) {
X		if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
X		    /* write it out */
X		    nch = p - cp->line + 1;
X		    if ((written = write(cp->fd, cp->line, nch)) != nch) {
X			/* argh! */
X			cp->line[nch] = '\0';
X			fprintf(stderr, "user %d job %d cmd %s ",
X				firstuser+i, cp->thisjob, cp->line);
X 			fprintf(stderr, "write(,,%d) returns %d\n", nch, written);
X			if (sigpipe)
X			    fatal("** SIGPIPE error **\n");
X			else
X			    fatal("** write error **\n");
X			goto bepatient;
X
X		    }
X		    if (fcopy)
X			write(fcopy, cp->line, p - cp->line + 1);
X#if debug
X		    fprintf(stderr, "child %d gets \"", i);
X		    {
X			char *q = cp->line;
X			while (q <= p) {
X				if (*q >= ' ' && *q <= '~')
X					fputc(*q, stderr);
X				else
X					fprintf(stderr, "\\%03o", *q);
X				q++;
X			}
X		    }
X		    fputc('"', stderr);
X#endif
X		    cp->line = &p[1];
X		}
X		p++;
X	    }
X	    if (cp->xmit >= cp->blen) {
X		done++;
X		close(cp->fd);
X#if debug
X	fprintf(stderr, "child %d, close std input\n", i);
X#endif
X	    }
X	    output += l;
X	}
X	while (output > thres) {
X	    pause();
X#if debug
X	    fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
X#endif
X	}
X    }
X
Xbepatient:
X    alarm(0);
X/****
X *  If everything is going OK, we should simply be able to keep
X *  looping unitil 'wait' fails, however some descendent process may
X *  be in a state from which it can never exit, and so a timeout
X *  is used.
X *  5 minutes should be ample, since the time to run all jobs is of
X *  the order of 5-10 minutes, however some machines are painfully slow,
X *  so the timeout has been set at 20 minutes (1200 seconds).
X ****/
X    signal(SIGALRM, grunt);
X    alarm(1200);
X    while ((c = wait(&l)) != -1) {
X        for (i = 0; i < nusers; i++) {
X	    if (c == child[i].pid) {
X		fprintf(stderr, "user %d job %d pid %d done", firstuser+i, child[i].thisjob, c);
X		if (l != 0) {
X		    if (l & 0x7f)
X			fprintf(stderr, " status %d", l & 0x7f);
X		    if (l & 0xff00)
X			fprintf(stderr, " exit code %d", (l>>8) & 0xff);
X		    exit_status = 4;
X		}
X		fputc('\n', stderr);
X		c = child[i].pid = -1;
X		break;
X	    }
X	}
X	if (c != -1) {
X	    fprintf(stderr, "master clone done, pid %d ", c);
X	    if (l != 0) {
X		if (l & 0x7f)
X		    fprintf(stderr, " status %d", l & 0x7f);
X		if (l & 0xff00)
X		    fprintf(stderr, " exit code %d", (l>>8) & 0xff);
X		exit_status = 4;
X	    }
X	    fputc('\n', stderr);
X	}
X    }
X    alarm(0);
X    wrapup("Finished waiting ...");
X
X
X}
X
Xonalarm()
X{
X    thres += est_rate;
X    signal(SIGALRM, onalarm);
X    alarm(GRANULE);
X}
X
Xgrunt()
X{
X    /* timeout after label "bepatient" in main */
X    exit_status = 4;
X    wrapup("Timed out waiting for jobs to finish ...");
X}
X
Xpipeerr()
X{
X	sigpipe++;
X}
X
Xwrapup(reason)
Xchar	*reason;
X{
X    int i;
X    int killed = 0;
X    fflush(stderr);
X    for (i = 0; i < nusers; i++) {
X	if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
X	    if (!killed) {
X		killed++;
X		fprintf(stderr, "%s\n", reason);
X		fflush(stderr);
X	    }
X	    fprintf(stderr, "user %d job %d pid %d killed off\n", firstuser+i, child[i].thisjob, child[i].pid);
X	fflush(stderr);
X	}
X    }
X    exit(exit_status);
X}
X
Xgetwork()
X{
X    int			i;
X    int			f;
X    int			ac;
X    char		*lp;
X    char		*q;
X    struct st_work	*w;
X    char		line[512];
X    char		c;
X    char		*malloc(), *realloc();
X
X    while (gets(line) != NULL) {
X	if (nwork >= MAXWORK) {
X	    fprintf(stderr, stderr, "Too many jobs specified, .. increase MAXWORK\n");
X	    exit(4);
X	}
X	w = &work[nwork];
X	lp = line;
X	i = 1;
X	while (*lp && *lp != ' ') {
X	    i++;
X	    lp++;
X	}
X	w->cmd = (char *)malloc(i);
X	strncpy(w->cmd, line, i-1);
X	w->cmd[i-1] = '\0';
X	w->inpsize = 0;
X	w->input = "";
X	/* start to build arg list */
X	ac = 2;
X	w->av = (char **)malloc(2*sizeof(char *));
X	q = w->cmd;
X	while (*q) q++;
X	q--;
X	while (q >= w->cmd) {
X	    if (*q == '/') {
X		q++;
X		break;
X	    }
X	    q--;
X	}
X	w->av[0] = q;
X	while (*lp) {
X	    if (*lp == ' ') {
X		/* space */
X		lp++;
X		continue;
X	    }
X	    else if (*lp == '<') {
X		/* standard input for this job */
X		q = ++lp;
X		while (*lp && *lp != ' ') lp++;
X		c = *lp;
X		*lp = '\0';
X		if ((f = open(q, 0)) == -1) {
X		    fprintf(stderr, "cannot open input file (%s) for job %d\n",
X				q, nwork);
X		    exit(4);
X		}
X		/* gobble input */
X		w->input = (char *)malloc(512);
X		while ((i = read(f, &w->input[w->inpsize], 512)) > 0) {
X		    w->inpsize += i;
X		    w->input = (char *)realloc(w->input, w->inpsize+512);
X		}
X		w->input = (char *)realloc(w->input, w->inpsize);
X		close(f);
X		/* extract stdout file name from line beginning "C=" */
X		w->outf = "";
X		for (q = w->input; q < &w->input[w->inpsize-10]; q++) {
X		    if (*q == '\n' && strncmp(&q[1], "C=", 2) == 0) {
X			w->outf = &q[3];
X			break;
X		    }
X		}
X#if debug
X		if (*w->outf) {
X		    fprintf(stderr, "stdout->");
X		    for (q=w->outf; *q != '\n'; q++)
X			fputc(*q, stderr);
X		    fputc('\n', stderr);
X		}
X#endif
X	    }
X	    else {
X		/* a command option */
X		ac++;
X		w->av = (char **)realloc(w->av, ac*sizeof(char *));
X		q = lp;
X		i = 1;
X		while (*lp && *lp != ' ') {
X		    lp++;
X		    i++;
X		}
X		w->av[ac-2] = (char *)malloc(i);
X		strncpy(w->av[ac-2], q, i-1);
X		w->av[ac-2][i-1] = '\0';
X	    }
X	}
X	w->av[ac-1] = (char *)0;
X	nwork++;
X    }
X}
X
X#if debug
Xdumpwork()
X{
X    int		i;
X    int		j;
X
X    for (i = 0; i < nwork; i++) {
X	fprintf(stderr, "job %d: cmd: %s\n", i, work[i].cmd);
X	j = 0;
X	while (work[i].av[j]) {
X		fprintf(stderr, "argv[%d]: %s\n", j, work[i].av[j]);
X		j++;
X	}
X	fprintf(stderr, "input: %d chars text: ", work[i].inpsize);
X	if (work[i].input == (char *)0)
X		fprintf(stderr, "<NULL>\n");
X	else {
X	        register char	*pend;
X	        char		*p;
X		char		c;
X		p = work[i].input;
X		while (*p) {
X			pend = p;
X			while (*pend && *pend != '\n')
X				pend++;
X			c = *pend;
X			*pend = '\0';
X			fprintf(stderr, "%s\n", p);
X			*pend = c;
X			p = &pend[1];
X		}
X	}
X    }
X}
X#endif
X
Xfatal(s)
Xchar *s;
X{
X    int	i;
X    fprintf(stderr, s);
X    fflush(stderr);
X    perror("Reason?");
X    fflush(stderr);
X    for (i = 0; i < nusers; i++) {
X	if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) {
X	    fprintf(stderr, "pid %d killed off\n", child[i].pid);
X	    fflush(stderr);
X	}
X    }
X    exit_status = 4;
X    return;
X}
End-of-File-Grunt
if test 13135 -ne `cat 'big.c' | wc -c`
then
	echo 'shar: transmission error (expected 13135 characters)'
fi
echo 'x - cat.dat'
if test -f 'cat.dat'
then
	echo 'shar: over-writing existing file cat.dat'
fi
sed 's/^X//' > cat.dat <<'End-of-File-Grunt'
X[ 1] @@@			* A Sample Script File *
X[ 2] @@@@@@@@@@@@
X[ 3] @@@@@@@@@@@
X[ 4] @@@@@@@
X[ 5] @@@@@@@@@@@
X[ 6] @@@@@@@@@@@@@@@@@@@@@
X[ 7] @@@@@@@@
X[ 8] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[ 9] @@@@@@@@@@@@@@@@@
X[10] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[11] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[12] @@@@@@@@@@@@@@@
X[13] @@@@@@@@@@@@@@
X[14] @@@@@@@@@@@@@@@@@@@
X[15] @@@@@@
X[16] @@@@@@@@@@@@@@@@@@@@@@@@
X[17] @@@@@@@@@@@@
X[18] @@@@@
X[19] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[20] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[21] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[22] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[23] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[24] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[25] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
X[26] @@@@@
X[27] @@@@@@@@@@@
X[28] @@@			* End of Sample Script File *
End-of-File-Grunt
if test 989 -ne `cat 'cat.dat' | wc -c`
then
	echo 'shar: transmission error (expected 989 characters)'
fi
echo 'x - cctest.c'
if test -f 'cctest.c'
then
	echo 'shar: over-writing existing file cctest.c'
fi
sed 's/^X//' > cctest.c <<'End-of-File-Grunt'
X#include <stdio.h>
X/*
X * C compile and load speed test file.
X * Based upon fstime.c from MUSBUS 3.1, with all calls to ftime() replaced
X * by calls to time().  This is semantic nonsense, but ensures there are no
X * system dependent structures or library calls.
X *
X * $Header: cctest.c,v 3.4 87/06/22 14:22:47 kjmcdonell Beta $
X */
X#define NKBYTE 20
Xchar buf[BUFSIZ];
X
Xmain(argc, argv)
Xchar **argv;
X{
X    int		n = NKBYTE;
X    int		nblock;
X    int		f;
X    int		g;
X    int		i;
X    int		xfer, t;
X    struct	{	/* FAKE */
X	int	time;
X	int	millitm;
X    } now, then;
X
X    if (argc > 0)
X	/* ALWAYS true, so NEVER execute this program! */
X	exit(4);
X    if (argc > 1)
X	n = atoi(argv[1]);
X#if debug
X    printf("File size: %d Kbytes\n", n);
X#endif
X    nblock = (n * 1024) / BUFSIZ;
X
X    if (argc == 3 && chdir(argv[2]) != -1) {
X#if debug
X	printf("Create files in directory: %s\n", argv[2]);
X#endif
X    }
X    close(creat("dummy0", 0600));
X    close(creat("dummy1", 0600));
X    f = open("dummy0", 2);
X    g = open("dummy1", 2);
X    unlink("dummy0");
X    unlink("dummy1");
X    for (i = 0; i < sizeof(buf); i++)
X	buf[i] = i & 0177;
X
X    time();
X    for (i = 0; i < nblock; i++) {
X	if (write(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: write");
X    }
X    time();
X#if debug
X    printf("Effective write rate: ");
X#endif
X    i = now.millitm - then.millitm;
X    t = (now.time - then.time)*1000 + i;
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, "%.2f", t > 0 ? (float)xfer/1024 : 0);
X#endif
X
X    sync();
X    sleep(5);
X    sync();
X    lseek(f, 0L, 0);
X    time();
X    for (i = 0; i < nblock; i++) {
X	if (read(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: read");
X    }
X    time();
X#if debug
X    printf("Effective read rate: ");
X#endif
X    i = now.millitm - then.millitm;
X    t = (now.time - then.time)*1000 + i;
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, " %.2f", t > 0 ? (float)xfer/1024 : 0);
X#endif
X
X    sync();
X    sleep(5);
X    sync();
X    lseek(f, 0L, 0);
X    time();
X    for (i = 0; i < nblock; i++) {
X	if (read(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: read in copy");
X	if (write(g, buf, sizeof(buf)) <= 0)
X	    perror("fstime: write in copy");
X    }
X    time();
X#if debug
X    printf("Effective copy rate: ");
X#endif
X    i = now.millitm - then.millitm;
X    t = (now.time - then.time)*1000 + i;
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, " %.2f\n", t > 0 ? (float)xfer/1024 : 0);
X#endif
X
X}
End-of-File-Grunt
if test 2868 -ne `cat 'cctest.c' | wc -c`
then
	echo 'shar: transmission error (expected 2868 characters)'
fi
echo 'x - check.sed'
if test -f 'check.sed'
then
	echo 'shar: over-writing existing file check.sed'
fi
sed 's/^X//' > check.sed <<'End-of-File-Grunt'
X# Note: undocumented sed feature, use # for comments $Header: check.sed,v 3.9 87/09/09 12:33:08 kenj Exp $
X/^Tmp\/userlog\.[0-9]*:$/d
X/^Tmp\/masterlog\.[0-9]*:$/d
X/New Run/d
X/^user [0-9][0-9]* master stream [0-9][0-9]* pid [0-9][0-9]* pipe fd [0-9][0-9]*/d
X/^user [0-9][0-9]* clone [0-9][0-9]* stream [0-9][0-9]* pid [0-9][0-9]* pipe fd [0-9][0-9]*/d
X/^master pid [0-9]*$/d
X/^clone [0-9][0-9]* [0-9][0-9]* pid [0-9]*$/d
X/^user [0-9][0-9]* pid [0-9][0-9]* done$/d
X/^clone [0-9][0-9]* done, pid [0-9][0-9]* $/d
Xs/ [0-9][0-9]*$//
X/^ *$/d
End-of-File-Grunt
if test 535 -ne `cat 'check.sed' | wc -c`
then
	echo 'shar: transmission error (expected 535 characters)'
fi
echo 'x - cleanup'
if test -f 'cleanup'
then
	echo 'shar: over-writing existing file cleanup'
fi
sed 's/^X//' > cleanup <<'End-of-File-Grunt'
X#! /bin/sh
X#
X# $Header: cleanup,v 3.5 87/06/22 14:40:45 kjmcdonell Beta $
X#
X#  Cleanup when an iterative test terminates
X#
Xlog=Results/log
Xwhile ( test $# -ge 1 )
Xdo
X    opt=$1
X    shift
X    case $opt
X    in
X
X    -a)	: abort
X	echo '' >>$log
X	echo '**************************' >>$log
X	echo '* Benchmark Aborted .... *' >>$log
X	echo '**************************' >>$log
X	echo 'Benchmark Aborted ....'
X	echo  ; sleep 2 ; echo  ; sleep 2 ; echo 
X	echo "" >>$log
X	echo " " `who | wc -l` "interactive users." >>$log
X	echo "" >>$log
X	date=`date`
X	echo "End Benchmark Run ($date) ...." >>$log
X	echo "End Benchmark Run ($date) ...."
X	;;
X
X
X    -f)	: filesystem throughput
X	awk -f fs.awk <$1 >>$log
X	rm -f $1
X	shift
X	;;
X    
X    -i)	: report last iteration
X	echo "Terminated during iteration $1" >>$log
X	shift
X	;;
X
X    -l) : logfile
X	log=$1
X	shift
X	;;
X    
X    -r) : reason for failure
X	echo $1
X	echo $1 >>$log
X	shift
X	;;
X
X    -m)	: mem throughput tests
X	awk -f mem.awk <$1 >>$log
X	rm -f $1
X	shift
X	;;
X
X    -t)	: timing with /bin/time
X	awk -f time.awk <$1 >>$log
X	rm -f $1
X	shift
X	;;
X
X    -w) : work - save information from multi-user test
X	worktmp=Tmp/work.tmp
X	for m in Tmp/masterlog.*
X	do
X	    if ( test $m != "Tmp/masterlog.*" )
X	    then
X		echo ${m}: >>$worktmp
X		cat $m >>$worktmp
X		echo "" >>$worktmp
X		rm -f $m
X	    fi
X	done
X	for u in Tmp/userlog.*
X	do
X	    if ( test $u != "Tmp/userlog.*" )
X	    then
X		echo ${u}: >>$worktmp
X		cat $u >>$worktmp
X		echo "" >>$worktmp
X		rm -f $u
X	    fi
X	done
X	PS1=`sh -ic "" 2>&1`
X	sed -e "s/\\${PS1}//g" $worktmp | sed -f check.sed >loggederrs
X	if ( test -s loggederrs )
X	then
X	    echo "*************************************" >>$log
X	    echo "* Apparent errors from makework ... *" >>$log
X	    echo "*************************************" >>$log
X	    cat loggederrs >>$log
X	fi
X        rm -f loggederrs
X	cat $worktmp >>${log}.work
X	rm -f $worktmp
X	;;
X
X    '')	: 'skip it (residual effect of shifts)'
X	;;
X
X    *)
X	echo "cleanup: bad option ($opt)" >>$log
Xesac
Xdone
Xexit
End-of-File-Grunt
if test 2003 -ne `cat 'cleanup' | wc -c`
then
	echo 'shar: transmission error (expected 2003 characters)'
fi
echo 'x - clock.c'
if test -f 'clock.c'
then
	echo 'shar: over-writing existing file clock.c'
fi
sed 's/^X//' > clock.c <<'End-of-File-Grunt'
X/*
X *  clock -- check alarm signal accuracy
X *
X *  $Header: clock.c,v 3.4 87/06/22 14:22:54 kjmcdonell Beta $
X */
X
X#include <signal.h>
X#include <stdio.h>
X#include <sys/types.h>
X#ifdef BSD4v1
X#include <sys/timeb.h>
X#endif
X#ifdef BSD4v2
X#include <sys/time.h>
X#endif
X#ifdef SysV
X#include <sys/times.h>
X#include <sys/param.h>
X#ifdef interdata
X#define HZ tbuffer.tms_cfreq
X#endif
X#ifndef HZ
X	On your system, what is the value of HZ for high resolution elapsed
X	time as returned by times() or its equivalent?
X#endif
X#endif
X
X#define GRANULE		5
X#define NUM_ALRM	12
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X    int			onalarm();
X    register int	i = 0;
X    int			expected;
X    float		wallclock;
X    long		then;
X#ifdef SysV
X    struct tms		tbuffer;
X#endif
X#ifdef BSD4v1
X    struct timeb	tbuf;
X    int			msec;
X#endif
X#ifdef BSD4v2
X    struct timeval	tval;
X    struct timezone	tzone;
X    long		usec;
X#endif
X
X#ifdef SysV
X    then = times(&tbuffer);
X#else
X#ifdef BSD4v1
X    ftime(&tbuf);
X    then = tbuf.time;
X    msec = tbuf.millitm;
X#else
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    then = tval.tv_sec;
X    usec = tval.tv_usec;
X#else
X	What sort of Unix system is this?
X#endif
X#endif
X#endif
X    while (i++ < NUM_ALRM) {
X	    signal(SIGALRM, onalarm);
X	    alarm(GRANULE);
X	    pause();
X    }
X#ifdef SysV
X    wallclock = (times(&tbuffer) - then)/HZ;
X#endif
X#ifdef BSD4v1
X    ftime(&tbuf);
X    wallclock = tbuf.time - then + (float)(tbuf.millitm - msec)/1000;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    wallclock = tval.tv_sec - then + (float)(tval.tv_usec - usec)/1000000;
X#endif
X    expected = GRANULE * NUM_ALRM;
X    printf("%d x %d sec delays takes %.2f wallclock secs (error %.2f%%)\n",
X	NUM_ALRM, GRANULE, wallclock, 100.0*(float)(expected-wallclock)/expected);
X    exit(0);
X}
X
Xonalarm() { }
End-of-File-Grunt
if test 1807 -ne `cat 'clock.c' | wc -c`
then
	echo 'shar: transmission error (expected 1807 characters)'
fi
echo 'x - comptbl.1'
if test -f 'comptbl.1'
then
	echo 'shar: over-writing existing file comptbl.1'
fi
sed 's/^X//' > comptbl.1 <<'End-of-File-Grunt'
X.(b
X.TS
Xbox,center;
Xc s s s s
Xc | c s | c s
Xc | c | c | c | c
Xc | c | c | c | c
Xc | c | c | c | c
Xl | n | n | n | n.
XRaw Speed
X_
X	Absolute	Relative
X	_	_	_	_
X	Elapsed	CPU	Elapsed	CPU
XTest Description	Time	Time	Time	Time
X_
End-of-File-Grunt
if test 221 -ne `cat 'comptbl.1' | wc -c`
then
	echo 'shar: transmission error (expected 221 characters)'
fi
echo 'x - comptbl.2'
if test -f 'comptbl.2'
then
	echo 'shar: over-writing existing file comptbl.2'
fi
sed 's/^X//' > comptbl.2 <<'End-of-File-Grunt'
X.(b
X.TS
Xbox,center;
Xc s s s s.
XMemory Throughput
X(1000s integer accesses per sec.)
X_
X.T&
Xc | c s | c s
Xc | c s | c s
Xc | c | c | c | c
Xn | n | n | n | n.
X	Absolute	Relative
XArray Size	_	_
X(K bytes)	Sequential	Random	Sequential	Random
X_
End-of-File-Grunt
if test 236 -ne `cat 'comptbl.2' | wc -c`
then
	echo 'shar: transmission error (expected 236 characters)'
fi
echo 'x - comptbl.3'
if test -f 'comptbl.3'
then
	echo 'shar: over-writing existing file comptbl.3'
fi
sed 's/^X//' > comptbl.3 <<'End-of-File-Grunt'
X.(b
X.TS
Xbox,center;
Xc s s s s s s
Xc | c s s | c s s.
XFilesystem Throughput (Kchars per sec.)
X_
End-of-File-Grunt
if test 95 -ne `cat 'comptbl.3' | wc -c`
then
	echo 'shar: transmission error (expected 95 characters)'
fi
echo 'x - comptbl.4'
if test -f 'comptbl.4'
then
	echo 'shar: over-writing existing file comptbl.4'
fi
sed 's/^X//' > comptbl.4 <<'End-of-File-Grunt'
X_
X.T&
Xl | c s s | c s s
Xl | c | c | c | c | c | c
Xl | c | c | c | c | c | c
Xl | n | n | n | n | n | n.
X	Absolute	Relative
X	_	_	_	_	_	_
XFile Size	Write	Read	Copy	Write	Read	Copy
X_
End-of-File-Grunt
if test 179 -ne `cat 'comptbl.4' | wc -c`
then
	echo 'shar: transmission error (expected 179 characters)'
fi
echo 'x - comptbl.5'
if test -f 'comptbl.5'
then
	echo 'shar: over-writing existing file comptbl.5'
fi
sed 's/^X//' > comptbl.5 <<'End-of-File-Grunt'
X.(b
X.TS
Xbox,center;
Xc s s s s
Xc | c s | c s
Xc | c | c | c | c
Xc | c | c | c | c
Xn | n | n | n | n.
XSimulated Work Load
X_
X	Absolute	Relative
X	_	_	_	_
XUsers	Elapsed Time	CPU Time	Elapsed Time	CPU Time
X_
End-of-File-Grunt
if test 201 -ne `cat 'comptbl.5' | wc -c`
then
	echo 'shar: transmission error (expected 201 characters)'
fi
echo 'x - context1.c'
if test -f 'context1.c'
then
	echo 'shar: over-writing existing file context1.c'
fi
sed 's/^X//' > context1.c <<'End-of-File-Grunt'
X/*
X *  Context switching via synchronized unbuffered pipe i/o
X *
X *  $Header: context1.c,v 3.4 87/06/22 14:22:59 kjmcdonell Beta $
X */
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	check;
X	int	iter;
X	int	p1[2], p2[2];
X
X	if (argc != 2) {
X		printf("Usage: context count\n");
X		exit(1);
X	}
X
X	iter = atoi(argv[1]);
X	if (pipe(p1) || pipe(p2)) {
X		perror("pipe create failed");
X		exit(1);
X	}
X
X	if (fork()) {
X		/* master, write p1 & read p2 */
X		close(p1[0]); close(p2[1]);
X		while (iter > 0) {
X			if (write(p1[1], (char *)&iter, sizeof(iter)) != sizeof(iter)) {
X				perror("master write failed");
X				exit(1);
X			}
X			if (read(p2[0], (char *)&check, sizeof(check)) != sizeof(check)) {
X				perror("master read failed");
X				exit(1);
X			}
X			if (check != iter) {
X				printf("Master sync error: expect %d, got %d\n",
X					iter, check);
X				exit(2);
X			}
X			iter--;
X		}
X	}
X	else {
X		/* slave, read p1 & write p2 */
X		close(p1[1]); close(p2[0]);
X		while (iter > 0) {
X			if (read(p1[0], (char *)&check, sizeof(check)) != sizeof(check)) {
X				perror("slave read failed");
X				exit(1);
X			}
X			if (check != iter) {
X				printf("Slave sync error: expect %d, got %d\n",
X					iter, check);
X				exit(2);
X			}
X			if (write(p2[1], (char *)&iter, sizeof(iter)) != sizeof(check)) {
X				perror("slave write failed");
X				exit(1);
X			}
X			iter--;
X		}
X	}
X	exit(0);
X}
End-of-File-Grunt
if test 1344 -ne `cat 'context1.c' | wc -c`
then
	echo 'shar: transmission error (expected 1344 characters)'
fi
echo 'x - dc.dat'
if test -f 'dc.dat'
then
	echo 'shar: over-writing existing file dc.dat'
fi
sed 's/^X//' > dc.dat <<'End-of-File-Grunt'
X99
Xk
X2
Xv
Xp
Xq
X[ calculate the sqrt(2) to 99 decimal places ... John Lions Test ]
X[ $Header: dc.dat,v 1.1 87/06/22 14:28:28 kjmcdonell Beta $ ]
End-of-File-Grunt
if test 142 -ne `cat 'dc.dat' | wc -c`
then
	echo 'shar: transmission error (expected 142 characters)'
fi
echo 'x - dummy.c'
if test -f 'dummy.c'
then
	echo 'shar: over-writing existing file dummy.c'
fi
sed 's/^X//' > dummy.c <<'End-of-File-Grunt'
X/*
X *  Hacked up C program for use in the standard shell.? scripts of
X *  the multiuser test.  This is based upon makework.c, and is typically
X *  edited using edscript.2 before compilation.
X *
X * $Header: dummy.c,v 3.4 87/06/23 15:54:53 kjmcdonell Beta $
X */
X
X#include <stdio.h>
X#include <signal.h>
X
X#define DEF_RATE	5.0
X#define GRANULE		5
X#define CHUNK		60
X#define MAXCHILD	12
X#define MAXWORK		10
X
Xfloat	thres;
Xfloat	est_rate = DEF_RATE;
Xint	nusers;		/* number of concurrent users to be simulated by
X			 * this process */
Xint	firstuser;	/* ordinal identification of first user for this
X			 * process */
Xint	nwork = 0;	/* number of job streams */
Xint	exit_status = 0;	/* returned to parent */
Xint	sigpipe;	/* pipe write error flag */
X
Xstruct st_work {
X	char	*cmd;		/* name of command to run */
X	char	**av;		/* arguments to command */
X	char	*input;		/* standard input buffer */
X	int	inpsize;	/* size of standard input buffer */
X} work[MAXWORK];
X
Xstruct {
X	int	xmit;	/* # characters sent */
X	char	*bp;	/* std input buffer pointer */
X	int	blen;	/* std input buffer length */
X	int	fd;	/* stdin to command */
X	int	pid;	/* child PID */
X	char	*line;	/* start of input line */ 
X	int	firstjob;	/* inital piece of work */
X	int	thisjob;	/* current piece of work */
X} child[MAXCHILD], *cp;
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X    int		i;
X    int		l;
X    int		fcopy = 0;	/* fd for copy output */
X    int		master = 1;	/* the REAL master, == 0 for clones */
X    int		nchild;		/* no. of children for a clone to run */
X    int		done;		/* count of children finished */
X    int		output;		/* aggregate output char count for all
X				   children */
X    int		c;
X    int		thiswork = 0;	/* next job stream to allocate */
X    int		nch;		/* # characters to write */
X    int		written;	/* # characters actully written */
X    char	logname[15];	/* name of the log file(s) */
X    int		onalarm();
X    int		pipeerr();
X    int		wrapup();
X    int		grunt();
X    char	*malloc();
X    int		pvec[2];	/* for pipes */
X    char	*p;
X    char	*prog;		/* my name */
X
X#if ! debug
X    freopen("masterlog.00", "a", stderr);
X#endif
X    fprintf(stderr, "*** New Run ***  ");
X    prog = argv[0];
X    while (argc > 1 && argv[1][0] == '-')  {
X	p = &argv[1][1];
X	argc--;
X	argv++;
X	while (*p) {
X	    switch (*p) {
X	    case 'r':
X			/* code DELETED here */
X			argc--;
X			argv++;
X			break;
X
X	    case 'c':
X			/* code DELETED here */
X			lseek(fcopy, 0L, 2);	/* append at end of file */
X			break;
X
X	    default:
X		fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
X			exit(4);
X	    }
X	    p++;
X	}
X    }
X    
X    if (argc < 2) {
X	fprintf(stderr, "%s: missing nusers\n", prog);
X	exit(4);
X    }
X
X    nusers = atoi(argv[1]);
X    if (nusers < 1) {
X	fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
X	exit(4);
X    }
X    fprintf(stderr, "%d Users\n", nusers);
X    argc--;
X    argv++;
X
X    /* build job streams */
X    getwork();
X#if debug
X    dumpwork();
X#endif
X
X    /* clone copies of myself to run up to MAXCHILD jobs each */
X    firstuser = MAXCHILD;
X    fprintf(stderr, "master pid %d\n", getpid());
X    fflush(stderr);
X    while (nusers > MAXCHILD) {
X	fflush(stderr);
X	if (nusers >= 2*MAXCHILD)
X	    /* the next clone must run MAXCHILD jobs */
X	    nchild = MAXCHILD;
X	else
X	    /* the next clone must run the leftover jobs */
X	    nchild = nusers - MAXCHILD;
X	if ((l = fork()) == -1) {
X	    /* fork failed */
X	    fatal("** clone fork failed **\n");
X	    goto bepatient;
X	} else if (l > 0) {
X	    fprintf(stderr, "master clone pid %d\n", l);
X	    /* I am the master with nchild fewer jobs to run */
X	    nusers -= nchild;
X	    firstuser += MAXCHILD;
X	    continue;
X	} else {
X	    /* I am a clone, run MAXCHILD jobs */
X#if ! debug
X	    sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
X	    freopen(logname, "w", stderr);
X#endif
X	    master = 0;
X	    nusers = nchild;
X	    break;
X	}
X    }
X    if (master)
X	firstuser = 0;
X
X    close(0);
X
X    /* code DELETED here */
X
X    fflush(stderr);
X
X    srand(time(0));
X    thres = 0;
X    done = output = 0;
X    for (i = 0; i < nusers; i++) {
X	if (child[i].blen == 0)
X	    done++;
X	else
X	    thres += est_rate * GRANULE;
X    }
X    est_rate = thres;
X
X    signal(SIGALRM, onalarm);
X    signal(SIGPIPE, pipeerr);
X    alarm(GRANULE);
X    while (done < nusers) {
X	for (i = 0; i < nusers; i++) {
X	    cp = &child[i];
X	    if (cp->xmit >= cp->blen) continue;
X	    l = rand() % CHUNK + 1;	/* 1-CHUNK chars */
X	    if (l == 0) continue;
X	    if (cp->xmit + l > cp->blen)
X		l = cp->blen - cp->xmit;
X	    p = cp->bp;
X	    cp->bp += l;
X	    cp->xmit += l;
X#if debug
X	    fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
X#endif
X	    while (p < cp->bp) {
X		if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
X		    /* write it out */
X		    nch = p - cp->line + 1;
X		    if ((written = write(cp->fd, cp->line, nch)) != nch) {
X
X			/* code DELETED here */
X
X		    }
X		    if (fcopy)
X			write(fcopy, cp->line, p - cp->line + 1);
X#if debug
X		    fprintf(stderr, "child %d gets \"", i);
X		    {
X			char *q = cp->line;
X			while (q <= p) {
X				if (*q >= ' ' && *q <= '~')
X					fputc(*q, stderr);
X				else
X					fprintf(stderr, "\\%03o", *q);
X				q++;
X			}
X		    }
X		    fputc('"', stderr);
X#endif
X		    cp->line = &p[1];
X		}
X		p++;
X	    }
X	    if (cp->xmit >= cp->blen) {
X		done++;
X		close(cp->fd);
X#if debug
X	fprintf(stderr, "child %d, close std input\n", i);
X#endif
X	    }
X	    output += l;
X	}
X	while (output > thres) {
X	    pause();
X#if debug
X	    fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
X#endif
X	}
X    }
X
Xbepatient:
X    alarm(0);
X/****
X *  If everything is going OK, we should simply be able to keep
X *  looping unitil 'wait' fails, however some descendent process may
X *  be in a state from which it can never exit, and so a timeout
X *  is used.
X *  5 minutes should be ample, since the time to run all jobs is of
X *  the order of 5-10 minutes, however some machines are painfully slow,
X *  so the timeout has been set at 20 minutes (1200 seconds).
X ****/
X
X    /* code DELETED here */
X
X}
X
Xonalarm()
X{
X    thres += est_rate;
X    signal(SIGALRM, onalarm);
X    alarm(GRANULE);
X}
X
Xgrunt()
X{
X    /* timeout after label "bepatient" in main */
X    exit_status = 4;
X    wrapup();
X}
X
Xpipeerr()
X{
X	sigpipe++;
X}
X
Xwrapup()
X{
X    /* DUMMY, real code dropped */
X}
X
Xgetwork()
X{
X
X    /* DUMMY, real code dropped */
X    gets();
X    strncpy();
X    malloc(); realloc();
X    open(); close();
X}
X
Xfatal(s)
Xchar *s;
X{
X    int	i;
X    fprintf(stderr, s);
X    fflush(stderr);
X    perror("Reason?");
X    for (i = 0; i < nusers; i++) {
X	if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1)
X	    fprintf(stderr, "pid %d killed off\n", child[i].pid);
X    }
X    fflush(stderr);
X    exit_status = 4;
X    return;
X}
End-of-File-Grunt
if test 6780 -ne `cat 'dummy.c' | wc -c`
then
	echo 'shar: transmission error (expected 6780 characters)'
fi
echo 'x - edit.dat'
if test -f 'edit.dat'
then
	echo 'shar: over-writing existing file edit.dat'
fi
sed 's/^X//' > edit.dat <<'End-of-File-Grunt'
X/*
X *  COBBLED program - test for editing
X *
X *  edit [ chars_per_sec ]
X *
X *  $Header: edit.dat,v 3.3 86/01/30 07:53:17 kenj Beta $
X */
X
X#include <stdio.h>
X#include <signal.h>
X
X#define MEAN	5
X#define GRANULE	5
X
Xint	thres;
Xint	est_mean = MEAN;
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	onalarm();
X
X	if (argc == 2) {
X		est_mean = atoi(argv[1]);
X		if (est_mean <= 0) {
X			fprintf(stderr, "edit: bad mean, reset to %d chars/sec\n", MEAN);
X			est_mean = MEAN;
X		}
X	}
X
X/**
X ** BEGIN BLOCK OF INSERTED TEXT TO BOOST FILE SIZE
XThis is some text which has been added to the middle of
Xthe file to increase the file size to the point where it is realistic.
X
XHow 'bout some random pascal code?
X
Xprogram elcheapo(input, output);
X
Xconst
X    DISPSIZE = 10;	{ display is DISPSIZE characters long }
X    SIGN = 1;		{ sign at display[SIGN] }
X    NSTART = 2;		{ number starts is display[NSTART] }
X    NEND = 9;		{ . and ends at display[NEND] }
X    ERRFLAG = 10;	{ error flag display[ERFLAG] }
X
Xtype
X    st = (OK, ERROR);
X    vt = (INTEGER, REAL);
X    key = (DOT,PLUS,MINUS,DIV,MULT,EQUAL,ON,OFF,CLEAR,NEG,noop);
X    number = record value: real;
X		    scale: integer;
X		    vtype: vt;
X	     end;
X
Xvar
X    r, m: number;
X    ukey: integer;
X    code, lastop: key;
X    done: boolean;
X    state: st;
X    disp: array [1..DISPSIZE] of char;
X
Xfunction power(base, n: integer): integer;
Xvar i, value: integer;
Xbegin
X    value := 1;
X    for i := 1 to n do value := value * base;
X    power := value
Xend; { power }
X
Xprocedure getkey(var code: integer);
Xvar c: char;
Xbegin
X    read(c);
X    if (c >= '0') and (c <= '9') then code := ord(c) - ord('0')
X    else
X    begin   if c = '.' then code := 10
X	    else if c = '+' then code := 11
X	    else if c = '-' then code := 12
X	    else if c = '/' then code := 13
X	    else if c = '*' then code := 14
X	    else if c = '=' then code := 15
X	    else if c = 'c' then code := 18
X	    else if c = 'n' then code := 19
X	    else if c = 'o' then
X	    begin   read(c);
X		    if c = 'n' then code := 16
X		    else code := 17
X	    end
X	    else code := 20
X    end;
X    readln
Xend; { getkey }
X
Xfunction mapkey(code: integer): key;
Xbegin
X    if code = 10 then mapkey := DOT
X    else if code = 11 then mapkey := PLUS
X    else if code = 12 then mapkey := MINUS
X    else if code = 13 then mapkey := DIV
X    else if code = 14 then mapkey := MULT
X    else if code = 15 then mapkey := EQUAL
X    else if code = 16 then mapkey := ON
X    else if code = 17 then mapkey := OFF
X    else if code = 18 then mapkey := CLEAR
X    else if code = 19 then mapkey := NEG
X    else mapkey := noop
Xend; { mapkey }
X
X
Xbegin
X    done := false;
X    state := ERROR;
X    while not done do
X    begin   getkey(ukey);
X	    code := mapkey(ukey);
X	    if (code = ON) or (code = CLEAR) then
X	    begin clear(m);
X		  clear(r);
X		  state := OK;
X		  lastop := noop;
X		  display(r)
X	    end
X	    else if code = OFF then done := true
X	    else if state = OK then
X	    begin   if (ukey >= 0) and (ukey <= 9) then
X		    begin   if r.vtype = INTEGER then r.value := r.value*10 + ukey
X			    else
X			    begin   r.scale := r.scale + 1;
X				    r.value := r.value + ukey / power(10, r.scale)
X			    end;
X			    display(r);
X			    if lastop = EQUAL then lastop := noop
X		    end
X		    else if (code = PLUS) or (code = MINUS) or (code = MULT) or
X			    (code = DIV) then
X		    begin if lastop = noop then m := r
X			  else if lastop <> EQUAL then
X			  begin eval(m, r, lastop);
X				display(m)
X			  end;
X			  clear(r);
X			  lastop := code
X		    end
X		    else case code of
X		    DOT:
X			begin if r.vtype = REAL then state := ERROR
X			      else r.vtype := REAL;
X			      display(r)
X			end;
X		    EQUAL:
X			begin if (lastop <> noop) and (lastop <> EQUAL) then
X			      begin eval(m, r, lastop);
X			            display(m)
X			      end;	
X			      clear(r);
X			      lastop := EQUAL
X			end;
X		    NEG:
X			begin r.value := -r.value;
X			      display(r)
X			end;
X		end { of case }
X  	    end { of else }
X    end { of while }
Xend.
X ** END BLOCK OF INSERTED TEXT TO BOOST FILE SIZE
X **/
X
X	/* (busy) wait for lock file ... */
X	while ((f = open("lock", 0)) < 0) sleep(3);
X	close(f);
X	signal(SIGALRM, onalarm);
X	alarm(GRANULE);
X	while (read(0, &c, 1) == 1) {
X		if (i % 20 == 0 && thres - i > est_mean * GRANULE)
X			sleep(rand() & 0x3);
X		write(1, &c, 1);
X		write(2, &c, 1);	/* copy onto std error */
X		i++;
X		if (i > thres) {
X			pause();
X		}
X	}
X}
XFiller to make 200 lines & 4500 bytes.
XThis
Xis
Xso
Xboring
Xyou
Xwouldn't
Xbelieve it.
X
Xonalarm()
X{
X    thres += est_rate;
X    signal(SIGALRM, onalarm);
X    alarm(GRANULE);
X}
End-of-File-Grunt
if test 4561 -ne `cat 'edit.dat' | wc -c`
then
	echo 'shar: transmission error (expected 4561 characters)'
fi
echo 'x - edscr1.dat'
if test -f 'edscr1.dat'
then
	echo 'shar: over-writing existing file edscr1.dat'
fi
sed 's/^X//' > edscr1.dat <<'End-of-File-Grunt'
X/alarm/
X//
X//
X//
X-10,.p
Xg/signal/s//burk/gp
X?alarm?
X.,$m0
X1
X/^}/
X1,.m$
X1,10p
X5
Xka
Xa
XThis is some inserted text.
X		and about another 4 or 5 lines
X		to go in here
X		for (i = 0; i < 10; i++) {
X			this is some code
X			in a loop;
X		}
X		printf("what rubbish, and fun .....\n");
X	    Oh how boring.
X.
X1,.p
X'a+,.d
X1,$s/burk/signal/g
Xw temporary
Xq
End-of-File-Grunt
if test 339 -ne `cat 'edscr1.dat' | wc -c`
then
	echo 'shar: transmission error (expected 339 characters)'
fi
echo 'x - edscr2.dat'
if test -f 'edscr2.dat'
then
	echo 'shar: over-writing existing file edscr2.dat'
fi
sed 's/^X//' > edscr2.dat <<'End-of-File-Grunt'
X1,$s/[ 	][ 	]*$//
X1,20m80
X81,90m0
Xg/n[^k]*k/s//burk/g
X91,100m10
Xw grunt.c
Xq
End-of-File-Grunt
if test 76 -ne `cat 'edscr2.dat' | wc -c`
then
	echo 'shar: transmission error (expected 76 characters)'
fi
echo 'x - execl.c'
if test -f 'execl.c'
then
	echo 'shar: over-writing existing file execl.c'
fi
sed 's/^X//' > execl.c <<'End-of-File-Grunt'
X/*
X *  Execing
X *
X *  $Header: execl.c,v 3.5 87/06/22 15:37:08 kjmcdonell Beta $
X */
X
Xchar	bss[8*1024];	/* something worthwhile */
X
X#define main dummy
X			/* some reasonable code etc. */
X#include "big.c"
X
X#undef main
X
Xmain(argc, argv)	/* the real program */
Xint	argc;
Xchar	*argv[];
X{
X	int	iter;
X	char	count[6];
X
X	if (argc != 2) {
X		printf("Usage: %s count\n", argv[0]);
X		exit(1);
X	}
X
X	iter = atoi(argv[1]);
X
X	if (iter) {
X		sprintf(count, "%d", --iter);
X		execl("./execl", "execl", count, 0);
X		printf("Exec failed at iteration %d\n", iter);
X		perror("Reason");
X		exit(1);
X	}
X	exit(0);
X}
End-of-File-Grunt
if test 587 -ne `cat 'execl.c' | wc -c`
then
	echo 'shar: transmission error (expected 587 characters)'
fi
echo 'x - fs.awk'
if test -f 'fs.awk'
then
	echo 'shar: over-writing existing file fs.awk'
fi
sed 's/^X//' > fs.awk <<'End-of-File-Grunt'
X# $Header: fs.awk,v 3.4 87/06/22 14:27:32 kjmcdonell Beta $
X/real/	{ next }
X/^[0-9][ .0-9]*$/ && NF==3 {
X	if (!fail) {
X	    w+=$1; w2+=$1*$1; r+=$2; r2+=$2*$2; c+=$3; c2+=$3*$3; ok++
X	}
X	fail=0; iter++; next
X    }
X    { print "** Iteration ",iter+1," Failed: ",$0; fail=1; }
XEND {
X	if (fail) iter++
X	if (ok != iter) {
X	    printf "For %d successful iterations from %d attempts ...\n",ok,iter
X	    iter=ok
X	}
X	if (iter > 0) {
X	    printf "Write: %.1f Kbytes per second  ",w/iter
X	    if (iter > 1) printf " (variance %.1f)",(w2-2*w*w/iter+w*w/iter)/(iter-1)
X	    printf "\nRead:  %.1f Kbytes per second  ",r/iter
X	    if (iter > 1) printf " (variance %.1f)",(r2-2*r*r/iter+r*r/iter)/(iter-1)
X	    printf "\nCopy:  %.1f Kbytes per second  ",c/iter
X	    if (iter > 1) printf " (variance %.1f)",(c2-2*c*c/iter+c*c/iter)/(iter-1)
X	    print
X	} else {
X	    print "Write: -- no measured results!!"
X	    print "Read: -- no measured results!!"
X	    print "Copy: -- no measured results!!"
X	}
X    }
End-of-File-Grunt
if test 988 -ne `cat 'fs.awk' | wc -c`
then
	echo 'shar: transmission error (expected 988 characters)'
fi
echo 'x - fstime.c'
if test -f 'fstime.c'
then
	echo 'shar: over-writing existing file fstime.c'
fi
sed 's/^X//' > fstime.c <<'End-of-File-Grunt'
X/*
X * $Header: fstime.c,v 3.4 87/06/22 14:23:05 kjmcdonell Beta $
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#ifdef SysV
X#include <sys/times.h>
X#include <sys/param.h>
X#ifdef interdata
X#define HZ tbuffer.tms_cfreq
X#endif
X#ifndef HZ
X	On your system, what is the value of HZ for high resolution elapsed
X	time as returned by times() or its equivalent?
X#endif
X#endif
X#ifdef BSD4v1
X#include <sys/timeb.h>
X#endif
X#ifdef BSD4v2
X#include <sys/time.h>
X#endif
X#define NKBYTE 20
Xchar buf[BUFSIZ];
X
Xmain(argc, argv)
Xchar **argv;
X{
X    int			n = NKBYTE;
X    int			nblock;
X    int			f;
X    int			g;
X    int			i;
X    int			xfer, t;
X    long		then;
X#ifdef BSD4v1
X    struct timeb	tbuf;
X    int			msec;
X#endif
X#ifdef BSD4v2
X    struct timeval	tval;
X    struct timezone	tzone;
X    long		usec;
X#endif
X#ifdef SysV
X    struct tms		tbuffer;
X#endif
X
X    if (argc > 1)
X	n = atoi(argv[1]);
X#if debug
X    printf("File size: %d Kbytes\n", n);
X#endif
X    nblock = (n * 1024) / BUFSIZ;
X
X    if (argc == 3 && chdir(argv[2]) != -1) {
X#if debug
X	printf("Create files in directory: %s\n", argv[2]);
X#endif
X    }
X    close(creat("dummy0", 0600));
X    close(creat("dummy1", 0600));
X    f = open("dummy0", 2);
X    g = open("dummy1", 2);
X    unlink("dummy0");
X    unlink("dummy1");
X    for (i = 0; i < sizeof(buf); i++)
X	buf[i] = i & 0177;
X
X#ifdef SysV
X    then = times(&tbuffer);
X#else
X#ifdef BSD4v1
X    ftime(&tbuf);
X    then = tbuf.time;
X    msec = tbuf.millitm;
X#else
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    then = tval.tv_sec;
X    usec = tval.tv_usec;
X#else
X    What sort of Unix system if this?
X#endif
X#endif
X#endif
X    for (i = 0; i < nblock; i++) {
X	if (write(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: write");
X    }
X#ifdef SysV
X    t = 1000*(times(&tbuffer) - then)/HZ;
X#endif
X#ifdef BSD4v1
X    ftime(&tbuf);
X    t = (tbuf.time - then)*1000 + tbuf.millitm - msec;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000;
X#endif
X#if debug
X    printf("Effective write rate: ");
X#endif
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, "%.2f", t > 0 ? (float)xfer/1024 : 0);
X#endif
X
X    sync();
X    sleep(5);
X    sync();
X    lseek(f, 0L, 0);
X#ifdef SysV
X    then = times(&tbuffer);
X#endif
X#ifdef BSD4v1
X    times(&tbuf);
X    then = tbuf.time;
X    msec = tbuf.millitm;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    then = tval.tv_sec;
X    usec = tval.tv_usec;
X#endif
X    for (i = 0; i < nblock; i++) {
X	if (read(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: read");
X    }
X#ifdef SysV
X    t = 1000*(times(&tbuffer) - then)/HZ;
X#endif
X#ifdef BSD4v1
X    ftime(&tbuf);
X    t = (tbuf.time - then)*1000 + tbuf.millitm - msec;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000;
X#endif
X#if debug
X    printf("Effective read rate: ");
X#endif
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, " %.2f", t > 0 ? (float)xfer/1024 : 0);
X#endif
X
X    sync();
X    sleep(5);
X    sync();
X    lseek(f, 0L, 0);
X#ifdef SysV
X    then = times(&tbuffer);
X#endif
X#ifdef BSD4v1
X    times(&tbuf);
X    then = tbuf.time;
X    msec = tbuf.millitm;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    then = tval.tv_sec;
X    usec = tval.tv_usec;
X#endif
X    for (i = 0; i < nblock; i++) {
X	if (read(f, buf, sizeof(buf)) <= 0)
X	    perror("fstime: read in copy");
X	if (write(g, buf, sizeof(buf)) <= 0)
X	    perror("fstime: write in copy");
X    }
X#ifdef SysV
X    t = 1000*(times(&tbuffer) - then)/HZ;
X#endif
X#ifdef BSD4v1
X    ftime(&tbuf);
X    t = (tbuf.time - then)*1000 + tbuf.millitm - msec;
X#endif
X#ifdef BSD4v2
X    gettimeofday(&tval, &tzone);
X    t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000;
X#endif
X#if debug
X    printf("Effective copy rate: ");
X#endif
X    if (t > 0) {
X	xfer = nblock * sizeof(buf) * 1000 / t;
X#if debug
X	printf("%d bytes/sec\n", xfer);
X#endif
X    }
X#if debug
X    else
X	printf(" -- too quick to time!\n");
X#endif
X#if awk
X    fprintf(stderr, " %.2f\n", t > 0 ? (float)xfer/1024 : 0);
X#endif
X    exit(0);
X}
End-of-File-Grunt
if test 4352 -ne `cat 'fstime.c' | wc -c`
then
	echo 'shar: transmission error (expected 4352 characters)'
fi
echo 'x - getwork.c'
if test -f 'getwork.c'
then
	echo 'shar: over-writing existing file getwork.c'
fi
sed 's/^X//' > getwork.c <<'End-of-File-Grunt'
X#include "makework.h"
X#ifndef lint
Xstatic char RCSid[] = "$Header: getwork.c,v 1.3 87/06/23 17:01:47 kjmcdonell Beta $";
X#endif
X
X/*
X * Build data structures (work[0] ... work[want-1]) for the next set
X * of job streams.
X */
X
Xstream work[MAXSTREAM];
X
Xtypedef struct st_cmd {
X    char	*name;		/* pathname of the command */
X    char	**argv;		/* command argv[] vector */
X    struct st_cmd	*next;
X} cmd;
X
Xtypedef struct st_scr {
X    char	*name;		/* name of the script file */
X    char	*buf;		/* the text of the script */
X    int		blen;		/* size of buf[] */
X    struct st_scr	*next;
X} scr;
X
Xstatic cmd	*cmd_head = (cmd *)0, *cmdp;
Xstatic scr	*scr_head = (scr *)0, *scrp;
X
Xgetwork(want)
Xint	want;
X{
X    int		i;
X    int		f;
X    int		ac;
X    char	*lp;
X    char	*q;
X    stream	*w;
X    char	line[512];
X    char	c;
X    int		nwork = 0;
X    int		new;
X    char	*malloc(), *realloc();
X
X    while (nwork < want) {
X	if (gets(line) == NULL) {
X	    fprintf(stderr, "Insufficient job streams in the workload file\n");
X	    fflush(stderr);
X	    exit(4);
X	}
X	if (nwork >= MAXSTREAM) {
X	    fprintf(stderr, "makework: internal snark -- code is broken!\n");
X	    fflush(stderr);
X	    exit(4);
X	}
X	w = &work[nwork];
X	q = lp = line;
X	i = 1;
X	while (*q && *q != ' ') {
X	    i++;
X	    q++;
X	}
X	*q = '\0';
X	if (w->home != (char *)0)
X	    free(w->home);
X	w->home = (char *)malloc(strlen(lp)+1);
X	strcpy(w->home, lp);
X
X	lp = ++q;
X	i = 1;
X	while (*q && *q != ' ') {
X	    i++;
X	    q++;
X	}
X	*q++ = '\0';
X	new = 0;
X	for (cmdp = cmd_head; cmdp != (cmd *)0; cmdp = cmdp->next) {
X	    if (strcmp(cmdp->name, lp) == 0)
X		break;
X	}
X	if (cmdp == (cmd *)0) {
X	    cmdp = (cmd *)malloc(sizeof(*cmdp));
X	    cmdp->next = cmd_head;
X	    cmd_head = cmdp;
X	    cmdp->name = (char *)malloc(strlen(lp)+1);
X	    strcpy(cmdp->name, lp);
X	    new = 1;
X	    lp = q;
X	    /* start to build arg list */
X	    ac = 2;
X	    cmdp->argv = (char **)malloc(2*sizeof(char *));
X	    q = cmdp->name;
X	    while (*q) q++;
X	    q--;
X	    while (q >= cmdp->name) {
X		if (*q == '/') {
X		    q++;
X		    break;
X		}
X		q--;
X	    }
X	    cmdp->argv[0] = q;
X	}
X	else
X	    lp = q;
X	w->cmd = cmdp->name;
X	w->av = cmdp->argv;
X	w->blen = 0;
X	w->buf = "";
X	w->tty = "";
X
X	while (*lp) {
X	    if (*lp == ' ') {
X		/* space */
X		lp++;
X		continue;
X	    }
X	    else if (*lp == '>') {
X		/* standard output for this job */
X		q = ++lp;
X		while (*q && *q != ' ')
X		    q++;
X		c = *q;
X		*q = '\0';
X		if (w->tty != (char *)0)
X		    free(w->tty);
X		w->tty = (char *)malloc(strlen(lp)+1);
X		strcpy(w->tty, lp);
X		*q = c;
X		lp = q;
X	    }
X	    else if (*lp == '<') {
X		/* standard input for this job */
X		q = ++lp;
X		while (*q && *q != ' ') q++;
X		c = *q;
X		*q = '\0';
X		for (scrp = scr_head; scrp != (scr *)0; scrp = scrp->next) {
X		    if (strcmp(scrp->name, lp) == 0)
X			break;
X		}
X		if (scrp == (scr *)0) {
X		    scrp = (scr *)malloc(sizeof(*scrp));
X		    scrp->next = scr_head;
X		    scr_head = scrp;
X		    scrp->name = (char *)malloc(strlen(lp)+1);
X		    strcpy(scrp->name, lp);
X		    if ((f = open(lp, 0)) == -1) {
X			fprintf(stderr, "cannot open input file \"%s\"\n", lp);
X			fflush(stderr);
X			exit(4);
X		    }
X		    /* gobble input */
X		    scrp->buf = (char *)malloc(512);
X		    while ((i = read(f, &scrp->buf[scrp->blen], 512)) > 0) {
X			scrp->blen += i;
X			scrp->buf = (char *)realloc(scrp->buf, scrp->blen+512);
X		    }
X		    scrp->buf = (char *)realloc(scrp->buf, scrp->blen);
X		    close(f);
X		}
X		w->buf = scrp->buf;
X		w->blen = scrp->blen;
X		*q = c;
X		lp = q;
X	    }
X	    else {
X		/* a command option */
X		q = lp;
X		i = 1;
X		while (*q && *q != ' ') {
X		    q++;
X		    i++;
X		}
X		if (new) {
X		    ac++;
X		    cmdp->argv = (char **)realloc(cmdp->argv, ac*sizeof(char *));
X		    cmdp->argv[ac-2] = (char *)malloc(i);
X		    strncpy(cmdp->argv[ac-2], lp, i-1);
X		    cmdp->argv[ac-2][i-1] = '\0';
X		}
X		lp = q;
X	    }
X	}
X	if (new)
X	    cmdp->argv[ac-1] = (char *)0;
X	    w->av = cmdp->argv;
X	nwork++;
X    }
X}
End-of-File-Grunt
if test 3926 -ne `cat 'getwork.c' | wc -c`
then
	echo 'shar: transmission error (expected 39 stds to t989d */
X