working on cat(1)
This commit is contained in:
parent
278f8f57a7
commit
980b4bae35
44
cat/cat.1
Normal file
44
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.
|
104
cat/cat.c
Normal file
104
cat/cat.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user