fixed xargs, added grep
This commit is contained in:
parent
2980f205df
commit
c601693811
@ -6,6 +6,7 @@ https://trivial.technology/
|
|||||||
|
|
||||||
Unportable:
|
Unportable:
|
||||||
proc_parser.h
|
proc_parser.h
|
||||||
|
|
||||||
ps
|
ps
|
||||||
kill
|
kill
|
||||||
dmesg
|
dmesg
|
||||||
|
1
TODO
1
TODO
@ -26,7 +26,6 @@ getty
|
|||||||
insmod
|
insmod
|
||||||
rmmod
|
rmmod
|
||||||
lsmod
|
lsmod
|
||||||
grep
|
|
||||||
find
|
find
|
||||||
|
|
||||||
FIX:
|
FIX:
|
||||||
|
@ -93,4 +93,3 @@ mode_t mu_parse_mode(const char *s, mode_t cur_mode) {
|
|||||||
else
|
else
|
||||||
return (cur_mode & ~mask) | (mode & mask);
|
return (cur_mode & ~mask) | (mode & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
289
src/grep.c
289
src/grep.c
@ -2,79 +2,314 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
typedef struct {
|
static struct pattern {
|
||||||
char *pattern;
|
char *str;
|
||||||
regex_t rgex;
|
|
||||||
} PATTERN;
|
regex_t reg;
|
||||||
static PATTERN *regexs;
|
char reg_set;
|
||||||
static size_t r_size;
|
} **ptrns;
|
||||||
|
static size_t ptrns_size = 0;
|
||||||
|
|
||||||
static char i_flag;
|
static char i_flag;
|
||||||
static char F_flag;
|
static char F_flag;
|
||||||
static char H_flag;
|
static char H_flag;
|
||||||
|
static char E_flag;
|
||||||
|
static char v_flag;
|
||||||
|
static char x_flag;
|
||||||
|
static char w_flag;
|
||||||
|
static char mode_flag;
|
||||||
|
static int reg_flag;
|
||||||
|
|
||||||
static int addpattern(char *str) {
|
static void free_patterns(void) {
|
||||||
if (regexs == NULL) {
|
if (ptrns == NULL)
|
||||||
regexs = malloc(sizeof(PATTERN));
|
return;
|
||||||
if (regexs == NULL) {
|
|
||||||
fprintf(stderr, "grep: malloc failed\n");
|
for (size_t i = 0; i < ptrns_size; i++) {
|
||||||
|
if (ptrns[i] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ptrns[i]->str != NULL)
|
||||||
|
free(ptrns[i]->str);
|
||||||
|
|
||||||
|
if (ptrns[i]->reg_set)
|
||||||
|
regfree(&ptrns[i]->reg);
|
||||||
|
|
||||||
|
free(ptrns[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ptrns);
|
||||||
|
ptrns = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int addpattern(const char *str, const size_t size) {
|
||||||
|
if (ptrns == NULL) {
|
||||||
|
ptrns = malloc(sizeof(struct pattern *));
|
||||||
|
if (ptrns == NULL) {
|
||||||
|
fprintf(stderr, "grep: malloc: %s\n", strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PATTERN *regexs_tmp = realloc(regexs, (r_size + 1) * sizeof(PATTERN));
|
struct pattern **bckp = realloc(ptrns, sizeof(struct pattern *) * (ptrns_size + 1));
|
||||||
if (regexs_tmp == NULL) {
|
if (bckp == NULL)
|
||||||
free(regexs);
|
goto ADDP_ERROR;
|
||||||
|
ptrns = bckp;
|
||||||
|
|
||||||
fprintf(stderr, "grep: realloc failed\n");
|
ptrns[ptrns_size] = malloc(sizeof(struct pattern));
|
||||||
|
if (ptrns[ptrns_size] == NULL)
|
||||||
|
goto ADDP_ERROR;
|
||||||
|
|
||||||
|
ptrns[ptrns_size]->str = strdup(str);
|
||||||
|
if (ptrns[ptrns_size]->str == NULL)
|
||||||
|
goto ADDP_ERROR;
|
||||||
|
|
||||||
|
if (!F_flag) {
|
||||||
|
char *reg_str = ptrns[ptrns_size]->str;
|
||||||
|
size_t rs_size = size;
|
||||||
|
|
||||||
|
char bol = (ptrns[ptrns_size]->str[0] == '^');
|
||||||
|
char eol = (ptrns[ptrns_size]->str[size - 1] == '^');
|
||||||
|
|
||||||
|
if (x_flag || w_flag) {
|
||||||
|
if (w_flag)
|
||||||
|
rs_size += 5 + ((E_flag) ? 2 : 4);
|
||||||
|
|
||||||
|
reg_str = malloc(rs_size + 4);
|
||||||
|
if (reg_str == NULL)
|
||||||
|
goto ADDP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x_flag)
|
||||||
|
snprintf(reg_str, rs_size + 4, "%s%s%s", (bol) ? "" : "^", ptrns[ptrns_size]->str, (eol) ? "" : "$");
|
||||||
|
|
||||||
|
else if (w_flag)
|
||||||
|
snprintf(reg_str, rs_size + 4, "%s\\<%s%.*s%s\\>%s", (bol) ? "^" : "", (E_flag) ? "(" : "\\(", (int)size - bol - eol, ptrns[ptrns_size]->str + bol, (E_flag) ? ")" : "\\)", (eol) ? "$" : "");
|
||||||
|
|
||||||
|
if (regcomp(&ptrns[ptrns_size]->reg, reg_str, reg_flag) < 0)
|
||||||
|
goto ADDP_ERROR;
|
||||||
|
|
||||||
|
ptrns[ptrns_size]->reg_set = 1;
|
||||||
|
if (x_flag || w_flag)
|
||||||
|
free(reg_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrns_size++;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ADDP_ERROR:
|
||||||
|
ptrns_size++;
|
||||||
|
free_patterns();
|
||||||
|
fprintf(stderr, "grep: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int addpattern_file(const char *file) {
|
||||||
|
FILE *fp = fopen(file, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr, "grep: %s: %s\n", file, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
regexs = regexs_tmp;
|
|
||||||
|
|
||||||
/* Add new pattern */
|
int ret = 0;
|
||||||
regexs[r_size].pattern = str;
|
|
||||||
|
char *buf = NULL;
|
||||||
r_size++;
|
size_t n = 0;
|
||||||
return 0;
|
|
||||||
|
ssize_t size = 0;
|
||||||
|
while ((size = getline(&buf, &n, fp)) > 0) {
|
||||||
|
if (size && buf[size - 1] == '\n')
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
|
||||||
|
if (addpattern(buf, (size_t)size)) {
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL)
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp(const char *str1, const char *str2) {
|
||||||
|
if (x_flag)
|
||||||
|
return !((i_flag) ? strcasecmp : strcmp)(str1, str2);
|
||||||
|
|
||||||
|
else
|
||||||
|
return ((i_flag) ? strcasestr : strstr)(str1, str2) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grep(FILE *fp, const char *file) {
|
||||||
|
int ret = 1;
|
||||||
|
size_t matched_files = 0;
|
||||||
|
regmatch_t m;
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
ssize_t size = 0;
|
||||||
|
while ((size = getline(&buf, &n, fp)) > 0) {
|
||||||
|
if (size && buf[size - 1] == '\n')
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
|
||||||
|
char match = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < ptrns_size; i++) {
|
||||||
|
if (F_flag && cmp(buf, ptrns[i]->str)) {
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (regexec(&ptrns[i]->reg, buf, 1, &m, 0) == 0) {
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match != v_flag) {
|
||||||
|
ret = 0;
|
||||||
|
switch (mode_flag) {
|
||||||
|
case 'q':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
if (ptrns[i]->reg_set) {
|
||||||
|
unsigned int start = m.rm_so;
|
||||||
|
unsigned int finish = m.rm_eo;
|
||||||
|
printf("%.*s\n", finish - start, buf + start);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
puts(ptrns[i]->str);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
matched_files++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (H_flag)
|
||||||
|
printf("%s: ", file);
|
||||||
|
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode_flag == 'c')
|
||||||
|
printf("%zu\n", matched_files);
|
||||||
|
|
||||||
|
if (buf != NULL)
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "e:iFH")) != -1) {
|
while ((opt = getopt(argc, argv, "e:f:iFHEvxwqoc")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'e':
|
case 'e':
|
||||||
if (addpattern(optarg))
|
if (addpattern(optarg, strlen(optarg)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
if (addpattern_file(optarg))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
i_flag = 1;
|
i_flag = 1;
|
||||||
|
reg_flag |= REG_ICASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
F_flag = 1;
|
F_flag = 1;
|
||||||
|
E_flag = 0;
|
||||||
|
reg_flag &= ~REG_EXTENDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
H_flag = 1;
|
H_flag = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
E_flag = 1;
|
||||||
|
F_flag = 0;
|
||||||
|
reg_flag |= REG_EXTENDED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
v_flag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
x_flag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
w_flag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
mode_flag = 'q';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
mode_flag = 'o';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
mode_flag = 'c';
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("grep [eiFH] [FILE]\n\t-e PTRN Pattern to match\n\t-i Ignore case\n\t-H Add 'filename:' prefix\n\t-F PATTERN is a literal (not regexp)\n");
|
puts("grep [efiFHvxwqoc] [FILE]\n\t-e PTRN Pattern to match\n\t-f FILE Read pattern from file\n\t-i Ignore case\n\t-H Add 'filename:' prefix\n\t-F PATTERN is a literal (not regexp)\n\t-E PATTERN is an extended regexp\n\t-v Select non-matching lines\n\t-x Match whole lines only\n\t-w Match whole words only\n\t-q Quiet\n\t-o Show only the matching part of line\n\t-c Show only count of matching lines");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
argv += optind;
|
argv += optind;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
if (r_size == 0) {
|
if (ptrns_size == 0) {
|
||||||
fprintf(stderr, "grep: no patterns specified\n");
|
fprintf(stderr, "grep: no patterns specified\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(regexs);
|
int ret = 0;
|
||||||
return 0;
|
if (argc == 0)
|
||||||
|
ret = grep(stdin, "-");
|
||||||
|
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
FILE *fp = stdin;
|
||||||
|
if (strcmp(argv[i], "-")) {
|
||||||
|
fp = fopen(argv[i], "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
ret = 1;
|
||||||
|
fprintf(stderr, "grep: %s: %s\n", argv[i], strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grep(fp, argv[i]))
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
if (fp != stdin)
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_patterns();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
31
src/xargs.c
31
src/xargs.c
@ -82,17 +82,10 @@ static int add_arg(const char *str, size_t chars, int flag) {
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
|
|
||||||
if (!flag && I_flag) {
|
if (!flag && I_flag) {
|
||||||
for (int i = 0; i < args; i++) {
|
for (int i = 0; i < args; i++)
|
||||||
while (1) {
|
if (strstr(cmd[i], I_flag))
|
||||||
if (strstr(cmd[i], I_flag)) {
|
if (Iflag_push(str, &cmd[i]))
|
||||||
if (Iflag_push(str, &cmd[i]))
|
return ERROR;
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return I_FLAG;
|
return I_FLAG;
|
||||||
}
|
}
|
||||||
@ -290,23 +283,18 @@ int main(int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
puts("xargs [tnsrP0Idt] [cmd [arg1] [arg2...]\n\t-t Print the command before start\n\t-n Pass no more than N args\n\t-r Don't run command if input is empty\n\t-s Pass command line of no more than N bytes\n\t-0 NUL terminated input\n\t-I STR Replace STR within PROG ARGS with input line\n\t-d CHR Use char as delimeter\n\t-i Ignore quotes");
|
puts("xargs [tnsrP0Idti] [cmd [arg1] [arg2...]\n\t-t Print the command before start\n\t-n Pass no more than N args\n\t-r Don't run command if input is empty\n\t-s Pass command line of no more than N bytes\n\t-0 NUL terminated input\n\t-I STR Replace STR within PROG ARGS with input line\n\t-d CHR Use char as delimeter\n\t-i Ignore quotes");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret)
|
||||||
if (d_flag)
|
goto CLEAN_UP;
|
||||||
free(d_flag);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv += optind;
|
argv += optind;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
/* Arg */
|
/* Arg */
|
||||||
if (argc) {
|
if (argc) {
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
@ -326,7 +314,9 @@ int main(int argc, char **argv) {
|
|||||||
if (cmd[i] == NULL) {
|
if (cmd[i] == NULL) {
|
||||||
fprintf(stderr, "xargs: strdup failed\n");
|
fprintf(stderr, "xargs: strdup failed\n");
|
||||||
clear_cmd();
|
clear_cmd();
|
||||||
return 1;
|
|
||||||
|
ret = 1;
|
||||||
|
goto CLEAN_UP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +334,7 @@ int main(int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLEAN_UP:
|
||||||
if (d_flag)
|
if (d_flag)
|
||||||
free(d_flag);
|
free(d_flag);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user