2 unstable releases
0.2.0 | Oct 11, 2023 |
---|---|
0.1.0 | Aug 31, 2023 |
#370 in Configuration
22KB
163 lines
EnvShim
EnvShim is a symlink shim to load executables with user-defined environment variables. Refer next section for more details on what this means.
Status: This project is active and a 1.0 release is planned. It currently has all the features I personally expect from it and is of beta quality. However, it will be in 0.x version for a while to identify any bugs or essentially needed features. Not a lot of features will be added, since that may slow down program and delay the loading of the final application.
EnvShim in detail
The problem: A big issue on a GNU/Linux desktop is that there are so many incompatible ways to
define environment variables. A cursory search indicates /etc/profile.d/
, .bashrc
, ~/.profile
,
~/.xprofile
, ~/.config/environment.d/envvars.conf
, /etc/environment
and numerous other
locations. There is no reliable method to define all the variables in one place and have all the
applications pick them up. There are also surprising ways in which desktop managers like SDDM and
GDM process these variables. Some desktop environments like Gnome and KDE force a standard way of
defining users' environment variables. However, it's still an issue on window managers like sway or
awesome.
The solution: EnvShim aims to provide a way for users to define their variables in a single
source of truth (~/.config/envshim/script
file) and ensure that the desired applications pick it
up.
The way EnvShim solves this is by acting as a loader shim for the desired target applications. For
this, symlinks to the envshim
executable is with the same name as the target application is placed
in directory that has precedence over the actual target application in the $PATH variable. Consider
an example using the sway executable:
_# printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/bin
_# which sway
/usr/bin/sway
_# which envshim
/usr/local/bin/envshim
_# ln -sr /usr/local/bin/envshim /usr/local/bin/sway
_# rehash
_# which sway
/usr/local/bin/sway
In the above case, /usr/local/bin
has a higher precedence than /usr/bin
. Therefore, when we try
to execute sway, envshim
will be invoked via the symlink in /usr/local/bin
instead of
/usr/bin/sway
. Envshim then takes care of initializing the variables and then invoking the target
(/usr/bin/sway
).
User settings: The second requirement for this to work is a file where the variables are
declared. This has to created by the user in their home directory under
$XDG_CONFIG_HOME/envshim/script
. If $XDG_CONFIG_HOME
is undefined, the default location is
assumed - ~/.config/envshim/script
.
The script
file is a shell script written for a shell (like sh
or bash
) of user's choice. At
the time of shim loading, envshim
invokes that shell as a subprocess and feeds the content of the
script to it. Envshim then reads the result of the script execution and uses it to define the
environment for the target application. Envshim then exec
s into the target application, replacing
itself with the target application in the process.
Building
Clone this repository and cd into it. Then issue the normal cargo
command to build it. Copy the
executable to the desired location afterwards.
git clone https://git.sr.ht/~gokuldas/envshim
cd envshim
cargo build --release
sudo cp target/release/envshim /usr/local/bin
Configuration
There are two steps in the configuration process:
1. Script file: The user has to create a script file at $XDG_CONFIG_HOME/envshim/script
. It
doesn't need an executable permission. The first line is a shebang line indicating the shell to
use and configured to accept input from stdin. The following are some options:
#!/usr/bin/sh -s
#!/usr/bin/bash -s
#!/usr/bin/zsh -s
Fill the script file to print the necessary variables in a VAR=value
format, one variable per
line. This can be done using echo
, for example. If it's desired to print out all the environment
variables at once, printenv
command does the job. Just remember to export
the variables before
using printenv
. For example:
export PATH=$HOME/.local/bin:$PATH
printenv
echo 'ENVSHIM_MARKER=envshim'
A sample of this file is provided as assets/script
in this repo.
2. Create shims: Shims are symlinks with the same name as the target and pointing to envshim
executable. The important matter here is to ensure that the shims come first in $PATH before the
target executable. For example, if PATH=/usr/local/bin:/usr/bin
and the target application is
/usr/bin/sway
, then /usr/local/bin/sway
is reasonable choice for the shim. Another matter to
note is that PATH variable mentioned here is what you get before shim loading. Don't depend on paths
defined in the script file. Have a look at the example given in 'EnvShim in detail' section.
Which applications should be chosen for shim loading? There are two guidelines that can help decide.
- Any application for which you want to ensure the correct variables
- Any application that is the parent process of most other applications
Shim loading adds a delay time to the loading of the target application, since a shell has to be run before it. The second guideline helps to reduce such delays by doing shim loading fewer times and then passing on the result to as many other processes as possible. Here are some possible candidate for shim loading:
- Shells (like bash or zsh)
- Window managers (like sway or awesome)
Troubleshooting
Envshim is designed to run the target application in any of the cases where the target is available. This means that the target will run even if the shell or the script fails or is missing. However, the environment variables that the target receives may not be what you expect. It's designed like this to avoid making the target application inaccessible in case of any other error. You wouldn't want your shell or window manager to be inaccessible because of a missing or misconfigured script.
If you suspect such a fail-safe shim load, you should try running the application from a command shell. EnvShell prints error messages on stderr if it encounters any problem.
Contributing
Suggestions and contributions are welcome through the mailing list. Refer to the Contributor Guidelines and Project Policies page of my free software index for details on how to contribute. Meanwhile, the following additional guidelines apply:
- Format your code with
rustfmt
before submission- The text width for markdown documents is 100
- The patches must be signed-off (
git commit -s
) - Set up the cloned local repository with the following configuration:
git config format.to "~gokuldas/projects@lists.sr.ht"
git config format.subjectPrefix "PATCH EnvShim"
git config format.coverLetter auto
git config format.useAutoBase true
git config format.signOff true
License
envshim: Symlink shim to load executables with user-defined environment variables
Copyright (C) 2023 Gokul Das B
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
Dependencies
~4–14MB
~183K SLoC