xref: /freebsd/contrib/tcsh/sh.print.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.print.c,v 3.37 2015/05/10 13:29:28 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 
35 RCSID("$tcsh: sh.print.c,v 3.37 2015/05/10 13:29:28 christos Exp $")
36 
37 #include "ed.h"
38 
39 extern int Tty_eight_bit;
40 
41 int     lbuffed = 1;		/* true if line buffered */
42 
43 static	void	p2dig	(unsigned int);
44 
45 /*
46  * C Shell
47  */
48 
49 #if defined(BSDLIMIT) || defined(RLIMIT_CPU)
50 void
51 psecs(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);
64 minsec:
65     i %= 60;
66     xprintf(":");
67     p2dig(i);
68 }
69 
70 #endif
71 
72 void			/* PWP: print mm:ss.dd, l is in sec*100 */
73 #ifdef BSDTIMES
74 pcsecs(unsigned long l)
75 #else /* BSDTIMES */
76 # ifndef POSIX
77 pcsecs(time_t l)
78 # else /* POSIX */
79 pcsecs(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);
94 minsec:
95     i %= 60;
96     xprintf(":");
97     p2dig(i);
98     xprintf(".");
99     p2dig((int) (l % 100));
100 }
101 
102 static void
103 p2dig(unsigned i)
104 {
105 
106     xprintf("%u%u", i / 10, i % 10);
107 }
108 
109 char    linbuf[2048];		/* was 128 */
110 char   *linp = linbuf;
111 int    output_raw = 0;		/* PWP */
112 int    xlate_cr   = 0;		/* HE */
113 
114 /* For cleanup_push() */
115 void
116 output_raw_restore(void *xorig)
117 {
118     int *orig;
119 
120     orig = xorig;
121     output_raw = *orig;
122 }
123 
124 #ifdef WIDE_STRINGS
125 void
126 putwraw(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 
136 void
137 xputwchar(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 
148 void
149 xputchar(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 
190 int
191 putraw(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 
205 int
206 putpure(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 
216 void
217 drainoline(void)
218 {
219     linp = linbuf;
220 }
221 
222 void
223 flush(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_interrupt)
235        exitset = 1;
236 
237     if (interrupted) {
238 	interrupted = 0;
239 	linp = linbuf;		/* avoid recursion as stderror calls flush */
240 	if (handle_interrupt)
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_interrupt == 0)
302 		xexit(1);
303 	    /*FALLTHROUGH*/
304 	default:
305 	    if (handle_interrupt)
306 		fixerror();
307 	    else
308 		stderror(ERR_SILENT);
309 	    break;
310 	}
311 
312     exitset = oldexitset;
313     linp = linbuf;
314     interrupted = 0;
315 }
316