/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Concatenate files.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <widec.h>
#include <wctype.h>
#include <limits.h>
#include <libintl.h>
static long ibsize;
static long obsize;
int
{
int c;
extern int optind;
int errflg = 0;
int stdinflg = 0;
int status = 0;
int estatus = 0;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
#ifdef STANDALONE
/*
* If the first argument is NULL,
* discard arguments until we find cat.
*/
if (argv[0][0] == '\0')
#endif
/*
* Process the options for cat.
*/
switch (c) {
case 'u':
/*
* If not standalone, set stdout to
* completely unbuffered I/O when
* the 'u' option is used.
*/
#ifndef STANDALONE
#endif
continue;
case 's':
/*
* The 's' option requests silent mode
* where no messages are written.
*/
silent++;
continue;
case 'v':
/*
* The 'v' option requests that non-printing
* characters (with the exception of newlines,
* form-feeds, and tabs) be displayed visibly.
*
* Control characters are printed as "^x".
* DEL characters are printed as "^?".
* Non-printable and non-contrlol characters with the
* 8th bit set are printed as "M-x".
*/
visi_mode++;
continue;
case 't':
/*
* When in visi_mode, this option causes tabs
* to be displayed as "^I".
*/
visi_tab++;
continue;
case 'e':
/*
* When in visi_mode, this option causes newlines
* and form-feeds to be displayed as "$" at the end
* of the line prior to the newline.
*/
visi_newline++;
continue;
case 'b':
/*
* Precede each line output with its line number,
* but omit the line numbers from blank lines.
*/
bflg++;
nflg++;
continue;
case 'n':
/*
* Precede each line output with its line number.
*/
nflg++;
continue;
case '?':
errflg++;
break;
}
break;
}
if (errflg) {
if (!silent)
gettext("usage: cat [ -usvtebn ] [-|file] ...\n"));
exit(2);
}
/*
* Stat stdout to be sure it is defined.
*/
if (!silent)
gettext("cat: Cannot stat stdout\n"));
exit(2);
}
/*
* If no arguments given, then use stdin for input.
*/
argc++;
stdinflg++;
}
/*
* Process each remaining argument,
* unless there is an error with stdout.
*/
/*
* If the argument was '-' or there were no files
* specified, take the input from stdin.
*/
if (stdinflg ||
else {
/*
* Attempt to open each specified file.
*/
if (!silent)
"cat: cannot open %s: %s\n"),
status = 2;
continue;
}
}
/*
* Stat source to make sure it is defined.
*/
if (!silent)
gettext("cat: cannot stat %s: %s\n"),
status = 2;
continue;
}
/*
* If the source is not a character special file, socket or a
* block special file, make sure it is not identical
* to the target.
*/
if (!silent)
gettext("cat: close error: %s\n"),
status = 2;
continue;
}
/*
* otherwise, use cat.
*/
else
if (estatus)
/*
* If the input is not stdin, close the source file.
*/
if (!silent)
gettext("cat: close error: %s\n"),
}
}
/*
* Display any error with stdout operations.
*/
if (!silent)
status = 2;
}
return (status);
}
static int
{
int nitems;
int nwritten;
int offset;
int fi_desc;
long buffsize;
char *bufferp;
/*
* Mmap time!
*/
mapsize = 0; /* I guess we can't mmap today */
} else
mapsize = 0; /* can't mmap non-regular files */
if (mapsize != 0) {
int read_error = 0;
char x;
/*
* NFS V2 will let root open a file it does not have permission
* to read. This read() is here to make sure that the access
* time on the input file will be updated. The VSC tests for
* cat do this:
* In this case the write()/mmap() pair will not read the file
* and the access time will not be updated.
*/
read_error = 1;
mapoffset = 0;
for (;;) {
/*
* Note that on some systems (V7), very large writes to
* a pipe return less than the requested size of the
* write. In this case, multiple writes are required.
*/
offset = 0;
do {
if (!silent) {
if (read_error == 1)
(void) fprintf(
"cat: cannot read "
"%s: "), filenm);
else
"cat: write "
"error: "));
perror("");
}
(size_t)munmapsize);
SEEK_SET);
return (2);
}
if (filesize == 0)
break;
if (!silent)
SEEK_SET);
return (1);
}
}
/*
* Move the file pointer past what we read. Shell scripts
* rely on cat to do this, so that successive commands in
* the script won't re-read the same data.
*/
} else {
} else {
if (obsize)
/*
* common case, use output blksize
*/
else if (ibsize)
else
if (buffsize <= SMALLFILESIZE) {
} else if ((bufferp =
return (1);
}
}
/*
* While not end of file, copy blocks to stdout.
*/
0) {
offset = 0;
/*
* Note that on some systems (V7), very large writes
* to a pipe return less than the requested size of
* the write. In this case, multiple writes are
* required.
*/
do {
if (nwritten < 0) {
if (!silent) {
if (nwritten == -1)
nwritten = 0l;
perror("");
}
return (2);
}
}
if (nitems < 0) {
perror("");
return (1);
}
}
return (0);
}
static int
{
int c;
int lno;
/* = 0 otherwise */
int len, n;
lno = 1;
boln = 1;
for (;;) {
break;
}
c = *p1++;
/*
* Display newlines as "$<newline>"
* if visi_newline set
*/
if (c == '\n') {
boln = 1;
if (visi_mode && visi_newline)
(void) putchar('$');
(void) putchar(c);
continue;
}
boln = 0;
/*
* For non-printable and non-cntrl chars,
* use the "M-x" notation.
*/
if (isascii(c)) {
(void) putchar(c);
continue;
}
/*
* For non-printable ascii characters.
*/
if (iscntrl(c)) {
/* For cntrl characters. */
if ((c == '\t') || (c == '\f')) {
/*
* Display tab as "^I" if visi_tab set
*/
(void) putchar('^');
(void) putchar(c^0100);
} else
(void) putchar(c);
continue;
}
(void) putchar('^');
(void) putchar(c^0100);
continue;
}
continue;
}
/*
* For non-ascii characters.
*/
p1--;
for (n = 0; n < len; n++)
}
len = MB_LEN_MAX;
continue;
}
}
(void) putchar('M');
(void) putchar('-');
c -= 0200;
if (isprint(c)) {
(void) putchar(c);
}
/* For non-printable characters. */
if (iscntrl(c)) {
/* For cntrl characters. */
if ((c == '\t') || (c == '\f')) {
/*
* Display tab as "^I" if visi_tab set
*/
(void) putchar('^');
(void) putchar(c^0100);
} else
(void) putchar(c);
} else {
(void) putchar('^');
(void) putchar(c^0100);
}
}
p1++;
}
return (0);
}