ansii c
This commit is contained in:
parent
bd471562c7
commit
b1364be7e2
30 changed files with 679 additions and 301 deletions
19
.clangd
Normal file
19
.clangd
Normal file
|
@ -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
|
2
Makefile
2
Makefile
|
@ -8,7 +8,7 @@ PATCH = 1
|
||||||
|
|
||||||
INCFLAGS = $(shell echo $(SOURCE) | xargs printf -- '-I%s')
|
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 += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK
|
||||||
CCFLAGS += $(INCFLAGS)
|
CCFLAGS += $(INCFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
#ifndef COMMAND_H
|
||||||
|
#define COMMAND_H
|
||||||
|
|
||||||
#include "util/shared.h"
|
#include "util/shared.h"
|
||||||
#include "util/stack.h"
|
#include "util/stack.h"
|
||||||
#include "util/regex.h"
|
#include "util/regex.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -39,3 +41,5 @@ COMMAND(cp);
|
||||||
COMMAND(makedir);
|
COMMAND(makedir);
|
||||||
COMMAND(mv);
|
COMMAND(mv);
|
||||||
COMMAND(grep);
|
COMMAND(grep);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -16,7 +16,7 @@ static bool printable(char c) {
|
||||||
case '\r': return true;
|
case '\r': return true;
|
||||||
case '\b': return true;
|
case '\b': return true;
|
||||||
case '\t': 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) {
|
COMMAND(cat) {
|
||||||
|
|
||||||
|
int start;
|
||||||
|
int arg_len;
|
||||||
|
int i;
|
||||||
|
|
||||||
flags.number_lines = false;
|
flags.number_lines = false;
|
||||||
flags.number_non_empty = false;
|
flags.number_non_empty = false;
|
||||||
flags.change_non_print = false;
|
flags.change_non_print = false;
|
||||||
flags.change_tabs = false;
|
flags.change_tabs = false;
|
||||||
flags.end_lines_dollar = 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) {
|
if (arg_len < 1) {
|
||||||
cat_file(stdin);
|
cat_file(stdin);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = start; i < argc; i++) {
|
for (i = start; i < argc; i++) {
|
||||||
FILE* in = get_file(argv[i], "r");
|
FILE* in = get_file(argv[i], "r");
|
||||||
cat_file(in);
|
cat_file(in);
|
||||||
if (in != stdin)
|
if (in != stdin)
|
||||||
|
|
|
@ -50,17 +50,19 @@ static int short_arg(char c, char* next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool copy_file(char* from, char* to) {
|
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
|
#define BS 1024
|
||||||
|
|
||||||
|
FILE *from_f, *to_f;
|
||||||
char buf[BS];
|
char buf[BS];
|
||||||
int read;
|
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) {
|
while ((read = fread(buf, 1, BS, from_f)) > 0) {
|
||||||
fwrite(buf, 1, read, to_f);
|
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_file(char* path);
|
||||||
|
|
||||||
static void cp_directory(struct stat* s) {
|
static void cp_directory(struct stat* s) {
|
||||||
|
|
||||||
|
DIR* d;
|
||||||
|
struct dirent* file;
|
||||||
|
|
||||||
if (!flags.recurse) {
|
if (!flags.recurse) {
|
||||||
error_s("-r not specified; omitting directory '%s'", get_path_buffer());
|
error_s("-r not specified; omitting directory '%s'", get_path_buffer());
|
||||||
return;
|
return;
|
||||||
|
@ -133,14 +139,13 @@ static void cp_directory(struct stat* s) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR* d = opendir(get_path_buffer());
|
d = opendir(get_path_buffer());
|
||||||
|
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
error_s("cannot open directory '%s': %s", get_path_buffer(), strerror(errno));
|
error_s("cannot open directory '%s': %s", get_path_buffer(), strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent* file;
|
|
||||||
while ((file = readdir(d)) != NULL) {
|
while ((file = readdir(d)) != NULL) {
|
||||||
if (is_dot_dir(file->d_name)) continue;
|
if (is_dot_dir(file->d_name)) continue;
|
||||||
cp_file(file->d_name);
|
cp_file(file->d_name);
|
||||||
|
@ -148,10 +153,11 @@ static void cp_directory(struct stat* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* get_file_name(char* path) {
|
static char* get_file_name(char* path) {
|
||||||
if (path[0] == '\0') return path;
|
|
||||||
|
|
||||||
int last = 0;
|
int last = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
if (path[0] == '\0') return path;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (path[i+1] == '\0') break;
|
if (path[i+1] == '\0') break;
|
||||||
if (path[i] == '/') {
|
if (path[i] == '/') {
|
||||||
|
@ -188,19 +194,22 @@ static void cp_file(char* path) {
|
||||||
|
|
||||||
COMMAND(cp) {
|
COMMAND(cp) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
struct stat s;
|
||||||
|
|
||||||
flags.hard_link = false;
|
flags.hard_link = false;
|
||||||
flags.sym_link = false;
|
flags.sym_link = false;
|
||||||
flags.preserve = false;
|
flags.preserve = false;
|
||||||
flags.recurse = false;
|
flags.recurse = false;
|
||||||
flags.verbose = 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) {
|
if (argc - start < 2) {
|
||||||
global_help(help);
|
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) {
|
if (argc - start == 2) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if (lstat(argv[start], &s) < 0) {
|
if (lstat(argv[start], &s) < 0) {
|
||||||
|
@ -216,15 +225,14 @@ COMMAND(cp) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push directory
|
/* push directory */
|
||||||
push_path_buffer_2(argv[argc-1]);
|
push_path_buffer_2(argv[argc-1]);
|
||||||
|
|
||||||
struct stat s;
|
|
||||||
if (lstat(get_path_buffer_2(), &s) < 0) {
|
if (lstat(get_path_buffer_2(), &s) < 0) {
|
||||||
error("target: '%s': %s", get_path_buffer_2(), strerror(errno));
|
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]);
|
cp_file(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,13 @@ COMMAND(dd) {
|
||||||
FILE* out_file = stdout;
|
FILE* out_file = stdout;
|
||||||
int bs = 1024;
|
int bs = 1024;
|
||||||
int count = -1;
|
int count = -1;
|
||||||
|
int i;
|
||||||
|
char* buffer;
|
||||||
|
size_t read;
|
||||||
|
|
||||||
parse_help(argc, argv, help);
|
parse_help(argc, argv, help);
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (prefix("if=", argv[i])) {
|
if (prefix("if=", argv[i])) {
|
||||||
char* path = argv[i] + 3;
|
char* path = argv[i] + 3;
|
||||||
in_file = get_file(path, "rb");
|
in_file = get_file(path, "rb");
|
||||||
|
@ -42,8 +45,8 @@ COMMAND(dd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* buffer = malloc(bs);
|
buffer = malloc(bs);
|
||||||
size_t read;
|
|
||||||
while ((read = fread(buffer, 1, bs, in_file)) != 0) {
|
while ((read = fread(buffer, 1, bs, in_file)) != 0) {
|
||||||
fwrite(buffer, 1, read, out_file);
|
fwrite(buffer, 1, read, out_file);
|
||||||
if (--count, count == 0) break;
|
if (--count, count == 0) break;
|
||||||
|
|
|
@ -8,6 +8,8 @@ static struct {
|
||||||
static void print_with_escape_codes(const char* str) {
|
static void print_with_escape_codes(const char* str) {
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
char n;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char c = str[index];
|
char c = str[index];
|
||||||
index++;
|
index++;
|
||||||
|
@ -18,7 +20,7 @@ static void print_with_escape_codes(const char* str) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char n = str[index];
|
n = str[index];
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
|
@ -71,6 +73,8 @@ static int short_arg(char c, char* next) {
|
||||||
|
|
||||||
COMMAND(echo) {
|
COMMAND(echo) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -78,9 +82,9 @@ COMMAND(echo) {
|
||||||
flags.escape_codes = false;
|
flags.escape_codes = false;
|
||||||
flags.newline = true;
|
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) {
|
if (flags.escape_codes) {
|
||||||
print_with_escape_codes(argv[i]);
|
print_with_escape_codes(argv[i]);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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) {
|
static bool parse_regex(char** end, struct LineAddress* address, enum RegexDirection dir) {
|
||||||
re_t regex;
|
re_t regex;
|
||||||
|
unsigned long cap, siz, i, until;
|
||||||
|
long int* buf;
|
||||||
|
|
||||||
if (!read_regex(end, ®ex, dir)) return false;
|
if (!read_regex(end, ®ex, dir)) return false;
|
||||||
|
|
||||||
unsigned long cap = 8;
|
cap = 8;
|
||||||
unsigned long siz = 0;
|
siz = 0;
|
||||||
long int* buf = malloc(cap * sizeof(long int));
|
buf = malloc(cap * sizeof(long int));
|
||||||
|
|
||||||
unsigned long i = (dir == ALL ? 0 : line_current);
|
i = (dir == ALL ? 0 : line_current);
|
||||||
unsigned long until = (dir == BEFORE ? 0 : line_count - 1);
|
until = (dir == BEFORE ? 0 : line_count - 1);
|
||||||
for (; (dir == BEFORE ? i >= until : i < until); dir == BEFORE ? i-- : i++) {
|
for (; (dir == BEFORE ? i >= until : i < until); dir == BEFORE ? i-- : i++) {
|
||||||
int len;
|
int len;
|
||||||
if (re_matchp(regex, lines[i], &len) == -1) {
|
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) {
|
static bool parse_regex_lines(char** end, struct LineAddress* address) {
|
||||||
re_t regex;
|
re_t regex;
|
||||||
|
unsigned long cap, siz;
|
||||||
|
long int* buf;
|
||||||
|
int len;
|
||||||
|
struct LineAddress addr;
|
||||||
|
|
||||||
if (!read_regex(end, ®ex, ALL)) return false;
|
if (!read_regex(end, ®ex, ALL)) return false;
|
||||||
|
|
||||||
unsigned long cap = 8;
|
cap = 8;
|
||||||
unsigned long siz = 0;
|
siz = 0;
|
||||||
long int* buf = malloc(cap * sizeof(long int));
|
buf = malloc(cap * sizeof(long int));
|
||||||
int len;
|
|
||||||
|
|
||||||
struct LineAddress addr = *address;
|
addr = *address;
|
||||||
if (addr.type == INDEX) {
|
if (addr.type == INDEX) {
|
||||||
if (re_matchp(regex, lines[addr.data.index.i], &len) != -1) {
|
if (re_matchp(regex, lines[addr.data.index.i], &len) != -1) {
|
||||||
buf[0] = addr.data.index.i;
|
buf[0] = addr.data.index.i;
|
||||||
siz = 1;
|
siz = 1;
|
||||||
}
|
}
|
||||||
} else if (addr.type == RANGE) {
|
} 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;
|
if (re_matchp(regex, lines[i], &len) == -1) continue;
|
||||||
expand_buffer(&buf, &cap, &siz);
|
expand_buffer(&buf, &cap, &siz);
|
||||||
buf[siz] = i;
|
buf[siz] = i;
|
||||||
siz++;
|
siz++;
|
||||||
}
|
}
|
||||||
} else if (addr.type == SET) {
|
} 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;
|
if (re_matchp(regex, lines[addr.data.set.b[i]], &len) == -1) continue;
|
||||||
expand_buffer(&buf, &cap, &siz);
|
expand_buffer(&buf, &cap, &siz);
|
||||||
buf[siz] = addr.data.set.b[i];
|
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) {
|
static bool read_address(char** command, bool whitespace, struct LineAddress* a) {
|
||||||
char* index = *command;
|
char* index = *command;
|
||||||
struct LineAddress address;
|
struct LineAddress address;
|
||||||
|
|
||||||
|
char* end_pre;
|
||||||
|
long int n_pre;
|
||||||
|
char pre;
|
||||||
|
|
||||||
memset(&address, 0, sizeof(struct LineAddress));
|
memset(&address, 0, sizeof(struct LineAddress));
|
||||||
|
|
||||||
address.empty = false;
|
address.empty = false;
|
||||||
|
@ -164,8 +178,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* end_pre;
|
n_pre = strtol(index, &end_pre, 10) - 1;
|
||||||
long int n_pre = strtol(index, &end_pre, 10) - 1;
|
|
||||||
if (end_pre == index) {
|
if (end_pre == index) {
|
||||||
n_pre = -1;
|
n_pre = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -176,7 +189,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
|
||||||
index = end_pre;
|
index = end_pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
char pre = *(index++);
|
pre = *(index++);
|
||||||
switch (pre) {
|
switch (pre) {
|
||||||
case '.':
|
case '.':
|
||||||
address.type = INDEX;
|
address.type = INDEX;
|
||||||
|
@ -188,28 +201,37 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
case '^': {
|
case '^': {
|
||||||
address.type = INDEX;
|
|
||||||
char* end;
|
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) {
|
if (n < 0) {
|
||||||
error_s("input cannot be negative\n");
|
error_s("input cannot be negative\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == end) {
|
if (index == end) {
|
||||||
address.data.index.i = line_current - 1;
|
address.data.index.i = line_current - 1;
|
||||||
} else {
|
} else {
|
||||||
address.data.index.i = line_current - n;
|
address.data.index.i = line_current - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.data.index.i < 0) {
|
if (address.data.index.i < 0) {
|
||||||
error_s("line number %ld does not exist\n", address.data.index.i + 1);
|
error_s("line number %ld does not exist\n", address.data.index.i + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '+': {
|
case '+': {
|
||||||
address.type = INDEX;
|
|
||||||
char* end;
|
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) {
|
if (n < 0) {
|
||||||
error_s("input cannot be negative\n");
|
error_s("input cannot be negative\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -268,7 +290,8 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
|
||||||
|
|
||||||
static void free_data(bool all) {
|
static void free_data(bool all) {
|
||||||
if (lines != NULL) {
|
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[i]);
|
||||||
}
|
}
|
||||||
free(lines);
|
free(lines);
|
||||||
|
@ -321,11 +344,11 @@ int ed_getline(char *buf, size_t size) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int ch;
|
int ch;
|
||||||
clearerr(stdin);
|
clearerr(stdin);
|
||||||
while ((ch = getchar()) != EOF) { // Read until EOF ...
|
while ((ch = getchar()) != EOF) { /* Read until EOF ... */
|
||||||
if (i + 1 < size) {
|
if (i + 1 < size) {
|
||||||
buf[i++] = ch;
|
buf[i++] = ch;
|
||||||
}
|
}
|
||||||
if (ch == '\n') { // ... or end of line
|
if (ch == '\n') { /* ... or end of line */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +369,8 @@ static void load_file(FILE* file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_if_sure(char* prompt) {
|
static bool check_if_sure(char* prompt) {
|
||||||
|
char buf[INPUT_LEN];
|
||||||
|
|
||||||
if (!pending_writes) {
|
if (!pending_writes) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +378,6 @@ static bool check_if_sure(char* prompt) {
|
||||||
printf("%s", prompt);
|
printf("%s", prompt);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
char buf[INPUT_LEN];
|
|
||||||
if (ed_getline(buf, INPUT_LEN) == EOF) {
|
if (ed_getline(buf, INPUT_LEN) == EOF) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return false;
|
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) {
|
static void delete_lines(unsigned long a, unsigned long b) {
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
if (b < a) return;
|
if (b < a) return;
|
||||||
pending_writes = true;
|
pending_writes = true;
|
||||||
for (unsigned long i = a; i <= b; i++) {
|
|
||||||
|
for (i = a; i <= b; i++) {
|
||||||
free(lines[i]);
|
free(lines[i]);
|
||||||
}
|
}
|
||||||
if (b == line_count - 1) {
|
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) {
|
static bool handle_append(struct LineAddress* address) {
|
||||||
|
char** buf;
|
||||||
|
unsigned long cap, size;
|
||||||
|
|
||||||
if (address->type != INDEX) {
|
if (address->type != INDEX) {
|
||||||
error_s("append command requires index addressing\n");
|
error_s("append command requires index addressing\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_count == 0) {
|
if (line_count == 0) {
|
||||||
address->data.index.i = -1;
|
address->data.index.i = -1;
|
||||||
}
|
}
|
||||||
char** buf;
|
|
||||||
unsigned long cap, size;
|
|
||||||
get_input(stdin, &buf, &cap, &size);
|
get_input(stdin, &buf, &cap, &size);
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
append_lines(address->data.index.i + 1, buf, size);
|
append_lines(address->data.index.i + 1, buf, size);
|
||||||
printf("ed: appened %lu lines\n", size);
|
printf("ed: appened %lu lines\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
line_current += size;
|
line_current += size;
|
||||||
free(buf);
|
free(buf);
|
||||||
return true;
|
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);
|
error_s("line number %ld does not exist\n", address->data.index.i + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address->type == INDEX) {
|
if (address->type == INDEX) {
|
||||||
delete_lines(address->data.index.i, address->data.index.i);
|
delete_lines(address->data.index.i, address->data.index.i);
|
||||||
output("deleted line %ld\n", address->data.index.i+1);
|
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);
|
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);
|
output("deleted lines %ld-%ld\n", address->data.range.a+1, address->data.range.b+1);
|
||||||
} else if (address->type == SET) {
|
} 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]);
|
delete_lines(address->data.set.b[i], address->data.set.b[i]);
|
||||||
}
|
}
|
||||||
output("deleted %lu lines\n", address->data.set.s);
|
output("deleted %lu lines\n", address->data.set.s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_file_name(char** filename) {
|
static bool get_file_name(char** filename) {
|
||||||
size_t len = strlen(*filename);
|
size_t len = strlen(*filename);
|
||||||
|
|
||||||
if (len < 1 || (len == 1 && **filename == '\n')) {
|
if (len < 1 || (len == 1 && **filename == '\n')) {
|
||||||
if (default_filename == NULL) {
|
if (default_filename == NULL) {
|
||||||
error_s("no default filename specified\n");
|
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) {
|
static void write_file(char* filename, struct LineAddress* address, char* type) {
|
||||||
|
FILE* file;
|
||||||
|
int wrote;
|
||||||
|
|
||||||
if (line_count < 1) {
|
if (line_count < 1) {
|
||||||
error_s("cannot write empty file\n");
|
error_s("cannot write empty file\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_file_name(&filename)) return;
|
if (!get_file_name(&filename)) return;
|
||||||
FILE* file = get_file_s(filename, type);
|
file = get_file_s(filename, type);
|
||||||
if (file == NULL) return;
|
if (file == NULL) return;
|
||||||
int wrote = 0;
|
|
||||||
|
wrote = 0;
|
||||||
|
|
||||||
if (address->empty) {
|
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]);
|
fprintf(file, "%s", lines[i]);
|
||||||
wrote++;
|
wrote++;
|
||||||
}
|
}
|
||||||
|
@ -485,30 +528,38 @@ static void write_file(char* filename, struct LineAddress* address, char* type)
|
||||||
fprintf(file, "%s", lines[i]);
|
fprintf(file, "%s", lines[i]);
|
||||||
wrote++;
|
wrote++;
|
||||||
} else if (address->type == RANGE) {
|
} 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]);
|
fprintf(file, "%s", lines[i]);
|
||||||
wrote++;
|
wrote++;
|
||||||
}
|
}
|
||||||
} else if (address->type == SET) {
|
} 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]]);
|
fprintf(file, "%s", lines[address->data.set.b[i]]);
|
||||||
wrote++;
|
wrote++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pending_writes = false;
|
pending_writes = false;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
output("wrote %d lines from %s\n", wrote, filename);
|
output("wrote %d lines from %s\n", wrote, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_file(char* filename) {
|
static void read_file(char* filename) {
|
||||||
|
FILE* file;
|
||||||
|
char** buf;
|
||||||
|
long int line;
|
||||||
|
unsigned long capacity, size;
|
||||||
|
|
||||||
if (!get_file_name(&filename)) return;
|
if (!get_file_name(&filename)) return;
|
||||||
FILE* file = get_file_s(filename, "r");
|
file = get_file_s(filename, "r");
|
||||||
if (file == NULL) return;
|
if (file == NULL) return;
|
||||||
|
|
||||||
unsigned long capacty = 8;
|
capacity = 8;
|
||||||
unsigned long size = 0;
|
size = 0;
|
||||||
char** buf = malloc(capacty * sizeof(char*));
|
buf = malloc(capacity * sizeof(char*));
|
||||||
get_input(file, &buf, &capacty, &size);
|
get_input(file, &buf, &capacity, &size);
|
||||||
|
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -516,10 +567,11 @@ static void read_file(char* filename) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int line = -1;
|
line = -1;
|
||||||
if (line_count > 0) {
|
if (line_count > 0) {
|
||||||
line = line_count - 1;
|
line = line_count - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
append_lines(line, buf, size);
|
append_lines(line, buf, size);
|
||||||
free(buf);
|
free(buf);
|
||||||
output("read and appended %lu lines from %s\n", size, filename);
|
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 capacity = 8;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
char* buf = malloc(sizeof(char) * capacity);
|
char* buf = malloc(sizeof(char) * capacity);
|
||||||
|
long int left;
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int matches_found = 0;
|
int matches_found = 0;
|
||||||
while(true) {
|
while(true) {
|
||||||
if (lines[index][offset] == '\0') break;
|
|
||||||
if (matches_found >= matches && matches > 0) break;
|
|
||||||
int distance, len;
|
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) {
|
if ((distance = re_matchp(regex, &lines[index][offset], &len)) == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (distance > 0)
|
|
||||||
|
if (distance > 0) {
|
||||||
expand_string(&buf, &capacity, &size, &lines[index][offset], distance);
|
expand_string(&buf, &capacity, &size, &lines[index][offset], distance);
|
||||||
|
}
|
||||||
|
|
||||||
expand_string(&buf, &capacity, &size, sub, sub_len);
|
expand_string(&buf, &capacity, &size, sub, sub_len);
|
||||||
offset += len + distance;
|
offset += len + distance;
|
||||||
matches_found++;
|
matches_found++;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int left = strlen(lines[index] + offset);
|
left = strlen(lines[index] + offset);
|
||||||
expand_string(&buf, &capacity, &size, &lines[index][offset], left + 1);
|
expand_string(&buf, &capacity, &size, &lines[index][offset], left + 1);
|
||||||
|
|
||||||
free(lines[index]);
|
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) {
|
static void prompt(void) {
|
||||||
|
char buf[INPUT_LEN];
|
||||||
|
char* index;
|
||||||
|
char cmd;
|
||||||
|
bool whitespace, linenumbers;
|
||||||
|
struct LineAddress address;
|
||||||
|
|
||||||
printf(": ");
|
printf(": ");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
char buf[INPUT_LEN];
|
|
||||||
if (ed_getline(buf, INPUT_LEN) == EOF) { putchar('\n'); return; }
|
if (ed_getline(buf, INPUT_LEN) == EOF) { putchar('\n'); return; }
|
||||||
if (buf[0] == '\0') { putchar('\n'); return; }
|
if (buf[0] == '\0') { putchar('\n'); return; }
|
||||||
|
|
||||||
char* index = &buf[0];
|
index = &buf[0];
|
||||||
bool whitespace = skip_whitespace(&index);
|
whitespace = skip_whitespace(&index);
|
||||||
|
|
||||||
struct LineAddress address;
|
|
||||||
if (!read_address(&index, whitespace, &address)) return;
|
if (!read_address(&index, whitespace, &address)) return;
|
||||||
|
|
||||||
char cmd = *(index++);
|
cmd = *(index++);
|
||||||
|
|
||||||
if (cmd == ',') {
|
if (cmd == ',') {
|
||||||
|
struct LineAddress address2;
|
||||||
|
|
||||||
if (address.type != INDEX) {
|
if (address.type != INDEX) {
|
||||||
error_s("comma range addressing requires two index addresses\n");
|
error_s("comma range addressing requires two index addresses\n");
|
||||||
free_address(address);
|
free_address(address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct LineAddress address2;
|
|
||||||
whitespace = skip_whitespace(&index);
|
whitespace = skip_whitespace(&index);
|
||||||
|
|
||||||
if (!read_address(&index, whitespace, &address2)) {
|
if (!read_address(&index, whitespace, &address2)) {
|
||||||
free_address(address);
|
free_address(address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address2.type != INDEX) {
|
if (address2.type != INDEX) {
|
||||||
error_s("comma range addressing requires two index addresses\n");
|
error_s("comma range addressing requires two index addresses\n");
|
||||||
free_address(address);
|
free_address(address);
|
||||||
free_address(address2);
|
free_address(address2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
address.type = RANGE;
|
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;
|
address.data.range.b = address2.data.index.i;
|
||||||
|
|
||||||
cmd = *(index++);
|
cmd = *(index++);
|
||||||
|
@ -611,7 +679,8 @@ static void prompt(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool linenumbers = false;
|
linenumbers = false;
|
||||||
|
|
||||||
test:
|
test:
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case '\0':
|
case '\0':
|
||||||
|
@ -663,12 +732,14 @@ test:
|
||||||
if (linenumbers) printf("%ld\t", address.data.index.i + 1);
|
if (linenumbers) printf("%ld\t", address.data.index.i + 1);
|
||||||
printf("%s", lines[address.data.index.i]);
|
printf("%s", lines[address.data.index.i]);
|
||||||
} else if (address.type == RANGE) {
|
} 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);
|
if (linenumbers) printf("%ld\t", i + 1);
|
||||||
printf("%s", lines[i]);
|
printf("%s", lines[i]);
|
||||||
}
|
}
|
||||||
} else if (address.type == SET) {
|
} 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);
|
if (linenumbers) printf("%ld\t", address.data.set.b[i] +1);
|
||||||
printf("%s", lines[address.data.set.b[i]]);
|
printf("%s", lines[address.data.set.b[i]]);
|
||||||
}
|
}
|
||||||
|
@ -698,14 +769,17 @@ test:
|
||||||
}
|
}
|
||||||
goto test;
|
goto test;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's': {
|
||||||
|
char* replace = index;
|
||||||
|
long int matches, sub_len, matches_found;
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
skip_whitespace(&index);
|
skip_whitespace(&index);
|
||||||
if (*(index++) != '/') {
|
if (*(index++) != '/') {
|
||||||
error_s("unexpected character at start of regex\n");
|
error_s("unexpected character at start of regex\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!parse_regex_lines(&index, &address)) { return; }
|
if (!parse_regex_lines(&index, &address)) { return; }
|
||||||
char* replace = index;
|
|
||||||
while(*index != '\0' && *index != '/') index++;
|
while(*index != '\0' && *index != '/') index++;
|
||||||
if (*index != '/') {
|
if (*index != '/') {
|
||||||
error_s("/ missing after %c\n", *index);
|
error_s("/ missing after %c\n", *index);
|
||||||
|
@ -716,7 +790,6 @@ test:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*(index++) = '\0';
|
*(index++) = '\0';
|
||||||
long int matches;
|
|
||||||
if (*index == '\0' || *index == '\n') {
|
if (*index == '\0' || *index == '\n') {
|
||||||
matches = 1;
|
matches = 1;
|
||||||
} else if (*index == 'g') {
|
} else if (*index == 'g') {
|
||||||
|
@ -733,15 +806,16 @@ test:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long int sub_len = strlen(replace);
|
sub_len = strlen(replace);
|
||||||
long int matches_found = 0;
|
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);
|
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);
|
output("replaced %ld matches over %ld lines\n", matches_found, address.data.set.s);
|
||||||
pending_writes = true;
|
pending_writes = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'w': {
|
case 'w': {
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
if (*index == 'q') {
|
if (*index == 'q') {
|
||||||
|
@ -766,11 +840,17 @@ test:
|
||||||
if (!check_if_sure("Load new file for sure? ")) break;
|
if (!check_if_sure("Load new file for sure? ")) break;
|
||||||
__attribute__((fallthrough));
|
__attribute__((fallthrough));
|
||||||
case 'E': {
|
case 'E': {
|
||||||
|
char* filename;
|
||||||
|
FILE* file;
|
||||||
|
|
||||||
skip_whitespace(&index);
|
skip_whitespace(&index);
|
||||||
char* filename = index;
|
|
||||||
|
filename = index;
|
||||||
if(!get_file_name(&filename)) break;
|
if(!get_file_name(&filename)) break;
|
||||||
FILE* file = get_file_s(filename, "r");
|
|
||||||
|
file = get_file_s(filename, "r");
|
||||||
if (file == NULL) break;
|
if (file == NULL) break;
|
||||||
|
|
||||||
load_file(file);
|
load_file(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,10 +92,11 @@ static bool match_literal(char** string, char* pattern) {
|
||||||
char* match = *string;
|
char* match = *string;
|
||||||
size_t match_len = strlen(match);
|
size_t match_len = strlen(match);
|
||||||
size_t pattern_len = strlen(pattern);
|
size_t pattern_len = strlen(pattern);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (match_len < pattern_len) return false;
|
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 (
|
if (
|
||||||
(!flags.ignore_case && strncmp(match + i, pattern, pattern_len) == 0) ||
|
(!flags.ignore_case && strncmp(match + i, pattern, pattern_len) == 0) ||
|
||||||
(flags.ignore_case && strncasecmp(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) {
|
static bool match_any(char* path, void* pattern) {
|
||||||
FILE* file = get_file_s(path, "r");
|
FILE* file;
|
||||||
if (file == NULL) return false;
|
|
||||||
|
|
||||||
char* buf = NULL;
|
char* buf = NULL;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
bool matched = false;
|
bool matched = false;
|
||||||
|
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
|
file = get_file_s(path, "r");
|
||||||
|
if (file == NULL) return false;
|
||||||
|
|
||||||
while ((read = getline(&buf, &offset, file)) > 0) {
|
while ((read = getline(&buf, &offset, file)) > 0) {
|
||||||
if (buf[read-1] == '\n') buf[read-1] = '\0';
|
|
||||||
char* save = buf;
|
char* save = buf;
|
||||||
|
if (buf[read-1] == '\n') buf[read-1] = '\0';
|
||||||
if (match(&save, pattern)) {
|
if (match(&save, pattern)) {
|
||||||
matched = true;
|
matched = true;
|
||||||
break;
|
break;
|
||||||
|
@ -145,31 +147,39 @@ static bool match_any(char* path, void* pattern) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match_file(char* path, void* pattern, bool many) {
|
static bool match_file(char* path, void* pattern, bool many) {
|
||||||
FILE* file = get_file_s(path, "r");
|
FILE* file;
|
||||||
if (file == NULL) return false;
|
|
||||||
|
|
||||||
int num_matched = 0;
|
|
||||||
int line_num = 0;
|
|
||||||
char* buf = NULL;
|
char* buf = NULL;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
int num_matched = 0;
|
||||||
|
int line_num = 0;
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
|
file = get_file_s(path, "r");
|
||||||
|
if (file == NULL) return false;
|
||||||
|
|
||||||
while((read = getline(&buf, &offset, file)) > 0) {
|
while((read = getline(&buf, &offset, file)) > 0) {
|
||||||
if (buf[read-1] == '\n') buf[read-1] = '\0';
|
|
||||||
char* matched = buf;
|
char* matched = buf;
|
||||||
|
|
||||||
|
if (buf[read-1] == '\n') buf[read-1] = '\0';
|
||||||
line_num++;
|
line_num++;
|
||||||
if (!match(&matched, pattern)) {
|
|
||||||
|
if (!match(&matched, pattern)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_matched++;
|
num_matched++;
|
||||||
|
|
||||||
if (flags.only_line_count || flags.quiet) continue;
|
if (flags.only_line_count || flags.quiet) continue;
|
||||||
|
|
||||||
if ((many || flags.filename_prefix) && !flags.never_file_prefix) {
|
if ((many || flags.filename_prefix) && !flags.never_file_prefix) {
|
||||||
print_file_path(path);
|
print_file_path(path);
|
||||||
putchar(':');
|
putchar(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.line_number) {
|
if (flags.line_number) {
|
||||||
printf("%d:", line_num);
|
printf("%d:", line_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.only_matching_part) {
|
if (flags.only_matching_part) {
|
||||||
printf("%s\n", matched);
|
printf("%s\n", matched);
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,6 +225,11 @@ static bool run_match(char* path, void* pattern, bool many) {
|
||||||
|
|
||||||
COMMAND(grep) {
|
COMMAND(grep) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
char* pattern;
|
||||||
|
bool many, ok;
|
||||||
|
void* compiled;
|
||||||
|
|
||||||
flags.only_matching_part = false;
|
flags.only_matching_part = false;
|
||||||
flags.only_non_matching_names = false;
|
flags.only_non_matching_names = false;
|
||||||
flags.only_matching_names = false;
|
flags.only_matching_names = false;
|
||||||
|
@ -226,19 +241,19 @@ COMMAND(grep) {
|
||||||
flags.filename_prefix = false;
|
flags.filename_prefix = false;
|
||||||
flags.inverse = 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);
|
if (argc - start < 1) global_help(help);
|
||||||
|
|
||||||
char* pattern = argv[start++];
|
pattern = argv[start++];
|
||||||
|
|
||||||
bool many = argc - start > 0;
|
many = argc - start > 0;
|
||||||
bool ok = false;
|
ok = false;
|
||||||
|
|
||||||
void* compiled = compile(pattern);
|
compiled = compile(pattern);
|
||||||
if (run_match("-", compiled, many)) ok = true;
|
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;
|
if (run_match(argv[i], compiled, many)) ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,38 @@
|
||||||
|
|
||||||
COMMAND_EMPTY(groups) {
|
COMMAND_EMPTY(groups) {
|
||||||
|
|
||||||
uid_t uid = getuid();
|
uid_t uid;
|
||||||
|
int ngroups, i;
|
||||||
|
gid_t* groups;
|
||||||
|
struct passwd* pw;
|
||||||
|
|
||||||
struct passwd* pw = getpwuid(uid);
|
uid = getuid();
|
||||||
|
|
||||||
|
pw = getpwuid(uid);
|
||||||
if(pw == NULL){
|
if(pw == NULL){
|
||||||
error("failed to fetch groups: %s", strerror(errno));
|
error("failed to fetch groups: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngroups = 0;
|
ngroups = 0;
|
||||||
getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups);
|
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);
|
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]);
|
struct group* gr = getgrgid(groups[i]);
|
||||||
if(gr == NULL){
|
|
||||||
|
if(gr == NULL) {
|
||||||
|
free(groups);
|
||||||
error("failed to fetch groups: %s", strerror(errno));
|
error("failed to fetch groups: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s ",gr->gr_name);
|
printf("%s ",gr->gr_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
free(groups);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,22 +66,32 @@ static void head_file(char* path, bool many) {
|
||||||
static int short_arg(char c, char* next) {
|
static int short_arg(char c, char* next) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
long int bkm;
|
||||||
|
|
||||||
flags.lines = false;
|
flags.lines = false;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int bkm = get_blkm(next);
|
bkm = get_blkm(next);
|
||||||
|
|
||||||
if (bkm < 1) {
|
if (bkm < 1) {
|
||||||
error("bkm cannot be less than 1");
|
error("bkm cannot be less than 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.count = bkm;
|
flags.count = bkm;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
}
|
}
|
||||||
case 'n': {
|
case 'n': {
|
||||||
|
long int bkm;
|
||||||
|
|
||||||
flags.lines = true;
|
flags.lines = true;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int bkm = get_blkm(next);
|
bkm = get_blkm(next);
|
||||||
|
|
||||||
if (bkm < 1) {
|
if (bkm < 1) {
|
||||||
error("bkm cannot be less than 1");
|
error("bkm cannot be less than 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.count = bkm;
|
flags.count = bkm;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
}
|
}
|
||||||
|
@ -98,14 +108,17 @@ static int short_arg(char c, char* next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(head) {
|
COMMAND(head) {
|
||||||
|
|
||||||
|
int start, count, i;
|
||||||
|
|
||||||
flags.count = 10;
|
flags.count = 10;
|
||||||
flags.lines = true;
|
flags.lines = true;
|
||||||
flags.print_headers = false;
|
flags.print_headers = false;
|
||||||
flags.dont_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) {
|
if (count < 1) {
|
||||||
head_file_lines(stdin);
|
head_file_lines(stdin);
|
||||||
|
@ -117,7 +130,7 @@ COMMAND(head) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
head_file(argv[start + i], true);
|
head_file(argv[start + i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,21 +5,27 @@
|
||||||
|
|
||||||
COMMAND_EMPTY(user_id) {
|
COMMAND_EMPTY(user_id) {
|
||||||
|
|
||||||
uid_t uid = getuid();
|
uid_t uid;
|
||||||
gid_t gid = getgid();
|
gid_t gid, *groups;
|
||||||
|
int ngroups, i;
|
||||||
|
struct passwd* pw;
|
||||||
|
struct group* ugr;
|
||||||
|
|
||||||
struct passwd* pw = getpwuid(uid);
|
uid = getuid();
|
||||||
|
gid = getgid();
|
||||||
|
|
||||||
|
pw = getpwuid(uid);
|
||||||
if(pw == NULL){
|
if(pw == NULL){
|
||||||
error("failed to fetch groups: %s", strerror(errno));
|
error("failed to fetch groups: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngroups = 0;
|
ngroups = 0;
|
||||||
getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups);
|
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);
|
getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
|
||||||
|
|
||||||
struct group* ugr = getgrgid(gid);
|
ugr = getgrgid(gid);
|
||||||
printf("uid=%d(%s) gid=%d(%s) ",
|
printf("uid=%d(%s) gid=%d(%s) ",
|
||||||
uid, ugr->gr_name, gid, ugr->gr_name);
|
uid, ugr->gr_name, gid, ugr->gr_name);
|
||||||
|
|
||||||
|
@ -27,15 +33,21 @@ COMMAND_EMPTY(user_id) {
|
||||||
printf("groups=");
|
printf("groups=");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ngroups; i++){
|
for (i = 0; i < ngroups; i++){
|
||||||
struct group* gr = getgrgid(groups[i]);
|
struct group* gr = getgrgid(groups[i]);
|
||||||
if(gr == NULL){
|
if(gr == NULL) {
|
||||||
|
free(groups);
|
||||||
error("failed to fetch groups: %s", strerror(errno));
|
error("failed to fetch groups: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%d(%s)", gr->gr_gid, gr->gr_name);
|
printf("%d(%s)", gr->gr_gid, gr->gr_name);
|
||||||
|
|
||||||
if (i + 1 < ngroups) putchar(',');
|
if (i + 1 < ngroups) putchar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\b\n");
|
printf("\b\n");
|
||||||
|
|
||||||
|
free(groups);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,13 +65,18 @@ static DIR* get_directory(char* path) {
|
||||||
|
|
||||||
static bool get_file_info(const char* file_name, struct FileInfo* info) {
|
static bool get_file_info(const char* file_name, struct FileInfo* info) {
|
||||||
|
|
||||||
uid_t uid = getuid();
|
uid_t uid;
|
||||||
gid_t gid = getgid();
|
gid_t gid;
|
||||||
|
int save, ty;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
size_t file_len;
|
||||||
|
|
||||||
|
uid = getuid();
|
||||||
|
gid = getgid();
|
||||||
|
|
||||||
memset(&s, 0, sizeof(struct stat));
|
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) {
|
if (lstat(get_path_buffer(), &s) < 0) {
|
||||||
error_s("failed to read file '%s': %s\n", get_path_buffer(), strerror(errno));
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ty = (s.st_mode & S_IFMT) >> 12;
|
ty = (s.st_mode & S_IFMT) >> 12;
|
||||||
|
|
||||||
info->set_uid = false;
|
info->set_uid = false;
|
||||||
info->set_gid = 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->links = s.st_nlink;
|
||||||
info->type = ty;
|
info->type = ty;
|
||||||
|
|
||||||
size_t file_len = strlen(file_name) + 1;
|
file_len = strlen(file_name) + 1;
|
||||||
info->name = malloc(file_len);
|
info->name = malloc(file_len);
|
||||||
memcpy(info->name, file_name, 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) {
|
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) {
|
if (flags.more_info) {
|
||||||
char total[13];
|
char total[13];
|
||||||
print_file_size(info.total_size, total);
|
print_file_size(info.total_size, total);
|
||||||
printf("total %s\n", total);
|
printf("total %s\n", total);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winsize w;
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
|
||||||
if (!isatty(1)) {
|
if (!isatty(1)) {
|
||||||
|
@ -232,11 +240,10 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo
|
||||||
flags.colored = NO;
|
flags.colored = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* color;
|
column_width = info.max_name + 1;
|
||||||
const int column_width = info.max_name + 1;
|
row_count = w.ws_col / column_width;
|
||||||
const int 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];
|
struct FileInfo finfo = files[i];
|
||||||
color = get_file_color(&finfo);
|
color = get_file_color(&finfo);
|
||||||
if (flags.more_info) {
|
if (flags.more_info) {
|
||||||
|
@ -305,25 +312,28 @@ static void push_file(
|
||||||
const char* file_path
|
const char* file_path
|
||||||
) {
|
) {
|
||||||
struct FileInfo finfo;
|
struct FileInfo finfo;
|
||||||
|
int user_len, group_len, name_len, size_len, link_len;
|
||||||
|
|
||||||
if (!get_file_info(file_path, &finfo)) return;
|
if (!get_file_info(file_path, &finfo)) return;
|
||||||
|
|
||||||
if (*size == *capacity) {
|
if (*size == *capacity) {
|
||||||
*capacity *= 2;
|
*capacity *= 2;
|
||||||
*files = realloc(*files, sizeof(struct FileInfo) * *capacity);
|
*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;
|
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;
|
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;
|
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;
|
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;
|
if (link_len > info->max_link) info->max_link = link_len;
|
||||||
|
|
||||||
info->total_len += name_len + 2;
|
info->total_len += name_len + 2;
|
||||||
|
@ -335,18 +345,22 @@ static void push_file(
|
||||||
|
|
||||||
static void recurse_directory(char* dir_name) {
|
static void recurse_directory(char* dir_name) {
|
||||||
DIR* d;
|
DIR* d;
|
||||||
|
int capacity, size, save;
|
||||||
struct dirent* file;
|
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());
|
d = get_directory(get_path_buffer());
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = 8;
|
capacity = 8;
|
||||||
int size = 0;
|
size = 0;
|
||||||
struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity);
|
|
||||||
struct FileListInfo info;
|
files = malloc(sizeof(struct FileInfo) * capacity);
|
||||||
memset(&info, 0, sizeof(struct FileListInfo));
|
memset(&info, 0, sizeof(struct FileListInfo));
|
||||||
|
|
||||||
while((file = readdir(d)) != NULL) {
|
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());
|
printf("\n%s:\n", get_path_buffer());
|
||||||
else
|
} else {
|
||||||
printf("\n%s%s:%s\n", DIR_COLOR, get_path_buffer(), FILE_COLOR);
|
printf("\n%s%s:%s\n", DIR_COLOR, get_path_buffer(), FILE_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
list_files(files, size, info);
|
list_files(files, size, info);
|
||||||
|
|
||||||
|
@ -377,23 +392,29 @@ static void recurse_directory(char* dir_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_directory(char* path) {
|
static void list_directory(char* path) {
|
||||||
|
|
||||||
|
DIR* d;
|
||||||
|
int capacity, size, save;
|
||||||
|
struct FileInfo* files;
|
||||||
|
struct FileListInfo info;
|
||||||
|
struct dirent* file;
|
||||||
|
|
||||||
if (flags.recurse) {
|
if (flags.recurse) {
|
||||||
recurse_directory(path);
|
recurse_directory(path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR* d = get_directory(path);
|
d = get_directory(path);
|
||||||
if (d == NULL) return;
|
if (d == NULL) return;
|
||||||
|
|
||||||
int save = push_path_buffer(path);
|
save = push_path_buffer(path);
|
||||||
|
|
||||||
int capacity = 8;
|
capacity = 8;
|
||||||
int size = 0;
|
size = 0;
|
||||||
struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity);
|
|
||||||
struct FileListInfo info;
|
files = malloc(sizeof(struct FileInfo) * capacity);
|
||||||
memset(&info, 0, sizeof(struct FileListInfo));
|
memset(&info, 0, sizeof(struct FileListInfo));
|
||||||
|
|
||||||
struct dirent* file;
|
|
||||||
while ((file = readdir(d)) != NULL) {
|
while ((file = readdir(d)) != NULL) {
|
||||||
if (!flags.hidden && prefix(".", file->d_name)) continue;
|
if (!flags.hidden && prefix(".", file->d_name)) continue;
|
||||||
if (flags.hide_dot && is_dot_dir(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) {
|
static void list_file_args(int start, int argc, char** argv) {
|
||||||
int capacity = 8;
|
|
||||||
int size = 0;
|
int capacity, size, i;
|
||||||
struct FileInfo* files = malloc(sizeof(struct FileInfo) * capacity);
|
struct FileInfo* files;
|
||||||
struct FileListInfo info;
|
struct FileListInfo info;
|
||||||
|
|
||||||
|
capacity = 8;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
files = malloc(sizeof(struct FileInfo) * capacity);
|
||||||
memset(&info, 0, sizeof(struct FileListInfo));
|
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;
|
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);
|
if (size > 0) list_files(files, size, info);
|
||||||
|
@ -487,6 +513,9 @@ static int long_arg(char* cur, char* next) {
|
||||||
|
|
||||||
COMMAND(ls) {
|
COMMAND(ls) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
bool titled;
|
||||||
|
|
||||||
flags.hidden = false;
|
flags.hidden = false;
|
||||||
flags.more_info = false;
|
flags.more_info = false;
|
||||||
flags.hide_dot = false;
|
flags.hide_dot = false;
|
||||||
|
@ -494,7 +523,7 @@ COMMAND(ls) {
|
||||||
flags.recurse = false;
|
flags.recurse = false;
|
||||||
flags.colored = NO;
|
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) {
|
if (argc - start == 0) {
|
||||||
list_directory(".");
|
list_directory(".");
|
||||||
|
@ -503,15 +532,19 @@ COMMAND(ls) {
|
||||||
|
|
||||||
list_file_args(start, argc, argv);
|
list_file_args(start, argc, argv);
|
||||||
|
|
||||||
bool titled = argc - start > 1;
|
titled = argc - start > 1;
|
||||||
for (int i = start; i < argc; i++) {
|
for (i = start; i < argc; i++) {
|
||||||
|
|
||||||
if (!is_dir(argv[i])) continue;
|
if (!is_dir(argv[i])) continue;
|
||||||
|
|
||||||
if (titled && !flags.recurse) {
|
if (titled && !flags.recurse) {
|
||||||
if (flags.colored != NO)
|
if (flags.colored != NO) {
|
||||||
printf("\n%s%s:%s\n", DIR_COLOR, argv[i], FILE_COLOR);
|
printf("\n%s%s:%s\n", DIR_COLOR, argv[i], FILE_COLOR);
|
||||||
else
|
} else {
|
||||||
printf("\n%s:\n", argv[i]);
|
printf("\n%s:\n", argv[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_directory(argv[i]);
|
list_directory(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ static void help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mkdir_parents(char* path) {
|
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;
|
if (path[i] != '/') continue;
|
||||||
path[i] = '\0';
|
path[i] = '\0';
|
||||||
if (mkdir(path, flags.mode) < 0 && errno != EEXIST) {
|
if (mkdir(path, flags.mode) < 0 && errno != EEXIST) {
|
||||||
|
@ -41,13 +42,17 @@ static bool mkdir_parents(char* path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(makedir) {
|
COMMAND(makedir) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
|
||||||
if (argc < 1) global_help(help);
|
if (argc < 1) global_help(help);
|
||||||
|
|
||||||
flags.make_parent = false;
|
flags.make_parent = false;
|
||||||
flags.mode = 0755;
|
flags.mode = 0755;
|
||||||
int start = parse_args(argc, argv, help, short_arg, NULL);
|
|
||||||
|
|
||||||
for (int i = start; i < argc; i++) {
|
start = parse_args(argc, argv, help, short_arg, NULL);
|
||||||
|
|
||||||
|
for (i = start; i < argc; i++) {
|
||||||
if (flags.make_parent && !mkdir_parents(argv[i])) {
|
if (flags.make_parent && !mkdir_parents(argv[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,18 +38,24 @@ static int short_arg(char c, char* next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mv_dir(bool exists) {
|
static void mv_dir(bool exists) {
|
||||||
|
|
||||||
|
char c;
|
||||||
|
|
||||||
if (exists && flags.dont_overwrite) {
|
if (exists && flags.dont_overwrite) {
|
||||||
if (flags.verbose) output("skipping '%s'; overwrise is false", get_path_buffer_2());
|
if (flags.verbose) output("skipping '%s'; overwrise is false", get_path_buffer_2());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists && flags.prompt) {
|
if (exists && flags.prompt) {
|
||||||
fprintf(stderr, "overwrite '%s'? ", get_path_buffer_2());
|
fprintf(stderr, "overwrite '%s'? ", get_path_buffer_2());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
char c = getchar();
|
|
||||||
|
c = getchar();
|
||||||
if (c != 'y' && c != 'Y') {
|
if (c != 'y' && c != 'Y') {
|
||||||
if (flags.verbose) output("skipping...");
|
if (flags.verbose) output("skipping...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rename(get_path_buffer(), get_path_buffer_2()) < 0) {
|
if (rename(get_path_buffer(), get_path_buffer_2()) < 0) {
|
||||||
|
@ -61,12 +67,15 @@ static void mv_dir(bool exists) {
|
||||||
|
|
||||||
COMMAND(mv) {
|
COMMAND(mv) {
|
||||||
|
|
||||||
|
int start, dest, i;
|
||||||
|
struct stat s;
|
||||||
|
|
||||||
flags.refuse_if_dir = false;
|
flags.refuse_if_dir = false;
|
||||||
flags.dont_overwrite = false;
|
flags.dont_overwrite = false;
|
||||||
flags.prompt = false;
|
flags.prompt = false;
|
||||||
flags.verbose = 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) {
|
if (argc - start < 2) {
|
||||||
global_help(help);
|
global_help(help);
|
||||||
|
@ -74,8 +83,7 @@ COMMAND(mv) {
|
||||||
|
|
||||||
push_path_buffer_2(argv[argc-1]);
|
push_path_buffer_2(argv[argc-1]);
|
||||||
|
|
||||||
bool dest = true;
|
dest = true;
|
||||||
struct stat s;
|
|
||||||
if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) {
|
if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) {
|
||||||
dest = false;
|
dest = false;
|
||||||
error("cannot stat '%s': %s", get_path_buffer_2(), strerror(errno));
|
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());
|
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]);
|
int save = push_path_buffer(argv[i]);
|
||||||
bool exists = lstat(get_path_buffer(), &s) >= 0;
|
bool exists = lstat(get_path_buffer(), &s) >= 0;
|
||||||
mv_dir(exists);
|
mv_dir(exists);
|
||||||
|
|
|
@ -40,7 +40,7 @@ static void handle_percent(char n, const char* arg) {
|
||||||
}
|
}
|
||||||
case 'f': {
|
case 'f': {
|
||||||
double d = cast_double(arg);
|
double d = cast_double(arg);
|
||||||
printf("%lf", d);
|
printf("%f", d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
@ -95,6 +95,11 @@ static void help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(print) {
|
COMMAND(print) {
|
||||||
|
|
||||||
|
size_t index;
|
||||||
|
int arg_index;
|
||||||
|
char n, *arg;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
global_help(help);
|
global_help(help);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -102,8 +107,8 @@ COMMAND(print) {
|
||||||
|
|
||||||
parse_help(argc, argv, help);
|
parse_help(argc, argv, help);
|
||||||
|
|
||||||
size_t index = 0;
|
index = 0;
|
||||||
int arg_index = 0;
|
arg_index = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char c = argv[0][index];
|
char c = argv[0][index];
|
||||||
|
@ -115,10 +120,10 @@ COMMAND(print) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char n = argv[0][index];
|
n = argv[0][index];
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
char* arg = NULL;
|
arg = NULL;
|
||||||
if (arg_index < argc) {
|
if (arg_index < argc) {
|
||||||
arg = argv[arg_index + 1];
|
arg = argv[arg_index + 1];
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,16 +40,18 @@ static int short_arg(char c, char* next) {
|
||||||
return ARG_UNUSED;
|
return ARG_UNUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rm_file(char* path);
|
static void rm_file (char* path);
|
||||||
|
|
||||||
static bool rm_dir() {
|
static bool rm_dir (void) {
|
||||||
DIR* d = opendir(get_path_buffer());
|
DIR* d;
|
||||||
|
struct dirent* file;
|
||||||
|
|
||||||
|
d = opendir(get_path_buffer());
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno));
|
error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent* file;
|
|
||||||
while ((file = readdir(d)) != NULL) {
|
while ((file = readdir(d)) != NULL) {
|
||||||
if (is_dot_dir(file->d_name)) continue;
|
if (is_dot_dir(file->d_name)) continue;
|
||||||
rm_file(file->d_name);
|
rm_file(file->d_name);
|
||||||
|
@ -82,9 +84,12 @@ static void rm_file(char* path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.prompt) {
|
if (flags.prompt) {
|
||||||
|
char c;
|
||||||
|
|
||||||
fprintf(stderr, "delete '%s'? ", get_path_buffer());
|
fprintf(stderr, "delete '%s'? ", get_path_buffer());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
char c = getchar();
|
|
||||||
|
c = getchar();
|
||||||
if (c != 'y' && c != 'Y') {
|
if (c != 'y' && c != 'Y') {
|
||||||
fprintf(stderr, "Skipping...\n");
|
fprintf(stderr, "Skipping...\n");
|
||||||
pop_path_buffer(save);
|
pop_path_buffer(save);
|
||||||
|
@ -102,6 +107,9 @@ static void rm_file(char* path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(rm) {
|
COMMAND(rm) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
global_help(help);
|
global_help(help);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -112,7 +120,7 @@ COMMAND(rm) {
|
||||||
flags.verbose = false;
|
flags.verbose = false;
|
||||||
flags.recurse = 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
|
#ifdef FRENCH
|
||||||
if (streql(argv[0], "-fr")) {
|
if (streql(argv[0], "-fr")) {
|
||||||
|
@ -120,7 +128,7 @@ COMMAND(rm) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i = start; i < argc; i++) {
|
for (i = start; i < argc; i++) {
|
||||||
rm_file(argv[i]);
|
rm_file(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,29 +10,36 @@ static void help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_range(FILE* file, int start, int end) {
|
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);
|
fseek(file, start, SEEK_SET);
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
putchar(getc(file));
|
putchar(getc(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char stdin_path[PATH_MAX];
|
static char stdin_path[PATH_MAX];
|
||||||
|
|
||||||
static FILE* read_stdin() {
|
static FILE* read_stdin (void) {
|
||||||
static bool read;
|
static bool read;
|
||||||
static FILE* file;
|
static FILE* file;
|
||||||
|
int r;
|
||||||
|
char c;
|
||||||
|
|
||||||
if (read) goto finished;
|
if (read) goto finished;
|
||||||
read = true;
|
read = true;
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
int r = rand() % 1000000;
|
|
||||||
|
r = rand() % 1000000;
|
||||||
|
|
||||||
sprintf(stdin_path, "/tmp/%d.tac", r);
|
sprintf(stdin_path, "/tmp/%d.tac", r);
|
||||||
file = get_file(stdin_path, "w");
|
file = get_file(stdin_path, "w");
|
||||||
|
|
||||||
char c;
|
|
||||||
while((c = getchar()) != EOF) putc(c, file);
|
while((c = getchar()) != EOF) putc(c, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
@ -43,15 +50,15 @@ finished:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_file(FILE* file, struct Stack* stack) {
|
static void parse_file(FILE* file, struct Stack* stack) {
|
||||||
char buf[1024];
|
char buf[1024], c;
|
||||||
int read;
|
int read, i;
|
||||||
int total = 1;
|
int total = 1;
|
||||||
|
|
||||||
stack_push_int(stack, 0);
|
stack_push_int(stack, 0);
|
||||||
rewind(file);
|
rewind(file);
|
||||||
while ((read = fread(buf, 1, 1024, file)) > 0) {
|
while ((read = fread(buf, 1, 1024, file)) > 0) {
|
||||||
for (int i = 0; i < read; i++) {
|
for (i = 0; i < read; i++) {
|
||||||
char c = buf[i];
|
c = buf[i];
|
||||||
if (c != '\n') continue;
|
if (c != '\n') continue;
|
||||||
stack_push_int(stack, total + i);
|
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) {
|
static void tac_file(FILE* file) {
|
||||||
struct Stack stack;
|
struct Stack stack;
|
||||||
stack_init(&stack, 80);
|
|
||||||
|
|
||||||
parse_file(file, &stack);
|
|
||||||
|
|
||||||
rewind(file);
|
|
||||||
int last, current;
|
int last, current;
|
||||||
|
|
||||||
|
stack_init(&stack, 80);
|
||||||
|
parse_file(file, &stack);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
if (!stack_pop_int(&stack, &last)) goto cleanup;
|
if (!stack_pop_int(&stack, &last)) goto cleanup;
|
||||||
|
|
||||||
while(stack_pop_int(&stack, ¤t)) {
|
while(stack_pop_int(&stack, ¤t)) {
|
||||||
print_range(file, current, last);
|
print_range(file, current, last);
|
||||||
last = current;
|
last = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
stack_free(&stack);
|
stack_free(&stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(tac) {
|
COMMAND(tac) {
|
||||||
|
|
||||||
|
FILE* in;
|
||||||
|
int i;
|
||||||
|
|
||||||
parse_help(argc, argv, help);
|
parse_help(argc, argv, help);
|
||||||
|
|
||||||
FILE* in = read_stdin();
|
in = read_stdin();
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
tac_file(in);
|
tac_file(in);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
FILE* file = get_file(argv[i], "r");
|
FILE* file = get_file(argv[i], "r");
|
||||||
if (file == stdin) {
|
if (file == stdin) {
|
||||||
tac_file(in);
|
tac_file(in);
|
||||||
|
|
|
@ -10,18 +10,27 @@ static struct {
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) {
|
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);
|
memset(ring, 0, sizeof(char*) * count);
|
||||||
|
|
||||||
int ring_len[count];
|
ring_len = malloc(sizeof(int) * count);
|
||||||
|
|
||||||
int index = 0;
|
index = 0;
|
||||||
unsigned int size = 0;
|
size = 0;
|
||||||
|
|
||||||
int read;
|
|
||||||
fseek(file, skip, SEEK_SET);
|
fseek(file, skip, SEEK_SET);
|
||||||
size_t len = skip;
|
|
||||||
char* line = NULL;
|
len = skip;
|
||||||
|
line = NULL;
|
||||||
|
|
||||||
while ((read = getline(&line, &len, file)) != -1) {
|
while ((read = getline(&line, &len, file)) != -1) {
|
||||||
|
|
||||||
if (ring[index] != NULL) free(ring[index]);
|
if (ring[index] != NULL) free(ring[index]);
|
||||||
|
@ -38,7 +47,7 @@ static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) {
|
||||||
index += count - size;
|
index += count - size;
|
||||||
index %= count;
|
index %= count;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
fwrite(ring[index], ring_len[index], 1, stdout);
|
fwrite(ring[index], ring_len[index], 1, stdout);
|
||||||
free(ring[index]);
|
free(ring[index]);
|
||||||
index += 1;
|
index += 1;
|
||||||
|
@ -47,20 +56,28 @@ static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) {
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
free(ring);
|
||||||
|
free(ring_len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t tail_file_chars(FILE* file, unsigned int count, size_t skip) {
|
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);
|
memset(ring, 0, count);
|
||||||
|
|
||||||
int index = 0;
|
index = 0;
|
||||||
unsigned int size = 0;
|
size = 0;
|
||||||
|
|
||||||
fseek(file, skip, SEEK_SET);
|
fseek(file, skip, SEEK_SET);
|
||||||
int read = skip;
|
read = skip;
|
||||||
int c;
|
|
||||||
while((c = getc(file)) != EOF) {
|
while((c = getc(file)) != EOF) {
|
||||||
ring[index] = c;
|
ring[index] = c;
|
||||||
index++;
|
index++;
|
||||||
|
@ -72,7 +89,7 @@ static size_t tail_file_chars(FILE* file, unsigned int count, size_t skip) {
|
||||||
index += count - size;
|
index += count - size;
|
||||||
index %= count;
|
index %= count;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
putchar(ring[index]);
|
putchar(ring[index]);
|
||||||
index += 1;
|
index += 1;
|
||||||
index %= count;
|
index %= count;
|
||||||
|
@ -108,10 +125,14 @@ static void print_header(char* path, bool many) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tail_file(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);
|
print_header(path, many);
|
||||||
|
|
||||||
size_t skip = 0;
|
skip = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (flags.lines) {
|
if (flags.lines) {
|
||||||
skip = tail_file_lines(file, flags.count, skip);
|
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) {
|
static int short_arg(char c, char* next) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
long int bkm;
|
||||||
|
|
||||||
flags.lines = false;
|
flags.lines = false;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int bkm = get_blkm(next);
|
bkm = get_blkm(next);
|
||||||
|
|
||||||
if (bkm < 1) {
|
if (bkm < 1) {
|
||||||
error("bkm cannot be less than 1");
|
error("bkm cannot be less than 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.count = bkm;
|
flags.count = bkm;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
}
|
}
|
||||||
case 'n': {
|
case 'n': {
|
||||||
|
long int bkm;
|
||||||
|
|
||||||
flags.lines = true;
|
flags.lines = true;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int bkm = get_blkm(next);
|
bkm = get_blkm(next);
|
||||||
|
|
||||||
if (bkm < 1) {
|
if (bkm < 1) {
|
||||||
error("bkm cannot be less than 1");
|
error("bkm cannot be less than 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.count = bkm;
|
flags.count = bkm;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
}
|
}
|
||||||
|
@ -156,11 +187,15 @@ static int short_arg(char c, char* next) {
|
||||||
flags.print_as_grow = true;
|
flags.print_as_grow = true;
|
||||||
break;
|
break;
|
||||||
case 's': {
|
case 's': {
|
||||||
|
long int sec;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int sec = get_number(next);
|
sec = get_number(next);
|
||||||
|
|
||||||
if (sec < 1) {
|
if (sec < 1) {
|
||||||
error("wait seconds cannot be less than 1");
|
error("wait seconds cannot be less than 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.grow_wait = sec;
|
flags.grow_wait = sec;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +207,8 @@ static int short_arg(char c, char* next) {
|
||||||
|
|
||||||
COMMAND(tail) {
|
COMMAND(tail) {
|
||||||
|
|
||||||
|
int start, count, i;
|
||||||
|
|
||||||
flags.count = 10;
|
flags.count = 10;
|
||||||
flags.dont_print_headers = false;
|
flags.dont_print_headers = false;
|
||||||
flags.print_headers = false;
|
flags.print_headers = false;
|
||||||
|
@ -179,9 +216,9 @@ COMMAND(tail) {
|
||||||
flags.print_as_grow = false;
|
flags.print_as_grow = false;
|
||||||
flags.grow_wait = 10;
|
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) {
|
if (count < 1) {
|
||||||
tail_file_lines(stdin, 10, 0);
|
tail_file_lines(stdin, 10, 0);
|
||||||
|
@ -193,7 +230,7 @@ COMMAND(tail) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
tail_file(argv[start + i], true);
|
tail_file(argv[start + i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,16 +17,20 @@ static void help(void) {
|
||||||
|
|
||||||
static void handle(int dummy){UNUSED(dummy);}
|
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;
|
char c;
|
||||||
|
int i;
|
||||||
|
|
||||||
while((c = getchar()) != EOF) {
|
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]);
|
fwrite(&c, 1, 1, files[i]);
|
||||||
fflush(files[i]);
|
fflush(files[i]);
|
||||||
}
|
}
|
||||||
putchar(c);
|
putchar(c);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < file_count; i++) {
|
|
||||||
|
for (i = 0; i < file_count; i++) {
|
||||||
fclose(files[i]);
|
fclose(files[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,10 +52,13 @@ static int short_arg(char c, char* next) {
|
||||||
|
|
||||||
COMMAND(tee) {
|
COMMAND(tee) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
FILE** files;
|
||||||
|
|
||||||
flags.append = false;
|
flags.append = false;
|
||||||
flags.handle_sigint = 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) {
|
if (flags.handle_sigint) {
|
||||||
signal(SIGINT, handle);
|
signal(SIGINT, handle);
|
||||||
|
@ -62,8 +69,9 @@ COMMAND(tee) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* files[argc - start];
|
files = malloc(sizeof(FILE*) * (argc - start));
|
||||||
for (int i = start; i < argc; i++) {
|
|
||||||
|
for (i = start; i < argc; i++) {
|
||||||
FILE* file = get_file(argv[i], flags.append ? "a" : "w");
|
FILE* file = get_file(argv[i], flags.append ? "a" : "w");
|
||||||
files[i - start] = file;
|
files[i - start] = file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,8 @@ static void run_wc(FILE* file) {
|
||||||
int read;
|
int read;
|
||||||
char buf[BS];
|
char buf[BS];
|
||||||
while ((read = fread(buf, 1, 1024, file)) > 0) {
|
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];
|
char ch = buf[i];
|
||||||
b++;
|
b++;
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
|
@ -118,6 +119,9 @@ static int short_arg(char c, char* next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(wc) {
|
COMMAND(wc) {
|
||||||
|
|
||||||
|
int start, i;
|
||||||
|
|
||||||
flags.newlines = false;
|
flags.newlines = false;
|
||||||
flags.words = false;
|
flags.words = false;
|
||||||
flags.characters = false;
|
flags.characters = false;
|
||||||
|
@ -126,7 +130,7 @@ COMMAND(wc) {
|
||||||
flags.has_flags = false;
|
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) {
|
if (!flags.has_flags) {
|
||||||
flags.newlines = true;
|
flags.newlines = true;
|
||||||
|
@ -140,7 +144,7 @@ COMMAND(wc) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = start; i < argc; i++) {
|
for (i = start; i < argc; i++) {
|
||||||
FILE* file = get_file(argv[i], "r");
|
FILE* file = get_file(argv[i], "r");
|
||||||
run_wc(file);
|
run_wc(file);
|
||||||
printf("\t%s\n", argv[i]);
|
printf("\t%s\n", argv[i]);
|
||||||
|
|
|
@ -9,10 +9,15 @@ static void help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(whoami) {
|
COMMAND(whoami) {
|
||||||
|
|
||||||
|
uid_t usr;
|
||||||
|
struct passwd* passwd;
|
||||||
|
|
||||||
parse_help(argc, argv, help);
|
parse_help(argc, argv, help);
|
||||||
|
|
||||||
uid_t usr = getuid();
|
usr = getuid();
|
||||||
struct passwd* passwd = getpwuid(usr);
|
passwd = getpwuid(usr);
|
||||||
|
|
||||||
if (passwd == NULL) {
|
if (passwd == NULL) {
|
||||||
printf("\x1b[1;91myou do not exist.\n");
|
printf("\x1b[1;91myou do not exist.\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,6 +24,7 @@ static void help(void) {
|
||||||
|
|
||||||
static int short_arg(char c, char* next) {
|
static int short_arg(char c, char* next) {
|
||||||
UNUSED(next);
|
UNUSED(next);
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '0':
|
case '0':
|
||||||
flags.null_seperated = true;
|
flags.null_seperated = true;
|
||||||
|
@ -41,14 +42,19 @@ static int short_arg(char c, char* next) {
|
||||||
case 'p':
|
case 'p':
|
||||||
flags.prompt_command = true;
|
flags.prompt_command = true;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n': {
|
||||||
|
long int n;
|
||||||
|
|
||||||
check_arg(next);
|
check_arg(next);
|
||||||
long int n = get_number(next);
|
n = get_number(next);
|
||||||
|
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
error("max arg count must be at least 1");
|
error("max arg count must be at least 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.max_args = n;
|
flags.max_args = n;
|
||||||
return ARG_USED;
|
return ARG_USED;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return ARG_INVALID;
|
return ARG_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -57,13 +63,16 @@ static int short_arg(char c, char* next) {
|
||||||
|
|
||||||
char* read_next(FILE* file, int arg_count) {
|
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;
|
if (flags.max_args != -1 && arg_count == flags.max_args) return NULL;
|
||||||
|
|
||||||
int size = 0;
|
size = 0;
|
||||||
int capacity = 8;
|
capacity = 8;
|
||||||
char* buf = malloc(sizeof(char) * capacity);
|
buf = malloc(sizeof(char) * capacity);
|
||||||
|
|
||||||
char c;
|
|
||||||
while(c = getc(file), true) {
|
while(c = getc(file), true) {
|
||||||
if (c == EOF && size == 0) {
|
if (c == EOF && size == 0) {
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -99,6 +108,12 @@ void read_args(FILE* file, char*** args, int* size, int* capacity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(xargs) {
|
COMMAND(xargs) {
|
||||||
|
|
||||||
|
int start, arg_start, arg_on_stack_count;
|
||||||
|
int size, capacity, i;
|
||||||
|
char* command;
|
||||||
|
char** args;
|
||||||
|
|
||||||
flags.null_seperated = false;
|
flags.null_seperated = false;
|
||||||
flags.ignore_empty = false;
|
flags.ignore_empty = false;
|
||||||
flags.print_command = false;
|
flags.print_command = false;
|
||||||
|
@ -106,17 +121,15 @@ COMMAND(xargs) {
|
||||||
flags.max_args = -1;
|
flags.max_args = -1;
|
||||||
flags.file = stdin;
|
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) {
|
if (start >= argc) {
|
||||||
command = "echo";
|
command = "echo";
|
||||||
} else {
|
} else {
|
||||||
command = argv[start];
|
command = argv[start];
|
||||||
}
|
}
|
||||||
|
|
||||||
int arg_start = start + 1;
|
arg_start = start + 1;
|
||||||
int arg_on_stack_count;
|
|
||||||
|
|
||||||
if (arg_start >= argc) {
|
if (arg_start >= argc) {
|
||||||
arg_on_stack_count = 0;
|
arg_on_stack_count = 0;
|
||||||
|
@ -125,9 +138,10 @@ COMMAND(xargs) {
|
||||||
arg_on_stack_count = argc - arg_start;
|
arg_on_stack_count = argc - arg_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = arg_on_stack_count + 1;
|
size = arg_on_stack_count + 1;
|
||||||
int capacity = size + 8;
|
capacity = size + 8;
|
||||||
char** args = malloc(sizeof(char*) * capacity);
|
|
||||||
|
args = malloc(sizeof(char*) * capacity);
|
||||||
args[0] = command;
|
args[0] = command;
|
||||||
memcpy(&args[1], &argv[arg_start], arg_on_stack_count * sizeof(char*));
|
memcpy(&args[1], &argv[arg_start], arg_on_stack_count * sizeof(char*));
|
||||||
read_args(flags.file, &args, &size, &capacity);
|
read_args(flags.file, &args, &size, &capacity);
|
||||||
|
@ -135,18 +149,23 @@ COMMAND(xargs) {
|
||||||
if (flags.ignore_empty && size < 2) goto cleanup;
|
if (flags.ignore_empty && size < 2) goto cleanup;
|
||||||
|
|
||||||
if (flags.prompt_command || flags.print_command) {
|
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, "%s ", args[i]);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\b\n");
|
fprintf(stderr, "\b\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.prompt_command) {
|
if (flags.prompt_command) {
|
||||||
|
FILE* in;
|
||||||
|
char c;
|
||||||
|
|
||||||
fprintf(stderr, "Run command? ");
|
fprintf(stderr, "Run command? ");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
FILE* in = get_tty_stream("r");
|
|
||||||
char c = getc(in);
|
in = get_tty_stream("r");
|
||||||
|
c = getc(in);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
if (c != 'y' && c != 'Y') {
|
if (c != 'y' && c != 'Y') {
|
||||||
fprintf(stderr, "Skipping...\n");
|
fprintf(stderr, "Skipping...\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -159,7 +178,7 @@ COMMAND(xargs) {
|
||||||
|
|
||||||
cleanup:
|
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]);
|
free(args[i]);
|
||||||
}
|
}
|
||||||
fclose(flags.file);
|
fclose(flags.file);
|
||||||
|
|
|
@ -6,15 +6,16 @@ static void help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND(yes) {
|
COMMAND(yes) {
|
||||||
|
const char* repeat;
|
||||||
|
int i;
|
||||||
|
|
||||||
parse_help(argc, argv, help);
|
parse_help(argc, argv, help);
|
||||||
|
|
||||||
const char* repeat;
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
repeat = "y";
|
repeat = "y";
|
||||||
} else {
|
} else {
|
||||||
repeat = argv[0];
|
repeat = argv[0];
|
||||||
for (int i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
*(argv[i]-1) = ' ';
|
*(argv[i]-1) = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,15 @@
|
||||||
char* cmd;
|
char* cmd;
|
||||||
|
|
||||||
int main (ARGUMENTS) {
|
int main (ARGUMENTS) {
|
||||||
|
#ifdef CHECK_LINK
|
||||||
|
struct stat buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHECK_LINK
|
#ifdef CHECK_LINK
|
||||||
struct stat buf;
|
|
||||||
lstat(argv[0], &buf);
|
lstat(argv[0], &buf);
|
||||||
|
|
||||||
if (!S_ISLNK(buf.st_mode)) {
|
if (!S_ISLNK(buf.st_mode)) {
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */
|
#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
|
typedef struct regex_t
|
||||||
{
|
{
|
||||||
|
@ -199,7 +199,7 @@ re_t re_compile(const char* pattern)
|
||||||
{
|
{
|
||||||
if (ccl_bufidx >= MAX_CHAR_CLASS_LEN - 1)
|
if (ccl_bufidx >= MAX_CHAR_CLASS_LEN - 1)
|
||||||
{
|
{
|
||||||
//fputs("exceeded internal buffer!\n", stderr);
|
/* fputs("exceeded internal buffer!\n", stderr); */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (pattern[i+1] == 0) /* incomplete pattern, missing non-zero char after '\\' */
|
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)
|
else if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
|
||||||
{
|
{
|
||||||
//fputs("exceeded internal buffer!\n", stderr);
|
/* fputs("exceeded internal buffer!\n", stderr); */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ccl_buf[ccl_bufidx++] = pattern[i];
|
ccl_buf[ccl_bufidx++] = pattern[i];
|
||||||
|
@ -218,7 +218,7 @@ re_t re_compile(const char* pattern)
|
||||||
if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
|
if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
|
||||||
{
|
{
|
||||||
/* Catches cases such as [00000000000000000000000000000000000000][ */
|
/* Catches cases such as [00000000000000000000000000000000000000][ */
|
||||||
//fputs("exceeded internal buffer!\n", stderr);
|
/* fputs("exceeded internal buffer!\n", stderr); */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Null-terminate string end */
|
/* Null-terminate string end */
|
||||||
|
|
|
@ -43,27 +43,33 @@ void output(const char *format, ...) {
|
||||||
|
|
||||||
FILE* get_file_s(const char* path, const char* type) {
|
FILE* get_file_s(const char* path, const char* type) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
FILE* file;
|
||||||
|
|
||||||
if (streql("-", path) && type[0] == 'r') {
|
if (streql("-", path) && type[0] == 'r') {
|
||||||
clearerr(stdin);
|
clearerr(stdin);
|
||||||
fflush(stdin);
|
fflush(stdin);
|
||||||
return stdin;
|
return stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lstat(path, &s) < 0) {
|
if (lstat(path, &s) < 0) {
|
||||||
if (type[0] != 'r') goto read;
|
if (type[0] != 'r') goto read;
|
||||||
error_s("failed to read %s: %s", path, strerror(errno));
|
error_s("failed to read %s: %s", path, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR(s.st_mode)) {
|
if (S_ISDIR(s.st_mode)) {
|
||||||
error_s("%s is a directory", path);
|
error_s("%s is a directory", path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* file;
|
|
||||||
read:
|
read:
|
||||||
|
|
||||||
file = fopen(path, type);
|
file = fopen(path, type);
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno));
|
error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +108,8 @@ long int get_blkm(const char* text) {
|
||||||
default:
|
default:
|
||||||
error("invalid bkm type %c", *end);
|
error("invalid bkm type %c", *end);
|
||||||
}
|
}
|
||||||
// shouldnt get here anyways
|
|
||||||
|
/* shouldnt get here anyways */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +125,10 @@ mode_t get_mode(const char* next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streql(const char* a, const char* b) {
|
bool streql(const char* a, const char* b) {
|
||||||
if (*a != *b) return false;
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
|
if (*a != *b) return false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (*(a+n) != *(b+n)) return false;
|
if (*(a+n) != *(b+n)) return false;
|
||||||
if (*(a+n) == '\0') return true;
|
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'};
|
static char fs_types[5] = {'K','M','G','T','P'};
|
||||||
void print_file_size(size_t bytes, char buf[5]) {
|
void print_file_size(size_t bytes, char buf[5]) {
|
||||||
int index = 0;
|
int index, n;
|
||||||
float next = bytes;
|
float next;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
next = bytes;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (next < 1000) {
|
if (next < 1000) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 5) {
|
if (index == 5) {
|
||||||
printf("999P");
|
printf("999P");
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
next /= 1024;
|
next /= 1024;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = snprintf(buf, 4, "%u", (int)(next+.5));
|
n = snprintf(buf, 4, "%u", (int)(next+.5));
|
||||||
|
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
buf[n] = (fs_types[index - 1]);
|
buf[n] = (fs_types[index - 1]);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[n] = '\0';
|
buf[n] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,8 +176,10 @@ static char* months[12] =
|
||||||
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
void print_date_time(time_t mills, char buf[13]) {
|
void print_date_time(time_t mills, char buf[13]) {
|
||||||
struct tm* info;
|
struct tm* info;
|
||||||
|
int n;
|
||||||
|
|
||||||
info = localtime(&mills);
|
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) {
|
if (info->tm_mday < 10) {
|
||||||
buf[n] = ' ';
|
buf[n] = ' ';
|
||||||
|
@ -203,35 +222,45 @@ void global_help(void (*help)(void)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_help(int argc, char** argv, void (*help)(void)) {
|
void parse_help(int argc, char** argv, void (*help)(void)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
if (argc < 1) return;
|
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 (!prefix("-", argv[i]) || streql("-", argv[i])) break;
|
||||||
if (help != NULL && streql("--help", argv[i])) global_help(help);
|
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 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;
|
if (argc < 1) return 0;
|
||||||
|
|
||||||
int start = 0;
|
start = 0;
|
||||||
for (int i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
|
|
||||||
if (!prefix("-", argv[i]) || streql("-", argv[i])) break;
|
if (!prefix("-", argv[i]) || streql("-", argv[i])) break;
|
||||||
if (help != NULL && streql("--help", argv[i])) global_help(help);
|
if (help != NULL && streql("--help", argv[i])) global_help(help);
|
||||||
|
|
||||||
char* next_arg;
|
|
||||||
if (i + 1 == argc) {
|
if (i + 1 == argc) {
|
||||||
next_arg = NULL;
|
next_arg = NULL;
|
||||||
} else {
|
} else {
|
||||||
next_arg = argv[i+1];
|
next_arg = argv[i+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int current = i;
|
current = i;
|
||||||
|
|
||||||
if (prefix("--", argv[i])) {
|
if (prefix("--", argv[i])) {
|
||||||
|
int r;
|
||||||
|
|
||||||
if (long_arg == NULL) {
|
if (long_arg == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
int r = long_arg(argv[current], next_arg);
|
|
||||||
|
r = long_arg(argv[current], next_arg);
|
||||||
|
|
||||||
if (r == ARG_USED) {
|
if (r == ARG_USED) {
|
||||||
i++;
|
i++;
|
||||||
start++;
|
start++;
|
||||||
|
@ -239,13 +268,20 @@ int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char,
|
||||||
goto exit;
|
goto exit;
|
||||||
} else if (r == ARG_INVALID) {
|
} else if (r == ARG_INVALID) {
|
||||||
error("invalid argument %s", argv[current]);
|
error("invalid argument %s", argv[current]);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
size_t j;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (short_arg == NULL) {
|
if (short_arg == NULL) {
|
||||||
goto exit;
|
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) {
|
if (r == ARG_USED) {
|
||||||
i++;
|
i++;
|
||||||
start++;
|
start++;
|
||||||
|
@ -259,11 +295,13 @@ int parse_args(int argc, char** argv, void (*help)(void), int (*short_arg)(char,
|
||||||
|
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_tty() {
|
int get_tty (void) {
|
||||||
int fd = open(_PATH_TTY, O_RDONLY);
|
int fd = open(_PATH_TTY, O_RDONLY);
|
||||||
if (fd < 0) error("failed to get tty: %s", strerror(errno));
|
if (fd < 0) error("failed to get tty: %s", strerror(errno));
|
||||||
return fd;
|
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) {
|
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] != '/')) {
|
if (*index > 1 || (*index == 1 && buf[0] != '/')) {
|
||||||
buf[(*index)++] = '/';
|
buf[(*index)++] = '/';
|
||||||
}
|
}
|
||||||
int string_len = strlen(string);
|
|
||||||
|
string_len = strlen(string);
|
||||||
memcpy(buf + *index, string, string_len + 1);
|
memcpy(buf + *index, string, string_len + 1);
|
||||||
|
|
||||||
*index += string_len;
|
*index += string_len;
|
||||||
|
|
||||||
return save;
|
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 char path_buffer[PATH_MAX + 1];
|
||||||
static int path_buffer_index = 0;
|
static int path_buffer_index = 0;
|
||||||
|
|
||||||
char* get_path_buffer() {
|
char* get_path_buffer(void) {
|
||||||
return path_buffer;
|
return path_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +355,7 @@ void pop_path_buffer(int i) {
|
||||||
static char path_buffer_2[PATH_MAX + 1];
|
static char path_buffer_2[PATH_MAX + 1];
|
||||||
static int path_buffer_index_2 = 0;
|
static int path_buffer_index_2 = 0;
|
||||||
|
|
||||||
char* get_path_buffer_2() {
|
char* get_path_buffer_2(void) {
|
||||||
return path_buffer_2;
|
return path_buffer_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#ifndef SHARED_H
|
||||||
|
#define SHARED_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
@ -26,6 +27,10 @@
|
||||||
|
|
||||||
#define COLOR "m"
|
#define COLOR "m"
|
||||||
|
|
||||||
|
typedef uint8_t bool;
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
enum When {
|
enum When {
|
||||||
YES,
|
YES,
|
||||||
NO,
|
NO,
|
||||||
|
@ -65,15 +70,17 @@ void global_help(void (*help)(void));
|
||||||
void parse_help (int argc, char** argv, 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 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);
|
FILE* get_tty_stream(char* type);
|
||||||
|
|
||||||
char* get_path_buffer();
|
char* get_path_buffer(void);
|
||||||
int push_path_buffer(const char* string);
|
int push_path_buffer(const char* string);
|
||||||
void pop_path_buffer(int i);
|
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);
|
int push_path_buffer_2(const char* string);
|
||||||
void pop_path_buffer_2(int i);
|
void pop_path_buffer_2(int i);
|
||||||
|
|
||||||
bool is_dot_dir(const char* path);
|
bool is_dot_dir(const char* path);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -30,3 +30,14 @@ void* stack_pop(struct Stack* stack, size_t len) {
|
||||||
void stack_free(struct Stack *stack) {
|
void stack_free(struct Stack *stack) {
|
||||||
free(stack->data);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#ifndef STACK_H
|
||||||
|
#define STACK_H
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
struct Stack {
|
struct Stack {
|
||||||
size_t size;
|
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_pop(struct Stack* stack, size_t len);
|
||||||
void stack_free(struct Stack* stack);
|
void stack_free(struct Stack* stack);
|
||||||
|
|
||||||
inline void stack_push_int(struct Stack* stack, int value) {
|
void stack_push_int(struct Stack* stack, int value);
|
||||||
stack_push(stack, &value, sizeof(int));
|
bool stack_pop_int(struct Stack* stack, int* value);
|
||||||
}
|
|
||||||
|
|
||||||
inline bool stack_pop_int(struct Stack* stack, int* value) {
|
#endif
|
||||||
void* d = stack_pop(stack, sizeof(int));
|
|
||||||
if (d == NULL) return false;
|
|
||||||
*value = *(int*)(d);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue