retire old cat
This commit is contained in:
2
Retired/cat/Makefile
Normal file
2
Retired/cat/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
cat: cat.c
|
||||
$(CC) -g -o cat cat.c
|
||||
44
Retired/cat/cat.1
Normal file
44
Retired/cat/cat.1
Normal file
@@ -0,0 +1,44 @@
|
||||
.TH CAT 1
|
||||
|
||||
.SH NAME
|
||||
|
||||
cat \(en catenate files
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
cat
|
||||
.RB ( -hu )
|
||||
.RB ( file... )
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Cat prints the contents of file arguments, one after the other.
|
||||
.PP
|
||||
The
|
||||
.B -h
|
||||
option prints the usage synopsis.
|
||||
|
||||
.SH BUFFERING
|
||||
|
||||
Output is not buffered.
|
||||
.PP
|
||||
The
|
||||
.B -u
|
||||
option that typically guarantees that output is not buffered is a no-op within this program,
|
||||
and is included for compatibility with other implementations of cat(1) as well as the POSIX.1 standard.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
|
||||
Cat prints an error message and exits with the appropriate status from sysexits(3) if it encounters an error.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
"Catenate" and "concatenate" mean the same thing in the English language.
|
||||
|
||||
.SH STANDARDS
|
||||
|
||||
Cat functions as described in POSIX.1-2017.
|
||||
|
||||
.SH COPYRIGHT
|
||||
|
||||
Public domain.
|
||||
94
Retired/cat/cat.c
Normal file
94
Retired/cat/cat.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <errno.h> /* errno, EBADF, EFAULT, EINVAL, ELOOP, ENAMETOOLONG,
|
||||
* ENOENT, ENOMEM, ENOTDIR, EOVERFLOW */
|
||||
#include <stdio.h> /* fprintf(3), getc(3), putc(3), setvbuf(3), stderr, stdin,
|
||||
* stdout */
|
||||
#include <string.h> /* strerror(3) */
|
||||
#include <sysexits.h> /* EX_DATAERR, EX_NOINPUT, EX_OK, EX_OSERR,
|
||||
* EX_UNAVAILABLE, EX_USAGE */
|
||||
#include <unistd.h> /* getopt(3) */
|
||||
#include <sys/stat.h> /* stat(2), struct stat, S_ISDIR */
|
||||
|
||||
static char *program_name = "cat";
|
||||
|
||||
/* NetBSD's default size according to an strace */
|
||||
static unsigned char buf[4096];
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
char *argv0;
|
||||
int c;
|
||||
struct stat fi; /* info */
|
||||
char *fn; /* name */
|
||||
FILE *fo; /* object */
|
||||
|
||||
setvbuf(stdout, (char *)buf, _IOFBF, (sizeof buf)/(sizeof *buf));
|
||||
if(argc < 2){
|
||||
argv0 = argc > 0
|
||||
? argv[0]
|
||||
: program_name;
|
||||
argv -= argv[0] == NULL;
|
||||
goto simple;
|
||||
}
|
||||
|
||||
while((c = getopt(argc, argv, "hu")) != -1)
|
||||
switch(c){
|
||||
case 'u':
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s (-h) (file...)\n",
|
||||
argv[0]);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
argv0 = argv[0];
|
||||
argv += optind;
|
||||
|
||||
while(*argv != NULL){
|
||||
if(argv[0][0] == '-' && argv[0][1] == '\0') /* "-" */
|
||||
simple: fo = stdin;
|
||||
else{
|
||||
fn = argv[0];
|
||||
if(stat(fn, &fi) == -1){
|
||||
fprintf(stderr, "%s: %s: %s\n", argv0, fn,
|
||||
strerror(errno));
|
||||
switch(errno){
|
||||
case EFAULT: case ENOENT: case ENOTDIR:
|
||||
return EX_NOINPUT;
|
||||
case EBADF: case EINVAL: case ENOMEM:
|
||||
case EOVERFLOW:
|
||||
return EX_OSERR;
|
||||
case ELOOP: case ENAMETOOLONG:
|
||||
return EX_DATAERR;
|
||||
}
|
||||
}
|
||||
if(S_ISDIR(fi.st_mode)){
|
||||
fprintf(stderr, "%s: %s: Is a directory\n",
|
||||
argv[0], fn);
|
||||
return EX_DATAERR;
|
||||
}
|
||||
if((fo = fopen(fn, "r")) == NULL){
|
||||
fprintf(stderr,
|
||||
"%s: %s: %s\n",
|
||||
argv0, fn, strerror(errno));
|
||||
return EX_OSERR;
|
||||
}
|
||||
}
|
||||
|
||||
while((c = getc(fo)) != EOF)
|
||||
if(putc(c, stdout) == EOF){
|
||||
fprintf(stderr,
|
||||
"%s: Exiting due to error writing to"
|
||||
" output...\n",
|
||||
argv0);
|
||||
fclose(fo);
|
||||
return EX_UNAVAILABLE;
|
||||
}
|
||||
|
||||
if(fo != stdin)
|
||||
fclose(fo);
|
||||
|
||||
++argv;
|
||||
}
|
||||
|
||||
return EX_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user