diff options
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/ls.c | 31 | ||||
-rw-r--r-- | src/commands/tac.c | 105 |
2 files changed, 127 insertions, 9 deletions
diff --git a/src/commands/ls.c b/src/commands/ls.c index ce7206c..3aad1a1 100644 --- a/src/commands/ls.c +++ b/src/commands/ls.c @@ -9,11 +9,12 @@ #define FILE_COLOR ANSCII BLACK COLOR #define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR #define DIR_COLOR_EXEC ANSCII BACKGROUND GREEN NEXT NORMAL BLACK COLOR -#define LINK_COLOR ANSCII BOLD NEXT HIGHLIGHT TURQUOISE COLOR +#define LINK_COLOR ANSCII BOLD NEXT NORMAL TURQUOISE COLOR #define SET_UID_COLOR ANSCII BACKGROUND RED NEXT NORMAL WHITE COLOR #define SET_GID_COLOR ANSCII BACKGROUND YELLOW NEXT NORMAL BLACK COLOR #define EXEC_COLOR ANSCII BOLD NEXT NORMAL GREEN COLOR #define BLK_COLOR ANSCII BOLD NEXT NORMAL YELLOW COLOR +#define SOCK_COLOR ANSCII BOLD NEXT NORMAL MAGENTA COLOR static struct { bool hidden; @@ -32,6 +33,7 @@ struct FileInfo { char mode[11]; char size[5]; int links; + int bytes; bool set_uid; bool set_gid; bool exec; @@ -45,6 +47,7 @@ struct FileListInfo { int max_size; int max_name; int total_len; + int total_size; }; static DIR* get_directory(char* path) { @@ -173,6 +176,9 @@ static bool get_file_info(const char* file_path, const char* dir_path, struct Fi print_file_size(s.st_size, info->size); print_date_time(s.st_mtim.tv_sec + s.st_mtim.tv_nsec / 1000000000, info->date); + + info->bytes = (s.st_size + s.st_blksize - 1) / s.st_blksize * s.st_blksize; + return true; } @@ -186,10 +192,11 @@ static char* get_file_color(struct FileInfo* info) { } } else if (info->type == DT_LNK) { color = LINK_COLOR; + } else if (info->type == DT_SOCK) { + color = SOCK_COLOR; } else if ( info->type == DT_CHR || - info->type == DT_BLK || - info->type == DT_SOCK + info->type == DT_BLK ) { color = BLK_COLOR; } else { @@ -207,6 +214,13 @@ static char* get_file_color(struct FileInfo* info) { } static void list_files(struct FileInfo* files, int file_len, struct FileListInfo info, const char* dir_path) { + + 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); @@ -316,6 +330,7 @@ static void push_file( if (link_len > info->max_link) info->max_link = link_len; info->total_len += name_len + 2; + info->total_size += finfo.bytes; (*files)[*size] = finfo; (*size)++; @@ -328,7 +343,6 @@ static bool recurse_directory(char* path) { d = get_directory(path); if (d == NULL) return false; - int capacity = 8; int size = 0; @@ -337,9 +351,9 @@ static bool recurse_directory(char* path) { memset(&info, 0, sizeof(struct FileListInfo)); while((file = readdir(d)) != NULL) { - if (file->d_type == DT_DIR) continue; + if (file->d_type == DT_DIR && !is_dot_dir(file->d_name)) continue; if (!flags.hidden && prefix(".", file->d_name)) continue; - if (is_dot_dir(file->d_name)) continue; + if (flags.hide_dot && is_dot_dir(file->d_name)) continue; if (first) { if (flags.colored == NO) printf("\n%s:\n", path); @@ -417,7 +431,7 @@ static void list_file_args(int start, int argc, char** argv) { for (int i = start; i < argc; i++) { if (is_dir(argv[i])) continue; - push_file((struct FileInfo**) &files, &info, &size, &capacity, argv[i], "."); + push_file((struct FileInfo**) &files, &info, &size, &capacity, argv[i], argv[i][0] == '/' ? "" : "."); } if (size > 0) list_files(files, size, info, "."); @@ -506,8 +520,7 @@ COMMAND(ls) { else printf("\n%s:\n", argv[i]); } - if (list_directory(argv[i]) && i + 1 != argc) - if (titled && !flags.recurse) printf("\n"); + list_directory(argv[i]); } return EXIT_SUCCESS; diff --git a/src/commands/tac.c b/src/commands/tac.c new file mode 100644 index 0000000..fbd0f74 --- /dev/null +++ b/src/commands/tac.c @@ -0,0 +1,105 @@ +#include "../command.h" + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> + +static void help(void) { + printf("Usage: tac [FILE]...\n\n"); + printf("Concatenate FILEs and print them in reverse\n"); +} + +static void print_range(FILE* file, int start, int end) { + int len = end - start; + fseek(file, start, SEEK_SET); + for (int i = 0; i < len; i++) { + putchar(getc(file)); + } + fflush(stdout); +} + +static char stdin_path[PATH_MAX]; + +static FILE* read_stdin() { + static bool read; + static FILE* file; + + if (read) goto finished; + read = true; + + srand(time(NULL)); + int 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); + + file = get_file(stdin_path, "r"); + +finished: + return file; +} + +static void parse_file(FILE* file, struct Stack* stack) { + char buf[1024]; + int read; + 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]; + if (c != '\n') continue; + stack_push_int(stack, total + i); + } + total += read; + } +} + +static void tac_file(FILE* file) { + struct Stack stack; + stack_init(&stack, 80); + + parse_file(file, &stack); + + rewind(file); + int last, current; + 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) { + + parse_help(argc, argv, help); + + FILE* in = read_stdin(); + + if (argc < 1) { + tac_file(in); + return EXIT_SUCCESS; + } + + for (int i = 0; i < argc; i++) { + FILE* file = get_file(argv[i], "r"); + if (file == stdin) { + tac_file(in); + } else { + tac_file(file); + fclose(file); + } + } + + fclose(in); + remove(stdin_path); + + return EXIT_SUCCESS; +} |