output.c revision 36150
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 3. All advertising materials mentioning features or use of this software
171556Srgrimes *    must display the following acknowledgement:
181556Srgrimes *	This product includes software developed by the University of
191556Srgrimes *	California, Berkeley and its contributors.
201556Srgrimes * 4. Neither the name of the University nor the names of its contributors
211556Srgrimes *    may be used to endorse or promote products derived from this software
221556Srgrimes *    without specific prior written permission.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341556Srgrimes * SUCH DAMAGE.
351556Srgrimes */
361556Srgrimes
371556Srgrimes#ifndef lint
3836150Scharnier#if 0
3936150Scharnierstatic char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
4036150Scharnier#endif
4136150Scharnierstatic const char rcsid[] =
4236150Scharnier	"$Id$";
431556Srgrimes#endif /* not lint */
441556Srgrimes
451556Srgrimes/*
461556Srgrimes * Shell output routines.  We use our own output routines because:
471556Srgrimes *	When a builtin command is interrupted we have to discard
481556Srgrimes *		any pending output.
491556Srgrimes *	When a builtin command appears in back quotes, we want to
501556Srgrimes *		save the output of the command in a region obtained
511556Srgrimes *		via malloc, rather than doing a fork and reading the
521556Srgrimes *		output of the command via a pipe.
531556Srgrimes *	Our output routines may be smaller than the stdio routines.
541556Srgrimes */
551556Srgrimes
5620425Ssteve#include <sys/types.h>        /* quad_t */
5717987Speter#include <sys/ioctl.h>
5817987Speter
591556Srgrimes#include <stdio.h>	/* defines BUFSIZ */
6017987Speter#include <string.h>
611556Srgrimes#ifdef __STDC__
6217987Speter#include <stdarg.h>
631556Srgrimes#else
641556Srgrimes#include <varargs.h>
651556Srgrimes#endif
661556Srgrimes#include <errno.h>
6717987Speter#include <unistd.h>
6817987Speter#include <stdlib.h>
691556Srgrimes
7017987Speter#include "shell.h"
7117987Speter#include "syntax.h"
7217987Speter#include "output.h"
7317987Speter#include "memalloc.h"
7417987Speter#include "error.h"
751556Srgrimes
7617987Speter
771556Srgrimes#define OUTBUFSIZ BUFSIZ
781556Srgrimes#define BLOCK_OUT -2		/* output to a fixed block of memory */
791556Srgrimes#define MEM_OUT -3		/* output to dynamically allocated memory */
801556Srgrimes#define OUTPUT_ERR 01		/* error occurred on output */
811556Srgrimes
821556Srgrimes
831556Srgrimesstruct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
8425232Sstevestruct output errout = {NULL, 0, NULL, 100, 2, 0};
851556Srgrimesstruct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
861556Srgrimesstruct output *out1 = &output;
871556Srgrimesstruct output *out2 = &errout;
881556Srgrimes
891556Srgrimes
901556Srgrimes
911556Srgrimes#ifdef mkinit
921556Srgrimes
931556SrgrimesINCLUDE "output.h"
941556SrgrimesINCLUDE "memalloc.h"
951556Srgrimes
961556SrgrimesRESET {
971556Srgrimes	out1 = &output;
981556Srgrimes	out2 = &errout;
991556Srgrimes	if (memout.buf != NULL) {
1001556Srgrimes		ckfree(memout.buf);
1011556Srgrimes		memout.buf = NULL;
1021556Srgrimes	}
1031556Srgrimes}
1041556Srgrimes
1051556Srgrimes#endif
1061556Srgrimes
1071556Srgrimes
1081556Srgrimes#ifdef notdef	/* no longer used */
1091556Srgrimes/*
1101556Srgrimes * Set up an output file to write to memory rather than a file.
1111556Srgrimes */
1121556Srgrimes
1131556Srgrimesvoid
1141556Srgrimesopen_mem(block, length, file)
1151556Srgrimes	char *block;
1161556Srgrimes	int length;
1171556Srgrimes	struct output *file;
1181556Srgrimes	{
1191556Srgrimes	file->nextc = block;
1201556Srgrimes	file->nleft = --length;
1211556Srgrimes	file->fd = BLOCK_OUT;
1221556Srgrimes	file->flags = 0;
1231556Srgrimes}
1241556Srgrimes#endif
1251556Srgrimes
1261556Srgrimes
1271556Srgrimesvoid
1281556Srgrimesout1str(p)
12917987Speter	const char *p;
1301556Srgrimes	{
1311556Srgrimes	outstr(p, out1);
1321556Srgrimes}
1331556Srgrimes
1341556Srgrimes
1351556Srgrimesvoid
1361556Srgrimesout2str(p)
13717987Speter	const char *p;
1381556Srgrimes	{
1391556Srgrimes	outstr(p, out2);
1401556Srgrimes}
1411556Srgrimes
1421556Srgrimes
1431556Srgrimesvoid
1441556Srgrimesoutstr(p, file)
14525232Ssteve	const char *p;
14625232Ssteve	struct output *file;
1471556Srgrimes	{
1481556Srgrimes	while (*p)
1491556Srgrimes		outc(*p++, file);
1501556Srgrimes	if (file == out2)
1511556Srgrimes		flushout(file);
1521556Srgrimes}
1531556Srgrimes
1541556Srgrimes
1551556Srgrimeschar out_junk[16];
1561556Srgrimes
1571556Srgrimes
1581556Srgrimesvoid
1591556Srgrimesemptyoutbuf(dest)
1601556Srgrimes	struct output *dest;
1611556Srgrimes	{
1621556Srgrimes	int offset;
1631556Srgrimes
1641556Srgrimes	if (dest->fd == BLOCK_OUT) {
1651556Srgrimes		dest->nextc = out_junk;
1661556Srgrimes		dest->nleft = sizeof out_junk;
1671556Srgrimes		dest->flags |= OUTPUT_ERR;
1681556Srgrimes	} else if (dest->buf == NULL) {
1691556Srgrimes		INTOFF;
1701556Srgrimes		dest->buf = ckmalloc(dest->bufsize);
1711556Srgrimes		dest->nextc = dest->buf;
1721556Srgrimes		dest->nleft = dest->bufsize;
1731556Srgrimes		INTON;
1741556Srgrimes	} else if (dest->fd == MEM_OUT) {
1751556Srgrimes		offset = dest->bufsize;
1761556Srgrimes		INTOFF;
1771556Srgrimes		dest->bufsize <<= 1;
1781556Srgrimes		dest->buf = ckrealloc(dest->buf, dest->bufsize);
1791556Srgrimes		dest->nleft = dest->bufsize - offset;
1801556Srgrimes		dest->nextc = dest->buf + offset;
1811556Srgrimes		INTON;
1821556Srgrimes	} else {
1831556Srgrimes		flushout(dest);
1841556Srgrimes	}
1851556Srgrimes	dest->nleft--;
1861556Srgrimes}
1871556Srgrimes
1881556Srgrimes
1891556Srgrimesvoid
1901556Srgrimesflushall() {
1911556Srgrimes	flushout(&output);
1921556Srgrimes	flushout(&errout);
1931556Srgrimes}
1941556Srgrimes
1951556Srgrimes
1961556Srgrimesvoid
1971556Srgrimesflushout(dest)
1981556Srgrimes	struct output *dest;
1991556Srgrimes	{
2001556Srgrimes
2011556Srgrimes	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
2021556Srgrimes		return;
2031556Srgrimes	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
2041556Srgrimes		dest->flags |= OUTPUT_ERR;
2051556Srgrimes	dest->nextc = dest->buf;
2061556Srgrimes	dest->nleft = dest->bufsize;
2071556Srgrimes}
2081556Srgrimes
2091556Srgrimes
2101556Srgrimesvoid
2111556Srgrimesfreestdout() {
2121556Srgrimes	INTOFF;
2131556Srgrimes	if (output.buf) {
2141556Srgrimes		ckfree(output.buf);
2151556Srgrimes		output.buf = NULL;
2161556Srgrimes		output.nleft = 0;
2171556Srgrimes	}
2181556Srgrimes	INTON;
2191556Srgrimes}
2201556Srgrimes
2211556Srgrimes
2221556Srgrimes#ifdef __STDC__
2231556Srgrimesvoid
2241556Srgrimesoutfmt(struct output *file, char *fmt, ...) {
2251556Srgrimes	va_list ap;
2261556Srgrimes
2271556Srgrimes	va_start(ap, fmt);
2281556Srgrimes	doformat(file, fmt, ap);
2291556Srgrimes	va_end(ap);
2301556Srgrimes}
2311556Srgrimes
2321556Srgrimes
2331556Srgrimesvoid
2341556Srgrimesout1fmt(char *fmt, ...) {
2351556Srgrimes	va_list ap;
2361556Srgrimes
2371556Srgrimes	va_start(ap, fmt);
2381556Srgrimes	doformat(out1, fmt, ap);
2391556Srgrimes	va_end(ap);
2401556Srgrimes}
2411556Srgrimes
2421556Srgrimesvoid
2431556Srgrimesdprintf(char *fmt, ...) {
2441556Srgrimes	va_list ap;
2451556Srgrimes
2461556Srgrimes	va_start(ap, fmt);
2471556Srgrimes	doformat(out2, fmt, ap);
2481556Srgrimes	va_end(ap);
2491556Srgrimes	flushout(out2);
2501556Srgrimes}
2511556Srgrimes
2521556Srgrimesvoid
2531556Srgrimesfmtstr(char *outbuf, int length, char *fmt, ...) {
2541556Srgrimes	va_list ap;
2551556Srgrimes	struct output strout;
2561556Srgrimes
2571556Srgrimes	va_start(ap, fmt);
2581556Srgrimes	strout.nextc = outbuf;
2591556Srgrimes	strout.nleft = length;
2601556Srgrimes	strout.fd = BLOCK_OUT;
2611556Srgrimes	strout.flags = 0;
2621556Srgrimes	doformat(&strout, fmt, ap);
2631556Srgrimes	outc('\0', &strout);
2641556Srgrimes	if (strout.flags & OUTPUT_ERR)
2651556Srgrimes		outbuf[length - 1] = '\0';
2661556Srgrimes}
2671556Srgrimes
2681556Srgrimes#else /* not __STDC__ */
2691556Srgrimes
2701556Srgrimesvoid
2711556Srgrimesoutfmt(va_alist)
2721556Srgrimes	va_dcl
2731556Srgrimes	{
2741556Srgrimes	va_list ap;
2751556Srgrimes	struct output *file;
2761556Srgrimes	char *fmt;
2771556Srgrimes
2781556Srgrimes	va_start(ap);
2791556Srgrimes	file = va_arg(ap, struct output *);
2801556Srgrimes	fmt = va_arg(ap, char *);
2811556Srgrimes	doformat(file, fmt, ap);
2821556Srgrimes	va_end(ap);
2831556Srgrimes}
2841556Srgrimes
2851556Srgrimes
2861556Srgrimesvoid
2871556Srgrimesout1fmt(va_alist)
2881556Srgrimes	va_dcl
2891556Srgrimes	{
2901556Srgrimes	va_list ap;
2911556Srgrimes	char *fmt;
2921556Srgrimes
2931556Srgrimes	va_start(ap);
2941556Srgrimes	fmt = va_arg(ap, char *);
2951556Srgrimes	doformat(out1, fmt, ap);
2961556Srgrimes	va_end(ap);
2971556Srgrimes}
2981556Srgrimes
2991556Srgrimesvoid
3001556Srgrimesdprintf(va_alist)
3011556Srgrimes	va_dcl
3021556Srgrimes	{
3031556Srgrimes	va_list ap;
3041556Srgrimes	char *fmt;
3051556Srgrimes
3061556Srgrimes	va_start(ap);
3071556Srgrimes	fmt = va_arg(ap, char *);
3081556Srgrimes	doformat(out2, fmt, ap);
3091556Srgrimes	va_end(ap);
3101556Srgrimes	flushout(out2);
3111556Srgrimes}
3121556Srgrimes
3131556Srgrimesvoid
3141556Srgrimesfmtstr(va_alist)
3151556Srgrimes	va_dcl
3161556Srgrimes	{
3171556Srgrimes	va_list ap;
3181556Srgrimes	struct output strout;
3191556Srgrimes	char *outbuf;
3201556Srgrimes	int length;
3211556Srgrimes	char *fmt;
3221556Srgrimes
3231556Srgrimes	va_start(ap);
3241556Srgrimes	outbuf = va_arg(ap, char *);
3251556Srgrimes	length = va_arg(ap, int);
3261556Srgrimes	fmt = va_arg(ap, char *);
3271556Srgrimes	strout.nextc = outbuf;
3281556Srgrimes	strout.nleft = length;
3291556Srgrimes	strout.fd = BLOCK_OUT;
3301556Srgrimes	strout.flags = 0;
3311556Srgrimes	doformat(&strout, fmt, ap);
3321556Srgrimes	outc('\0', &strout);
3331556Srgrimes	if (strout.flags & OUTPUT_ERR)
3341556Srgrimes		outbuf[length - 1] = '\0';
3351556Srgrimes}
3361556Srgrimes#endif /* __STDC__ */
3371556Srgrimes
3381556Srgrimes
3391556Srgrimes/*
3401556Srgrimes * Formatted output.  This routine handles a subset of the printf formats:
3411556Srgrimes * - Formats supported: d, u, o, X, s, and c.
3421556Srgrimes * - The x format is also accepted but is treated like X.
34320425Ssteve * - The l and q modifiers are accepted.
3441556Srgrimes * - The - and # flags are accepted; # only works with the o format.
3451556Srgrimes * - Width and precision may be specified with any format except c.
3461556Srgrimes * - An * may be given for the width or precision.
3471556Srgrimes * - The obsolete practice of preceding the width with a zero to get
3481556Srgrimes *   zero padding is not supported; use the precision field.
3491556Srgrimes * - A % may be printed by writing %% in the format string.
3501556Srgrimes */
3511556Srgrimes
3521556Srgrimes#define TEMPSIZE 24
3531556Srgrimes
35418018Speterstatic const char digit[] = "0123456789ABCDEF";
3551556Srgrimes
3561556Srgrimes
3571556Srgrimesvoid
3581556Srgrimesdoformat(dest, f, ap)
35925232Ssteve	struct output *dest;
36025232Ssteve	char *f;		/* format string */
3611556Srgrimes	va_list ap;
3621556Srgrimes	{
36325232Ssteve	char c;
3641556Srgrimes	char temp[TEMPSIZE];
3651556Srgrimes	int flushleft;
3661556Srgrimes	int sharp;
3671556Srgrimes	int width;
3681556Srgrimes	int prec;
3691556Srgrimes	int islong;
37018018Speter	int isquad;
3711556Srgrimes	char *p;
3721556Srgrimes	int sign;
37318018Speter	quad_t l;
37418018Speter	u_quad_t num;
3751556Srgrimes	unsigned base;
3761556Srgrimes	int len;
3771556Srgrimes	int size;
3781556Srgrimes	int pad;
3791556Srgrimes
3801556Srgrimes	while ((c = *f++) != '\0') {
3811556Srgrimes		if (c != '%') {
3821556Srgrimes			outc(c, dest);
3831556Srgrimes			continue;
3841556Srgrimes		}
3851556Srgrimes		flushleft = 0;
3861556Srgrimes		sharp = 0;
3871556Srgrimes		width = 0;
3881556Srgrimes		prec = -1;
3891556Srgrimes		islong = 0;
39018018Speter		isquad = 0;
3911556Srgrimes		for (;;) {
3921556Srgrimes			if (*f == '-')
3931556Srgrimes				flushleft++;
3941556Srgrimes			else if (*f == '#')
3951556Srgrimes				sharp++;
3961556Srgrimes			else
3971556Srgrimes				break;
3981556Srgrimes			f++;
3991556Srgrimes		}
4001556Srgrimes		if (*f == '*') {
4011556Srgrimes			width = va_arg(ap, int);
4021556Srgrimes			f++;
4031556Srgrimes		} else {
4041556Srgrimes			while (is_digit(*f)) {
4051556Srgrimes				width = 10 * width + digit_val(*f++);
4061556Srgrimes			}
4071556Srgrimes		}
4081556Srgrimes		if (*f == '.') {
4091556Srgrimes			if (*++f == '*') {
4101556Srgrimes				prec = va_arg(ap, int);
4111556Srgrimes				f++;
4121556Srgrimes			} else {
4131556Srgrimes				prec = 0;
4141556Srgrimes				while (is_digit(*f)) {
4151556Srgrimes					prec = 10 * prec + digit_val(*f++);
4161556Srgrimes				}
4171556Srgrimes			}
4181556Srgrimes		}
4191556Srgrimes		if (*f == 'l') {
4201556Srgrimes			islong++;
4211556Srgrimes			f++;
42218018Speter		} else if (*f == 'q') {
42318018Speter			isquad++;
42418018Speter			f++;
4251556Srgrimes		}
4261556Srgrimes		switch (*f) {
4271556Srgrimes		case 'd':
42820425Ssteve			if (isquad)
42920425Ssteve				l = va_arg(ap, quad_t);
43020425Ssteve			else if (islong)
4311556Srgrimes				l = va_arg(ap, long);
4321556Srgrimes			else
4331556Srgrimes				l = va_arg(ap, int);
4341556Srgrimes			sign = 0;
4351556Srgrimes			num = l;
4361556Srgrimes			if (l < 0) {
4371556Srgrimes				num = -l;
4381556Srgrimes				sign = 1;
4391556Srgrimes			}
4401556Srgrimes			base = 10;
4411556Srgrimes			goto number;
4421556Srgrimes		case 'u':
4431556Srgrimes			base = 10;
4441556Srgrimes			goto uns_number;
4451556Srgrimes		case 'o':
4461556Srgrimes			base = 8;
4471556Srgrimes			goto uns_number;
4481556Srgrimes		case 'x':
4491556Srgrimes			/* we don't implement 'x'; treat like 'X' */
4501556Srgrimes		case 'X':
4511556Srgrimes			base = 16;
4521556Srgrimesuns_number:	  /* an unsigned number */
4531556Srgrimes			sign = 0;
45420425Ssteve			if (isquad)
45520425Ssteve				num = va_arg(ap, u_quad_t);
45620425Ssteve			else if (islong)
4571556Srgrimes				num = va_arg(ap, unsigned long);
4581556Srgrimes			else
4591556Srgrimes				num = va_arg(ap, unsigned int);
4601556Srgrimesnumber:		  /* process a number */
4611556Srgrimes			p = temp + TEMPSIZE - 1;
4621556Srgrimes			*p = '\0';
4631556Srgrimes			while (num) {
4641556Srgrimes				*--p = digit[num % base];
4651556Srgrimes				num /= base;
4661556Srgrimes			}
4671556Srgrimes			len = (temp + TEMPSIZE - 1) - p;
4681556Srgrimes			if (prec < 0)
4691556Srgrimes				prec = 1;
4701556Srgrimes			if (sharp && *f == 'o' && prec <= len)
4711556Srgrimes				prec = len + 1;
4721556Srgrimes			pad = 0;
4731556Srgrimes			if (width) {
4741556Srgrimes				size = len;
4751556Srgrimes				if (size < prec)
4761556Srgrimes					size = prec;
4771556Srgrimes				size += sign;
4781556Srgrimes				pad = width - size;
4791556Srgrimes				if (flushleft == 0) {
4801556Srgrimes					while (--pad >= 0)
4811556Srgrimes						outc(' ', dest);
4821556Srgrimes				}
4831556Srgrimes			}
4841556Srgrimes			if (sign)
4851556Srgrimes				outc('-', dest);
4861556Srgrimes			prec -= len;
4871556Srgrimes			while (--prec >= 0)
4881556Srgrimes				outc('0', dest);
4891556Srgrimes			while (*p)
4901556Srgrimes				outc(*p++, dest);
4911556Srgrimes			while (--pad >= 0)
4921556Srgrimes				outc(' ', dest);
4931556Srgrimes			break;
4941556Srgrimes		case 's':
4951556Srgrimes			p = va_arg(ap, char *);
4961556Srgrimes			pad = 0;
4971556Srgrimes			if (width) {
4981556Srgrimes				len = strlen(p);
4991556Srgrimes				if (prec >= 0 && len > prec)
5001556Srgrimes					len = prec;
5011556Srgrimes				pad = width - len;
5021556Srgrimes				if (flushleft == 0) {
5031556Srgrimes					while (--pad >= 0)
5041556Srgrimes						outc(' ', dest);
5051556Srgrimes				}
5061556Srgrimes			}
5071556Srgrimes			prec++;
5081556Srgrimes			while (--prec != 0 && *p)
5091556Srgrimes				outc(*p++, dest);
5101556Srgrimes			while (--pad >= 0)
5111556Srgrimes				outc(' ', dest);
5121556Srgrimes			break;
5131556Srgrimes		case 'c':
5141556Srgrimes			c = va_arg(ap, int);
5151556Srgrimes			outc(c, dest);
5161556Srgrimes			break;
5171556Srgrimes		default:
5181556Srgrimes			outc(*f, dest);
5191556Srgrimes			break;
5201556Srgrimes		}
5211556Srgrimes		f++;
5221556Srgrimes	}
5231556Srgrimes}
5241556Srgrimes
5251556Srgrimes
5261556Srgrimes
5271556Srgrimes/*
5281556Srgrimes * Version of write which resumes after a signal is caught.
5291556Srgrimes */
5301556Srgrimes
5311556Srgrimesint
5321556Srgrimesxwrite(fd, buf, nbytes)
5331556Srgrimes	int fd;
5341556Srgrimes	char *buf;
5351556Srgrimes	int nbytes;
5361556Srgrimes	{
5371556Srgrimes	int ntry;
5381556Srgrimes	int i;
5391556Srgrimes	int n;
5401556Srgrimes
5411556Srgrimes	n = nbytes;
5421556Srgrimes	ntry = 0;
5431556Srgrimes	for (;;) {
5441556Srgrimes		i = write(fd, buf, n);
5451556Srgrimes		if (i > 0) {
5461556Srgrimes			if ((n -= i) <= 0)
5471556Srgrimes				return nbytes;
5481556Srgrimes			buf += i;
5491556Srgrimes			ntry = 0;
5501556Srgrimes		} else if (i == 0) {
5511556Srgrimes			if (++ntry > 10)
5521556Srgrimes				return nbytes - n;
5531556Srgrimes		} else if (errno != EINTR) {
5541556Srgrimes			return -1;
5551556Srgrimes		}
5561556Srgrimes	}
5571556Srgrimes}
5581556Srgrimes
5591556Srgrimes
5601556Srgrimes/*
5611556Srgrimes * Version of ioctl that retries after a signal is caught.
56217987Speter * XXX unused function
5631556Srgrimes */
5641556Srgrimes
5651556Srgrimesint
56620425Sstevexioctl(fd, request, arg)
56717987Speter	int fd;
56817987Speter	unsigned long request;
56917987Speter	char * arg;
57017987Speter{
5711556Srgrimes	int i;
5721556Srgrimes
5731556Srgrimes	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
5741556Srgrimes	return i;
5751556Srgrimes}
576