1
0
This commit is contained in:
dtb 2023-10-08 12:11:44 -04:00
parent dba3120da6
commit 182720118a
2 changed files with 23 additions and 39 deletions

View File

@ -1,7 +1,2 @@
cat: cat.c cat: cat.c
$(CC) -g -o cat cat.c $(CC) -g -o cat cat.c
clean:
rm -f cat
.PHONY: clean

View File

@ -2,34 +2,31 @@
* ENOENT, ENOMEM, ENOTDIR, EOVERFLOW */ * ENOENT, ENOMEM, ENOTDIR, EOVERFLOW */
#include <stdio.h> /* fprintf(3), getc(3), putc(3), setvbuf(3), stderr, stdin, #include <stdio.h> /* fprintf(3), getc(3), putc(3), setvbuf(3), stderr, stdin,
* stdout */ * stdout */
#include <string.h> /* strerror(3) */
#include <sysexits.h> /* EX_DATAERR, EX_NOINPUT, EX_OK, EX_OSERR, #include <sysexits.h> /* EX_DATAERR, EX_NOINPUT, EX_OK, EX_OSERR,
* EX_UNAVAILABLE, EX_USAGE */ * EX_UNAVAILABLE, EX_USAGE */
#include <unistd.h> /* getopt(3) */ #include <unistd.h> /* getopt(3) */
#include <sys/stat.h> /* stat(2), struct stat, S_ISDIR */ #include <sys/stat.h> /* stat(2), struct stat, S_ISDIR */
static char *program_name = "cat";
/* NetBSD's default size according to an strace */ /* NetBSD's default size according to an strace */
static unsigned char buf[4096]; static unsigned char buf[4096];
static char *default_argv[] = {
"cat",
"-",
(char *)NULL
};
static char *stdin_name = "/dev/stdin";
int main(int argc, char *argv[]){ int main(int argc, char *argv[]){
char *argv0; char *argv0;
int c; int c;
extern int errno;
struct stat fi; /* info */ struct stat fi; /* info */
char *fn; /* name */ char *fn; /* name */
FILE *fo; /* object */ FILE *fo; /* object */
setvbuf(stdout, buf, _IOFBF, (sizeof buf)/(sizeof *buf)); setvbuf(stdout, (char *)buf, _IOFBF, (sizeof buf)/(sizeof *buf));
if(argc < 2){ if(argc < 2){
argc = 2; argv0 = argc > 0
if(argc > 0) ? argv[0]
default_argv[0] = argv[0]; : program_name;
argv = default_argv; argv -= argv[0] == NULL;
goto simple;
} }
while((c = getopt(argc, argv, "hu")) != -1) while((c = getopt(argc, argv, "hu")) != -1)
@ -37,52 +34,42 @@ int main(int argc, char *argv[]){
case 'u': case 'u':
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
continue; continue;
case 'h': default: usage: default:
fprintf(stderr, "Usage: %s (-h) (file...)\n", fprintf(stderr, "Usage: %s (-h) (file...)\n",
argv[0]); argv[0]);
return EX_USAGE; return EX_USAGE;
} }
argv0 = argv[0]; argv0 = argv[0];
argc -= optind;
argv += optind; argv += optind;
while(argc --> 0){ while(*argv != NULL){
if(argv[0][0] == '-' && argv[0][1] == '\0'){ /* "-" */ if(argv[0][0] == '-' && argv[0][1] == '\0') /* "-" */
fn = stdin_name; simple: fo = stdin;
fo = stdin; else{
}else{
fn = argv[0]; fn = argv[0];
if(stat(fn, &fi) == -1){ if(stat(fn, &fi) == -1){
fprintf(stderr, "%s: %s: %s\n", argv0, fn,
strerror(errno));
switch(errno){ switch(errno){
case EFAULT: case ENOENT: case ENOTDIR: case EFAULT: case ENOENT: case ENOTDIR:
fprintf(stderr,
"%s: %s: Unable to open file."
" Does it exist?\n",
argv[0], fn);
return EX_NOINPUT; return EX_NOINPUT;
case EBADF: case EINVAL: case ENOMEM: case EBADF: case EINVAL: case ENOMEM:
case EOVERFLOW: case EOVERFLOW:
fprintf(stderr,
"%s: %s: System error"
" (errno=%d),\n",
argv[0], fn, errno);
return EX_OSERR; return EX_OSERR;
case ELOOP: case ENAMETOOLONG: case ELOOP: case ENAMETOOLONG:
fprintf(stderr,
"%s: %s: Unable to open file.",
argv[0], fn);
return EX_DATAERR; return EX_DATAERR;
} }
} }
if(S_ISDIR(fi.st_mode)){ if(S_ISDIR(fi.st_mode)){
fprintf(stderr, "%s: %s: Is a directory.\n", fprintf(stderr, "%s: %s: Is a directory\n",
argv[0], fn); argv[0], fn);
return EX_DATAERR; return EX_DATAERR;
} }
if((fo = fopen(fn, "r")) == NULL){ if((fo = fopen(fn, "r")) == NULL){
fprintf(stderr, fprintf(stderr,
"%s: %s: Error opening file.\n", "%s: %s: %s\n",
argv[0], fn); argv0, fn, strerror(errno));
return EX_OSERR; return EX_OSERR;
} }
} }
@ -92,13 +79,15 @@ int main(int argc, char *argv[]){
fprintf(stderr, fprintf(stderr,
"%s: Exiting due to error writing to" "%s: Exiting due to error writing to"
" output...\n", " output...\n",
argv[0]); argv0);
fclose(fo); fclose(fo);
return EX_UNAVAILABLE; return EX_UNAVAILABLE;
} }
if(fo != stdin) if(fo != stdin)
fclose(fo); fclose(fo);
++argv;
} }
return EX_OK; return EX_OK;