1 /* 2 * sh.print.c: Primitive Output routines. 3 */ 4 /*- 5 * Copyright (c) 1980, 1991 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 #include "sh.h" 33 #include "ed.h" 34 35 extern int Tty_eight_bit; 36 37 int lbuffed = 1; /* true if line buffered */ 38 39 static void p2dig (unsigned int); 40 41 /* 42 * C Shell 43 */ 44 45 #if defined(BSDLIMIT) || defined(RLIMIT_CPU) 46 void 47 psecs(unsigned long l) 48 { 49 int i; 50 51 i = (int) (l / 3600); 52 if (i) { 53 xprintf("%d:", i); 54 i = (int) (l % 3600); 55 p2dig(i / 60); 56 goto minsec; 57 } 58 i = (int) l; 59 xprintf("%d", i / 60); 60 minsec: 61 i %= 60; 62 xprintf(":"); 63 p2dig(i); 64 } 65 66 #endif 67 68 void /* PWP: print mm:ss.dd, l is in sec*100 */ 69 #ifdef BSDTIMES 70 pcsecs(unsigned long l) 71 #else /* BSDTIMES */ 72 # ifndef POSIX 73 pcsecs(time_t l) 74 # else /* POSIX */ 75 pcsecs(clock_t l) 76 # endif /* POSIX */ 77 #endif /* BSDTIMES */ 78 { 79 int i; 80 81 i = (int) (l / 360000); 82 if (i) { 83 xprintf("%d:", i); 84 i = (int) ((l % 360000) / 100); 85 p2dig(i / 60); 86 goto minsec; 87 } 88 i = (int) (l / 100); 89 xprintf("%d", i / 60); 90 minsec: 91 i %= 60; 92 xprintf(":"); 93 p2dig(i); 94 xprintf("."); 95 p2dig((int) (l % 100)); 96 } 97 98 static void 99 p2dig(unsigned i) 100 { 101 102 xprintf("%u%u", i / 10, i % 10); 103 } 104 105 char linbuf[2048]; /* was 128 */ 106 char *linp = linbuf; 107 int output_raw = 0; /* PWP */ 108 int xlate_cr = 0; /* HE */ 109 110 /* For cleanup_push() */ 111 void 112 output_raw_restore(void *xorig) 113 { 114 int *orig; 115 116 orig = xorig; 117 output_raw = *orig; 118 } 119 120 #ifdef WIDE_STRINGS 121 void 122 putwraw(Char c) 123 { 124 char buf[MB_LEN_MAX]; 125 size_t i, len; 126 127 len = one_wctomb(buf, c & CHAR); 128 for (i = 0; i < len; i++) 129 putraw((unsigned char)buf[i] | (c & ~CHAR)); 130 } 131 132 void 133 xputwchar(Char c) 134 { 135 char buf[MB_LEN_MAX]; 136 size_t i, len; 137 138 len = one_wctomb(buf, c & CHAR); 139 for (i = 0; i < len; i++) 140 xputchar((unsigned char)buf[i] | (c & ~CHAR)); 141 } 142 #endif 143 144 void 145 xputchar(int c) 146 { 147 int atr; 148 149 atr = c & ATTRIBUTES & TRIM; 150 c &= CHAR | QUOTE; 151 if (!output_raw && (c & QUOTE) == 0) { 152 if (iscntrl(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) { 153 if (c != '\t' && c != '\n' 154 #ifdef COLORCAT 155 && !(adrof(STRcolorcat) && c == CTL_ESC('\033')) 156 #endif 157 && (xlate_cr || c != '\r')) 158 { 159 xputchar('^' | atr); 160 if (c == CTL_ESC('\177')) 161 c = '?'; 162 else 163 /* Note: for IS_ASCII, this compiles to: c = c | 0100 */ 164 c = CTL_ESC(ASC(c)|0100); 165 } 166 } 167 else if (!isprint(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) { 168 xputchar('\\' | atr); 169 xputchar((((c >> 6) & 7) + '0') | atr); 170 xputchar((((c >> 3) & 7) + '0') | atr); 171 c = (c & 7) + '0'; 172 } 173 (void) putraw(c | atr); 174 } 175 else { 176 c &= TRIM; 177 if (haderr ? (didfds ? is2atty : isdiagatty) : 178 (didfds ? is1atty : isoutatty)) 179 SetAttributes(c | atr); 180 (void) putpure(c); 181 } 182 if (lbuffed && (c & CHAR) == '\n') 183 flush(); 184 } 185 186 int 187 putraw(int c) 188 { 189 if (haderr ? (didfds ? is2atty : isdiagatty) : 190 (didfds ? is1atty : isoutatty)) { 191 if (Tty_eight_bit == -1) 192 ed_set_tty_eight_bit(); 193 if (!Tty_eight_bit && (c & META)) { 194 c = (c & ~META) | STANDOUT; 195 } 196 SetAttributes(c); 197 } 198 return putpure(c); 199 } 200 201 int 202 putpure(int c) 203 { 204 c &= CHAR; 205 206 *linp++ = (char) c; 207 if (linp >= &linbuf[sizeof linbuf - 10]) 208 flush(); 209 return (1); 210 } 211 212 void 213 drainoline(void) 214 { 215 linp = linbuf; 216 } 217 218 void 219 flush(void) 220 { 221 int unit, oldexitset = exitset; 222 static int interrupted = 0; 223 224 /* int lmode; */ 225 226 if (linp == linbuf) 227 return; 228 if (GettingInput && !Tty_raw_mode && linp < &linbuf[sizeof linbuf - 10]) 229 return; 230 if (handle_interrupt) 231 exitset = 1; 232 233 if (interrupted) { 234 interrupted = 0; 235 linp = linbuf; /* avoid recursion as stderror calls flush */ 236 if (handle_interrupt) 237 fixerror(); 238 else 239 stderror(ERR_SILENT); 240 } 241 interrupted = 1; 242 if (haderr) 243 unit = didfds ? 2 : SHDIAG; 244 else 245 unit = didfds ? 1 : SHOUT; 246 #ifdef COMMENT 247 #ifdef TIOCLGET 248 if (didfds == 0 && ioctl(unit, TIOCLGET, (ioctl_t) & lmode) == 0 && 249 lmode & LFLUSHO) { 250 lmode = LFLUSHO; 251 (void) ioctl(unit, TIOCLBIC, (ioclt_t) & lmode); 252 (void) xwrite(unit, "\n", 1); 253 } 254 #endif 255 #endif 256 if (xwrite(unit, linbuf, linp - linbuf) == -1) 257 switch (errno) { 258 #ifdef EIO 259 /* We lost our tty */ 260 case EIO: 261 #endif 262 #ifdef ENXIO 263 /* 264 * Deal with Digital Unix 4.0D bogocity, returning ENXIO when 265 * we lose our tty. 266 */ 267 case ENXIO: 268 #endif 269 /* 270 * IRIX 6.4 bogocity? 271 */ 272 #ifdef ENOTTY 273 case ENOTTY: 274 #endif 275 #ifdef EBADF 276 case EBADF: 277 #endif 278 #ifdef ESTALE 279 /* 280 * Lost our file descriptor, exit (IRIS4D) 281 */ 282 case ESTALE: 283 #endif 284 #ifdef ENOENT 285 /* 286 * Deal with SoFS bogocity: returns ENOENT instead of ESTALE. 287 */ 288 case ENOENT: 289 #endif 290 /* 291 * Over our quota, writing the history file 292 */ 293 #ifdef EDQUOT 294 case EDQUOT: 295 #endif 296 /* Nothing to do, but die */ 297 if (handle_interrupt == 0) 298 xexit(1); 299 /*FALLTHROUGH*/ 300 default: 301 if (handle_interrupt) 302 fixerror(); 303 else 304 stderror(ERR_SILENT); 305 break; 306 } 307 308 exitset = oldexitset; 309 linp = linbuf; 310 interrupted = 0; 311 } 312