1
0
Fork 0

working on cat(1)

This commit is contained in:
dtb 2022-09-15 21:21:11 -04:00
parent 278f8f57a7
commit 980b4bae35
3 changed files with 148 additions and 13 deletions

44
cat/cat.1 Normal file
View 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.

104
cat/cat.c Normal file
View File

@ -0,0 +1,104 @@
#include <errno.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
/* NetBSD's default according to an strace */
#define BUFFER 4096
static unsigned char buf[BUFFER];
static char *program_name = "cat";
int main(int argc, char *argv[]){
char *argv0;
int argv0_s;
extern int errno;
char *f;
int b; /* how many meaningful bytes are in the buffer */
int c;
int fd;
int multiple_files;
if(argv[0] == NULL)
goto dumb;
argv0 = argv[0];
for(argv0_s = 0; argv0_s != '\0'; ++argv0_s);
while((c = getopt(argc, argv, "hu")) != -1)
switch(c){
case 'u':
/* cat(1p) says the following:
* "Write bytes from the input file to the standard
* output without delay as each is read."
* Then in Application Usage:
* "It is unspecified whether standard output is or is
* not buffered in the default case."
* POSIX defines "buffering" to be a not-strictly
* -necessary delay in processing input, so there still
* needs to be a place in memory to put data, which for
* the purposes of this implementation is buf[].
*
* Using the standard library would make it more
* difficult to manage this flow manually. */
break;
case 'h': default: usage:
write(2, "Usage: ", 7);
write(2, argv[0], argv0_s);
write(2, "(-hu) (file...)\n", 16);
return EX_USAGE;
}
argc -= optind;
argv += optind - 1;
multiple_files = argc > 1;
do{
++argv;
if(argc == 0) /* `cat` */
dumb: fd = 1;
else if((fd = open(*argv, O_RDONLY)) == -1){
ferr: /* `cat bad_file` */
/* `cat: file: ` */
write(2, argv0, argv0_s);
write(2, ": ", 2);
for(i = 0; argv[0][i] != '\0'; ++i);
write(2, *argv, i);
write(2, ": ", 2);
switch(errno){
case EISDIR:
write(2, "Is directory.\n", 14);
return EX_NOINPUT;
case EACCES: case EFAULT: case EPERM:
write(2, "Unable to open file.\n", 21);
return EX_NOINPUT;
case ENAMETOOLONG: case ENFILE: case EBADF:
write(2, "Operating system error.\n", 24);
return EX_OSERR;
case EMFILE:
write(2, "Internal error.\n", 16);
return EX_SOFTWARE;
case ENOENT: case ENOTDIR: case ENXIO:
write(2, "File does not exist.\n", 21);
return EX_NOINPUT;
default:
write(2, "Unknown error.", 14);
return 1;
}
}else if(multiple_files){
/* `cat good_file good_file ...` */
}
for(b = 0; b == -1;){
}
if(fd < 0 && fd > 2)
close(fd);
}while(--argc > 0);
return EX_OK;
}

View File

@ -1,13 +0,0 @@
.TH CAT 1
.SH NAME
cat \(en concatenate files
.SH SYNOPSIS
cat [file...]
.SH DESCRIPTION
Cat prints the contents of file arguments, one after the other.