fixed xargs

This commit is contained in:
Your Name 2024-04-06 18:34:14 +03:00
parent db62ddffc1
commit 0640e58135
7 changed files with 75 additions and 279 deletions

View File

@ -12,7 +12,7 @@ if [ -z $CC ]; then
fi
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
#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
cd $PROJECT_DIR
done
echo
echo -n "\n"
done
done

View File

@ -2,7 +2,7 @@
#define _CONFIG_H
/* (cat tee wc xargs rev split) */
#define BUF_SIZE 4096
#define BUF_SIZE 2048
/* Random source (shred) */
#define RAND_SOURCE "/dev/urandom"
@ -35,10 +35,13 @@ char *INIT_START[] = {"/etc/rc.init", NULL};
#endif
/* Max args (xargs) */
#define NARGS 1024
#ifdef XARGS
#include <limits.h>
#define NARGS ARG_MAX
/* Arg size (xargs) */
#define ARG_SIZE 1024
#endif
/* Default cmd (xargs) */
#define ECHO_CMD "echo"

View File

@ -100,7 +100,7 @@ int main(int argc, char **argv) {
break;
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;
}
}

View File

@ -1,14 +1,18 @@
#define XARGS
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include "config.h"
char *I_flag;
char t_flag;
char r_flag;
char nl_flag;
int n_flag;
int s_flag;
int P_flag;
@ -22,6 +26,13 @@ enum {
QUOTE
};
enum {
NORMAL,
CEOF,
ERROR,
I_FLAG
};
void clear_cmd(void) {
for (int i = 0; i < args; i++)
if (cmd[i] != NULL)
@ -30,20 +41,36 @@ void clear_cmd(void) {
args = 0;
}
int add_arg(const char *str, int chars) {
int add_arg(const char *str, int chars, int flag) {
if (args >= NARGS)
return 1;
return ERROR;
else if (n_flag > 0 && args > n_flag)
return 1;
return ERROR;
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);
args++;
return 0;
return NORMAL;
}
int is_correct(char c) {
if (nl_flag)
return c == '\0';
else
return isspace(c);
}
int stdin_read(void) {
@ -55,32 +82,37 @@ int stdin_read(void) {
int chars = 0;
int args_passed = 0;
int ret = 0;
int ret = NORMAL;
char flag = NONE;
while (1) {
int c = getchar();
if (c == EOF) {
if (flag == QUOTE) {
fprintf(stderr, "xargs: unterminated double quote\n");
ret = 2;
ret = ERROR;
}
if (p != arg)
goto PUSH;
ret = 1;
ret = CEOF;
break;
}
/* 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:
*p = '\0';
p = arg;
if (add_arg(arg, chars))
int r = add_arg(arg, chars, 0);
if (r == ERROR)
break;
else if (r == I_FLAG)
return NORMAL;
args_passed++;
}
@ -106,11 +138,18 @@ PUSH:
}
if (args_passed == 0)
ret = 1;
ret = CEOF;
return ret;
}
/* Run */
void sig_handler(int sig) {
if (sig == SIGUSR1)
if (P_flag2)
P_flag2--;
}
int run(void) {
if (t_flag) {
for (int i = 0; i < args; i++)
@ -153,9 +192,10 @@ void check(int val) {
}
int main(int argc, char **argv) {
signal(SIGUSR1, sig_handler);
int opt;
while ((opt = getopt(argc, argv, "tn:s:rP:")) != -1) {
while ((opt = getopt(argc, argv, "tn:s:rP:0I:")) != -1) {
switch (opt) {
case 't':
t_flag = 1;
@ -180,8 +220,16 @@ int main(int argc, char **argv) {
check(P_flag);
break;
case '0':
nl_flag = 1;
break;
case 'I':
I_flag = optarg;
break;
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;
}
}
@ -195,12 +243,12 @@ int main(int argc, char **argv) {
/* Arg */
if (argc) {
for (int i = 0; i < argc; i++)
if (add_arg(argv[i], 0))
if (add_arg(argv[i], 0, 1))
break;
}
else
add_arg(ECHO_CMD, 0);
add_arg(ECHO_CMD, 0, 1);
/* Stdin */
int stdin_stat = stdin_read();
@ -215,12 +263,12 @@ int main(int argc, char **argv) {
}
/* Run */
if (stdin_stat == 1) {
if (stdin_stat == CEOF && I_flag == NULL) {
if (!r_flag)
ret = spawn();
}
else if (stdin_stat == 0)
else if (stdin_stat == NORMAL)
ret = spawn();
/* Clear */

View File

@ -35,7 +35,7 @@ SIG signals[] = {
int parse_sig(char *arg) {
int sig = atoi(arg);
if (sig >= 0 && sig <= NSIG)
if (sig > 0 && sig <= NSIG)
return sig;
if (!strncasecmp(arg, "SIG", 3))

View File

@ -1,3 +0,0 @@
#!/bin/sh
echo ./*.c $CFLAGS -o rc | xargs $CC
mv rc $OUTPUT/sh

View File

@ -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;
}