output.c revision 17987
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.
353044Sdg *
3617987Speter *	$Id: output.c,v 1.2 1994/09/24 02:58:06 davidg Exp $
371556Srgrimes */
381556Srgrimes
391556Srgrimes#ifndef lint
4017987Speterstatic char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
411556Srgrimes#endif /* not lint */
421556Srgrimes
431556Srgrimes/*
441556Srgrimes * Shell output routines.  We use our own output routines because:
451556Srgrimes *	When a builtin command is interrupted we have to discard
461556Srgrimes *		any pending output.
471556Srgrimes *	When a builtin command appears in back quotes, we want to
481556Srgrimes *		save the output of the command in a region obtained
491556Srgrimes *		via malloc, rather than doing a fork and reading the
501556Srgrimes *		output of the command via a pipe.
511556Srgrimes *	Our output routines may be smaller than the stdio routines.
521556Srgrimes */
531556Srgrimes
5417987Speter#include <sys/ioctl.h>
5517987Speter
561556Srgrimes#include <stdio.h>	/* defines BUFSIZ */
5717987Speter#include <string.h>
581556Srgrimes#ifdef __STDC__
5917987Speter#include <stdarg.h>
601556Srgrimes#else
611556Srgrimes#include <varargs.h>
621556Srgrimes#endif
631556Srgrimes#include <errno.h>
6417987Speter#include <unistd.h>
6517987Speter#include <stdlib.h>
661556Srgrimes
6717987Speter#include "shell.h"
6817987Speter#include "syntax.h"
6917987Speter#include "output.h"
7017987Speter#include "memalloc.h"
7117987Speter#include "error.h"
721556Srgrimes
7317987Speter
741556Srgrimes#define OUTBUFSIZ BUFSIZ
751556Srgrimes#define BLOCK_OUT -2		/* output to a fixed block of memory */
761556Srgrimes#define MEM_OUT -3		/* output to dynamically allocated memory */
771556Srgrimes#define OUTPUT_ERR 01		/* error occurred on output */
781556Srgrimes
791556Srgrimes
801556Srgrimesstruct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
811556Srgrimesstruct output errout = {NULL, 0, NULL, 100, 2, 0};;
821556Srgrimesstruct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
831556Srgrimesstruct output *out1 = &output;
841556Srgrimesstruct output *out2 = &errout;
851556Srgrimes
861556Srgrimes
871556Srgrimes
881556Srgrimes#ifdef mkinit
891556Srgrimes
901556SrgrimesINCLUDE "output.h"
911556SrgrimesINCLUDE "memalloc.h"
921556Srgrimes
931556SrgrimesRESET {
941556Srgrimes	out1 = &output;
951556Srgrimes	out2 = &errout;
961556Srgrimes	if (memout.buf != NULL) {
971556Srgrimes		ckfree(memout.buf);
981556Srgrimes		memout.buf = NULL;
991556Srgrimes	}
1001556Srgrimes}
1011556Srgrimes
1021556Srgrimes#endif
1031556Srgrimes
1041556Srgrimes
1051556Srgrimes#ifdef notdef	/* no longer used */
1061556Srgrimes/*
1071556Srgrimes * Set up an output file to write to memory rather than a file.
1081556Srgrimes */
1091556Srgrimes
1101556Srgrimesvoid
1111556Srgrimesopen_mem(block, length, file)
1121556Srgrimes	char *block;
1131556Srgrimes	int length;
1141556Srgrimes	struct output *file;
1151556Srgrimes	{
1161556Srgrimes	file->nextc = block;
1171556Srgrimes	file->nleft = --length;
1181556Srgrimes	file->fd = BLOCK_OUT;
1191556Srgrimes	file->flags = 0;
1201556Srgrimes}
1211556Srgrimes#endif
1221556Srgrimes
1231556Srgrimes
1241556Srgrimesvoid
1251556Srgrimesout1str(p)
12617987Speter	const char *p;
1271556Srgrimes	{
1281556Srgrimes	outstr(p, out1);
1291556Srgrimes}
1301556Srgrimes
1311556Srgrimes
1321556Srgrimesvoid
1331556Srgrimesout2str(p)
13417987Speter	const char *p;
1351556Srgrimes	{
1361556Srgrimes	outstr(p, out2);
1371556Srgrimes}
1381556Srgrimes
1391556Srgrimes
1401556Srgrimesvoid
1411556Srgrimesoutstr(p, file)
14217987Speter	register const char *p;
1431556Srgrimes	register struct output *file;
1441556Srgrimes	{
1451556Srgrimes	while (*p)
1461556Srgrimes		outc(*p++, file);
1471556Srgrimes	if (file == out2)
1481556Srgrimes		flushout(file);
1491556Srgrimes}
1501556Srgrimes
1511556Srgrimes
1521556Srgrimeschar out_junk[16];
1531556Srgrimes
1541556Srgrimes
1551556Srgrimesvoid
1561556Srgrimesemptyoutbuf(dest)
1571556Srgrimes	struct output *dest;
1581556Srgrimes	{
1591556Srgrimes	int offset;
1601556Srgrimes
1611556Srgrimes	if (dest->fd == BLOCK_OUT) {
1621556Srgrimes		dest->nextc = out_junk;
1631556Srgrimes		dest->nleft = sizeof out_junk;
1641556Srgrimes		dest->flags |= OUTPUT_ERR;
1651556Srgrimes	} else if (dest->buf == NULL) {
1661556Srgrimes		INTOFF;
1671556Srgrimes		dest->buf = ckmalloc(dest->bufsize);
1681556Srgrimes		dest->nextc = dest->buf;
1691556Srgrimes		dest->nleft = dest->bufsize;
1701556Srgrimes		INTON;
1711556Srgrimes	} else if (dest->fd == MEM_OUT) {
1721556Srgrimes		offset = dest->bufsize;
1731556Srgrimes		INTOFF;
1741556Srgrimes		dest->bufsize <<= 1;
1751556Srgrimes		dest->buf = ckrealloc(dest->buf, dest->bufsize);
1761556Srgrimes		dest->nleft = dest->bufsize - offset;
1771556Srgrimes		dest->nextc = dest->buf + offset;
1781556Srgrimes		INTON;
1791556Srgrimes	} else {
1801556Srgrimes		flushout(dest);
1811556Srgrimes	}
1821556Srgrimes	dest->nleft--;
1831556Srgrimes}
1841556Srgrimes
1851556Srgrimes
1861556Srgrimesvoid
1871556Srgrimesflushall() {
1881556Srgrimes	flushout(&output);
1891556Srgrimes	flushout(&errout);
1901556Srgrimes}
1911556Srgrimes
1921556Srgrimes
1931556Srgrimesvoid
1941556Srgrimesflushout(dest)
1951556Srgrimes	struct output *dest;
1961556Srgrimes	{
1971556Srgrimes
1981556Srgrimes	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
1991556Srgrimes		return;
2001556Srgrimes	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
2011556Srgrimes		dest->flags |= OUTPUT_ERR;
2021556Srgrimes	dest->nextc = dest->buf;
2031556Srgrimes	dest->nleft = dest->bufsize;
2041556Srgrimes}
2051556Srgrimes
2061556Srgrimes
2071556Srgrimesvoid
2081556Srgrimesfreestdout() {
2091556Srgrimes	INTOFF;
2101556Srgrimes	if (output.buf) {
2111556Srgrimes		ckfree(output.buf);
2121556Srgrimes		output.buf = NULL;
2131556Srgrimes		output.nleft = 0;
2141556Srgrimes	}
2151556Srgrimes	INTON;
2161556Srgrimes}
2171556Srgrimes
2181556Srgrimes
2191556Srgrimes#ifdef __STDC__
2201556Srgrimesvoid
2211556Srgrimesoutfmt(struct output *file, char *fmt, ...) {
2221556Srgrimes	va_list ap;
2231556Srgrimes
2241556Srgrimes	va_start(ap, fmt);
2251556Srgrimes	doformat(file, fmt, ap);
2261556Srgrimes	va_end(ap);
2271556Srgrimes}
2281556Srgrimes
2291556Srgrimes
2301556Srgrimesvoid
2311556Srgrimesout1fmt(char *fmt, ...) {
2321556Srgrimes	va_list ap;
2331556Srgrimes
2341556Srgrimes	va_start(ap, fmt);
2351556Srgrimes	doformat(out1, fmt, ap);
2361556Srgrimes	va_end(ap);
2371556Srgrimes}
2381556Srgrimes
2391556Srgrimesvoid
2401556Srgrimesdprintf(char *fmt, ...) {
2411556Srgrimes	va_list ap;
2421556Srgrimes
2431556Srgrimes	va_start(ap, fmt);
2441556Srgrimes	doformat(out2, fmt, ap);
2451556Srgrimes	va_end(ap);
2461556Srgrimes	flushout(out2);
2471556Srgrimes}
2481556Srgrimes
2491556Srgrimesvoid
2501556Srgrimesfmtstr(char *outbuf, int length, char *fmt, ...) {
2511556Srgrimes	va_list ap;
2521556Srgrimes	struct output strout;
2531556Srgrimes
2541556Srgrimes	va_start(ap, fmt);
2551556Srgrimes	strout.nextc = outbuf;
2561556Srgrimes	strout.nleft = length;
2571556Srgrimes	strout.fd = BLOCK_OUT;
2581556Srgrimes	strout.flags = 0;
2591556Srgrimes	doformat(&strout, fmt, ap);
2601556Srgrimes	outc('\0', &strout);
2611556Srgrimes	if (strout.flags & OUTPUT_ERR)
2621556Srgrimes		outbuf[length - 1] = '\0';
2631556Srgrimes}
2641556Srgrimes
2651556Srgrimes#else /* not __STDC__ */
2661556Srgrimes
2671556Srgrimesvoid
2681556Srgrimesoutfmt(va_alist)
2691556Srgrimes	va_dcl
2701556Srgrimes	{
2711556Srgrimes	va_list ap;
2721556Srgrimes	struct output *file;
2731556Srgrimes	char *fmt;
2741556Srgrimes
2751556Srgrimes	va_start(ap);
2761556Srgrimes	file = va_arg(ap, struct output *);
2771556Srgrimes	fmt = va_arg(ap, char *);
2781556Srgrimes	doformat(file, fmt, ap);
2791556Srgrimes	va_end(ap);
2801556Srgrimes}
2811556Srgrimes
2821556Srgrimes
2831556Srgrimesvoid
2841556Srgrimesout1fmt(va_alist)
2851556Srgrimes	va_dcl
2861556Srgrimes	{
2871556Srgrimes	va_list ap;
2881556Srgrimes	char *fmt;
2891556Srgrimes
2901556Srgrimes	va_start(ap);
2911556Srgrimes	fmt = va_arg(ap, char *);
2921556Srgrimes	doformat(out1, fmt, ap);
2931556Srgrimes	va_end(ap);
2941556Srgrimes}
2951556Srgrimes
2961556Srgrimesvoid
2971556Srgrimesdprintf(va_alist)
2981556Srgrimes	va_dcl
2991556Srgrimes	{
3001556Srgrimes	va_list ap;
3011556Srgrimes	char *fmt;
3021556Srgrimes
3031556Srgrimes	va_start(ap);
3041556Srgrimes	fmt = va_arg(ap, char *);
3051556Srgrimes	doformat(out2, fmt, ap);
3061556Srgrimes	va_end(ap);
3071556Srgrimes	flushout(out2);
3081556Srgrimes}
3091556Srgrimes
3101556Srgrimesvoid
3111556Srgrimesfmtstr(va_alist)
3121556Srgrimes	va_dcl
3131556Srgrimes	{
3141556Srgrimes	va_list ap;
3151556Srgrimes	struct output strout;
3161556Srgrimes	char *outbuf;
3171556Srgrimes	int length;
3181556Srgrimes	char *fmt;
3191556Srgrimes
3201556Srgrimes	va_start(ap);
3211556Srgrimes	outbuf = va_arg(ap, char *);
3221556Srgrimes	length = va_arg(ap, int);
3231556Srgrimes	fmt = va_arg(ap, char *);
3241556Srgrimes	strout.nextc = outbuf;
3251556Srgrimes	strout.nleft = length;
3261556Srgrimes	strout.fd = BLOCK_OUT;
3271556Srgrimes	strout.flags = 0;
3281556Srgrimes	doformat(&strout, fmt, ap);
3291556Srgrimes	outc('\0', &strout);
3301556Srgrimes	if (strout.flags & OUTPUT_ERR)
3311556Srgrimes		outbuf[length - 1] = '\0';
3321556Srgrimes}
3331556Srgrimes#endif /* __STDC__ */
3341556Srgrimes
3351556Srgrimes
3361556Srgrimes/*
3371556Srgrimes * Formatted output.  This routine handles a subset of the printf formats:
3381556Srgrimes * - Formats supported: d, u, o, X, s, and c.
3391556Srgrimes * - The x format is also accepted but is treated like X.
3401556Srgrimes * - The l modifier is accepted.
3411556Srgrimes * - The - and # flags are accepted; # only works with the o format.
3421556Srgrimes * - Width and precision may be specified with any format except c.
3431556Srgrimes * - An * may be given for the width or precision.
3441556Srgrimes * - The obsolete practice of preceding the width with a zero to get
3451556Srgrimes *   zero padding is not supported; use the precision field.
3461556Srgrimes * - A % may be printed by writing %% in the format string.
3471556Srgrimes */
3481556Srgrimes
3491556Srgrimes#define TEMPSIZE 24
3501556Srgrimes
3511556Srgrimes#ifdef __STDC__
3521556Srgrimesstatic const char digit[16] = "0123456789ABCDEF";
3531556Srgrimes#else
3541556Srgrimesstatic const char digit[17] = "0123456789ABCDEF";
3551556Srgrimes#endif
3561556Srgrimes
3571556Srgrimes
3581556Srgrimesvoid
3591556Srgrimesdoformat(dest, f, ap)
3601556Srgrimes	register struct output *dest;
3611556Srgrimes	register char *f;		/* format string */
3621556Srgrimes	va_list ap;
3631556Srgrimes	{
3641556Srgrimes	register char c;
3651556Srgrimes	char temp[TEMPSIZE];
3661556Srgrimes	int flushleft;
3671556Srgrimes	int sharp;
3681556Srgrimes	int width;
3691556Srgrimes	int prec;
3701556Srgrimes	int islong;
3711556Srgrimes	char *p;
3721556Srgrimes	int sign;
3731556Srgrimes	long l;
3741556Srgrimes	unsigned long 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;
3901556Srgrimes		for (;;) {
3911556Srgrimes			if (*f == '-')
3921556Srgrimes				flushleft++;
3931556Srgrimes			else if (*f == '#')
3941556Srgrimes				sharp++;
3951556Srgrimes			else
3961556Srgrimes				break;
3971556Srgrimes			f++;
3981556Srgrimes		}
3991556Srgrimes		if (*f == '*') {
4001556Srgrimes			width = va_arg(ap, int);
4011556Srgrimes			f++;
4021556Srgrimes		} else {
4031556Srgrimes			while (is_digit(*f)) {
4041556Srgrimes				width = 10 * width + digit_val(*f++);
4051556Srgrimes			}
4061556Srgrimes		}
4071556Srgrimes		if (*f == '.') {
4081556Srgrimes			if (*++f == '*') {
4091556Srgrimes				prec = va_arg(ap, int);
4101556Srgrimes				f++;
4111556Srgrimes			} else {
4121556Srgrimes				prec = 0;
4131556Srgrimes				while (is_digit(*f)) {
4141556Srgrimes					prec = 10 * prec + digit_val(*f++);
4151556Srgrimes				}
4161556Srgrimes			}
4171556Srgrimes		}
4181556Srgrimes		if (*f == 'l') {
4191556Srgrimes			islong++;
4201556Srgrimes			f++;
4211556Srgrimes		}
4221556Srgrimes		switch (*f) {
4231556Srgrimes		case 'd':
4241556Srgrimes			if (islong)
4251556Srgrimes				l = va_arg(ap, long);
4261556Srgrimes			else
4271556Srgrimes				l = va_arg(ap, int);
4281556Srgrimes			sign = 0;
4291556Srgrimes			num = l;
4301556Srgrimes			if (l < 0) {
4311556Srgrimes				num = -l;
4321556Srgrimes				sign = 1;
4331556Srgrimes			}
4341556Srgrimes			base = 10;
4351556Srgrimes			goto number;
4361556Srgrimes		case 'u':
4371556Srgrimes			base = 10;
4381556Srgrimes			goto uns_number;
4391556Srgrimes		case 'o':
4401556Srgrimes			base = 8;
4411556Srgrimes			goto uns_number;
4421556Srgrimes		case 'x':
4431556Srgrimes			/* we don't implement 'x'; treat like 'X' */
4441556Srgrimes		case 'X':
4451556Srgrimes			base = 16;
4461556Srgrimesuns_number:	  /* an unsigned number */
4471556Srgrimes			sign = 0;
4481556Srgrimes			if (islong)
4491556Srgrimes				num = va_arg(ap, unsigned long);
4501556Srgrimes			else
4511556Srgrimes				num = va_arg(ap, unsigned int);
4521556Srgrimesnumber:		  /* process a number */
4531556Srgrimes			p = temp + TEMPSIZE - 1;
4541556Srgrimes			*p = '\0';
4551556Srgrimes			while (num) {
4561556Srgrimes				*--p = digit[num % base];
4571556Srgrimes				num /= base;
4581556Srgrimes			}
4591556Srgrimes			len = (temp + TEMPSIZE - 1) - p;
4601556Srgrimes			if (prec < 0)
4611556Srgrimes				prec = 1;
4621556Srgrimes			if (sharp && *f == 'o' && prec <= len)
4631556Srgrimes				prec = len + 1;
4641556Srgrimes			pad = 0;
4651556Srgrimes			if (width) {
4661556Srgrimes				size = len;
4671556Srgrimes				if (size < prec)
4681556Srgrimes					size = prec;
4691556Srgrimes				size += sign;
4701556Srgrimes				pad = width - size;
4711556Srgrimes				if (flushleft == 0) {
4721556Srgrimes					while (--pad >= 0)
4731556Srgrimes						outc(' ', dest);
4741556Srgrimes				}
4751556Srgrimes			}
4761556Srgrimes			if (sign)
4771556Srgrimes				outc('-', dest);
4781556Srgrimes			prec -= len;
4791556Srgrimes			while (--prec >= 0)
4801556Srgrimes				outc('0', dest);
4811556Srgrimes			while (*p)
4821556Srgrimes				outc(*p++, dest);
4831556Srgrimes			while (--pad >= 0)
4841556Srgrimes				outc(' ', dest);
4851556Srgrimes			break;
4861556Srgrimes		case 's':
4871556Srgrimes			p = va_arg(ap, char *);
4881556Srgrimes			pad = 0;
4891556Srgrimes			if (width) {
4901556Srgrimes				len = strlen(p);
4911556Srgrimes				if (prec >= 0 && len > prec)
4921556Srgrimes					len = prec;
4931556Srgrimes				pad = width - len;
4941556Srgrimes				if (flushleft == 0) {
4951556Srgrimes					while (--pad >= 0)
4961556Srgrimes						outc(' ', dest);
4971556Srgrimes				}
4981556Srgrimes			}
4991556Srgrimes			prec++;
5001556Srgrimes			while (--prec != 0 && *p)
5011556Srgrimes				outc(*p++, dest);
5021556Srgrimes			while (--pad >= 0)
5031556Srgrimes				outc(' ', dest);
5041556Srgrimes			break;
5051556Srgrimes		case 'c':
5061556Srgrimes			c = va_arg(ap, int);
5071556Srgrimes			outc(c, dest);
5081556Srgrimes			break;
5091556Srgrimes		default:
5101556Srgrimes			outc(*f, dest);
5111556Srgrimes			break;
5121556Srgrimes		}
5131556Srgrimes		f++;
5141556Srgrimes	}
5151556Srgrimes}
5161556Srgrimes
5171556Srgrimes
5181556Srgrimes
5191556Srgrimes/*
5201556Srgrimes * Version of write which resumes after a signal is caught.
5211556Srgrimes */
5221556Srgrimes
5231556Srgrimesint
5241556Srgrimesxwrite(fd, buf, nbytes)
5251556Srgrimes	int fd;
5261556Srgrimes	char *buf;
5271556Srgrimes	int nbytes;
5281556Srgrimes	{
5291556Srgrimes	int ntry;
5301556Srgrimes	int i;
5311556Srgrimes	int n;
5321556Srgrimes
5331556Srgrimes	n = nbytes;
5341556Srgrimes	ntry = 0;
5351556Srgrimes	for (;;) {
5361556Srgrimes		i = write(fd, buf, n);
5371556Srgrimes		if (i > 0) {
5381556Srgrimes			if ((n -= i) <= 0)
5391556Srgrimes				return nbytes;
5401556Srgrimes			buf += i;
5411556Srgrimes			ntry = 0;
5421556Srgrimes		} else if (i == 0) {
5431556Srgrimes			if (++ntry > 10)
5441556Srgrimes				return nbytes - n;
5451556Srgrimes		} else if (errno != EINTR) {
5461556Srgrimes			return -1;
5471556Srgrimes		}
5481556Srgrimes	}
5491556Srgrimes}
5501556Srgrimes
5511556Srgrimes
5521556Srgrimes/*
5531556Srgrimes * Version of ioctl that retries after a signal is caught.
55417987Speter * XXX unused function
5551556Srgrimes */
5561556Srgrimes
5571556Srgrimesint
55817987Speterxioctl(fd, request, arg)
55917987Speter	int fd;
56017987Speter	unsigned long request;
56117987Speter	char * arg;
56217987Speter{
5631556Srgrimes	int i;
5641556Srgrimes
5651556Srgrimes	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
5661556Srgrimes	return i;
5671556Srgrimes}
568