From 7f5e5322160c73d6a89b4b2fdc64057445fbadb8 Mon Sep 17 00:00:00 2001 From: emma Date: Mon, 28 Aug 2023 23:03:33 -0600 Subject: [PATCH] moved file resolution code to a shared library --- Makefile | 16 ++++++++--- src/cat.c | 56 ++++++-------------------------------- src/false.c | 2 +- src/true.c | 2 +- src/yac.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/yac.h | 26 ++++++++++++++++++ 6 files changed, 125 insertions(+), 54 deletions(-) create mode 100644 src/yac.c create mode 100644 src/yac.h diff --git a/Makefile b/Makefile index b620128..e427c1e 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,10 @@ .POSIX: -PREFIX=/usr/local/bin -CFLAGS=-O3 -s -Wl,-z,noseparate-code,-z,nosectionheader -flto +PREFIX=/usr/local +CFLAGS=-O3 -s -Wl,-z,noseparate-code,-z,nosectionheader -flto -Lbuild -lyac -build: build_dir cat false true +build: build_dir lib cat false tail true clean: build_dir rm -rf build/ @@ -21,12 +21,20 @@ cat: build_dir false: build_dir cc $(CFLAGS) -o build/false src/false.c +tail: build_dir + cc $(CFLAGS) -o build/tail src/tail.c + true: build_dir cc $(CFLAGS) -o build/true src/true.c +lib: + cc -c -fPIC $(CFLAGS) -o build/yac.o src/yac.c + cc $(CFLAGS) -shared -o build/libyac.so build/yac.o + build_dir: mkdir -p build install: build mkdir -p $(PREFIX) - cp -f build/* $(PREFIX)/ + cp -f build/*.so $(PREFIX)/lib/ + cp -f build/* $(PREFIX)/bin/ diff --git a/src/cat.c b/src/cat.c index 4c1f17d..34eb43f 100644 --- a/src/cat.c +++ b/src/cat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Emma Tebibyte + * Copyright (c) 2023 Emma Tebibyte * SPDX-License-Identifier: AGPL-3.0-or-later * * This file is part of YAC coreutils. @@ -25,6 +25,8 @@ #include #include +#include "yac.h" + void cat(FILE *file, bool u) { int byte = 0; /* variable for storing bytes as they are read */ int p = 0; /* index counter for bytes in buffered reading */ @@ -89,55 +91,13 @@ int main(int argc, char *argv[]) { } FILE *file; - struct stat stats; for (i = optind; i < argc; i++) { - if (argv[i][0] == '-') { - switch (argv[i][1]) { - case '\0': - file = stdin; - break; - default: - continue; - } - } else if (stat(argv[i], &stats) == 0 && S_ISDIR(stats.st_mode)) { - fprintf(stderr, "%s: %s: Is a directory.\n", argv[0], argv[i]); - return EX_NOINPUT; - } else if ((file = fopen(argv[i], "r")) == NULL) { - switch (errno) { - case EACCES: - fprintf(stderr, "%s: %s: Permission denied.\n", argv[0], argv[i]); - return EX_NOINPUT; - case EISDIR: - fprintf(stderr, "%s: %s: Is a directory.\n", argv[0], argv[i]); - return EX_NOINPUT; - case ELOOP: - fprintf( - stderr, - "%s: %s: Is a symbolic link loop.\n", - argv[0], - argv[i] - ); - return EX_UNAVAILABLE; - case EMFILE: - fprintf(stderr, "%s: Internal error.\n", argv[0]); - return EX_SOFTWARE; - case ENOENT: case ENOTDIR: case ENXIO: - fprintf( - stderr, - "%s: %s: No such file or directory.\n", - argv[0], - argv[i] - ); - return EX_NOINPUT; - default: - fprintf(stderr, "%s: Unknown error.\n", argv[0]); - return EX_UNAVAILABLE; - } - } - - cat(file, u); - if (file != stdin) { fclose(file); } + file = rpath(argv[0], argv[i]); + if (file != NULL) { + cat(file, u); + if (file != stdin) { fclose(file); } + } else { continue; } } return EX_OK; diff --git a/src/false.c b/src/false.c index e6f64b3..1890c85 100644 --- a/src/false.c +++ b/src/false.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Emma Tebibyte + * Copyright (c) 2023 Emma Tebibyte * SPDX-License-Identifier: AGPL-3.0-or-later * * This file is part of YAC coreutils. diff --git a/src/true.c b/src/true.c index 9d1f79f..c012c36 100644 --- a/src/true.c +++ b/src/true.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Emma Tebibyte + * Copyright (c) 2023 Emma Tebibyte * SPDX-License-Identifier: AGPL-3.0-or-later * * This file is part of YAC coreutils. diff --git a/src/yac.c b/src/yac.c new file mode 100644 index 0000000..dd1f7c4 --- /dev/null +++ b/src/yac.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Emma Tebibyte + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This file is part of YAC coreutils. + * + * YAC coreutils is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * YAC coreutils is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include +#include +#include +#include +#include + +/* Resolve a file from a path */ +FILE *rpath(char *argv0, char *path) { + struct stat stats; + FILE *file; + + if (path[0] == '-') { + switch (path[1]) { + case '\0': + file = stdin; + break; + default: + file = NULL; + break; + } + } else if (stat(path, &stats) == 0 && S_ISDIR(stats.st_mode)) { + fprintf(stderr, "%s: %s: Is a directory.\n", argv0, path); + exit(EX_NOINPUT); + } else if ((file = fopen(path, "r")) == NULL) { + switch (errno) { + case EACCES: + fprintf(stderr, "%s: %s: Permission denied.\n", argv0, path); + exit(EX_NOINPUT); + case EISDIR: + fprintf(stderr, "%s: %s: Is a directory.\n", argv0, path); + exit(EX_NOINPUT); + case ELOOP: + fprintf( + stderr, + "%s: %s: Is a symbolic link loop.\n", + argv0, + path + ); + exit(EX_UNAVAILABLE); + case EMFILE: + fprintf(stderr, "%s: Internal error.\n", argv0); + exit(EX_SOFTWARE); + case ENOENT: case ENOTDIR: case ENXIO: + fprintf( + stderr, + "%s: %s: No such path or directory.\n", + argv0, + path + ); + exit(EX_NOINPUT); + default: + fprintf(stderr, "%s: Unknown error.\n", argv0); + exit(EX_UNAVAILABLE); + } + } + return file; +} diff --git a/src/yac.h b/src/yac.h new file mode 100644 index 0000000..4729708 --- /dev/null +++ b/src/yac.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Emma Tebibyte + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This file is part of YAC coreutils. + * + * YAC coreutils is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * YAC coreutils is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#ifndef YAC_H +#define YAC_H + +FILE *rpath(char *argv0, char *path); + +#endif