Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@ host-edit
host-clip
host-info
host-download
host-env
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# SPDX-FileCopyrightText: 2020-2026 Dimitris Panokostas
# SPDX-License-Identifier: GPL-3.0-or-later

TOOLS = host-run host-multiview host-shell host-path host-reveal host-notify host-edit host-clip host-info host-download
TOOLS = host-run host-multiview host-shell host-path host-reveal host-notify host-edit host-clip host-info host-download host-env
Comment thread
midwan marked this conversation as resolved.
TEST_BINS = tests/test_host_common.out tests/test_host_command_builders.out tests/test_host_edit_command.out tests/test_host_download_command.out
TEST_SCRIPTS = tests/test_package_layout.sh tests/test_ahi_driver_source.sh
TESTS = $(TEST_BINS) $(TEST_SCRIPTS)
COMMON_HEADERS = src/host_common.h src/host_path.h src/host_capture.h src/host_base64.h src/host_clip_command.h src/host_download_command.h src/host_edit_command.h src/host_info_command.h src/host_notify_command.h src/host_powershell.h src/host_reveal_command.h src/uae_pragmas.h
COMMON_HEADERS = src/host_common.h src/host_path.h src/host_capture.h src/host_base64.h src/host_clip_command.h src/host_download_command.h src/host_edit_command.h src/host_env_command.h src/host_info_command.h src/host_notify_command.h src/host_powershell.h src/host_reveal_command.h src/uae_pragmas.h
PACKAGE = Host-Tools-$(VERSION).lha
PACKAGE_ROOT = Host-Tools
PACKAGE_DIR ?= build/package
Expand Down Expand Up @@ -91,10 +91,13 @@ host-info: src/host-info.c $(COMMON_HEADERS)
host-download: src/host-download.c $(COMMON_HEADERS)
$(CC) $(CFLAGS) $(VERFLAGS) $(INCLUDES) src/host-download.c -o $@

host-env: src/host-env.c $(COMMON_HEADERS)
$(CC) $(CFLAGS) $(VERFLAGS) $(INCLUDES) src/host-env.c -o $@

tests/test_host_common.out: tests/test_host_common.c src/host_common.h
$(HOST_CC) $(HOST_NATIVE_FLAGS) $(HOST_CFLAGS) tests/test_host_common.c -o $@

tests/test_host_command_builders.out: tests/test_host_command_builders.c src/host_base64.h src/host_clip_command.h src/host_common.h src/host_info_command.h src/host_notify_command.h src/host_powershell.h src/host_reveal_command.h
tests/test_host_command_builders.out: tests/test_host_command_builders.c src/host_base64.h src/host_clip_command.h src/host_common.h src/host_env_command.h src/host_info_command.h src/host_notify_command.h src/host_powershell.h src/host_reveal_command.h
$(HOST_CC) $(HOST_NATIVE_FLAGS) $(HOST_CFLAGS) tests/test_host_command_builders.c -o $@

tests/test_host_edit_command.out: tests/test_host_edit_command.c src/host_edit_command.h src/host_common.h
Expand Down
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,27 @@ host-info
host-download <URL> [<destination>] [FORCE]
```

### 11. host-env
**Get and set host user environment variables.**
`host-env` reads, writes, removes, and lists environment variables on the host. On Windows it updates the user's persistent environment. On Linux and macOS it writes persistent values to `$HOME/.host-tools-env`; source that file from your host shell startup files if you want future host login shells to import those values automatically.
- **Persistent**: Changes are intended for future host processes.
- **Scoped Safely**: Existing host shells, desktop apps, and Amiberry's parent process cannot have their live environment changed by a child process.

**Usage:**
```shell
host-env get NAME
host-env set NAME VALUE
host-env unset NAME
host-env list
```

---

## Requirements

- **Amiberry v6.0+** (or a version with updated `uaelib` support).
- "Native Code" execution must be enabled in Amiberry settings.
- All tools work on **Linux and macOS hosts**. On **Windows hosts**, `host-path`, `host-download`, `host-clip`, `host-reveal`, and `host-info` are supported with a current Amiberry (PowerShell and Explorer handle the Windows side; `curl.exe` ships with Windows 10 and later). The remaining tools (`host-run`, `host-multiview`, `host-shell`, `host-edit`, `host-notify`) currently require a Linux or macOS host, since their host commands run through the POSIX shell.
- All tools work on **Linux and macOS hosts**. On **Windows hosts**, `host-path`, `host-download`, `host-clip`, `host-reveal`, `host-info`, and `host-env` are supported with a current Amiberry (PowerShell and Explorer handle the Windows side; `curl.exe` ships with Windows 10 and later). The remaining tools (`host-run`, `host-multiview`, `host-shell`, `host-edit`, `host-notify`) currently require a Linux or macOS host, since their host commands run through the POSIX shell.
- For status-aware tools (`host-reveal`, `host-notify`, `host-clip`, and `host-info`), a newer Amiberry build with the `HostShell_Status` trap reports host command failures immediately. Older builds still work, but use timeout-based completion detection.
- Linux desktop integration uses `xdg-utils` (`xdg-open`, `xdg-mime`) and GTK's `gtk-launch` when available. Notifications use `notify-send`; clipboard support uses `wl-clipboard`, `xclip`, or `xsel`; file selection in `host-reveal` uses `gdbus` when present. Character set conversion uses `iconv` when present.
- `host-download` uses the host's `curl` or `wget` (`curl.exe` on Windows). Live streaming progress requires an Amiberry build with pipe-based HostShell sessions; on older Linux and macOS builds the tool falls back to a two-phase transfer that downloads on the host first.
Expand All @@ -138,7 +152,7 @@ All tools follow AmigaDOS conventions: `0` on success, `10` (`RETURN_ERROR`) whe

The installer shows a component checklist for the command tools, AmigaGuide documentation, and the UAE and UAESND AHI audio drivers. Before replacing an existing versioned file, it shows the installed and package versions and asks whether to replace or skip it. Files without version strings are still checked for existence and ask before overwrite. It does not edit startup files, system settings, AHI preferences, or existing driver configuration.

For manual installation, copy the binaries (`host-run`, `host-multiview`, `host-shell`, `host-path`, `host-reveal`, `host-notify`, `host-edit`, `host-clip`, `host-info`) from the package `C` drawer to `C:` or anywhere in your system path. To install the UAE AHI driver manually, copy `Devs/AHI/uae.audio` to `DEVS:AHI/` and `Devs/AudioModes/UAE` to `DEVS:AudioModes/`. To install the UAESND AHI driver manually, copy `Devs/AHI/uaesnd.audio` to `DEVS:AHI/` and `Devs/AudioModes/UAESND` to `DEVS:AudioModes/`. The UAESND driver plays each AHI channel through a hardware audio stream and requires the UAESND sound board to be enabled in the Amiberry configuration.
For manual installation, copy the binaries (`host-run`, `host-multiview`, `host-shell`, `host-path`, `host-reveal`, `host-notify`, `host-edit`, `host-clip`, `host-info`, `host-download`, `host-env`) from the package `C` drawer to `C:` or anywhere in your system path. To install the UAE AHI driver manually, copy `Devs/AHI/uae.audio` to `DEVS:AHI/` and `Devs/AudioModes/UAE` to `DEVS:AudioModes/`. To install the UAESND AHI driver manually, copy `Devs/AHI/uaesnd.audio` to `DEVS:AHI/` and `Devs/AudioModes/UAESND` to `DEVS:AudioModes/`. The UAESND driver plays each AHI channel through a hardware audio stream and requires the UAESND sound board to be enabled in the Amiberry configuration.

## Examples

Expand Down
23 changes: 22 additions & 1 deletion package/Help/Host-Tools.guide
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The command tools are installed to C: when selected in the installer.
@{"host-clip" link HostClip} exchanges text with the host clipboard.
@{"host-info" link HostInfo} prints host integration details.
@{"host-download" link HostDownload} downloads files through the host.
@{"host-env" link HostEnv} gets and sets host environment variables.

@endnode

Expand Down Expand Up @@ -180,13 +181,33 @@ host-download works on Linux, macOS, and Windows hosts. On Windows a current Ami

@endnode

@node HostEnv "host-env"
host-env gets, sets, removes, and lists host user environment variables.

Usage:

host-env get NAME
host-env set NAME VALUE
host-env unset NAME
host-env list

On Windows, host-env updates the user's persistent environment through PowerShell and the Windows user environment store. New host processes see the changed values.

On Linux and macOS, host-env writes persistent values to $HOME/.host-tools-env. Source that file from your host shell startup files if you want future host login shells to import those values automatically.

host-env cannot change the live environment of already-running host shells, desktop apps, or Amiberry's parent process.

Variable names must use ASCII letters, digits, and underscores, and must not start with a digit.

@endnode

@node InstallNotes "Installation Notes"
The installer copies selected files only. It shows a component checklist first. When a versioned file already exists, Installer shows the installed and package versions and asks whether to replace or skip it. Files without version strings are still checked for existence and ask before overwrite.

It does not edit startup files, system settings, or existing driver configuration.

Native Code execution must be enabled in Amiberry for these tools to communicate with the host.

All tools work on Linux and macOS hosts. On Windows hosts, host-path, host-download, host-clip, host-reveal, and host-info are supported with a current Amiberry; the remaining tools require a Linux or macOS host.
All tools work on Linux and macOS hosts. On Windows hosts, host-path, host-download, host-clip, host-reveal, host-info, and host-env are supported with a current Amiberry; the remaining tools require a Linux or macOS host.

@endnode
1 change: 1 addition & 0 deletions package/Install
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@
(P_InstallCommandTool "host-clip")
(P_InstallCommandTool "host-info")
(P_InstallCommandTool "host-download")
(P_InstallCommandTool "host-env")
)
)

Expand Down
144 changes: 144 additions & 0 deletions src/host-env.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* SPDX-FileCopyrightText: 2020-2026 Dimitris Panokostas
* SPDX-License-Identifier: GPL-3.0-or-later
*/

#include <stdio.h>
#include <string.h>
#include "host_capture.h"
#include "host_env_command.h"

static const char version[] = "$VER: Host-Env " VERSION_STR " (" DATE_STR ")";

static int print_usage(void)
{
printf("Host-Env v%s\n", VERSION_STR);
printf("Host-Env gets and sets host user environment variables.\n");
printf("%s\nUsage: host-env get <name>\n"
" host-env set <name> <value>\n"
" host-env unset <name>\n"
" host-env list\n", version);
return 0;
}

static int require_name(const char *name)
{
if (!host_env_valid_name(name)) {
printf("Invalid environment variable name\n");
return 0;
}
return 1;
}

int main(int argc, char *argv[])
{
static char command[HOST_MAX_COMMAND_LEN];
int windows;

command[0] = '\0';

if (!InitUAEResource())
{
printf("UAEResource not found!\n");
return 2;
}

if (argc <= 1)
{
printf("Missing environment command\n");
print_usage();
return HOST_RETURN_ERROR;
}

if (strcmp(argv[1], "?") == 0)
{
return print_usage();
}

windows = (GetHostPlatform() == HOST_PLATFORM_WINDOWS);

if (strcmp(argv[1], "get") == 0) {
if (argc != 3) {
printf("Usage error\n");
print_usage();
return HOST_RETURN_ERROR;
}
if (!require_name(argv[2])) {
return HOST_RETURN_ERROR;
}
if (windows) {
if (!host_append_env_get_command_windows(command, sizeof(command), argv[2])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
} else if (!host_append_env_get_command(command, sizeof(command), argv[2])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
return host_print_command_output(command);
}

if (strcmp(argv[1], "set") == 0) {
if (argc != 4) {
printf("Usage error\n");
print_usage();
return HOST_RETURN_ERROR;
}
if (!require_name(argv[2])) {
return HOST_RETURN_ERROR;
}
if (windows) {
if (!host_append_env_set_command_windows(command, sizeof(command), argv[2], argv[3])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
} else if (!host_append_env_set_command(command, sizeof(command), argv[2], argv[3])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
return host_print_command_output(command);
}

if (strcmp(argv[1], "unset") == 0) {
if (argc != 3) {
printf("Usage error\n");
print_usage();
return HOST_RETURN_ERROR;
}
if (!require_name(argv[2])) {
return HOST_RETURN_ERROR;
}
if (windows) {
if (!host_append_env_unset_command_windows(command, sizeof(command), argv[2])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
} else if (!host_append_env_unset_command(command, sizeof(command), argv[2])) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
return host_print_command_output(command);
}

if (strcmp(argv[1], "list") == 0) {
if (argc != 2) {
printf("Unexpected argument after list\n");
print_usage();
return HOST_RETURN_ERROR;
}
if (windows) {
if (!host_append_env_list_command_windows(command, sizeof(command))) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
} else if (!host_append_env_list_command(command, sizeof(command))) {
printf("Command is too long\n");
return HOST_RETURN_ERROR;
}
return host_print_command_output(command);
}

printf("Unknown environment command\n");
print_usage();
return HOST_RETURN_ERROR;
}
Loading