14b88c807SRodney W. Grimes /*- 24b88c807SRodney W. Grimes * Copyright (c) 1991, 1993 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Kenneth Almquist. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 174b88c807SRodney W. Grimes * must display the following acknowledgement: 184b88c807SRodney W. Grimes * This product includes software developed by the University of 194b88c807SRodney W. Grimes * California, Berkeley and its contributors. 204b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 354b88c807SRodney W. Grimes */ 364b88c807SRodney W. Grimes 374b88c807SRodney W. Grimes #ifndef lint 383d7b5b93SPhilippe Charnier #if 0 393d7b5b93SPhilippe Charnier static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; 403d7b5b93SPhilippe Charnier #endif 413d7b5b93SPhilippe Charnier static const char rcsid[] = 422a456239SPeter Wemm "$FreeBSD$"; 434b88c807SRodney W. Grimes #endif /* not lint */ 444b88c807SRodney W. Grimes 454b88c807SRodney W. Grimes /* 464b88c807SRodney W. Grimes * Shell output routines. We use our own output routines because: 474b88c807SRodney W. Grimes * When a builtin command is interrupted we have to discard 484b88c807SRodney W. Grimes * any pending output. 494b88c807SRodney W. Grimes * When a builtin command appears in back quotes, we want to 504b88c807SRodney W. Grimes * save the output of the command in a region obtained 514b88c807SRodney W. Grimes * via malloc, rather than doing a fork and reading the 524b88c807SRodney W. Grimes * output of the command via a pipe. 534b88c807SRodney W. Grimes * Our output routines may be smaller than the stdio routines. 544b88c807SRodney W. Grimes */ 554b88c807SRodney W. Grimes 564417f629SPeter Wemm #include <sys/types.h> /* quad_t */ 57ab0a2172SSteve Price #include <sys/ioctl.h> 58aa9caaf6SPeter Wemm 594b88c807SRodney W. Grimes #include <stdio.h> /* defines BUFSIZ */ 60aa9caaf6SPeter Wemm #include <string.h> 61aa9caaf6SPeter Wemm #include <stdarg.h> 62aa9caaf6SPeter Wemm #include <errno.h> 63aa9caaf6SPeter Wemm #include <unistd.h> 64aa9caaf6SPeter Wemm #include <stdlib.h> 65aa9caaf6SPeter Wemm 664b88c807SRodney W. Grimes #include "shell.h" 674b88c807SRodney W. Grimes #include "syntax.h" 684b88c807SRodney W. Grimes #include "output.h" 694b88c807SRodney W. Grimes #include "memalloc.h" 704b88c807SRodney W. Grimes #include "error.h" 71dee75cf7STim J. Robbins #include "var.h" 724b88c807SRodney W. Grimes 734b88c807SRodney W. Grimes 744b88c807SRodney W. Grimes #define OUTBUFSIZ BUFSIZ 754b88c807SRodney W. Grimes #define BLOCK_OUT -2 /* output to a fixed block of memory */ 764b88c807SRodney W. Grimes #define MEM_OUT -3 /* output to dynamically allocated memory */ 774b88c807SRodney W. Grimes #define OUTPUT_ERR 01 /* error occurred on output */ 784b88c807SRodney W. Grimes 794b88c807SRodney W. Grimes 804b88c807SRodney W. Grimes struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0}; 81f4eb55baSSteve Price struct output errout = {NULL, 0, NULL, 100, 2, 0}; 824b88c807SRodney W. Grimes struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0}; 834b88c807SRodney W. Grimes struct output *out1 = &output; 844b88c807SRodney W. Grimes struct output *out2 = &errout; 854b88c807SRodney W. Grimes 864b88c807SRodney W. Grimes 874b88c807SRodney W. Grimes 884b88c807SRodney W. Grimes #ifdef mkinit 894b88c807SRodney W. Grimes 904b88c807SRodney W. Grimes INCLUDE "output.h" 914b88c807SRodney W. Grimes INCLUDE "memalloc.h" 924b88c807SRodney W. Grimes 934b88c807SRodney W. Grimes RESET { 944b88c807SRodney W. Grimes out1 = &output; 954b88c807SRodney W. Grimes out2 = &errout; 964b88c807SRodney W. Grimes if (memout.buf != NULL) { 974b88c807SRodney W. Grimes ckfree(memout.buf); 984b88c807SRodney W. Grimes memout.buf = NULL; 994b88c807SRodney W. Grimes } 1004b88c807SRodney W. Grimes } 1014b88c807SRodney W. Grimes 1024b88c807SRodney W. Grimes #endif 1034b88c807SRodney W. Grimes 1044b88c807SRodney W. Grimes 1054b88c807SRodney W. Grimes void 1065134c3f7SWarner Losh out1str(const char *p) 1074b88c807SRodney W. Grimes { 1084b88c807SRodney W. Grimes outstr(p, out1); 1094b88c807SRodney W. Grimes } 1104b88c807SRodney W. Grimes 111e5341cbbSTim J. Robbins void 112e5341cbbSTim J. Robbins out1qstr(const char *p) 113e5341cbbSTim J. Robbins { 114e5341cbbSTim J. Robbins outqstr(p, out1); 115e5341cbbSTim J. Robbins } 1164b88c807SRodney W. Grimes 1174b88c807SRodney W. Grimes void 1185134c3f7SWarner Losh out2str(const char *p) 1194b88c807SRodney W. Grimes { 1204b88c807SRodney W. Grimes outstr(p, out2); 1214b88c807SRodney W. Grimes } 1224b88c807SRodney W. Grimes 123e5341cbbSTim J. Robbins void 124e5341cbbSTim J. Robbins out2qstr(const char *p) 125e5341cbbSTim J. Robbins { 126e5341cbbSTim J. Robbins outqstr(p, out2); 127e5341cbbSTim J. Robbins } 1284b88c807SRodney W. Grimes 1294b88c807SRodney W. Grimes void 1305134c3f7SWarner Losh outstr(const char *p, struct output *file) 1314b88c807SRodney W. Grimes { 1324b88c807SRodney W. Grimes while (*p) 1334b88c807SRodney W. Grimes outc(*p++, file); 1344b88c807SRodney W. Grimes if (file == out2) 1354b88c807SRodney W. Grimes flushout(file); 1364b88c807SRodney W. Grimes } 1374b88c807SRodney W. Grimes 138e5341cbbSTim J. Robbins /* Like outstr(), but quote for re-input into the shell. */ 139e5341cbbSTim J. Robbins void 140e5341cbbSTim J. Robbins outqstr(const char *p, struct output *file) 141e5341cbbSTim J. Robbins { 142e5341cbbSTim J. Robbins char ch; 143e5341cbbSTim J. Robbins 144dee75cf7STim J. Robbins if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() || 145dee75cf7STim J. Robbins p[strcspn(p, ifsval())] == '\0')) { 146dee75cf7STim J. Robbins outstr(p, file); 147dee75cf7STim J. Robbins return; 148dee75cf7STim J. Robbins } 149dee75cf7STim J. Robbins 150e5341cbbSTim J. Robbins out1c('\''); 151e5341cbbSTim J. Robbins while ((ch = *p++) != '\0') { 152e5341cbbSTim J. Robbins switch (ch) { 153e5341cbbSTim J. Robbins case '\'': 154e5341cbbSTim J. Robbins /* 155e5341cbbSTim J. Robbins * Can't quote single quotes inside single quotes; 156e5341cbbSTim J. Robbins * close them, write escaped single quote, open again. 157e5341cbbSTim J. Robbins */ 158e5341cbbSTim J. Robbins outstr("'\\''", file); 159e5341cbbSTim J. Robbins break; 160e5341cbbSTim J. Robbins default: 161e5341cbbSTim J. Robbins outc(ch, file); 162e5341cbbSTim J. Robbins } 163e5341cbbSTim J. Robbins } 164e5341cbbSTim J. Robbins out1c('\''); 165e5341cbbSTim J. Robbins } 1664b88c807SRodney W. Grimes 1674b88c807SRodney W. Grimes char out_junk[16]; 1684b88c807SRodney W. Grimes 1694b88c807SRodney W. Grimes void 1705134c3f7SWarner Losh emptyoutbuf(struct output *dest) 1714b88c807SRodney W. Grimes { 1724b88c807SRodney W. Grimes int offset; 1734b88c807SRodney W. Grimes 1744b88c807SRodney W. Grimes if (dest->fd == BLOCK_OUT) { 1754b88c807SRodney W. Grimes dest->nextc = out_junk; 1764b88c807SRodney W. Grimes dest->nleft = sizeof out_junk; 1774b88c807SRodney W. Grimes dest->flags |= OUTPUT_ERR; 1784b88c807SRodney W. Grimes } else if (dest->buf == NULL) { 1794b88c807SRodney W. Grimes INTOFF; 1804b88c807SRodney W. Grimes dest->buf = ckmalloc(dest->bufsize); 1814b88c807SRodney W. Grimes dest->nextc = dest->buf; 1824b88c807SRodney W. Grimes dest->nleft = dest->bufsize; 1834b88c807SRodney W. Grimes INTON; 1844b88c807SRodney W. Grimes } else if (dest->fd == MEM_OUT) { 1854b88c807SRodney W. Grimes offset = dest->bufsize; 1864b88c807SRodney W. Grimes INTOFF; 1874b88c807SRodney W. Grimes dest->bufsize <<= 1; 1884b88c807SRodney W. Grimes dest->buf = ckrealloc(dest->buf, dest->bufsize); 1894b88c807SRodney W. Grimes dest->nleft = dest->bufsize - offset; 1904b88c807SRodney W. Grimes dest->nextc = dest->buf + offset; 1914b88c807SRodney W. Grimes INTON; 1924b88c807SRodney W. Grimes } else { 1934b88c807SRodney W. Grimes flushout(dest); 1944b88c807SRodney W. Grimes } 1954b88c807SRodney W. Grimes dest->nleft--; 1964b88c807SRodney W. Grimes } 1974b88c807SRodney W. Grimes 1984b88c807SRodney W. Grimes 1994b88c807SRodney W. Grimes void 2005134c3f7SWarner Losh flushall(void) 2015134c3f7SWarner Losh { 2024b88c807SRodney W. Grimes flushout(&output); 2034b88c807SRodney W. Grimes flushout(&errout); 2044b88c807SRodney W. Grimes } 2054b88c807SRodney W. Grimes 2064b88c807SRodney W. Grimes 2074b88c807SRodney W. Grimes void 2085134c3f7SWarner Losh flushout(struct output *dest) 2094b88c807SRodney W. Grimes { 2104b88c807SRodney W. Grimes 2114b88c807SRodney W. Grimes if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0) 2124b88c807SRodney W. Grimes return; 2134b88c807SRodney W. Grimes if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0) 2144b88c807SRodney W. Grimes dest->flags |= OUTPUT_ERR; 2154b88c807SRodney W. Grimes dest->nextc = dest->buf; 2164b88c807SRodney W. Grimes dest->nleft = dest->bufsize; 2174b88c807SRodney W. Grimes } 2184b88c807SRodney W. Grimes 2194b88c807SRodney W. Grimes 2204b88c807SRodney W. Grimes void 2215134c3f7SWarner Losh freestdout(void) 2225134c3f7SWarner Losh { 2234b88c807SRodney W. Grimes INTOFF; 2244b88c807SRodney W. Grimes if (output.buf) { 2254b88c807SRodney W. Grimes ckfree(output.buf); 2264b88c807SRodney W. Grimes output.buf = NULL; 2274b88c807SRodney W. Grimes output.nleft = 0; 2284b88c807SRodney W. Grimes } 2294b88c807SRodney W. Grimes INTON; 2304b88c807SRodney W. Grimes } 2314b88c807SRodney W. Grimes 2324b88c807SRodney W. Grimes 2334b88c807SRodney W. Grimes void 2345134c3f7SWarner Losh outfmt(struct output *file, const char *fmt, ...) 2355134c3f7SWarner Losh { 2364b88c807SRodney W. Grimes va_list ap; 2374b88c807SRodney W. Grimes 2384b88c807SRodney W. Grimes va_start(ap, fmt); 2394b88c807SRodney W. Grimes doformat(file, fmt, ap); 2404b88c807SRodney W. Grimes va_end(ap); 2414b88c807SRodney W. Grimes } 2424b88c807SRodney W. Grimes 2434b88c807SRodney W. Grimes 2444b88c807SRodney W. Grimes void 2455134c3f7SWarner Losh out1fmt(const char *fmt, ...) 2465134c3f7SWarner Losh { 2474b88c807SRodney W. Grimes va_list ap; 2484b88c807SRodney W. Grimes 2494b88c807SRodney W. Grimes va_start(ap, fmt); 2504b88c807SRodney W. Grimes doformat(out1, fmt, ap); 2514b88c807SRodney W. Grimes va_end(ap); 2524b88c807SRodney W. Grimes } 2534b88c807SRodney W. Grimes 2544b88c807SRodney W. Grimes void 2555134c3f7SWarner Losh dprintf(const char *fmt, ...) 2565134c3f7SWarner Losh { 2574b88c807SRodney W. Grimes va_list ap; 2584b88c807SRodney W. Grimes 2594b88c807SRodney W. Grimes va_start(ap, fmt); 2604b88c807SRodney W. Grimes doformat(out2, fmt, ap); 2614b88c807SRodney W. Grimes va_end(ap); 2624b88c807SRodney W. Grimes flushout(out2); 2634b88c807SRodney W. Grimes } 2644b88c807SRodney W. Grimes 2654b88c807SRodney W. Grimes void 2665134c3f7SWarner Losh fmtstr(char *outbuf, int length, const char *fmt, ...) 2675134c3f7SWarner Losh { 2684b88c807SRodney W. Grimes va_list ap; 2694b88c807SRodney W. Grimes struct output strout; 2704b88c807SRodney W. Grimes 2714b88c807SRodney W. Grimes va_start(ap, fmt); 2724b88c807SRodney W. Grimes strout.nextc = outbuf; 2734b88c807SRodney W. Grimes strout.nleft = length; 2744b88c807SRodney W. Grimes strout.fd = BLOCK_OUT; 2754b88c807SRodney W. Grimes strout.flags = 0; 2764b88c807SRodney W. Grimes doformat(&strout, fmt, ap); 2774b88c807SRodney W. Grimes outc('\0', &strout); 2784b88c807SRodney W. Grimes if (strout.flags & OUTPUT_ERR) 2794b88c807SRodney W. Grimes outbuf[length - 1] = '\0'; 2804b88c807SRodney W. Grimes } 2814b88c807SRodney W. Grimes 2824b88c807SRodney W. Grimes /* 2834b88c807SRodney W. Grimes * Formatted output. This routine handles a subset of the printf formats: 2844b88c807SRodney W. Grimes * - Formats supported: d, u, o, X, s, and c. 2854b88c807SRodney W. Grimes * - The x format is also accepted but is treated like X. 286ab0a2172SSteve Price * - The l and q modifiers are accepted. 2874b88c807SRodney W. Grimes * - The - and # flags are accepted; # only works with the o format. 2884b88c807SRodney W. Grimes * - Width and precision may be specified with any format except c. 2894b88c807SRodney W. Grimes * - An * may be given for the width or precision. 2904b88c807SRodney W. Grimes * - The obsolete practice of preceding the width with a zero to get 2914b88c807SRodney W. Grimes * zero padding is not supported; use the precision field. 2924b88c807SRodney W. Grimes * - A % may be printed by writing %% in the format string. 2934b88c807SRodney W. Grimes */ 2944b88c807SRodney W. Grimes 2954b88c807SRodney W. Grimes #define TEMPSIZE 24 2964b88c807SRodney W. Grimes 2974417f629SPeter Wemm static const char digit[] = "0123456789ABCDEF"; 2984b88c807SRodney W. Grimes 2994b88c807SRodney W. Grimes 3004b88c807SRodney W. Grimes void 3015134c3f7SWarner Losh doformat(struct output *dest, const char *f, va_list ap) 3024b88c807SRodney W. Grimes { 303f4eb55baSSteve Price char c; 3044b88c807SRodney W. Grimes char temp[TEMPSIZE]; 3054b88c807SRodney W. Grimes int flushleft; 3064b88c807SRodney W. Grimes int sharp; 3074b88c807SRodney W. Grimes int width; 3084b88c807SRodney W. Grimes int prec; 3094b88c807SRodney W. Grimes int islong; 3104417f629SPeter Wemm int isquad; 3114b88c807SRodney W. Grimes char *p; 3124b88c807SRodney W. Grimes int sign; 3134417f629SPeter Wemm quad_t l; 3144417f629SPeter Wemm u_quad_t num; 3154b88c807SRodney W. Grimes unsigned base; 3164b88c807SRodney W. Grimes int len; 3174b88c807SRodney W. Grimes int size; 3184b88c807SRodney W. Grimes int pad; 3194b88c807SRodney W. Grimes 3204b88c807SRodney W. Grimes while ((c = *f++) != '\0') { 3214b88c807SRodney W. Grimes if (c != '%') { 3224b88c807SRodney W. Grimes outc(c, dest); 3234b88c807SRodney W. Grimes continue; 3244b88c807SRodney W. Grimes } 3254b88c807SRodney W. Grimes flushleft = 0; 3264b88c807SRodney W. Grimes sharp = 0; 3274b88c807SRodney W. Grimes width = 0; 3284b88c807SRodney W. Grimes prec = -1; 3294b88c807SRodney W. Grimes islong = 0; 3304417f629SPeter Wemm isquad = 0; 3314b88c807SRodney W. Grimes for (;;) { 3324b88c807SRodney W. Grimes if (*f == '-') 3334b88c807SRodney W. Grimes flushleft++; 3344b88c807SRodney W. Grimes else if (*f == '#') 3354b88c807SRodney W. Grimes sharp++; 3364b88c807SRodney W. Grimes else 3374b88c807SRodney W. Grimes break; 3384b88c807SRodney W. Grimes f++; 3394b88c807SRodney W. Grimes } 3404b88c807SRodney W. Grimes if (*f == '*') { 3414b88c807SRodney W. Grimes width = va_arg(ap, int); 3424b88c807SRodney W. Grimes f++; 3434b88c807SRodney W. Grimes } else { 3444b88c807SRodney W. Grimes while (is_digit(*f)) { 3454b88c807SRodney W. Grimes width = 10 * width + digit_val(*f++); 3464b88c807SRodney W. Grimes } 3474b88c807SRodney W. Grimes } 3484b88c807SRodney W. Grimes if (*f == '.') { 3494b88c807SRodney W. Grimes if (*++f == '*') { 3504b88c807SRodney W. Grimes prec = va_arg(ap, int); 3514b88c807SRodney W. Grimes f++; 3524b88c807SRodney W. Grimes } else { 3534b88c807SRodney W. Grimes prec = 0; 3544b88c807SRodney W. Grimes while (is_digit(*f)) { 3554b88c807SRodney W. Grimes prec = 10 * prec + digit_val(*f++); 3564b88c807SRodney W. Grimes } 3574b88c807SRodney W. Grimes } 3584b88c807SRodney W. Grimes } 3594b88c807SRodney W. Grimes if (*f == 'l') { 3604b88c807SRodney W. Grimes islong++; 3614b88c807SRodney W. Grimes f++; 3624417f629SPeter Wemm } else if (*f == 'q') { 3634417f629SPeter Wemm isquad++; 3644417f629SPeter Wemm f++; 3654b88c807SRodney W. Grimes } 3664b88c807SRodney W. Grimes switch (*f) { 3674b88c807SRodney W. Grimes case 'd': 368ab0a2172SSteve Price if (isquad) 3694417f629SPeter Wemm l = va_arg(ap, quad_t); 370ab0a2172SSteve Price else if (islong) 371ab0a2172SSteve Price l = va_arg(ap, long); 3724b88c807SRodney W. Grimes else 3734b88c807SRodney W. Grimes l = va_arg(ap, int); 3744b88c807SRodney W. Grimes sign = 0; 3754b88c807SRodney W. Grimes num = l; 3764b88c807SRodney W. Grimes if (l < 0) { 3774b88c807SRodney W. Grimes num = -l; 3784b88c807SRodney W. Grimes sign = 1; 3794b88c807SRodney W. Grimes } 3804b88c807SRodney W. Grimes base = 10; 3814b88c807SRodney W. Grimes goto number; 3824b88c807SRodney W. Grimes case 'u': 3834b88c807SRodney W. Grimes base = 10; 3844b88c807SRodney W. Grimes goto uns_number; 3854b88c807SRodney W. Grimes case 'o': 3864b88c807SRodney W. Grimes base = 8; 3874b88c807SRodney W. Grimes goto uns_number; 3884b88c807SRodney W. Grimes case 'x': 3894b88c807SRodney W. Grimes /* we don't implement 'x'; treat like 'X' */ 3904b88c807SRodney W. Grimes case 'X': 3914b88c807SRodney W. Grimes base = 16; 3924b88c807SRodney W. Grimes uns_number: /* an unsigned number */ 3934b88c807SRodney W. Grimes sign = 0; 394ab0a2172SSteve Price if (isquad) 3954417f629SPeter Wemm num = va_arg(ap, u_quad_t); 396ab0a2172SSteve Price else if (islong) 397ab0a2172SSteve Price num = va_arg(ap, unsigned long); 3984b88c807SRodney W. Grimes else 3994b88c807SRodney W. Grimes num = va_arg(ap, unsigned int); 4004b88c807SRodney W. Grimes number: /* process a number */ 4014b88c807SRodney W. Grimes p = temp + TEMPSIZE - 1; 4024b88c807SRodney W. Grimes *p = '\0'; 4034b88c807SRodney W. Grimes while (num) { 4044b88c807SRodney W. Grimes *--p = digit[num % base]; 4054b88c807SRodney W. Grimes num /= base; 4064b88c807SRodney W. Grimes } 4074b88c807SRodney W. Grimes len = (temp + TEMPSIZE - 1) - p; 4084b88c807SRodney W. Grimes if (prec < 0) 4094b88c807SRodney W. Grimes prec = 1; 4104b88c807SRodney W. Grimes if (sharp && *f == 'o' && prec <= len) 4114b88c807SRodney W. Grimes prec = len + 1; 4124b88c807SRodney W. Grimes pad = 0; 4134b88c807SRodney W. Grimes if (width) { 4144b88c807SRodney W. Grimes size = len; 4154b88c807SRodney W. Grimes if (size < prec) 4164b88c807SRodney W. Grimes size = prec; 4174b88c807SRodney W. Grimes size += sign; 4184b88c807SRodney W. Grimes pad = width - size; 4194b88c807SRodney W. Grimes if (flushleft == 0) { 4204b88c807SRodney W. Grimes while (--pad >= 0) 4214b88c807SRodney W. Grimes outc(' ', dest); 4224b88c807SRodney W. Grimes } 4234b88c807SRodney W. Grimes } 4244b88c807SRodney W. Grimes if (sign) 4254b88c807SRodney W. Grimes outc('-', dest); 4264b88c807SRodney W. Grimes prec -= len; 4274b88c807SRodney W. Grimes while (--prec >= 0) 4284b88c807SRodney W. Grimes outc('0', dest); 4294b88c807SRodney W. Grimes while (*p) 4304b88c807SRodney W. Grimes outc(*p++, dest); 4314b88c807SRodney W. Grimes while (--pad >= 0) 4324b88c807SRodney W. Grimes outc(' ', dest); 4334b88c807SRodney W. Grimes break; 4344b88c807SRodney W. Grimes case 's': 4354b88c807SRodney W. Grimes p = va_arg(ap, char *); 4364b88c807SRodney W. Grimes pad = 0; 4374b88c807SRodney W. Grimes if (width) { 4384b88c807SRodney W. Grimes len = strlen(p); 4394b88c807SRodney W. Grimes if (prec >= 0 && len > prec) 4404b88c807SRodney W. Grimes len = prec; 4414b88c807SRodney W. Grimes pad = width - len; 4424b88c807SRodney W. Grimes if (flushleft == 0) { 4434b88c807SRodney W. Grimes while (--pad >= 0) 4444b88c807SRodney W. Grimes outc(' ', dest); 4454b88c807SRodney W. Grimes } 4464b88c807SRodney W. Grimes } 4474b88c807SRodney W. Grimes prec++; 4484b88c807SRodney W. Grimes while (--prec != 0 && *p) 4494b88c807SRodney W. Grimes outc(*p++, dest); 4504b88c807SRodney W. Grimes while (--pad >= 0) 4514b88c807SRodney W. Grimes outc(' ', dest); 4524b88c807SRodney W. Grimes break; 4534b88c807SRodney W. Grimes case 'c': 4544b88c807SRodney W. Grimes c = va_arg(ap, int); 4554b88c807SRodney W. Grimes outc(c, dest); 4564b88c807SRodney W. Grimes break; 4574b88c807SRodney W. Grimes default: 4584b88c807SRodney W. Grimes outc(*f, dest); 4594b88c807SRodney W. Grimes break; 4604b88c807SRodney W. Grimes } 4614b88c807SRodney W. Grimes f++; 4624b88c807SRodney W. Grimes } 4634b88c807SRodney W. Grimes } 4644b88c807SRodney W. Grimes 4654b88c807SRodney W. Grimes 4664b88c807SRodney W. Grimes 4674b88c807SRodney W. Grimes /* 4684b88c807SRodney W. Grimes * Version of write which resumes after a signal is caught. 4694b88c807SRodney W. Grimes */ 4704b88c807SRodney W. Grimes 4714b88c807SRodney W. Grimes int 4725134c3f7SWarner Losh xwrite(int fd, char *buf, int nbytes) 4734b88c807SRodney W. Grimes { 4744b88c807SRodney W. Grimes int ntry; 4754b88c807SRodney W. Grimes int i; 4764b88c807SRodney W. Grimes int n; 4774b88c807SRodney W. Grimes 4784b88c807SRodney W. Grimes n = nbytes; 4794b88c807SRodney W. Grimes ntry = 0; 4804b88c807SRodney W. Grimes for (;;) { 4814b88c807SRodney W. Grimes i = write(fd, buf, n); 4824b88c807SRodney W. Grimes if (i > 0) { 4834b88c807SRodney W. Grimes if ((n -= i) <= 0) 4844b88c807SRodney W. Grimes return nbytes; 4854b88c807SRodney W. Grimes buf += i; 4864b88c807SRodney W. Grimes ntry = 0; 4874b88c807SRodney W. Grimes } else if (i == 0) { 4884b88c807SRodney W. Grimes if (++ntry > 10) 4894b88c807SRodney W. Grimes return nbytes - n; 4904b88c807SRodney W. Grimes } else if (errno != EINTR) { 4914b88c807SRodney W. Grimes return -1; 4924b88c807SRodney W. Grimes } 4934b88c807SRodney W. Grimes } 4944b88c807SRodney W. Grimes } 495