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 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

View File

@ -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"

View File

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

View File

@ -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 */

View File

@ -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))

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