sh.print.c revision 302408
1/* $Header: /p/tcsh/cvsroot/tcsh/sh.print.c,v 3.36 2011/05/25 20:17:20 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.36 2011/05/25 20:17:20 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, 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_intr)
235	exitset = 1;
236
237    if (interrupted) {
238	interrupted = 0;
239	linp = linbuf;		/* avoid recursion as stderror calls flush */
240	if (handle_intr)
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_intr == 0)
302		xexit(1);
303	    /*FALLTHROUGH*/
304	default:
305	    if (handle_intr)
306		fixerror();
307	    else
308		stderror(ERR_SILENT);
309	    break;
310	}
311
312    exitset = oldexitset;
313    linp = linbuf;
314    interrupted = 0;
315}
316