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