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