diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..ef142b4 --- /dev/null +++ b/.clangd @@ -0,0 +1,19 @@ +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 708443e..d68e96a 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ PATCH = 1 INCFLAGS = $(shell echo $(SOURCE) | xargs printf -- '-I%s') -CCFLAGS = -std=c99 -Wall -Wextra -pedantic -O2 +CCFLAGS = -std=c89 -Wall -Wextra -pedantic -O2 CCFLAGS += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK CCFLAGS += $(INCFLAGS) diff --git a/src/command.h b/src/command.h index d614c75..cca2877 100644 --- a/src/command.h +++ b/src/command.h @@ -1,10 +1,12 @@ +#ifndef COMMAND_H +#define COMMAND_H + #include "util/shared.h" #include "util/stack.h" #include "util/regex.h" #include #include -#include #include #include #include @@ -39,3 +41,5 @@ COMMAND(cp); COMMAND(makedir); COMMAND(mv); COMMAND(grep); + +#endif diff --git a/src/commands/cat.c b/src/commands/cat.c index 8c15522..0495fe3 100644 --- a/src/commands/cat.c +++ b/src/commands/cat.c @@ -16,7 +16,7 @@ static bool printable(char c) { case '\r': return true; case '\b': return true; case '\t': return true; - default: return isprint(c); + default: return isprint(c) == 0; } } @@ -110,22 +110,26 @@ static int short_arg(char c, char* next) { COMMAND(cat) { + int start; + int arg_len; + int i; + flags.number_lines = false; flags.number_non_empty = false; flags.change_non_print = false; flags.change_tabs = false; flags.end_lines_dollar = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); - int arg_len = argc - start; + arg_len = argc - start; if (arg_len < 1) { cat_file(stdin); return EXIT_SUCCESS; } - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { FILE* in = get_file(argv[i], "r"); cat_file(in); if (in != stdin) diff --git a/src/commands/cp.c b/src/commands/cp.c index 37e3354..df88155 100644 --- a/src/commands/cp.c +++ b/src/commands/cp.c @@ -50,17 +50,19 @@ static int short_arg(char c, char* next) { } static bool copy_file(char* from, char* to) { - FILE* from_f = get_file_s(from, "r"); - if (from_f == NULL) { return false; } - - FILE* to_f = get_file_s(to, "w"); - if (to_f == NULL) { fclose(from_f); return false; } - #define BS 1024 - + + FILE *from_f, *to_f; char buf[BS]; int read; + from_f = get_file_s(from, "r"); + if (from_f == NULL) { return false; } + + to_f = get_file_s(to, "w"); + if (to_f == NULL) { fclose(from_f); return false; } + + while ((read = fread(buf, 1, BS, from_f)) > 0) { fwrite(buf, 1, read, to_f); } @@ -123,6 +125,10 @@ static void run_copy(struct stat* s) { static void cp_file(char* path); static void cp_directory(struct stat* s) { + + DIR* d; + struct dirent* file; + if (!flags.recurse) { error_s("-r not specified; omitting directory '%s'", get_path_buffer()); return; @@ -133,14 +139,13 @@ static void cp_directory(struct stat* s) { return; } - DIR* d = opendir(get_path_buffer()); + d = opendir(get_path_buffer()); if (d == NULL) { error_s("cannot open directory '%s': %s", get_path_buffer(), strerror(errno)); return; } - struct dirent* file; while ((file = readdir(d)) != NULL) { if (is_dot_dir(file->d_name)) continue; cp_file(file->d_name); @@ -148,10 +153,11 @@ static void cp_directory(struct stat* s) { } static char* get_file_name(char* path) { - if (path[0] == '\0') return path; - int last = 0; int i = 0; + + if (path[0] == '\0') return path; + while (true) { if (path[i+1] == '\0') break; if (path[i] == '/') { @@ -188,19 +194,22 @@ static void cp_file(char* path) { COMMAND(cp) { + int start, i; + struct stat s; + flags.hard_link = false; flags.sym_link = false; flags.preserve = false; flags.recurse = false; flags.verbose = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); if (argc - start < 2) { global_help(help); } - // only when 2 args and first is a file, the 2nd will be a file + /* only when 2 args and first is a file, the 2nd will be a file */ if (argc - start == 2) { struct stat s; if (lstat(argv[start], &s) < 0) { @@ -216,15 +225,14 @@ COMMAND(cp) { return EXIT_SUCCESS; } - // push directory + /* push directory */ push_path_buffer_2(argv[argc-1]); - struct stat s; if (lstat(get_path_buffer_2(), &s) < 0) { error("target: '%s': %s", get_path_buffer_2(), strerror(errno)); } - for (int i = start; i < argc - 1; i++) { + for (i = start; i < argc - 1; i++) { cp_file(argv[i]); } diff --git a/src/commands/dd.c b/src/commands/dd.c index 78f6041..1387317 100644 --- a/src/commands/dd.c +++ b/src/commands/dd.c @@ -15,10 +15,13 @@ COMMAND(dd) { FILE* out_file = stdout; int bs = 1024; int count = -1; + int i; + char* buffer; + size_t read; parse_help(argc, argv, help); - for (int i = 0; i < argc; i++) { + for (i = 0; i < argc; i++) { if (prefix("if=", argv[i])) { char* path = argv[i] + 3; in_file = get_file(path, "rb"); @@ -42,8 +45,8 @@ COMMAND(dd) { } } - char* buffer = malloc(bs); - size_t read; + buffer = malloc(bs); + while ((read = fread(buffer, 1, bs, in_file)) != 0) { fwrite(buffer, 1, read, out_file); if (--count, count == 0) break; diff --git a/src/commands/echo.c b/src/commands/echo.c index 8b39531..fe70a6a 100644 --- a/src/commands/echo.c +++ b/src/commands/echo.c @@ -8,6 +8,8 @@ static struct { static void print_with_escape_codes(const char* str) { size_t index = 0; + char n; + while (true) { char c = str[index]; index++; @@ -18,7 +20,7 @@ static void print_with_escape_codes(const char* str) { continue; } - char n = str[index]; + n = str[index]; index++; switch (n) { @@ -71,6 +73,8 @@ static int short_arg(char c, char* next) { COMMAND(echo) { + int start, i; + if (argc < 1) { return EXIT_SUCCESS; } @@ -78,9 +82,9 @@ COMMAND(echo) { flags.escape_codes = false; flags.newline = true; - int start = parse_args(argc, argv, NULL, short_arg, NULL); + start = parse_args(argc, argv, NULL, short_arg, NULL); - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { if (flags.escape_codes) { print_with_escape_codes(argv[i]); } else { diff --git a/src/commands/ed.c b/src/commands/ed.c index 379da3c..d7e8881 100644 --- a/src/commands/ed.c +++ b/src/commands/ed.c @@ -66,14 +66,17 @@ static bool read_regex(char** end, re_t* regex, enum RegexDirection dir) { static bool parse_regex(char** end, struct LineAddress* address, enum RegexDirection dir) { re_t regex; + unsigned long cap, siz, i, until; + long int* buf; + if (!read_regex(end, ®ex, dir)) return false; - unsigned long cap = 8; - unsigned long siz = 0; - long int* buf = malloc(cap * sizeof(long int)); + cap = 8; + siz = 0; + buf = malloc(cap * sizeof(long int)); - unsigned long i = (dir == ALL ? 0 : line_current); - unsigned long until = (dir == BEFORE ? 0 : line_count - 1); + i = (dir == ALL ? 0 : line_current); + until = (dir == BEFORE ? 0 : line_count - 1); for (; (dir == BEFORE ? i >= until : i < until); dir == BEFORE ? i-- : i++) { int len; if (re_matchp(regex, lines[i], &len) == -1) { @@ -112,28 +115,34 @@ static void expand_buffer(long int** buf, unsigned long* cap, unsigned long* siz static bool parse_regex_lines(char** end, struct LineAddress* address) { re_t regex; + unsigned long cap, siz; + long int* buf; + int len; + struct LineAddress addr; + if (!read_regex(end, ®ex, ALL)) return false; - unsigned long cap = 8; - unsigned long siz = 0; - long int* buf = malloc(cap * sizeof(long int)); - int len; + cap = 8; + siz = 0; + buf = malloc(cap * sizeof(long int)); - struct LineAddress addr = *address; + addr = *address; if (addr.type == INDEX) { if (re_matchp(regex, lines[addr.data.index.i], &len) != -1) { buf[0] = addr.data.index.i; siz = 1; } } else if (addr.type == RANGE) { - for (long int i = addr.data.range.a; i < addr.data.range.b; i++) { + long int i; + for (i = addr.data.range.a; i < addr.data.range.b; i++) { if (re_matchp(regex, lines[i], &len) == -1) continue; expand_buffer(&buf, &cap, &siz); buf[siz] = i; siz++; } } else if (addr.type == SET) { - for (unsigned long i = 0; i < addr.data.set.s; i++) { + unsigned long i; + for (i = 0; i < addr.data.set.s; i++) { if (re_matchp(regex, lines[addr.data.set.b[i]], &len) == -1) continue; expand_buffer(&buf, &cap, &siz); buf[siz] = addr.data.set.b[i]; @@ -153,6 +162,11 @@ static bool parse_regex_lines(char** end, struct LineAddress* address) { static bool read_address(char** command, bool whitespace, struct LineAddress* a) { char* index = *command; struct LineAddress address; + + char* end_pre; + long int n_pre; + char pre; + memset(&address, 0, sizeof(struct LineAddress)); address.empty = false; @@ -164,8 +178,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a) return true; } - char* end_pre; - long int n_pre = strtol(index, &end_pre, 10) - 1; + n_pre = strtol(index, &end_pre, 10) - 1; if (end_pre == index) { n_pre = -1; } else { @@ -176,7 +189,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a) index = end_pre; } - char pre = *(index++); + pre = *(index++); switch (pre) { case '.': address.type = INDEX; @@ -188,28 +201,37 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a) break; case '-': case '^': { - address.type = INDEX; char* end; - long int n = strtol(index, &end, 10) - 1; + long int n; + + address.type = INDEX; + n = strtol(index, &end, 10) - 1; + if (n < 0) { error_s("input cannot be negative\n"); return false; } + if (index == end) { address.data.index.i = line_current - 1; } else { address.data.index.i = line_current - n; } + if (address.data.index.i < 0) { error_s("line number %ld does not exist\n", address.data.index.i + 1); return false; } + break; } case '+': { - address.type = INDEX; char* end; - long int n = strtol(index, &end, 10) - 1; + long int n; + + address.type = INDEX; + n = strtol(index, &end, 10) - 1; + if (n < 0) { error_s("input cannot be negative\n"); return false; @@ -268,7 +290,8 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a) static void free_data(bool all) { if (lines != NULL) { - for (unsigned long i = 0; i < line_count; i++) { + unsigned long i; + for (i = 0; i < line_count; i++) { free(lines[i]); } free(lines); @@ -321,11 +344,11 @@ int ed_getline(char *buf, size_t size) { size_t i = 0; int ch; clearerr(stdin); - while ((ch = getchar()) != EOF) { // Read until EOF ... + while ((ch = getchar()) != EOF) { /* Read until EOF ... */ if (i + 1 < size) { buf[i++] = ch; } - if (ch == '\n') { // ... or end of line + if (ch == '\n') { /* ... or end of line */ break; } } @@ -346,6 +369,8 @@ static void load_file(FILE* file) { } static bool check_if_sure(char* prompt) { + char buf[INPUT_LEN]; + if (!pending_writes) { return true; } @@ -353,7 +378,6 @@ static bool check_if_sure(char* prompt) { printf("%s", prompt); fflush(stdout); - char buf[INPUT_LEN]; if (ed_getline(buf, INPUT_LEN) == EOF) { putchar('\n'); return false; @@ -387,9 +411,12 @@ static void append_lines(unsigned long index, char** new, unsigned long new_len) } static void delete_lines(unsigned long a, unsigned long b) { + unsigned long i; + if (b < a) return; pending_writes = true; - for (unsigned long i = a; i <= b; i++) { + + for (i = a; i <= b; i++) { free(lines[i]); } if (b == line_count - 1) { @@ -403,20 +430,25 @@ static void delete_lines(unsigned long a, unsigned long b) { } static bool handle_append(struct LineAddress* address) { + char** buf; + unsigned long cap, size; + if (address->type != INDEX) { error_s("append command requires index addressing\n"); return false; } + if (line_count == 0) { address->data.index.i = -1; } - char** buf; - unsigned long cap, size; + get_input(stdin, &buf, &cap, &size); + if (size > 0) { append_lines(address->data.index.i + 1, buf, size); printf("ed: appened %lu lines\n", size); } + line_current += size; free(buf); return true; @@ -427,6 +459,7 @@ static bool handle_delete(struct LineAddress* address) { error_s("line number %ld does not exist\n", address->data.index.i + 1); return false; } + if (address->type == INDEX) { delete_lines(address->data.index.i, address->data.index.i); output("deleted line %ld\n", address->data.index.i+1); @@ -434,16 +467,19 @@ static bool handle_delete(struct LineAddress* address) { delete_lines(address->data.range.a, address->data.range.b); output("deleted lines %ld-%ld\n", address->data.range.a+1, address->data.range.b+1); } else if (address->type == SET) { - for (unsigned long i = 0; i < address->data.set.s; i++) { + unsigned long i; + for (i = 0; i < address->data.set.s; i++) { delete_lines(address->data.set.b[i], address->data.set.b[i]); } output("deleted %lu lines\n", address->data.set.s); } + return true; } static bool get_file_name(char** filename) { size_t len = strlen(*filename); + if (len < 1 || (len == 1 && **filename == '\n')) { if (default_filename == NULL) { error_s("no default filename specified\n"); @@ -467,16 +503,23 @@ static bool get_file_name(char** filename) { } static void write_file(char* filename, struct LineAddress* address, char* type) { + FILE* file; + int wrote; + if (line_count < 1) { error_s("cannot write empty file\n"); return; } + if (!get_file_name(&filename)) return; - FILE* file = get_file_s(filename, type); + file = get_file_s(filename, type); if (file == NULL) return; - int wrote = 0; + + wrote = 0; + if (address->empty) { - for (unsigned long i = 0; i < line_count; i++) { + unsigned long i; + for (i = 0; i < line_count; i++) { fprintf(file, "%s", lines[i]); wrote++; } @@ -485,30 +528,38 @@ static void write_file(char* filename, struct LineAddress* address, char* type) fprintf(file, "%s", lines[i]); wrote++; } else if (address->type == RANGE) { - for (long int i = address->data.range.a; i < address->data.range.b; i++) { + long int i; + for (i = address->data.range.a; i < address->data.range.b; i++) { fprintf(file, "%s", lines[i]); wrote++; } } else if (address->type == SET) { - for (unsigned long i = 0; i < address->data.set.s; i++) { + unsigned long i; + for (i = 0; i < address->data.set.s; i++) { fprintf(file, "%s", lines[address->data.set.b[i]]); wrote++; } } + pending_writes = false; fclose(file); output("wrote %d lines from %s\n", wrote, filename); } static void read_file(char* filename) { + FILE* file; + char** buf; + long int line; + unsigned long capacity, size; + if (!get_file_name(&filename)) return; - FILE* file = get_file_s(filename, "r"); + file = get_file_s(filename, "r"); if (file == NULL) return; - unsigned long capacty = 8; - unsigned long size = 0; - char** buf = malloc(capacty * sizeof(char*)); - get_input(file, &buf, &capacty, &size); + capacity = 8; + size = 0; + buf = malloc(capacity * sizeof(char*)); + get_input(file, &buf, &capacity, &size); if (size < 1) { free(buf); @@ -516,10 +567,11 @@ static void read_file(char* filename) { return; } - long int line = -1; + line = -1; if (line_count > 0) { line = line_count - 1; } + append_lines(line, buf, size); free(buf); output("read and appended %lu lines from %s\n", size, filename); @@ -539,24 +591,31 @@ static int substute_string(long int index, long int matches, re_t regex, char* s int capacity = 8; int size = 0; char* buf = malloc(sizeof(char) * capacity); + long int left; int offset = 0; int matches_found = 0; while(true) { - if (lines[index][offset] == '\0') break; - if (matches_found >= matches && matches > 0) break; int distance, len; + + if (lines[index][offset] == '\0') break; + + if (matches_found >= matches && matches > 0) break; + if ((distance = re_matchp(regex, &lines[index][offset], &len)) == -1) { break; } - if (distance > 0) + + if (distance > 0) { expand_string(&buf, &capacity, &size, &lines[index][offset], distance); + } + expand_string(&buf, &capacity, &size, sub, sub_len); offset += len + distance; matches_found++; } - long int left = strlen(lines[index] + offset); + left = strlen(lines[index] + offset); expand_string(&buf, &capacity, &size, &lines[index][offset], left + 1); free(lines[index]); @@ -565,41 +624,50 @@ static int substute_string(long int index, long int matches, re_t regex, char* s } static void prompt(void) { + char buf[INPUT_LEN]; + char* index; + char cmd; + bool whitespace, linenumbers; + struct LineAddress address; + printf(": "); fflush(stdout); - char buf[INPUT_LEN]; if (ed_getline(buf, INPUT_LEN) == EOF) { putchar('\n'); return; } if (buf[0] == '\0') { putchar('\n'); return; } - char* index = &buf[0]; - bool whitespace = skip_whitespace(&index); + index = &buf[0]; + whitespace = skip_whitespace(&index); - struct LineAddress address; if (!read_address(&index, whitespace, &address)) return; - char cmd = *(index++); + cmd = *(index++); if (cmd == ',') { + struct LineAddress address2; + if (address.type != INDEX) { error_s("comma range addressing requires two index addresses\n"); free_address(address); return; } - struct LineAddress address2; + whitespace = skip_whitespace(&index); + if (!read_address(&index, whitespace, &address2)) { free_address(address); return; } + if (address2.type != INDEX) { error_s("comma range addressing requires two index addresses\n"); free_address(address); free_address(address2); return; } + address.type = RANGE; - address.data.range.a = address.data.index.i; // cursed + address.data.range.a = address.data.index.i; /* cursed */ address.data.range.b = address2.data.index.i; cmd = *(index++); @@ -611,7 +679,8 @@ static void prompt(void) { return; } - bool linenumbers = false; + linenumbers = false; + test: switch (cmd) { case '\0': @@ -663,12 +732,14 @@ test: if (linenumbers) printf("%ld\t", address.data.index.i + 1); printf("%s", lines[address.data.index.i]); } else if (address.type == RANGE) { - for (long int i = address.data.range.a; i <= address.data.range.b; i++) { + long int i; + for (i = address.data.range.a; i <= address.data.range.b; i++) { if (linenumbers) printf("%ld\t", i + 1); printf("%s", lines[i]); } } else if (address.type == SET) { - for (unsigned long i = 0; i < address.data.set.s; i++) { + unsigned long i; + for (i = 0; i < address.data.set.s; i++) { if (linenumbers) printf("%ld\t", address.data.set.b[i] +1); printf("%s", lines[address.data.set.b[i]]); } @@ -698,14 +769,17 @@ test: } goto test; break; - case 's': + case 's': { + char* replace = index; + long int matches, sub_len, matches_found; + unsigned long i; + skip_whitespace(&index); if (*(index++) != '/') { error_s("unexpected character at start of regex\n"); break; } if (!parse_regex_lines(&index, &address)) { return; } - char* replace = index; while(*index != '\0' && *index != '/') index++; if (*index != '/') { error_s("/ missing after %c\n", *index); @@ -716,7 +790,6 @@ test: break; } *(index++) = '\0'; - long int matches; if (*index == '\0' || *index == '\n') { matches = 1; } else if (*index == 'g') { @@ -733,15 +806,16 @@ test: break; } } - long int sub_len = strlen(replace); - long int matches_found = 0; + sub_len = strlen(replace); + matches_found = 0; - for (unsigned long i = 0; i < address.data.set.s; i++) { + for (i = 0; i < address.data.set.s; i++) { matches_found += substute_string(address.data.set.b[i], matches, last_regex, replace, sub_len); } output("replaced %ld matches over %ld lines\n", matches_found, address.data.set.s); pending_writes = true; break; + } case 'w': { bool quit = false; if (*index == 'q') { @@ -766,11 +840,17 @@ test: if (!check_if_sure("Load new file for sure? ")) break; __attribute__((fallthrough)); case 'E': { + char* filename; + FILE* file; + skip_whitespace(&index); - char* filename = index; + + filename = index; if(!get_file_name(&filename)) break; - FILE* file = get_file_s(filename, "r"); + + file = get_file_s(filename, "r"); if (file == NULL) break; + load_file(file); break; } diff --git a/src/commands/grep.c b/src/commands/grep.c index ffa1a41..4062734 100644 --- a/src/commands/grep.c +++ b/src/commands/grep.c @@ -92,10 +92,11 @@ static bool match_literal(char** string, char* pattern) { char* match = *string; size_t match_len = strlen(match); size_t pattern_len = strlen(pattern); + size_t i; if (match_len < pattern_len) return false; - for (size_t i = 0; i < match_len - pattern_len + 1; i++) { + for (i = 0; i < match_len - pattern_len + 1; i++) { if ( (!flags.ignore_case && strncmp(match + i, pattern, pattern_len) == 0) || (flags.ignore_case && strncasecmp(match + i, pattern, pattern_len) == 0) @@ -122,17 +123,18 @@ static bool match(char** string, void* pattern) { } static bool match_any(char* path, void* pattern) { - FILE* file = get_file_s(path, "r"); - if (file == NULL) return false; - + FILE* file; char* buf = NULL; size_t offset; bool matched = false; - int read; + + file = get_file_s(path, "r"); + if (file == NULL) return false; + while ((read = getline(&buf, &offset, file)) > 0) { - if (buf[read-1] == '\n') buf[read-1] = '\0'; char* save = buf; + if (buf[read-1] == '\n') buf[read-1] = '\0'; if (match(&save, pattern)) { matched = true; break; @@ -145,31 +147,39 @@ static bool match_any(char* path, void* pattern) { } static bool match_file(char* path, void* pattern, bool many) { - FILE* file = get_file_s(path, "r"); - if (file == NULL) return false; - - int num_matched = 0; - int line_num = 0; + FILE* file; char* buf = NULL; size_t offset; - + int num_matched = 0; + int line_num = 0; int read; + + file = get_file_s(path, "r"); + if (file == NULL) return false; + while((read = getline(&buf, &offset, file)) > 0) { - if (buf[read-1] == '\n') buf[read-1] = '\0'; char* matched = buf; + + if (buf[read-1] == '\n') buf[read-1] = '\0'; line_num++; - if (!match(&matched, pattern)) { + + if (!match(&matched, pattern)) { continue; } + num_matched++; + if (flags.only_line_count || flags.quiet) continue; + if ((many || flags.filename_prefix) && !flags.never_file_prefix) { print_file_path(path); putchar(':'); } + if (flags.line_number) { printf("%d:", line_num); } + if (flags.only_matching_part) { printf("%s\n", matched); } else { @@ -215,6 +225,11 @@ static bool run_match(char* path, void* pattern, bool many) { COMMAND(grep) { + int start, i; + char* pattern; + bool many, ok; + void* compiled; + flags.only_matching_part = false; flags.only_non_matching_names = false; flags.only_matching_names = false; @@ -226,19 +241,19 @@ COMMAND(grep) { flags.filename_prefix = false; flags.inverse = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); if (argc - start < 1) global_help(help); - char* pattern = argv[start++]; + pattern = argv[start++]; - bool many = argc - start > 0; - bool ok = false; + many = argc - start > 0; + ok = false; - void* compiled = compile(pattern); + compiled = compile(pattern); if (run_match("-", compiled, many)) ok = true; - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { if (run_match(argv[i], compiled, many)) ok = true; } diff --git a/src/commands/groups.c b/src/commands/groups.c index 763f294..bd2e5f9 100644 --- a/src/commands/groups.c +++ b/src/commands/groups.c @@ -5,27 +5,38 @@ COMMAND_EMPTY(groups) { - uid_t uid = getuid(); + uid_t uid; + int ngroups, i; + gid_t* groups; + struct passwd* pw; + + uid = getuid(); - struct passwd* pw = getpwuid(uid); + pw = getpwuid(uid); if(pw == NULL){ error("failed to fetch groups: %s", strerror(errno)); } - int ngroups = 0; + ngroups = 0; getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups); - gid_t groups[ngroups]; + groups = malloc(sizeof(gid_t) * ngroups); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); - - for (int i = 0; i < ngroups; i++){ + + for (i = 0; i < ngroups; i++){ struct group* gr = getgrgid(groups[i]); - if(gr == NULL){ + + if(gr == NULL) { + free(groups); error("failed to fetch groups: %s", strerror(errno)); } + printf("%s ",gr->gr_name); } + printf("\n"); + free(groups); + return EXIT_SUCCESS; } diff --git a/src/commands/head.c b/src/commands/head.c index c09dc9a..da8b9b3 100644 --- a/src/commands/head.c +++ b/src/commands/head.c @@ -66,22 +66,32 @@ static void head_file(char* path, bool many) { static int short_arg(char c, char* next) { switch(c) { case 'c': { + long int bkm; + flags.lines = false; + check_arg(next); - long int bkm = get_blkm(next); + bkm = get_blkm(next); + if (bkm < 1) { error("bkm cannot be less than 1"); } + flags.count = bkm; return ARG_USED; } case 'n': { + long int bkm; + flags.lines = true; + check_arg(next); - long int bkm = get_blkm(next); + bkm = get_blkm(next); + if (bkm < 1) { error("bkm cannot be less than 1"); } + flags.count = bkm; return ARG_USED; } @@ -98,14 +108,17 @@ static int short_arg(char c, char* next) { } COMMAND(head) { + + int start, count, i; + flags.count = 10; flags.lines = true; flags.print_headers = false; flags.dont_print_headers = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); - int count = argc - start; + count = argc - start; if (count < 1) { head_file_lines(stdin); @@ -116,8 +129,8 @@ COMMAND(head) { head_file(argv[start], false); return EXIT_SUCCESS; } - - for (int i = 0; i < count; i++) { + + for (i = 0; i < count; i++) { head_file(argv[start + i], true); } diff --git a/src/commands/id.c b/src/commands/id.c index 4bd7bca..3bef4f6 100644 --- a/src/commands/id.c +++ b/src/commands/id.c @@ -4,22 +4,28 @@ #include COMMAND_EMPTY(user_id) { - - uid_t uid = getuid(); - gid_t gid = getgid(); - struct passwd* pw = getpwuid(uid); + uid_t uid; + gid_t gid, *groups; + int ngroups, i; + struct passwd* pw; + struct group* ugr; + + uid = getuid(); + gid = getgid(); + + pw = getpwuid(uid); if(pw == NULL){ error("failed to fetch groups: %s", strerror(errno)); } - int ngroups = 0; + ngroups = 0; getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups); - gid_t groups[ngroups]; + groups = malloc(sizeof(gid_t) * ngroups); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); - struct group* ugr = getgrgid(gid); + ugr = getgrgid(gid); printf("uid=%d(%s) gid=%d(%s) ", uid, ugr->gr_name, gid, ugr->gr_name); @@ -27,15 +33,21 @@ COMMAND_EMPTY(user_id) { printf("groups="); } - for (int i = 0; i < ngroups; i++){ + for (i = 0; i < ngroups; i++){ struct group* gr = getgrgid(groups[i]); - if(gr == NULL){ + if(gr == NULL) { + free(groups); error("failed to fetch groups: %s", strerror(errno)); } + printf("%d(%s)", gr->gr_gid, gr->gr_name); + if (i + 1 < ngroups) putchar(','); } + printf("\b\n"); + free(groups); + return EXIT_SUCCESS; } diff --git a/src/commands/ls.c b/src/commands/ls.c index a5c60d2..e8d58d0 100644 --- a/src/commands/ls.c +++ b/src/commands/ls.c @@ -65,13 +65,18 @@ static DIR* get_directory(char* path) { static bool get_file_info(const char* file_name, struct FileInfo* info) { - uid_t uid = getuid(); - gid_t gid = getgid(); - + uid_t uid; + gid_t gid; + int save, ty; struct stat s; + size_t file_len; + + uid = getuid(); + gid = getgid(); + memset(&s, 0, sizeof(struct stat)); - int save = push_path_buffer(file_name); + save = push_path_buffer(file_name); if (lstat(get_path_buffer(), &s) < 0) { error_s("failed to read file '%s': %s\n", get_path_buffer(), strerror(errno)); @@ -79,7 +84,7 @@ static bool get_file_info(const char* file_name, struct FileInfo* info) { return false; } - int ty = (s.st_mode & S_IFMT) >> 12; + ty = (s.st_mode & S_IFMT) >> 12; info->set_uid = false; info->set_gid = false; @@ -171,7 +176,7 @@ static bool get_file_info(const char* file_name, struct FileInfo* info) { info->links = s.st_nlink; info->type = ty; - size_t file_len = strlen(file_name) + 1; + file_len = strlen(file_name) + 1; info->name = malloc(file_len); memcpy(info->name, file_name, file_len); @@ -217,13 +222,16 @@ static char* get_file_color(struct FileInfo* info) { static void list_files(struct FileInfo* files, int file_len, struct FileListInfo info) { + struct winsize w; + char* color; + int column_width, row_count, i; + if (flags.more_info) { char total[13]; print_file_size(info.total_size, total); printf("total %s\n", total); } - struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); if (!isatty(1)) { @@ -232,11 +240,10 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo flags.colored = NO; } - char* color; - const int column_width = info.max_name + 1; - const int row_count = w.ws_col / column_width; + column_width = info.max_name + 1; + row_count = w.ws_col / column_width; - for (int i = 0; i < file_len; i++) { + for (i = 0; i < file_len; i++) { struct FileInfo finfo = files[i]; color = get_file_color(&finfo); if (flags.more_info) { @@ -305,25 +312,28 @@ static void push_file( const char* file_path ) { struct FileInfo finfo; + int user_len, group_len, name_len, size_len, link_len; + if (!get_file_info(file_path, &finfo)) return; if (*size == *capacity) { *capacity *= 2; *files = realloc(*files, sizeof(struct FileInfo) * *capacity); } - int user_len = strlen(finfo.usr->pw_name); + + user_len = strlen(finfo.usr->pw_name); if (user_len > info->max_usr) info->max_usr = user_len; - int group_len = strlen(finfo.grp->gr_name); + group_len = strlen(finfo.grp->gr_name); if (group_len > info->max_grp) info->max_grp = group_len; - int name_len = strlen(file_path); + name_len = strlen(file_path); if (name_len > info->max_name) info->max_name = name_len; - int size_len = strlen(finfo.size); + size_len = strlen(finfo.size); if (size_len > info->max_size) info->max_size = size_len; - int link_len = num_places(finfo.links); + link_len = num_places(finfo.links); if (link_len > info->max_link) info->max_link = link_len; info->total_len += name_len + 2; @@ -335,18 +345,22 @@ static void push_file( static void recurse_directory(char* dir_name) { DIR* d; + int capacity, size, save; struct dirent* file; - int save = push_path_buffer(dir_name); + struct FileInfo* files; + struct FileListInfo info; + + save = push_path_buffer(dir_name); d = get_directory(get_path_buffer()); if (d == NULL) { return; } - int capacity = 8; - int size = 0; - struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity); - struct FileListInfo info; + capacity = 8; + size = 0; + + files = malloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); while((file = readdir(d)) != NULL) { @@ -360,10 +374,11 @@ static void recurse_directory(char* dir_name) { } - if (flags.colored == NO) + if (flags.colored == NO) { printf("\n%s:\n", get_path_buffer()); - else + } else { printf("\n%s%s:%s\n", DIR_COLOR, get_path_buffer(), FILE_COLOR); + } list_files(files, size, info); @@ -377,23 +392,29 @@ static void recurse_directory(char* dir_name) { } static void list_directory(char* path) { + + DIR* d; + int capacity, size, save; + struct FileInfo* files; + struct FileListInfo info; + struct dirent* file; + if (flags.recurse) { recurse_directory(path); return; } - DIR* d = get_directory(path); + d = get_directory(path); if (d == NULL) return; - int save = push_path_buffer(path); + save = push_path_buffer(path); - int capacity = 8; - int size = 0; - struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity); - struct FileListInfo info; + capacity = 8; + size = 0; + + files = malloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); - struct dirent* file; while ((file = readdir(d)) != NULL) { if (!flags.hidden && prefix(".", file->d_name)) continue; if (flags.hide_dot && is_dot_dir(file->d_name)) continue; @@ -415,15 +436,20 @@ static bool is_dir(const char* path) { } static void list_file_args(int start, int argc, char** argv) { - int capacity = 8; - int size = 0; - struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity); + + int capacity, size, i; + struct FileInfo* files; struct FileListInfo info; + + capacity = 8; + size = 0; + + files = malloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { if (is_dir(argv[i])) continue; - push_file((struct FileInfo**) &files, &info, &size, &capacity, argv[i]); + push_file(&files, &info, &size, &capacity, argv[i]); } if (size > 0) list_files(files, size, info); @@ -487,6 +513,9 @@ static int long_arg(char* cur, char* next) { COMMAND(ls) { + int start, i; + bool titled; + flags.hidden = false; flags.more_info = false; flags.hide_dot = false; @@ -494,7 +523,7 @@ COMMAND(ls) { flags.recurse = false; flags.colored = NO; - int start = parse_args(argc, argv, help, short_arg, long_arg); + start = parse_args(argc, argv, help, short_arg, long_arg); if (argc - start == 0) { list_directory("."); @@ -503,15 +532,19 @@ COMMAND(ls) { list_file_args(start, argc, argv); - bool titled = argc - start > 1; - for (int i = start; i < argc; i++) { + titled = argc - start > 1; + for (i = start; i < argc; i++) { + if (!is_dir(argv[i])) continue; + if (titled && !flags.recurse) { - if (flags.colored != NO) + if (flags.colored != NO) { printf("\n%s%s:%s\n", DIR_COLOR, argv[i], FILE_COLOR); - else + } else { printf("\n%s:\n", argv[i]); + } } + list_directory(argv[i]); } diff --git a/src/commands/mkdir.c b/src/commands/mkdir.c index 3ff1afd..02fccca 100644 --- a/src/commands/mkdir.c +++ b/src/commands/mkdir.c @@ -28,7 +28,8 @@ static void help(void) { } static bool mkdir_parents(char* path) { - for (size_t i = 1; i < strlen(path); i++) { + size_t i; + for (i = 1; i < strlen(path); i++) { if (path[i] != '/') continue; path[i] = '\0'; if (mkdir(path, flags.mode) < 0 && errno != EEXIST) { @@ -41,13 +42,17 @@ static bool mkdir_parents(char* path) { } COMMAND(makedir) { + + int start, i; + if (argc < 1) global_help(help); flags.make_parent = false; flags.mode = 0755; - int start = parse_args(argc, argv, help, short_arg, NULL); + + start = parse_args(argc, argv, help, short_arg, NULL); - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { if (flags.make_parent && !mkdir_parents(argv[i])) { continue; } diff --git a/src/commands/mv.c b/src/commands/mv.c index f3e759a..d203607 100644 --- a/src/commands/mv.c +++ b/src/commands/mv.c @@ -38,18 +38,24 @@ static int short_arg(char c, char* next) { } static void mv_dir(bool exists) { + + char c; + if (exists && flags.dont_overwrite) { if (flags.verbose) output("skipping '%s'; overwrise is false", get_path_buffer_2()); return; } + if (exists && flags.prompt) { fprintf(stderr, "overwrite '%s'? ", get_path_buffer_2()); fflush(stderr); - char c = getchar(); + + c = getchar(); if (c != 'y' && c != 'Y') { if (flags.verbose) output("skipping..."); return; } + } if (rename(get_path_buffer(), get_path_buffer_2()) < 0) { @@ -61,12 +67,15 @@ static void mv_dir(bool exists) { COMMAND(mv) { + int start, dest, i; + struct stat s; + flags.refuse_if_dir = false; flags.dont_overwrite = false; flags.prompt = false; flags.verbose = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); if (argc - start < 2) { global_help(help); @@ -74,8 +83,7 @@ COMMAND(mv) { push_path_buffer_2(argv[argc-1]); - bool dest = true; - struct stat s; + dest = true; if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) { dest = false; error("cannot stat '%s': %s", get_path_buffer_2(), strerror(errno)); @@ -97,7 +105,7 @@ COMMAND(mv) { error("target '%s': Is Not A Directory", get_path_buffer_2()); } - for (int i = start; i < argc - 1; i++) { + for (i = start; i < argc - 1; i++) { int save = push_path_buffer(argv[i]); bool exists = lstat(get_path_buffer(), &s) >= 0; mv_dir(exists); diff --git a/src/commands/printf.c b/src/commands/printf.c index df6ce32..519b8a2 100644 --- a/src/commands/printf.c +++ b/src/commands/printf.c @@ -40,7 +40,7 @@ static void handle_percent(char n, const char* arg) { } case 'f': { double d = cast_double(arg); - printf("%lf", d); + printf("%f", d); break; } case 'c': { @@ -95,6 +95,11 @@ static void help(void) { } COMMAND(print) { + + size_t index; + int arg_index; + char n, *arg; + if (argc < 1) { global_help(help); return EXIT_SUCCESS; @@ -102,8 +107,8 @@ COMMAND(print) { parse_help(argc, argv, help); - size_t index = 0; - int arg_index = 0; + index = 0; + arg_index = 0; while (true) { char c = argv[0][index]; @@ -115,10 +120,10 @@ COMMAND(print) { continue; } - char n = argv[0][index]; + n = argv[0][index]; index++; - char* arg = NULL; + arg = NULL; if (arg_index < argc) { arg = argv[arg_index + 1]; } diff --git a/src/commands/rm.c b/src/commands/rm.c index 7d72c2d..8ce3e1c 100644 --- a/src/commands/rm.c +++ b/src/commands/rm.c @@ -40,16 +40,18 @@ static int short_arg(char c, char* next) { return ARG_UNUSED; } -static void rm_file(char* path); +static void rm_file (char* path); -static bool rm_dir() { - DIR* d = opendir(get_path_buffer()); +static bool rm_dir (void) { + DIR* d; + struct dirent* file; + + d = opendir(get_path_buffer()); if (d == NULL) { error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); return false; } - struct dirent* file; while ((file = readdir(d)) != NULL) { if (is_dot_dir(file->d_name)) continue; rm_file(file->d_name); @@ -82,9 +84,12 @@ static void rm_file(char* path) { } if (flags.prompt) { + char c; + fprintf(stderr, "delete '%s'? ", get_path_buffer()); fflush(stderr); - char c = getchar(); + + c = getchar(); if (c != 'y' && c != 'Y') { fprintf(stderr, "Skipping...\n"); pop_path_buffer(save); @@ -102,6 +107,9 @@ static void rm_file(char* path) { } COMMAND(rm) { + + int start, i; + if (argc < 1) { global_help(help); return EXIT_SUCCESS; @@ -112,7 +120,7 @@ COMMAND(rm) { flags.verbose = false; flags.recurse = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); #ifdef FRENCH if (streql(argv[0], "-fr")) { @@ -120,7 +128,7 @@ COMMAND(rm) { } #endif - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { rm_file(argv[i]); } diff --git a/src/commands/tac.c b/src/commands/tac.c index fbd0f74..d188de9 100644 --- a/src/commands/tac.c +++ b/src/commands/tac.c @@ -10,29 +10,36 @@ static void help(void) { } static void print_range(FILE* file, int start, int end) { - int len = end - start; + int len, i; + + len = end - start; fseek(file, start, SEEK_SET); - for (int i = 0; i < len; i++) { + + for (i = 0; i < len; i++) { putchar(getc(file)); } + fflush(stdout); } static char stdin_path[PATH_MAX]; -static FILE* read_stdin() { +static FILE* read_stdin (void) { static bool read; static FILE* file; + int r; + char c; if (read) goto finished; read = true; srand(time(NULL)); - int r = rand() % 1000000; + + r = rand() % 1000000; + sprintf(stdin_path, "/tmp/%d.tac", r); file = get_file(stdin_path, "w"); - char c; while((c = getchar()) != EOF) putc(c, file); fclose(file); @@ -43,15 +50,15 @@ finished: } static void parse_file(FILE* file, struct Stack* stack) { - char buf[1024]; - int read; + char buf[1024], c; + int read, i; int total = 1; stack_push_int(stack, 0); rewind(file); while ((read = fread(buf, 1, 1024, file)) > 0) { - for (int i = 0; i < read; i++) { - char c = buf[i]; + for (i = 0; i < read; i++) { + c = buf[i]; if (c != '\n') continue; stack_push_int(stack, total + i); } @@ -61,34 +68,39 @@ static void parse_file(FILE* file, struct Stack* stack) { static void tac_file(FILE* file) { struct Stack stack; - stack_init(&stack, 80); - - parse_file(file, &stack); - - rewind(file); int last, current; + + stack_init(&stack, 80); + parse_file(file, &stack); + rewind(file); + if (!stack_pop_int(&stack, &last)) goto cleanup; + while(stack_pop_int(&stack, ¤t)) { print_range(file, current, last); last = current; } cleanup: + stack_free(&stack); } COMMAND(tac) { + FILE* in; + int i; + parse_help(argc, argv, help); - FILE* in = read_stdin(); + in = read_stdin(); if (argc < 1) { tac_file(in); return EXIT_SUCCESS; } - for (int i = 0; i < argc; i++) { + for (i = 0; i < argc; i++) { FILE* file = get_file(argv[i], "r"); if (file == stdin) { tac_file(in); diff --git a/src/commands/tail.c b/src/commands/tail.c index 4856bc0..07b3d2b 100644 --- a/src/commands/tail.c +++ b/src/commands/tail.c @@ -10,18 +10,27 @@ static struct { } flags; static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) { - char* ring[count]; + + char** ring; + int* ring_len; + int index, read; + unsigned int size, i; + size_t len; + char* line; + + ring = malloc(sizeof(char*) * count); memset(ring, 0, sizeof(char*) * count); - int ring_len[count]; + ring_len = malloc(sizeof(int) * count); - int index = 0; - unsigned int size = 0; + index = 0; + size = 0; - int read; fseek(file, skip, SEEK_SET); - size_t len = skip; - char* line = NULL; + + len = skip; + line = NULL; + while ((read = getline(&line, &len, file)) != -1) { if (ring[index] != NULL) free(ring[index]); @@ -37,8 +46,8 @@ static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) { index += count - size; index %= count; - - for (unsigned int i = 0; i < size; i++) { + + for (i = 0; i < size; i++) { fwrite(ring[index], ring_len[index], 1, stdout); free(ring[index]); index += 1; @@ -47,20 +56,28 @@ static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) { free(line); fclose(file); + free(ring); + free(ring_len); return len; } static size_t tail_file_chars(FILE* file, unsigned int count, size_t skip) { - char ring[count]; + + char* ring; + int index; + unsigned int size, i; + int read, c; + + ring = malloc(sizeof(char) * count); memset(ring, 0, count); - int index = 0; - unsigned int size = 0; + index = 0; + size = 0; fseek(file, skip, SEEK_SET); - int read = skip; - int c; + read = skip; + while((c = getc(file)) != EOF) { ring[index] = c; index++; @@ -72,7 +89,7 @@ static size_t tail_file_chars(FILE* file, unsigned int count, size_t skip) { index += count - size; index %= count; - for (unsigned int i = 0; i < size; i++) { + for (i = 0; i < size; i++) { putchar(ring[index]); index += 1; index %= count; @@ -108,10 +125,14 @@ static void print_header(char* path, bool many) { } static void tail_file(char* path, bool many) { - FILE* file = get_file(path, "r"); + + FILE* file; + size_t skip; + + file = get_file(path, "r"); print_header(path, many); - size_t skip = 0; + skip = 0; while (true) { if (flags.lines) { skip = tail_file_lines(file, flags.count, skip); @@ -127,22 +148,32 @@ static void tail_file(char* path, bool many) { static int short_arg(char c, char* next) { switch (c) { case 'c': { + long int bkm; + flags.lines = false; + check_arg(next); - long int bkm = get_blkm(next); + bkm = get_blkm(next); + if (bkm < 1) { error("bkm cannot be less than 1"); } + flags.count = bkm; return ARG_USED; } case 'n': { + long int bkm; + flags.lines = true; + check_arg(next); - long int bkm = get_blkm(next); + bkm = get_blkm(next); + if (bkm < 1) { error("bkm cannot be less than 1"); } + flags.count = bkm; return ARG_USED; } @@ -156,11 +187,15 @@ static int short_arg(char c, char* next) { flags.print_as_grow = true; break; case 's': { + long int sec; + check_arg(next); - long int sec = get_number(next); + sec = get_number(next); + if (sec < 1) { error("wait seconds cannot be less than 1"); } + flags.grow_wait = sec; return ARG_USED; } @@ -172,6 +207,8 @@ static int short_arg(char c, char* next) { COMMAND(tail) { + int start, count, i; + flags.count = 10; flags.dont_print_headers = false; flags.print_headers = false; @@ -179,9 +216,9 @@ COMMAND(tail) { flags.print_as_grow = false; flags.grow_wait = 10; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); - int count = argc - start; + count = argc - start; if (count < 1) { tail_file_lines(stdin, 10, 0); @@ -193,7 +230,7 @@ COMMAND(tail) { return EXIT_SUCCESS; } - for (int i = 0; i < count; i++) { + for (i = 0; i < count; i++) { tail_file(argv[start + i], true); } diff --git a/src/commands/tee.c b/src/commands/tee.c index 652e369..b9b31be 100644 --- a/src/commands/tee.c +++ b/src/commands/tee.c @@ -17,16 +17,20 @@ static void help(void) { static void handle(int dummy){UNUSED(dummy);} -static void run_tee(int file_count, FILE* files[file_count]) { +static void run_tee(int file_count, FILE** files) { char c; + int i; + while((c = getchar()) != EOF) { - for (int i = 0; i < file_count; i++) { + int i; + for (i = 0; i < file_count; i++) { fwrite(&c, 1, 1, files[i]); fflush(files[i]); } putchar(c); } - for (int i = 0; i < file_count; i++) { + + for (i = 0; i < file_count; i++) { fclose(files[i]); } } @@ -48,10 +52,13 @@ static int short_arg(char c, char* next) { COMMAND(tee) { + int start, i; + FILE** files; + flags.append = false; flags.handle_sigint = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); if (flags.handle_sigint) { signal(SIGINT, handle); @@ -62,8 +69,9 @@ COMMAND(tee) { return EXIT_SUCCESS; } - FILE* files[argc - start]; - for (int i = start; i < argc; i++) { + files = malloc(sizeof(FILE*) * (argc - start)); + + for (i = start; i < argc; i++) { FILE* file = get_file(argv[i], flags.append ? "a" : "w"); files[i - start] = file; } diff --git a/src/commands/wc.c b/src/commands/wc.c index 4012b6c..d8905a5 100644 --- a/src/commands/wc.c +++ b/src/commands/wc.c @@ -50,7 +50,8 @@ static void run_wc(FILE* file) { int read; char buf[BS]; while ((read = fread(buf, 1, 1024, file)) > 0) { - for (int i = 0; i < read; i++) { + int i; + for (i = 0; i < read; i++) { char ch = buf[i]; b++; if (ch == '\n') { @@ -118,6 +119,9 @@ static int short_arg(char c, char* next) { } COMMAND(wc) { + + int start, i; + flags.newlines = false; flags.words = false; flags.characters = false; @@ -126,7 +130,7 @@ COMMAND(wc) { flags.has_flags = false; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); if (!flags.has_flags) { flags.newlines = true; @@ -140,7 +144,7 @@ COMMAND(wc) { return EXIT_SUCCESS; } - for (int i = start; i < argc; i++) { + for (i = start; i < argc; i++) { FILE* file = get_file(argv[i], "r"); run_wc(file); printf("\t%s\n", argv[i]); diff --git a/src/commands/whoami.c b/src/commands/whoami.c index 623a35a..7fd7c85 100644 --- a/src/commands/whoami.c +++ b/src/commands/whoami.c @@ -9,10 +9,15 @@ static void help(void) { } COMMAND(whoami) { + + uid_t usr; + struct passwd* passwd; + parse_help(argc, argv, help); - uid_t usr = getuid(); - struct passwd* passwd = getpwuid(usr); + usr = getuid(); + passwd = getpwuid(usr); + if (passwd == NULL) { printf("\x1b[1;91myou do not exist.\n"); } else { diff --git a/src/commands/xargs.c b/src/commands/xargs.c index 8f24441..3008c3c 100644 --- a/src/commands/xargs.c +++ b/src/commands/xargs.c @@ -24,6 +24,7 @@ static void help(void) { static int short_arg(char c, char* next) { UNUSED(next); + switch (c) { case '0': flags.null_seperated = true; @@ -41,14 +42,19 @@ static int short_arg(char c, char* next) { case 'p': flags.prompt_command = true; break; - case 'n': + case 'n': { + long int n; + check_arg(next); - long int n = get_number(next); + n = get_number(next); + if (n < 1) { error("max arg count must be at least 1"); } + flags.max_args = n; return ARG_USED; + } default: return ARG_INVALID; } @@ -57,13 +63,16 @@ static int short_arg(char c, char* next) { char* read_next(FILE* file, int arg_count) { + int size, capacity; + char* buf; + char c; + if (flags.max_args != -1 && arg_count == flags.max_args) return NULL; - int size = 0; - int capacity = 8; - char* buf = malloc(sizeof(char) * capacity); + size = 0; + capacity = 8; + buf = malloc(sizeof(char) * capacity); - char c; while(c = getc(file), true) { if (c == EOF && size == 0) { free(buf); @@ -99,6 +108,12 @@ void read_args(FILE* file, char*** args, int* size, int* capacity) { } COMMAND(xargs) { + + int start, arg_start, arg_on_stack_count; + int size, capacity, i; + char* command; + char** args; + flags.null_seperated = false; flags.ignore_empty = false; flags.print_command = false; @@ -106,17 +121,15 @@ COMMAND(xargs) { flags.max_args = -1; flags.file = stdin; - int start = parse_args(argc, argv, help, short_arg, NULL); + start = parse_args(argc, argv, help, short_arg, NULL); - char* command; if (start >= argc) { command = "echo"; } else { command = argv[start]; } - int arg_start = start + 1; - int arg_on_stack_count; + arg_start = start + 1; if (arg_start >= argc) { arg_on_stack_count = 0; @@ -125,9 +138,10 @@ COMMAND(xargs) { arg_on_stack_count = argc - arg_start; } - int size = arg_on_stack_count + 1; - int capacity = size + 8; - char** args = malloc(sizeof(char*) * capacity); + size = arg_on_stack_count + 1; + capacity = size + 8; + + args = malloc(sizeof(char*) * capacity); args[0] = command; memcpy(&args[1], &argv[arg_start], arg_on_stack_count * sizeof(char*)); read_args(flags.file, &args, &size, &capacity); @@ -135,18 +149,23 @@ COMMAND(xargs) { if (flags.ignore_empty && size < 2) goto cleanup; if (flags.prompt_command || flags.print_command) { - for (int i = 0; i < size - 1; i++) { + for (i = 0; i < size - 1; i++) { fprintf(stderr, "%s ", args[i]); } fprintf(stderr, "\b\n"); } if (flags.prompt_command) { + FILE* in; + char c; + fprintf(stderr, "Run command? "); fflush(stderr); - FILE* in = get_tty_stream("r"); - char c = getc(in); + + in = get_tty_stream("r"); + c = getc(in); fclose(in); + if (c != 'y' && c != 'Y') { fprintf(stderr, "Skipping...\n"); goto cleanup; @@ -159,7 +178,7 @@ COMMAND(xargs) { cleanup: - for (int i = arg_on_stack_count + 1; i < size - 1; i++) { + for (i = arg_on_stack_count + 1; i < size - 1; i++) { free(args[i]); } fclose(flags.file); diff --git a/src/commands/yes.c b/src/commands/yes.c index 39cf75d..6a44789 100644 --- a/src/commands/yes.c +++ b/src/commands/yes.c @@ -6,15 +6,16 @@ static void help(void) { } COMMAND(yes) { + const char* repeat; + int i; parse_help(argc, argv, help); - const char* repeat; if (argc == 0) { repeat = "y"; } else { repeat = argv[0]; - for (int i = 1; i < argc; i++) { + for (i = 1; i < argc; i++) { *(argv[i]-1) = ' '; } } diff --git a/src/main.c b/src/main.c index c5943f0..1977e17 100644 --- a/src/main.c +++ b/src/main.c @@ -11,12 +11,15 @@ char* cmd; int main (ARGUMENTS) { +#ifdef CHECK_LINK + struct stat buf; +#endif + if (argc < 1) { return EXIT_FAILURE; } #ifdef CHECK_LINK - struct stat buf; lstat(argv[0], &buf); if (!S_ISLNK(buf.st_mode)) { diff --git a/src/util/regex.c b/src/util/regex.c index 58b1f54..0e0dc52 100644 --- a/src/util/regex.c +++ b/src/util/regex.c @@ -39,7 +39,7 @@ #define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */ -enum { UNUSED, DOT, BEGIN, END, QUESTIONMARK, STAR, PLUS, CHAR, CHAR_CLASS, INV_CHAR_CLASS, DIGIT, NOT_DIGIT, ALPHA, NOT_ALPHA, WHITESPACE, NOT_WHITESPACE, /* BRANCH */ }; +enum { UNUSED, DOT, BEGIN, END, QUESTIONMARK, STAR, PLUS, CHAR, CHAR_CLASS, INV_CHAR_CLASS, DIGIT, NOT_DIGIT, ALPHA, NOT_ALPHA, WHITESPACE, NOT_WHITESPACE}; typedef struct regex_t { @@ -199,7 +199,7 @@ re_t re_compile(const char* pattern) { if (ccl_bufidx >= MAX_CHAR_CLASS_LEN - 1) { - //fputs("exceeded internal buffer!\n", stderr); + /* fputs("exceeded internal buffer!\n", stderr); */ return 0; } if (pattern[i+1] == 0) /* incomplete pattern, missing non-zero char after '\\' */ @@ -210,7 +210,7 @@ re_t re_compile(const char* pattern) } else if (ccl_bufidx >= MAX_CHAR_CLASS_LEN) { - //fputs("exceeded internal buffer!\n", stderr); + /* fputs("exceeded internal buffer!\n", stderr); */ return 0; } ccl_buf[ccl_bufidx++] = pattern[i]; @@ -218,7 +218,7 @@ re_t re_compile(const char* pattern) if (ccl_bufidx >= MAX_CHAR_CLASS_LEN) { /* Catches cases such as [00000000000000000000000000000000000000][ */ - //fputs("exceeded internal buffer!\n", stderr); + /* fputs("exceeded internal buffer!\n", stderr); */ return 0; } /* Null-terminate string end */ diff --git a/src/util/shared.c b/src/util/shared.c index 5e08b8d..2e0c98a 100644 --- a/src/util/shared.c +++ b/src/util/shared.c @@ -43,27 +43,33 @@ void output(const char *format, ...) { 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; } - FILE* file; 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; } @@ -102,7 +108,8 @@ long int get_blkm(const char* text) { default: error("invalid bkm type %c", *end); } - // shouldnt get here anyways + + /* shouldnt get here anyways */ return 0; } @@ -118,8 +125,10 @@ mode_t get_mode(const char* next) { } bool streql(const char* a, const char* b) { - if (*a != *b) return false; int n = 0; + + if (*a != *b) return false; + while (true) { if (*(a+n) != *(b+n)) return false; if (*(a+n) == '\0') return true; @@ -133,25 +142,33 @@ bool prefix(const char* pre, const char* str) { static char fs_types[5] = {'K','M','G','T','P'}; void print_file_size(size_t bytes, char buf[5]) { - int index = 0; - float next = bytes; + int index, n; + float next; + + index = 0; + next = bytes; + while (true) { if (next < 1000) { break; } + if (index == 5) { printf("999P"); return; - }; + } + next /= 1024; index++; } - int n = snprintf(buf, 4, "%u", (int)(next+.5)); + n = snprintf(buf, 4, "%u", (int)(next+.5)); + if (index > 0) { buf[n] = (fs_types[index - 1]); n++; } + buf[n] = '\0'; } @@ -159,8 +176,10 @@ 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); - int n = snprintf(buf, 5, "%s ", months[info->tm_mon]); + n = snprintf(buf, 5, "%s ", months[info->tm_mon]); if (info->tm_mday < 10) { buf[n] = ' '; @@ -203,35 +222,45 @@ void global_help(void (*help)(void)) { } void parse_help(int argc, char** argv, void (*help)(void)) { + int i; + if (argc < 1) return; - for (int i = 0; i < argc; i++) { + + 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; - int start = 0; - for (int i = 0; i < argc; i++) { + 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); - char* next_arg; if (i + 1 == argc) { next_arg = NULL; } else { next_arg = argv[i+1]; } - int current = i; + current = i; if (prefix("--", argv[i])) { + int r; + if (long_arg == NULL) { goto exit; } - int r = long_arg(argv[current], next_arg); + + r = long_arg(argv[current], next_arg); + if (r == ARG_USED) { i++; start++; @@ -239,13 +268,20 @@ int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char, 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 (size_t j = 1; j < strlen(argv[current]); j++) { - int r = short_arg(argv[current][j], next_arg); + + for (j = 1; j < strlen(argv[current]); j++) { + + r = short_arg(argv[current][j], next_arg); + if (r == ARG_USED) { i++; start++; @@ -259,11 +295,13 @@ int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char, start++; } + exit: + return start; } -int get_tty() { +int get_tty (void) { int fd = open(_PATH_TTY, O_RDONLY); if (fd < 0) error("failed to get tty: %s", strerror(errno)); return fd; @@ -279,13 +317,18 @@ FILE* get_tty_stream(char* type) { } static int push_path_buffer_b(char* buf, int* index, const char* string) { - int save = *index; + int save, string_len; + + save = *index; if (*index > 1 || (*index == 1 && buf[0] != '/')) { buf[(*index)++] = '/'; } - int string_len = strlen(string); + + string_len = strlen(string); memcpy(buf + *index, string, string_len + 1); + *index += string_len; + return save; } @@ -297,7 +340,7 @@ static void pop_path_buffer_b(char* buf, int* index, int i) { static char path_buffer[PATH_MAX + 1]; static int path_buffer_index = 0; -char* get_path_buffer() { +char* get_path_buffer(void) { return path_buffer; } @@ -312,7 +355,7 @@ void pop_path_buffer(int i) { static char path_buffer_2[PATH_MAX + 1]; static int path_buffer_index_2 = 0; -char* get_path_buffer_2() { +char* get_path_buffer_2(void) { return path_buffer_2; } diff --git a/src/util/shared.h b/src/util/shared.h index 07da4a7..a3e6a56 100644 --- a/src/util/shared.h +++ b/src/util/shared.h @@ -1,7 +1,8 @@ -#pragma once +#ifndef SHARED_H +#define SHARED_H +#include #include -#include #include #include @@ -26,6 +27,10 @@ #define COLOR "m" +typedef uint8_t bool; +#define true 1 +#define false 0 + enum When { YES, NO, @@ -65,15 +70,17 @@ 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(); +int get_tty(void); FILE* get_tty_stream(char* type); -char* get_path_buffer(); +char* get_path_buffer(void); int push_path_buffer(const char* string); void pop_path_buffer(int i); -char* get_path_buffer_2(); +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/src/util/stack.c b/src/util/stack.c index 15d5a8e..acffc1a 100644 --- a/src/util/stack.c +++ b/src/util/stack.c @@ -30,3 +30,14 @@ void* stack_pop(struct Stack* stack, size_t len) { void stack_free(struct Stack *stack) { free(stack->data); } + +void stack_push_int(struct Stack *stack, int value) { + stack_push(stack, &value, sizeof(int)); +} + +bool stack_pop_int(struct Stack *stack, int* value) { + void* d = stack_pop(stack, sizeof(int)); + if (d == NULL) return false; + *value = *(int*)(d); + return true; +} diff --git a/src/util/stack.h b/src/util/stack.h index 01a48e5..8d6fc80 100644 --- a/src/util/stack.h +++ b/src/util/stack.h @@ -1,7 +1,9 @@ -#pragma once +#ifndef STACK_H +#define STACK_H + +#include "shared.h" #include -#include struct Stack { size_t size; @@ -14,13 +16,7 @@ void stack_push(struct Stack* stack, void* data, size_t len); void* stack_pop(struct Stack* stack, size_t len); void stack_free(struct Stack* stack); -inline void stack_push_int(struct Stack* stack, int value) { - stack_push(stack, &value, sizeof(int)); -} +void stack_push_int(struct Stack* stack, int value); +bool stack_pop_int(struct Stack* stack, int* value); -inline bool stack_pop_int(struct Stack* stack, int* value) { - void* d = stack_pop(stack, sizeof(int)); - if (d == NULL) return false; - *value = *(int*)(d); - return true; -} +#endif