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)
|
xargs (getopt with glibc)
|
||||||
|
|
||||||
FIX:
|
FIX:
|
||||||
|
xargs (-d)
|
||||||
echo (escape)
|
echo (escape)
|
||||||
que (unicode)
|
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 <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);
|
||||||
|
49
src/xargs.c
49
src/xargs.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user