xref: /onnv-gate/usr/src/lib/libcmd/common/cat.c (revision 10898)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*10898Sroland.mainz@nrubsig.org *          Copyright (c) 1992-2009 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                                                                      *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin /*
234887Schin  * David Korn
244887Schin  * Glenn Fowler
254887Schin  * AT&T Bell Laboratories
264887Schin  *
274887Schin  * cat
284887Schin  */
294887Schin 
304887Schin #include <cmd.h>
314887Schin #include <fcntl.h>
324887Schin 
334887Schin static const char usage[] =
34*10898Sroland.mainz@nrubsig.org "[-?\n@(#)$Id: cat (AT&T Research) 2009-03-31 $\n]"
354887Schin USAGE_LICENSE
364887Schin "[+NAME?cat - concatenate files]"
374887Schin "[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard"
384887Schin "	output. If no \afile\a is given, or if the \afile\a is \b-\b,"
394887Schin "	\bcat\b copies from standard input starting at the current location.]"
404887Schin 
414887Schin "[b:number-nonblank?Number lines as with \b-n\b but omit line numbers from"
424887Schin "	blank lines.]"
434887Schin "[d:dos-input?Input files are opened in \atext\amode which removes carriage"
444887Schin "	returns in front of new-lines on some systems.]"
454887Schin "[e?Equivalent to \b-vE\b.]"
464887Schin "[n:number?Causes a line number to be inserted at the beginning of each line.]"
474887Schin "[s?Equivalent to \b-S\b for \aatt\a universe and \b-B\b otherwise.]"
484887Schin "[t?Equivalent to \b-vT\b.]"
494887Schin "[u:unbuffer?The output is not delayed by buffering.]"
504887Schin "[v:show-nonprinting?Causes non-printing characters (whith the exception of"
514887Schin "	tabs, new-lines, and form-feeds) to be output as printable charater"
524887Schin "	sequences. ASCII control characters are printed as \b^\b\an\a,"
534887Schin "	where \an\a is the corresponding ASCII character in the range"
544887Schin "	octal 100-137. The DEL character (octal 0177) is copied"
554887Schin "	as \b^?\b. Other non-printable characters are copied as \bM-\b\ax\a"
564887Schin "	where \ax\a is the ASCII character specified by the low-order seven"
574887Schin "	bits.  Multibyte characters in the current locale are treated as"
584887Schin "	printable characters.]"
594887Schin "[A:show-all?Equivalent to \b-vET\b.]"
604887Schin "[B:squeeze-blank?Multiple adjacent new-line characters are replace by one"
614887Schin "	new-line.]"
624887Schin "[D:dos-output?Output files are opened in \atext\amode which inserts carriage"
634887Schin "	returns in front of new-lines on some systems.]"
644887Schin "[E:show-ends?Causes a \b$\b to be inserted before each new-line.]"
65*10898Sroland.mainz@nrubsig.org "[R:regress?Regression test defaults: \b-v\b buffer size 4.]"
664887Schin "[S:silent?\bcat\b is silent about non-existent files.]"
674887Schin "[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]"
684887Schin 
694887Schin "\n"
704887Schin "\n[file ...]\n"
714887Schin "\n"
724887Schin 
734887Schin "[+SEE ALSO?\bcp\b(1), \bgetconf\b(1), \bpr\b(1)]"
744887Schin ;
754887Schin 
764887Schin #define RUBOUT	0177
774887Schin 
784887Schin /* control flags */
794887Schin #define B_FLAG		(1<<0)
804887Schin #define E_FLAG		(1<<1)
814887Schin #define F_FLAG		(1<<2)
824887Schin #define N_FLAG		(1<<3)
834887Schin #define S_FLAG		(1<<4)
844887Schin #define T_FLAG		(1<<5)
854887Schin #define U_FLAG		(1<<6)
864887Schin #define V_FLAG		(1<<7)
874887Schin #define D_FLAG		(1<<8)
884887Schin #define d_FLAG		(1<<9)
894887Schin 
904887Schin /* character types */
91*10898Sroland.mainz@nrubsig.org #define T_ERROR		1
92*10898Sroland.mainz@nrubsig.org #define T_EOF		2
93*10898Sroland.mainz@nrubsig.org #define T_ENDBUF	3
94*10898Sroland.mainz@nrubsig.org #define T_NEWLINE	4
95*10898Sroland.mainz@nrubsig.org #define T_CONTROL	5
96*10898Sroland.mainz@nrubsig.org #define T_EIGHTBIT	6
97*10898Sroland.mainz@nrubsig.org #define T_CNTL8BIT	7
984887Schin 
994887Schin #define printof(c)	((c)^0100)
1004887Schin 
101*10898Sroland.mainz@nrubsig.org typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int);
102*10898Sroland.mainz@nrubsig.org 
103*10898Sroland.mainz@nrubsig.org #ifndef sfvalue
104*10898Sroland.mainz@nrubsig.org #define sfvalue(f)	((f)->_val)
105*10898Sroland.mainz@nrubsig.org #endif
106*10898Sroland.mainz@nrubsig.org 
107*10898Sroland.mainz@nrubsig.org static void*
108*10898Sroland.mainz@nrubsig.org regress(Sfio_t* sp, ssize_t n, int f)
109*10898Sroland.mainz@nrubsig.org {
110*10898Sroland.mainz@nrubsig.org 	void*	r;
111*10898Sroland.mainz@nrubsig.org 
112*10898Sroland.mainz@nrubsig.org 	if (!(r = sfreserve(sp, 4, f)))
113*10898Sroland.mainz@nrubsig.org 		r = sfreserve(sp, n, f);
114*10898Sroland.mainz@nrubsig.org 	else if (sfvalue(sp) > 4)
115*10898Sroland.mainz@nrubsig.org 		sfvalue(sp) = 4;
116*10898Sroland.mainz@nrubsig.org 	return r;
117*10898Sroland.mainz@nrubsig.org }
118*10898Sroland.mainz@nrubsig.org 
1194887Schin /*
1204887Schin  * called for any special output processing
1214887Schin  */
1224887Schin 
1234887Schin static int
124*10898Sroland.mainz@nrubsig.org vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags)
1254887Schin {
1264887Schin 	register unsigned char*	cp;
127*10898Sroland.mainz@nrubsig.org 	register unsigned char*	pp;
128*10898Sroland.mainz@nrubsig.org 	unsigned char*		cur;
129*10898Sroland.mainz@nrubsig.org 	unsigned char*		end;
130*10898Sroland.mainz@nrubsig.org 	unsigned char*		buf;
131*10898Sroland.mainz@nrubsig.org 	unsigned char*		nxt;
1324887Schin 	register int		n;
133*10898Sroland.mainz@nrubsig.org 	register int		line;
134*10898Sroland.mainz@nrubsig.org 	register int		raw;
135*10898Sroland.mainz@nrubsig.org 	int			last;
136*10898Sroland.mainz@nrubsig.org 	int			c;
137*10898Sroland.mainz@nrubsig.org 	int			m;
138*10898Sroland.mainz@nrubsig.org 	int			any;
139*10898Sroland.mainz@nrubsig.org 	int			header;
1404887Schin 
1414887Schin 	unsigned char		meta[4];
142*10898Sroland.mainz@nrubsig.org 	unsigned char		tmp[32];
1434887Schin 
1444887Schin 	meta[0] = 'M';
1454887Schin 	meta[1] = '-';
146*10898Sroland.mainz@nrubsig.org 	last = -1;
147*10898Sroland.mainz@nrubsig.org 	*(cp = buf = end = tmp) = 0;
148*10898Sroland.mainz@nrubsig.org 	any = 0;
149*10898Sroland.mainz@nrubsig.org 	header = flags & (B_FLAG|N_FLAG);
150*10898Sroland.mainz@nrubsig.org 	line = 1;
151*10898Sroland.mainz@nrubsig.org 	states[0] = T_ENDBUF;
152*10898Sroland.mainz@nrubsig.org 	raw = !mbwide();
1534887Schin 	for (;;)
1544887Schin 	{
155*10898Sroland.mainz@nrubsig.org 		cur = cp;
156*10898Sroland.mainz@nrubsig.org 		if (raw)
157*10898Sroland.mainz@nrubsig.org 			while (!(n = states[*cp++]));
158*10898Sroland.mainz@nrubsig.org 		else
159*10898Sroland.mainz@nrubsig.org 			for (;;)
160*10898Sroland.mainz@nrubsig.org 			{
161*10898Sroland.mainz@nrubsig.org 				while (!(n = states[*cp++]));
162*10898Sroland.mainz@nrubsig.org 				if (n < T_CONTROL)
163*10898Sroland.mainz@nrubsig.org 					break;
164*10898Sroland.mainz@nrubsig.org 				if ((m = mbsize(pp = cp - 1)) > 1)
165*10898Sroland.mainz@nrubsig.org 					cp += m - 1;
166*10898Sroland.mainz@nrubsig.org 				else
167*10898Sroland.mainz@nrubsig.org 				{
168*10898Sroland.mainz@nrubsig.org 					if (m <= 0)
169*10898Sroland.mainz@nrubsig.org 					{
170*10898Sroland.mainz@nrubsig.org 						if (cur == pp)
171*10898Sroland.mainz@nrubsig.org 						{
172*10898Sroland.mainz@nrubsig.org 							if (last > 0)
173*10898Sroland.mainz@nrubsig.org 							{
174*10898Sroland.mainz@nrubsig.org 								*end = last;
175*10898Sroland.mainz@nrubsig.org 								last = -1;
176*10898Sroland.mainz@nrubsig.org 								c = end - pp + 1;
177*10898Sroland.mainz@nrubsig.org 								if ((m = mbsize(pp)) == c)
178*10898Sroland.mainz@nrubsig.org 								{
179*10898Sroland.mainz@nrubsig.org 									any = 1;
180*10898Sroland.mainz@nrubsig.org 									if (header)
181*10898Sroland.mainz@nrubsig.org 									{
182*10898Sroland.mainz@nrubsig.org 										header = 0;
183*10898Sroland.mainz@nrubsig.org 										sfprintf(op, "%6d\t", line);
184*10898Sroland.mainz@nrubsig.org 									}
185*10898Sroland.mainz@nrubsig.org 									sfwrite(op, cur, m);
186*10898Sroland.mainz@nrubsig.org 									*(cp = cur = end) = 0;
187*10898Sroland.mainz@nrubsig.org 								}
188*10898Sroland.mainz@nrubsig.org 								else
189*10898Sroland.mainz@nrubsig.org 								{
190*10898Sroland.mainz@nrubsig.org 									memcpy(tmp, pp, c);
191*10898Sroland.mainz@nrubsig.org 									if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
192*10898Sroland.mainz@nrubsig.org 									{
193*10898Sroland.mainz@nrubsig.org 										states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
194*10898Sroland.mainz@nrubsig.org 										*(cp = end = tmp + sizeof(tmp) - 1) = 0;
195*10898Sroland.mainz@nrubsig.org 										last = -1;
196*10898Sroland.mainz@nrubsig.org 									}
197*10898Sroland.mainz@nrubsig.org 									else if ((n = sfvalue(ip)) <= 0)
198*10898Sroland.mainz@nrubsig.org 									{
199*10898Sroland.mainz@nrubsig.org 										states[0] = n ? T_ERROR : T_EOF;
200*10898Sroland.mainz@nrubsig.org 										*(cp = end = tmp + sizeof(tmp) - 1) = 0;
201*10898Sroland.mainz@nrubsig.org 										last = -1;
202*10898Sroland.mainz@nrubsig.org 									}
203*10898Sroland.mainz@nrubsig.org 									else
204*10898Sroland.mainz@nrubsig.org 									{
205*10898Sroland.mainz@nrubsig.org 										cp = buf = nxt;
206*10898Sroland.mainz@nrubsig.org 										end = buf + n - 1;
207*10898Sroland.mainz@nrubsig.org 										last = *end;
208*10898Sroland.mainz@nrubsig.org 										*end = 0;
209*10898Sroland.mainz@nrubsig.org 									}
210*10898Sroland.mainz@nrubsig.org  mb:
211*10898Sroland.mainz@nrubsig.org 									if ((n = end - cp + 1) >= (sizeof(tmp) - c))
212*10898Sroland.mainz@nrubsig.org 										n = sizeof(tmp) - c - 1;
213*10898Sroland.mainz@nrubsig.org 									memcpy(tmp + c, cp, n);
214*10898Sroland.mainz@nrubsig.org 									if ((m = mbsize(tmp)) >= c)
215*10898Sroland.mainz@nrubsig.org 									{
216*10898Sroland.mainz@nrubsig.org 										any = 1;
217*10898Sroland.mainz@nrubsig.org 										if (header)
218*10898Sroland.mainz@nrubsig.org 										{
219*10898Sroland.mainz@nrubsig.org 											header = 0;
220*10898Sroland.mainz@nrubsig.org 											sfprintf(op, "%6d\t", line);
221*10898Sroland.mainz@nrubsig.org 										}
222*10898Sroland.mainz@nrubsig.org 										sfwrite(op, tmp, m);
223*10898Sroland.mainz@nrubsig.org 										cur = cp += m - c;
224*10898Sroland.mainz@nrubsig.org 									}
225*10898Sroland.mainz@nrubsig.org 								}
226*10898Sroland.mainz@nrubsig.org 								continue;
227*10898Sroland.mainz@nrubsig.org 							}
228*10898Sroland.mainz@nrubsig.org 						}
229*10898Sroland.mainz@nrubsig.org 						else
230*10898Sroland.mainz@nrubsig.org 						{
231*10898Sroland.mainz@nrubsig.org 							cp = pp + 1;
232*10898Sroland.mainz@nrubsig.org 							n = 0;
233*10898Sroland.mainz@nrubsig.org 						}
234*10898Sroland.mainz@nrubsig.org 					}
235*10898Sroland.mainz@nrubsig.org 					break;
236*10898Sroland.mainz@nrubsig.org 				}
237*10898Sroland.mainz@nrubsig.org 			}
238*10898Sroland.mainz@nrubsig.org 		c = *--cp;
239*10898Sroland.mainz@nrubsig.org 		if ((m = cp - cur) || n >= T_CONTROL)
2404887Schin 		{
241*10898Sroland.mainz@nrubsig.org  flush:
242*10898Sroland.mainz@nrubsig.org 			any = 1;
243*10898Sroland.mainz@nrubsig.org 			if (header)
244*10898Sroland.mainz@nrubsig.org 			{
245*10898Sroland.mainz@nrubsig.org 				header = 0;
246*10898Sroland.mainz@nrubsig.org 				sfprintf(op, "%6d\t", line);
247*10898Sroland.mainz@nrubsig.org 			}
248*10898Sroland.mainz@nrubsig.org 			if (m)
249*10898Sroland.mainz@nrubsig.org 				sfwrite(op, cur, m);
2504887Schin 		}
251*10898Sroland.mainz@nrubsig.org  special:
252*10898Sroland.mainz@nrubsig.org 		switch (n)
2534887Schin 		{
254*10898Sroland.mainz@nrubsig.org 		case T_ERROR:
255*10898Sroland.mainz@nrubsig.org 			if (cp != end)
256*10898Sroland.mainz@nrubsig.org 			{
257*10898Sroland.mainz@nrubsig.org 				n = T_CONTROL;
258*10898Sroland.mainz@nrubsig.org 				goto flush;
259*10898Sroland.mainz@nrubsig.org 			}
260*10898Sroland.mainz@nrubsig.org 			return -1;
261*10898Sroland.mainz@nrubsig.org 		case T_EOF:
262*10898Sroland.mainz@nrubsig.org 			if (cp != end)
263*10898Sroland.mainz@nrubsig.org 			{
264*10898Sroland.mainz@nrubsig.org 				n = T_CONTROL;
265*10898Sroland.mainz@nrubsig.org 				goto flush;
266*10898Sroland.mainz@nrubsig.org 			}
267*10898Sroland.mainz@nrubsig.org 			return 0;
268*10898Sroland.mainz@nrubsig.org 		case T_ENDBUF:
269*10898Sroland.mainz@nrubsig.org 			if (cp != end)
270*10898Sroland.mainz@nrubsig.org 			{
271*10898Sroland.mainz@nrubsig.org 				n = T_CONTROL;
272*10898Sroland.mainz@nrubsig.org 				goto flush;
273*10898Sroland.mainz@nrubsig.org 			}
274*10898Sroland.mainz@nrubsig.org 			c = last;
275*10898Sroland.mainz@nrubsig.org 			if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
276*10898Sroland.mainz@nrubsig.org 			{
277*10898Sroland.mainz@nrubsig.org 				*(cp = end = tmp) = 0;
278*10898Sroland.mainz@nrubsig.org 				states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
279*10898Sroland.mainz@nrubsig.org 				last = -1;
280*10898Sroland.mainz@nrubsig.org 			}
281*10898Sroland.mainz@nrubsig.org 			else if ((m = sfvalue(ip)) <= 0)
282*10898Sroland.mainz@nrubsig.org 			{
283*10898Sroland.mainz@nrubsig.org 				*(cp = end = tmp) = 0;
284*10898Sroland.mainz@nrubsig.org 				states[0] = m ? T_ERROR : T_EOF;
285*10898Sroland.mainz@nrubsig.org 				last = -1;
286*10898Sroland.mainz@nrubsig.org 			}
2874887Schin 			else
2884887Schin 			{
289*10898Sroland.mainz@nrubsig.org 				buf = nxt;
290*10898Sroland.mainz@nrubsig.org 				end = buf + m - 1;
291*10898Sroland.mainz@nrubsig.org 				last = *end;
292*10898Sroland.mainz@nrubsig.org 				*end = 0;
293*10898Sroland.mainz@nrubsig.org 				cp = buf;
294*10898Sroland.mainz@nrubsig.org 			}
295*10898Sroland.mainz@nrubsig.org 			if (c >= 0)
296*10898Sroland.mainz@nrubsig.org 			{
297*10898Sroland.mainz@nrubsig.org 				if (!(n = states[c]))
298*10898Sroland.mainz@nrubsig.org 				{
299*10898Sroland.mainz@nrubsig.org 					*(cur = tmp) = c;
300*10898Sroland.mainz@nrubsig.org 					m = 1;
301*10898Sroland.mainz@nrubsig.org 					goto flush;
302*10898Sroland.mainz@nrubsig.org 				}
303*10898Sroland.mainz@nrubsig.org 				if (raw || n < T_CONTROL)
3044887Schin 				{
305*10898Sroland.mainz@nrubsig.org 					cp--;
306*10898Sroland.mainz@nrubsig.org 					goto special;
307*10898Sroland.mainz@nrubsig.org 				}
308*10898Sroland.mainz@nrubsig.org 				tmp[0] = c;
309*10898Sroland.mainz@nrubsig.org 				c = 1;
310*10898Sroland.mainz@nrubsig.org 				goto mb;
311*10898Sroland.mainz@nrubsig.org 			}
312*10898Sroland.mainz@nrubsig.org 			break;
313*10898Sroland.mainz@nrubsig.org 		case T_CONTROL:
314*10898Sroland.mainz@nrubsig.org 			do
315*10898Sroland.mainz@nrubsig.org 			{
316*10898Sroland.mainz@nrubsig.org 				sfputc(op, '^');
317*10898Sroland.mainz@nrubsig.org 				sfputc(op, printof(c));
318*10898Sroland.mainz@nrubsig.org 			} while (states[c = *++cp] == T_CONTROL);
319*10898Sroland.mainz@nrubsig.org 			break;
320*10898Sroland.mainz@nrubsig.org 		case T_CNTL8BIT:
321*10898Sroland.mainz@nrubsig.org 			meta[2] = '^';
322*10898Sroland.mainz@nrubsig.org 			do
323*10898Sroland.mainz@nrubsig.org 			{
324*10898Sroland.mainz@nrubsig.org 				n = c & ~0200;
325*10898Sroland.mainz@nrubsig.org 				meta[3] = printof(n);
326*10898Sroland.mainz@nrubsig.org 				sfwrite(op, (char*)meta, 4);
327*10898Sroland.mainz@nrubsig.org 			} while (states[c = *++cp] == T_CNTL8BIT && raw);
328*10898Sroland.mainz@nrubsig.org 			break;
329*10898Sroland.mainz@nrubsig.org 		case T_EIGHTBIT:
330*10898Sroland.mainz@nrubsig.org 			do
331*10898Sroland.mainz@nrubsig.org 			{
332*10898Sroland.mainz@nrubsig.org 				meta[2] = c & ~0200;
333*10898Sroland.mainz@nrubsig.org 				sfwrite(op, (char*)meta, 3);
334*10898Sroland.mainz@nrubsig.org 			} while (states[c = *++cp] == T_EIGHTBIT && raw);
335*10898Sroland.mainz@nrubsig.org 			break;
336*10898Sroland.mainz@nrubsig.org 		case T_NEWLINE:
337*10898Sroland.mainz@nrubsig.org 			if (header && !(flags & B_FLAG))
338*10898Sroland.mainz@nrubsig.org 				sfprintf(op, "%6d\t", line);
339*10898Sroland.mainz@nrubsig.org 			if (flags & E_FLAG)
340*10898Sroland.mainz@nrubsig.org 				sfputc(op, '$');
341*10898Sroland.mainz@nrubsig.org 			sfputc(op, '\n');
342*10898Sroland.mainz@nrubsig.org 			if (!header || !(flags & B_FLAG))
343*10898Sroland.mainz@nrubsig.org 				line++;
344*10898Sroland.mainz@nrubsig.org 			header = !(flags & S_FLAG);
345*10898Sroland.mainz@nrubsig.org 			for (;;)
346*10898Sroland.mainz@nrubsig.org 			{
347*10898Sroland.mainz@nrubsig.org 				if ((n = states[*++cp]) == T_ENDBUF)
348*10898Sroland.mainz@nrubsig.org 				{
349*10898Sroland.mainz@nrubsig.org 					if (cp != end || last != '\n')
350*10898Sroland.mainz@nrubsig.org 						break;
351*10898Sroland.mainz@nrubsig.org 					if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
3524887Schin 					{
353*10898Sroland.mainz@nrubsig.org 						states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
354*10898Sroland.mainz@nrubsig.org 						cp = end = tmp;
355*10898Sroland.mainz@nrubsig.org 						*cp-- = 0;
356*10898Sroland.mainz@nrubsig.org 						last = -1;
357*10898Sroland.mainz@nrubsig.org 					}
358*10898Sroland.mainz@nrubsig.org 					else if ((n = sfvalue(ip)) <= 0)
359*10898Sroland.mainz@nrubsig.org 					{
360*10898Sroland.mainz@nrubsig.org 						states[0] = n ? T_ERROR : T_EOF;
361*10898Sroland.mainz@nrubsig.org 						cp = end = tmp;
362*10898Sroland.mainz@nrubsig.org 						*cp-- = 0;
363*10898Sroland.mainz@nrubsig.org 						last = -1;
3644887Schin 					}
3654887Schin 					else
3664887Schin 					{
367*10898Sroland.mainz@nrubsig.org 						buf = nxt;
368*10898Sroland.mainz@nrubsig.org 						end = buf + n - 1;
369*10898Sroland.mainz@nrubsig.org 						last = *end;
370*10898Sroland.mainz@nrubsig.org 						*end = 0;
371*10898Sroland.mainz@nrubsig.org 						cp = buf - 1;
3724887Schin 					}
3734887Schin 				}
374*10898Sroland.mainz@nrubsig.org 				else if (n != T_NEWLINE)
3754887Schin 					break;
376*10898Sroland.mainz@nrubsig.org 				if (!(flags & S_FLAG) || any || header)
377*10898Sroland.mainz@nrubsig.org 				{
378*10898Sroland.mainz@nrubsig.org 					any = 0;
379*10898Sroland.mainz@nrubsig.org 					header = 0;
380*10898Sroland.mainz@nrubsig.org 					if ((flags & (B_FLAG|N_FLAG)) == N_FLAG)
381*10898Sroland.mainz@nrubsig.org 						sfprintf(op, "%6d\t", line);
382*10898Sroland.mainz@nrubsig.org 					if (flags & E_FLAG)
383*10898Sroland.mainz@nrubsig.org 						sfputc(op, '$');
384*10898Sroland.mainz@nrubsig.org 					sfputc(op, '\n');
385*10898Sroland.mainz@nrubsig.org 				}
386*10898Sroland.mainz@nrubsig.org 				if (!(flags & B_FLAG))
387*10898Sroland.mainz@nrubsig.org 					line++;
3884887Schin 			}
389*10898Sroland.mainz@nrubsig.org 			header = flags & (B_FLAG|N_FLAG);
390*10898Sroland.mainz@nrubsig.org 			break;
3914887Schin 		}
3924887Schin 	}
3934887Schin }
3944887Schin 
3954887Schin int
3964887Schin b_cat(int argc, char** argv, void* context)
3974887Schin {
3984887Schin 	register int		n;
3994887Schin 	register int		flags = 0;
4004887Schin 	register char*		cp;
4014887Schin 	register Sfio_t*	fp;
4024887Schin 	char*			mode;
403*10898Sroland.mainz@nrubsig.org 	Reserve_f		reserve = sfreserve;
4044887Schin 	int			att;
405*10898Sroland.mainz@nrubsig.org 	int			dovcat = 0;
4064887Schin 	char			states[UCHAR_MAX+1];
4074887Schin 
4084887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
409*10898Sroland.mainz@nrubsig.org 	setlocale(LC_ALL, "");
4104887Schin 	att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att");
4114887Schin 	mode = "r";
4124887Schin 	for (;;)
4134887Schin 	{
414*10898Sroland.mainz@nrubsig.org 		n = 0;
4154887Schin 		switch (optget(argv, usage))
4164887Schin 		{
4174887Schin 		case 'A':
418*10898Sroland.mainz@nrubsig.org 			n = T_FLAG|E_FLAG|V_FLAG;
419*10898Sroland.mainz@nrubsig.org 			break;
4204887Schin 		case 'B':
421*10898Sroland.mainz@nrubsig.org 			n = S_FLAG;
422*10898Sroland.mainz@nrubsig.org 			break;
4234887Schin 		case 'b':
424*10898Sroland.mainz@nrubsig.org 			n = B_FLAG;
425*10898Sroland.mainz@nrubsig.org 			break;
426*10898Sroland.mainz@nrubsig.org 		case 'd':
427*10898Sroland.mainz@nrubsig.org 			mode = opt_info.num ? "rt" : "r";
4284887Schin 			continue;
429*10898Sroland.mainz@nrubsig.org 		case 'D':
430*10898Sroland.mainz@nrubsig.org 			n = d_FLAG;
431*10898Sroland.mainz@nrubsig.org 			break;
4324887Schin 		case 'E':
433*10898Sroland.mainz@nrubsig.org 			n = E_FLAG;
434*10898Sroland.mainz@nrubsig.org 			break;
4354887Schin 		case 'e':
436*10898Sroland.mainz@nrubsig.org 			n = E_FLAG|V_FLAG;
437*10898Sroland.mainz@nrubsig.org 			break;
4384887Schin 		case 'n':
439*10898Sroland.mainz@nrubsig.org 			n = N_FLAG;
440*10898Sroland.mainz@nrubsig.org 			break;
441*10898Sroland.mainz@nrubsig.org 		case 'R':
442*10898Sroland.mainz@nrubsig.org 			reserve = opt_info.num ? regress : sfreserve;
4434887Schin 			continue;
4444887Schin 		case 's':
445*10898Sroland.mainz@nrubsig.org 			n = att ? F_FLAG : S_FLAG;
446*10898Sroland.mainz@nrubsig.org 			break;
4474887Schin 		case 'S':
448*10898Sroland.mainz@nrubsig.org 			n = F_FLAG;
449*10898Sroland.mainz@nrubsig.org 			break;
4504887Schin 		case 'T':
451*10898Sroland.mainz@nrubsig.org 			n = T_FLAG;
452*10898Sroland.mainz@nrubsig.org 			break;
4534887Schin 		case 't':
454*10898Sroland.mainz@nrubsig.org 			n = T_FLAG|V_FLAG;
455*10898Sroland.mainz@nrubsig.org 			break;
4564887Schin 		case 'u':
457*10898Sroland.mainz@nrubsig.org 			n = U_FLAG;
458*10898Sroland.mainz@nrubsig.org 			break;
4594887Schin 		case 'v':
460*10898Sroland.mainz@nrubsig.org 			n = V_FLAG;
461*10898Sroland.mainz@nrubsig.org 			break;
4624887Schin 		case ':':
4634887Schin 			error(2, "%s", opt_info.arg);
4644887Schin 			break;
4654887Schin 		case '?':
4664887Schin 			error(ERROR_usage(2), "%s", opt_info.arg);
4674887Schin 			break;
4684887Schin 		}
469*10898Sroland.mainz@nrubsig.org 		if (!n)
470*10898Sroland.mainz@nrubsig.org 			break;
471*10898Sroland.mainz@nrubsig.org 		if (opt_info.num)
472*10898Sroland.mainz@nrubsig.org 			flags |= n;
473*10898Sroland.mainz@nrubsig.org 		else
474*10898Sroland.mainz@nrubsig.org 			flags &= ~n;
4754887Schin 	}
4764887Schin 	argv += opt_info.index;
4774887Schin 	if (error_info.errors)
4784887Schin 		error(ERROR_usage(2), "%s", optusage(NiL));
4794887Schin 	memset(states, 0, sizeof(states));
4804887Schin 	if (flags&V_FLAG)
4814887Schin 	{
4824887Schin 		memset(states, T_CONTROL, ' ');
4834887Schin 		states[RUBOUT] = T_CONTROL;
4844887Schin 		memset(states+0200, T_EIGHTBIT, 0200);
4854887Schin 		memset(states+0200, T_CNTL8BIT, ' ');
4864887Schin 		states[RUBOUT|0200] = T_CNTL8BIT;
4874887Schin 		states['\n'] = 0;
4884887Schin 	}
4894887Schin 	if (flags&T_FLAG)
4904887Schin 		states['\t'] = T_CONTROL;
4914887Schin 	states[0] = T_ENDBUF;
4924887Schin 	if (att)
4934887Schin 	{
4944887Schin 		if (flags&V_FLAG)
4954887Schin 		{
4964887Schin 			states['\n'|0200] = T_EIGHTBIT;
4974887Schin 			if (!(flags&T_FLAG))
4984887Schin 			{
4994887Schin 				states['\t'] = states['\f'] = 0;
5004887Schin 				states['\t'|0200] = states['\f'|0200] = T_EIGHTBIT;
5014887Schin 			}
5024887Schin 		}
5034887Schin 	}
5044887Schin 	else if (flags)
5054887Schin 	{
5064887Schin 		if (!(flags&T_FLAG))
5074887Schin 			states['\t'] = 0;
5084887Schin 	}
5098462SApril.Chin@Sun.COM 	if (flags&(V_FLAG|T_FLAG|N_FLAG|E_FLAG|B_FLAG|S_FLAG))
5104887Schin 	{
5114887Schin 		states['\n'] = T_NEWLINE;
5124887Schin 		dovcat = 1;
5134887Schin 	}
5144887Schin 	if (flags&d_FLAG)
5154887Schin 		sfopen(sfstdout, NiL, "wt");
5164887Schin 	if (cp = *argv)
5174887Schin 		argv++;
5184887Schin 	do
5194887Schin 	{
520*10898Sroland.mainz@nrubsig.org 		if (!cp || streq(cp, "-"))
5214887Schin 		{
5224887Schin 			fp = sfstdin;
5234887Schin 			if (flags&D_FLAG)
5244887Schin 				sfopen(fp, NiL, mode);
5254887Schin 		}
5264887Schin 		else if (!(fp = sfopen(NiL, cp, mode)))
5274887Schin 		{
5284887Schin 			if (!(flags&F_FLAG))
5294887Schin 				error(ERROR_system(0), "%s: cannot open", cp);
5304887Schin 			error_info.errors = 1;
5314887Schin 			continue;
5324887Schin 		}
5334887Schin 		if (flags&U_FLAG)
5344887Schin 			sfsetbuf(fp, (void*)fp, -1);
5354887Schin 		if (dovcat)
536*10898Sroland.mainz@nrubsig.org 			n = vcat(states, fp, sfstdout, reserve, flags);
5374887Schin 		else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp))
5384887Schin 			n = 0;
5394887Schin 		else
5404887Schin 			n = -1;
5414887Schin 		if (fp != sfstdin)
5424887Schin 			sfclose(fp);
5434887Schin 		if (n < 0 && errno != EPIPE)
5444887Schin 		{
5454887Schin 			if (cp)
5464887Schin 				error(ERROR_system(0), "%s: read error", cp);
5474887Schin 			else
5484887Schin 				error(ERROR_system(0), "read error");
5494887Schin 		}
5504887Schin 		if (sferror(sfstdout))
5514887Schin 			break;
5524887Schin 	} while (cp = *argv++);
5534887Schin 	if (sfsync(sfstdout))
5544887Schin 		error(ERROR_system(0), "write error");
5554887Schin 	if (flags&d_FLAG)
5564887Schin 		sfopen(sfstdout, NiL, "w");
5574887Schin 	return error_info.errors;
5584887Schin }
559