xref: /plan9/sys/src/cmd/scuzz/scuzz.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier #include "scsireq.h"
63e12c5d1SDavid du Colombier 
73e12c5d1SDavid du Colombier #define MIN(a, b)	((a) < (b) ? (a): (b))
83e12c5d1SDavid du Colombier 
9*219b2ee8SDavid du Colombier int bus;
103e12c5d1SDavid du Colombier Biobuf bin, bout;
113e12c5d1SDavid du Colombier static char rwbuf[MaxIOsize];
123e12c5d1SDavid du Colombier static int verbose = 1;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier typedef struct {
153e12c5d1SDavid du Colombier 	char *name;
163e12c5d1SDavid du Colombier 	long (*f)(ScsiReq *, int, char *[]);
173e12c5d1SDavid du Colombier 	int open;
183e12c5d1SDavid du Colombier 	char *help;
193e12c5d1SDavid du Colombier } ScsiCmd;
203e12c5d1SDavid du Colombier static ScsiCmd scsicmd[];
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier static long
233e12c5d1SDavid du Colombier cmdready(ScsiReq *rp, int argc, char *argv[])
243e12c5d1SDavid du Colombier {
253e12c5d1SDavid du Colombier 	USED(argc, argv);
263e12c5d1SDavid du Colombier 	return SRready(rp);
273e12c5d1SDavid du Colombier }
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier static long
303e12c5d1SDavid du Colombier cmdrewind(ScsiReq *rp, int argc, char *argv[])
313e12c5d1SDavid du Colombier {
323e12c5d1SDavid du Colombier 	USED(argc, argv);
333e12c5d1SDavid du Colombier 	return SRrewind(rp);
343e12c5d1SDavid du Colombier }
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier static long
373e12c5d1SDavid du Colombier cmdreqsense(ScsiReq *rp, int argc, char *argv[])
383e12c5d1SDavid du Colombier {
393e12c5d1SDavid du Colombier 	long nbytes;
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier 	USED(argc, argv);
423e12c5d1SDavid du Colombier 	if((nbytes = SRreqsense(rp)) != -1)
433e12c5d1SDavid du Colombier 		makesense(rp);
443e12c5d1SDavid du Colombier 	return nbytes;
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier static long
483e12c5d1SDavid du Colombier cmdformat(ScsiReq *rp, int argc, char *argv[])
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	USED(argc, argv);
513e12c5d1SDavid du Colombier 	return SRformat(rp);
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier static long
553e12c5d1SDavid du Colombier cmdrblimits(ScsiReq *rp, int argc, char *argv[])
563e12c5d1SDavid du Colombier {
573e12c5d1SDavid du Colombier 	uchar l[6];
583e12c5d1SDavid du Colombier 	long n;
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier 	USED(argc, argv);
613e12c5d1SDavid du Colombier 	if((n = SRrblimits(rp, l)) == -1)
623e12c5d1SDavid du Colombier 		return -1;
633e12c5d1SDavid du Colombier 	Bprint(&bout, " %2.2ux %2.2ux %2.2ux %2.2ux %2.2ux %2.2ux\n",
643e12c5d1SDavid du Colombier 		l[0], l[1], l[2], l[3], l[4], l[5]);
653e12c5d1SDavid du Colombier 	return n;
663e12c5d1SDavid du Colombier }
673e12c5d1SDavid du Colombier 
683e12c5d1SDavid du Colombier static int
693e12c5d1SDavid du Colombier mkfile(char *file, int omode, int *pid)
703e12c5d1SDavid du Colombier {
713e12c5d1SDavid du Colombier 	int fd[2];
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier 	if(*file != '|'){
743e12c5d1SDavid du Colombier 		*pid = -1;
753e12c5d1SDavid du Colombier 		if(omode == OWRITE)
763e12c5d1SDavid du Colombier 			return create(file, OWRITE, 0666);
773e12c5d1SDavid du Colombier 		else if(omode == OREAD)
783e12c5d1SDavid du Colombier 			return open(file, OREAD);
793e12c5d1SDavid du Colombier 		return -1;
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 
823e12c5d1SDavid du Colombier 	file++;
833e12c5d1SDavid du Colombier 	if(*file == 0 || pipe(fd) == -1)
843e12c5d1SDavid du Colombier 		return -1;
853e12c5d1SDavid du Colombier 	if((*pid = fork()) == -1){
863e12c5d1SDavid du Colombier 		close(fd[0]);
873e12c5d1SDavid du Colombier 		return -1;
883e12c5d1SDavid du Colombier 	}
893e12c5d1SDavid du Colombier 	if(*pid == 0){
903e12c5d1SDavid du Colombier 		switch(omode){
913e12c5d1SDavid du Colombier 
923e12c5d1SDavid du Colombier 		case OREAD:
933e12c5d1SDavid du Colombier 			dup(fd[0], 1);
943e12c5d1SDavid du Colombier 			break;
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier 		case OWRITE:
973e12c5d1SDavid du Colombier 			dup(fd[0], 0);
983e12c5d1SDavid du Colombier 			break;
993e12c5d1SDavid du Colombier 		}
1003e12c5d1SDavid du Colombier 		close(fd[0]);
1013e12c5d1SDavid du Colombier 		close(fd[1]);
1023e12c5d1SDavid du Colombier 		execl("/bin/rc", "rc", "-c", file, 0);
1033e12c5d1SDavid du Colombier 		exits("exec");
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier 	close(fd[0]);
1063e12c5d1SDavid du Colombier 	return fd[1];
1073e12c5d1SDavid du Colombier }
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier int
1103e12c5d1SDavid du Colombier waitfor(int pid)
1113e12c5d1SDavid du Colombier {
1123e12c5d1SDavid du Colombier 	int rpid;
1133e12c5d1SDavid du Colombier 	Waitmsg w;
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	while((rpid = wait(&w)) != pid && rpid != -1)
1163e12c5d1SDavid du Colombier 		;
1173e12c5d1SDavid du Colombier 	return w.msg[0];
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier static long
1213e12c5d1SDavid du Colombier cmdread(ScsiReq *rp, int argc, char *argv[])
1223e12c5d1SDavid du Colombier {
1233e12c5d1SDavid du Colombier 	long n, nbytes, total, iosize;
1243e12c5d1SDavid du Colombier 	int fd, pid;
1253e12c5d1SDavid du Colombier 	char *p;
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	iosize = MaxIOsize;
1283e12c5d1SDavid du Colombier 	nbytes = 0x7FFFFFFF & ~iosize;
1293e12c5d1SDavid du Colombier 	switch(argc){
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier 	default:
1323e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
1333e12c5d1SDavid du Colombier 		return -1;
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier 	case 2:
1363e12c5d1SDavid du Colombier 		if((nbytes = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){
1373e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
1383e12c5d1SDavid du Colombier 			return -1;
1393e12c5d1SDavid du Colombier 		}
1403e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier 	case 1:
1433e12c5d1SDavid du Colombier 		if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){
1443e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
1453e12c5d1SDavid du Colombier 			return -1;
1463e12c5d1SDavid du Colombier 		}
1473e12c5d1SDavid du Colombier 		break;
1483e12c5d1SDavid du Colombier 	}
149*219b2ee8SDavid du Colombier 	print("bsize=%d\n", rp->lbsize);
1503e12c5d1SDavid du Colombier 	total = 0;
1513e12c5d1SDavid du Colombier 	while(nbytes){
1523e12c5d1SDavid du Colombier 		n = MIN(nbytes, iosize);
1533e12c5d1SDavid du Colombier 		if((n = SRread(rp, rwbuf, n)) == -1){
1543e12c5d1SDavid du Colombier 			if(total == 0)
1553e12c5d1SDavid du Colombier 				total = -1;
1563e12c5d1SDavid du Colombier 			break;
1573e12c5d1SDavid du Colombier 		}
1583e12c5d1SDavid du Colombier 		if(write(fd, rwbuf, n) != n){
1593e12c5d1SDavid du Colombier 			if(total == 0)
1603e12c5d1SDavid du Colombier 				total = -1;
1613e12c5d1SDavid du Colombier 			if(rp->status == Status_OK)
1623e12c5d1SDavid du Colombier 				rp->status = Status_SW;
1633e12c5d1SDavid du Colombier 			break;
1643e12c5d1SDavid du Colombier 		}
1653e12c5d1SDavid du Colombier 		nbytes -= n;
1663e12c5d1SDavid du Colombier 		total += n;
1673e12c5d1SDavid du Colombier 	}
1683e12c5d1SDavid du Colombier 	close(fd);
1693e12c5d1SDavid du Colombier 	if(pid >= 0 && waitfor(pid)){
1703e12c5d1SDavid du Colombier 		rp->status = Status_SW;
1713e12c5d1SDavid du Colombier 		return -1;
1723e12c5d1SDavid du Colombier 	}
1733e12c5d1SDavid du Colombier 	return total;
1743e12c5d1SDavid du Colombier }
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier static long
1773e12c5d1SDavid du Colombier cmdwrite(ScsiReq *rp, int argc, char *argv[])
1783e12c5d1SDavid du Colombier {
1793e12c5d1SDavid du Colombier 	long n, nbytes, total;
1803e12c5d1SDavid du Colombier 	int fd, pid;
1813e12c5d1SDavid du Colombier 	char *p;
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier 	nbytes = 0x7FFFFFFF & ~MaxIOsize;
1843e12c5d1SDavid du Colombier 	switch(argc){
1853e12c5d1SDavid du Colombier 
1863e12c5d1SDavid du Colombier 	default:
1873e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
1883e12c5d1SDavid du Colombier 		return -1;
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier 	case 2:
1913e12c5d1SDavid du Colombier 		if((nbytes = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){
1923e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
1933e12c5d1SDavid du Colombier 			return -1;
1943e12c5d1SDavid du Colombier 		}
1953e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	case 1:
1983e12c5d1SDavid du Colombier 		if((fd = mkfile(argv[0], OREAD, &pid)) == -1){
1993e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
2003e12c5d1SDavid du Colombier 			return -1;
2013e12c5d1SDavid du Colombier 		}
2023e12c5d1SDavid du Colombier 		break;
2033e12c5d1SDavid du Colombier 	}
2043e12c5d1SDavid du Colombier 	total = 0;
2053e12c5d1SDavid du Colombier 	while(nbytes){
2063e12c5d1SDavid du Colombier 		n = MIN(nbytes, MaxIOsize);
2073e12c5d1SDavid du Colombier 		if((n = read(fd, rwbuf, n)) == -1){
2083e12c5d1SDavid du Colombier 			if(total == 0)
2093e12c5d1SDavid du Colombier 				total = -1;
2103e12c5d1SDavid du Colombier 			break;
2113e12c5d1SDavid du Colombier 		}
2123e12c5d1SDavid du Colombier 		if(SRwrite(rp, rwbuf, n) != n){
2133e12c5d1SDavid du Colombier 			if(total == 0)
2143e12c5d1SDavid du Colombier 				total = -1;
2153e12c5d1SDavid du Colombier 			if(rp->status == Status_OK)
2163e12c5d1SDavid du Colombier 				rp->status = Status_SW;
2173e12c5d1SDavid du Colombier 			break;
2183e12c5d1SDavid du Colombier 		}
2193e12c5d1SDavid du Colombier 		nbytes -= n;
2203e12c5d1SDavid du Colombier 		total += n;
2213e12c5d1SDavid du Colombier 	}
2223e12c5d1SDavid du Colombier 	close(fd);
2233e12c5d1SDavid du Colombier 	if(pid >= 0 && waitfor(pid)){
2243e12c5d1SDavid du Colombier 		rp->status = Status_SW;
2253e12c5d1SDavid du Colombier 		return -1;
2263e12c5d1SDavid du Colombier 	}
2273e12c5d1SDavid du Colombier 	return total;
2283e12c5d1SDavid du Colombier }
2293e12c5d1SDavid du Colombier 
2303e12c5d1SDavid du Colombier static long
2313e12c5d1SDavid du Colombier cmdseek(ScsiReq *rp, int argc, char *argv[])
2323e12c5d1SDavid du Colombier {
2333e12c5d1SDavid du Colombier 	char *p;
2343e12c5d1SDavid du Colombier 	long offset;
2353e12c5d1SDavid du Colombier 	int type;
2363e12c5d1SDavid du Colombier 
2373e12c5d1SDavid du Colombier 	type = 0;
2383e12c5d1SDavid du Colombier 	switch(argc){
2393e12c5d1SDavid du Colombier 
2403e12c5d1SDavid du Colombier 	default:
2413e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
2423e12c5d1SDavid du Colombier 		return -1;
2433e12c5d1SDavid du Colombier 
2443e12c5d1SDavid du Colombier 	case 2:
2453e12c5d1SDavid du Colombier 		if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){
2463e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
2473e12c5d1SDavid du Colombier 			return -1;
2483e12c5d1SDavid du Colombier 		}
2493e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
2503e12c5d1SDavid du Colombier 
2513e12c5d1SDavid du Colombier 	case 1:
2523e12c5d1SDavid du Colombier 		if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){
2533e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
2543e12c5d1SDavid du Colombier 			return -1;
2553e12c5d1SDavid du Colombier 		}
2563e12c5d1SDavid du Colombier 		break;
2573e12c5d1SDavid du Colombier 	}
2583e12c5d1SDavid du Colombier 	return SRseek(rp, offset, type);
2593e12c5d1SDavid du Colombier }
2603e12c5d1SDavid du Colombier 
2613e12c5d1SDavid du Colombier static long
2623e12c5d1SDavid du Colombier cmdfilemark(ScsiReq *rp, int argc, char *argv[])
2633e12c5d1SDavid du Colombier {
2643e12c5d1SDavid du Colombier 	char *p;
2653e12c5d1SDavid du Colombier 	ulong howmany;
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier 	howmany = 1;
2683e12c5d1SDavid du Colombier 	if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
2693e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
2703e12c5d1SDavid du Colombier 		return -1;
2713e12c5d1SDavid du Colombier 	}
2723e12c5d1SDavid du Colombier 	return SRfilemark(rp, howmany);
2733e12c5d1SDavid du Colombier }
2743e12c5d1SDavid du Colombier 
2753e12c5d1SDavid du Colombier static long
2763e12c5d1SDavid du Colombier cmdspace(ScsiReq *rp, int argc, char *argv[])
2773e12c5d1SDavid du Colombier {
2783e12c5d1SDavid du Colombier 	uchar code;
2793e12c5d1SDavid du Colombier 	long howmany;
2803e12c5d1SDavid du Colombier 	char option, *p;
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier 	code = 0x00;
2833e12c5d1SDavid du Colombier 	howmany = 1;
2843e12c5d1SDavid du Colombier 	while(argc && (*argv)[0] == '-'){
2853e12c5d1SDavid du Colombier 		while(option = *++argv[0]){
2863e12c5d1SDavid du Colombier 			switch(option){
2873e12c5d1SDavid du Colombier 
2883e12c5d1SDavid du Colombier 			case '-':
2893e12c5d1SDavid du Colombier 				break;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier 			case 'b':
2923e12c5d1SDavid du Colombier 				code = 0x00;
2933e12c5d1SDavid du Colombier 				break;
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier 			case 'f':
2963e12c5d1SDavid du Colombier 				code = 0x01;
2973e12c5d1SDavid du Colombier 				break;
2983e12c5d1SDavid du Colombier 
2993e12c5d1SDavid du Colombier 			default:
3003e12c5d1SDavid du Colombier 				rp->status = Status_BADARG;
3013e12c5d1SDavid du Colombier 				return -1;
3023e12c5d1SDavid du Colombier 			}
3033e12c5d1SDavid du Colombier 			break;
3043e12c5d1SDavid du Colombier 		}
3053e12c5d1SDavid du Colombier 		argc--; argv++;
3063e12c5d1SDavid du Colombier 		if(option == '-')
3073e12c5d1SDavid du Colombier 			break;
3083e12c5d1SDavid du Colombier 	}
3093e12c5d1SDavid du Colombier 	if(argc || ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){
3103e12c5d1SDavid du Colombier 		USED(howmany);
3113e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
3123e12c5d1SDavid du Colombier 		return -1;
3133e12c5d1SDavid du Colombier 	}
3143e12c5d1SDavid du Colombier 	return SRspace(rp, code, howmany);
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier 
3173e12c5d1SDavid du Colombier static long
3183e12c5d1SDavid du Colombier cmdinquiry(ScsiReq *rp, int argc, char *argv[])
3193e12c5d1SDavid du Colombier {
3203e12c5d1SDavid du Colombier 	long status;
3213e12c5d1SDavid du Colombier 	int i, n;
3223e12c5d1SDavid du Colombier 	uchar *p;
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier 	USED(argc, argv);
3253e12c5d1SDavid du Colombier 	if((status = SRinquiry(rp)) != -1){
3263e12c5d1SDavid du Colombier 		n = rp->inquiry[4]+4;
3273e12c5d1SDavid du Colombier 		for(i = 0; i < MIN(8, n); i++)
3283e12c5d1SDavid du Colombier 			Bprint(&bout, " %2.2ux", rp->inquiry[i]);
3293e12c5d1SDavid du Colombier 		p = &rp->inquiry[8];
3303e12c5d1SDavid du Colombier 		n = MIN(n, sizeof(rp->inquiry)-8);
3313e12c5d1SDavid du Colombier 		while(n && (*p == ' ' || *p == '\t' || *p == '\n')){
3323e12c5d1SDavid du Colombier 			n--;
3333e12c5d1SDavid du Colombier 			p++;
3343e12c5d1SDavid du Colombier 		}
3353e12c5d1SDavid du Colombier 		Bprint(&bout, "\t%.*s\n", n, p);
3363e12c5d1SDavid du Colombier 	}
3373e12c5d1SDavid du Colombier 	return status;
3383e12c5d1SDavid du Colombier }
3393e12c5d1SDavid du Colombier 
3403e12c5d1SDavid du Colombier static long
3413e12c5d1SDavid du Colombier cmdmodeselect(ScsiReq *rp, int argc, char *argv[])
3423e12c5d1SDavid du Colombier {
3433e12c5d1SDavid du Colombier 	uchar list[MaxDirData];
3443e12c5d1SDavid du Colombier 	long nbytes, ul;
3453e12c5d1SDavid du Colombier 	char *p;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	memset(list, 0, sizeof(list));
3483e12c5d1SDavid du Colombier 	for(nbytes = 0; argc; argc--, argv++, nbytes++){
3493e12c5d1SDavid du Colombier 		if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
3503e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
3513e12c5d1SDavid du Colombier 			return -1;
3523e12c5d1SDavid du Colombier 		}
3533e12c5d1SDavid du Colombier 		list[nbytes] = ul;
3543e12c5d1SDavid du Colombier 	}
3553e12c5d1SDavid du Colombier 	return SRmodeselect(rp, list, nbytes);
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier static long
3593e12c5d1SDavid du Colombier cmdmodesense(ScsiReq *rp, int argc, char *argv[])
3603e12c5d1SDavid du Colombier {
3613e12c5d1SDavid du Colombier 	uchar list[MaxDirData], *lp, page;
3623e12c5d1SDavid du Colombier 	long i, nbytes, status;
3633e12c5d1SDavid du Colombier 	char *p;
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier 	nbytes = sizeof(list);
3663e12c5d1SDavid du Colombier 	switch(argc){
3673e12c5d1SDavid du Colombier 
3683e12c5d1SDavid du Colombier 	default:
3693e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
3703e12c5d1SDavid du Colombier 		return -1;
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier 	case 2:
3733e12c5d1SDavid du Colombier 		if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
3743e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
3753e12c5d1SDavid du Colombier 			return -1;
3763e12c5d1SDavid du Colombier 		}
3773e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier 	case 1:
3803e12c5d1SDavid du Colombier 		if((page = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
3813e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
3823e12c5d1SDavid du Colombier 			return -1;
3833e12c5d1SDavid du Colombier 		}
3843e12c5d1SDavid du Colombier 		break;
3853e12c5d1SDavid du Colombier 
3863e12c5d1SDavid du Colombier 	case 0:
3873e12c5d1SDavid du Colombier 		page = 0x3F;
3883e12c5d1SDavid du Colombier 		break;
3893e12c5d1SDavid du Colombier 	}
3903e12c5d1SDavid du Colombier 	if((status = SRmodesense(rp, page, list, nbytes)) == -1)
3913e12c5d1SDavid du Colombier 		return -1;
3923e12c5d1SDavid du Colombier 	lp = list;
3933e12c5d1SDavid du Colombier 	nbytes = list[0]-1;
3943e12c5d1SDavid du Colombier 	for(i = 0; i < 4; i++){				/* header */
3953e12c5d1SDavid du Colombier 		Bprint(&bout, " %2.2ux", *lp);
3963e12c5d1SDavid du Colombier 		lp++;
3973e12c5d1SDavid du Colombier 	}
3983e12c5d1SDavid du Colombier 	nbytes -= 4;
3993e12c5d1SDavid du Colombier 	Bputc(&bout, '\n');
4003e12c5d1SDavid du Colombier 	for(i = 0; i < 8; i++){				/* block descriptor */
4013e12c5d1SDavid du Colombier 		Bprint(&bout, " %2.2ux", *lp);
4023e12c5d1SDavid du Colombier 		lp++;
4033e12c5d1SDavid du Colombier 	}
4043e12c5d1SDavid du Colombier 	nbytes -= 8;
4053e12c5d1SDavid du Colombier 	Bputc(&bout, '\n');
4063e12c5d1SDavid du Colombier 	while(nbytes > 0){
4073e12c5d1SDavid du Colombier 		i = *(lp+1);
4083e12c5d1SDavid du Colombier 		nbytes -= i+2;
4093e12c5d1SDavid du Colombier 		Bprint(&bout, " %2.2ux %2.2ux", *lp, *(lp+1));
4103e12c5d1SDavid du Colombier 		lp += 2;
4113e12c5d1SDavid du Colombier 		while(i--){
4123e12c5d1SDavid du Colombier 			Bprint(&bout, " %2.2ux", *lp);
4133e12c5d1SDavid du Colombier 			lp++;
4143e12c5d1SDavid du Colombier 		}
4153e12c5d1SDavid du Colombier 		Bputc(&bout, '\n');
4163e12c5d1SDavid du Colombier 	}
4173e12c5d1SDavid du Colombier 	return status;
4183e12c5d1SDavid du Colombier }
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier static long
4213e12c5d1SDavid du Colombier start(ScsiReq *rp, int argc, char *argv[], uchar code)
4223e12c5d1SDavid du Colombier {
4233e12c5d1SDavid du Colombier 	char *p;
4243e12c5d1SDavid du Colombier 
4253e12c5d1SDavid du Colombier 	if(argc && (code = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
4263e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
4273e12c5d1SDavid du Colombier 		return -1;
4283e12c5d1SDavid du Colombier 	}
4293e12c5d1SDavid du Colombier 	return SRstart(rp, code);
4303e12c5d1SDavid du Colombier }
4313e12c5d1SDavid du Colombier 
4323e12c5d1SDavid du Colombier static long
4333e12c5d1SDavid du Colombier cmdstart(ScsiReq *rp, int argc, char *argv[])
4343e12c5d1SDavid du Colombier {
4353e12c5d1SDavid du Colombier 	return start(rp, argc, argv, 1);
4363e12c5d1SDavid du Colombier }
4373e12c5d1SDavid du Colombier 
4383e12c5d1SDavid du Colombier static long
4393e12c5d1SDavid du Colombier cmdstop(ScsiReq *rp, int argc, char *argv[])
4403e12c5d1SDavid du Colombier {
4413e12c5d1SDavid du Colombier 	return start(rp, argc, argv, 0);
4423e12c5d1SDavid du Colombier }
4433e12c5d1SDavid du Colombier 
4443e12c5d1SDavid du Colombier static long
4453e12c5d1SDavid du Colombier cmdeject(ScsiReq *rp, int argc, char *argv[])
4463e12c5d1SDavid du Colombier {
4473e12c5d1SDavid du Colombier 	return start(rp, argc, argv, 2);
4483e12c5d1SDavid du Colombier }
4493e12c5d1SDavid du Colombier 
4503e12c5d1SDavid du Colombier static long
4513e12c5d1SDavid du Colombier cmdcapacity(ScsiReq *rp, int argc, char *argv[])
4523e12c5d1SDavid du Colombier {
4533e12c5d1SDavid du Colombier 	uchar d[6];
4543e12c5d1SDavid du Colombier 	long n;
4553e12c5d1SDavid du Colombier 
4563e12c5d1SDavid du Colombier 	USED(argc, argv);
4573e12c5d1SDavid du Colombier 	if((n = SRrcapacity(rp, d)) == -1)
4583e12c5d1SDavid du Colombier 		return -1;
4593e12c5d1SDavid du Colombier 	Bprint(&bout, " %ld %ld\n", d[0]<<24|d[1]<<16|d[2]<<8|d[3],
4603e12c5d1SDavid du Colombier 		 d[4]<<24|d[5]<<16|d[6]<<8|d[7]);
4613e12c5d1SDavid du Colombier 	return n;
4623e12c5d1SDavid du Colombier }
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier static long
4653e12c5d1SDavid du Colombier cmdflushcache(ScsiReq *rp, int argc, char *argv[])
4663e12c5d1SDavid du Colombier {
4673e12c5d1SDavid du Colombier 	USED(argc, argv);
4683e12c5d1SDavid du Colombier 	return SRflushcache(rp);
4693e12c5d1SDavid du Colombier }
4703e12c5d1SDavid du Colombier 
4713e12c5d1SDavid du Colombier static long
4723e12c5d1SDavid du Colombier cmdrdiscinfo(ScsiReq *rp, int argc, char *argv[])
4733e12c5d1SDavid du Colombier {
4743e12c5d1SDavid du Colombier 	uchar d[MaxDirData], ses, track, *p;
4753e12c5d1SDavid du Colombier 	char *sp;
4763e12c5d1SDavid du Colombier 	long n, nbytes;
4773e12c5d1SDavid du Colombier 
4783e12c5d1SDavid du Colombier 	ses = track = 0;
4793e12c5d1SDavid du Colombier 	switch(argc){
4803e12c5d1SDavid du Colombier 
4813e12c5d1SDavid du Colombier 	default:
4823e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
4833e12c5d1SDavid du Colombier 		return -1;
4843e12c5d1SDavid du Colombier 
4853e12c5d1SDavid du Colombier 	case 2:
4863e12c5d1SDavid du Colombier 		if((ses = strtoul(argv[1], &sp, 0)) == 0 && sp == argv[1]){
4873e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
4883e12c5d1SDavid du Colombier 			return -1;
4893e12c5d1SDavid du Colombier 		}
4903e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
4913e12c5d1SDavid du Colombier 
4923e12c5d1SDavid du Colombier 	case 1:
4933e12c5d1SDavid du Colombier 		if((track = strtoul(argv[0], &sp, 0)) == 0 && sp == argv[0]){
4943e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
4953e12c5d1SDavid du Colombier 			return -1;
4963e12c5d1SDavid du Colombier 		}
4973e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
4983e12c5d1SDavid du Colombier 
4993e12c5d1SDavid du Colombier 	case 0:
5003e12c5d1SDavid du Colombier 		break;
5013e12c5d1SDavid du Colombier 	}
5023e12c5d1SDavid du Colombier 	if((nbytes = SRrdiscinfo(rp, d, ses, track)) == -1)
5033e12c5d1SDavid du Colombier 		return -1;
5043e12c5d1SDavid du Colombier 	if(ses == 0){
5053e12c5d1SDavid du Colombier 		Bprint(&bout, "\ttoc/pma data length: 0x%ux\n", (d[0]<<8)|d[1]);
5063e12c5d1SDavid du Colombier 		Bprint(&bout, "\tfirst track number: %d\n", d[2]);
5073e12c5d1SDavid du Colombier 		Bprint(&bout, "\tlast track number: %d\n", d[3]);
5083e12c5d1SDavid du Colombier 		for(p = &d[4], n = nbytes-4; n; n -= 8, p += 8){
5093e12c5d1SDavid du Colombier 			Bprint(&bout, "\ttrack number: 0x%2.2ux\n", p[2]);
5103e12c5d1SDavid du Colombier 			Bprint(&bout, "\t\tcontrol: 0x%2.2ux\n", p[1] & 0x0F);
5113e12c5d1SDavid du Colombier 			Bprint(&bout, "\t\tblock address: 0x%lux\n",
5123e12c5d1SDavid du Colombier 				(p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]);
5133e12c5d1SDavid du Colombier 		}
5143e12c5d1SDavid du Colombier 	}
5153e12c5d1SDavid du Colombier 	else{
5163e12c5d1SDavid du Colombier 		Bprint(&bout, "\tsessions data length: 0x%ux\n", (d[0]<<8)|d[1]);
5173e12c5d1SDavid du Colombier 		Bprint(&bout, "\tnumber of finished sessions: %d\n", d[2]);
5183e12c5d1SDavid du Colombier 		Bprint(&bout, "\tunfinished session number: %d\n", d[3]);
5193e12c5d1SDavid du Colombier 		for(p = &d[4], n = nbytes-4; n; n -= 8, p += 8){
5203e12c5d1SDavid du Colombier 			Bprint(&bout, "\tsession number: 0x%2.2ux\n", p[0]);
5213e12c5d1SDavid du Colombier 			Bprint(&bout, "\t\tfirst track number in session: 0x%2.2ux\n",
5223e12c5d1SDavid du Colombier 				p[2]);
5233e12c5d1SDavid du Colombier 			Bprint(&bout, "\t\tlogical start address: 0x%lux\n",
5243e12c5d1SDavid du Colombier 				(p[5]<<16)|(p[6]<<8)|p[7]);
5253e12c5d1SDavid du Colombier 		}
5263e12c5d1SDavid du Colombier 	}
5273e12c5d1SDavid du Colombier 	for(n = 0; n < nbytes; n++)
5283e12c5d1SDavid du Colombier 		Bprint(&bout, " %2.2ux", d[n]);
5293e12c5d1SDavid du Colombier 	Bprint(&bout, "\n");
5303e12c5d1SDavid du Colombier 	return nbytes;
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier 
5333e12c5d1SDavid du Colombier static long
5343e12c5d1SDavid du Colombier cmdfwaddr(ScsiReq *rp, int argc, char *argv[])
5353e12c5d1SDavid du Colombier {
5363e12c5d1SDavid du Colombier 	uchar d[MaxDirData], npa, track, mode;
5373e12c5d1SDavid du Colombier 	long n;
5383e12c5d1SDavid du Colombier 	char *p;
5393e12c5d1SDavid du Colombier 
5403e12c5d1SDavid du Colombier 	npa = mode = track = 0;
5413e12c5d1SDavid du Colombier 	switch(argc){
5423e12c5d1SDavid du Colombier 
5433e12c5d1SDavid du Colombier 	default:
5443e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
5453e12c5d1SDavid du Colombier 		return -1;
5463e12c5d1SDavid du Colombier 
5473e12c5d1SDavid du Colombier 	case 3:
5483e12c5d1SDavid du Colombier 		if((npa = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
5493e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
5503e12c5d1SDavid du Colombier 			return -1;
5513e12c5d1SDavid du Colombier 		}
5523e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
5533e12c5d1SDavid du Colombier 
5543e12c5d1SDavid du Colombier 	case 2:
5553e12c5d1SDavid du Colombier 		if((mode = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
5563e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
5573e12c5d1SDavid du Colombier 			return -1;
5583e12c5d1SDavid du Colombier 		}
5593e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier 	case 1:
5623e12c5d1SDavid du Colombier 		if((track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
5633e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
5643e12c5d1SDavid du Colombier 			return -1;
5653e12c5d1SDavid du Colombier 		}
5663e12c5d1SDavid du Colombier 		break;
5673e12c5d1SDavid du Colombier 
5683e12c5d1SDavid du Colombier 	case 0:
5693e12c5d1SDavid du Colombier 		break;
5703e12c5d1SDavid du Colombier 	}
5713e12c5d1SDavid du Colombier 	if((n = SRfwaddr(rp, track, mode, npa, d)) == -1)
5723e12c5d1SDavid du Colombier 		return -1;
5733e12c5d1SDavid du Colombier 	Bprint(&bout, "%ud %ld\n", d[0], (d[1]<<24)|(d[2]<<16)|(d[3]<<8)|d[4]);
5743e12c5d1SDavid du Colombier 	return n;
5753e12c5d1SDavid du Colombier }
5763e12c5d1SDavid du Colombier 
5773e12c5d1SDavid du Colombier static long
5783e12c5d1SDavid du Colombier cmdtreserve(ScsiReq *rp, int argc, char *argv[])
5793e12c5d1SDavid du Colombier {
5803e12c5d1SDavid du Colombier 	long nbytes;
5813e12c5d1SDavid du Colombier 	char *p;
5823e12c5d1SDavid du Colombier 
5833e12c5d1SDavid du Colombier 	if(argc != 1 || ((nbytes = strtoul(argv[0], &p, 0)) == 0 && p == argv[0])){
5843e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
5853e12c5d1SDavid du Colombier 		return -1;
5863e12c5d1SDavid du Colombier 	}
5873e12c5d1SDavid du Colombier 	return SRtreserve(rp, nbytes);
5883e12c5d1SDavid du Colombier }
5893e12c5d1SDavid du Colombier 
5903e12c5d1SDavid du Colombier static long
5913e12c5d1SDavid du Colombier cmdtrackinfo(ScsiReq *rp, int argc, char *argv[])
5923e12c5d1SDavid du Colombier {
5933e12c5d1SDavid du Colombier 	uchar d[MaxDirData], track;
5943e12c5d1SDavid du Colombier 	long n;
5953e12c5d1SDavid du Colombier 	ulong ul;
5963e12c5d1SDavid du Colombier 	char *p;
5973e12c5d1SDavid du Colombier 
5983e12c5d1SDavid du Colombier 	track = 0;
5993e12c5d1SDavid du Colombier 	if(argc && (track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
6003e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
6013e12c5d1SDavid du Colombier 		return -1;
6023e12c5d1SDavid du Colombier 	}
6033e12c5d1SDavid du Colombier 	if((n = SRtinfo(rp, track, d)) == -1)
6043e12c5d1SDavid du Colombier 		return -1;
6053e12c5d1SDavid du Colombier 	Bprint(&bout, "buffer length: 0x%ux\n", d[0]);
6063e12c5d1SDavid du Colombier 	Bprint(&bout, "number of tracks: 0x%ux\n", d[1]);
6073e12c5d1SDavid du Colombier 	ul = (d[2]<<24)|(d[3]<<16)|(d[4]<<8)|d[5];
6083e12c5d1SDavid du Colombier 	Bprint(&bout, "start address: 0x%lux\n", ul);
6093e12c5d1SDavid du Colombier 	ul = (d[6]<<24)|(d[7]<<16)|(d[8]<<8)|d[9];
6103e12c5d1SDavid du Colombier 	Bprint(&bout, "track length: 0x%lux\n", ul);
6113e12c5d1SDavid du Colombier 	Bprint(&bout, "track mode: 0x%ux\n", d[0x0A] & 0x0F);
6123e12c5d1SDavid du Colombier 	Bprint(&bout, "track status: 0x%ux\n", (d[0x0A]>>4) & 0x0F);
6133e12c5d1SDavid du Colombier 	Bprint(&bout, "data mode: 0x%ux\n", d[0x0B] & 0x0F);
6143e12c5d1SDavid du Colombier 	ul = (d[0x0C]<<24)|(d[0x0D]<<16)|(d[0x0E]<<8)|d[0x0F];
6153e12c5d1SDavid du Colombier 	Bprint(&bout, "free blocks: 0x%lux\n", ul);
6163e12c5d1SDavid du Colombier 	return n;
6173e12c5d1SDavid du Colombier }
6183e12c5d1SDavid du Colombier 
6193e12c5d1SDavid du Colombier static long
6203e12c5d1SDavid du Colombier cmdwtrack(ScsiReq *rp, int argc, char *argv[])
6213e12c5d1SDavid du Colombier {
6223e12c5d1SDavid du Colombier 	uchar mode, track;
6233e12c5d1SDavid du Colombier 	long n, nbytes, total, x;
6243e12c5d1SDavid du Colombier 	int fd, pid;
6253e12c5d1SDavid du Colombier 	char *p;
6263e12c5d1SDavid du Colombier 
6273e12c5d1SDavid du Colombier 	mode = track = 0;
6283e12c5d1SDavid du Colombier 	nbytes = 0;
6293e12c5d1SDavid du Colombier 	switch(argc){
6303e12c5d1SDavid du Colombier 
6313e12c5d1SDavid du Colombier 	default:
6323e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
6333e12c5d1SDavid du Colombier 		return -1;
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 	case 4:
6363e12c5d1SDavid du Colombier 		if((mode = strtoul(argv[3], &p, 0)) == 0 && p == argv[3]){
6373e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
6383e12c5d1SDavid du Colombier 			return -1;
6393e12c5d1SDavid du Colombier 		}
6403e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
6413e12c5d1SDavid du Colombier 
6423e12c5d1SDavid du Colombier 	case 3:
6433e12c5d1SDavid du Colombier 		if((track = strtoul(argv[2], &p, 0)) == 0 && p == argv[2]){
6443e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
6453e12c5d1SDavid du Colombier 			return -1;
6463e12c5d1SDavid du Colombier 		}
6473e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
6483e12c5d1SDavid du Colombier 
6493e12c5d1SDavid du Colombier 	case 2:
6503e12c5d1SDavid du Colombier 		if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
6513e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
6523e12c5d1SDavid du Colombier 			return -1;
6533e12c5d1SDavid du Colombier 		}
6543e12c5d1SDavid du Colombier 		/*FALLTHROUGH*/
6553e12c5d1SDavid du Colombier 
6563e12c5d1SDavid du Colombier 	case 1:
6573e12c5d1SDavid du Colombier 		if((fd = mkfile(argv[0], OREAD, &pid)) == -1){
6583e12c5d1SDavid du Colombier 			rp->status = Status_BADARG;
6593e12c5d1SDavid du Colombier 			return -1;
6603e12c5d1SDavid du Colombier 		}
6613e12c5d1SDavid du Colombier 		break;
6623e12c5d1SDavid du Colombier 	}
6633e12c5d1SDavid du Colombier 	total = 0;
6643e12c5d1SDavid du Colombier 	n = MIN(nbytes, MaxIOsize);
6653e12c5d1SDavid du Colombier 	if((n = read(fd, rwbuf, n)) == -1){
6663e12c5d1SDavid du Colombier 		fprint(2, "file read failed %r\n");
6673e12c5d1SDavid du Colombier 		close(fd);
6683e12c5d1SDavid du Colombier 		return -1;
6693e12c5d1SDavid du Colombier 	}
6703e12c5d1SDavid du Colombier 	if((x = SRwtrack(rp, rwbuf, n, track, mode)) != n){
6713e12c5d1SDavid du Colombier 		fprint(2, "wtrack: write incomplete: asked %d, did %d\n", n, x);
6723e12c5d1SDavid du Colombier 		if(rp->status == Status_OK)
6733e12c5d1SDavid du Colombier 			rp->status = Status_SW;
6743e12c5d1SDavid du Colombier 		close(fd);
6753e12c5d1SDavid du Colombier 		return -1;
6763e12c5d1SDavid du Colombier 	}
6773e12c5d1SDavid du Colombier 	nbytes -= n;
6783e12c5d1SDavid du Colombier 	total += n;
6793e12c5d1SDavid du Colombier 	while(nbytes){
6803e12c5d1SDavid du Colombier 		n = MIN(nbytes, MaxIOsize);
6813e12c5d1SDavid du Colombier 		if((n = read(fd, rwbuf, n)) == -1){
6823e12c5d1SDavid du Colombier 			break;
6833e12c5d1SDavid du Colombier 		}
6843e12c5d1SDavid du Colombier 		if((x = SRwrite(rp, rwbuf, n)) != n){
6853e12c5d1SDavid du Colombier 			fprint(2, "write: write incomplete: asked %d, did %d\n", n, x);
6863e12c5d1SDavid du Colombier 			if(rp->status == Status_OK)
6873e12c5d1SDavid du Colombier 				rp->status = Status_SW;
6883e12c5d1SDavid du Colombier 			break;
6893e12c5d1SDavid du Colombier 		}
6903e12c5d1SDavid du Colombier 		nbytes -= n;
6913e12c5d1SDavid du Colombier 		total += n;
6923e12c5d1SDavid du Colombier 	}
6933e12c5d1SDavid du Colombier 	close(fd);
6943e12c5d1SDavid du Colombier 	if(pid >= 0 && waitfor(pid)){
6953e12c5d1SDavid du Colombier 		rp->status = Status_SW;
6963e12c5d1SDavid du Colombier 		return -1;
6973e12c5d1SDavid du Colombier 	}
6983e12c5d1SDavid du Colombier 	return total;
6993e12c5d1SDavid du Colombier }
7003e12c5d1SDavid du Colombier 
7013e12c5d1SDavid du Colombier static long
7023e12c5d1SDavid du Colombier cmdload(ScsiReq *rp, int argc, char *argv[])
7033e12c5d1SDavid du Colombier {
7043e12c5d1SDavid du Colombier 	USED(argc, argv);
7053e12c5d1SDavid du Colombier 	return SRmload(rp, 0);
7063e12c5d1SDavid du Colombier }
7073e12c5d1SDavid du Colombier 
7083e12c5d1SDavid du Colombier static long
7093e12c5d1SDavid du Colombier cmdunload(ScsiReq *rp, int argc, char *argv[])
7103e12c5d1SDavid du Colombier {
7113e12c5d1SDavid du Colombier 	USED(argc, argv);
7123e12c5d1SDavid du Colombier 	return SRmload(rp, 1);
7133e12c5d1SDavid du Colombier }
7143e12c5d1SDavid du Colombier 
7153e12c5d1SDavid du Colombier static long
7163e12c5d1SDavid du Colombier cmdfixation(ScsiReq *rp, int argc, char *argv[])
7173e12c5d1SDavid du Colombier {
7183e12c5d1SDavid du Colombier 	uchar type;
7193e12c5d1SDavid du Colombier 	char *p;
7203e12c5d1SDavid du Colombier 
7213e12c5d1SDavid du Colombier 	type = 0;
7223e12c5d1SDavid du Colombier 	if(argc && (type = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
7233e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
7243e12c5d1SDavid du Colombier 		return -1;
7253e12c5d1SDavid du Colombier 	}
7263e12c5d1SDavid du Colombier 	return SRfixation(rp, type);
7273e12c5d1SDavid du Colombier }
7283e12c5d1SDavid du Colombier 
7293e12c5d1SDavid du Colombier static long
7303e12c5d1SDavid du Colombier cmdhelp(ScsiReq *rp, int argc, char *argv[])
7313e12c5d1SDavid du Colombier {
7323e12c5d1SDavid du Colombier 	ScsiCmd *cp;
7333e12c5d1SDavid du Colombier 	char *p;
7343e12c5d1SDavid du Colombier 
7353e12c5d1SDavid du Colombier 	USED(rp);
7363e12c5d1SDavid du Colombier 	if(argc)
7373e12c5d1SDavid du Colombier 		p = argv[0];
7383e12c5d1SDavid du Colombier 	else
7393e12c5d1SDavid du Colombier 		p = 0;
7403e12c5d1SDavid du Colombier 	for(cp = scsicmd; cp->name; cp++){
7413e12c5d1SDavid du Colombier 		if(p == 0 || strcmp(p, cp->name) == 0)
7423e12c5d1SDavid du Colombier 			Bprint(&bout, "%s\n", cp->help);
7433e12c5d1SDavid du Colombier 	}
7443e12c5d1SDavid du Colombier 	return 0;
7453e12c5d1SDavid du Colombier }
7463e12c5d1SDavid du Colombier 
7473e12c5d1SDavid du Colombier static long
7483e12c5d1SDavid du Colombier cmdprobe(ScsiReq *rp, int argc, char *argv[])
7493e12c5d1SDavid du Colombier {
7503e12c5d1SDavid du Colombier 	ScsiReq scsireq;
7513e12c5d1SDavid du Colombier 	uchar id;
7523e12c5d1SDavid du Colombier 
7533e12c5d1SDavid du Colombier 	USED(argc, argv);
7543e12c5d1SDavid du Colombier 	rp->status = Status_OK;
7553e12c5d1SDavid du Colombier 	scsireq.flags = 0;
7563e12c5d1SDavid du Colombier 	for(id = 0; id < CtlrID; id++){
7573e12c5d1SDavid du Colombier 		if(SRopenraw(&scsireq, id) == -1)
7583e12c5d1SDavid du Colombier 			return -1;
7593e12c5d1SDavid du Colombier 		SRreqsense(&scsireq);
7603e12c5d1SDavid du Colombier 		switch(scsireq.status){
7613e12c5d1SDavid du Colombier 
7623e12c5d1SDavid du Colombier 		default:
7633e12c5d1SDavid du Colombier 			break;
7643e12c5d1SDavid du Colombier 
7653e12c5d1SDavid du Colombier 		case Status_OK:
7663e12c5d1SDavid du Colombier 		case Status_SD:
7673e12c5d1SDavid du Colombier 			Bprint(&bout, "%d: ", id);
7683e12c5d1SDavid du Colombier 			cmdinquiry(&scsireq, 0, 0);
7693e12c5d1SDavid du Colombier 			break;
7703e12c5d1SDavid du Colombier 		}
7713e12c5d1SDavid du Colombier 		SRclose(&scsireq);
7723e12c5d1SDavid du Colombier 	}
7733e12c5d1SDavid du Colombier 	return 0;
7743e12c5d1SDavid du Colombier }
7753e12c5d1SDavid du Colombier 
7763e12c5d1SDavid du Colombier static long
7773e12c5d1SDavid du Colombier cmdclose(ScsiReq *rp, int argc, char *argv[])
7783e12c5d1SDavid du Colombier {
7793e12c5d1SDavid du Colombier 	USED(argc, argv);
7803e12c5d1SDavid du Colombier 	return SRclose(rp);
7813e12c5d1SDavid du Colombier }
7823e12c5d1SDavid du Colombier 
7833e12c5d1SDavid du Colombier static long
7843e12c5d1SDavid du Colombier cmdopen(ScsiReq *rp, int argc, char *argv[])
7853e12c5d1SDavid du Colombier {
7863e12c5d1SDavid du Colombier 	char *p;
787bd389b36SDavid du Colombier 	int id, raw;
7883e12c5d1SDavid du Colombier 	long status;
7893e12c5d1SDavid du Colombier 
790bd389b36SDavid du Colombier 	raw = 0;
791bd389b36SDavid du Colombier 	if(argc && strcmp("-r", argv[0]) == 0){
792bd389b36SDavid du Colombier 		raw = 1;
793bd389b36SDavid du Colombier 		argc--, argv++;
794bd389b36SDavid du Colombier 	}
7953e12c5d1SDavid du Colombier 	if(argc != 1 || ((id = strtoul(argv[0], &p, 0)) == 0 && p == argv[0])){
7963e12c5d1SDavid du Colombier 		rp->status = Status_BADARG;
7973e12c5d1SDavid du Colombier 		return -1;
7983e12c5d1SDavid du Colombier 	}
799bd389b36SDavid du Colombier 	if(raw == 0){
800bd389b36SDavid du Colombier 		if((status = SRopen(rp, id)) != -1 && verbose)
8013e12c5d1SDavid du Colombier 			Bprint(&bout, "block size: %ld\n", rp->lbsize);
802bd389b36SDavid du Colombier 	}
803bd389b36SDavid du Colombier 	else {
804bd389b36SDavid du Colombier 		status = SRopenraw(rp, id);
805bd389b36SDavid du Colombier 		rp->lbsize = 512;
806bd389b36SDavid du Colombier 	}
8073e12c5d1SDavid du Colombier 	return status;
8083e12c5d1SDavid du Colombier }
8093e12c5d1SDavid du Colombier 
8103e12c5d1SDavid du Colombier static ScsiCmd scsicmd[] = {
8113e12c5d1SDavid du Colombier 	{ "ready",	cmdready,	1,		/*[0x00]*/
8123e12c5d1SDavid du Colombier 	  "ready",
8133e12c5d1SDavid du Colombier 	},
8143e12c5d1SDavid du Colombier 	{ "rewind",	cmdrewind,	1,		/*[0x01]*/
8153e12c5d1SDavid du Colombier 	  "rewind",
8163e12c5d1SDavid du Colombier 	},
8173e12c5d1SDavid du Colombier 	{ "rezero",	cmdrewind,	1,		/*[0x01]*/
8183e12c5d1SDavid du Colombier 	  "rezero",
8193e12c5d1SDavid du Colombier 	},
8203e12c5d1SDavid du Colombier 	{ "reqsense",	cmdreqsense,	1,		/*[0x03]*/
8213e12c5d1SDavid du Colombier 	  "reqsense",
8223e12c5d1SDavid du Colombier 	},
823bd389b36SDavid du Colombier 	{ "format",	cmdformat,	0,		/*[0x04]*/
8243e12c5d1SDavid du Colombier 	  "format",
8253e12c5d1SDavid du Colombier 	},
8263e12c5d1SDavid du Colombier 	{ "rblimits",	cmdrblimits,	1,		/*[0x05]*/
8273e12c5d1SDavid du Colombier 	  "rblimits",
8283e12c5d1SDavid du Colombier 	},
8293e12c5d1SDavid du Colombier 	{ "read",	cmdread,	1,		/*[0x08]*/
8303e12c5d1SDavid du Colombier 	  "read [|]file [nbytes]",
8313e12c5d1SDavid du Colombier 	},
8323e12c5d1SDavid du Colombier 	{ "write",	cmdwrite,	1,		/*[0x0A]*/
8333e12c5d1SDavid du Colombier 	  "write [|]file [nbytes]",
8343e12c5d1SDavid du Colombier 	},
8353e12c5d1SDavid du Colombier 	{ "seek",	cmdseek,	1,		/*[0x0B]*/
8363e12c5d1SDavid du Colombier 	  "seek offset [whence]",
8373e12c5d1SDavid du Colombier 	},
8383e12c5d1SDavid du Colombier 	{ "filemark",	cmdfilemark,	1,		/*[0x10]*/
8393e12c5d1SDavid du Colombier 	  "filemark [howmany]",
8403e12c5d1SDavid du Colombier 	},
8413e12c5d1SDavid du Colombier 	{ "space",	cmdspace,	1,		/*[0x11]*/
8423e12c5d1SDavid du Colombier 	  "space [-f] [-b] [[--] howmany]",
8433e12c5d1SDavid du Colombier 	},
8443e12c5d1SDavid du Colombier 	{ "inquiry",	cmdinquiry,	1,		/*[0x12]*/
8453e12c5d1SDavid du Colombier 	  "inquiry",
8463e12c5d1SDavid du Colombier 	},
8473e12c5d1SDavid du Colombier 	{ "modeselect",	cmdmodeselect,	1,		/*[0x15] */
8483e12c5d1SDavid du Colombier 	  "modeselect bytes...",
8493e12c5d1SDavid du Colombier 	},
8503e12c5d1SDavid du Colombier 	{ "modesense",	cmdmodesense,	1,		/*[0x1A]*/
8513e12c5d1SDavid du Colombier 	  "modesense [page [nbytes]]",
8523e12c5d1SDavid du Colombier 	},
8533e12c5d1SDavid du Colombier 	{ "start",	cmdstart,	1,		/*[0x1B]*/
8543e12c5d1SDavid du Colombier 	  "start [code]",
8553e12c5d1SDavid du Colombier 	},
8563e12c5d1SDavid du Colombier 	{ "stop",	cmdstop,	1,		/*[0x1B]*/
8573e12c5d1SDavid du Colombier 	  "stop [code]",
8583e12c5d1SDavid du Colombier 	},
8593e12c5d1SDavid du Colombier 	{ "eject",	cmdeject,	1,		/*[0x1B]*/
8603e12c5d1SDavid du Colombier 	  "eject [code]",
8613e12c5d1SDavid du Colombier 	},
8623e12c5d1SDavid du Colombier 	{ "capacity",	cmdcapacity,	1,		/*[0x25]*/
8633e12c5d1SDavid du Colombier 	  "capacity",
8643e12c5d1SDavid du Colombier 	},
8653e12c5d1SDavid du Colombier 
8663e12c5d1SDavid du Colombier 	{ "flushcache",	cmdflushcache,	1,		/*[0x35]*/
8673e12c5d1SDavid du Colombier 	  "flushcache",
8683e12c5d1SDavid du Colombier 	},
8693e12c5d1SDavid du Colombier 	{ "rdiscinfo",	cmdrdiscinfo,	1,		/*[0x43]*/
8703e12c5d1SDavid du Colombier 	  "rdiscinfo [track/session-number [ses]]",
8713e12c5d1SDavid du Colombier 	},
8723e12c5d1SDavid du Colombier 	{ "fwaddr",	cmdfwaddr,	1,		/*[0xE2]*/
8733e12c5d1SDavid du Colombier 	  "fwaddr [track [mode [npa]]]",
8743e12c5d1SDavid du Colombier 	},
8753e12c5d1SDavid du Colombier 	{ "treserve",	cmdtreserve,	1,		/*[0xE4]*/
8763e12c5d1SDavid du Colombier 	  "treserve nbytes",
8773e12c5d1SDavid du Colombier 	},
8783e12c5d1SDavid du Colombier 	{ "trackinfo",	cmdtrackinfo,	1,		/*[0xE5]*/
8793e12c5d1SDavid du Colombier 	  "trackinfo [track]",
8803e12c5d1SDavid du Colombier 	},
8813e12c5d1SDavid du Colombier 	{ "wtrack",	cmdwtrack,	1,		/*[0xE6]*/
8823e12c5d1SDavid du Colombier 	  "wtrack [|]file [nbytes [track [mode]]]",
8833e12c5d1SDavid du Colombier 	},
8843e12c5d1SDavid du Colombier 	{ "load",	cmdload,	1,		/*[0xE7]*/
8853e12c5d1SDavid du Colombier 	  "load",
8863e12c5d1SDavid du Colombier 	},
8873e12c5d1SDavid du Colombier 	{ "unload",	cmdunload,	1,		/*[0xE7]*/
8883e12c5d1SDavid du Colombier 	  "unload",
8893e12c5d1SDavid du Colombier 	},
8903e12c5d1SDavid du Colombier 	{ "fixation",	cmdfixation,	1,		/*[0xE9]*/
8913e12c5d1SDavid du Colombier 	  "fixation [toc-type]",
8923e12c5d1SDavid du Colombier 	},
8933e12c5d1SDavid du Colombier 
8943e12c5d1SDavid du Colombier 	{ "help",	cmdhelp,	0,
8953e12c5d1SDavid du Colombier 	  "help",
8963e12c5d1SDavid du Colombier 	},
8973e12c5d1SDavid du Colombier 	{ "probe",	cmdprobe,	0,
8983e12c5d1SDavid du Colombier 	  "probe",
8993e12c5d1SDavid du Colombier 	},
9003e12c5d1SDavid du Colombier 	{ "close",	cmdclose,	1,
9013e12c5d1SDavid du Colombier 	  "close",
9023e12c5d1SDavid du Colombier 	},
9033e12c5d1SDavid du Colombier 	{ "open",	cmdopen,	0,
9043e12c5d1SDavid du Colombier 	  "open target-id",
9053e12c5d1SDavid du Colombier 	},
9063e12c5d1SDavid du Colombier 	{ 0, 0 },
9073e12c5d1SDavid du Colombier };
9083e12c5d1SDavid du Colombier 
9093e12c5d1SDavid du Colombier #define	SEP(c)	(((c)==' ')||((c)=='\t')||((c)=='\n'))
9103e12c5d1SDavid du Colombier 
9113e12c5d1SDavid du Colombier static char *
9123e12c5d1SDavid du Colombier tokenise(char *s, char **start, char **end)
9133e12c5d1SDavid du Colombier {
9143e12c5d1SDavid du Colombier 	char *to;
9153e12c5d1SDavid du Colombier 	Rune r;
9163e12c5d1SDavid du Colombier 	int n;
9173e12c5d1SDavid du Colombier 
9183e12c5d1SDavid du Colombier 	while(*s && SEP(*s))				/* skip leading white space */
9193e12c5d1SDavid du Colombier 		s++;
9203e12c5d1SDavid du Colombier 	to = *start = s;
9213e12c5d1SDavid du Colombier 	while(*s){
9223e12c5d1SDavid du Colombier 		n = chartorune(&r, s);
9233e12c5d1SDavid du Colombier 		if(SEP(r)){
9243e12c5d1SDavid du Colombier 			if(to != *start)		/* we have data */
9253e12c5d1SDavid du Colombier 				break;
9263e12c5d1SDavid du Colombier 			s += n;				/* null string - keep looking */
9273e12c5d1SDavid du Colombier 			while(*s && SEP(*s))
9283e12c5d1SDavid du Colombier 				s++;
9293e12c5d1SDavid du Colombier 			to = *start = s;
9303e12c5d1SDavid du Colombier 		}
9313e12c5d1SDavid du Colombier 		else if(r == '\''){
9323e12c5d1SDavid du Colombier 			s += n;				/* skip leading quote */
9333e12c5d1SDavid du Colombier 			while(*s){
9343e12c5d1SDavid du Colombier 				n = chartorune(&r, s);
9353e12c5d1SDavid du Colombier 				if(r == '\''){
9363e12c5d1SDavid du Colombier 					if(s[1] != '\'')
9373e12c5d1SDavid du Colombier 						break;
9383e12c5d1SDavid du Colombier 					s++;		/* embedded quote */
9393e12c5d1SDavid du Colombier 				}
9403e12c5d1SDavid du Colombier 				while (n--)
9413e12c5d1SDavid du Colombier 					*to++ = *s++;
9423e12c5d1SDavid du Colombier 			}
9433e12c5d1SDavid du Colombier 			if(!*s)				/* no trailing quote */
9443e12c5d1SDavid du Colombier 				break;
9453e12c5d1SDavid du Colombier 			s++;				/* skip trailing quote */
9463e12c5d1SDavid du Colombier 		}
9473e12c5d1SDavid du Colombier 		else  {
9483e12c5d1SDavid du Colombier 			while(n--)
9493e12c5d1SDavid du Colombier 				*to++ = *s++;
9503e12c5d1SDavid du Colombier 		}
9513e12c5d1SDavid du Colombier 	}
9523e12c5d1SDavid du Colombier 	*end = to;
9533e12c5d1SDavid du Colombier 	return s;
9543e12c5d1SDavid du Colombier }
9553e12c5d1SDavid du Colombier 
9563e12c5d1SDavid du Colombier static int
9573e12c5d1SDavid du Colombier parse(char *s, char *fields[], int nfields)
9583e12c5d1SDavid du Colombier {
959*219b2ee8SDavid du Colombier 	int c, argc;
9603e12c5d1SDavid du Colombier 	char *start, *end;
9613e12c5d1SDavid du Colombier 
9623e12c5d1SDavid du Colombier 	argc = 0;
963*219b2ee8SDavid du Colombier 	c = *s;
964*219b2ee8SDavid du Colombier 	while(c){
9653e12c5d1SDavid du Colombier 		s = tokenise(s, &start, &end);
966*219b2ee8SDavid du Colombier 		c = *s++;
9673e12c5d1SDavid du Colombier 		if(*start == 0)
9683e12c5d1SDavid du Colombier 			break;
9693e12c5d1SDavid du Colombier 		if(argc >= nfields-1)
9703e12c5d1SDavid du Colombier 			return -1;
9713e12c5d1SDavid du Colombier 		*end = 0;
9723e12c5d1SDavid du Colombier 		fields[argc++] = start;
9733e12c5d1SDavid du Colombier 	}
9743e12c5d1SDavid du Colombier 	fields[argc] = 0;
9753e12c5d1SDavid du Colombier 	return argc;
9763e12c5d1SDavid du Colombier }
9773e12c5d1SDavid du Colombier 
9783e12c5d1SDavid du Colombier static void
9793e12c5d1SDavid du Colombier usage(void)
9803e12c5d1SDavid du Colombier {
981*219b2ee8SDavid du Colombier 	fprint(2, "%s: usage: %s [-b bus] [-q] [scsi-id]\n", argv0, argv0);
9823e12c5d1SDavid du Colombier 	exits("usage");
9833e12c5d1SDavid du Colombier }
9843e12c5d1SDavid du Colombier 
9853e12c5d1SDavid du Colombier void
9863e12c5d1SDavid du Colombier main(int argc, char *argv[])
9873e12c5d1SDavid du Colombier {
9883e12c5d1SDavid du Colombier 	ScsiReq target;
9893e12c5d1SDavid du Colombier 	char *ap, *av[50];
9903e12c5d1SDavid du Colombier 	int ac;
9913e12c5d1SDavid du Colombier 	ScsiCmd *cp;
9923e12c5d1SDavid du Colombier 	long status;
9933e12c5d1SDavid du Colombier 
9943e12c5d1SDavid du Colombier 	ARGBEGIN {
995*219b2ee8SDavid du Colombier 	case 'b':
996*219b2ee8SDavid du Colombier 		bus = atoi(ARGF());
997*219b2ee8SDavid du Colombier 		break;
9983e12c5d1SDavid du Colombier 
9993e12c5d1SDavid du Colombier 	case 'q':
10003e12c5d1SDavid du Colombier 		verbose = 0;
10013e12c5d1SDavid du Colombier 		break;
10023e12c5d1SDavid du Colombier 
10033e12c5d1SDavid du Colombier 	default:
10043e12c5d1SDavid du Colombier 		usage();
10053e12c5d1SDavid du Colombier 	} ARGEND
10063e12c5d1SDavid du Colombier 
10073e12c5d1SDavid du Colombier 	if(Binit(&bin, 0, OREAD) == Beof || Binit(&bout, 1, OWRITE) == Beof){
10083e12c5d1SDavid du Colombier 		fprint(2, "%s: can't init bio: %r\n", argv0);
10093e12c5d1SDavid du Colombier 		exits("Binit");
10103e12c5d1SDavid du Colombier 	}
10113e12c5d1SDavid du Colombier 
10123e12c5d1SDavid du Colombier 	memset(&target, 0, sizeof(target));
10133e12c5d1SDavid du Colombier 	if(argc && cmdopen(&target, argc, argv) == -1)
10143e12c5d1SDavid du Colombier 		usage();
10153e12c5d1SDavid du Colombier 	Bflush(&bout);
10163e12c5d1SDavid du Colombier 
10173e12c5d1SDavid du Colombier 	while(ap = Brdline(&bin, '\n')){
10183e12c5d1SDavid du Colombier 		ap[BLINELEN(&bin)-1] = 0;
1019*219b2ee8SDavid du Colombier 		switch(ac = parse(ap, av, nelem(av))){
10203e12c5d1SDavid du Colombier 
10213e12c5d1SDavid du Colombier 		default:
10223e12c5d1SDavid du Colombier 			for(cp = scsicmd; cp->name; cp++){
10233e12c5d1SDavid du Colombier 				if(strcmp(cp->name, av[0]) == 0)
10243e12c5d1SDavid du Colombier 					break;
10253e12c5d1SDavid du Colombier 			}
10263e12c5d1SDavid du Colombier 			if(cp->name == 0){
10273e12c5d1SDavid du Colombier 				Bprint(&bout, "eh?\n");
10283e12c5d1SDavid du Colombier 				break;
10293e12c5d1SDavid du Colombier 			}
10303e12c5d1SDavid du Colombier 			if((target.flags & Fopen) == 0 && cp->open){
10313e12c5d1SDavid du Colombier 				Bprint(&bout, "no current target\n");
10323e12c5d1SDavid du Colombier 				break;
10333e12c5d1SDavid du Colombier 			}
10343e12c5d1SDavid du Colombier 			if((status = (*cp->f)(&target, ac-1, &av[1])) != -1){
10353e12c5d1SDavid du Colombier 				if(verbose)
10363e12c5d1SDavid du Colombier 					Bprint(&bout, "ok %ld\n", status);
10373e12c5d1SDavid du Colombier 				break;
10383e12c5d1SDavid du Colombier 			}
10393e12c5d1SDavid du Colombier 			switch(target.status){
10403e12c5d1SDavid du Colombier 
10413e12c5d1SDavid du Colombier 			case Status_OK:
10423e12c5d1SDavid du Colombier 				if(verbose)
10433e12c5d1SDavid du Colombier 					Bprint(&bout, "ok %ld\n", status);
10443e12c5d1SDavid du Colombier 				break;
10453e12c5d1SDavid du Colombier 
10463e12c5d1SDavid du Colombier 			case Status_SD:
10473e12c5d1SDavid du Colombier 				makesense(&target);
10483e12c5d1SDavid du Colombier 				break;
10493e12c5d1SDavid du Colombier 
10503e12c5d1SDavid du Colombier 			case Status_NX:
10513e12c5d1SDavid du Colombier 				Bprint(&bout, "select timeout\n");
10523e12c5d1SDavid du Colombier 				break;
10533e12c5d1SDavid du Colombier 
10543e12c5d1SDavid du Colombier 			case Status_HW:
10553e12c5d1SDavid du Colombier 				Bprint(&bout, "hardware error\n");
10563e12c5d1SDavid du Colombier 				break;
10573e12c5d1SDavid du Colombier 
10583e12c5d1SDavid du Colombier 			case Status_SW:
10593e12c5d1SDavid du Colombier 				Bprint(&bout, "software error\n");
10603e12c5d1SDavid du Colombier 				break;
10613e12c5d1SDavid du Colombier 
10623e12c5d1SDavid du Colombier 			case Status_BADARG:
10633e12c5d1SDavid du Colombier 				Bprint(&bout, "bad argument\n");
10643e12c5d1SDavid du Colombier 				break;
10653e12c5d1SDavid du Colombier 
10663e12c5d1SDavid du Colombier 			case Status_RO:
10673e12c5d1SDavid du Colombier 				Bprint(&bout, "device is read-only\n");
10683e12c5d1SDavid du Colombier 				break;
10693e12c5d1SDavid du Colombier 
10703e12c5d1SDavid du Colombier 			default:
10713e12c5d1SDavid du Colombier 				Bprint(&bout, "status %ld #%2.2ux\n", status, target.status);
10723e12c5d1SDavid du Colombier 				break;
10733e12c5d1SDavid du Colombier 			}
10743e12c5d1SDavid du Colombier 			break;
10753e12c5d1SDavid du Colombier 
10763e12c5d1SDavid du Colombier 		case -1:
10773e12c5d1SDavid du Colombier 			Bprint(&bout, "eh?\n");
10783e12c5d1SDavid du Colombier 			break;
10793e12c5d1SDavid du Colombier 
10803e12c5d1SDavid du Colombier 		case 0:
10813e12c5d1SDavid du Colombier 			break;
10823e12c5d1SDavid du Colombier 		}
10833e12c5d1SDavid du Colombier 		Bflush(&bout);
10843e12c5d1SDavid du Colombier 	}
10853e12c5d1SDavid du Colombier 	exits(0);
10863e12c5d1SDavid du Colombier }
10873e12c5d1SDavid du Colombier 
1088