1
0

can't work any less than before

This commit is contained in:
dtb 2023-08-14 20:24:57 -04:00
parent 4393dcac21
commit 54f69b21ed

186
cat/cat.c
View File

@ -1,104 +1,106 @@
#include <errno.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
#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 <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 */
/* NetBSD's default according to an strace */
#define BUFFER 4096
static unsigned char buf[BUFFER];
static char *program_name = "cat";
/* NetBSD's default size according to an strace */
static unsigned char buf[4096];
static char **default_argv = {
(char [])"cat",
(char [])"-",
NULL
}
static char *program_name = *default_argv;
static char *stdout_name = "/dev/stdout";
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 arguing;
int c;
int fd;
int multiple_files;
extern int errno;
extern int opterr;
extern int optind;
struct stat fi; /* info */
char *fn; /* name */
FILE *fo; /* object */
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;
setvbuf(stdout, buf, _IOFBF, (sizeof buf)/(sizeof *buf));
if(argc < 2){
argc = 2;
if(argc > 0)
default_argv[0] = argv[0];
argv = default_argv;
}
arguing = 1;
opterr = 0;
while(optind < argc){
if(arguing && (c = getopt(argc, argv, "hu")) != -1)
switch(c){
case 'u':
setvbuf(stdout, NULL, _IONBF, 0);
continue;
case '-':
arguing = 0;
continue;
case 'h': default: usage:
fprintf(stderr, "Usage: %s (-h) (file...)\n",
argv[0]);
return EX_USAGE;
}
if(arguing && *argv[optind] == '-'){ /* "--" */
arguing = 0;
continue;
if(*argv[optind] == '-' && argv[optind][1] == '\0'){ /* "-" */
fn = stdout_name;
fo = stdout;
}else{
fn = argv[optind];
if(stat(fn, &fi) == -1){
fclose(fo);
switch(errno){
case EFAULT: case ENOENT: case ENOTDIR:
fprintf(stderr,
"%s: %s: Unable to open file."
" Does it exist?\n",
argv[0], fn);
return EX_NOINPUT;
case EBADF: case EINVAL: case ENOMEM:
case EOVERFLOW:
fprintf(stderr,
"%s: %s: System error"
" (errno=%d),\n",
argv[0], fn, errno);
return EX_OSERR;
case ELOOP: case ENAMETOOLONG:
fprintf(stderr,
"%s: %s: Unable to open file.",
argv[0], fn);
return EX_DATAERR;
}
}
if(S_ISDIR(fi.st_mode)){
fclose(fo);
fprintf(stderr, "%s: %s: Is a directory.\n",
argv[0], fn);
return EX_DATAERR;
}
}else if(multiple_files){
/* `cat good_file good_file ...` */
}
for(b = 0; b == -1;){
while((c = getc(fo)) != EOF)
if(putc(c, stdout) == EOF){
fprintf(stderr,
"%s: Exiting due to error writing to"
" output...\n",
argv[0]);
fclose(fo);
return EX_UNAVAILABLE;
}
}
if(fd < 0 && fd > 2)
close(fd);
}while(--argc > 0);
++optind;
}
return EX_OK;
}