xref: /plan9/sys/src/cmd/ip/telnet.h (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier typedef struct Opt	Opt;
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier int debug;
43e12c5d1SDavid du Colombier #define DPRINT if(debug)fprint
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier enum
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier 	/* control characters */
93e12c5d1SDavid du Colombier 	Se=		240,		/* end subnegotiation */
103e12c5d1SDavid du Colombier 	NOP=		241,
113e12c5d1SDavid du Colombier 	Mark=		242,		/* data mark */
123e12c5d1SDavid du Colombier 	Break=		243,
133e12c5d1SDavid du Colombier 	Interrupt=	244,
143e12c5d1SDavid du Colombier 	Abort=		245,		/* TENEX ^O */
153e12c5d1SDavid du Colombier 	AreYouThere=	246,
163e12c5d1SDavid du Colombier 	Erasechar=	247,		/* erase last character */
173e12c5d1SDavid du Colombier 	Eraseline=	248,		/* erase line */
183e12c5d1SDavid du Colombier 	GoAhead=	249,		/* half duplex clear to send */
193e12c5d1SDavid du Colombier 	Sb=		250,		/* start subnegotiation */
203e12c5d1SDavid du Colombier 	Will=		251,
213e12c5d1SDavid du Colombier 	Wont=		252,
223e12c5d1SDavid du Colombier 	Do=		253,
233e12c5d1SDavid du Colombier 	Dont=		254,
243e12c5d1SDavid du Colombier 	Iac=		255,
253e12c5d1SDavid du Colombier 
263e12c5d1SDavid du Colombier 	/* options */
273e12c5d1SDavid du Colombier 	Binary=		0,
283e12c5d1SDavid du Colombier 	Echo,
293e12c5d1SDavid du Colombier 	SGA,
303e12c5d1SDavid du Colombier 	Stat,
313e12c5d1SDavid du Colombier 	Timing,
323e12c5d1SDavid du Colombier 	Det,
333e12c5d1SDavid du Colombier 	Term,
343e12c5d1SDavid du Colombier 	EOR,
353e12c5d1SDavid du Colombier 	Uid,
363e12c5d1SDavid du Colombier 	Outmark,
373e12c5d1SDavid du Colombier 	Ttyloc,
383e12c5d1SDavid du Colombier 	M3270,
393e12c5d1SDavid du Colombier 	Padx3,
403e12c5d1SDavid du Colombier 	Window,
413e12c5d1SDavid du Colombier 	Speed,
423e12c5d1SDavid du Colombier 	Flow,
433e12c5d1SDavid du Colombier 	Line,
443e12c5d1SDavid du Colombier 	Xloc,
453e12c5d1SDavid du Colombier 	Extend,
463e12c5d1SDavid du Colombier };
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier struct Opt
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	char	*name;
513e12c5d1SDavid du Colombier 	int	code;
523e12c5d1SDavid du Colombier 	char	noway;
533e12c5d1SDavid du Colombier 	int	(*change)(Biobuf*, int);	/* routine for status change */
543e12c5d1SDavid du Colombier 	int	(*sub)(Biobuf*, uchar*, int n);	/* routine for subnegotiation */
553e12c5d1SDavid du Colombier 	char	remote;				/* remote value */
563e12c5d1SDavid du Colombier 	char	local;				/* local value */
573e12c5d1SDavid du Colombier };
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier Opt opt[] =
603e12c5d1SDavid du Colombier {
613e12c5d1SDavid du Colombier [Binary]	{ "binary",		0,  0, },
623e12c5d1SDavid du Colombier [Echo]		{ "echo",		1,  0, },
633e12c5d1SDavid du Colombier [SGA]		{ "suppress Go Ahead",	3,  0, },
643e12c5d1SDavid du Colombier [Stat]		{ "status",		5,  1, },
653e12c5d1SDavid du Colombier [Timing]	{ "timing",		6,  1, },
663e12c5d1SDavid du Colombier [Det]		{ "det",		20, 1, },
673e12c5d1SDavid du Colombier [Term]		{ "terminal",		24, 0, },
683e12c5d1SDavid du Colombier [EOR]		{ "end of record",	25, 1, },
693e12c5d1SDavid du Colombier [Uid]		{ "uid",		26, 1, },
703e12c5d1SDavid du Colombier [Outmark]	{ "outmark",		27, 1, },
713e12c5d1SDavid du Colombier [Ttyloc]	{ "ttyloc",		28, 1, },
723e12c5d1SDavid du Colombier [M3270]		{ "3270 mode",		29, 1, },
733e12c5d1SDavid du Colombier [Padx3]		{ "pad x.3",		30, 1, },
743e12c5d1SDavid du Colombier [Window]	{ "window size",	31, 1, },
753e12c5d1SDavid du Colombier [Speed]		{ "speed",		32, 1, },
763e12c5d1SDavid du Colombier [Flow]		{ "flow control",	33, 1, },
773e12c5d1SDavid du Colombier [Line]		{ "line mode",		34, 1, },
783e12c5d1SDavid du Colombier [Xloc]		{ "X display loc",	35, 0, },
793e12c5d1SDavid du Colombier [Extend]	{ "Extended",		255, 1, },
803e12c5d1SDavid du Colombier };
813e12c5d1SDavid du Colombier 
823e12c5d1SDavid du Colombier int	control(Biobuf*, int);
833e12c5d1SDavid du Colombier Opt*	findopt(int);
843e12c5d1SDavid du Colombier int	will(Biobuf*);
853e12c5d1SDavid du Colombier int	wont(Biobuf*);
863e12c5d1SDavid du Colombier int	doit(Biobuf*);
873e12c5d1SDavid du Colombier int	dont(Biobuf*);
883e12c5d1SDavid du Colombier int	sub(Biobuf*);
893e12c5d1SDavid du Colombier int	send2(int, int, int);
903e12c5d1SDavid du Colombier int	send3(int, int, int, int);
913e12c5d1SDavid du Colombier int	sendnote(int, char*);
923e12c5d1SDavid du Colombier void	fatal(char*, void*, void*);
933e12c5d1SDavid du Colombier char*	syserr(void);
943e12c5d1SDavid du Colombier int	wasintr(void);
953e12c5d1SDavid du Colombier long	iread(int, void*, int);
963e12c5d1SDavid du Colombier long	iwrite(int, void*, int);
973e12c5d1SDavid du Colombier void	binit(Biobuf*, int);
983e12c5d1SDavid du Colombier void	berase(Biobuf*);
993e12c5d1SDavid du Colombier void	bkill(Biobuf*);
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier /*
1023e12c5d1SDavid du Colombier  *  parse telnet control messages
1033e12c5d1SDavid du Colombier  */
1043e12c5d1SDavid du Colombier int
control(Biobuf * bp,int c)1053e12c5d1SDavid du Colombier control(Biobuf *bp, int c)
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	if(c < 0)
1083e12c5d1SDavid du Colombier 		return -1;
1093e12c5d1SDavid du Colombier 	switch(c){
1103e12c5d1SDavid du Colombier 	case AreYouThere:
1113e12c5d1SDavid du Colombier 		fprint(Bfildes(bp), "Plan 9 telnet, version 1\r\n");
1123e12c5d1SDavid du Colombier 		break;
1133e12c5d1SDavid du Colombier 	case Sb:
1143e12c5d1SDavid du Colombier 		return sub(bp);
1153e12c5d1SDavid du Colombier 	case Will:
1163e12c5d1SDavid du Colombier 		return will(bp);
1173e12c5d1SDavid du Colombier 	case Wont:
1183e12c5d1SDavid du Colombier 		return wont(bp);
1193e12c5d1SDavid du Colombier 	case Do:
1203e12c5d1SDavid du Colombier 		return doit(bp);
1213e12c5d1SDavid du Colombier 	case Dont:
1223e12c5d1SDavid du Colombier 		return dont(bp);
1233e12c5d1SDavid du Colombier 	case Se:
1243e12c5d1SDavid du Colombier 		fprint(2, "telnet: SE without an SB\n");
1253e12c5d1SDavid du Colombier 		break;
1263e12c5d1SDavid du Colombier 	default:
1273e12c5d1SDavid du Colombier 		break;
1283e12c5d1SDavid du Colombier 	}
1293e12c5d1SDavid du Colombier 	return 0;
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier Opt*
findopt(int c)1333e12c5d1SDavid du Colombier findopt(int c)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier 	Opt *o;
1363e12c5d1SDavid du Colombier 
1373e12c5d1SDavid du Colombier 	for(o = opt; o <= &opt[Extend]; o++)
1383e12c5d1SDavid du Colombier 		if(o->code == c)
1393e12c5d1SDavid du Colombier 			return o;
1403e12c5d1SDavid du Colombier 	return 0;
1413e12c5d1SDavid du Colombier }
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier int
will(Biobuf * bp)1443e12c5d1SDavid du Colombier will(Biobuf *bp)
1453e12c5d1SDavid du Colombier {
1463e12c5d1SDavid du Colombier 	Opt *o;
1473e12c5d1SDavid du Colombier 	int c;
1483e12c5d1SDavid du Colombier 	int rv = 0;
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier 	c = Bgetc(bp);
1513e12c5d1SDavid du Colombier 	if(c < 0)
1523e12c5d1SDavid du Colombier 		return -1;
1533e12c5d1SDavid du Colombier 	DPRINT(2, "will %d\n", c);
1543e12c5d1SDavid du Colombier 	o = findopt(c);
1553e12c5d1SDavid du Colombier 	if(o == 0){
1563e12c5d1SDavid du Colombier 		send3(Bfildes(bp), Iac, Dont, c);
1573e12c5d1SDavid du Colombier 		return 0;
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 	if(o->noway)
1603e12c5d1SDavid du Colombier 		send3(Bfildes(bp), Iac, Dont, c);
161bd389b36SDavid du Colombier 	else if(o->remote == 0)
1623e12c5d1SDavid du Colombier 		rv |= send3(Bfildes(bp), Iac, Do, c);
1633e12c5d1SDavid du Colombier 	if(o->remote == 0){
1643e12c5d1SDavid du Colombier 		if(o->change)
1653e12c5d1SDavid du Colombier 			rv |= (*o->change)(bp, Will);
1663e12c5d1SDavid du Colombier 	}
1673e12c5d1SDavid du Colombier 	o->remote = 1;
1683e12c5d1SDavid du Colombier 	return rv;
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier int
wont(Biobuf * bp)1723e12c5d1SDavid du Colombier wont(Biobuf *bp)
1733e12c5d1SDavid du Colombier {
1743e12c5d1SDavid du Colombier 	Opt *o;
1753e12c5d1SDavid du Colombier 	int c;
1763e12c5d1SDavid du Colombier 	int rv = 0;
1773e12c5d1SDavid du Colombier 
1783e12c5d1SDavid du Colombier 	c = Bgetc(bp);
1793e12c5d1SDavid du Colombier 	if(c < 0)
1803e12c5d1SDavid du Colombier 		return -1;
1813e12c5d1SDavid du Colombier 	DPRINT(2, "wont %d\n", c);
1823e12c5d1SDavid du Colombier 	o = findopt(c);
1833e12c5d1SDavid du Colombier 	if(o == 0)
1843e12c5d1SDavid du Colombier 		return 0;
1853e12c5d1SDavid du Colombier 	if(o->remote){
1863e12c5d1SDavid du Colombier 		if(o->change)
1873e12c5d1SDavid du Colombier 			rv |= (*o->change)(bp, Wont);
1883e12c5d1SDavid du Colombier 		rv |= send3(Bfildes(bp), Iac, Dont, c);
1893e12c5d1SDavid du Colombier 	}
1903e12c5d1SDavid du Colombier 	o->remote = 0;
1913e12c5d1SDavid du Colombier 	return rv;
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier int
doit(Biobuf * bp)1953e12c5d1SDavid du Colombier doit(Biobuf *bp)
1963e12c5d1SDavid du Colombier {
1973e12c5d1SDavid du Colombier 	Opt *o;
1983e12c5d1SDavid du Colombier 	int c;
1993e12c5d1SDavid du Colombier 	int rv = 0;
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier 	c = Bgetc(bp);
2023e12c5d1SDavid du Colombier 	if(c < 0)
2033e12c5d1SDavid du Colombier 		return -1;
2043e12c5d1SDavid du Colombier 	DPRINT(2, "do %d\n", c);
2053e12c5d1SDavid du Colombier 	o = findopt(c);
2063e12c5d1SDavid du Colombier 	if(o == 0 || o->noway){
2073e12c5d1SDavid du Colombier 		send3(Bfildes(bp), Iac, Wont, c);
2083e12c5d1SDavid du Colombier 		return 0;
2093e12c5d1SDavid du Colombier 	}
2103e12c5d1SDavid du Colombier 	if(o->noway)
2113e12c5d1SDavid du Colombier 		return 0;
2123e12c5d1SDavid du Colombier 	if(o->local == 0){
2133e12c5d1SDavid du Colombier 		if(o->change)
2143e12c5d1SDavid du Colombier 			rv |= (*o->change)(bp, Do);
2153e12c5d1SDavid du Colombier 		rv |= send3(Bfildes(bp), Iac, Will, c);
2163e12c5d1SDavid du Colombier 	}
2173e12c5d1SDavid du Colombier 	o->local = 1;
2183e12c5d1SDavid du Colombier 	return rv;
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier int
dont(Biobuf * bp)2223e12c5d1SDavid du Colombier dont(Biobuf *bp)
2233e12c5d1SDavid du Colombier {
2243e12c5d1SDavid du Colombier 	Opt *o;
2253e12c5d1SDavid du Colombier 	int c;
2263e12c5d1SDavid du Colombier 	int rv = 0;
2273e12c5d1SDavid du Colombier 
2283e12c5d1SDavid du Colombier 	c = Bgetc(bp);
2293e12c5d1SDavid du Colombier 	if(c < 0)
2303e12c5d1SDavid du Colombier 		return -1;
2313e12c5d1SDavid du Colombier 	DPRINT(2, "dont %d\n", c);
2323e12c5d1SDavid du Colombier 	o = findopt(c);
2333e12c5d1SDavid du Colombier 	if(o == 0)
2343e12c5d1SDavid du Colombier 		return 0;
2353e12c5d1SDavid du Colombier 	if(o->noway)
2363e12c5d1SDavid du Colombier 		return 0;
2373e12c5d1SDavid du Colombier 	if(o->local){
2383e12c5d1SDavid du Colombier 		o->local = 0;
2393e12c5d1SDavid du Colombier 		if(o->change)
2403e12c5d1SDavid du Colombier 			rv |= (*o->change)(bp, Dont);
2413e12c5d1SDavid du Colombier 		rv |= send3(Bfildes(bp), Iac, Wont, c);
2423e12c5d1SDavid du Colombier 	}
2433e12c5d1SDavid du Colombier 	o->local = 0;
2443e12c5d1SDavid du Colombier 	return rv;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier /* read in a subnegotiation message and pass it to a routine for that option */
2483e12c5d1SDavid du Colombier int
sub(Biobuf * bp)2493e12c5d1SDavid du Colombier sub(Biobuf *bp)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier 	uchar subneg[128];
2523e12c5d1SDavid du Colombier 	uchar *p;
2533e12c5d1SDavid du Colombier 	Opt *o;
2543e12c5d1SDavid du Colombier 	int c;
2553e12c5d1SDavid du Colombier 
2563e12c5d1SDavid du Colombier 	p = subneg;
2573e12c5d1SDavid du Colombier 	for(;;){
2583e12c5d1SDavid du Colombier 		c = Bgetc(bp);
2593e12c5d1SDavid du Colombier 		if(c == Iac){
2603e12c5d1SDavid du Colombier 			c = Bgetc(bp);
2613e12c5d1SDavid du Colombier 			if(c == Se)
2623e12c5d1SDavid du Colombier 				break;
2633e12c5d1SDavid du Colombier 			if(p < &subneg[sizeof(subneg)])
2643e12c5d1SDavid du Colombier 				*p++ = Iac;
2653e12c5d1SDavid du Colombier 		}
2663e12c5d1SDavid du Colombier 		if(c < 0)
2673e12c5d1SDavid du Colombier 			return -1;
2683e12c5d1SDavid du Colombier 		if(p < &subneg[sizeof(subneg)])
2693e12c5d1SDavid du Colombier 			*p++ = c;
2703e12c5d1SDavid du Colombier 	}
2713e12c5d1SDavid du Colombier 	if(p == subneg)
2723e12c5d1SDavid du Colombier 		return 0;
2737dd7cddfSDavid du Colombier 	DPRINT(2, "sub %d %d n = %d\n", subneg[0], subneg[1], (int)(p - subneg - 1));
2743e12c5d1SDavid du Colombier 	o = findopt(subneg[0]);
2753e12c5d1SDavid du Colombier 	if(o == 0 || o->sub == 0)
2763e12c5d1SDavid du Colombier 		return 0;
2773e12c5d1SDavid du Colombier 	return (*o->sub)(bp, subneg+1, p - subneg - 1);
2783e12c5d1SDavid du Colombier }
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier void
sendd(int c0,int c1)2813e12c5d1SDavid du Colombier sendd(int c0, int c1)
2823e12c5d1SDavid du Colombier {
2833e12c5d1SDavid du Colombier 	char *t = 0;
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier 	switch(c0){
2863e12c5d1SDavid du Colombier 	case Will:
2873e12c5d1SDavid du Colombier 		t = "Will";
2883e12c5d1SDavid du Colombier 		break;
2893e12c5d1SDavid du Colombier 	case Wont:
2903e12c5d1SDavid du Colombier 		t = "Wont";
2913e12c5d1SDavid du Colombier 		break;
2923e12c5d1SDavid du Colombier 	case Do:
2933e12c5d1SDavid du Colombier 		t = "Do";
2943e12c5d1SDavid du Colombier 		break;
2953e12c5d1SDavid du Colombier 	case Dont:
2963e12c5d1SDavid du Colombier 		t = "Dont";
2973e12c5d1SDavid du Colombier 		break;
2983e12c5d1SDavid du Colombier 	}
2993e12c5d1SDavid du Colombier 	if(t)
3003e12c5d1SDavid du Colombier 		DPRINT(2, "r %s %d\n", t, c1);
3013e12c5d1SDavid du Colombier }
3023e12c5d1SDavid du Colombier 
3033e12c5d1SDavid du Colombier int
send2(int f,int c0,int c1)3043e12c5d1SDavid du Colombier send2(int f, int c0, int c1)
3053e12c5d1SDavid du Colombier {
3063e12c5d1SDavid du Colombier 	uchar buf[2];
3073e12c5d1SDavid du Colombier 
3083e12c5d1SDavid du Colombier 	buf[0] = c0;
3093e12c5d1SDavid du Colombier 	buf[1] = c1;
3103e12c5d1SDavid du Colombier 	return iwrite(f, buf, 2) == 2 ? 0 : -1;
3113e12c5d1SDavid du Colombier }
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier int
send3(int f,int c0,int c1,int c2)3143e12c5d1SDavid du Colombier send3(int f, int c0, int c1, int c2)
3153e12c5d1SDavid du Colombier {
3163e12c5d1SDavid du Colombier 	uchar buf[3];
3173e12c5d1SDavid du Colombier 
3183e12c5d1SDavid du Colombier 	buf[0] = c0;
3193e12c5d1SDavid du Colombier 	buf[1] = c1;
3203e12c5d1SDavid du Colombier 	buf[2] = c2;
3213e12c5d1SDavid du Colombier 	sendd(c1, c2);
3223e12c5d1SDavid du Colombier 	return iwrite(f, buf, 3) == 3 ? 0 : -1;
3233e12c5d1SDavid du Colombier }
3243e12c5d1SDavid du Colombier 
3253e12c5d1SDavid du Colombier int
sendnote(int pid,char * msg)3263e12c5d1SDavid du Colombier sendnote(int pid, char *msg)
3273e12c5d1SDavid du Colombier {
3283e12c5d1SDavid du Colombier 	int fd;
3293e12c5d1SDavid du Colombier 	char name[128];
3303e12c5d1SDavid du Colombier 
3313e12c5d1SDavid du Colombier 	sprint(name, "/proc/%d/note", pid);
3323e12c5d1SDavid du Colombier 	fd = open(name, OWRITE);
3333e12c5d1SDavid du Colombier 	if(fd < 0)
3343e12c5d1SDavid du Colombier 		return -1;
3353e12c5d1SDavid du Colombier 	if(write(fd, msg, strlen(msg))!=strlen(msg))
3363e12c5d1SDavid du Colombier 		return -1;
3373e12c5d1SDavid du Colombier 	return close(fd);
3383e12c5d1SDavid du Colombier }
3393e12c5d1SDavid du Colombier 
3403e12c5d1SDavid du Colombier void
fatal(char * fmt,void * a0,void * a1)3413e12c5d1SDavid du Colombier fatal(char *fmt, void *a0, void *a1)
3423e12c5d1SDavid du Colombier {
3433e12c5d1SDavid du Colombier 	char buf[128];
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 	sprint(buf, fmt, a0, a1);
3467dd7cddfSDavid du Colombier 	fprint(2, "%s: %s\n", argv0, buf);
3473e12c5d1SDavid du Colombier 	exits(buf);
3483e12c5d1SDavid du Colombier }
3493e12c5d1SDavid du Colombier 
3503e12c5d1SDavid du Colombier char*
syserr(void)3513e12c5d1SDavid du Colombier syserr(void)
3523e12c5d1SDavid du Colombier {
353*9a747e4fSDavid du Colombier 	static char err[ERRMAX];
354*9a747e4fSDavid du Colombier 
355*9a747e4fSDavid du Colombier 	errstr(err, sizeof err);
3563e12c5d1SDavid du Colombier 	return err;
3573e12c5d1SDavid du Colombier }
3583e12c5d1SDavid du Colombier 
3593e12c5d1SDavid du Colombier int
wasintr(void)3603e12c5d1SDavid du Colombier wasintr(void)
3613e12c5d1SDavid du Colombier {
3623e12c5d1SDavid du Colombier 	return strcmp(syserr(), "interrupted") == 0;
3633e12c5d1SDavid du Colombier }
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier long
iread(int f,void * a,int n)3663e12c5d1SDavid du Colombier iread(int f, void *a, int n)
3673e12c5d1SDavid du Colombier {
3683e12c5d1SDavid du Colombier 	long m;
3693e12c5d1SDavid du Colombier 
3703e12c5d1SDavid du Colombier 	for(;;){
3713e12c5d1SDavid du Colombier 		m = read(f, a, n);
3723e12c5d1SDavid du Colombier 		if(m >= 0 || !wasintr())
3733e12c5d1SDavid du Colombier 			break;
3743e12c5d1SDavid du Colombier 	}
3753e12c5d1SDavid du Colombier 	return m;
3763e12c5d1SDavid du Colombier }
3773e12c5d1SDavid du Colombier 
3783e12c5d1SDavid du Colombier long
iwrite(int f,void * a,int n)3793e12c5d1SDavid du Colombier iwrite(int f, void *a, int n)
3803e12c5d1SDavid du Colombier {
3813e12c5d1SDavid du Colombier 	long m;
3823e12c5d1SDavid du Colombier 
3833e12c5d1SDavid du Colombier 	m = write(f, a, n);
3843e12c5d1SDavid du Colombier 	if(m < 0 && wasintr())
3853e12c5d1SDavid du Colombier 		return n;
3863e12c5d1SDavid du Colombier 	return m;
3873e12c5d1SDavid du Colombier }
388