summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-08-09 23:26:25 -0400
committerTavian Barnes <tavianator@tavianator.com>2024-08-09 23:28:55 -0400
commit1507cc211f6ce5b4f20f83470eacf44755a0cdcc (patch)
tree79f204eeb7ebdceeee027297d48d1d59802d3f66 /src
parentbaf9ee660c9f1d44d64341e225f9e0d7b808424d (diff)
downloadbfs-1507cc211f6ce5b4f20f83470eacf44755a0cdcc.tar.xz
bfstd: New sysoption() macro to check for POSIX option runtime support
POSIX allows optional features to be supported at compile time but not necessarily at run time by defining _POSIX_OPTION to 0 and requiring users to check sysconf(_SC_OPTION) > 0. The new sysoption() macro simplifies the check. sighook() and bfs_spawn() now check for conditional runtime support for the relevant POSIX options.
Diffstat (limited to 'src')
-rw-r--r--src/bfstd.h13
-rw-r--r--src/eval.c11
-rw-r--r--src/sighook.c24
-rw-r--r--src/xspawn.c65
-rw-r--r--src/xspawn.h10
5 files changed, 84 insertions, 39 deletions
diff --git a/src/bfstd.h b/src/bfstd.h
index afb5282..968c0ac 100644
--- a/src/bfstd.h
+++ b/src/bfstd.h
@@ -447,6 +447,19 @@ int xstrtofflags(const char **str, unsigned long long *set, unsigned long long *
*/
long xsysconf(int name);
+/**
+ * Check for a POSIX option[1] at runtime.
+ *
+ * [1]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap02.html#tag_02_01_06
+ *
+ * @param name
+ * The symbolic name of the POSIX option (e.g. SPAWN).
+ * @return
+ * The value of the option, either -1 or a date like 202405.
+ */
+#define sysoption(name) \
+ (_POSIX_##name == 0 ? xsysconf(_SC_##name) : _POSIX_##name)
+
#include <wchar.h>
/**
diff --git a/src/eval.c b/src/eval.c
index 8ec6908..90d9d37 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1018,12 +1018,15 @@ bool eval_xtype(const struct bfs_expr *expr, struct bfs_eval *state) {
* clock_gettime() wrapper.
*/
static int eval_gettime(struct bfs_eval *state, struct timespec *ts) {
-#if _POSIX_MONOTONIC_CLOCK > 0
- int ret = clock_gettime(CLOCK_MONOTONIC, ts);
-#else
- int ret = clock_gettime(CLOCK_REALTIME, ts);
+ clockid_t clock = CLOCK_REALTIME;
+
+#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
+ if (sysoption(MONOTONIC_CLOCK) > 0) {
+ clock = CLOCK_MONOTONIC;
+ }
#endif
+ int ret = clock_gettime(clock, ts);
if (ret != 0) {
bfs_warning(state->ctx, "%pP: clock_gettime(): %s.\n", state->ftwbuf, errstr());
}
diff --git a/src/sighook.c b/src/sighook.c
index b761a12..3f60405 100644
--- a/src/sighook.c
+++ b/src/sighook.c
@@ -29,7 +29,13 @@
#include <stdlib.h>
#include <unistd.h>
-#if _POSIX_SEMAPHORES > 0
+#ifdef _POSIX_SEMAPHORES
+# define BFS_POSIX_SEMAPHORES _POSIX_SEMAPHORES
+#else
+# define BFS_POSIX_SEMAPHORES (-1)
+#endif
+
+#if BFS_POSIX_SEMAPHORES >= 0
# include <semaphore.h>
#endif
@@ -42,7 +48,7 @@ struct arc {
/** The reference itself. */
void *ptr;
-#if _POSIX_SEMAPHORES > 0
+#if BFS_POSIX_SEMAPHORES >= 0
/** A semaphore for arc_wake(). */
sem_t sem;
/** sem_init() result. */
@@ -57,8 +63,12 @@ static void arc_init(struct arc *arc) {
atomic_init(&arc->refs, 0);
arc->ptr = NULL;
-#if _POSIX_SEMAPHORES > 0
- arc->sem_status = sem_init(&arc->sem, false, 0);
+#if BFS_POSIX_SEMAPHORES >= 0
+ if (sysoption(SEMAPHORES) > 0) {
+ arc->sem_status = sem_init(&arc->sem, false, 0);
+ } else {
+ arc->sem_status = -1;
+ }
#endif
}
@@ -93,7 +103,7 @@ static void arc_put(struct arc *arc) {
size_t refs = fetch_sub(&arc->refs, 1, release);
if (refs == 1) {
-#if _POSIX_SEMAPHORES > 0
+#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0 && sem_post(&arc->sem) != 0) {
abort();
}
@@ -103,7 +113,7 @@ static void arc_put(struct arc *arc) {
/** Wait on the semaphore. */
static int arc_sem_wait(struct arc *arc) {
-#if _POSIX_SEMAPHORES > 0
+#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0) {
while (sem_wait(&arc->sem) != 0) {
bfs_everify(errno == EINTR, "sem_wait()");
@@ -146,7 +156,7 @@ done:;
static void arc_destroy(struct arc *arc) {
bfs_assert(arc_refs(arc) == 0);
-#if _POSIX_SEMAPHORES > 0
+#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0) {
bfs_everify(sem_destroy(&arc->sem) == 0, "sem_destroy()");
}
diff --git a/src/xspawn.c b/src/xspawn.c
index 30c9c40..5e0f989 100644
--- a/src/xspawn.c
+++ b/src/xspawn.c
@@ -20,7 +20,7 @@
# include <paths.h>
#endif
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
# include <spawn.h>
#endif
@@ -70,29 +70,42 @@ int bfs_spawn_init(struct bfs_spawn *ctx) {
ctx->flags = 0;
SLIST_INIT(ctx);
-#if _POSIX_SPAWN > 0
- ctx->flags |= BFS_SPAWN_USE_POSIX;
+#if BFS_POSIX_SPAWN >= 0
+ if (sysoption(SPAWN) > 0) {
+ ctx->flags |= BFS_SPAWN_USE_POSIX;
- errno = posix_spawn_file_actions_init(&ctx->actions);
- if (errno != 0) {
- return -1;
- }
+ errno = posix_spawn_file_actions_init(&ctx->actions);
+ if (errno != 0) {
+ return -1;
+ }
- errno = posix_spawnattr_init(&ctx->attr);
- if (errno != 0) {
- posix_spawn_file_actions_destroy(&ctx->actions);
- return -1;
+ errno = posix_spawnattr_init(&ctx->attr);
+ if (errno != 0) {
+ posix_spawn_file_actions_destroy(&ctx->actions);
+ return -1;
+ }
}
#endif
return 0;
}
-int bfs_spawn_destroy(struct bfs_spawn *ctx) {
-#if _POSIX_SPAWN > 0
- posix_spawnattr_destroy(&ctx->attr);
- posix_spawn_file_actions_destroy(&ctx->actions);
+/**
+ * Clear the BFS_SPAWN_USE_POSIX flag and free the attributes.
+ */
+static void bfs_spawn_clear_posix(struct bfs_spawn *ctx) {
+ if (ctx->flags & BFS_SPAWN_USE_POSIX) {
+ ctx->flags &= ~BFS_SPAWN_USE_POSIX;
+
+#if BFS_POSIX_SPAWN >= 0
+ posix_spawnattr_destroy(&ctx->attr);
+ posix_spawn_file_actions_destroy(&ctx->actions);
#endif
+ }
+}
+
+int bfs_spawn_destroy(struct bfs_spawn *ctx) {
+ bfs_spawn_clear_posix(ctx);
for_slist (struct bfs_spawn_action, action, ctx) {
free(action);
@@ -101,7 +114,7 @@ int bfs_spawn_destroy(struct bfs_spawn *ctx) {
return 0;
}
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
/** Set some posix_spawnattr flags. */
_maybe_unused
static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) {
@@ -121,7 +134,7 @@ static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) {
return 0;
}
-#endif // _POSIX_SPAWN > 0
+#endif
/** Allocate a spawn action. */
static struct bfs_spawn_action *bfs_spawn_action(enum bfs_spawn_op op) {
@@ -143,7 +156,7 @@ int bfs_spawn_addopen(struct bfs_spawn *ctx, int fd, const char *path, int flags
return -1;
}
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_addopen(&ctx->actions, fd, path, flags, mode);
if (errno != 0) {
@@ -167,7 +180,7 @@ int bfs_spawn_addclose(struct bfs_spawn *ctx, int fd) {
return -1;
}
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_addclose(&ctx->actions, fd);
if (errno != 0) {
@@ -188,7 +201,7 @@ int bfs_spawn_adddup2(struct bfs_spawn *ctx, int oldfd, int newfd) {
return -1;
}
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_adddup2(&ctx->actions, oldfd, newfd);
if (errno != 0) {
@@ -228,7 +241,7 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) {
# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir_np
#endif
-#if _POSIX_SPAWN > 0 && defined(BFS_POSIX_SPAWN_ADDFCHDIR)
+#if BFS_POSIX_SPAWN >= 0 && defined(BFS_POSIX_SPAWN_ADDFCHDIR)
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = BFS_POSIX_SPAWN_ADDFCHDIR(&ctx->actions, fd);
if (errno != 0) {
@@ -237,7 +250,7 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) {
}
}
#else
- ctx->flags &= ~BFS_SPAWN_USE_POSIX;
+ bfs_spawn_clear_posix(ctx);
#endif
action->in_fd = fd;
@@ -261,7 +274,7 @@ int bfs_spawn_setrlimit(struct bfs_spawn *ctx, int resource, const struct rlimit
goto fail;
}
#else
- ctx->flags &= ~BFS_SPAWN_USE_POSIX;
+ bfs_spawn_clear_posix(ctx);
#endif
action->resource = resource;
@@ -482,7 +495,7 @@ fail:
return -1;
}
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
/** bfs_spawn() implementation using posix_spawn(). */
static pid_t bfs_posix_spawn(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp) {
@@ -516,7 +529,7 @@ static bool bfs_use_posix_spawn(const struct bfs_resolver *res, const struct bfs
return true;
}
-#endif // _POSIX_SPAWN > 0
+#endif // BFS_POSIX_SPAWN >= 0
/** Actually exec() the new process. */
_noreturn
@@ -653,7 +666,7 @@ fail:
/** Call the right bfs_spawn() implementation. */
static pid_t bfs_spawn_impl(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp) {
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
if (bfs_use_posix_spawn(res, ctx)) {
return bfs_posix_spawn(res, ctx, argv, envp);
}
diff --git a/src/xspawn.h b/src/xspawn.h
index 6a8f54a..05dcf99 100644
--- a/src/xspawn.h
+++ b/src/xspawn.h
@@ -13,7 +13,13 @@
#include <sys/types.h>
#include <unistd.h>
-#if _POSIX_SPAWN > 0
+#ifdef _POSIX_SPAWN
+# define BFS_POSIX_SPAWN _POSIX_SPAWN
+#else
+# define BFS_POSIX_SPAWN (-1)
+#endif
+
+#if BFS_POSIX_SPAWN >= 0
# include <spawn.h>
#endif
@@ -38,7 +44,7 @@ struct bfs_spawn {
struct bfs_spawn_action *head;
struct bfs_spawn_action **tail;
-#if _POSIX_SPAWN > 0
+#if BFS_POSIX_SPAWN >= 0
/** posix_spawn() context, for when we can use it. */
posix_spawn_file_actions_t actions;
posix_spawnattr_t attr;