summaryrefslogtreecommitdiffstats
path: root/src/bfstd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bfstd.c')
-rw-r--r--src/bfstd.c63
1 files changed, 54 insertions, 9 deletions
diff --git a/src/bfstd.c b/src/bfstd.c
index 7680f17..b29fb7b 100644
--- a/src/bfstd.c
+++ b/src/bfstd.c
@@ -1,13 +1,15 @@
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD
-#include "prelude.h"
#include "bfstd.h"
+
+#include "bfs.h"
#include "bit.h"
#include "diag.h"
#include "sanity.h"
#include "thread.h"
#include "xregex.h"
+
#include <errno.h>
#include <fcntl.h>
#include <langinfo.h>
@@ -27,13 +29,13 @@
#include <unistd.h>
#include <wchar.h>
-#if BFS_USE_SYS_SYSMACROS_H
+#if __has_include(<sys/sysmacros.h>)
# include <sys/sysmacros.h>
-#elif BFS_USE_SYS_MKDEV_H
+#elif __has_include(<sys/mkdev.h>)
# include <sys/mkdev.h>
#endif
-#if BFS_USE_UTIL_H
+#if __has_include(<util.h>)
# include <util.h>
#endif
@@ -184,6 +186,16 @@ char *xgetdelim(FILE *file, char delim) {
}
}
+int open_cterm(int flags) {
+ char path[L_ctermid];
+ if (ctermid(path) == NULL || strlen(path) == 0) {
+ errno = ENOTTY;
+ return -1;
+ }
+
+ return open(path, flags);
+}
+
const char *xgetprogname(void) {
const char *cmd = NULL;
#if BFS_HAS_GETPROGNAME
@@ -199,6 +211,35 @@ const char *xgetprogname(void) {
return cmd;
}
+int xstrtoll(const char *str, char **end, int base, long long *value) {
+ // strtoll() skips leading spaces, but we want to reject them
+ if (xisspace(str[0])) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // If end is NULL, make sure the entire string is valid
+ bool entire = !end;
+ char *endp;
+ if (!end) {
+ end = &endp;
+ }
+
+ errno = 0;
+ long long result = strtoll(str, end, base);
+ if (errno != 0) {
+ return -1;
+ }
+
+ if (*end == str || (entire && **end != '\0')) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *value = result;
+ return 0;
+}
+
/** Compile and execute a regular expression for xrpmatch(). */
static int xrpregex(nl_item item, const char *response) {
const char *pattern = nl_langinfo(item);
@@ -285,7 +326,7 @@ const char *xstrerror(int errnum) {
// On FreeBSD with MemorySanitizer, duplocale() triggers
// https://github.com/llvm/llvm-project/issues/65532
-#if BFS_HAS_STRERROR_L && !(__FreeBSD__ && SANITIZE_MEMORY)
+#if BFS_HAS_STRERROR_L && !(__FreeBSD__ && __SANITIZE_MEMORY__)
# if BFS_HAS_USELOCALE
locale_t loc = uselocale((locale_t)0);
# else
@@ -322,6 +363,10 @@ const char *xstrerror(int errnum) {
return ret;
}
+const char *errstr(void) {
+ return xstrerror(errno);
+}
+
/** Get the single character describing the given file type. */
static char type_char(mode_t mode) {
switch (mode & S_IFMT) {
@@ -672,14 +717,14 @@ int xstrtofflags(const char **str, unsigned long long *set, unsigned long long *
}
long xsysconf(int name) {
-#if __FreeBSD__ && SANITIZE_MEMORY
+#if __FreeBSD__ && __SANITIZE_MEMORY__
// Work around https://github.com/llvm/llvm-project/issues/88163
__msan_scoped_disable_interceptor_checks();
#endif
long ret = sysconf(name);
-#if __FreeBSD__ && SANITIZE_MEMORY
+#if __FreeBSD__ && __SANITIZE_MEMORY__
__msan_scoped_enable_interceptor_checks();
#endif
@@ -922,14 +967,14 @@ static char *dollar_quote(char *dest, char *end, const char *str, size_t len, en
/** How much of this string is safe as a bare word? */
static size_t bare_len(const char *str, size_t len) {
- // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
+ // https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_02
size_t ret = strcspn(str, "|&;<>()$`\\\"' *?[#~=%!{}");
return ret < len ? ret : len;
}
/** How much of this string is safe to double-quote? */
static size_t quotable_len(const char *str, size_t len) {
- // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_03
+ // https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_02_03
size_t ret = strcspn(str, "`$\\\"!");
return ret < len ? ret : len;
}