1
0
src/cat/cat.c
2023-10-08 12:11:44 -04:00

95 lines
2.1 KiB
C

#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;
}