aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Mignot <victor@vmignot.fr>2026-02-18 08:16:09 +0100
committerVictor Mignot <victor@vmignot.fr>2026-03-09 19:52:47 +0100
commitc856ca9339e7154699a8ac81ec943d45d8c5ffe8 (patch)
treee5cd54cd3df53dc84e8d755a64e31f52c464e9d5
downloadfutiles-c856ca9339e7154699a8ac81ec943d45d8c5ffe8.tar.gz
Implement `true` and `false`
-rw-r--r--.gitignore2
-rw-r--r--LICENSE14
-rw-r--r--Makefile28
-rw-r--r--README.md3
-rw-r--r--src/false.c3
-rw-r--r--src/main.c44
-rw-r--r--src/true.c3
7 files changed, 97 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1da65b4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+futiles
+*.o
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d2bb57b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2026 Victor Mignot
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c8010d2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+CC := gcc
+CFLAGS :=
+CFLAGS_EXTRA := -std=c23 -Wpedantic -Wall -Wextra
+LDFLAGS :=
+PREFIX :=
+UTILS := true false
+
+BIN := futiles
+OBJS := $(patsubst %.c, %.o, $(wildcard src/*.c))
+
+all: $(BIN)
+
+$(BIN): $(OBJS)
+ $(CC) -o $@ $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) $^
+
+src/%.o: src/%.c
+ $(CC) -c -o $@ $(CFLAGS) $(CFLAGS_EXTRA) $<
+
+clean:
+ rm -f $(BIN) $(OBJS)
+
+install: $(BIN)
+ install -m 755 $(BIN) $(PREFIX)/bin/
+ for util in $(UTILS) ; do \
+ ln -sf futiles /usr/bin/$$util; \
+ done
+
+.PHONY: clean install
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7934cd0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# futiles
+
+An implementation of POSIX utilities.
diff --git a/src/false.c b/src/false.c
new file mode 100644
index 0000000..f30e835
--- /dev/null
+++ b/src/false.c
@@ -0,0 +1,3 @@
+int false_main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
+ return 1;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..64da70f
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,44 @@
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef int util_main(int, char **);
+
+extern util_main true_main;
+extern util_main false_main;
+
+typedef struct futiles_util futiles_util_t;
+struct futiles_util {
+ const char *name;
+ util_main *main;
+};
+
+int display_utils(int, char **);
+const futiles_util_t utils[] = {
+ { .name = "futiles", .main = display_utils },
+ { .name = "true", .main = true_main },
+ { .name = "false", .main = false_main }
+};
+#define UTILS_NB (sizeof(utils) / sizeof(futiles_util_t))
+
+int display_utils([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
+ fputs("Available utils: ", stdout);
+ for (size_t i = 1; i < UTILS_NB; i++) {
+ printf("%s ", utils[i].name);
+ }
+ putc('\n', stdout);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char *argv[]) {
+ char *called_basename = basename(argv[0]);
+
+ for (size_t i = 0; i < UTILS_NB; i++) {
+ if (strcmp(called_basename, utils[i].name) == 0) {
+ return utils[i].main(argc, argv);
+ }
+ }
+ return EXIT_FAILURE;
+}
diff --git a/src/true.c b/src/true.c
new file mode 100644
index 0000000..aed6117
--- /dev/null
+++ b/src/true.c
@@ -0,0 +1,3 @@
+int true_main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
+ return 0;
+}