xref: /illumos-gate/usr/src/contrib/ast/src/lib/libcmd/cat.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1992-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                                                                      *
20*b30d1939SAndy Fiddaman ***********************************************************************/
21*b30d1939SAndy Fiddaman #pragma prototyped
22*b30d1939SAndy Fiddaman /*
23*b30d1939SAndy Fiddaman  * David Korn
24*b30d1939SAndy Fiddaman  * Glenn Fowler
25*b30d1939SAndy Fiddaman  * AT&T Bell Laboratories
26*b30d1939SAndy Fiddaman  *
27*b30d1939SAndy Fiddaman  * cat
28*b30d1939SAndy Fiddaman  */
29*b30d1939SAndy Fiddaman 
30*b30d1939SAndy Fiddaman #include <cmd.h>
31*b30d1939SAndy Fiddaman #include <fcntl.h>
32*b30d1939SAndy Fiddaman 
33*b30d1939SAndy Fiddaman static const char usage[] =
34*b30d1939SAndy Fiddaman "[-?\n@(#)$Id: cat (AT&T Research) 2012-05-31 $\n]"
35*b30d1939SAndy Fiddaman USAGE_LICENSE
36*b30d1939SAndy Fiddaman "[+NAME?cat - concatenate files]"
37*b30d1939SAndy Fiddaman "[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard"
38*b30d1939SAndy Fiddaman "	output. If no \afile\a is given, or if the \afile\a is \b-\b,"
39*b30d1939SAndy Fiddaman "	\bcat\b copies from standard input starting at the current location.]"
40*b30d1939SAndy Fiddaman 
41*b30d1939SAndy Fiddaman "[b:number-nonblank?Number lines as with \b-n\b but omit line numbers from"
42*b30d1939SAndy Fiddaman "	blank lines.]"
43*b30d1939SAndy Fiddaman "[d:dos-input?Input files are opened in \atext\amode which removes carriage"
44*b30d1939SAndy Fiddaman "	returns in front of new-lines on some systems.]"
45*b30d1939SAndy Fiddaman "[e?Equivalent to \b-vE\b.]"
46*b30d1939SAndy Fiddaman "[n:number?Causes a line number to be inserted at the beginning of each line.]"
47*b30d1939SAndy Fiddaman "[s?Equivalent to \b-S\b for \aatt\a universe and \b-B\b otherwise.]"
48*b30d1939SAndy Fiddaman "[t?Equivalent to \b-vT\b.]"
49*b30d1939SAndy Fiddaman "[u:unbuffer?The output is not delayed by buffering.]"
50*b30d1939SAndy Fiddaman "[v:show-nonprinting|print-chars?Print characters as follows: space and "
51*b30d1939SAndy Fiddaman     "printable characters as themselves; control characters as \b^\b "
52*b30d1939SAndy Fiddaman     "followed by a letter of the alphabet; and characters with the high bit "
53*b30d1939SAndy Fiddaman     "set as the lower 7 bit character prefixed by \bM^\b for 7 bit "
54*b30d1939SAndy Fiddaman     "non-printable characters and \bM-\b for all other characters. If the 7 "
55*b30d1939SAndy Fiddaman     "bit character encoding is not ASCII then the characters are converted "
56*b30d1939SAndy Fiddaman     "to ASCII to determine \ahigh bit set\a, and if set it is cleared and "
57*b30d1939SAndy Fiddaman     "converted back to the native encoding. Multibyte characters in the "
58*b30d1939SAndy Fiddaman     "current locale are treated as printable characters.]"
59*b30d1939SAndy Fiddaman "[A:show-all?Equivalent to \b-vET\b.]"
60*b30d1939SAndy Fiddaman "[B:squeeze-blank?Multiple adjacent new-line characters are replace by one"
61*b30d1939SAndy Fiddaman "	new-line.]"
62*b30d1939SAndy Fiddaman "[D:dos-output?Output files are opened in \atext\amode which inserts carriage"
63*b30d1939SAndy Fiddaman "	returns in front of new-lines on some systems.]"
64*b30d1939SAndy Fiddaman "[E:show-ends?Causes a \b$\b to be inserted before each new-line.]"
65*b30d1939SAndy Fiddaman "[R:regress?Regression test defaults: \b-v\b buffer size 4.]"
66*b30d1939SAndy Fiddaman "[S:silent?\bcat\b is silent about non-existent files.]"
67*b30d1939SAndy Fiddaman "[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]"
68*b30d1939SAndy Fiddaman 
69*b30d1939SAndy Fiddaman "\n"
70*b30d1939SAndy Fiddaman "\n[file ...]\n"
71*b30d1939SAndy Fiddaman "\n"
72*b30d1939SAndy Fiddaman 
73*b30d1939SAndy Fiddaman "[+SEE ALSO?\bcp\b(1), \bgetconf\b(1), \bpr\b(1)]"
74*b30d1939SAndy Fiddaman ;
75*b30d1939SAndy Fiddaman 
76*b30d1939SAndy Fiddaman #define RUBOUT	0177
77*b30d1939SAndy Fiddaman 
78*b30d1939SAndy Fiddaman /* control flags */
79*b30d1939SAndy Fiddaman #define B_FLAG		(1<<0)
80*b30d1939SAndy Fiddaman #define E_FLAG		(1<<1)
81*b30d1939SAndy Fiddaman #define F_FLAG		(1<<2)
82*b30d1939SAndy Fiddaman #define N_FLAG		(1<<3)
83*b30d1939SAndy Fiddaman #define S_FLAG		(1<<4)
84*b30d1939SAndy Fiddaman #define T_FLAG		(1<<5)
85*b30d1939SAndy Fiddaman #define U_FLAG		(1<<6)
86*b30d1939SAndy Fiddaman #define V_FLAG		(1<<7)
87*b30d1939SAndy Fiddaman #define D_FLAG		(1<<8)
88*b30d1939SAndy Fiddaman #define d_FLAG		(1<<9)
89*b30d1939SAndy Fiddaman 
90*b30d1939SAndy Fiddaman /* character types */
91*b30d1939SAndy Fiddaman #define T_ERROR		1
92*b30d1939SAndy Fiddaman #define T_EOF		2
93*b30d1939SAndy Fiddaman #define T_ENDBUF	3
94*b30d1939SAndy Fiddaman #define T_NEWLINE	4
95*b30d1939SAndy Fiddaman #define T_CONTROL	5
96*b30d1939SAndy Fiddaman #define T_EIGHTBIT	6
97*b30d1939SAndy Fiddaman #define T_CNTL8BIT	7
98*b30d1939SAndy Fiddaman 
99*b30d1939SAndy Fiddaman #define printof(c)	((c)^0100)
100*b30d1939SAndy Fiddaman 
101*b30d1939SAndy Fiddaman typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int);
102*b30d1939SAndy Fiddaman 
103*b30d1939SAndy Fiddaman #ifndef sfvalue
104*b30d1939SAndy Fiddaman #define sfvalue(f)	((f)->_val)
105*b30d1939SAndy Fiddaman #endif
106*b30d1939SAndy Fiddaman 
107*b30d1939SAndy Fiddaman static void*
regress(Sfio_t * sp,ssize_t n,int f)108*b30d1939SAndy Fiddaman regress(Sfio_t* sp, ssize_t n, int f)
109*b30d1939SAndy Fiddaman {
110*b30d1939SAndy Fiddaman 	void*	r;
111*b30d1939SAndy Fiddaman 
112*b30d1939SAndy Fiddaman 	if (!(r = sfreserve(sp, 4, f)))
113*b30d1939SAndy Fiddaman 		r = sfreserve(sp, n, f);
114*b30d1939SAndy Fiddaman 	else if (sfvalue(sp) > 4)
115*b30d1939SAndy Fiddaman 		sfvalue(sp) = 4;
116*b30d1939SAndy Fiddaman 	return r;
117*b30d1939SAndy Fiddaman }
118*b30d1939SAndy Fiddaman 
119*b30d1939SAndy Fiddaman /*
120*b30d1939SAndy Fiddaman  * called for any special output processing
121*b30d1939SAndy Fiddaman  */
122*b30d1939SAndy Fiddaman 
123*b30d1939SAndy Fiddaman static int
vcat(register char * states,Sfio_t * ip,Sfio_t * op,Reserve_f reserve,int flags)124*b30d1939SAndy Fiddaman vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags)
125*b30d1939SAndy Fiddaman {
126*b30d1939SAndy Fiddaman 	register unsigned char*	cp;
127*b30d1939SAndy Fiddaman 	register unsigned char*	pp;
128*b30d1939SAndy Fiddaman 	unsigned char*		cur;
129*b30d1939SAndy Fiddaman 	unsigned char*		end;
130*b30d1939SAndy Fiddaman 	unsigned char*		buf;
131*b30d1939SAndy Fiddaman 	unsigned char*		nxt;
132*b30d1939SAndy Fiddaman 	register int		n;
133*b30d1939SAndy Fiddaman 	register int		line;
134*b30d1939SAndy Fiddaman 	register int		raw;
135*b30d1939SAndy Fiddaman 	int			last;
136*b30d1939SAndy Fiddaman 	int			c;
137*b30d1939SAndy Fiddaman 	int			m;
138*b30d1939SAndy Fiddaman 	int			any;
139*b30d1939SAndy Fiddaman 	int			header;
140*b30d1939SAndy Fiddaman 
141*b30d1939SAndy Fiddaman 	unsigned char		meta[3];
142*b30d1939SAndy Fiddaman 	unsigned char		tmp[32];
143*b30d1939SAndy Fiddaman 
144*b30d1939SAndy Fiddaman 	meta[0] = 'M';
145*b30d1939SAndy Fiddaman 	last = -1;
146*b30d1939SAndy Fiddaman 	*(cp = buf = end = tmp) = 0;
147*b30d1939SAndy Fiddaman 	any = 0;
148*b30d1939SAndy Fiddaman 	header = flags & (B_FLAG|N_FLAG);
149*b30d1939SAndy Fiddaman 	line = 1;
150*b30d1939SAndy Fiddaman 	states[0] = T_ENDBUF;
151*b30d1939SAndy Fiddaman 	raw = !mbwide();
152*b30d1939SAndy Fiddaman 	for (;;)
153*b30d1939SAndy Fiddaman 	{
154*b30d1939SAndy Fiddaman 		cur = cp;
155*b30d1939SAndy Fiddaman 		if (raw)
156*b30d1939SAndy Fiddaman 			while (!(n = states[*cp++]));
157*b30d1939SAndy Fiddaman 		else
158*b30d1939SAndy Fiddaman 			for (;;)
159*b30d1939SAndy Fiddaman 			{
160*b30d1939SAndy Fiddaman 				while (!(n = states[*cp++]));
161*b30d1939SAndy Fiddaman 				if (n < T_CONTROL)
162*b30d1939SAndy Fiddaman 					break;
163*b30d1939SAndy Fiddaman 				if ((m = mbsize(pp = cp - 1)) > 1)
164*b30d1939SAndy Fiddaman 					cp += m - 1;
165*b30d1939SAndy Fiddaman 				else
166*b30d1939SAndy Fiddaman 				{
167*b30d1939SAndy Fiddaman 					if (m <= 0)
168*b30d1939SAndy Fiddaman 					{
169*b30d1939SAndy Fiddaman 						if (cur == pp)
170*b30d1939SAndy Fiddaman 						{
171*b30d1939SAndy Fiddaman 							if (last > 0)
172*b30d1939SAndy Fiddaman 							{
173*b30d1939SAndy Fiddaman 								*end = last;
174*b30d1939SAndy Fiddaman 								last = -1;
175*b30d1939SAndy Fiddaman 								c = end - pp + 1;
176*b30d1939SAndy Fiddaman 								if ((m = mbsize(pp)) == c)
177*b30d1939SAndy Fiddaman 								{
178*b30d1939SAndy Fiddaman 									any = 1;
179*b30d1939SAndy Fiddaman 									if (header)
180*b30d1939SAndy Fiddaman 									{
181*b30d1939SAndy Fiddaman 										header = 0;
182*b30d1939SAndy Fiddaman 										sfprintf(op, "%6d\t", line);
183*b30d1939SAndy Fiddaman 									}
184*b30d1939SAndy Fiddaman 									sfwrite(op, cur, m);
185*b30d1939SAndy Fiddaman 									*(cp = cur = end) = 0;
186*b30d1939SAndy Fiddaman 								}
187*b30d1939SAndy Fiddaman 								else
188*b30d1939SAndy Fiddaman 								{
189*b30d1939SAndy Fiddaman 									memcpy(tmp, pp, c);
190*b30d1939SAndy Fiddaman 									if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
191*b30d1939SAndy Fiddaman 									{
192*b30d1939SAndy Fiddaman 										states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
193*b30d1939SAndy Fiddaman 										*(cp = end = tmp + sizeof(tmp) - 1) = 0;
194*b30d1939SAndy Fiddaman 										last = -1;
195*b30d1939SAndy Fiddaman 									}
196*b30d1939SAndy Fiddaman 									else if ((n = sfvalue(ip)) <= 0)
197*b30d1939SAndy Fiddaman 									{
198*b30d1939SAndy Fiddaman 										states[0] = n ? T_ERROR : T_EOF;
199*b30d1939SAndy Fiddaman 										*(cp = end = tmp + sizeof(tmp) - 1) = 0;
200*b30d1939SAndy Fiddaman 										last = -1;
201*b30d1939SAndy Fiddaman 									}
202*b30d1939SAndy Fiddaman 									else
203*b30d1939SAndy Fiddaman 									{
204*b30d1939SAndy Fiddaman 										cp = buf = nxt;
205*b30d1939SAndy Fiddaman 										end = buf + n - 1;
206*b30d1939SAndy Fiddaman 										last = *end;
207*b30d1939SAndy Fiddaman 										*end = 0;
208*b30d1939SAndy Fiddaman 									}
209*b30d1939SAndy Fiddaman  mb:
210*b30d1939SAndy Fiddaman 									if ((n = end - cp + 1) >= (sizeof(tmp) - c))
211*b30d1939SAndy Fiddaman 										n = sizeof(tmp) - c - 1;
212*b30d1939SAndy Fiddaman 									memcpy(tmp + c, cp, n);
213*b30d1939SAndy Fiddaman 									if ((m = mbsize(tmp)) >= c)
214*b30d1939SAndy Fiddaman 									{
215*b30d1939SAndy Fiddaman 										any = 1;
216*b30d1939SAndy Fiddaman 										if (header)
217*b30d1939SAndy Fiddaman 										{
218*b30d1939SAndy Fiddaman 											header = 0;
219*b30d1939SAndy Fiddaman 											sfprintf(op, "%6d\t", line);
220*b30d1939SAndy Fiddaman 										}
221*b30d1939SAndy Fiddaman 										sfwrite(op, tmp, m);
222*b30d1939SAndy Fiddaman 										cur = cp += m - c;
223*b30d1939SAndy Fiddaman 									}
224*b30d1939SAndy Fiddaman 								}
225*b30d1939SAndy Fiddaman 								continue;
226*b30d1939SAndy Fiddaman 							}
227*b30d1939SAndy Fiddaman 						}
228*b30d1939SAndy Fiddaman 						else
229*b30d1939SAndy Fiddaman 						{
230*b30d1939SAndy Fiddaman 							cp = pp + 1;
231*b30d1939SAndy Fiddaman 							n = 0;
232*b30d1939SAndy Fiddaman 						}
233*b30d1939SAndy Fiddaman 					}
234*b30d1939SAndy Fiddaman 					break;
235*b30d1939SAndy Fiddaman 				}
236*b30d1939SAndy Fiddaman 			}
237*b30d1939SAndy Fiddaman 		c = *--cp;
238*b30d1939SAndy Fiddaman 		if ((m = cp - cur) || n >= T_CONTROL)
239*b30d1939SAndy Fiddaman 		{
240*b30d1939SAndy Fiddaman  flush:
241*b30d1939SAndy Fiddaman 			any = 1;
242*b30d1939SAndy Fiddaman 			if (header)
243*b30d1939SAndy Fiddaman 			{
244*b30d1939SAndy Fiddaman 				header = 0;
245*b30d1939SAndy Fiddaman 				sfprintf(op, "%6d\t", line);
246*b30d1939SAndy Fiddaman 			}
247*b30d1939SAndy Fiddaman 			if (m)
248*b30d1939SAndy Fiddaman 				sfwrite(op, cur, m);
249*b30d1939SAndy Fiddaman 		}
250*b30d1939SAndy Fiddaman  special:
251*b30d1939SAndy Fiddaman 		switch (n)
252*b30d1939SAndy Fiddaman 		{
253*b30d1939SAndy Fiddaman 		case T_ERROR:
254*b30d1939SAndy Fiddaman 			if (cp < end)
255*b30d1939SAndy Fiddaman 			{
256*b30d1939SAndy Fiddaman 				n = T_CONTROL;
257*b30d1939SAndy Fiddaman 				goto flush;
258*b30d1939SAndy Fiddaman 			}
259*b30d1939SAndy Fiddaman 			return -1;
260*b30d1939SAndy Fiddaman 		case T_EOF:
261*b30d1939SAndy Fiddaman 			if (cp < end)
262*b30d1939SAndy Fiddaman 			{
263*b30d1939SAndy Fiddaman 				n = T_CONTROL;
264*b30d1939SAndy Fiddaman 				goto flush;
265*b30d1939SAndy Fiddaman 			}
266*b30d1939SAndy Fiddaman 			return 0;
267*b30d1939SAndy Fiddaman 		case T_ENDBUF:
268*b30d1939SAndy Fiddaman 			if (cp < end)
269*b30d1939SAndy Fiddaman 			{
270*b30d1939SAndy Fiddaman 				n = T_CONTROL;
271*b30d1939SAndy Fiddaman 				goto flush;
272*b30d1939SAndy Fiddaman 			}
273*b30d1939SAndy Fiddaman 			c = last;
274*b30d1939SAndy Fiddaman 			if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
275*b30d1939SAndy Fiddaman 			{
276*b30d1939SAndy Fiddaman 				*(cp = end = tmp + sizeof(tmp) - 1) = 0;
277*b30d1939SAndy Fiddaman 				states[0] = (m = sfvalue(ip)) ? T_ERROR : T_EOF;
278*b30d1939SAndy Fiddaman 				last = -1;
279*b30d1939SAndy Fiddaman 			}
280*b30d1939SAndy Fiddaman 			else if ((m = sfvalue(ip)) <= 0)
281*b30d1939SAndy Fiddaman 			{
282*b30d1939SAndy Fiddaman 				*(cp = end = tmp + sizeof(tmp) - 1) = 0;
283*b30d1939SAndy Fiddaman 				states[0] = m ? T_ERROR : T_EOF;
284*b30d1939SAndy Fiddaman 				last = -1;
285*b30d1939SAndy Fiddaman 			}
286*b30d1939SAndy Fiddaman 			else
287*b30d1939SAndy Fiddaman 			{
288*b30d1939SAndy Fiddaman 				buf = nxt;
289*b30d1939SAndy Fiddaman 				end = buf + m - 1;
290*b30d1939SAndy Fiddaman 				last = *end;
291*b30d1939SAndy Fiddaman 				*end = 0;
292*b30d1939SAndy Fiddaman 				cp = buf;
293*b30d1939SAndy Fiddaman 			}
294*b30d1939SAndy Fiddaman 			if (c >= 0)
295*b30d1939SAndy Fiddaman 			{
296*b30d1939SAndy Fiddaman 				if (!(n = states[c]))
297*b30d1939SAndy Fiddaman 				{
298*b30d1939SAndy Fiddaman 					*(cur = tmp) = c;
299*b30d1939SAndy Fiddaman 					m = 1;
300*b30d1939SAndy Fiddaman 					goto flush;
301*b30d1939SAndy Fiddaman 				}
302*b30d1939SAndy Fiddaman 				if (raw || n < T_CONTROL)
303*b30d1939SAndy Fiddaman 				{
304*b30d1939SAndy Fiddaman 					cp--;
305*b30d1939SAndy Fiddaman 					goto special;
306*b30d1939SAndy Fiddaman 				}
307*b30d1939SAndy Fiddaman 				tmp[0] = c;
308*b30d1939SAndy Fiddaman 				c = 1;
309*b30d1939SAndy Fiddaman 				goto mb;
310*b30d1939SAndy Fiddaman 			}
311*b30d1939SAndy Fiddaman 			break;
312*b30d1939SAndy Fiddaman 		case T_CONTROL:
313*b30d1939SAndy Fiddaman 			do
314*b30d1939SAndy Fiddaman 			{
315*b30d1939SAndy Fiddaman 				sfputc(op, '^');
316*b30d1939SAndy Fiddaman 				sfputc(op, printof(c));
317*b30d1939SAndy Fiddaman 			} while (states[c = *++cp] == T_CONTROL);
318*b30d1939SAndy Fiddaman 			break;
319*b30d1939SAndy Fiddaman 		case T_CNTL8BIT:
320*b30d1939SAndy Fiddaman 			meta[1] = '^';
321*b30d1939SAndy Fiddaman 			do
322*b30d1939SAndy Fiddaman 			{
323*b30d1939SAndy Fiddaman 				n = c & ~0200;
324*b30d1939SAndy Fiddaman 				meta[2] = printof(n);
325*b30d1939SAndy Fiddaman 				sfwrite(op, (char*)meta, 3);
326*b30d1939SAndy Fiddaman 			} while (states[c = *++cp] == T_CNTL8BIT && raw);
327*b30d1939SAndy Fiddaman 			break;
328*b30d1939SAndy Fiddaman 		case T_EIGHTBIT:
329*b30d1939SAndy Fiddaman 			meta[1] = '-';
330*b30d1939SAndy Fiddaman 			do
331*b30d1939SAndy Fiddaman 			{
332*b30d1939SAndy Fiddaman 				meta[2] = c & ~0200;
333*b30d1939SAndy Fiddaman 				sfwrite(op, (char*)meta, 3);
334*b30d1939SAndy Fiddaman 			} while (states[c = *++cp] == T_EIGHTBIT && raw);
335*b30d1939SAndy Fiddaman 			break;
336*b30d1939SAndy Fiddaman 		case T_NEWLINE:
337*b30d1939SAndy Fiddaman 			if (header && !(flags & B_FLAG))
338*b30d1939SAndy Fiddaman 				sfprintf(op, "%6d\t", line);
339*b30d1939SAndy Fiddaman 			if (flags & E_FLAG)
340*b30d1939SAndy Fiddaman 				sfputc(op, '$');
341*b30d1939SAndy Fiddaman 			sfputc(op, '\n');
342*b30d1939SAndy Fiddaman 			if (!header || !(flags & B_FLAG))
343*b30d1939SAndy Fiddaman 				line++;
344*b30d1939SAndy Fiddaman 			header = !(flags & S_FLAG);
345*b30d1939SAndy Fiddaman 			for (;;)
346*b30d1939SAndy Fiddaman 			{
347*b30d1939SAndy Fiddaman 				if ((n = states[*++cp]) == T_ENDBUF)
348*b30d1939SAndy Fiddaman 				{
349*b30d1939SAndy Fiddaman 					if (cp < end || last != '\n')
350*b30d1939SAndy Fiddaman 						break;
351*b30d1939SAndy Fiddaman 					if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
352*b30d1939SAndy Fiddaman 					{
353*b30d1939SAndy Fiddaman 						states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
354*b30d1939SAndy Fiddaman 						cp = end = tmp;
355*b30d1939SAndy Fiddaman 						*cp-- = 0;
356*b30d1939SAndy Fiddaman 						last = -1;
357*b30d1939SAndy Fiddaman 					}
358*b30d1939SAndy Fiddaman 					else if ((n = sfvalue(ip)) <= 0)
359*b30d1939SAndy Fiddaman 					{
360*b30d1939SAndy Fiddaman 						states[0] = n ? T_ERROR : T_EOF;
361*b30d1939SAndy Fiddaman 						cp = end = tmp;
362*b30d1939SAndy Fiddaman 						*cp-- = 0;
363*b30d1939SAndy Fiddaman 						last = -1;
364*b30d1939SAndy Fiddaman 					}
365*b30d1939SAndy Fiddaman 					else
366*b30d1939SAndy Fiddaman 					{
367*b30d1939SAndy Fiddaman 						buf = nxt;
368*b30d1939SAndy Fiddaman 						end = buf + n - 1;
369*b30d1939SAndy Fiddaman 						last = *end;
370*b30d1939SAndy Fiddaman 						*end = 0;
371*b30d1939SAndy Fiddaman 						cp = buf - 1;
372*b30d1939SAndy Fiddaman 					}
373*b30d1939SAndy Fiddaman 				}
374*b30d1939SAndy Fiddaman 				else if (n != T_NEWLINE)
375*b30d1939SAndy Fiddaman 					break;
376*b30d1939SAndy Fiddaman 				if (!(flags & S_FLAG) || any || header)
377*b30d1939SAndy Fiddaman 				{
378*b30d1939SAndy Fiddaman 					any = 0;
379*b30d1939SAndy Fiddaman 					header = 0;
380*b30d1939SAndy Fiddaman 					if ((flags & (B_FLAG|N_FLAG)) == N_FLAG)
381*b30d1939SAndy Fiddaman 						sfprintf(op, "%6d\t", line);
382*b30d1939SAndy Fiddaman 					if (flags & E_FLAG)
383*b30d1939SAndy Fiddaman 						sfputc(op, '$');
384*b30d1939SAndy Fiddaman 					sfputc(op, '\n');
385*b30d1939SAndy Fiddaman 				}
386*b30d1939SAndy Fiddaman 				if (!(flags & B_FLAG))
387*b30d1939SAndy Fiddaman 					line++;
388*b30d1939SAndy Fiddaman 			}
389*b30d1939SAndy Fiddaman 			header = flags & (B_FLAG|N_FLAG);
390*b30d1939SAndy Fiddaman 			break;
391*b30d1939SAndy Fiddaman 		}
392*b30d1939SAndy Fiddaman 	}
393*b30d1939SAndy Fiddaman }
394*b30d1939SAndy Fiddaman 
395*b30d1939SAndy Fiddaman int
b_cat(int argc,char ** argv,Shbltin_t * context)396*b30d1939SAndy Fiddaman b_cat(int argc, char** argv, Shbltin_t* context)
397*b30d1939SAndy Fiddaman {
398*b30d1939SAndy Fiddaman 	register int		n;
399*b30d1939SAndy Fiddaman 	register int		flags = 0;
400*b30d1939SAndy Fiddaman 	register char*		cp;
401*b30d1939SAndy Fiddaman 	register Sfio_t*	fp;
402*b30d1939SAndy Fiddaman 	char*			mode;
403*b30d1939SAndy Fiddaman 	Reserve_f		reserve = sfreserve;
404*b30d1939SAndy Fiddaman 	int			att;
405*b30d1939SAndy Fiddaman 	int			dovcat = 0;
406*b30d1939SAndy Fiddaman 	char			states[UCHAR_MAX+1];
407*b30d1939SAndy Fiddaman 
408*b30d1939SAndy Fiddaman 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
409*b30d1939SAndy Fiddaman 	att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att");
410*b30d1939SAndy Fiddaman 	mode = "r";
411*b30d1939SAndy Fiddaman 	for (;;)
412*b30d1939SAndy Fiddaman 	{
413*b30d1939SAndy Fiddaman 		n = 0;
414*b30d1939SAndy Fiddaman 		switch (optget(argv, usage))
415*b30d1939SAndy Fiddaman 		{
416*b30d1939SAndy Fiddaman 		case 'A':
417*b30d1939SAndy Fiddaman 			n = T_FLAG|E_FLAG|V_FLAG;
418*b30d1939SAndy Fiddaman 			break;
419*b30d1939SAndy Fiddaman 		case 'B':
420*b30d1939SAndy Fiddaman 			n = S_FLAG;
421*b30d1939SAndy Fiddaman 			break;
422*b30d1939SAndy Fiddaman 		case 'b':
423*b30d1939SAndy Fiddaman 			n = B_FLAG;
424*b30d1939SAndy Fiddaman 			break;
425*b30d1939SAndy Fiddaman 		case 'd':
426*b30d1939SAndy Fiddaman 			mode = opt_info.num ? "rt" : "r";
427*b30d1939SAndy Fiddaman 			continue;
428*b30d1939SAndy Fiddaman 		case 'D':
429*b30d1939SAndy Fiddaman 			n = d_FLAG;
430*b30d1939SAndy Fiddaman 			break;
431*b30d1939SAndy Fiddaman 		case 'E':
432*b30d1939SAndy Fiddaman 			n = E_FLAG;
433*b30d1939SAndy Fiddaman 			break;
434*b30d1939SAndy Fiddaman 		case 'e':
435*b30d1939SAndy Fiddaman 			n = E_FLAG|V_FLAG;
436*b30d1939SAndy Fiddaman 			break;
437*b30d1939SAndy Fiddaman 		case 'n':
438*b30d1939SAndy Fiddaman 			n = N_FLAG;
439*b30d1939SAndy Fiddaman 			break;
440*b30d1939SAndy Fiddaman 		case 'R':
441*b30d1939SAndy Fiddaman 			reserve = opt_info.num ? regress : sfreserve;
442*b30d1939SAndy Fiddaman 			continue;
443*b30d1939SAndy Fiddaman 		case 's':
444*b30d1939SAndy Fiddaman 			n = att ? F_FLAG : S_FLAG;
445*b30d1939SAndy Fiddaman 			break;
446*b30d1939SAndy Fiddaman 		case 'S':
447*b30d1939SAndy Fiddaman 			n = F_FLAG;
448*b30d1939SAndy Fiddaman 			break;
449*b30d1939SAndy Fiddaman 		case 'T':
450*b30d1939SAndy Fiddaman 			n = T_FLAG;
451*b30d1939SAndy Fiddaman 			break;
452*b30d1939SAndy Fiddaman 		case 't':
453*b30d1939SAndy Fiddaman 			n = T_FLAG|V_FLAG;
454*b30d1939SAndy Fiddaman 			break;
455*b30d1939SAndy Fiddaman 		case 'u':
456*b30d1939SAndy Fiddaman 			n = U_FLAG;
457*b30d1939SAndy Fiddaman 			break;
458*b30d1939SAndy Fiddaman 		case 'v':
459*b30d1939SAndy Fiddaman 			n = V_FLAG;
460*b30d1939SAndy Fiddaman 			break;
461*b30d1939SAndy Fiddaman 		case ':':
462*b30d1939SAndy Fiddaman 			error(2, "%s", opt_info.arg);
463*b30d1939SAndy Fiddaman 			break;
464*b30d1939SAndy Fiddaman 		case '?':
465*b30d1939SAndy Fiddaman 			error(ERROR_usage(2), "%s", opt_info.arg);
466*b30d1939SAndy Fiddaman 			break;
467*b30d1939SAndy Fiddaman 		}
468*b30d1939SAndy Fiddaman 		if (!n)
469*b30d1939SAndy Fiddaman 			break;
470*b30d1939SAndy Fiddaman 		if (opt_info.num)
471*b30d1939SAndy Fiddaman 			flags |= n;
472*b30d1939SAndy Fiddaman 		else
473*b30d1939SAndy Fiddaman 			flags &= ~n;
474*b30d1939SAndy Fiddaman 	}
475*b30d1939SAndy Fiddaman 	argv += opt_info.index;
476*b30d1939SAndy Fiddaman 	if (error_info.errors)
477*b30d1939SAndy Fiddaman 		error(ERROR_usage(2), "%s", optusage(NiL));
478*b30d1939SAndy Fiddaman 	memset(states, 0, sizeof(states));
479*b30d1939SAndy Fiddaman 	if (flags&V_FLAG)
480*b30d1939SAndy Fiddaman 	{
481*b30d1939SAndy Fiddaman 		memset(states, T_CONTROL, ' ');
482*b30d1939SAndy Fiddaman 		states[RUBOUT] = T_CONTROL;
483*b30d1939SAndy Fiddaman 		memset(states+0200, T_EIGHTBIT, 0200);
484*b30d1939SAndy Fiddaman 		memset(states+0200, T_CNTL8BIT, ' ');
485*b30d1939SAndy Fiddaman 		states[RUBOUT|0200] = T_CNTL8BIT;
486*b30d1939SAndy Fiddaman 		states['\n'] = 0;
487*b30d1939SAndy Fiddaman 	}
488*b30d1939SAndy Fiddaman 	if (flags&T_FLAG)
489*b30d1939SAndy Fiddaman 		states['\t'] = T_CONTROL;
490*b30d1939SAndy Fiddaman 	states[0] = T_ENDBUF;
491*b30d1939SAndy Fiddaman 	if (att)
492*b30d1939SAndy Fiddaman 	{
493*b30d1939SAndy Fiddaman 		if (flags&V_FLAG)
494*b30d1939SAndy Fiddaman 		{
495*b30d1939SAndy Fiddaman 			states['\n'|0200] = T_EIGHTBIT;
496*b30d1939SAndy Fiddaman 			if (!(flags&T_FLAG))
497*b30d1939SAndy Fiddaman 			{
498*b30d1939SAndy Fiddaman 				states['\t'] = states['\f'] = 0;
499*b30d1939SAndy Fiddaman 				states['\t'|0200] = states['\f'|0200] = T_EIGHTBIT;
500*b30d1939SAndy Fiddaman 			}
501*b30d1939SAndy Fiddaman 		}
502*b30d1939SAndy Fiddaman 	}
503*b30d1939SAndy Fiddaman 	else if (flags)
504*b30d1939SAndy Fiddaman 	{
505*b30d1939SAndy Fiddaman 		if (!(flags&T_FLAG))
506*b30d1939SAndy Fiddaman 			states['\t'] = 0;
507*b30d1939SAndy Fiddaman 	}
508*b30d1939SAndy Fiddaman 	if (flags&(V_FLAG|T_FLAG|N_FLAG|E_FLAG|B_FLAG|S_FLAG))
509*b30d1939SAndy Fiddaman 	{
510*b30d1939SAndy Fiddaman 		states['\n'] = T_NEWLINE;
511*b30d1939SAndy Fiddaman 		dovcat = 1;
512*b30d1939SAndy Fiddaman 	}
513*b30d1939SAndy Fiddaman 	if (flags&d_FLAG)
514*b30d1939SAndy Fiddaman 		sfopen(sfstdout, NiL, "wt");
515*b30d1939SAndy Fiddaman 	if (cp = *argv)
516*b30d1939SAndy Fiddaman 		argv++;
517*b30d1939SAndy Fiddaman 	do
518*b30d1939SAndy Fiddaman 	{
519*b30d1939SAndy Fiddaman 		if (!cp || streq(cp, "-"))
520*b30d1939SAndy Fiddaman 		{
521*b30d1939SAndy Fiddaman 			fp = sfstdin;
522*b30d1939SAndy Fiddaman 			if (flags&D_FLAG)
523*b30d1939SAndy Fiddaman 				sfopen(fp, NiL, mode);
524*b30d1939SAndy Fiddaman 		}
525*b30d1939SAndy Fiddaman 		else if (!(fp = sfopen(NiL, cp, mode)))
526*b30d1939SAndy Fiddaman 		{
527*b30d1939SAndy Fiddaman 			if (!(flags&F_FLAG))
528*b30d1939SAndy Fiddaman 				error(ERROR_system(0), "%s: cannot open", cp);
529*b30d1939SAndy Fiddaman 			error_info.errors = 1;
530*b30d1939SAndy Fiddaman 			continue;
531*b30d1939SAndy Fiddaman 		}
532*b30d1939SAndy Fiddaman 		if (flags&U_FLAG)
533*b30d1939SAndy Fiddaman 			sfsetbuf(fp, (void*)fp, -1);
534*b30d1939SAndy Fiddaman 		if (dovcat)
535*b30d1939SAndy Fiddaman 			n = vcat(states, fp, sfstdout, reserve, flags);
536*b30d1939SAndy Fiddaman 		else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp))
537*b30d1939SAndy Fiddaman 			n = 0;
538*b30d1939SAndy Fiddaman 		else
539*b30d1939SAndy Fiddaman 			n = -1;
540*b30d1939SAndy Fiddaman 		if (fp != sfstdin)
541*b30d1939SAndy Fiddaman 			sfclose(fp);
542*b30d1939SAndy Fiddaman 		if (n < 0 && !ERROR_PIPE(errno) && errno != EINTR)
543*b30d1939SAndy Fiddaman 		{
544*b30d1939SAndy Fiddaman 			if (cp)
545*b30d1939SAndy Fiddaman 				error(ERROR_system(0), "%s: read error", cp);
546*b30d1939SAndy Fiddaman 			else
547*b30d1939SAndy Fiddaman 				error(ERROR_system(0), "read error");
548*b30d1939SAndy Fiddaman 		}
549*b30d1939SAndy Fiddaman 		if (sferror(sfstdout))
550*b30d1939SAndy Fiddaman 			break;
551*b30d1939SAndy Fiddaman 	} while (cp = *argv++);
552*b30d1939SAndy Fiddaman 	if (sfsync(sfstdout))
553*b30d1939SAndy Fiddaman 		error(ERROR_system(0), "write error");
554*b30d1939SAndy Fiddaman 	if (flags&d_FLAG)
555*b30d1939SAndy Fiddaman 		sfopen(sfstdout, NiL, "w");
556*b30d1939SAndy Fiddaman 	return error_info.errors;
557*b30d1939SAndy Fiddaman }
558