diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-05-05 15:11:14 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-05-05 15:11:14 -0400 |
| commit | a1f81258c164e772307043cf1be65c1343319d58 (patch) | |
| tree | 270a3ab316010ad625d13119c5f9556627cd42d7 | |
| parent | 0df984c4b2ec7cdc683b452ffea068c220470405 (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-- | Makefile | 33 | ||||
| -rwxr-xr-x | configure.sh | 12 | ||||
| -rw-r--r-- | src/compile.c | 2 | ||||
| -rw-r--r-- | src/stdlib/stacktrace.c | 2 | ||||
| -rw-r--r-- | src/tomo.c | 54 | ||||
| -rw-r--r-- | src/typecheck.c | 2 |
6 files changed, 64 insertions, 41 deletions
@@ -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])); @@ -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); |
