1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/sh.print.c,v 3.36 2011/05/25 20:17:20 christos Exp $ */
259243Sobrien/*
359243Sobrien * sh.print.c: Primitive Output routines.
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and binary forms, with or without
1059243Sobrien * modification, are permitted provided that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source code must retain the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp * 3. Neither the name of the University nor the names of its contributors
1859243Sobrien *    may be used to endorse or promote products derived from this software
1959243Sobrien *    without specific prior written permission.
2059243Sobrien *
2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159243Sobrien * SUCH DAMAGE.
3259243Sobrien */
3359243Sobrien#include "sh.h"
3459243Sobrien
35232633SmpRCSID("$tcsh: sh.print.c,v 3.36 2011/05/25 20:17:20 christos Exp $")
3659243Sobrien
3759243Sobrien#include "ed.h"
3859243Sobrien
3959243Sobrienextern int Tty_eight_bit;
4059243Sobrien
4159243Sobrienint     lbuffed = 1;		/* true if line buffered */
4259243Sobrien
43167465Smpstatic	void	p2dig	(unsigned int);
4459243Sobrien
4559243Sobrien/*
4659243Sobrien * C Shell
4759243Sobrien */
4859243Sobrien
4959243Sobrien#if defined(BSDLIMIT) || defined(RLIMIT_CPU)
5059243Sobrienvoid
51167465Smppsecs(unsigned long l)
5259243Sobrien{
53145479Smp    int i;
5459243Sobrien
5559243Sobrien    i = (int) (l / 3600);
5659243Sobrien    if (i) {
5759243Sobrien	xprintf("%d:", i);
5859243Sobrien	i = (int) (l % 3600);
5959243Sobrien	p2dig(i / 60);
6059243Sobrien	goto minsec;
6159243Sobrien    }
6259243Sobrien    i = (int) l;
6359243Sobrien    xprintf("%d", i / 60);
6459243Sobrienminsec:
6559243Sobrien    i %= 60;
6659243Sobrien    xprintf(":");
6759243Sobrien    p2dig(i);
6859243Sobrien}
6959243Sobrien
7059243Sobrien#endif
7159243Sobrien
72167465Smpvoid			/* PWP: print mm:ss.dd, l is in sec*100 */
7359243Sobrien#ifdef BSDTIMES
74167465Smppcsecs(unsigned long l)
7559243Sobrien#else /* BSDTIMES */
7659243Sobrien# ifndef POSIX
77167465Smppcsecs(time_t l)
7859243Sobrien# else /* POSIX */
79167465Smppcsecs(clock_t l)
8059243Sobrien# endif /* POSIX */
8159243Sobrien#endif /* BSDTIMES */
8259243Sobrien{
83145479Smp    int i;
8459243Sobrien
8559243Sobrien    i = (int) (l / 360000);
8659243Sobrien    if (i) {
8759243Sobrien	xprintf("%d:", i);
8859243Sobrien	i = (int) ((l % 360000) / 100);
8959243Sobrien	p2dig(i / 60);
9059243Sobrien	goto minsec;
9159243Sobrien    }
9259243Sobrien    i = (int) (l / 100);
9359243Sobrien    xprintf("%d", i / 60);
9459243Sobrienminsec:
9559243Sobrien    i %= 60;
9659243Sobrien    xprintf(":");
9759243Sobrien    p2dig(i);
9859243Sobrien    xprintf(".");
9959243Sobrien    p2dig((int) (l % 100));
10059243Sobrien}
10159243Sobrien
10259243Sobrienstatic void
103167465Smpp2dig(unsigned i)
10459243Sobrien{
10559243Sobrien
106145479Smp    xprintf("%u%u", i / 10, i % 10);
10759243Sobrien}
10859243Sobrien
10959243Sobrienchar    linbuf[2048];		/* was 128 */
11059243Sobrienchar   *linp = linbuf;
111145479Smpint    output_raw = 0;		/* PWP */
112145479Smpint    xlate_cr   = 0;		/* HE */
11359243Sobrien
114167465Smp/* For cleanup_push() */
115167465Smpvoid
116167465Smpoutput_raw_restore(void *xorig)
117167465Smp{
118167465Smp    int *orig;
119167465Smp
120167465Smp    orig = xorig;
121167465Smp    output_raw = *orig;
122167465Smp}
123167465Smp
124145479Smp#ifdef WIDE_STRINGS
12559243Sobrienvoid
126145479Smpputwraw(Char c)
127145479Smp{
128145479Smp    char buf[MB_LEN_MAX];
129145479Smp    size_t i, len;
130145479Smp
131145479Smp    len = one_wctomb(buf, c & CHAR);
132145479Smp    for (i = 0; i < len; i++)
133145479Smp	putraw((unsigned char)buf[i] | (c & ~CHAR));
134145479Smp}
135145479Smp
136145479Smpvoid
137145479Smpxputwchar(Char c)
138145479Smp{
139145479Smp    char buf[MB_LEN_MAX];
140145479Smp    size_t i, len;
141145479Smp
142145479Smp    len = one_wctomb(buf, c & CHAR);
143145479Smp    for (i = 0; i < len; i++)
144145479Smp	xputchar((unsigned char)buf[i] | (c & ~CHAR));
145145479Smp}
146145479Smp#endif
147145479Smp
148145479Smpvoid
149167465Smpxputchar(int c)
15059243Sobrien{
151167465Smp    int     atr;
15259243Sobrien
153167465Smp    atr = c & ATTRIBUTES & TRIM;
15459243Sobrien    c &= CHAR | QUOTE;
15559243Sobrien    if (!output_raw && (c & QUOTE) == 0) {
156167465Smp	if (iscntrl(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) {
157167465Smp	    if (c != '\t' && c != '\n'
15859243Sobrien#ifdef COLORCAT
159167465Smp	        && !(adrof(STRcolorcat) && c == CTL_ESC('\033'))
16059243Sobrien#endif
161167465Smp		&& (xlate_cr || c != '\r'))
162145479Smp	    {
16359243Sobrien		xputchar('^' | atr);
16459243Sobrien		if (c == CTL_ESC('\177'))
16559243Sobrien		    c = '?';
16659243Sobrien		else
167167465Smp		    /* Note: for IS_ASCII, this compiles to: c = c | 0100 */
168167465Smp		    c = CTL_ESC(ASC(c)|0100);
16959243Sobrien	    }
17059243Sobrien	}
171167465Smp	else if (!isprint(c) && (ASC(c) < 0x80 || MB_CUR_MAX == 1)) {
17259243Sobrien	    xputchar('\\' | atr);
17359243Sobrien	    xputchar((((c >> 6) & 7) + '0') | atr);
17459243Sobrien	    xputchar((((c >> 3) & 7) + '0') | atr);
17559243Sobrien	    c = (c & 7) + '0';
17659243Sobrien	}
17759243Sobrien	(void) putraw(c | atr);
17859243Sobrien    }
17959243Sobrien    else {
18059243Sobrien	c &= TRIM;
18159243Sobrien	if (haderr ? (didfds ? is2atty : isdiagatty) :
18259243Sobrien	    (didfds ? is1atty : isoutatty))
18359243Sobrien	    SetAttributes(c | atr);
18459243Sobrien	(void) putpure(c);
18559243Sobrien    }
18659243Sobrien    if (lbuffed && (c & CHAR) == '\n')
18759243Sobrien	flush();
18859243Sobrien}
18959243Sobrien
19059243Sobrienint
191167465Smpputraw(int c)
19259243Sobrien{
19359243Sobrien    if (haderr ? (didfds ? is2atty : isdiagatty) :
19459243Sobrien	(didfds ? is1atty : isoutatty)) {
19559243Sobrien	if (Tty_eight_bit == -1)
19659243Sobrien	    ed_set_tty_eight_bit();
19759243Sobrien	if (!Tty_eight_bit && (c & META)) {
19859243Sobrien	    c = (c & ~META) | STANDOUT;
19959243Sobrien	}
20059243Sobrien	SetAttributes(c);
20159243Sobrien    }
20259243Sobrien    return putpure(c);
20359243Sobrien}
20459243Sobrien
20559243Sobrienint
206167465Smpputpure(int c)
20759243Sobrien{
20859243Sobrien    c &= CHAR;
20959243Sobrien
21059243Sobrien    *linp++ = (char) c;
21159243Sobrien    if (linp >= &linbuf[sizeof linbuf - 10])
21259243Sobrien	flush();
21359243Sobrien    return (1);
21459243Sobrien}
21559243Sobrien
21659243Sobrienvoid
217167465Smpdrainoline(void)
21859243Sobrien{
21959243Sobrien    linp = linbuf;
22059243Sobrien}
22159243Sobrien
22259243Sobrienvoid
223167465Smpflush(void)
22459243Sobrien{
225232633Smp    int unit, oldexitset = exitset;
22659243Sobrien    static int interrupted = 0;
22759243Sobrien
22859243Sobrien    /* int lmode; */
22959243Sobrien
23059243Sobrien    if (linp == linbuf)
23159243Sobrien	return;
23259243Sobrien    if (GettingInput && !Tty_raw_mode && linp < &linbuf[sizeof linbuf - 10])
23359243Sobrien	return;
234232633Smp    if (handle_intr)
235232633Smp	exitset = 1;
236232633Smp
23759243Sobrien    if (interrupted) {
23859243Sobrien	interrupted = 0;
239167465Smp	linp = linbuf;		/* avoid recursion as stderror calls flush */
240232633Smp	if (handle_intr)
241232633Smp	    fixerror();
242232633Smp	else
243232633Smp	    stderror(ERR_SILENT);
24459243Sobrien    }
24559243Sobrien    interrupted = 1;
24659243Sobrien    if (haderr)
24759243Sobrien	unit = didfds ? 2 : SHDIAG;
24859243Sobrien    else
24959243Sobrien	unit = didfds ? 1 : SHOUT;
25059243Sobrien#ifdef COMMENT
25159243Sobrien#ifdef TIOCLGET
25259243Sobrien    if (didfds == 0 && ioctl(unit, TIOCLGET, (ioctl_t) & lmode) == 0 &&
25359243Sobrien	lmode & LFLUSHO) {
25459243Sobrien	lmode = LFLUSHO;
25559243Sobrien	(void) ioctl(unit, TIOCLBIC, (ioclt_t) & lmode);
256167465Smp	(void) xwrite(unit, "\n", 1);
25759243Sobrien    }
25859243Sobrien#endif
25959243Sobrien#endif
260167465Smp    if (xwrite(unit, linbuf, linp - linbuf) == -1)
26159243Sobrien	switch (errno) {
26259243Sobrien#ifdef EIO
26359243Sobrien	/* We lost our tty */
26459243Sobrien	case EIO:
26559243Sobrien#endif
26659243Sobrien#ifdef ENXIO
26759243Sobrien	/*
26859243Sobrien	 * Deal with Digital Unix 4.0D bogocity, returning ENXIO when
26959243Sobrien	 * we lose our tty.
27059243Sobrien	 */
27159243Sobrien	case ENXIO:
27259243Sobrien#endif
27359243Sobrien	/*
27459243Sobrien	 * IRIX 6.4 bogocity?
27559243Sobrien	 */
27659243Sobrien#ifdef ENOTTY
27759243Sobrien	case ENOTTY:
27859243Sobrien#endif
27959243Sobrien#ifdef EBADF
28059243Sobrien	case EBADF:
28159243Sobrien#endif
28259415Sobrien#ifdef ESTALE
28359243Sobrien	/*
28459415Sobrien	 * Lost our file descriptor, exit (IRIS4D)
28559415Sobrien	 */
28659415Sobrien	case ESTALE:
28759415Sobrien#endif
288232633Smp#ifdef ENOENT
28959415Sobrien	/*
290232633Smp	 * Deal with SoFS bogocity: returns ENOENT instead of ESTALE.
291232633Smp	 */
292232633Smp	case ENOENT:
293232633Smp#endif
294232633Smp	/*
29559243Sobrien	 * Over our quota, writing the history file
29659243Sobrien	 */
29759243Sobrien#ifdef EDQUOT
29859243Sobrien	case EDQUOT:
29959243Sobrien#endif
30059243Sobrien	/* Nothing to do, but die */
301232633Smp	    if (handle_intr == 0)
302232633Smp		xexit(1);
303232633Smp	    /*FALLTHROUGH*/
30459243Sobrien	default:
305232633Smp	    if (handle_intr)
306232633Smp		fixerror();
307232633Smp	    else
308232633Smp		stderror(ERR_SILENT);
30959243Sobrien	    break;
31059243Sobrien	}
31159243Sobrien
312232633Smp    exitset = oldexitset;
31359243Sobrien    linp = linbuf;
31459243Sobrien    interrupted = 0;
31559243Sobrien}
316