commit - 77abbd7c60f1b86567878155667ad2806ff24d1c
commit + ecbc43f0d9708d2ddb4708e27b3f24cdb3902da7
blob - e5bb910dee32022ed917f75383a5771c5e2704ec
blob + 68a69f134860e2eb21be7320c03677c6055f71b9
--- Makefile
+++ Makefile
-LIBDIR = src
+PREFIX ?= /usr/local
+BINDIR ?= $(PREFIX)/bin
+LIBEXECDIR ?= $(PREFIX)/libexec/pisol
+MANDIR ?= $(PREFIX)/share/man
+DESTDIR ?=
+
+INSTALL ?= install
+RM ?= rm -f
SCHEME ?= scheme
-
-.PHONY: build tui test copy-config clean run fmt install uninstall help
-
+.PHONY: build tui test copy-config clean run install uninstall help
default: help
-
build: build/runtime/pisol.so
-
build/runtime/pisol.so: bin/pisol.ss src/pisol/core.sls src/pisol/tui.sls tools/build.ss
@mkdir -p build/runtime/lib/pisol
- $(SCHEME) --libdirs $(LIBDIR) --compile-imported-libraries --program tools/build.ss
+ $(SCHEME) --libdirs src --compile-imported-libraries --program tools/build.ss
cp src/pisol/core.so src/pisol/tui.so build/runtime/lib/pisol/
-
tui: build
- $(SCHEME) --libdirs $(LIBDIR) --program bin/pisol.ss
-
+ $(SCHEME) --libdirs src --program bin/pisol.ss
test: build
- shellcheck bin/pisol test/integration.sh tools/fmt.sh
- $(SCHEME) --libdirs $(LIBDIR) --program test/test.ss
+ shellcheck bin/pisol test/integration.sh
+ $(SCHEME) --libdirs src --program test/test.ss
sh test/integration.sh
-
copy-config:
- @config_home="$${XDG_CONFIG_HOME:-$$HOME/.config}"; \
- target="$$config_home/pisol/init"; \
- s=; if [ -e "$$config_home" ] && [ ! -w "$$config_home" ]; then s=sudo; fi; \
- if [ -f "$$target" ]; then \
- printf 'pisol: %s already exists\n' "$$target" >&2; \
- exit 1; \
- fi; \
- $$s install -d "$$config_home/pisol" && \
- $$s install -m 644 config/pisol/init "$$target"
-
+ @target="$${XDG_CONFIG_HOME:-$$HOME/.config}/pisol/init"; \
+ [ ! -e "$$target" ] || { printf 'pisol: %s already exists\n' "$$target" >&2; exit 1; }; \
+ $(INSTALL) -d "$${target%/*}" && $(INSTALL) -m 644 config/pisol/init "$$target"
clean:
rm -rf build src/pisol/core.so src/pisol/tui.so
-
run: install
- bash /usr/local/bin/pisol
-
-fmt:
- sh tools/fmt.sh src/pisol/core.sls src/pisol/tui.sls bin/pisol.ss test/test.ss tools/build.ss
-
+ $(DESTDIR)$(BINDIR)/pisol
install: build
- @prefix="$${PREFIX:-/usr/local}"; \
- bindir="$${BINDIR:-$$prefix/bin}"; \
- libexecdir="$${LIBEXECDIR:-$$prefix/libexec/pisol}"; \
- mandir="$${MANDIR:-$$prefix/share/man}"; \
- destdir="$${DESTDIR:-}"; \
- can_create() { d="$$1"; while [ -n "$$d" ] && [ ! -e "$$d" ]; do d=$$(dirname "$$d"); done; [ -d "$$d" ] && [ -w "$$d" ]; }; \
- s=; if ! can_create "$$destdir$$bindir"; then s=sudo; fi; \
- $$s install -d "$$destdir$$bindir" "$$destdir$$libexecdir/lib/pisol" "$$destdir$$mandir/man1" && \
- $$s install -m 755 bin/pisol "$$destdir$$bindir/pisol" && \
- $$s install -m 755 build/runtime/pisol.so "$$destdir$$libexecdir/pisol.so" && \
- $$s install -m 644 build/runtime/lib/pisol/core.so build/runtime/lib/pisol/tui.so "$$destdir$$libexecdir/lib/pisol/" && \
- $$s install -m 644 doc/pisol.1 "$$destdir$$mandir/man1/pisol.1"
-
+ $(INSTALL) -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBEXECDIR)/lib/pisol $(DESTDIR)$(MANDIR)/man1
+ $(INSTALL) -m 755 bin/pisol $(DESTDIR)$(BINDIR)/pisol
+ $(INSTALL) -m 755 build/runtime/pisol.so $(DESTDIR)$(LIBEXECDIR)/pisol.so
+ $(INSTALL) -m 644 build/runtime/lib/pisol/core.so build/runtime/lib/pisol/tui.so $(DESTDIR)$(LIBEXECDIR)/lib/pisol/
+ $(INSTALL) -m 644 doc/pisol.1 $(DESTDIR)$(MANDIR)/man1/pisol.1
uninstall:
- @prefix="$${PREFIX:-/usr/local}"; \
- bindir="$${BINDIR:-$$prefix/bin}"; \
- libexecdir="$${LIBEXECDIR:-$$prefix/libexec/pisol}"; \
- mandir="$${MANDIR:-$$prefix/share/man}"; \
- destdir="$${DESTDIR:-}"; \
- can_create() { d="$$1"; while [ -n "$$d" ] && [ ! -e "$$d" ]; do d=$$(dirname "$$d"); done; [ -d "$$d" ] && [ -w "$$d" ]; }; \
- s=; if ! can_create "$$destdir$$bindir"; then s=sudo; fi; \
- $$s rm -f "$$destdir$$bindir/pisol" "$$destdir$$libexecdir/pisol.so" "$$destdir$$libexecdir/lib/pisol/core.so" "$$destdir$$libexecdir/lib/pisol/tui.so" "$$destdir$$mandir/man1/pisol.1"
-
+ $(RM) $(DESTDIR)$(BINDIR)/pisol $(DESTDIR)$(LIBEXECDIR)/pisol.so
+ $(RM) $(DESTDIR)$(LIBEXECDIR)/lib/pisol/core.so $(DESTDIR)$(LIBEXECDIR)/lib/pisol/tui.so
+ $(RM) $(DESTDIR)$(MANDIR)/man1/pisol.1
help:
@printf '%s\n' \
- 'make build Compile the Chez Scheme program' \
- 'make tui Run the configuration TUI' \
- 'make test Run specification, static, Chez, shell, and TUI tests' \
- 'make run Install and run pisol' \
- 'make fmt Format Scheme sources with emacs scheme-mode' \
+ 'make build Compile pisol' \
+ 'make tui Run pisol program' \
+ 'make test Run pisol tests' \
'make copy-config Copy the default global init to ~/.config/pisol/init' \
'make clean Remove generated artifacts' \
'make install Install pisol and its manual' \
'make uninstall Remove installed pisol files' \
'make help Show this help message' \
'' \
- 'Variables: SCHEME=scheme'
+ 'Variables: PREFIX=/usr/local DESTDIR= BINDIR=PREFIX/bin' \
+ ' LIBEXECDIR=PREFIX/libexec/pisol MANDIR=PREFIX/share/man' \
+ ' SCHEME=scheme INSTALL=install'
blob - ea1eb8902b18e4e1e8e1880e09dcef553b61fd1e
blob + e9e5036cf087d5343b0cbd5a121280f5c1b858f3
--- README.md
+++ README.md
# pisol
-Working-directory Landrun isolation and configuration, with a terminal interface
-written in Chez Scheme.
+Run commands in a Landrun sandbox and manage each project's isolation settings.
+The terminal interface is written in Chez Scheme.
-`pisol` combines command isolation with an editor for the local trusted
-`.isolate` shell fragment. Outbound TCP is denied by default. The editor manages
-extra writable/executable directories and the destination TCP ports commands
-may connect to.
+`pisol` uses a trusted local `.isolate` Bash file. It denies outbound TCP by
+default. Use the editor to add writable and executable directories, and allow
+connections to specific TCP ports.
## Run
-You need Bash, [Landrun](https://github.com/Zouuup/landrun), Chez Scheme 10.4 or
-newer, and Make. Install `fzf` for fuzzy directory selection. Without it, the
-editor uses direct path entry. Install `emacs` to run `make fmt`.
+You need Bash, [Landrun](https://github.com/Zouuup/landrun), Chez Scheme 10.4
+or later, and Make.
+Install `fzf` to search for directories. Without it, enter a path directly.
+Install `emacs` to run `make fmt`.
+
```sh
make tui
make test
pisol your-command --with arguments
```
-Use `pisol -- COMMAND` when a command name conflicts with a pisol option. The
-command receives the caller environment, `PROMPT_ENV_INDICATOR=isolated`, and
-`ISOLATE_ENV` set to the canonical working directory. Calling `pisol COMMAND`
-inside an existing pisol sandbox prints a warning and directly executes the
-command rather than creating a nested Landlock domain.
+Use `pisol -- COMMAND` when a command name conflicts with a pisol option.
-## TUI commands
+The command receives your environment, `PROMPT_ENV_INDICATOR=isolated` and
+`ISOLATE_ENV`, set to the resolved working directory. If you run `pisol COMMAND`
+inside an existing pisol sandbox, it warns you and runs the command directly.
+## Terminal interface commands
+
```text
a fuzzy-find or enter a writable directory path
r choose and remove a writable directory
x exit (discards any unsaved changes)
```
-After selecting `a`, enter a base path such as `/home/miro`, or press Enter to
-open the picker in your home directory. `fzf` then lists that path and its
-immediate child directories only. Press Enter to drill down into a directory,
-Alt+Enter or Ctrl-S to select it, or Escape to use the typed path directly.
-The baseline writable tree cannot be added redundantly.
+After you select `a`, enter a base path such as `/home/miro`. Press Enter to
+start in your home directory. `fzf` shows the path and its immediate child
+directories. Press Enter to open a directory. Press Alt+Enter or Ctrl-S to
+select it. Press Escape to use the path you entered.
+You cannot add the baseline writable tree again.
+
Set `NO_COLOR=1` to disable colour. `COLUMNS` and `LINES` are respected by the
terminal environment. Set `ISOLATE_EXTRA_CONFIG` to use a config path other
than `CURRENT_DIRECTORY/.isolate`.
## Configuration and trust
-`.isolate` is sourced as trusted Bash by the launcher. A generated file looks
-like this:
+`.isolate` is trusted Bash code. The launcher sources it. A generated file
+looks like this:
```bash
args+=(
)
```
-A global init file at `~/.config/pisol/init` is sourced before the local
-`.isolate` when it exists. Put shared grants there; the project-specific file
-builds on top of it. Override the path with `PISOL_INIT_CONFIG`.
+A global init file at `~/.config/pisol/init` runs before the local `.isolate`
+file. Put shared grants there. Project settings build on those grants. Set
+`PISOL_INIT_CONFIG` to use a different global init file.
-A permissive example init based on the legacy `isolate` script is included at
-`config/pisol/init`. Copy it to `~/.config/pisol/init` and edit to taste;
-remove `--unrestricted-network` to keep outbound TCP denied by default.
+The source tree includes a permissive example init at `config/pisol/init`.
+Copy it to `~/.config/pisol/init` and change it for your needs. Remove
+`--unrestricted-network` to deny outbound TCP by default.
-The TUI also evaluates existing custom `.isolate` logic. It extracts the
-resulting `--rwx` and `--connect-tcp` entries and preserves other resulting
-Landrun arguments. Saving custom logic requires confirmation because the source
-is replaced by a canonical argument array; comments and dynamic logic are not
-retained. Default grants from the global init are shown but not edited in the
-TUI; add or remove project-specific entries instead.
+The editor evaluates existing custom `.isolate` code. It manages the resulting
+`--rwx` and `--connect-tcp` values and keeps the other Landrun arguments.
-The minimal default policy grants the working tree read/write/execute access,
-temporary storage write access, read access to system configuration/data, and
-read/execute access to standard runtime and absolute `PATH` directories. It
-also grants the standard null, zero, random, and controlling-terminal devices,
-but does not grant unrestricted networking. A Wayland socket is added when
+Saving custom code needs confirmation. It replaces the code with a static
+argument array, so it removes comments and dynamic logic. The editor shows
+global grants but does not let you change them. Add or remove project grants
+instead.
+
+The default policy gives the working tree read, write and execute access. It
+also gives write access to temporary storage. System configuration and shared
+data are read-only. Standard runtime and absolute `PATH` directories are
+readable and executable.
+
+The policy allows the standard null, zero, random and terminal devices. It does
+not allow unrestricted networking. It adds a Wayland socket when
`WAYLAND_DISPLAY` and `XDG_RUNTIME_DIR` are set.
## Build and install
make copy-config
```
-`make fmt` reindents the Scheme sources in place with `emacs` scheme-mode. Run
-it after editing Scheme files; it is a no-op on already-formatted files.
+`make fmt` formats Scheme files in place with `emacs` scheme mode. Run it after
+you edit Scheme files. It does not change files that are already formatted.
-`make install` defaults to `/usr/local` and asks for `sudo` only when needed.
+`make install` defaults to `/usr/local`; use `sudo make install` only when your
+chosen destination requires it.
Set `PREFIX`, `DESTDIR`, `BINDIR`, `LIBEXECDIR`, `MANDIR`, or `SCHEME` to
override the defaults. See `pisol(1)` after installation.
blob - 02b2e3b98611be14fa0f53f80d5647f81aa32e41
blob + 1c6a2cb10b3921fbcddd56b0df72f9f5daa4cf4d
--- config/pisol/init
+++ config/pisol/init
#!/usr/bin/env bash
-# Default global init for pisol.
-# Sourced before the project-specific .isolate file. Put shared grants here
-# and keep per-project additions in `.isolate`.
+# Default global init for pisol that is sourced before
+# the project-specific .isolate file.
args+=(--unrestricted-network)
blob - 89789314f9085e56e28497232eb4c24a28d07602
blob + ce3f2aec5603520c0caa998b0008cc9b32a17d3d
--- doc/pisol.1
+++ doc/pisol.1
.RI [ ARG ...]
.SH DESCRIPTION
.B pisol
-opens a Chez Scheme terminal editor for the current directory isolation
-configuration. With a command, it replaces itself with
+opens a Chez Scheme terminal editor for the current directory's isolation
+settings. With a command, it replaces itself with
.BR landrun (1)
-and executes the command in a working-directory sandbox. Use
+and runs the command in a sandbox for the current directory. Use
.B --
before a command whose name conflicts with a pisol option.
.PP
-The canonical current directory defines the writable tree. The configuration
+The resolved current directory defines the writable tree. The configuration
path is
.I CURRENT_DIRECTORY/.isolate
unless
.B ISOLATE_EXTRA_CONFIG
is set.
.SH ISOLATION POLICY
-The working tree is readable, writable, and executable. Temporary storage is
+The working tree is readable, writable and executable. Temporary storage is
writable. Standard runtime and absolute PATH directories are readable and
-executable, while system configuration and shared data are read-only. The
-standard null, zero, random, and controlling-terminal devices are writable.
+executable. System configuration and shared data are read-only. The standard
+null, zero, random and controlling-terminal devices are writable.
.PP
Outbound TCP is denied by default. Only destination ports configured with
.B --connect-tcp
are granted. Scoped IPC restrictions are relaxed, and the current Wayland
socket is granted when its environment variables are available.
.PP
-The caller environment is forwarded. The command additionally receives
+The command receives the caller environment. It also receives
.B PROMPT_ENV_INDICATOR=isolated
and
.B ISOLATE_ENV
-set to the canonical working directory. If
+set to the resolved working directory. If
.B ISOLATE_ENV
-is already non-empty, pisol warns and directly executes the command without
-starting a nested Landlock domain.
-.SH TUI COMMANDS
+is already non-empty, pisol warns and runs the command directly. It does not
+start a nested Landlock domain.
+.SH TERMINAL INTERFACE COMMANDS
.TP
.B a
-Prompt for a base directory path and add it as an additional
-read/write/execute grant. With no input, the picker opens in the user's home
-directory. When
+Prompt for a base directory path and add a read/write/execute grant. With no
+input, the picker opens in the user's home directory. When
.BR fzf (1)
-is available, the picker lists only the typed path and its immediate child
-directories. Press Enter to drill down into a directory, Alt+Enter or
-Ctrl-S to select it, or Escape to use the typed path directly.
+is available, the picker lists the typed path and its immediate child
+directories. Press Enter to open a directory. Press Alt+Enter or Ctrl-S to
+select it. Press Escape to use the typed path directly.
.TP
.B r
Prompt for the number of a writable directory and remove it.
.TP
.BI p " PORT"
-Allow outbound TCP connections to PORT. Valid ports are 1 through 65535.
+Allow outbound TCP connections to PORT. Valid ports are 1 to 65535.
.TP
.B d
Prompt for a configured outbound TCP port and remove it.
.TP
.B c
-Show the resolved global init file and the local configuration file, including their raw contents. A missing file is labelled absent.
+Show the global init file and local configuration file, including their raw
+contents. A missing file is labelled absent.
.TP
.B s
Save atomically with mode 0600. The combined commands
Show help or exit. Exit discards any unsaved changes.
.SH CONFIGURATION
.I .isolate
-is trusted Bash code sourced by the launcher. It modifies the Bash array
+is trusted Bash code. The launcher sources it. It changes the Bash array
.IR args ,
normally with an
.B args+=(...)
.PP
If
.I ~/.config/pisol/init
-exists, it is sourced before the local
+exists, the launcher sources it before the local
.I .isolate .
-Put shared grants in the global init file; per-project configuration builds on
-top of it. The path can be overridden with
+Put shared grants in the global init file. Per-project configuration builds on
+it. Set
.BR PISOL_INIT_CONFIG .
.PP
A permissive example global init based on the legacy
.IR config/pisol/init .
Copy it to
.I ~/.config/pisol/init
-and edit to customize. Remove
+and change it for your needs. Remove
.B --unrestricted-network
from the copy to deny outbound TCP by default.
.PP
-The editor evaluates an existing file, manages resulting
+The editor evaluates an existing file. It manages the resulting
.B --rwx
and
.B --connect-tcp
-pairs, and preserves other resulting arguments. Saving custom shell logic
-requires confirmation and replaces it with a canonical static array; source
-comments and dynamic logic are not preserved. Default grants from the global
-init file are shown but not editable in the TUI.
+pairs and keeps other resulting arguments. Saving custom shell code requires
+confirmation. It replaces the code with a static array, so it removes source
+comments and dynamic logic. The terminal interface shows global init grants.
+It does not let you change them.
.SH ENVIRONMENT
.TP
.B ISOLATE_EXTRA_CONFIG
.BR WAYLAND_DISPLAY , " XDG_RUNTIME_DIR"
Identify an optional Wayland Unix socket grant.
.SH EXIT STATUS
-The TUI returns zero on normal exit and non-zero on load or save errors. In
+The terminal interface returns zero on normal exit and non-zero on load or save errors. In
command mode, pisol propagates the executed command status. Usage errors
return 2 and a missing Landrun executable returns 127.
.SH SEE ALSO