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)
FIX:
xargs (-d)
echo (escape)
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 <stdlib.h>
#include <string.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);
}
}
#include "parse_escape.h"
int main(int argc, char **argv) {
char n_flag = 0;
char e_flag = 0;
argv++;
argc--;
@ -77,8 +26,14 @@ int main(int argc, char **argv) {
}
for (int i = 0; i < argc; i++) {
if (e_flag)
format(argv[i]);
if (e_flag) {
char *str = mu_parse_escape(NULL, argv[i]);
if (str == NULL)
return 1;
fputs(str, stdout);
free(str);
}
else
fputs(argv[i], stdout);

View File

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