aboutsummaryrefslogtreecommitdiffstats
path: root/open.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-08-28 16:42:05 +0200
committerMattias Andrée <maandree@kth.se>2024-08-28 16:42:05 +0200
commita24071ae913b223487df78859c8d830f9e69f580 (patch)
treee2ec712cc29461c82cfdd477e8b1ba961b50018d /open.c
parentFirst commit (diff)
downloadanysum-a24071ae913b223487df78859c8d830f9e69f580.tar.gz
anysum-a24071ae913b223487df78859c8d830f9e69f580.tar.bz2
anysum-a24071ae913b223487df78859c8d830f9e69f580.tar.xz
Second commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'open.c')
-rw-r--r--open.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/open.c b/open.c
new file mode 100644
index 0000000..8d1a4c5
--- /dev/null
+++ b/open.c
@@ -0,0 +1,66 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+int
+patheq(const char *have, const char *want, const char **end_out)
+{
+ while (*want) {
+ if (*have != *want)
+ return 0;
+ if (*have == '/') {
+ while (*++have == '/');
+ while (*++want == '/');
+ }
+ }
+ if (!end_out)
+ return !*have;
+ *end_out = have;
+ return 1;
+}
+
+
+int
+openfile(const char *path, int *is_new_fd_out, const char **fname_out)
+{
+ const char *p;
+ int fd, digit;
+
+ *fname_out = path;
+
+ if (patheq(path, "/dev/fd/", &p) || patheq(path, "/proc/self/fd/", &p)) {
+ fd = 0;
+ while (isdigit(*p)) {
+ digit = (int)(*p & 15);
+ if (fd > (INT_MAX - digit) / 10)
+ goto fallback;
+ fd = fd * 10 + digit;
+ }
+ if (*p)
+ goto fallback;
+ *is_new_fd_out = 0;
+ return 0;
+ } else if (!strcmp(path, "-")) {
+ *fname_out = "<stdin>";
+ *is_new_fd_out = 0;
+ return STDIN_FILENO;
+ } else if (patheq(path, "/dev/stdin", NULL)) {
+ *is_new_fd_out = 0;
+ return STDIN_FILENO;
+ } else if (patheq(path, "/dev/stdout", NULL)) {
+ *is_new_fd_out = 0;
+ return STDOUT_FILENO;
+ } else if (patheq(path, "/dev/stderr", NULL)) {
+ *is_new_fd_out = 0;
+ return STDERR_FILENO;
+ } else {
+ fallback:
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ weprintf("%s:", path);
+ return -1;
+ }
+ *is_new_fd_out = 0;
+ return fd;
+ }
+}