sh.print.c revision 225736
1/* $Header: /p/tcsh/cvsroot/tcsh/sh.print.c,v 3.33 2006/08/23 15:03:14 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
35RCSID("$tcsh: sh.print.c,v 3.33 2006/08/23 15:03:14 christos Exp $")
36
37#include "ed.h"
38
39extern int Tty_eight_bit;
40
41int     lbuffed = 1;		/* true if line buffered */
42
43static	void	p2dig	(unsigned int);
44
45/*
46 * C Shell
47 */
48
49#if defined(BSDLIMIT) || defined(RLIMIT_CPU)
50void
51psecs(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);
64minsec:
65    i %= 60;
66    xprintf(":");
67    p2dig(i);
68}
69
70#endif
71
72void			/* PWP: print mm:ss.dd, l is in sec*100 */
73#ifdef BSDTIMES
74pcsecs(unsigned long l)
75#else /* BSDTIMES */
76# ifndef POSIX
77pcsecs(time_t l)
78# else /* POSIX */
79pcsecs(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);
94minsec:
95    i %= 60;
96    xprintf(":");
97    p2dig(i);
98    xprintf(".");
99    p2dig((int) (l % 100));
100}
101
102static void
103p2dig(unsigned i)
104{
105
106    xprintf("%u%u", i / 10, i % 10);
107}
108
109char    linbuf[2048];		/* was 128 */
110char   *linp = linbuf;
111int    output_raw = 0;		/* PWP */
112int    xlate_cr   = 0;		/* HE */
113
114/* For cleanup_push() */
115void
116output_raw_restore(void *xorig)
117{
118    int *orig;
119
120    orig = xorig;
121    output_raw = *orig;
122}
123
124#ifdef WIDE_STRINGS
125void
126putwraw(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
136void
137xputwchar(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
148void
149xputchar(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
190int
191putraw(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
205int
206putpure(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
216void
217drainoline(void)
218{
219    linp = linbuf;
220}
221
222void
223flush(void)
224{
225    int unit;
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 (interrupted) {
235	interrupted = 0;
236	linp = linbuf;		/* avoid recursion as stderror calls flush */
237	stderror(ERR_SILENT);
238    }
239    interrupted = 1;
240    if (haderr)
241	unit = didfds ? 2 : SHDIAG;
242    else
243	unit = didfds ? 1 : SHOUT;
244#ifdef COMMENT
245#ifdef TIOCLGET
246    if (didfds == 0 && ioctl(unit, TIOCLGET, (ioctl_t) & lmode) == 0 &&
247	lmode & LFLUSHO) {
248	lmode = LFLUSHO;
249	(void) ioctl(unit, TIOCLBIC, (ioclt_t) & lmode);
250	(void) xwrite(unit, "\n", 1);
251    }
252#endif
253#endif
254    if (xwrite(unit, linbuf, linp - linbuf) == -1)
255	switch (errno) {
256#ifdef EIO
257	/* We lost our tty */
258	case EIO:
259#endif
260#ifdef ENXIO
261	/*
262	 * Deal with Digital Unix 4.0D bogocity, returning ENXIO when
263	 * we lose our tty.
264	 */
265	case ENXIO:
266#endif
267	/*
268	 * IRIX 6.4 bogocity?
269	 */
270#ifdef ENOTTY
271	case ENOTTY:
272#endif
273#ifdef EBADF
274	case EBADF:
275#endif
276#ifdef ESTALE
277	/*
278	 * Lost our file descriptor, exit (IRIS4D)
279	 */
280	case ESTALE:
281#endif
282	/*
283	 * Over our quota, writing the history file
284	 */
285#ifdef EDQUOT
286	case EDQUOT:
287#endif
288	/* Nothing to do, but die */
289	    xexit(1);
290	    break;
291	default:
292	    stderror(ERR_SILENT);
293	    break;
294	}
295
296    linp = linbuf;
297    interrupted = 0;
298}
299