diff --git a/.clangd b/.clangd deleted file mode 100644 index ef142b4..0000000 --- a/.clangd +++ /dev/null @@ -1,19 +0,0 @@ -If: - PathMatch: - - .*\.c - - .*\.h - - -CompileFlags: - Add: - - -xc - - -std=c89 - - -Isrc - - -Wall - - -Wextra, - - -pedantic - - -O2 - - -ferror-limit=0 - - -D_DEFAULT_SOURCE - - -D_CHECK_LINK - Compiler: clang diff --git a/Makefile b/Makefile index d68e96a..07ffbf4 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ CC = gcc -SOURCE = src +SOURCE = src +SOURCE += lib +SOURCE += command MAJOR = 0 MINOR = 0 PATCH = 1 -INCFLAGS = $(shell echo $(SOURCE) | xargs printf -- '-I%s') +INCFLAGS = $(shell echo $(SOURCE) | xargs printf -- '-I%s ') CCFLAGS = -std=c89 -Wall -Wextra -pedantic -O2 CCFLAGS += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK @@ -21,9 +23,9 @@ SRC = $(shell find $(SOURCE) -name "*.c") DIR = $(shell find $(SOURCE) -type d) OBJ = $(SRC:%.c=$(BIN)/%.o) -.PHONY: dirs run clean build install uninstall +.PHONY: empty dirs run clean build install uninstall -EOF: clean build +empty: clean build dirs: echo $(DIR) | xargs printf -- '$(BIN)/%s\n' | xargs mkdir -p diff --git a/src/commands/cat.c b/command/cat.c similarity index 98% rename from src/commands/cat.c rename to command/cat.c index 0495fe3..c392a46 100644 --- a/src/commands/cat.c +++ b/command/cat.c @@ -1,6 +1,8 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include +#include static struct { bool number_lines; diff --git a/src/commands/cp.c b/command/cp.c similarity index 98% rename from src/commands/cp.c rename to command/cp.c index df88155..ca80f69 100644 --- a/src/commands/cp.c +++ b/command/cp.c @@ -1,7 +1,12 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + #include +#include #include #include +#include +#include #include #include diff --git a/src/commands/dd.c b/command/dd.c similarity index 96% rename from src/commands/dd.c rename to command/dd.c index 1387317..67f8be3 100644 --- a/src/commands/dd.c +++ b/command/dd.c @@ -1,4 +1,7 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include static void help(void) { printf("Usage: dd [if=FILE] [of=FILE] [bs=N] [count=N]\n\n"); diff --git a/src/commands/echo.c b/command/echo.c similarity index 97% rename from src/commands/echo.c rename to command/echo.c index fe70a6a..a0ab78d 100644 --- a/src/commands/echo.c +++ b/command/echo.c @@ -1,4 +1,7 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include static struct { bool escape_codes; diff --git a/src/commands/ed.c b/command/ed.c similarity index 99% rename from src/commands/ed.c rename to command/ed.c index d7e8881..472473f 100644 --- a/src/commands/ed.c +++ b/command/ed.c @@ -1,5 +1,8 @@ -#include "../command.h" -#include "../util//regex.h" +#include "command.h" +#include "lslib.h" + +#include +#include #define INPUT_LEN 1024 diff --git a/src/commands/grep.c b/command/grep.c similarity index 98% rename from src/commands/grep.c rename to command/grep.c index 4062734..0dad094 100644 --- a/src/commands/grep.c +++ b/command/grep.c @@ -1,5 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + #include +#include +#include static struct { bool filename_prefix; diff --git a/src/commands/groups.c b/command/groups.c similarity index 53% rename from src/commands/groups.c rename to command/groups.c index bd2e5f9..cb950be 100644 --- a/src/commands/groups.c +++ b/command/groups.c @@ -1,20 +1,41 @@ -#include "../command.h" +#include "args.h" +#include "command.h" +#include "lslib.h" +#include #include #include +#include +#include +#include -COMMAND_EMPTY(groups) { +static void help (void) { + printf("Usage: groups [USER]\n\n"); + printf("Print the groups USER is in\n"); +} + +COMMAND(groups) { uid_t uid; int ngroups, i; gid_t* groups; struct passwd* pw; - uid = getuid(); + parse_help(argc, argv, help); - pw = getpwuid(uid); + if (argc < 1) { + uid = getuid(); + pw = getpwuid(uid); + } else { + pw = getpwnam(argv[0]); + } + if(pw == NULL){ - error("failed to fetch groups: %s", strerror(errno)); + if (errno == 0) { + error("user not found"); + } else { + error("failed to fetch groups: %s", strerror(errno)); + } } ngroups = 0; diff --git a/src/commands/head.c b/command/head.c similarity index 98% rename from src/commands/head.c rename to command/head.c index da8b9b3..c28a82c 100644 --- a/src/commands/head.c +++ b/command/head.c @@ -1,4 +1,7 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include static struct { int count; diff --git a/src/commands/id.c b/command/id.c similarity index 60% rename from src/commands/id.c rename to command/id.c index 3bef4f6..3a63989 100644 --- a/src/commands/id.c +++ b/command/id.c @@ -1,9 +1,20 @@ -#include "../command.h" +#include "args.h" +#include "command.h" +#include "lslib.h" +#include #include #include +#include +#include +#include -COMMAND_EMPTY(user_id) { +static void help (void) { + printf("Usage: id [USER]\n\n"); + printf("Print information about the USER\n"); +} + +COMMAND(user_id) { uid_t uid; gid_t gid, *groups; @@ -11,13 +22,24 @@ COMMAND_EMPTY(user_id) { struct passwd* pw; struct group* ugr; - uid = getuid(); - gid = getgid(); + parse_help(argc, argv, help); - pw = getpwuid(uid); - if(pw == NULL){ - error("failed to fetch groups: %s", strerror(errno)); + if (argc < 1) { + uid = getuid(); + pw = getpwuid(uid); + } else { + pw = getpwnam(argv[0]); } + + if(pw == NULL){ + if (errno == 0) { + error("user not found"); + } else { + error("failed to fetch groups: %s", strerror(errno)); + } + } + + uid = pw->pw_uid; ngroups = 0; getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups); @@ -25,6 +47,7 @@ COMMAND_EMPTY(user_id) { groups = malloc(sizeof(gid_t) * ngroups); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); + gid = pw->pw_gid; ugr = getgrgid(gid); printf("uid=%d(%s) gid=%d(%s) ", uid, ugr->gr_name, gid, ugr->gr_name); diff --git a/src/commands/ls.c b/command/ls.c similarity index 98% rename from src/commands/ls.c rename to command/ls.c index e8d58d0..8ed796f 100644 --- a/src/commands/ls.c +++ b/command/ls.c @@ -1,11 +1,16 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include #include #include #include #include +#include #include +#include +#include +#include #define FILE_COLOR ANSCII BLACK COLOR #define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR @@ -17,6 +22,12 @@ #define BLK_COLOR ANSCII BOLD NEXT NORMAL YELLOW COLOR #define SOCK_COLOR ANSCII BOLD NEXT NORMAL MAGENTA COLOR +enum When { + YES, + NO, + AUTO +}; + static struct { bool hidden; bool hide_dot; diff --git a/src/commands/mkdir.c b/command/mkdir.c similarity index 93% rename from src/commands/mkdir.c rename to command/mkdir.c index 02fccca..0d3950d 100644 --- a/src/commands/mkdir.c +++ b/command/mkdir.c @@ -1,4 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include +#include +#include static struct { bool make_parent; diff --git a/src/commands/mv.c b/command/mv.c similarity index 96% rename from src/commands/mv.c rename to command/mv.c index d203607..adce2b7 100644 --- a/src/commands/mv.c +++ b/command/mv.c @@ -1,4 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include +#include +#include static struct { bool prompt; diff --git a/src/commands/printf.c b/command/printf.c similarity index 97% rename from src/commands/printf.c rename to command/printf.c index 519b8a2..99139d0 100644 --- a/src/commands/printf.c +++ b/command/printf.c @@ -1,4 +1,7 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include static long cast_long(const char* arg) { char* end; diff --git a/src/commands/rm.c b/command/rm.c similarity index 97% rename from src/commands/rm.c rename to command/rm.c index 8ce3e1c..81a956a 100644 --- a/src/commands/rm.c +++ b/command/rm.c @@ -1,5 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + #include +#include +#include #include static struct { diff --git a/src/commands/tac.c b/command/tac.c similarity index 97% rename from src/commands/tac.c rename to command/tac.c index d188de9..9e9e48e 100644 --- a/src/commands/tac.c +++ b/command/tac.c @@ -1,8 +1,10 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include #include #include +#include static void help(void) { printf("Usage: tac [FILE]...\n\n"); diff --git a/src/commands/tail.c b/command/tail.c similarity index 98% rename from src/commands/tail.c rename to command/tail.c index 07b3d2b..8137eca 100644 --- a/src/commands/tail.c +++ b/command/tail.c @@ -1,4 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include +#include +#include static struct { bool lines; diff --git a/src/commands/tee.c b/command/tee.c similarity index 96% rename from src/commands/tee.c rename to command/tee.c index b9b31be..0462517 100644 --- a/src/commands/tee.c +++ b/command/tee.c @@ -1,6 +1,8 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include +#include static struct { bool append; diff --git a/src/commands/wc.c b/command/wc.c similarity index 98% rename from src/commands/wc.c rename to command/wc.c index d8905a5..3150045 100644 --- a/src/commands/wc.c +++ b/command/wc.c @@ -1,6 +1,8 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include +#include static struct { bool newlines; diff --git a/src/commands/whoami.c b/command/whoami.c similarity index 86% rename from src/commands/whoami.c rename to command/whoami.c index 7fd7c85..5823b8f 100644 --- a/src/commands/whoami.c +++ b/command/whoami.c @@ -1,6 +1,9 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" #include +#include +#include static void help(void) { printf("Usage: whoami\n\n"); diff --git a/src/commands/xargs.c b/command/xargs.c similarity index 97% rename from src/commands/xargs.c rename to command/xargs.c index 3008c3c..2a41460 100644 --- a/src/commands/xargs.c +++ b/command/xargs.c @@ -1,6 +1,11 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" + +#include #include #include +#include +#include static struct { bool null_seperated; diff --git a/src/commands/yes.c b/command/yes.c similarity index 92% rename from src/commands/yes.c rename to command/yes.c index 6a44789..f979a9f 100644 --- a/src/commands/yes.c +++ b/command/yes.c @@ -1,4 +1,5 @@ -#include "../command.h" +#include "command.h" +#include "lslib.h" static void help(void) { printf("Usage: yes [STRING]\n\n"); diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..396bda2 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,15 @@ +-c +-std=c89 +-Wall +-Wextra +-pedantic +-O2 +-Isrc +-Icommand +-Ilib +-D_DEFAULT_SOURCE +-DMAJOR=0 +-DMINOR=0 +-DPATCH=0 +-DCHECK_LINK + diff --git a/lib/args.c b/lib/args.c new file mode 100644 index 0000000..f907746 --- /dev/null +++ b/lib/args.c @@ -0,0 +1,111 @@ +#include "args.h" +#include "error.h" +#include "convert.h" + +#include +#include +#include + +#ifndef MAJOR +#define MAJOR 0 +#endif + +#ifndef MINOR +#define MINOR 0 +#endif + +#ifndef PATCH +#define PATCH 0 +#endif + +void check_arg (char* arg) { + if (arg == NULL) { + error("expected another argument after option"); + } +} + +void global_help(void (*help)(void)) { + printf("LazySphere v%d.%d.%d multi-call binary.\n\n", MAJOR, MINOR, PATCH); + help(); + exit(EXIT_SUCCESS); +} + +void parse_help(int argc, char** argv, void (*help)(void)) { + int i; + + if (argc < 1) return; + + for (i = 0; i < argc; i++) { + if (!prefix("-", argv[i]) || streql("-", argv[i])) break; + if (help != NULL && streql("--help", argv[i])) global_help(help); + } +} + +int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)) { + int start, i, current; + char* next_arg; + + if (argc < 1) return 0; + + start = 0; + for (i = 0; i < argc; i++) { + + if (!prefix("-", argv[i]) || streql("-", argv[i])) break; + if (help != NULL && streql("--help", argv[i])) global_help(help); + + if (i + 1 == argc) { + next_arg = NULL; + } else { + next_arg = argv[i+1]; + } + + current = i; + + if (prefix("--", argv[i])) { + int r; + + if (long_arg == NULL) { + goto exit; + } + + r = long_arg(argv[current], next_arg); + + if (r == ARG_USED) { + i++; + start++; + } else if (r == ARG_IGNORE) { + goto exit; + } else if (r == ARG_INVALID) { + error("invalid argument %s", argv[current]); + + } + } else { + size_t j; + int r; + + if (short_arg == NULL) { + goto exit; + } + + for (j = 1; j < strlen(argv[current]); j++) { + + r = short_arg(argv[current][j], next_arg); + + if (r == ARG_USED) { + i++; + start++; + } else if (r == ARG_IGNORE) { + goto exit; + } else if (r == ARG_INVALID) { + error("invalid argument -%c", argv[current][j]); + } + } + } + + start++; + } + +exit: + + return start; +} diff --git a/lib/args.h b/lib/args.h new file mode 100644 index 0000000..0b89fca --- /dev/null +++ b/lib/args.h @@ -0,0 +1,18 @@ +#ifndef ARGS_H +#define ARGS_H + +#define UNUSED(x) (void)(x) +#define ARG_UNUSED 0 +#define ARG_USED 1 +#define ARG_IGNORE 2 +#define ARG_INVALID 3 + +void check_arg (char* arg); + +void global_help(void (*help)(void)); + +void parse_help (int argc, char** argv, void (*help)(void)); + +int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); + +#endif diff --git a/lib/buffer.c b/lib/buffer.c new file mode 100644 index 0000000..2bee94b --- /dev/null +++ b/lib/buffer.c @@ -0,0 +1,60 @@ +#include "buffer.h" +#include "convert.h" + +#include +#include + +static int push_path_buffer_b(char* buf, int* index, const char* string) { + int save, string_len; + + save = *index; + if (*index > 1 || (*index == 1 && buf[0] != '/')) { + buf[(*index)++] = '/'; + } + + string_len = strlen(string); + memcpy(buf + *index, string, string_len + 1); + + *index += string_len; + + return save; +} + +static void pop_path_buffer_b(char* buf, int* index, int i) { + *index = i; + buf[*index] = '\0'; +} + +static char path_buffer[PATH_MAX + 1]; +static int path_buffer_index = 0; + +char* get_path_buffer(void) { + return path_buffer; +} + +int push_path_buffer(const char* string) { + return push_path_buffer_b(path_buffer, &path_buffer_index, string); +} + +void pop_path_buffer(int i) { + pop_path_buffer_b(path_buffer, &path_buffer_index, i); +} + +static char path_buffer_2[PATH_MAX + 1]; +static int path_buffer_index_2 = 0; + +char* get_path_buffer_2(void) { + return path_buffer_2; +} + +int push_path_buffer_2(const char* string) { + return push_path_buffer_b(path_buffer_2, &path_buffer_index_2, string); +} + +void pop_path_buffer_2(int i) { + pop_path_buffer_b(path_buffer_2, &path_buffer_index_2, i); +} + +bool is_dot_dir(const char* path) { + return streql(path, ".") || streql(path, ".."); +} diff --git a/lib/buffer.h b/lib/buffer.h new file mode 100644 index 0000000..fd47ee7 --- /dev/null +++ b/lib/buffer.h @@ -0,0 +1,16 @@ +#ifndef BUFFER_H +#define BUFFER_H + +#include "def.h" + +char* get_path_buffer(void); +int push_path_buffer(const char* string); +void pop_path_buffer(int i); + +char* get_path_buffer_2(void); +int push_path_buffer_2(const char* string); +void pop_path_buffer_2(int i); + +bool is_dot_dir(const char* path); + +#endif diff --git a/lib/convert.c b/lib/convert.c new file mode 100644 index 0000000..071268e --- /dev/null +++ b/lib/convert.c @@ -0,0 +1,126 @@ +#include "convert.h" +#include "error.h" + +#include +#include +#include +#include +#include + +long int get_number(const char* text) { + char* end; + long int n = strtol(text, &end, 10); + if (text == end) { + error("%s is not a valid number", text); + } + return n; +} + +long int get_blkm(const char* text) { + char* end; + long int n = strtol(text, &end, 10); + if (text == end) { + error("%s is not a valid bkm", text); + } + if (*end == '\0') return n; + switch (*end) { + case 'K': + case 'k': + return n * 1024; + case 'B': + case 'b': + return n * 512; + case 'M': + case 'm': + return n * 1024 * 1204; + default: + error("invalid bkm type %c", *end); + } + + /* shouldnt get here anyways */ + return 0; +} + +mode_t get_mode(const char* next) { + char* end = NULL; + mode_t mode = (mode_t)strtol(next, &end, 8); + if (!end) return 0; + while(isspace(*end)) end++; + if (*end != '\0' || (unsigned) mode < 010000) { + error("invalid file mode: `%s`", next); + } + return mode; +} + +bool streql(const char* a, const char* b) { + int n = 0; + + if (*a != *b) return false; + + while (true) { + if (*(a+n) != *(b+n)) return false; + if (*(a+n) == '\0') return true; + ++n; + } +} + +bool prefix(const char* pre, const char* str) { + return strncmp(pre, str, strlen(pre)) == 0; +} + +static char fs_types[5] = {'K','M','G','T','P'}; +void print_file_size(size_t bytes, char buf[5]) { + int index, n; + float next; + + index = 0; + next = bytes; + + while (true) { + if (next < 1000) { + break; + } + + if (index == 5) { + printf("999P"); + return; + } + + next /= 1024; + index++; + } + + n = snprintf(buf, 4, "%u", (int)(next+.5)); + + if (index > 0) { + buf[n] = (fs_types[index - 1]); + n++; + } + + buf[n] = '\0'; +} + +static char* months[12] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; +void print_date_time(time_t mills, char buf[13]) { + struct tm* info; + int n; + + info = localtime(&mills); + n = snprintf(buf, 5, "%s ", months[info->tm_mon]); + + if (info->tm_mday < 10) { + buf[n] = ' '; + n++; + } + + snprintf(buf + n, 13 - n, "%d %02d:%02d ", info->tm_mday, info->tm_hour, info->tm_sec); +} + +void print_file_path(char* path) { + if (streql("-", path)) { + printf("(standard input)"); + } else { + printf("%s", path); + } +} diff --git a/lib/convert.h b/lib/convert.h new file mode 100644 index 0000000..f07614b --- /dev/null +++ b/lib/convert.h @@ -0,0 +1,20 @@ +#ifndef CONVERT_H +#define CONVERT_H + +#include "def.h" + +#include +#include + +long int get_number(const char* text); +long int get_blkm(const char* text); +mode_t get_mode(const char* text); + +bool streql(const char* a, const char* b); +bool prefix(const char* pre, const char* str); + +void print_file_size(size_t bytes, char buf[5]); +void print_date_time(time_t mills, char buf[13]); +void print_file_path(char* path); + +#endif diff --git a/lib/def.h b/lib/def.h new file mode 100644 index 0000000..33a32a0 --- /dev/null +++ b/lib/def.h @@ -0,0 +1,31 @@ +#ifndef COLOR_H +#define COLOR_H + +#include + +#define ANSCII "\x1b[" +#define NEXT ";" + +#define RESET "0" +#define BOLD "1" + +#define NORMAL "3" +#define BACKGROUND "4" +#define HIGHLIGHT "9" + +#define BLACK "0" +#define RED "1" +#define GREEN "2" +#define YELLOW "3" +#define BLUE "4" +#define MAGENTA "5" +#define TURQUOISE "6" +#define WHITE "7" + +#define COLOR "m" + +typedef uint8_t bool; +#define true 1 +#define false 0 + +#endif diff --git a/lib/error.c b/lib/error.c new file mode 100644 index 0000000..67828c9 --- /dev/null +++ b/lib/error.c @@ -0,0 +1,35 @@ +#include "error.h" + +#include +#include +#include + +extern char* cmd; + +void error_s(const char *format, ...) { + va_list list; + va_start(list, format); + + fprintf(stderr, "%s: ", cmd); + vfprintf(stderr, format, list); + fprintf(stderr, "\n"); +} + +void error(const char *format, ...) { + va_list list; + va_start(list, format); + + fprintf(stderr, "%s: ", cmd); + vfprintf(stderr, format, list); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); +} + +void output(const char *format, ...) { + va_list list; + va_start(list, format); + + fprintf(stdout, "%s: ", cmd); + vfprintf(stdout, format, list); + fprintf(stdout, "\n"); +} diff --git a/lib/error.h b/lib/error.h new file mode 100644 index 0000000..bae532e --- /dev/null +++ b/lib/error.h @@ -0,0 +1,13 @@ +#ifndef ERROR_H +#define ERROR_H + +__attribute__ ((__format__(printf, 1, 2))) +void error_s(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void error(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void output(const char* format, ...); + +#endif diff --git a/lib/file.c b/lib/file.c new file mode 100644 index 0000000..f89b489 --- /dev/null +++ b/lib/file.c @@ -0,0 +1,63 @@ +#include "file.h" +#include "error.h" +#include "convert.h" + +#include +#include +#include +#include +#include +#include + +FILE* get_file_s(const char* path, const char* type) { + struct stat s; + FILE* file; + + if (streql("-", path) && type[0] == 'r') { + clearerr(stdin); + fflush(stdin); + return stdin; + } + + if (lstat(path, &s) < 0) { + if (type[0] != 'r') goto read; + error_s("failed to read %s: %s", path, strerror(errno)); + return NULL; + } + + if (S_ISDIR(s.st_mode)) { + error_s("%s is a directory", path); + return NULL; + } + +read: + + file = fopen(path, type); + + if (file == NULL) { + error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno)); + } + + return file; +} + +FILE* get_file(const char* path, const char* type) { + FILE* file = get_file_s(path, type); + if (file == NULL) exit(EXIT_FAILURE); + return file; +} + +int get_tty (void) { + int fd = open(_PATH_TTY, O_RDONLY); + if (fd < 0) error("failed to get tty: %s", strerror(errno)); + return fd; +} + +FILE* get_tty_stream(char* type) { + int fd = get_tty(); + FILE* file = fdopen(fd, type); + if (file == NULL) { + error("failed to open tty stream: %s", strerror(errno)); + } + return file; +} diff --git a/lib/file.h b/lib/file.h new file mode 100644 index 0000000..0bb5939 --- /dev/null +++ b/lib/file.h @@ -0,0 +1,14 @@ +#ifndef FILE_H +#define FILE_H + +#include + +FILE* get_file_s(const char* path, const char* type); + +FILE* get_file(const char* path, const char* type); + +int get_tty(void); + +FILE* get_tty_stream(char* type); + +#endif diff --git a/lib/lslib.h b/lib/lslib.h new file mode 100644 index 0000000..dfa1202 --- /dev/null +++ b/lib/lslib.h @@ -0,0 +1,16 @@ +#ifndef SHARED_H +#define SHARED_H + +#include +#include + +#include "args.h" +#include "buffer.h" +#include "def.h" +#include "convert.h" +#include "error.h" +#include "file.h" +#include "regex.h" +#include "stack.h" + +#endif diff --git a/src/util/regex.c b/lib/regex.c similarity index 100% rename from src/util/regex.c rename to lib/regex.c diff --git a/src/util/regex.h b/lib/regex.h similarity index 95% rename from src/util/regex.h rename to lib/regex.h index 69facc6..d4c61b6 100644 --- a/src/util/regex.h +++ b/lib/regex.h @@ -36,16 +36,9 @@ #define RE_DOT_MATCHES_NEWLINE 1 #endif -#ifdef __cplusplus -extern "C"{ -#endif - - - /* Typedef'd pointer to get abstract datatype. */ typedef struct regex_t* re_t; - /* Compile regex string pattern to a regex_t-array. */ re_t re_compile(const char* pattern); @@ -58,8 +51,4 @@ int re_matchp(re_t pattern, const char* text, int* matchlength); int re_match(const char* pattern, const char* text, int* matchlength); -#ifdef __cplusplus -} -#endif - #endif /* ifndef _TINY_REGEX_C */ diff --git a/src/util/stack.c b/lib/stack.c similarity index 100% rename from src/util/stack.c rename to lib/stack.c diff --git a/src/util/stack.h b/lib/stack.h similarity index 95% rename from src/util/stack.h rename to lib/stack.h index 8d6fc80..38fb185 100644 --- a/src/util/stack.h +++ b/lib/stack.h @@ -1,7 +1,7 @@ #ifndef STACK_H #define STACK_H -#include "shared.h" +#include "def.h" #include diff --git a/src/command.h b/src/command.h index cca2877..87cc749 100644 --- a/src/command.h +++ b/src/command.h @@ -1,32 +1,17 @@ #ifndef COMMAND_H #define COMMAND_H -#include "util/shared.h" -#include "util/stack.h" -#include "util/regex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #define ARGUMENTS int argc, char** argv #define NEXT_ARGS argc - 1, &argv[1] #define COMMAND(name) int name (ARGUMENTS) -#define COMMAND_EMPTY(name) int name (void) COMMAND(dd); COMMAND(cat); COMMAND(yes); COMMAND(echo); COMMAND(print); -COMMAND_EMPTY(groups); -COMMAND_EMPTY(user_id); +COMMAND(groups); +COMMAND(user_id); COMMAND(ls); COMMAND(tail); COMMAND(head); diff --git a/src/main.c b/src/main.c index 1977e17..ad64b10 100644 --- a/src/main.c +++ b/src/main.c @@ -1,12 +1,8 @@ -#include "util/shared.h" #include "command.h" +#include "lslib.h" -#include #include #include -#include -#include -#include char* cmd; @@ -51,9 +47,9 @@ int main (ARGUMENTS) { } else if (streql(cmd, "printf")) { return print(NEXT_ARGS); } else if (streql(cmd, "groups")) { - return groups(); + return groups(NEXT_ARGS); } else if (streql(cmd, "id")) { - return user_id(); + return user_id(NEXT_ARGS); } else if (streql(cmd, "ls") || streql(cmd, "dir")) { return ls(NEXT_ARGS); } else if (streql(cmd, "lsd")) { diff --git a/src/util/shared.c b/src/util/shared.c deleted file mode 100644 index 2e0c98a..0000000 --- a/src/util/shared.c +++ /dev/null @@ -1,372 +0,0 @@ -#include "shared.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern char* cmd; - -void error_s(const char *format, ...) { - va_list list; - va_start(list, format); - - fprintf(stderr, "%s: ", cmd); - vfprintf(stderr, format, list); - fprintf(stderr, "\n"); -} - -void error(const char *format, ...) { - va_list list; - va_start(list, format); - - fprintf(stderr, "%s: ", cmd); - vfprintf(stderr, format, list); - fprintf(stderr, "\n"); - exit(EXIT_FAILURE); -} - -void output(const char *format, ...) { - va_list list; - va_start(list, format); - - fprintf(stdout, "%s: ", cmd); - vfprintf(stdout, format, list); - fprintf(stdout, "\n"); -} - -FILE* get_file_s(const char* path, const char* type) { - struct stat s; - FILE* file; - - if (streql("-", path) && type[0] == 'r') { - clearerr(stdin); - fflush(stdin); - return stdin; - } - - if (lstat(path, &s) < 0) { - if (type[0] != 'r') goto read; - error_s("failed to read %s: %s", path, strerror(errno)); - return NULL; - } - - if (S_ISDIR(s.st_mode)) { - error_s("%s is a directory", path); - return NULL; - } - -read: - - file = fopen(path, type); - - if (file == NULL) { - error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno)); - } - - return file; -} - -FILE* get_file(const char* path, const char* type) { - FILE* file = get_file_s(path, type); - if (file == NULL) exit(EXIT_FAILURE); - return file; -} - -long int get_number(const char* text) { - char* end; - long int n = strtol(text, &end, 10); - if (text == end) { - error("%s is not a valid number", text); - } - return n; -} - -long int get_blkm(const char* text) { - char* end; - long int n = strtol(text, &end, 10); - if (text == end) { - error("%s is not a valid bkm", text); - } - if (*end == '\0') return n; - switch (*end) { - case 'K': - case 'k': - return n * 1024; - case 'B': - case 'b': - return n * 512; - case 'M': - case 'm': - return n * 1024 * 1204; - default: - error("invalid bkm type %c", *end); - } - - /* shouldnt get here anyways */ - return 0; -} - -mode_t get_mode(const char* next) { - char* end = NULL; - mode_t mode = (mode_t)strtol(next, &end, 8); - if (!end) return 0; - while(isspace(*end)) end++; - if (*end != '\0' || (unsigned) mode < 010000) { - error("invalid file mode: `%s`", next); - } - return mode; -} - -bool streql(const char* a, const char* b) { - int n = 0; - - if (*a != *b) return false; - - while (true) { - if (*(a+n) != *(b+n)) return false; - if (*(a+n) == '\0') return true; - ++n; - } -} - -bool prefix(const char* pre, const char* str) { - return strncmp(pre, str, strlen(pre)) == 0; -} - -static char fs_types[5] = {'K','M','G','T','P'}; -void print_file_size(size_t bytes, char buf[5]) { - int index, n; - float next; - - index = 0; - next = bytes; - - while (true) { - if (next < 1000) { - break; - } - - if (index == 5) { - printf("999P"); - return; - } - - next /= 1024; - index++; - } - - n = snprintf(buf, 4, "%u", (int)(next+.5)); - - if (index > 0) { - buf[n] = (fs_types[index - 1]); - n++; - } - - buf[n] = '\0'; -} - -static char* months[12] = - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; -void print_date_time(time_t mills, char buf[13]) { - struct tm* info; - int n; - - info = localtime(&mills); - n = snprintf(buf, 5, "%s ", months[info->tm_mon]); - - if (info->tm_mday < 10) { - buf[n] = ' '; - n++; - } - - snprintf(buf + n, 13 - n, "%d %02d:%02d ", info->tm_mday, info->tm_hour, info->tm_sec); -} - -void print_file_path(char* path) { - if (streql("-", path)) { - printf("(standard input)"); - } else { - printf("%s", path); - } -} - -#ifndef MAJOR -#define MAJOR 0 -#endif - -#ifndef MINOR -#define MINOR 0 -#endif - -#ifndef PATCH -#define PATCH 0 -#endif - -void check_arg (char* arg) { - if (arg == NULL) { - error("expected another argument after option"); - } -} - -void global_help(void (*help)(void)) { - printf("LazySphere v%d.%d.%d multi-call binary.\n\n", MAJOR, MINOR, PATCH); - help(); - exit(EXIT_SUCCESS); -} - -void parse_help(int argc, char** argv, void (*help)(void)) { - int i; - - if (argc < 1) return; - - for (i = 0; i < argc; i++) { - if (!prefix("-", argv[i]) || streql("-", argv[i])) break; - if (help != NULL && streql("--help", argv[i])) global_help(help); - } -} - -int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)) { - int start, i, current; - char* next_arg; - - if (argc < 1) return 0; - - start = 0; - for (i = 0; i < argc; i++) { - - if (!prefix("-", argv[i]) || streql("-", argv[i])) break; - if (help != NULL && streql("--help", argv[i])) global_help(help); - - if (i + 1 == argc) { - next_arg = NULL; - } else { - next_arg = argv[i+1]; - } - - current = i; - - if (prefix("--", argv[i])) { - int r; - - if (long_arg == NULL) { - goto exit; - } - - r = long_arg(argv[current], next_arg); - - if (r == ARG_USED) { - i++; - start++; - } else if (r == ARG_IGNORE) { - goto exit; - } else if (r == ARG_INVALID) { - error("invalid argument %s", argv[current]); - - } - } else { - size_t j; - int r; - - if (short_arg == NULL) { - goto exit; - } - - for (j = 1; j < strlen(argv[current]); j++) { - - r = short_arg(argv[current][j], next_arg); - - if (r == ARG_USED) { - i++; - start++; - } else if (r == ARG_IGNORE) { - goto exit; - } else if (r == ARG_INVALID) { - error("invalid argument -%c", argv[current][j]); - } - } - } - - start++; - } - -exit: - - return start; -} - -int get_tty (void) { - int fd = open(_PATH_TTY, O_RDONLY); - if (fd < 0) error("failed to get tty: %s", strerror(errno)); - return fd; -} - -FILE* get_tty_stream(char* type) { - int fd = get_tty(); - FILE* file = fdopen(fd, type); - if (file == NULL) { - error("failed to open tty stream: %s", strerror(errno)); - } - return file; -} - -static int push_path_buffer_b(char* buf, int* index, const char* string) { - int save, string_len; - - save = *index; - if (*index > 1 || (*index == 1 && buf[0] != '/')) { - buf[(*index)++] = '/'; - } - - string_len = strlen(string); - memcpy(buf + *index, string, string_len + 1); - - *index += string_len; - - return save; -} - -static void pop_path_buffer_b(char* buf, int* index, int i) { - *index = i; - buf[*index] = '\0'; -} - -static char path_buffer[PATH_MAX + 1]; -static int path_buffer_index = 0; - -char* get_path_buffer(void) { - return path_buffer; -} - -int push_path_buffer(const char* string) { - return push_path_buffer_b(path_buffer, &path_buffer_index, string); -} - -void pop_path_buffer(int i) { - pop_path_buffer_b(path_buffer, &path_buffer_index, i); -} - -static char path_buffer_2[PATH_MAX + 1]; -static int path_buffer_index_2 = 0; - -char* get_path_buffer_2(void) { - return path_buffer_2; -} - -int push_path_buffer_2(const char* string) { - return push_path_buffer_b(path_buffer_2, &path_buffer_index_2, string); -} - -void pop_path_buffer_2(int i) { - pop_path_buffer_b(path_buffer_2, &path_buffer_index_2, i); -} - -bool is_dot_dir(const char* path) { - return streql(path, ".") || streql(path, ".."); -} diff --git a/src/util/shared.h b/src/util/shared.h deleted file mode 100644 index a3e6a56..0000000 --- a/src/util/shared.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef SHARED_H -#define SHARED_H - -#include -#include -#include -#include - -#define ANSCII "\x1b[" -#define NEXT ";" - -#define RESET "0" -#define BOLD "1" - -#define NORMAL "3" -#define BACKGROUND "4" -#define HIGHLIGHT "9" - -#define BLACK "0" -#define RED "1" -#define GREEN "2" -#define YELLOW "3" -#define BLUE "4" -#define MAGENTA "5" -#define TURQUOISE "6" -#define WHITE "7" - -#define COLOR "m" - -typedef uint8_t bool; -#define true 1 -#define false 0 - -enum When { - YES, - NO, - AUTO -}; - -__attribute__ ((__format__(printf, 1, 2))) -void error_s(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void error(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void output(const char* format, ...); - -FILE* get_file_s(const char* path, const char* type); -FILE* get_file(const char* path, const char* type); -long int get_number(const char* text); -long int get_blkm(const char* text); -mode_t get_mode(const char* next); - -bool streql(const char* a, const char* b); -bool prefix(const char* pre, const char* str); - -void print_file_size(size_t bytes, char buf[5]); -void print_date_time(time_t mills, char buf[13]); -void print_file_path(char* path); - -#define UNUSED(x) (void)(x) -#define ARG_UNUSED 0 -#define ARG_USED 1 -#define ARG_IGNORE 2 -#define ARG_INVALID 3 - -void check_arg (char* arg); -void global_help(void (*help)(void)); -void parse_help (int argc, char** argv, void (*help)(void)); -int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); - -int get_tty(void); -FILE* get_tty_stream(char* type); - -char* get_path_buffer(void); -int push_path_buffer(const char* string); -void pop_path_buffer(int i); - -char* get_path_buffer_2(void); -int push_path_buffer_2(const char* string); -void pop_path_buffer_2(int i); - -bool is_dot_dir(const char* path); - -#endif