diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /42sh/src/builtins | |
Diffstat (limited to '42sh/src/builtins')
| -rw-r--r-- | 42sh/src/builtins/Makefile.am | 20 | ||||
| -rw-r--r-- | 42sh/src/builtins/break.c | 27 | ||||
| -rw-r--r-- | 42sh/src/builtins/builtins.h | 21 | ||||
| -rw-r--r-- | 42sh/src/builtins/cd.c | 74 | ||||
| -rw-r--r-- | 42sh/src/builtins/continue.c | 27 | ||||
| -rw-r--r-- | 42sh/src/builtins/dot.c | 43 | ||||
| -rw-r--r-- | 42sh/src/builtins/echo.c | 94 | ||||
| -rw-r--r-- | 42sh/src/builtins/exit.c | 28 | ||||
| -rw-r--r-- | 42sh/src/builtins/export.c | 68 | ||||
| -rw-r--r-- | 42sh/src/builtins/false.c | 10 | ||||
| -rw-r--r-- | 42sh/src/builtins/true.c | 10 | ||||
| -rw-r--r-- | 42sh/src/builtins/unset.c | 44 |
12 files changed, 466 insertions, 0 deletions
diff --git a/42sh/src/builtins/Makefile.am b/42sh/src/builtins/Makefile.am new file mode 100644 index 0000000..4a16c3d --- /dev/null +++ b/42sh/src/builtins/Makefile.am @@ -0,0 +1,20 @@ +lib_LIBRARIES = libbuiltins.a + +libbuiltins_a_SOURCES = \ + builtins.h \ + true.c \ + false.c \ + echo.c \ + exit.c \ + break.c \ + export.c \ + continue.c \ + unset.c \ + dot.c \ + cd.c + +libbuiltins_a_CPPFLAGS = -I$(top_srcdir)/src + +libbuiltins_a_CFLAGS = -std=c99 -Werror -Wall -Wextra -Wvla -pedantic + +noinst_LIBRARIES = libbuiltins.a diff --git a/42sh/src/builtins/break.c b/42sh/src/builtins/break.c new file mode 100644 index 0000000..6718de1 --- /dev/null +++ b/42sh/src/builtins/break.c @@ -0,0 +1,27 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" +#include "utils/env.h" + +int my_break(struct string **args) +{ + char *n = "1"; + if (args[0] != NULL) + { + char *end; + long num = strtol(args[0]->data, &end, 10); + if (*end != '\0' || num <= 0) + { + fprintf(stderr, "break: %s: numeric argument required\n", + args[1]->data); + return 2; + } + n = args[0]->data; + } + env_set("BREAK", n); + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/builtins.h b/42sh/src/builtins/builtins.h new file mode 100644 index 0000000..6b99918 --- /dev/null +++ b/42sh/src/builtins/builtins.h @@ -0,0 +1,21 @@ +#ifndef BUILTINS_H +#define BUILTINS_H + +#include "utils/libstring.h" + +#define NB_BUILTINS 10 + +typedef int (*builtin)(struct string **); + +int echo(struct string **args); +int my_true(struct string **args); +int my_false(struct string **args); +int my_exit(struct string **args); +int cd(struct string **args); +int my_continue(struct string **args); +int my_break(struct string **args); +int dot(struct string **args); +int unset(struct string **args); +int export(struct string **args); + +#endif /* ! BUILTINS_H */ diff --git a/42sh/src/builtins/cd.c b/42sh/src/builtins/cd.c new file mode 100644 index 0000000..90fd9db --- /dev/null +++ b/42sh/src/builtins/cd.c @@ -0,0 +1,74 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" +#include "utils/env.h" + +int cd_pointpoint(char *path, char *old) +{ + char *current = strrchr(path, '/'); + size_t len = current - path; + if (len == 0) + { + fprintf(stderr, "cd: error with ..\n"); + return 2; + } + char *parent = malloc(len + 1); + memcpy(parent, current, len); + parent[len] = '\0'; + old = path; + path = parent; + env_set("OLDPWD", old); + env_set("PWD", path); + free(parent); + + return 0; +} + +int cd(struct string **args) +{ + if (args[0] == NULL || args[1] != NULL) + { + fprintf(stderr, "cd: error too many arguments\n"); + fflush(stdout); + return 2; + } + if (strcmp(env_get("PWD"), "") == 0) + { + fprintf(stderr, "cd: error with PWD\n"); + fflush(stdout); + return 2; + } + char *old = env_get("OLDPWD"); + char *path = env_get("PWD"); + char *tmp = old; + if (strcmp(args[0]->data, "-") == 0) + { + if (strcmp(old, "") == 0) + { + fprintf(stderr, "cd: error with OLDPWD\n"); + fflush(stdout); + return 2; + } + printf("%s\n", old); + old = path; + path = tmp; + } + else if (strcmp(args[0]->data, "..") == 0) + { + int res = cd_pointpoint(path, old); + fflush(stdout); + return res; + } + else + { + old = path; + path = args[0]->data; + } + env_set("OLDPWD", old); + env_set("PWD", path); + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/continue.c b/42sh/src/builtins/continue.c new file mode 100644 index 0000000..295fb8c --- /dev/null +++ b/42sh/src/builtins/continue.c @@ -0,0 +1,27 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" +#include "utils/env.h" + +int my_continue(struct string **args) +{ + char *n = "1"; + if (args[0] != NULL) + { + char *end; + long num = strtol(args[0]->data, &end, 10); + if (*end != '\0' || num <= 0) + { + fprintf(stderr, "continue: %s: numeric argument required\n", + args[1]->data); + return 2; + } + n = args[0]->data; + } + env_set("CONTINUE", n); + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/dot.c b/42sh/src/builtins/dot.c new file mode 100644 index 0000000..6cec097 --- /dev/null +++ b/42sh/src/builtins/dot.c @@ -0,0 +1,43 @@ +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "builtins.h" +#include "utils/env.h" + +int dot(struct string **args) +{ + if (args[0] == NULL) + { + fprintf(stderr, ".: filename argument required\n"); + fflush(stdout); + return 2; + } + if (args[1] != NULL) + { + fprintf(stderr, ".: too many arguments\n"); + fflush(stdout); + return 2; + } + + FILE *file = fopen(args[0]->data, "r"); + if (file == NULL) + { + fprintf(stderr, ".: filename does not exist\n"); + fflush(stdout); + return 1; + } + + char line[1024]; + while (fgets(line, sizeof(line), file)) + { + // TODO : execute file + fputs(line, stdout); + } + fclose(file); + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/echo.c b/42sh/src/builtins/echo.c new file mode 100644 index 0000000..f330050 --- /dev/null +++ b/42sh/src/builtins/echo.c @@ -0,0 +1,94 @@ +#include <stdio.h> +#include <string.h> + +#include "builtins.h" + +static void print_echo(struct string **args, int escapes, int newline, int i) +{ + while (args[i] != NULL) + { + if (escapes) + { + size_t j = 0; + while (j < args[i]->length) + { + if (args[i]->data[j] == '\\' && args[i]->data[j] != '\0') + { + j += 1; + switch (args[i]->data[j]) + { + case 'n': + putchar('\n'); + break; + case 't': + putchar('\t'); + break; + case '\\': + putchar('\\'); + break; + default: + putchar('\\'); + putchar(args[i]->data[j]); + break; + } + j += 1; + } + else + { + putchar(args[i]->data[j]); + j += 1; + } + } + } + else + { + fputs(args[i]->data, stdout); + } + if (args[i + 1] != NULL) + { + putchar(' '); + } + i += 1; + } + if (newline) + { + putchar('\n'); + } +} + +int echo(struct string **args) +{ + int newline = 1; + int escapes = 0; + size_t i = 0; + if (args[0] == NULL) + { + putchar('\n'); + return 0; + } + while (args[i] != NULL && args[i]->data[0] == '-') + { + if (args[i]->length == 2 && args[i]->data[1] == 'n') + { + newline = 0; + i += 1; + } + else if (args[i]->length == 2 && args[i]->data[1] == 'e') + { + escapes = 1; + i += 1; + } + else if (args[i]->length == 2 && args[i]->data[1] == 'E') + { + escapes = 0; + i += 1; + } + else + { + break; + } + } + print_echo(args, escapes, newline, i); + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/exit.c b/42sh/src/builtins/exit.c new file mode 100644 index 0000000..943c22f --- /dev/null +++ b/42sh/src/builtins/exit.c @@ -0,0 +1,28 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" + +int my_exit(struct string **args) +{ + unsigned int res = 0; + if (args[0] != NULL) + { + char *c; + long status = strtol(args[0]->data, &c, 10); + if (*c != '\0' || status < 0 || status > 255) + { + fprintf(stderr, "exit: %s: numeric argument required\n", + args[0]->data); + res = 2; + } + else + { + res = (unsigned int)status; + } + } + fflush(stdout); + exit(res); +} diff --git a/42sh/src/builtins/export.c b/42sh/src/builtins/export.c new file mode 100644 index 0000000..358cfc7 --- /dev/null +++ b/42sh/src/builtins/export.c @@ -0,0 +1,68 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" +#include "utils/env.h" + +extern char **environ; + +void printenv(void) +{ + size_t i = 0; + while (environ[i] != NULL) + { + printf("export %s\n", environ[i]); + i += 1; + } +} + +void export_var(struct string *arg) +{ + char *equal = strchr(arg->data, '='); + if (equal != NULL) + { + size_t len = equal - arg->data; + char *var = malloc(len + 1); + memcpy(var, arg->data, len); + char *value = equal + 1; + var[len] = '\0'; + env_set(var, value); + free(var); + } + else + { + env_set(arg->data, ""); + } +} + +int export(struct string **args) +{ + if (args[0] == NULL) + { + printenv(); + fflush(stdout); + return 0; + } + int flagp = 0; + size_t i = 0; + if (strcmp(args[0]->data, "-p") == 0) + { + flagp = 1; + i += 1; + } + if (args[1] == NULL && flagp) + { + printenv(); + fflush(stdout); + return 0; + } + while (args[i] != NULL) + { + export_var(args[i]); + i += 1; + } + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/false.c b/42sh/src/builtins/false.c new file mode 100644 index 0000000..17ab256 --- /dev/null +++ b/42sh/src/builtins/false.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#include "builtins.h" + +int my_false(struct string **args) +{ + (void)args; + fflush(stdout); + return 1; +} diff --git a/42sh/src/builtins/true.c b/42sh/src/builtins/true.c new file mode 100644 index 0000000..ed7c7d1 --- /dev/null +++ b/42sh/src/builtins/true.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#include "builtins.h" + +int my_true(struct string **args) +{ + (void)args; + fflush(stdout); + return 0; +} diff --git a/42sh/src/builtins/unset.c b/42sh/src/builtins/unset.c new file mode 100644 index 0000000..77b323a --- /dev/null +++ b/42sh/src/builtins/unset.c @@ -0,0 +1,44 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "builtins.h" +#include "utils/env.h" + +int unset(struct string **args) +{ + size_t i = 0; + int var = 0; + int fun = 0; + while (args[i] != NULL && args[i]->data[0] == '-') + { + if (args[i]->data[1] == 'v') + { + var = 1; + i += 1; + } + else if (args[i]->data[1] == 'f') + { + fun = 1; + i += 1; + } + else + { + break; + } + } + if (var == 0 && fun == 0) + { + var = 1; + fun = 1; + } + // TODO unset with flag -f + while (args[i] != NULL) + { + env_unset(args[i]->data); + i += 1; + } + fflush(stdout); + return 0; +} |
