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