159243Sobrien/* 259243Sobrien * sh.print.c: Primitive Output routines. 359243Sobrien */ 459243Sobrien/*- 559243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 659243Sobrien * All rights reserved. 759243Sobrien * 859243Sobrien * Redistribution and use in source and binary forms, with or without 959243Sobrien * modification, are permitted provided that the following conditions 1059243Sobrien * are met: 1159243Sobrien * 1. Redistributions of source code must retain the above copyright 1259243Sobrien * notice, this list of conditions and the following disclaimer. 1359243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1459243Sobrien * notice, this list of conditions and the following disclaimer in the 1559243Sobrien * documentation and/or other materials provided with the distribution. 16100616Smp * 3. Neither the name of the University nor the names of its contributors 1759243Sobrien * may be used to endorse or promote products derived from this software 1859243Sobrien * without specific prior written permission. 1959243Sobrien * 2059243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059243Sobrien * SUCH DAMAGE. 3159243Sobrien */ 3259243Sobrien#include "sh.h" 3359243Sobrien#include "ed.h" 3459243Sobrien 3559243Sobrienextern int Tty_eight_bit; 3659243Sobrien 3759243Sobrienint lbuffed = 1; /* true if line buffered */ 3859243Sobrien 39167465Smpstatic void p2dig (unsigned int); 4059243Sobrien 4159243Sobrien/* 4259243Sobrien * C Shell 4359243Sobrien */ 4459243Sobrien 4559243Sobrien#if defined(BSDLIMIT) || defined(RLIMIT_CPU) 4659243Sobrienvoid 47167465Smppsecs(unsigned long l) 4859243Sobrien{ 49145479Smp int i; 5059243Sobrien 5159243Sobrien i = (int) (l / 3600); 5259243Sobrien if (i) { 5359243Sobrien xprintf("%d:", i); 5459243Sobrien i = (int) (l % 3600); 5559243Sobrien p2dig(i / 60); 5659243Sobrien goto minsec; 5759243Sobrien } 5859243Sobrien i = (int) l; 5959243Sobrien xprintf("%d", i / 60); 6059243Sobrienminsec: 6159243Sobrien i %= 60; 6259243Sobrien xprintf(":"); 6359243Sobrien p2dig(i); 6459243Sobrien} 6559243Sobrien 6659243Sobrien#endif 6759243Sobrien 68167465Smpvoid /* PWP: print mm:ss.dd, l is in sec*100 */ 6959243Sobrien#ifdef BSDTIMES 70167465Smppcsecs(unsigned long l) 7159243Sobrien#else /* BSDTIMES */ 7259243Sobrien# ifndef POSIX 73167465Smppcsecs(time_t l) 7459243Sobrien# else /* POSIX */ 75167465Smppcsecs(clock_t l) 7659243Sobrien# endif /* POSIX */ 7759243Sobrien#endif /* BSDTIMES */ 7859243Sobrien{ 79145479Smp int i; 8059243Sobrien 8159243Sobrien i = (int) (l / 360000); 8259243Sobrien if (i) { 8359243Sobrien xprintf("%d:", i); 8459243Sobrien i = (int) ((l % 360000) / 100); 8559243Sobrien p2dig(i / 60); 8659243Sobrien goto minsec; 8759243Sobrien } 8859243Sobrien i = (int) (l / 100); 8959243Sobrien xprintf("%d", i / 60); 9059243Sobrienminsec: 9159243Sobrien i %= 60; 9259243Sobrien xprintf(":"); 9359243Sobrien p2dig(i); 9459243Sobrien xprintf("."); 9559243Sobrien p2dig((int) (l % 100)); 9659243Sobrien} 9759243Sobrien 9859243Sobrienstatic void 99167465Smpp2dig(unsigned i) 10059243Sobrien{ 10159243Sobrien 102145479Smp xprintf("%u%u", i / 10, i % 10); 10359243Sobrien} 10459243Sobrien 10559243Sobrienchar linbuf[2048]; /* was 128 */ 10659243Sobrienchar *linp = linbuf; 107145479Smpint output_raw = 0; /* PWP */ 108145479Smpint xlate_cr = 0; /* HE */ 10959243Sobrien 110167465Smp/* For cleanup_push() */ 111167465Smpvoid 112167465Smpoutput_raw_restore(void *xorig) 113167465Smp{ 114167465Smp int *orig; 115167465Smp 116167465Smp orig = xorig; 117167465Smp output_raw = *orig; 118167465Smp} 119167465Smp 120145479Smp#ifdef WIDE_STRINGS 12159243Sobrienvoid 122145479Smpputwraw(Char c) 123145479Smp{ 124145479Smp char buf[MB_LEN_MAX]; 125145479Smp size_t i, len; 126145479Smp 127145479Smp len = one_wctomb(buf, c & CHAR); 128145479Smp for (i = 0; i < len; i++) 129145479Smp putraw((unsigned char)buf[i] | (c & ~CHAR)); 130145479Smp} 131145479Smp 132145479Smpvoid 133145479Smpxputwchar(Char c) 134145479Smp{ 135145479Smp char buf[MB_LEN_MAX]; 136145479Smp size_t i, len; 137145479Smp 138145479Smp len = one_wctomb(buf, c & CHAR); 139145479Smp for (i = 0; i < len; i++) 140145479Smp xputchar((unsigned char)buf[i] | (c & ~CHAR)); 141145479Smp} 142145479Smp#endif 143145479Smp 144145479Smpvoid 145167465Smpxputchar(int c) 14659243Sobrien{ 147167465Smp int atr; 14859243Sobrien 149167465Smp atr = c & ATTRIBUTES & TRIM; 15059243Sobrien c &= CHAR | QUOTE; 15159243Sobrien if (!output_raw && (c & QUOTE) == 0) { 152167465Smp if (iscntrl(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) { 153167465Smp if (c != '\t' && c != '\n' 15459243Sobrien#ifdef COLORCAT 155167465Smp && !(adrof(STRcolorcat) && c == CTL_ESC('\033')) 15659243Sobrien#endif 157167465Smp && (xlate_cr || c != '\r')) 158145479Smp { 15959243Sobrien xputchar('^' | atr); 16059243Sobrien if (c == CTL_ESC('\177')) 16159243Sobrien c = '?'; 16259243Sobrien else 163167465Smp /* Note: for IS_ASCII, this compiles to: c = c | 0100 */ 164167465Smp c = CTL_ESC(ASC(c)|0100); 16559243Sobrien } 16659243Sobrien } 167167465Smp else if (!isprint(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) { 16859243Sobrien xputchar('\\' | atr); 16959243Sobrien xputchar((((c >> 6) & 7) + '0') | atr); 17059243Sobrien xputchar((((c >> 3) & 7) + '0') | atr); 17159243Sobrien c = (c & 7) + '0'; 17259243Sobrien } 17359243Sobrien (void) putraw(c | atr); 17459243Sobrien } 17559243Sobrien else { 17659243Sobrien c &= TRIM; 17759243Sobrien if (haderr ? (didfds ? is2atty : isdiagatty) : 17859243Sobrien (didfds ? is1atty : isoutatty)) 17959243Sobrien SetAttributes(c | atr); 18059243Sobrien (void) putpure(c); 18159243Sobrien } 18259243Sobrien if (lbuffed && (c & CHAR) == '\n') 18359243Sobrien flush(); 18459243Sobrien} 18559243Sobrien 18659243Sobrienint 187167465Smpputraw(int c) 18859243Sobrien{ 18959243Sobrien if (haderr ? (didfds ? is2atty : isdiagatty) : 19059243Sobrien (didfds ? is1atty : isoutatty)) { 19159243Sobrien if (Tty_eight_bit == -1) 19259243Sobrien ed_set_tty_eight_bit(); 19359243Sobrien if (!Tty_eight_bit && (c & META)) { 19459243Sobrien c = (c & ~META) | STANDOUT; 19559243Sobrien } 19659243Sobrien SetAttributes(c); 19759243Sobrien } 19859243Sobrien return putpure(c); 19959243Sobrien} 20059243Sobrien 20159243Sobrienint 202167465Smpputpure(int c) 20359243Sobrien{ 20459243Sobrien c &= CHAR; 20559243Sobrien 20659243Sobrien *linp++ = (char) c; 20759243Sobrien if (linp >= &linbuf[sizeof linbuf - 10]) 20859243Sobrien flush(); 20959243Sobrien return (1); 21059243Sobrien} 21159243Sobrien 21259243Sobrienvoid 213167465Smpdrainoline(void) 21459243Sobrien{ 21559243Sobrien linp = linbuf; 21659243Sobrien} 21759243Sobrien 21859243Sobrienvoid 219167465Smpflush(void) 22059243Sobrien{ 221231990Smp int unit, oldexitset = exitset; 22259243Sobrien static int interrupted = 0; 22359243Sobrien 22459243Sobrien /* int lmode; */ 22559243Sobrien 22659243Sobrien if (linp == linbuf) 22759243Sobrien return; 22859243Sobrien if (GettingInput && !Tty_raw_mode && linp < &linbuf[sizeof linbuf - 10]) 22959243Sobrien return; 230316957Sdchagin if (handle_interrupt) 231316957Sdchagin exitset = 1; 232231990Smp 23359243Sobrien if (interrupted) { 23459243Sobrien interrupted = 0; 235167465Smp linp = linbuf; /* avoid recursion as stderror calls flush */ 236316957Sdchagin if (handle_interrupt) 237231990Smp fixerror(); 238231990Smp else 239231990Smp stderror(ERR_SILENT); 24059243Sobrien } 24159243Sobrien interrupted = 1; 24259243Sobrien if (haderr) 24359243Sobrien unit = didfds ? 2 : SHDIAG; 24459243Sobrien else 24559243Sobrien unit = didfds ? 1 : SHOUT; 24659243Sobrien#ifdef COMMENT 24759243Sobrien#ifdef TIOCLGET 24859243Sobrien if (didfds == 0 && ioctl(unit, TIOCLGET, (ioctl_t) & lmode) == 0 && 24959243Sobrien lmode & LFLUSHO) { 25059243Sobrien lmode = LFLUSHO; 25159243Sobrien (void) ioctl(unit, TIOCLBIC, (ioclt_t) & lmode); 252167465Smp (void) xwrite(unit, "\n", 1); 25359243Sobrien } 25459243Sobrien#endif 25559243Sobrien#endif 256167465Smp if (xwrite(unit, linbuf, linp - linbuf) == -1) 25759243Sobrien switch (errno) { 25859243Sobrien#ifdef EIO 25959243Sobrien /* We lost our tty */ 26059243Sobrien case EIO: 26159243Sobrien#endif 26259243Sobrien#ifdef ENXIO 26359243Sobrien /* 26459243Sobrien * Deal with Digital Unix 4.0D bogocity, returning ENXIO when 26559243Sobrien * we lose our tty. 26659243Sobrien */ 26759243Sobrien case ENXIO: 26859243Sobrien#endif 26959243Sobrien /* 27059243Sobrien * IRIX 6.4 bogocity? 27159243Sobrien */ 27259243Sobrien#ifdef ENOTTY 27359243Sobrien case ENOTTY: 27459243Sobrien#endif 27559243Sobrien#ifdef EBADF 27659243Sobrien case EBADF: 27759243Sobrien#endif 27859415Sobrien#ifdef ESTALE 27959243Sobrien /* 28059415Sobrien * Lost our file descriptor, exit (IRIS4D) 28159415Sobrien */ 28259415Sobrien case ESTALE: 28359415Sobrien#endif 284231990Smp#ifdef ENOENT 28559415Sobrien /* 286231990Smp * Deal with SoFS bogocity: returns ENOENT instead of ESTALE. 287231990Smp */ 288231990Smp case ENOENT: 289231990Smp#endif 290231990Smp /* 29159243Sobrien * Over our quota, writing the history file 29259243Sobrien */ 29359243Sobrien#ifdef EDQUOT 29459243Sobrien case EDQUOT: 29559243Sobrien#endif 29659243Sobrien /* Nothing to do, but die */ 297316957Sdchagin if (handle_interrupt == 0) 298231990Smp xexit(1); 299231990Smp /*FALLTHROUGH*/ 30059243Sobrien default: 301316957Sdchagin if (handle_interrupt) 302231990Smp fixerror(); 303231990Smp else 304231990Smp stderror(ERR_SILENT); 30559243Sobrien break; 30659243Sobrien } 30759243Sobrien 308231990Smp exitset = oldexitset; 30959243Sobrien linp = linbuf; 31059243Sobrien interrupted = 0; 31159243Sobrien} 312