fixed xargs
This commit is contained in:
parent
db62ddffc1
commit
0640e58135
4
build.sh
4
build.sh
|
@ -12,7 +12,7 @@ if [ -z $CC ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z $projects ]; then
|
if [ -z $projects ]; then
|
||||||
projects="sysutils-linux init console-tools coreutils findutils networking miscutils shell loginutils procps"
|
projects="sysutils-linux init console-tools coreutils findutils networking loginutils procps"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#Compile
|
#Compile
|
||||||
|
@ -29,7 +29,7 @@ for project in $projects; do
|
||||||
env CC=$CC CFLAGS="$CFLAGS -I$PROJECT_DIR -I$PROJECT_DIR/include/libmu" OUTPUT="$PROJECT_DIR"/bin/ ./build.sh
|
env CC=$CC CFLAGS="$CFLAGS -I$PROJECT_DIR -I$PROJECT_DIR/include/libmu" OUTPUT="$PROJECT_DIR"/bin/ ./build.sh
|
||||||
cd $PROJECT_DIR
|
cd $PROJECT_DIR
|
||||||
done
|
done
|
||||||
echo
|
echo -n "\n"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
7
config.h
7
config.h
|
@ -2,7 +2,7 @@
|
||||||
#define _CONFIG_H
|
#define _CONFIG_H
|
||||||
|
|
||||||
/* (cat tee wc xargs rev split) */
|
/* (cat tee wc xargs rev split) */
|
||||||
#define BUF_SIZE 4096
|
#define BUF_SIZE 2048
|
||||||
|
|
||||||
/* Random source (shred) */
|
/* Random source (shred) */
|
||||||
#define RAND_SOURCE "/dev/urandom"
|
#define RAND_SOURCE "/dev/urandom"
|
||||||
|
@ -35,10 +35,13 @@ char *INIT_START[] = {"/etc/rc.init", NULL};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Max args (xargs) */
|
/* Max args (xargs) */
|
||||||
#define NARGS 1024
|
#ifdef XARGS
|
||||||
|
#include <limits.h>
|
||||||
|
#define NARGS ARG_MAX
|
||||||
|
|
||||||
/* Arg size (xargs) */
|
/* Arg size (xargs) */
|
||||||
#define ARG_SIZE 1024
|
#define ARG_SIZE 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Default cmd (xargs) */
|
/* Default cmd (xargs) */
|
||||||
#define ECHO_CMD "echo"
|
#define ECHO_CMD "echo"
|
||||||
|
|
|
@ -100,7 +100,7 @@ int main(int argc, char **argv) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("uname [asnrvmop]\n\t-a All\n\t-s Sys]\n\t-n Nodename\n\t-r Release\n\t-v Version\n\t-m Machine\n\t-o Os name\n");
|
printf("uname [asnrvmop]\n\t-a All\n\t-s Sys\n\t-n Nodename\n\t-r Release\n\t-v Version\n\t-m Machine\n\t-o Os name\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
|
#define XARGS
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
char *I_flag;
|
||||||
char t_flag;
|
char t_flag;
|
||||||
char r_flag;
|
char r_flag;
|
||||||
|
char nl_flag;
|
||||||
int n_flag;
|
int n_flag;
|
||||||
int s_flag;
|
int s_flag;
|
||||||
int P_flag;
|
int P_flag;
|
||||||
|
@ -22,6 +26,13 @@ enum {
|
||||||
QUOTE
|
QUOTE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NORMAL,
|
||||||
|
CEOF,
|
||||||
|
ERROR,
|
||||||
|
I_FLAG
|
||||||
|
};
|
||||||
|
|
||||||
void clear_cmd(void) {
|
void clear_cmd(void) {
|
||||||
for (int i = 0; i < args; i++)
|
for (int i = 0; i < args; i++)
|
||||||
if (cmd[i] != NULL)
|
if (cmd[i] != NULL)
|
||||||
|
@ -30,20 +41,36 @@ void clear_cmd(void) {
|
||||||
args = 0;
|
args = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_arg(const char *str, int chars) {
|
int add_arg(const char *str, int chars, int flag) {
|
||||||
if (args >= NARGS)
|
if (args >= NARGS)
|
||||||
return 1;
|
return ERROR;
|
||||||
|
|
||||||
else if (n_flag > 0 && args > n_flag)
|
else if (n_flag > 0 && args > n_flag)
|
||||||
return 1;
|
return ERROR;
|
||||||
|
|
||||||
else if (s_flag > 0 && chars > s_flag)
|
else if (s_flag > 0 && chars > s_flag)
|
||||||
return 1;
|
return ERROR;
|
||||||
|
|
||||||
|
if (!flag && I_flag) {
|
||||||
|
for (int i = 0; i < args; i++)
|
||||||
|
if (!strcmp(cmd[i], I_flag))
|
||||||
|
cmd[i] = strdup(str);
|
||||||
|
|
||||||
|
return I_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
cmd[args] = strdup(str);
|
cmd[args] = strdup(str);
|
||||||
args++;
|
args++;
|
||||||
|
|
||||||
return 0;
|
return NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_correct(char c) {
|
||||||
|
if (nl_flag)
|
||||||
|
return c == '\0';
|
||||||
|
|
||||||
|
else
|
||||||
|
return isspace(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
int stdin_read(void) {
|
int stdin_read(void) {
|
||||||
|
@ -55,32 +82,37 @@ int stdin_read(void) {
|
||||||
int chars = 0;
|
int chars = 0;
|
||||||
int args_passed = 0;
|
int args_passed = 0;
|
||||||
|
|
||||||
int ret = 0;
|
int ret = NORMAL;
|
||||||
char flag = NONE;
|
char flag = NONE;
|
||||||
while (1) {
|
while (1) {
|
||||||
int c = getchar();
|
int c = getchar();
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
if (flag == QUOTE) {
|
if (flag == QUOTE) {
|
||||||
fprintf(stderr, "xargs: unterminated double quote\n");
|
fprintf(stderr, "xargs: unterminated double quote\n");
|
||||||
ret = 2;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p != arg)
|
if (p != arg)
|
||||||
goto PUSH;
|
goto PUSH;
|
||||||
|
|
||||||
ret = 1;
|
ret = CEOF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place str */
|
/* Place str */
|
||||||
else if ((flag == NONE && isspace(c) && strlen(arg) > 0) || p + 1 == arg + sizeof(arg)) {
|
else if ((flag == NONE && is_correct(c) && strlen(arg) > 0) || p == arg + sizeof(arg) - 1) {
|
||||||
PUSH:
|
PUSH:
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
p = arg;
|
p = arg;
|
||||||
|
|
||||||
if (add_arg(arg, chars))
|
int r = add_arg(arg, chars, 0);
|
||||||
|
if (r == ERROR)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
else if (r == I_FLAG)
|
||||||
|
return NORMAL;
|
||||||
|
|
||||||
args_passed++;
|
args_passed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,11 +138,18 @@ PUSH:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_passed == 0)
|
if (args_passed == 0)
|
||||||
ret = 1;
|
ret = CEOF;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Run */
|
||||||
|
void sig_handler(int sig) {
|
||||||
|
if (sig == SIGUSR1)
|
||||||
|
if (P_flag2)
|
||||||
|
P_flag2--;
|
||||||
|
}
|
||||||
|
|
||||||
int run(void) {
|
int run(void) {
|
||||||
if (t_flag) {
|
if (t_flag) {
|
||||||
for (int i = 0; i < args; i++)
|
for (int i = 0; i < args; i++)
|
||||||
|
@ -153,9 +192,10 @@ void check(int val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
signal(SIGUSR1, sig_handler);
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "tn:s:rP:")) != -1) {
|
while ((opt = getopt(argc, argv, "tn:s:rP:0I:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
t_flag = 1;
|
t_flag = 1;
|
||||||
|
@ -180,8 +220,16 @@ int main(int argc, char **argv) {
|
||||||
check(P_flag);
|
check(P_flag);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
nl_flag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
I_flag = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("xargs [tnsr] [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-P Run up to N PROGs in parallel\n");
|
printf("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-P Run up to N PROGs in parallel\n\t-0 NUL terminated input\n\t-I STR Replace STR within PROG ARGS with input line\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,12 +243,12 @@ int main(int argc, char **argv) {
|
||||||
/* Arg */
|
/* Arg */
|
||||||
if (argc) {
|
if (argc) {
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
if (add_arg(argv[i], 0))
|
if (add_arg(argv[i], 0, 1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
add_arg(ECHO_CMD, 0);
|
add_arg(ECHO_CMD, 0, 1);
|
||||||
|
|
||||||
/* Stdin */
|
/* Stdin */
|
||||||
int stdin_stat = stdin_read();
|
int stdin_stat = stdin_read();
|
||||||
|
@ -215,12 +263,12 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run */
|
/* Run */
|
||||||
if (stdin_stat == 1) {
|
if (stdin_stat == CEOF && I_flag == NULL) {
|
||||||
if (!r_flag)
|
if (!r_flag)
|
||||||
ret = spawn();
|
ret = spawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (stdin_stat == 0)
|
else if (stdin_stat == NORMAL)
|
||||||
ret = spawn();
|
ret = spawn();
|
||||||
|
|
||||||
/* Clear */
|
/* Clear */
|
||||||
|
|
|
@ -35,7 +35,7 @@ SIG signals[] = {
|
||||||
|
|
||||||
int parse_sig(char *arg) {
|
int parse_sig(char *arg) {
|
||||||
int sig = atoi(arg);
|
int sig = atoi(arg);
|
||||||
if (sig >= 0 && sig <= NSIG)
|
if (sig > 0 && sig <= NSIG)
|
||||||
return sig;
|
return sig;
|
||||||
|
|
||||||
if (!strncasecmp(arg, "SIG", 3))
|
if (!strncasecmp(arg, "SIG", 3))
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
echo ./*.c $CFLAGS -o rc | xargs $CC
|
|
||||||
mv rc $OUTPUT/sh
|
|
|
@ -1,252 +0,0 @@
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include "unused.h"
|
|
||||||
|
|
||||||
#define TOK_DELIM " \t\r\n\a"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
char *val;
|
|
||||||
} ALIAS;
|
|
||||||
ALIAS *aliases;
|
|
||||||
size_t aliases_size;
|
|
||||||
|
|
||||||
unsigned int exit_flag;
|
|
||||||
|
|
||||||
int rc_alias(char **args);
|
|
||||||
int rc_exit(char **args);
|
|
||||||
int rc_cd(char **args);
|
|
||||||
|
|
||||||
/* Builtin commands */
|
|
||||||
char *cmd[] = {"cd", "exit", "alias"};
|
|
||||||
int (*func[])(char **args) = {rc_cd, rc_exit, rc_alias};
|
|
||||||
|
|
||||||
int rc_alias(char **args) {
|
|
||||||
/* Print all aliases */
|
|
||||||
if (args[0] == NULL) {
|
|
||||||
for (size_t i = 0; i < aliases_size; i++)
|
|
||||||
printf("alias %s=\"%s\"\n", aliases[i].name, aliases[i].val);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *val = strchr(args[0], '=');
|
|
||||||
if (val == NULL) {
|
|
||||||
fprintf(stderr, "rc: syntax error\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
val[0] = '\0';
|
|
||||||
|
|
||||||
/* Check is exist */
|
|
||||||
for (size_t i = 0; i < aliases_size; i++)
|
|
||||||
if (!strcmp(args[0], aliases[i].name))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
aliases_size++;
|
|
||||||
aliases = realloc(aliases, sizeof(ALIAS) * aliases_size);
|
|
||||||
if (aliases == NULL) {
|
|
||||||
fprintf(stderr, "rc: realloc failed\n");
|
|
||||||
exit_flag = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
val++;
|
|
||||||
aliases[aliases_size - 1].name = malloc(strlen(args[0]) + 1);
|
|
||||||
aliases[aliases_size - 1].val = malloc(strlen(val) + 1);
|
|
||||||
if (aliases[aliases_size - 1].name == NULL || aliases[aliases_size - 1].val == NULL) {
|
|
||||||
fprintf(stderr, "rc: malloc failed\n");
|
|
||||||
exit_flag = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(aliases[aliases_size - 1].name, "%s", args[0]);
|
|
||||||
sprintf(aliases[aliases_size - 1].val, "%s", val);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc_exit(char **args) {
|
|
||||||
UNUSED(args);
|
|
||||||
|
|
||||||
exit_flag = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc_cd(char **args) {
|
|
||||||
int status = 0;
|
|
||||||
if (args[0] == NULL)
|
|
||||||
status = chdir(getenv("HOME"));
|
|
||||||
|
|
||||||
else
|
|
||||||
status = chdir(args[0]);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
fprintf(stderr, "rc: cd: Not such directory\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shell */
|
|
||||||
int execute(char **tok) {
|
|
||||||
if (tok[0] == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(cmd) / sizeof(char *); i++)
|
|
||||||
if (!strcmp(tok[0], cmd[i]))
|
|
||||||
return func[i](tok + 1);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < aliases_size; i++)
|
|
||||||
if (!strcmp(tok[0], aliases[i].name))
|
|
||||||
tok[0] = aliases[i].val;
|
|
||||||
|
|
||||||
/* If its not builtin cmd */
|
|
||||||
pid_t pid;
|
|
||||||
if ((pid = fork()) == 0) {
|
|
||||||
if (pid == 1)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
if (execvp(tok[0], tok) == -1)
|
|
||||||
fprintf(stderr, "rc: %s: unknow command\n", tok[0]);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid == -1) {
|
|
||||||
fprintf(stderr, "rc: fork failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = 0;
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
char **tokenize(char *str) {
|
|
||||||
size_t buflen = 1;
|
|
||||||
|
|
||||||
char *p = str;
|
|
||||||
while (*p++)
|
|
||||||
if (*p == ' ')
|
|
||||||
buflen++;
|
|
||||||
|
|
||||||
char **tokens = malloc(sizeof(char *) * (buflen + 1));
|
|
||||||
if (tokens == NULL) {
|
|
||||||
fprintf(stderr, "rc: malloc failed\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *token = strtok(str, TOK_DELIM);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while (token != NULL) {
|
|
||||||
tokens[i] = token;
|
|
||||||
token = strtok(NULL, TOK_DELIM);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens[i] = NULL;
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *readline(FILE *fp) {
|
|
||||||
char *str = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
if (getline(&str, &len, fp) == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void catch_sig(int sig) {
|
|
||||||
UNUSED(sig);
|
|
||||||
|
|
||||||
putchar('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
signal(SIGINT, catch_sig);
|
|
||||||
|
|
||||||
/* Alias */
|
|
||||||
aliases = malloc(sizeof(ALIAS));
|
|
||||||
if (aliases == NULL) {
|
|
||||||
fprintf(stderr, "rc: malloc failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int opt;
|
|
||||||
while ((opt = getopt(argc, argv, "l")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'l':
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("rc [l] [script]\n\t-l UNUSED\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argv += optind;
|
|
||||||
argc -= optind;
|
|
||||||
|
|
||||||
unsigned int script_flag = 0;
|
|
||||||
|
|
||||||
FILE *fp = stdin;
|
|
||||||
if (argc == 1) {
|
|
||||||
fp = fopen(argv[0], "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
fprintf(stderr, "rc: %s: %s\n", argv[0], strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
script_flag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!exit_flag) {
|
|
||||||
if (!script_flag) {
|
|
||||||
printf("> ");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *str = readline(fp);
|
|
||||||
if (str == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
char **tok = tokenize(str);
|
|
||||||
if (tok == NULL) {
|
|
||||||
free(str);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = execute(tok);
|
|
||||||
if (status)
|
|
||||||
setenv("status", "1", 1);
|
|
||||||
|
|
||||||
else
|
|
||||||
setenv("status", "0", 1);
|
|
||||||
|
|
||||||
free(tok);
|
|
||||||
free(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < aliases_size; i++) {
|
|
||||||
free(aliases[i].name);
|
|
||||||
free(aliases[i].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(aliases);
|
|
||||||
if (script_flag)
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
putchar('\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue