aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-05-05 15:11:14 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-05-05 15:11:14 -0400
commita1f81258c164e772307043cf1be65c1343319d58 (patch)
tree270a3ab316010ad625d13119c5f9556627cd42d7
parent0df984c4b2ec7cdc683b452ffea068c220470405 (diff)
Fix some permission stuff to make it more seamless to install to
directories the user doesn't own (e.g. /usr/local, owned by root)
-rw-r--r--Makefile33
-rwxr-xr-xconfigure.sh12
-rw-r--r--src/compile.c2
-rw-r--r--src/stdlib/stacktrace.c2
-rw-r--r--src/tomo.c54
-rw-r--r--src/typecheck.c2
6 files changed, 64 insertions, 41 deletions
diff --git a/Makefile b/Makefile
index ac9c6c50..236a5572 100644
--- a/Makefile
+++ b/Makefile
@@ -40,11 +40,13 @@ CWARN=-Wall -Wextra -Wno-format -Wno-format-security -Wshadow \
-Wunused-const-variable -Wunused-local-typedefs -Wunused-macros -Wvariadic-macros \
-Wwrite-strings
+ifeq ($(SUDO),)
ifeq ($(shell command -v doas 2>/dev/null),)
SUDO=sudo
else
SUDO=doas
endif
+endif
OWNER=$(shell ls -ld '$(PREFIX)' | awk '{print $$3}')
@@ -67,12 +69,20 @@ G=-ggdb
O=-O3
GIT_VERSION=$(shell git log -1 --pretty=format:"$$(git describe --tags --abbrev=0)_%as_%h")
CFLAGS=$(CCONFIG) $(INCLUDE_DIRS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LTO) \
- -DTOMO_HOME='"$(TOMO_HOME)"' -DTOMO_PREFIX='"$(PREFIX)"' -DDEFAULT_C_COMPILER='"$(DEFAULT_C_COMPILER)"' \
+ -DTOMO_PREFIX='"$(PREFIX)"' -DSUDO='"$(SUDO)"' -DDEFAULT_C_COMPILER='"$(DEFAULT_C_COMPILER)"' \
-DTOMO_VERSION='"$(GIT_VERSION)"'
CFLAGS_PLACEHOLDER="$$(printf '\033[2m<flags...>\033[m\n')"
LDLIBS=-lgc -lcord -lm -lunistring -lgmp
LIBTOMO_FLAGS=-shared
+DEFINE_AS_OWNER=as_owner() { \
+ if [ "$$USER" = "$(OWNER)" ]; then \
+ "$$@"; \
+ else \
+ $(SUDO) -u "$(OWNER)" "$$@"; \
+ fi; \
+} \
+
ifeq ($(OS),OpenBSD)
LDLIBS += -lexecinfo
endif
@@ -188,21 +198,24 @@ install-files: build/bin/tomo build/lib/$(LIB_FILE) build/lib/$(AR_FILE) check-u
printf "\n\033[1mexport PATH=\"$(PREFIX):\$$PATH\"\033[m\n\n" >&2; \
exit 1; \
fi
- $(SUDO) -u "$(OWNER)" mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/man/man3" "$(PREFIX)/bin" "$(PREFIX)/include/tomo" "$(PREFIX)/lib" "$(PREFIX)/share/tomo/modules" "$(PREFIX)/share/tomo/lib"
- $(SUDO) -u "$(OWNER)" cp src/stdlib/*.h "$(PREFIX)/include/tomo/"
- $(SUDO) -u "$(OWNER)" cp build/lib/$(LIB_FILE) build/lib/$(AR_FILE) "$(PREFIX)/lib/"
- $(SUDO) -u "$(OWNER)" rm -f "$(PREFIX)/bin/tomo"
- $(SUDO) -u "$(OWNER)" cp build/bin/tomo "$(PREFIX)/bin/"
- $(SUDO) -u "$(OWNER)" cp man/man1/* "$(PREFIX)/man/man1/"
- $(SUDO) -u "$(OWNER)" cp man/man3/* "$(PREFIX)/man/man3/"
+ $(DEFINE_AS_OWNER); \
+ as_owner mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/man/man3" "$(PREFIX)/bin" "$(PREFIX)/include/tomo" "$(PREFIX)/lib" "$(PREFIX)/share/tomo/modules" "$(PREFIX)/share/tomo/lib"; \
+ as_owner cp src/stdlib/*.h "$(PREFIX)/include/tomo/"; \
+ as_owner cp build/lib/$(LIB_FILE) build/lib/$(AR_FILE) "$(PREFIX)/lib/"; \
+ as_owner rm -f "$(PREFIX)/bin/tomo"; \
+ as_owner cp build/bin/tomo "$(PREFIX)/bin/"; \
+ as_owner cp man/man1/* "$(PREFIX)/man/man1/"; \
+ as_owner cp man/man3/* "$(PREFIX)/man/man3/";
install-libs: build/bin/tomo check-utilities
- ./local-tomo -qIL lib/patterns lib/time lib/commands lib/shell lib/random lib/base64 lib/pthreads lib/uuid lib/core; \
+ $(DEFINE_AS_OWNER); \
+ ./local-tomo -qIL lib/patterns lib/time lib/commands lib/shell lib/random lib/base64 lib/pthreads lib/uuid lib/core
install: install-files install-libs
uninstall:
- rm -rvf "$(PREFIX)/bin/tomo" "$(PREFIX)/include/tomo" "$(PREFIX)/lib/$(LIB_FILE)" "$(PREFIX)/lib/$(AR_FILE)" "$(PREFIX)/share/tomo";
+ $(DEFINE_AS_OWNER); \
+ as_owner rm -rvf "$(PREFIX)/bin/tomo" "$(PREFIX)/include/tomo" "$(PREFIX)/lib/$(LIB_FILE)" "$(PREFIX)/lib/$(AR_FILE)" "$(PREFIX)/share/tomo";
endif
diff --git a/configure.sh b/configure.sh
index b89a31f6..1b5bd272 100755
--- a/configure.sh
+++ b/configure.sh
@@ -25,11 +25,11 @@ if ! echo "$PATH" | tr ':' '\n' | grep -qx "$PREFIX/bin"; then
"Please put this in your .profile or .bashrc: export PATH=\"$PREFIX/bin:\$PATH\""
fi
-default_home="~/.local/share/tomo"
-printf '\033[1mChoose where to install Tomo libraries (default: %s):\033[m ' "$default_home"
-read TOMO_HOME
-if [ -z "$TOMO_HOME" ]; then TOMO_HOME="$default_home"; fi
-TOMO_HOME="${TOMO_HOME/#\~/$HOME}"
+if command -v doas >/dev/null; then
+ SUDO=doas
+else
+ SUDO=sudo
+fi
default_cc="cc"
printf '\033[1mChoose which C compiler to use by default (default: %s):\033[m ' "$default_cc"
@@ -39,6 +39,6 @@ DEFAULT_C_COMPILER="${DEFAULT_C_COMPILER/#\~/$HOME}"
cat <<END >config.mk
PREFIX=$PREFIX
-TOMO_HOME=$TOMO_HOME
DEFAULT_C_COMPILER=$DEFAULT_C_COMPILER
+SUDO=$SUDO
END
diff --git a/src/compile.c b/src/compile.c
index 8494766a..76f519c8 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -1977,7 +1977,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
return with_source_info(env, ast, CORD_all("$initialize", suffix, "();\n"));
} else if (use->what == USE_MODULE) {
glob_t tm_files;
- if (glob(String(TOMO_HOME"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
+ if (glob(String(TOMO_PREFIX"/share/tomo/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
code_err(ast, "Could not find library");
CORD initialization = CORD_EMPTY;
diff --git a/src/stdlib/stacktrace.c b/src/stdlib/stacktrace.c
index bcec6b0a..f4093849 100644
--- a/src/stdlib/stacktrace.c
+++ b/src/stdlib/stacktrace.c
@@ -102,7 +102,7 @@ public void print_stacktrace(FILE *out, int offset)
cwd[cwd_len++] = '/';
cwd[cwd_len] = '\0';
- const char *install_dir = TOMO_HOME"/installed/";
+ const char *install_dir = TOMO_PREFIX"/share/tomo/installed/";
static void *stack[1024];
int64_t size = (int64_t)backtrace(stack, sizeof(stack)/sizeof(stack[0]));
diff --git a/src/tomo.c b/src/tomo.c
index 44038d91..4547b66b 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -82,14 +82,18 @@ static OptionalText_t
" -D_BSD_SOURCE"
#endif
" -DGC_THREADS"
- " -I'" TOMO_PREFIX "/include' -I'" TOMO_HOME "/installed' -I/usr/local/include"),
+ " -I'" TOMO_PREFIX "/include' -I'" TOMO_PREFIX "/share/tomo/installed' -I/usr/local/include"),
ldlibs = Text("-lgc -lm -lgmp -lunistring -ltomo"),
- ldflags = Text("-Wl,-rpath,'"TOMO_PREFIX"/lib',-rpath,'" TOMO_HOME "/lib',-rpath,/usr/local/lib "
- "-L'" TOMO_HOME "/lib' -L/usr/local/lib"),
+ ldflags = Text("-Wl,-rpath,'"TOMO_PREFIX"/lib',-rpath,'" TOMO_PREFIX "/share/tomo/lib',-rpath,/usr/local/lib "
+ "-L'" TOMO_PREFIX "/share/tomo/lib' -L/usr/local/lib"),
optimization = Text("2"),
cc = Text(DEFAULT_C_COMPILER);
-static Text_t config_summary;
+static Text_t config_summary,
+ // This will be either "" or "sudo -u <user>" or "doas -u <user>"
+ // to allow a command to put stuff into TOMO_PREFIX as the owner
+ // of that directory.
+ as_owner = Text("");
static void transpile_header(env_t *base_env, Path_t path);
static void transpile_code(env_t *base_env, Path_t path);
@@ -156,7 +160,7 @@ int main(int argc, char *argv[])
// Run a tool:
if ((streq(argv[1], "-r") || streq(argv[1], "--run")) && argc >= 3) {
if (strcspn(argv[2], "/;$") == strlen(argv[2])) {
- const char *program = String("'"TOMO_HOME"'/installed/", argv[2], "/", argv[2]);
+ const char *program = String("'"TOMO_PREFIX"'/share/tomo/installed/", argv[2], "/", argv[2]);
execv(program, &argv[2]);
}
print_err("This is not an installed tomo program: \033[31;1m", argv[2], "\033[m");
@@ -175,7 +179,7 @@ int main(int argc, char *argv[])
" --parse|-p: show parse tree\n"
" --install|-I: install the executable or library\n"
" --optimization|-O <level>: set optimization level\n"
- " --run|-r: run a program from " TOMO_HOME "/installed\n"
+ " --run|-r: run a program from " TOMO_PREFIX "/share/tomo/installed\n"
);
Text_t help = Texts(Text("\x1b[1mtomo\x1b[m: a compiler for the Tomo programming language"), Text("\n\n"), usage);
tomo_parse_args(
@@ -237,9 +241,15 @@ int main(int argc, char *argv[])
config_summary = Text$from_str(String(cc, " ", cflags, " -O", optimization));
+ Text_t owner = Path$owner(Path$from_str(TOMO_PREFIX), true);
+ Text_t user = Text$from_str(getenv("USER"));
+ if (!Text$equal_values(user, owner)) {
+ as_owner = Texts(Text(SUDO" -u "), owner, Text(" "));
+ }
+
for (int64_t i = 0; i < uninstall.length; i++) {
Text_t *u = (Text_t*)(uninstall.data + i*uninstall.stride);
- xsystem("rm -rvf '"TOMO_HOME"'/installed/", *u, " '"TOMO_HOME"'/lib/lib", *u, SHARED_SUFFIX);
+ xsystem(as_owner, "rm -rvf '"TOMO_PREFIX"'/share/tomo/installed/", *u, " '"TOMO_PREFIX"/share/tomo/lib/lib'", *u, SHARED_SUFFIX);
print("Uninstalled ", *u);
}
@@ -322,7 +332,7 @@ int main(int argc, char *argv[])
for (int64_t i = 0; i < files.length; i++) {
Path_t path = *(Path_t*)(files.data + i*files.stride);
Path_t exe = Path$with_extension(path, Text(""), true);
- xsystem("cp -v '", exe, "' '"TOMO_PREFIX"'/bin/");
+ xsystem(as_owner, "cp -v '", exe, "' '"TOMO_PREFIX"'/bin/");
}
}
return 0;
@@ -500,27 +510,27 @@ void build_library(Path_t lib_dir)
void install_library(Path_t lib_dir)
{
Text_t lib_dir_name = Path$base_name(lib_dir);
- Path_t dest = Path$with_component(Path$from_str(TOMO_HOME"/installed"), lib_dir_name);
+ Path_t dest = Path$with_component(Path$from_str(TOMO_PREFIX"/share/tomo/installed"), lib_dir_name);
if (!Path$equal_values(lib_dir, dest)) {
if (verbose) whisper("Clearing out any pre-existing version of ", lib_dir_name);
- Path$remove(dest, true);
+ xsystem(as_owner, "rm -rf '", dest, "'");
if (verbose) whisper("Moving files to ", dest);
- xsystem("mkdir -p '", dest, "'");
- xsystem("cp -r '", lib_dir, "'/* '", dest, "/'");
- xsystem("cp -r '", lib_dir, "'/.build '", dest, "/'");
- }
- if (verbose) whisper("Linking "TOMO_HOME"/lib/lib", lib_dir_name, SHARED_SUFFIX);
- xsystem("mkdir -p '"TOMO_HOME"'/lib/");
- xsystem("ln -f -s ../installed/'", lib_dir_name, "'/lib'", lib_dir_name, SHARED_SUFFIX,
- "' '"TOMO_HOME"'/lib/lib'", lib_dir_name, SHARED_SUFFIX, "'");
+ xsystem(as_owner, "mkdir -p '", dest, "'");
+ xsystem(as_owner, "cp -r '", lib_dir, "'/* '", dest, "/'");
+ xsystem(as_owner, "cp -r '", lib_dir, "'/.build '", dest, "/'");
+ }
+ if (verbose) whisper("Linking "TOMO_PREFIX"/share/tomo/lib/lib", lib_dir_name, SHARED_SUFFIX);
+ xsystem(as_owner, "mkdir -p '"TOMO_PREFIX"/share/tomo/lib/'");
+ xsystem(as_owner, "ln -f -s ../installed/'", lib_dir_name, "'/lib'", lib_dir_name, SHARED_SUFFIX,
+ "' '"TOMO_PREFIX"/share/tomo/lib/lib", lib_dir_name, SHARED_SUFFIX, "'");
// If we have `debugedit` on this system, use it to remap the debugging source information
// to point to the installed version of the source file. Otherwise, fail silently.
if (verbose) whisper("Updating debug symbols for ", dest, "/lib", lib_dir_name, SHARED_SUFFIX);
- (void)system(String("debugedit -b ", lib_dir,
+ (void)system(String(as_owner, "debugedit -b ", lib_dir,
" -d '", dest, "'"
" '", dest, "/lib", lib_dir_name, SHARED_SUFFIX, "'"
" 2>/dev/null >/dev/null"));
- print("Installed \033[1m", lib_dir_name, "\033[m to "TOMO_HOME"/installed");
+ print("Installed \033[1m", lib_dir_name, "\033[m to "TOMO_PREFIX"/share/tomo/installed");
}
void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *extra_ldlibs)
@@ -683,11 +693,11 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
break;
}
case USE_MODULE: {
- Text_t lib = Texts(Text("'" TOMO_HOME "/installed/"),
+ Text_t lib = Texts(Text("'" TOMO_PREFIX "/share/tomo/installed/"),
Text$from_str(use->path), Text("/lib"), Text$from_str(use->path), Text(SHARED_SUFFIX "'"));
Table$set(to_link, &lib, NULL, Table$info(&Text$info, &Void$info));
- List_t children = Path$glob(Path$from_str(String(TOMO_HOME"/installed/", use->path, "/*.tm")));
+ List_t children = Path$glob(Path$from_str(String(TOMO_PREFIX"/share/tomo/installed/", use->path, "/*.tm")));
for (int64_t i = 0; i < children.length; i++) {
Path_t *child = (Path_t*)(children.data + i*children.stride);
Table_t discarded = {.fallback=to_compile};
diff --git a/src/typecheck.c b/src/typecheck.c
index f0326913..db3f392a 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -183,7 +183,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
}
case USE_MODULE: {
glob_t tm_files;
- if (glob(String(TOMO_HOME"/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
+ if (glob(String(TOMO_PREFIX"/share/tomo/installed/", use->path, "/[!._0-9]*.tm"), GLOB_TILDE, NULL, &tm_files) != 0)
code_err(module_ast, "Could not find library");
env_t *module_env = fresh_scope(env);