fixed echo, xargs
This commit is contained in:
parent
2a90ce246c
commit
c705f3b30b
1
TODO
1
TODO
@ -49,5 +49,6 @@ BUGS:
|
||||
xargs (getopt with glibc)
|
||||
|
||||
FIX:
|
||||
xargs (-d)
|
||||
echo (escape)
|
||||
que (unicode)
|
||||
|
73
libmu/parse_escape.c
Normal file
73
libmu/parse_escape.c
Normal 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
5
libmu/parse_escape.h
Normal 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
|
67
src/echo.c
67
src/echo.c
@ -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);
|
||||
|
49
src/xargs.c
49
src/xargs.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user