Skip to content

Commit

Permalink
Added better error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mckenney5 committed Jun 16, 2023
1 parent d57ff64 commit 0675a56
Showing 1 changed file with 8 additions and 15 deletions.
23 changes: 8 additions & 15 deletions src/cat.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* A way slimmer version of cat without the GNU bloat features that I have never used nor needed */
#include <stdio.h> //fprintf, perror
#include <stdlib.h> //exit
#include <err.h> //err, errx
#include <unistd.h> //read, write, close
#include <sys/types.h> //stat
#include <sys/stat.h> //stat
Expand All @@ -13,36 +14,28 @@
#define BUFF_SIZE 10000 //a larger buffer trades memory for speed
#define MAX_SENDFILE_LINUX 2147479552 //max file size for sendfile in Linux

void throw_error(const char* extra_msg, const int exit_code){
/* function to writes the program name, optionally extra info, then the error to stderr */
if(extra_msg != NULL) fprintf(stderr, "%s: %s: ", NAME, extra_msg);
else fprintf(stderr, "%s: ", NAME);
perror("");
if(exit_code) exit(exit_code); //allows non-fatal errors to keep going
}
void cat(const int fd, const char no_buf, size_t size){
/* reads from the file descriptor into buf, until zero bytes are read */
//tries sendfile if available (since it is faster, if not, do sys read & write)
if(fd == STDIN_FILENO || size > MAX_SENDFILE_LINUX || sendfile(STDOUT_FILENO, fd, 0, size) != size){
size_t r = 0;
if(no_buf) size = 1;
void *buf = (void*)malloc(size);
if(buf == NULL) throw_error("Buffer Allocation", 4);
if(buf == NULL) err(EXIT_FAILURE, "while allocating buf in cat()");
while((r=read(fd, buf, size)) > 0)
if(write(STDOUT_FILENO, buf, r) != r) throw_error(NULL, 3); //if writing stops for some reason
if(r == -1) throw_error(NULL, 1); //if read(2) throws an error
if(write(STDOUT_FILENO, buf, r) != r) err(EXIT_FAILURE, "while writing to fd in cat(). %ld bytes were written", r); //if writing stops for some reason
if(r == -1) err(EXIT_FAILURE, "while reading fd in cat()."); //if read(2) throws an error
free(buf);
} //else
// throw_error("Unable to cat file.", 1);
}
}
void get_file(const char* file_name, const char no_buf){
/* tries to open the user's file, then calls cat() with its file pointer */
if(file_name[0] == '-' && file_name[1] == '\0'){ cat(STDIN_FILENO, no_buf, BUFF_SIZE); return;}
struct stat buffer;
int fd = -1, status = stat(file_name, &buffer);
if(status != 0) throw_error(file_name, 1);
if(status != 0) err(EXIT_FAILURE, "while checking file '%s' in get_file()", file_name);
fd = open(file_name, O_RDONLY);
if(fd == -1) throw_error(file_name, 1);
if(fd == -1) err(EXIT_FAILURE, "while opening file '%s' in get_file()", file_name);
cat(fd, no_buf, buffer.st_size);
close(fd);
}
Expand All @@ -55,7 +48,7 @@ int main(int argc, char *argv[]){
else if(argv[i][0] == '-' && argv[i][1] != '\0'){ //if its a command line arg
if(argv[i][1] == 'h') { puts(HELP); return 0; }
else if(argv[i][1] == 'u') no_buf = 1; //required by POSIX, turns off buffered output
else { fprintf(stderr, "%s: unknown command line arg '%s'\n", NAME, argv[i]); return 2;}
else errx(EXIT_FAILURE, "while reading command line arg %ld in main(): unknown command line arg '%s'\n", i, argv[i]);
} else {
for( ; i < argc; i++) get_file(argv[i], no_buf); //step through each arg as if it's a file, even if its a -
}
Expand Down

0 comments on commit 0675a56

Please sign in to comment.