Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exporting engine definition to other bash instances #50

Open
wants to merge 24 commits into
base: master
Choose a base branch
from

Conversation

brainchild0
Copy link
Contributor

The submitted revisions add several functions and accompanying tests.

The functions support the case of invoking the template engine in Bash instances other than the one that originally sourced the distribution file giving the function definitions.

The need arose from a use case of running the engine in a clean environment, free from any possible contamination from other sources, but still having the functionality of the template engine.

Support for such a case is provided most flexibly and robustly by the new moDeclare function, which prints the declarations of the functions defined in the source file relying only on environment, not the original file. A Bash instance may process this output in order to acquire the functionality of the engine from the environment of a parent, or any other Bash process, without inheriting environment or reading a source file.

Other included functions are the following:

  • The function moExport marks all functions and variables defined by the source file for export to the environment of descendants.
  • The function moUnexport reversed the effect of moExport, marking these functions and variables as not for export.
  • The function moUnload removes all shell functions and variables provided by the source file. It reverses the effect of sourcing the file.

All functions explained above are suitable and intended for public use.

Two further functions, moListFuncs and moListVars are intended for use internally, but harmless for public use.

@fidian
Copy link
Contributor

fidian commented Jan 26, 2022

I'm having difficulty understanding the need for this functionality. If I were to include this code, it seems that it would only get used extremely rarely. Could you please elaborate on the following points?

  1. Why is sourcing a file a worse option than exporting and importing functions between Bash instances?
  2. Can you explain the scenario more so I can better understand the problem you're facing?
  3. Shouldn't this be made into a more generic tool and kept separate from this repository? Maybe something that would take a snapshot of the environment, then you'd source a file, then take a second snapshot and it would write out the differences so you could export everything to your second instance?

@brainchild0
Copy link
Contributor Author

brainchild0 commented Jan 26, 2022

I understand your reluctance, but ultimately, I feel the enhancements apply widely to general use cases, and solve problems that are not easily resolved externally.

Sourcing the same file in each instance is not an optimal solution. Once the functionality is imported into the Bash environment, it should be available to child processes without re-importation from the original source file. Normally, environment may be accessed by children through inheritance, but templates are a special case, introducing concerns that are not common in shell scripting contexts, because a template is a dumb file that can integrate any data from the environment, even if undesirable, because of name collisions, or security or privacy concerns. When templates are user supplied, not included in the same application that runs the template engine, these concerns become especially salient. A compelling case emerges for limiting environmental contaminants from the parent process (which may be helped by invocations such as env -i), yet transferring specifically the needed tools to the new, clean environment. The new functionality allows the child-parent relationship to emulate inheritance, while ensuring that unwanted elements of the environment are not inherited by default.

I have begun to develop further enhancements that build on the work just submitted, to help fully harness its true potential. The ultimate objective is to provide an accessible and reusable interface for invoking the template engine in an environment that is fully determined by the invocation parameters. I believe such enhancements incorporated into the tool as a complete package carry the project to a more highly-evolved state.

Generally, four operations would contribute to a complete solution for moderating between a shell environment and a template engine:

  1. Clear the environment before invoking the template engine.
  2. Introduce the template engine into the cleared environment.
  3. Populate the environment with template data, only the specific fields required by the templates.
  4. Ignore environment variables automatically populated by Bash, when the template engine selects data for interpolation.

The current revisions satisfy only (2), which by itself offers some but limited overall enhancement for the full use case.

The further work would process a mapping table supplied on invocation, which would list variables in the environment intended to be used by the templates, and for each, an optional mapping to a new name, the one referenced in the template. The system would generate declarations of the limited set of variables, with name translations, to be read by another Bash instance, without inheriting the environment the environment of the parent.

Fully automating the process of building the child shell, and generating the declarations it needs for processing a target template file would be a valuable and core enhancement to the project. It would support important functionality that is infeasible to be managed by the invoking application or an external tool.

The enhancements do not degrade the performance or usability of the existing design, or violate any constraints on size. I think the core issue is a concern for feature bloat, but I think the supported cases are central to general use, and provide benefit even to those who currently are not depending on them.

@fidian
Copy link
Contributor

fidian commented Feb 1, 2022

I've rolled this over for a while but still don't understand why sourcing mo is unacceptable. Could you describe the scenario where you can copy some data from the environment but are unable (or unwilling) to source a file?

I think you could accomplish most of this with a shell script. If this doesn't work for you, I think you might need to help clue me into your use case.

By the way, exposing templates to users directly is a bad idea. Lots of stuff is executed blindly because it is difficult or impossible to ensure the user isn't doing something malicious.

#!/usr/bin/env -S -i bash --noprofile --norc

# Clean more of the environment
while read -r line; do
    var=${line%%=*}
    case "$var" in
        PWD | SHLVL | _ )
            ;;

        *)
            unset "$var" 2> /dev/null || :
    esac
done < <(set)

unset line
unset var

# Load mo, load data
. path-to/mo
. path-to/data

# Process template
mo path-to/template

@brainchild0
Copy link
Contributor Author

brainchild0 commented Feb 2, 2022

Invoking the original source file from the subshell is not robust because it requires the subshell to utilize the same source file as the parent, rather than allowing it to inherit values, as normally occurs in parent-child shell relations. The proposed solution ensures that the child would carry the same definitions as the parent, insulated from the details of the method of the parent having loaded the definitions, which might not have been as plain as invoking the command source mo over the same search path and view of the file system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants