diff --git a/Fennix Userspace.code-workspace b/Fennix Userspace.code-workspace
index f0b2c3c3..42164709 100644
--- a/Fennix Userspace.code-workspace
+++ b/Fennix Userspace.code-workspace
@@ -20,7 +20,8 @@
"userspace/libs",
"userspace/apps/test",
"userspace/apps/usr",
- "userspace"
+ "userspace",
+ "coreutils"
]
}
}
diff --git a/Userspace/.editorconfig b/Userspace/.editorconfig
index 784b867b..591828a8 100644
--- a/Userspace/.editorconfig
+++ b/Userspace/.editorconfig
@@ -11,3 +11,7 @@ indent_size = 4
[Makefile]
indent_style = tab
+
+[{CMakeLists.txt,*.cmake}]
+indent_size = 2
+indent_style = space
diff --git a/Userspace/.vscode/c_boilerplates.code-snippets b/Userspace/.vscode/c_boilerplates.code-snippets
index 6942dbf6..711453fe 100644
--- a/Userspace/.vscode/c_boilerplates.code-snippets
+++ b/Userspace/.vscode/c_boilerplates.code-snippets
@@ -160,5 +160,30 @@
"*/"
],
"description": "Create libc license."
+ },
+ "Core Utilities License": {
+ "isFileTemplate": true,
+ "prefix": [
+ "license_coreutils",
+ ],
+ "body": [
+ "/*",
+ "\tThis file is part of Fennix Core Utilities.",
+ "",
+ "\tFennix Core Utilities is free software: you can redistribute it and/or",
+ "\tmodify it under the terms of the GNU General Public License as",
+ "\tpublished by the Free Software Foundation, either version 3 of",
+ "\tthe License, or (at your option) any later version.",
+ "",
+ "\tFennix Core Utilities is distributed in the hope that it will be useful,",
+ "\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
+ "\tGNU General Public License for more details.",
+ "",
+ "\tYou should have received a copy of the GNU General Public License",
+ "\talong with Fennix Core Utilities. If not, see .",
+ "*/"
+ ],
+ "description": "Create coreutils license."
}
}
diff --git a/Userspace/.vscode/c_cpp_properties.json b/Userspace/.vscode/c_cpp_properties.json
index a6c44b52..8079dd31 100644
--- a/Userspace/.vscode/c_cpp_properties.json
+++ b/Userspace/.vscode/c_cpp_properties.json
@@ -4,6 +4,7 @@
"name": "Fennix x64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
+ "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@@ -45,6 +46,7 @@
"name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
+ "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@@ -86,6 +88,7 @@
"name": "Fennix Arm (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
+ "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@@ -107,6 +110,7 @@
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
+ "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@@ -126,4 +130,4 @@
}
],
"version": 4
-}
\ No newline at end of file
+}
diff --git a/Userspace/Makefile b/Userspace/Makefile
index 1b5d48a4..bfe84f86 100644
--- a/Userspace/Makefile
+++ b/Userspace/Makefile
@@ -37,9 +37,22 @@ create_out:
mkdir -p out/usr/include
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
+build_coreutils:
+ mkdir -p cache/coreutils
+ cd cache/coreutils && \
+ cmake $(WORKSPACE_DIR)/coreutils \
+ -DCMAKE_INSTALL_PREFIX:PATH=$(WORKSPACE_DIR)/out \
+ -DCMAKE_SYSROOT=$(WORKSPACE_DIR)/out \
+ -DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
+ -DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
+ && \
+ make -j$(shell nproc) && \
+ make install
+
build: create_out
make -C libc build
make -C libs build
+ $(MAKE) build_coreutils
make -C apps build
prepare:
diff --git a/Userspace/coreutils/.gitignore b/Userspace/coreutils/.gitignore
new file mode 100644
index 00000000..378eac25
--- /dev/null
+++ b/Userspace/coreutils/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/Userspace/coreutils/CMakeLists.txt b/Userspace/coreutils/CMakeLists.txt
new file mode 100644
index 00000000..5f5fe17c
--- /dev/null
+++ b/Userspace/coreutils/CMakeLists.txt
@@ -0,0 +1,51 @@
+cmake_minimum_required(VERSION 3.10)
+project(FennixCoreUtilities VERSION 1.0.0)
+
+if(NOT DEFINED ENV{WORKSPACE_DIR})
+ set(STANDALONE_BUILD ON)
+ message(STATUS "Compiling standalone")
+else()
+ set(STANDALONE_BUILD OFF)
+ message(STATUS "Compiling within workspace")
+endif()
+
+set(CMAKE_C_COMPILER "$ENV{CC}")
+set(CMAKE_CXX_COMPILER "$ENV{CXX}")
+set(CMAKE_ASM_COMPILER "$ENV{AS}")
+set(CMAKE_AR "$ENV{AR}")
+set(CMAKE_LINKER "$ENV{LD}")
+
+if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
+ set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
+else()
+ set(CMAKE_C_FLAGS "-O2")
+endif()
+
+include_directories(${CMAKE_SOURCE_DIR}/include)
+
+file(GLOB SINGLE_SOURCE "src/*.c")
+foreach(file ${SINGLE_SOURCE})
+ get_filename_component(name ${file} NAME_WE)
+ add_executable(${name} ${file})
+ target_compile_definitions(${name} PRIVATE
+ PROGRAM_NAME="${name}"
+ PROGRAM_VERSION="${PROJECT_VERSION}"
+ )
+ install(TARGETS ${name} DESTINATION bin)
+endforeach()
+
+file(GLOB_RECURSE GROUP_SOURCES "src/*/*.c")
+foreach(file ${GROUP_SOURCES})
+ get_filename_component(name ${file} DIRECTORY)
+ get_filename_component(name ${name} NAME)
+ list(APPEND GROUP_MAP_${name} ${file})
+endforeach()
+
+foreach(name IN LISTS GROUP_MAP_)
+ add_executable(${name} ${GROUP_MAP_${name}})
+ target_compile_definitions(${name} PRIVATE
+ PROGRAM_NAME="${name}"
+ PROGRAM_VERSION="${PROJECT_VERSION}"
+ )
+ install(TARGETS ${name} DESTINATION bin)
+endforeach()
diff --git a/Userspace/coreutils/include/coreutils.h b/Userspace/coreutils/include/coreutils.h
new file mode 100644
index 00000000..3a7cb142
--- /dev/null
+++ b/Userspace/coreutils/include/coreutils.h
@@ -0,0 +1,38 @@
+/*
+ This file is part of Fennix Core Utilities.
+
+ Fennix Core Utilities is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Core Utilities is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Core Utilities. If not, see .
+*/
+
+#ifndef _COREUTILS_H
+#define _COREUTILS_H
+
+#ifndef PROGRAM_NAME
+#define PROGRAM_NAME ""
+#endif
+
+#ifndef PROGRAM_VERSION
+#define PROGRAM_VERSION ""
+#endif
+
+#define BUILD_YEAR (__DATE__ + 7)
+
+#define PRINTF_VERSION \
+ printf("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); \
+ printf("Fennix Core Utilities Copyright (C) %s EnderIce2\n", BUILD_YEAR); \
+ printf("This program comes with ABSOLUTELY NO WARRANTY\n"); \
+ printf("This is free software, and you are welcome to redistribute it\n"); \
+ printf("under certain conditions\n")
+
+#endif // _COREUTILS_H
diff --git a/Userspace/coreutils/src/echo.c b/Userspace/coreutils/src/echo.c
new file mode 100644
index 00000000..204ade67
--- /dev/null
+++ b/Userspace/coreutils/src/echo.c
@@ -0,0 +1,183 @@
+/*
+ This file is part of Fennix Core Utilities.
+
+ Fennix Core Utilities is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Core Utilities is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Core Utilities. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+void PrintHelp()
+{
+ printf("Usage: echo [OPTION]... [STRING]...\n");
+ printf("Echo the STRING(s) to standard output.\n\n");
+ printf(" -n do not output the trailing newline\n");
+ printf(" -e enable interpretation of backslash escapes\n");
+ printf(" -E disable interpretation of backslash escapes (default)\n");
+ printf(" --help display this help and exit\n");
+ printf(" --version output version information and exit\n\n");
+ printf("If -e is specified, the following sequences are recognized:\n");
+ printf(" \\\\ backslash\n");
+ printf(" \\a alert (BEL)\n");
+ printf(" \\b backspace\n");
+ printf(" \\c produce no further output\n");
+ printf(" \\e escape\n");
+ printf(" \\f form feed\n");
+ printf(" \\n new line\n");
+ printf(" \\r carriage return\n");
+ printf(" \\t horizontal tab\n");
+ printf(" \\v vertical tab\n");
+}
+
+static void PrintEscaped(const char *str)
+{
+ while (*str)
+ {
+ if (*str == '\\')
+ {
+ str++;
+ switch (*str)
+ {
+ case 'n':
+ putchar('\n');
+ break;
+ case 't':
+ putchar('\t');
+ break;
+ case '\\':
+ putchar('\\');
+ break;
+ case 'a':
+ putchar('\a');
+ break;
+ case 'b':
+ putchar('\b');
+ break;
+ case 'r':
+ putchar('\r');
+ break;
+ case 'v':
+ putchar('\v');
+ break;
+ case 'f':
+ putchar('\f');
+ break;
+ case '0' ... '7':
+ {
+ int octal = 0;
+ for (int i = 0; i < 3 && *str >= '0' && *str <= '7'; i++, str++)
+ {
+ octal = octal * 8 + (*str - '0');
+ }
+ putchar(octal);
+ str--;
+ break;
+ }
+ case 'x':
+ {
+ int hex = 0;
+ str++;
+ for (int i = 0; i < 2 && ((*str >= '0' && *str <= '9') ||
+ (*str >= 'a' && *str <= 'f') ||
+ (*str >= 'A' && *str <= 'F'));
+ i++, str++)
+ {
+ if (*str >= '0' && *str <= '9')
+ hex = hex * 16 + (*str - '0');
+ else if (*str >= 'a' && *str <= 'f')
+ hex = hex * 16 + (*str - 'a' + 10);
+ else if (*str >= 'A' && *str <= 'F')
+ hex = hex * 16 + (*str - 'A' + 10);
+ }
+ putchar(hex);
+ str--;
+ break;
+ }
+ default:
+ putchar(*str);
+ break;
+ }
+ }
+ else
+ {
+ putchar(*str);
+ }
+ str++;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ bool newline = true;
+ bool interpret_escapes = false;
+ int arg_start = 1;
+
+ if (argc == 2)
+ {
+ if (strcmp(argv[1], "--help") == 0)
+ {
+ PrintHelp();
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[1], "--version") == 0)
+ {
+ PRINTF_VERSION;
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (argc > 1)
+ {
+ for (int i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-' && argv[i][1] != '\0')
+ {
+ for (size_t j = 1; argv[i][j] != '\0'; j++)
+ {
+ if (argv[i][j] == 'n')
+ newline = false;
+ else if (argv[i][j] == 'e')
+ interpret_escapes = true;
+ else if (argv[i][j] == 'E')
+ interpret_escapes = false;
+ else
+ goto print_args;
+ }
+ arg_start++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+print_args:
+ for (int i = arg_start; i < argc; i++)
+ {
+ if (interpret_escapes)
+ PrintEscaped(argv[i]);
+ else
+ fputs(argv[i], stdout);
+ if (i < argc - 1)
+ putchar(' ');
+ }
+
+ if (newline)
+ putchar('\n');
+ return 0;
+}