diff options
author | Mattias Andrée <maandree@kth.se> | 2024-08-28 16:42:05 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-08-28 16:42:05 +0200 |
commit | a24071ae913b223487df78859c8d830f9e69f580 (patch) | |
tree | e2ec712cc29461c82cfdd477e8b1ba961b50018d /open.c | |
parent | First commit (diff) | |
download | anysum-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.c | 66 |
1 files changed, 66 insertions, 0 deletions
@@ -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; + } +} |