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