95 lines
2.1 KiB
C
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;
|
|
}
|