fixed echo, xargs

This commit is contained in:
Your Name 2024-07-22 14:29:48 +03:00
parent 2a90ce246c
commit c705f3b30b
5 changed files with 131 additions and 64 deletions

1
TODO
View File

@ -49,5 +49,6 @@ BUGS:
xargs (getopt with glibc) xargs (getopt with glibc)
FIX: FIX:
xargs (-d)
echo (escape) echo (escape)
que (unicode) que (unicode)

73
libmu/parse_escape.c Normal file
View File

@ -0,0 +1,73 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
char *mu_parse_escape(const char *prog_name, const char *src) {
size_t size = 0;
size_t src_len = strlen(src);
for (size_t i = 0; i < src_len; i++) {
size++;
size -= (src[i] == '\\');
}
char *buf = malloc(size + 1);
if (buf == NULL) {
if (prog_name)
fprintf(stderr, "%s: malloc: %s\n", prog_name, strerror(errno));
return NULL;
}
size = 0;
for (size_t i = 0; i < src_len; i++) {
char c = src[i];
if (c == '\\' && i < src_len) {
switch (src[i + 1]) {
case 'n':
c = '\n';
break;
case 'a':
c = '\a';
break;
case 't':
c = '\t';
break;
case 'b':
c = '\b';
break;
case 'e':
c = '\033';
break;
case 'r':
c = '\r';
break;
case 'f':
c = '\f';
break;
case 'v':
c = '\v';
break;
default:
c = '\\';
}
i++;
}
buf[size] = c;
size++;
}
buf[size + 1] = '\0';
return buf;
}

5
libmu/parse_escape.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef PARSE_ESCAPE_H
#define PARSE_ESCAPE_H
char *mu_parse_escape(const char *prog_name, const char *src);
#endif

View File

@ -3,62 +3,11 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "parse_escape.h"
static char n_flag = 0;
static char e_flag = 0;
static void format(char *str) {
for (size_t i = 0; i < strlen(str); i++) {
unsigned int c = str[i];
if (c == '\\') {
switch (str[i + 1]) {
case 'a':
c = '\a';
break;
case 'n':
c = '\n';
break;
case 't':
c = '\t';
break;
case 'c':
exit(0);
case 'v':
c = '\v';
break;
case 'r':
c = '\r';
break;
case 'f':
c = '\f';
break;
case 'e':
c = '\033';
break;
case 'b':
c = '\b';
break;
default:
c = '\\';
}
i++;
}
putchar(c);
}
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
char n_flag = 0;
char e_flag = 0;
argv++; argv++;
argc--; argc--;
@ -77,8 +26,14 @@ int main(int argc, char **argv) {
} }
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
if (e_flag) if (e_flag) {
format(argv[i]); char *str = mu_parse_escape(NULL, argv[i]);
if (str == NULL)
return 1;
fputs(str, stdout);
free(str);
}
else else
fputs(argv[i], stdout); fputs(argv[i], stdout);

View File

@ -7,6 +7,7 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include "parse_escape.h"
#ifndef ARG_MAX #ifndef ARG_MAX
#define ARG_MAX 10000 #define ARG_MAX 10000
@ -21,6 +22,8 @@ static char r_flag;
static char nl_flag; static char nl_flag;
static int n_flag; static int n_flag;
static size_t s_flag; static size_t s_flag;
static char *d_flag;
static char i_flag;
enum { enum {
NORMAL, NORMAL,
@ -102,7 +105,16 @@ static int add_arg(const char *str, size_t chars, int flag) {
static int is_correct(char c) { static int is_correct(char c) {
if (nl_flag) if (nl_flag)
return c == '\0'; return (c == '\0');
else if (d_flag) {
for (size_t i = 0; i < strlen(d_flag); i++) {
if (c == d_flag[i])
return 1;
}
return 0;
}
else else
return isspace(c); return isspace(c);
@ -134,7 +146,7 @@ static int xargs(void) {
break; break;
} }
if (flag == NONE && is_correct(c) && index > 0) { if ((i_flag || flag == NONE) && is_correct(c) && index > 0) {
arg[index] = '\0'; arg[index] = '\0';
int r = add_arg(arg, chars, 0); int r = add_arg(arg, chars, 0);
@ -161,7 +173,7 @@ static int xargs(void) {
} }
else { else {
if (c == '"' || c == '\'') { if (!i_flag && (c == '"' || c == '\'')) {
if (flag == QUOTE) if (flag == QUOTE)
flag = NONE; flag = NONE;
@ -227,9 +239,10 @@ static int spawn(void) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
/* For -s flag */ /* For -s flag */
char *p = NULL; char *p = NULL;
int ret = 0;
int opt; int opt;
while ((opt = getopt(argc, argv, "tn:s:rP:0I:")) != -1) { while ((opt = getopt(argc, argv, "tn:s:rP:0I:d:i")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
t_flag = 1; t_flag = 1;
@ -239,7 +252,7 @@ int main(int argc, char **argv) {
n_flag = atoi(optarg); n_flag = atoi(optarg);
if (n_flag <= 0) { if (n_flag <= 0) {
fprintf(stderr, "xargs: -n: invalid number: %s\n", optarg); fprintf(stderr, "xargs: -n: invalid number: %s\n", optarg);
return 1; ret = 1;
} }
break; break;
@ -248,7 +261,7 @@ int main(int argc, char **argv) {
s_flag = strtoul(optarg, &p, 0); s_flag = strtoul(optarg, &p, 0);
if (s_flag <= 0 || *p) { if (s_flag <= 0 || *p) {
fprintf(stderr, "xargs: -s: invalid number: %zu%s\n", s_flag, (p) ? p : ""); fprintf(stderr, "xargs: -s: invalid number: %zu%s\n", s_flag, (p) ? p : "");
return 1; ret = 1;
} }
break; break;
@ -265,16 +278,33 @@ int main(int argc, char **argv) {
I_flag = optarg; I_flag = optarg;
break; break;
case 'd':
d_flag = mu_parse_escape("xargs", optarg);
if (d_flag == NULL)
return 1;
break;
case 'i':
i_flag = 1;
break;
default: default:
puts("xargs [tnsrP0I] [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"); 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");
return 0; return 0;
} }
} }
if (ret) {
if (d_flag)
free(d_flag);
return 1;
}
argv += optind; argv += optind;
argc -= optind; argc -= optind;
int ret = 0;
while (1) { while (1) {
/* Arg */ /* Arg */
@ -314,5 +344,8 @@ int main(int argc, char **argv) {
break; break;
} }
if (d_flag)
free(d_flag);
return ret; return ret;
} }