first commit
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 25 Nov 2024 12:06:25 +0000 (12:06 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 25 Nov 2024 12:06:25 +0000 (12:06 +0000)
60 files changed:
.gitignore [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README.md [new file with mode: 0644]
developer/amd64/home [new file with mode: 0755]
developer/amd64/user [new file with mode: 0755]
developer/amd64/user-stem [new file with mode: 0755]
developer/amd64/user-subu [new file with mode: 0755]
developer/bash/Z [new file with mode: 0755]
developer/bash/bashrc [new file with mode: 0644]
developer/bash/cat_w_fn [new file with mode: 0755]
developer/bash/githolder [new file with mode: 0755]
developer/bash/rm_tilda_files_tree [new file with mode: 0755]
developer/bash/vl [new file with mode: 0755]
developer/cc/home.cli.c [new file with mode: 0644]
developer/cc/user-stem.cli.c [new file with mode: 0644]
developer/cc/user-subu.cli.c [new file with mode: 0644]
developer/cc/user.cli.c [new file with mode: 0644]
developer/deprecated/iseq_C/LICENSE [new file with mode: 0644]
developer/deprecated/iseq_C/README.md [new file with mode: 0644]
developer/deprecated/iseq_C/makefile [new file with mode: 0644]
developer/deprecated/iseq_C/user-stem.c [new file with mode: 0644]
developer/deprecated/iseq_C/user-subu.c [new file with mode: 0644]
developer/deprecated/makefile [new file with mode: 0644]
developer/deprecated/release/make/environment.h [new file with mode: 0644]
developer/deprecated/release/make/makefile [new file with mode: 0644]
developer/deprecated/release/make/makefile-environment [new file with mode: 0644]
developer/deprecated/release/repo/repo [new file with mode: 0755]
developer/deprecated/release/repo/repo_pull [new file with mode: 0755]
developer/deprecated/release/repo/repo_push [new file with mode: 0755]
developer/deprecated/release/util/rm_tilda_files_tree [new file with mode: 0755]
developer/deprecated/repo/repo [new file with mode: 0755]
developer/deprecated/repo/repo_pull [new file with mode: 0755]
developer/deprecated/repo/repo_push [new file with mode: 0755]
developer/deprecated/subu_setup [new file with mode: 0644]
developer/deprecated/subu_systemd [new file with mode: 0755]
developer/emacs/emacs.el [new file with mode: 0644]
developer/make/RT_0.h [new file with mode: 0644]
developer/make/environment_RT_0 [new file with mode: 0644]
developer/make/targets [new file with mode: 0644]
developer/nautilus/Decrypt [new file with mode: 0644]
developer/nautilus/Encrypt [new file with mode: 0644]
developer/nautilus/README.md [new file with mode: 0644]
developer/python3/gen_email [new file with mode: 0755]
developer/python3/gen_passwd [new file with mode: 0755]
developer/python3/gen_sig [new file with mode: 0755]
developer/scratchpad/.gitignore [new file with mode: 0644]
developer/tool/env [new file with mode: 0644]
developer/tool/make [new file with mode: 0755]
developer/tool/makefile [new file with mode: 0644]
developer/tool/release [new file with mode: 0755]
env_administrator [new file with mode: 0644]
env_developer [new file with mode: 0644]
tool/env [new file with mode: 0644]
tool_shared/bespoke/cat_w_fn [new file with mode: 0755]
tool_shared/bespoke/env [new file with mode: 0644]
tool_shared/bespoke/githolder [new file with mode: 0755]
tool_shared/bespoke/version [new file with mode: 0755]
tool_shared/bespoke/vl [new file with mode: 0755]
tool_shared/third_party/.gitignore [new file with mode: 0644]
tool_shared/third_party/upstream/.gitignore [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8783d88
--- /dev/null
@@ -0,0 +1,5 @@
+
+.*
+!.gitignore
+*~
+temporary
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..8fcce09
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020,2024 Thomas Walker Lynch
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..58ce2a5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,734 @@
+|2022-02-26|` `TWL|brought the README.md into doc/README.odt (still converting), then using online tool to convert the pdf to README.md|\r
+| :-: | :- | :- |\r
+||||\r
+\r
+**The ‘resources’ Project**\r
+1. # **What is it?**\r
+A set of scripts used for the projects found in github.com/thomas-walker-lynch and other places where it has been adopted.  These apply to C, C++, Python, Django, Rust, Lisp, etc. This replaces any other script you might be accustom to for entering a ‘virtual environment’.  \r
+\r
+|setup|sets up the environment for a project|\r
+| :- | :- |\r
+|pull|fancy shortcut for git pull|\r
+|push|fancy shortcut for git push|\r
+|makefile|a genetic makefile for C/C++ projects|\r
+|makefil-env|default variables for make|\r
+\r
+These scripts  have been evolving with each project, so tweaks might be required.\r
+\r
+Assume we have a top level directory called repos, and we have expanded resources\r
+\r
+/home/Thomas/repos/\r
+\r
+`  `resources\_repo/\r
+\r
+`    `bin/<br>\r
+\r
+`    `include/\r
+\r
+`    `lib/\r
+\r
+`    `media/\r
+\r
+`    `tmp/\r
+\r
+`    `LICENSE\r
+\r
+`    `README.md\r
+\r
+`    `projects-init.sh\r
+\r
+1. # **Modifying the resources repo**\r
+If you make some changes and are testing them, then do that on a branch. Merge the branch after it is tested.\r
+\r
+If you do something to the resources repo of general interest, then check it in to master.\r
+\r
+If you need special modifications specific to your needs, i.e. not of general interest even to those who might come in the future and be working in the same language, etc., then make your very own branch.\r
+\r
+` `If you have a fundamentally different way of going about this, some people want it, others don't - then that goes on a branch.\r
+\r
+1. # **Your local directory for holding project, ‘repos’**\r
+\r
+1. make a top level directory for holding all the repos you work on, independent of language, etc.\r
+\r
+` `> mkdir ~/repos\r
+\r
+1. expand the system  repo, then inspect and install those script in the system\r
+\r
+\> cd ~/repos\r
+\r
+\> git clone git@github.com:Thomas-Walker-Lynch/system\r
+\r
+Follow the directions from the system repo for installing home, user, and Z.  There is not really much to it. ‘Z’ is used for timestamps.  home returns the home directory from /etc/passwd.\r
+\r
+1. expand the resources repo\r
+\r
+`  `> cd ~/repos\r
+\r
+`  `> git clone git@github.com:Thomas-Walker-Lynch/resources\r
+\r
+1. add the following to .bashrc.  Note the file lib/bashrc to get started.\r
+\r
+` `> export PATH=~/repos/resources/bin:"$PATH"\r
+\r
+\r
+1. # **The setup script**\r
+\r
+`    `This command will open a new shell with the environment in that shell setup for the project.\r
+\r
+`      `2022-02-25T13:06:24Z\r
+\r
+`      `lander10@beast§~/§\r
+\r
+`      `> setup Endian\r
+\r
+`      `Hello Emacs\r
+\r
+`      `/home/Thomas/repos/bin:/home/Thomas/repos/resources/bin:/usr/local/bin:/usr/bin:/bin\r
+\r
+`      `2022-02-25T13:06:28Z [Endian]\r
+\r
+`      `lander10@beast§~/repos/Endian§\r
+\r
+`      `>\r
+\r
+Currently <tt>setup</tt> echos the path so that they user will understand where the executables\r
+\r
+come from.\r
+\r
+The prompt carries sufficient information for making sense of the transcript when it is read later.\r
+\r
+On the first line, the time shown is UTC in standard iso8601 format. This comes from the ‘/usr/bin/Z’ script.\r
+\r
+Following the time, in square brackets you will see the name of the project. If the square brackets are not there, then no project environment has been setup.  If a user attempts to work on a project that has not been setup, he or she is likely to experience many errors.\r
+\r
+On the second line we have the user name, machine name, and current working directory.\r
+\r
+On the third line the familiar `>` appears. Anything you type after the prompt is taken as the command for the shell. It is conventional for script run as root user that this will instead be '#'.\r
+1. # **The generic makefile**\r
+\r
+`  `By default a C/C++ project wil have this directory structure:\r
+\r
+`    `~/repos/\r
+\r
+`         `Endian/\r
+\r
+`             `deprecated/\r
+\r
+`             `doc/\r
+\r
+`             `exec/\r
+\r
+`             `lib/\r
+\r
+`             `src/\r
+\r
+`             `test/\r
+\r
+`             `tmp/\r
+\r
+`             `try/\r
+\r
+`             `LICENSE\r
+\r
+`             `makefile\r
+\r
+`             `makefile-env\r
+\r
+`         `resources/\r
+\r
+`         `system/\r
+\r
+`         `tmp/\r
+\r
+Note <tt>makefile</tt> and <tt>makefile-env</tt> inside the Endian project are there only to override defaults on  the <tt>resources</tt> versions of those files. They are stubs tweak a couple of things and then pass the heavy  lifting to <tt>resources/lib/makefile</tt> and <tt>resources/lib/makefile-env</tt>.  Leave the  <tt>resources/lib/makefile</tt> and <tt>resources/lib/makefile-env</tt> where they are and do not make copies.\r
+\r
+Give source files two suffixes. For example the Endian project source directory appears as:\r
+\r
+`     `2022-02-26T10:54:55Z [Endian]\r
+\r
+`     `thomas@beast§~/resources§\r
+\r
+`     `> cd $PROJECT\_HOME\r
+\r
+`     `2022-02-26T10:55:47Z [Endian]\r
+\r
+`     `thomas@beast§~/Endian§\r
+\r
+`     `> ls src\r
+\r
+`     `endian.lib.c  endian\_test.cli.c  ip4.lib.c  ip4\_test.cli.c\r
+\r
+Endian is a C project. For C++ sources the suffix will be <tt>.cc</tt>.  I suppose the generic makefile should  be improved by adding a variable to configure the string used for suffixes.  Right now I think this convention is hard coded.\r
+\r
+The compiled lib files will go into <tt>lib/$PROJECT\_lib.a</tt> while the cli files will be made stand alone and appear in the <tt>exec</tt> directory.  Presumably all the <tt>.cli.c</tt> files have a main function defined.\r
+1. # **Push and pull scripts**\r
+These are git command sequence shortcuts.  They do the usual things when pushing and pulling from  a git repo and also do some checks.\r
+1. # **Other things**\r
+`     `Other useful things will be found in the resource tree.\r
+1. # **Projects with submodules**\r
+\r
+`  `By convention, projects with submodules have the suffix <tt>\_ensemble</tt>.\r
+\r
+`  `1. install the project\r
+\r
+`    `Suppose the project with submodules is called <project>\_ensemble\r
+\r
+`      `> cd ~/repos\r
+\r
+`      `> git clone git@github.com/<user>/<project>\_ensemble.git\r
+\r
+`      `> mv <project>\_ensemble <project>\_master\r
+\r
+`      `> cd <project>\_master\r
+\r
+`    `Note in the line that moves the cloned repo directory to `<project>\_master`, you might\r
+\r
+`    `use a different suffix than `master`.  Conventionally the suffix is the branch to be\r
+\r
+`    `checked out and worked on, but the scripts do not care what it is set to. Inside the\r
+\r
+`    `scripts this suffix is called the project ‘version’.  If this checkout is for\r
+\r
+`    `working on multiple branches, just leave the <tt>\_ensemble</tt>.\r
+\r
+`  `2. for submodules that have not yet been added:\r
+\r
+\r
+`      `> git submodule add https://github.com/../<resource\_project>\r
+\r
+`      `> git submodule add https://github.com/../<resource\_project>\r
+\r
+`      `...\r
+\r
+\r
+`     `Etc. for the other modules\r
+\r
+`  `3. if a submodule is empty, then do the following:\r
+\r
+`      `> git submodule init\r
+\r
+`      `> git submodule update\r
+\r
+\r
+`     `Submodules directories will be empty when the `--recursive` switch is not provided with\r
+\r
+`     `the clone. Actually, I prefer not to use `--recursive` and then to follow up with an\r
+\r
+`     ``init` and `update` so that it is easier to tell what caused errors.\r
+\r
+1. # **## generally about project security**\r
+\r
+`  `0. Contain your development work\r
+\r
+`    `Consdider giving the repos directory its own user.  If you do add this link so that\r
+\r
+`    `the scripts can still have a 'repos' target.\r
+\r
+`    `> ln -s . repos\r
+\r
+\r
+`    `Alternatively put them in a container or a virtual machine.\r
+\r
+`  `1. audit source files and legible scripts\r
+\r
+`    `Watch what git pulls.  For new things that are source code or scripts, audit those.\r
+\r
+`    `Note! ‘.gitignore’ does not apply to pulled content.\r
+\r
+`  `2. hidden files\r
+\r
+`     `Files that should be audited must not be hidden.  Otherwise they are too easy to miss during\r
+\r
+`     `the audit.\r
+\r
+`     `Hidden files are not seen by file globs, so does not see the <tt>.gitignore</tt> file.\r
+\r
+\r
+`      `> ls -ld \*\r
+\r
+`      `drwxrwx---. 1 thomas thomas    64 2022-02-26 07:55 bin\r
+\r
+`      `drwxrwx---. 1 thomas thomas   142 2022-02-26 07:03 lib\r
+\r
+`      `-rw-rw----. 1 thomas thomas  1076 2022-02-25 07:25 LICENSE\r
+\r
+`      `drwxrwx---. 1 thomas thomas    20 2022-02-25 07:25 media\r
+\r
+`      `-rw-rw----. 1 thomas thomas   141 2022-02-25 07:25 projects-init.sh\r
+\r
+`      `-rw-rw----. 1 thomas thomas 18209 2022-02-26 08:02 README.md\r
+\r
+`      `drwxrwx---. 1 thomas thomas    84 2022-02-26 05:40 tmp\r
+\r
+\r
+`    `Globs not seeing hidden files is generally considered to be a good thing when we do not want usual shell operations\r
+\r
+`    `to see it.  For example <tt> cp \* </tt> a repo manually we often want a copy of the project, not a copy of the repo\r
+\r
+`    `administrative files.  There is a separate command for copying a repo, <tt> git clone </tt>.\r
+\r
+`    `If we want to 'unhide' dot file from a file glob, then we rename it.  That is best. In the case <tt>.gitignore</tt>\r
+\r
+`    `<tt>git</tt> is expecting to see the file with that very name.  If we make a file that is not hidden and then\r
+\r
+`    `link <tt>.gitignore</tt> to it, git will yell at us "too many symbolic links!".\r
+\r
+`     `Hence, we can expose a file like <tt>.gitignore</tt> by linking to it (rather than the other way around).\r
+\r
+`     `When doing this, typically the link name is the same but without the dot in front of it.  Here I expose the\r
+\r
+`     `<tt>.gitignore</tt>.  \r
+\r
+\r
+`      `2022-02-26T13:02:28Z [Endian]\r
+\r
+`      `thomas@beast§~/resources§\r
+\r
+`      `> ln -s .gitignore gitignore\r
+\r
+`      `And now the file glob will pick it up.\r
+\r
+\r
+`      `2022-02-26T13:07:13Z [Endian]\r
+\r
+`      `thomas@beast§~/resources§\r
+\r
+`      `> ls -ld \*\r
+\r
+`      `drwxrwx---. 1 thomas thomas    64 2022-02-26 07:55 bin\r
+\r
+`      `lrwxrwxrwx. 1 thomas thomas    10 2022-02-26 08:07 gitignore -> .gitignore\r
+\r
+`      `drwxrwx---. 1 thomas thomas   142 2022-02-26 07:03 lib\r
+\r
+`      `-rw-rw----. 1 thomas thomas  1076 2022-02-25 07:25 LICENSE\r
+\r
+`      `drwxrwx---. 1 thomas thomas    20 2022-02-25 07:25 media\r
+\r
+`      `-rw-rw----. 1 thomas thomas   141 2022-02-25 07:25 projects-init.sh\r
+\r
+`      `-rw-rw----. 1 thomas thomas 20454 2022-02-26 08:14 README.md\r
+\r
+`      `drwxrwx---. 1 thomas thomas    84 2022-02-26 05:40 tmp\r
+\r
+\r
+`  `2. PATH\r
+\r
+`     `Do not put a repo in your execution PATH.  When running tests and such call them out locally, <tt>./program</tt>,\r
+\r
+`     `or through one of the environment variables initialized by the <tt>setup</tt>.\r
+\r
+`     `The <tt>~/repos/resources/bin</tt> directory is an exception to this. We need to maintain the executables used for\r
+\r
+`     `maintaing the projects themselves. Be careful to audit any changes to this <tt>resources</tt>.\r
+\r
+`  `3. pulled binary executbles\r
+\r
+`    `It is best to not pull binary executables then run them, because they can not be audited.\r
+\r
+`    `It sometimes happens that a co-developers will compile and create an executable, and then not clean it, and then\r
+\r
+`    `accidentally the user poisons the repo with them.  Watch your pulls and clones, and remove executables from the\r
+\r
+`    `repo, and complain about them. The generic makefile, push, and pull scripts can help with this.\r
+\r
+`    `When an unauditable executable arrives in a pull it creates a trust problem.  We distrist both the\r
+\r
+`    `source and the integrity of the distribution process.  This latter problem can be mitigated if\r
+\r
+`    `cryptographic signatures are independently available.\r
+\r
+`    `Consider running such an executable in a container.\r
+\r
+`    `Make sure make your clean targets remove executables before a push.\r
+\r
+`    `Be careful with the programs in <tt>resources/bin</tt>.\r
+\r
+`  `4. check for the .gitignore and audit it, add to it\r
+\r
+`   `If you add the <tt>exec</tt>  or  <tt>bin</tt> directories to gitignore and then forget to\r
+\r
+`   `run make clean, it might prevent accidentally adding executables.\r
+\r
+`   `Typical .gitignore files:\r
+\r
+`        `env/\r
+\r
+`        `tmp/\r
+\r
+`        `.\*\r
+\r
+`        `!.gitignore\r
+\r
+`        `\*~\r
+\r
+`    `For a C or C++ project home directory we will also ignore various intermediate files,\r
+\r
+\r
+`        `tmp/\r
+\r
+`        `bin/\r
+\r
+`        `exec/\r
+\r
+`        `.\*\r
+\r
+`        `!.gitignore\r
+\r
+`        `\*~\r
+\r
+`        `\*.o\r
+\r
+`        `\*.i\r
+\r
+`        `\*.s\r
+\r
+`        `a.out\r
+\r
+\r
+`    `For a python project:\r
+\r
+`        `tmp/\r
+\r
+`        `.\*\r
+\r
+`        `!.gitignore\r
+\r
+`        `\_\_pycache\_\_/\r
+\r
+`        `\*\*/\*.pyc\r
+\r
+\r
+`      `And for a django project:\r
+\r
+\r
+`        `tmp/\r
+\r
+`        `.\*\r
+\r
+`        `!.gitignore\r
+\r
+`        `\_\_pycache\_\_/\r
+\r
+`        `\*\*/\*.pyc\r
+\r
+`        `manage.py\r
+\r
+`        `\*\*/migrations\r
+\r
+`        `.vscode\r
+\r
+\r
+\## General info and concepts\r
+\r
+`  `### What is a ‘project’\r
+\r
+`  `The term ‘project’ occurs repeatedly in this document and generally when we talk about code, so it is best to start by\r
+\r
+`  `nailing that term down.  Generally speaking, a ‘project’ has a well defined final product, along with a list resource\r
+\r
+`  `needs, tasks, task dependencies, and a tasks schedule.  It is the job of the team members to execute said tasks.\r
+\r
+`  `In project management parlance, a group of related projects is called a ‘program’. Well that sure is an unfortunate\r
+\r
+`  `choice of terminology for us CS people, so instead we will call a group of related projects a ‘project ensemble’.  A\r
+\r
+`  `project ensemble itself is also a kind of project, where the tasks are the component projects.  Hence we have a\r
+\r
+`  `recursive structure. CS people like recursive structures ;-)\r
+\r
+`  `Projects are held in git repositories, as project ensembles are also projects, they are also held in git\r
+\r
+`  `repositories. When we clone a project ensemble we will find other git repositories have been expanded inside the\r
+\r
+`  `directory tree.  Those are for the component projects.  In git speak we call these component project directory trees\r
+\r
+`  `‘submodules’.\r
+\r
+`  `When a project ensemble is expanded out, we end up with a directory tree structure where project resources, tools, and\r
+\r
+`  `work products are stored.\r
+\r
+\r
+1. # `  `**### Where project code goes**\r
+`  `--------\r
+\r
+`  `On a typical project we will have three distinct types of code:\r
+\r
+`  `1. the application source code\r
+\r
+`  `2. the libraries and other resources the application makes use of\r
+\r
+`  `3. the tools used for building the source code\r
+\r
+`  `Let's give these code types short names:\r
+\r
+`  `1. source\r
+\r
+`  `2. resources\r
+\r
+`  `3. tools\r
+\r
+`  `We have various places where we might put code that we need in a program:\r
+\r
+`  `1. in the system\r
+\r
+`  `2. in the developer's user directory\r
+\r
+`  `3. in a project ensemble\r
+\r
+`  `4. in a project's home directory.\r
+\r
+\r
+`  `We shorten this list of places to:\r
+\r
+`  `1. system\r
+\r
+`  `2. user\r
+\r
+`  `3. ensemble\r
+\r
+`  `4. project\r
+\r
+`  `Now combining our code and locations into one list:\r
+\r
+`  `1. source\r
+\r
+`     `1. project\r
+\r
+`  `2. resources\r
+\r
+`     `1. system\r
+\r
+`     `2. user\r
+\r
+`     `3. ensemble\r
+\r
+`  `3. tools\r
+\r
+`     `1. system\r
+\r
+`     `2. user\r
+\r
+`     `3. ensemble\r
+\r
+`  `So there is only one place we will find the application source code that we are\r
+\r
+`  `developing, and that is under the project directory. Resources that we may need in\r
+\r
+`  `order to compile our code will be found either in the system, the user directory, or in\r
+\r
+`  `the ensemble. The same can be said for the tools we will use.\r
+\r
+`  `This is what my home directory looks like:\r
+\r
+`  `/home/thomas/\r
+\r
+`    `bin/\r
+\r
+`    `Desktop/\r
+\r
+`    `Documents/\r
+\r
+`    `Downloads/\r
+\r
+`    `repos/\r
+\r
+`      `chessgame/\r
+\r
+`      `resources/  <--- resources for all projects - expand this repo here\r
+\r
+`          `LICENSE\r
+\r
+`          `README.md\r
+\r
+`          `bin/\r
+\r
+`              `makefile-cc\r
+\r
+`              `pull\r
+\r
+`              `push\r
+\r
+`              `rm\_tilda\_files\_tree\r
+\r
+`              `setup\r
+\r
+`      `subu/\r
+\r
+`      `tm/\r
+\r
+`      `ws4\_master/   <--- an ensemble directory\r
+\r
+`        `LICENSE\r
+\r
+`        `README.md\r
+\r
+`        `env/  <--- resources specific to the ensemble (wish this was called ‘resources’\r
+\r
+`            `bin/\r
+\r
+`            `lib/\r
+\r
+`            `include/\r
+\r
+`        `tmp/\r
+\r
+`        `uWebSockets/ <--- resource project directory\r
+\r
+`        `ws4/   <--- target project directory\r
+\r
+`  `Now looking under my `projects` directory, and expanding out `ws4\_master`:\r
+\r
+\r
+`     `ws4\_master/\r
+\r
+`       `LICENSE\r
+\r
+`       `README.md\r
+\r
+`       `env/\r
+\r
+`          `bin/\r
+\r
+`          `include/\r
+\r
+`          `lib/\r
+\r
+`       `tmp/\r
+\r
+`       `uWebSockets/\r
+\r
+`       `ws4/\r
+\r
+\r
+`  ``ws4\_master` is a project ensemble. The component projects include `uWebSockets` and\r
+\r
+`  ``ws4`. This project ensemble also comes from a git repo.\r
+\r
+`  ``ws4\_master/ws4` is the home directory for the project this team is actively working on.\r
+\r
+`  `We know it is the active project because it has the same name as the ensemble prefix.\r
+\r
+`  `Whereas `ws4\_master/uWebSockets` is someone else's github project. There are other people\r
+\r
+`  `working that, but it is not us, and it is being developed in a different\r
+\r
+`  `environment. Rather we are just making use of the work product of that project.\r
+\r
+`  `Also inside of `ws4\_master` we have a directory called `env`. Frankly, I don't like the\r
+\r
+`  `name.  I have toyed with calling it `project-share`, but `env` is the name that Python and others\r
+\r
+`  `expect.  Perhaps make it a symbol link?  This directory is used to hold project specific\r
+\r
+`  `resources and tools.  Note that the contents of `env` are \*not\* pushed to the repo. This\r
+\r
+`  `means that custom edits you make to scripts will not be backed up to the repo.  I also do\r
+\r
+`  `not like `env` because it is not pushed to the repo, but it might be \*pulled\* from it.\r
+\r
+`  ``.gitignore` does not affect pulls.  This is a security hazard.\r
+\r
+\r
+1. # **## Repo and Directory Naming (again)**\r
+\r
+`  `If a repo has submodules in it, I generally give the repo name a suffix of ‘\_ensemble’.\r
+\r
+`  `After cloning, if I am only going to work on a given breanch within that clone, I will change\r
+\r
+`  `the suffix to the branch name,  <project>\_<branch>.\r
+\r
+`  `So you ask why do we need more than one directory for the same repo? Well in this case I\r
+\r
+`  `am running a web server against the v2.0 branch, and it needs to see the files the v2.0.\r
+\r
+`  `The v1.0 directory was the one that was formally being served. There are no servers\r
+\r
+`  `pointed at it now, so I should probably delete it.  If I ever need v1.0 again I can always\r
+\r
+`  `check it out.\r
+\r
+`  `> cd ~/repos\r
+\r
+`  `> ls\r
+\r
+`      `customer\_gateway\_master\r
+\r
+`      `customer\_gateway\_v1.0\r
+\r
+`      `customer\_gateway\_v2.0\r
+\r
+\r
+`  `This is how the `customer\_gateway\_master` project environment directory was made:\r
+\r
+\r
+`  `> cd ~/repos\r
+\r
+`  `> git clone --recursive --jobs 8 git@github.com:Reasoning-Technology/customer\_gateway\_ensemble.git\r
+\r
+`  `> mv customer\_gateway\_ensemble customer\_gateway\_master\r
+\r
+`  `When downloading a `<project>\_ensemble` repo, we can expand the submodules at the same time\r
+\r
+`  `by including the --recursive switch, as was shown above.  If the `--recursive` switch\r
+\r
+`  `is not given, the submodules will have to be initialized and updated.\r
+\r
+`  `The second directory was then created with the commands:\r
+\r
+\r
+`  `> git clone --recursive --jobs 8 git@github.com:Reasoning-Technology/customer\_gateway\_ensemble.git\r
+\r
+`  `> mv customer\_gateway\_ensemble customer\_gateway\_v1.0\r
+\r
+`  `> cd customer\_gateway\_v1.0\r
+\r
+`  `> git checkout v1.0\r
+\r
+\r
+`  `Cloning a `git` repository produces a directory tree, which in git speak is\r
+\r
+`  `apparently called a `module`.\r
+\r
+`  `We may `cd` into a module and clone another module, this will be called a ‘submodule’.  A\r
+\r
+`  `submodule clone operation requires a special command so that the module will know it is\r
+\r
+`  `there:\r
+\r
+\r
+`  `git submodule add <repo>\r
+\r
+\r
+`  `We might do this because our project depends on other projects, and those other projects\r
+\r
+`  `have their own git repositories, or because we are developing more than one project\r
+\r
+`  `together with one shared environment.\r
+\r
+`  `We then use the submodule just like we would use any other git module.  I.e. after we make\r
+\r
+`  `changes we must add the changes, then commit them, and then push the submodule.\r
+\r
+`  `The parent module only sees the submodule changes when there is a commit in the\r
+\r
+`  `submodule.  Hence, after there is a commit in a submodule, we must go up to the module, and\r
+\r
+`  `then add the submodule, commit, then push the module.\r
+\r
+`  `We truly have two layers, and we have to maintain them individually. Luckily we have some\r
+\r
+`  `scripts so that we don't to type stuff twice. In the `project-share` project there are two\r
+\r
+`  `scripts, one called `push` the other called `pull`.  When we run the `push` script it goes\r
+\r
+`  `into the project home and does an add, commit, and push.  It then goes up to the ensemble\r
+\r
+`  `directory and `git add`s the project submodule, commits the change, and then pushes. Finally\r
+\r
+`  `it pops directory back to the project.  The current `pull` script pulls down all the\r
+\r
+`  `submodules and the ensemble.\r
+\r
+\r
diff --git a/developer/amd64/home b/developer/amd64/home
new file mode 100755 (executable)
index 0000000..15ecf68
Binary files /dev/null and b/developer/amd64/home differ
diff --git a/developer/amd64/user b/developer/amd64/user
new file mode 100755 (executable)
index 0000000..19264ea
Binary files /dev/null and b/developer/amd64/user differ
diff --git a/developer/amd64/user-stem b/developer/amd64/user-stem
new file mode 100755 (executable)
index 0000000..316ac06
Binary files /dev/null and b/developer/amd64/user-stem differ
diff --git a/developer/amd64/user-subu b/developer/amd64/user-subu
new file mode 100755 (executable)
index 0000000..bb525bb
Binary files /dev/null and b/developer/amd64/user-subu differ
diff --git a/developer/bash/Z b/developer/bash/Z
new file mode 100755 (executable)
index 0000000..4cf0486
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+/usr/bin/date -u +"%Y-%m-%dT%H:%M:%SZ"
diff --git a/developer/bash/bashrc b/developer/bash/bashrc
new file mode 100644 (file)
index 0000000..0914cfc
--- /dev/null
@@ -0,0 +1,51 @@
+# ssh login will fail if .bashrc writes to stdout, so we write to "bash_error.txt"
+# set -x
+# in F37 something seems to be caching PATH, which can be annoying
+
+# If not running interactively, don't do anything
+  case $- in
+      *i*) ;;
+        *) return;;
+  esac
+
+# This should also be the default from login.defs, because gnome ignores 
+# .login, .profile, etc. and uses systemd to launch applications from the desktop,
+  umask 0077
+
+# - note the variable $PROMPT_DECOR, that is how the project name ends up in the prompt.
+# - without -i bash will clear PS1, just because, so we set PPS1, ,PPS2 to not lose the profit.
+# - use $(pwd) instead of \w or it will prefix '~' which confuses dirtrack when the
+#   user is changed using su
+  export PPS1='\n$($iseq/Z)[$PROMPT_DECOR]\n\u@\h§$(pwd)§\n> '
+  export PPS2='>> '
+  export PS1="$PPS1"
+  export PS2="$PPS2"
+
+# sort the output of printenv, show newlines as environment variable values as \n
+  alias printenv='printenv | awk '\''{gsub(/\n/, "\\n")}1'\'' | sort'
+
+# iso time in ls -l, show hidden files, human readable sizes
+  alias ls='ls -a -h --time-style=long-iso' 
+
+# iso time for all Linux programs, which they will all ignore, but at least we
+# tried, perhaps someday ...
+  export TZ=UTC
+  export TIME_STYLE=long-iso
+  export LC_ALL=en_DK.UTF-8
+
+# -l don't truncate long lins
+# -p show pids
+  alias pstree='pstree -lp'
+
+# - make bash gp to sleep, revealing the calling shell
+# - useful for job control of multiple bash shells from a controlling shell
+  alias zzz="kill -STOP \$\$"
+
+# The one true operating system.
+# Proof that an OS can be as small as an editor.
+  export EDITOR=emacs
+
+# check the window size after each command and, if necessary, update the values
+# of LINES and COLUMNS.
+  shopt -s checkwinsize
+
diff --git a/developer/bash/cat_w_fn b/developer/bash/cat_w_fn
new file mode 100755 (executable)
index 0000000..3308525
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# Check if at least one file is provided
+if [ $# -eq 0 ]; then
+  echo "Usage: $(script_fp) <filename1> [filename2] ..."
+  exit 1
+fi
+
+# Loop through all the provided files
+for file in "$@"; do
+  # Check if the file exists
+  if [ ! -f "$file" ]; then
+    echo "Error: File '$file' not found!"
+    continue
+  fi
+
+  # Print 80 dashes
+  printf '%.0s-' {1..80}
+  echo
+
+  # Print the filename and a colon
+  echo "$file:"
+
+  # Print the contents of the file
+  cat "$file"
+
+  # Print a newline for spacing between files
+  echo
+done
diff --git a/developer/bash/githolder b/developer/bash/githolder
new file mode 100755 (executable)
index 0000000..49fb12b
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/env /bin/bash
+
+# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
+# does not descend into hidden directories.
+
+# examples:
+#   > git_holder
+#   > git_holder --dry-run
+
+set -e
+
+find_empty_dirs() {
+  local dir="$1"
+  local dry_run="$2"
+
+  # Skip `.git` specifically
+  if [[ "$(basename "$dir")" == ".git" ]]; then
+    return
+  fi
+
+  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
+  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
+    if [[ "$dry_run" == "true" ]]; then
+      echo "Dry-run: Would add .githolder in $dir"
+    else
+      echo "Adding .githolder to $dir"
+      touch "$dir/.githolder"
+    fi
+  else
+    # Recurse into subdirectories
+    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
+      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
+        find_empty_dirs "$subdir" "$dry_run"
+      fi
+    done
+  fi
+}
+
+# Default parameters
+dry_run="false"
+target_dir="."
+
+# Parse arguments
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --dry-run)
+      dry_run="true"
+      shift
+      ;;
+    *)
+      if [[ -d "$1" ]]; then
+        target_dir="$1"
+        shift
+      else
+        echo "Invalid argument: $1 is not a directory"
+        exit 1
+      fi
+      ;;
+  esac
+done
+
+# Run the function
+find_empty_dirs "$target_dir" "$dry_run"
diff --git a/developer/bash/rm_tilda_files_tree b/developer/bash/rm_tilda_files_tree
new file mode 100755 (executable)
index 0000000..6ce67f5
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# rm_tilda_files_tree .
+#
+
+if [ ! -d "$1" ]; then
+  echo "expected first arg to be a directory where rm_tilda_files_tree is to be applied, but found: " "$1"
+  exit 1
+fi
+
+find "$1" -not -path '*/\.git/*' -name '*~' -exec rm {} \;
+
diff --git a/developer/bash/vl b/developer/bash/vl
new file mode 100755 (executable)
index 0000000..2c968d3
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+# vl 'vertical list'
+
+# Check if the command is provided
+if [ -z "$1" ]; then
+  echo "Usage: vl <command> [args...]"
+  exit 1
+fi
+
+# Capture the command and its arguments
+cmd=$1
+shift
+
+# Run the command with the remaining arguments and replace colons or spaces with newlines
+"$cmd" "$@" | tr ' :' '\n'
+
+exit 0
diff --git a/developer/cc/home.cli.c b/developer/cc/home.cli.c
new file mode 100644 (file)
index 0000000..4395a60
--- /dev/null
@@ -0,0 +1,34 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdio.h>
+
+/*
+We return the home directory without a trailing slash.  Otherwise in bash scripts ~/... will
+expand out with two slashes.  Also, if we returned with a trailing slash, then rsync 
+would behave differently with ~ (specifying contents of home instead of home itself).
+
+I am not sure if pw_dir has always returned a trailing slash on the home directory, though with
+the latest upgrade is the first time I am noticing two slashes in transcripts.
+
+It is an error for pw_dir to be an empty string?  I suppose not, but rather it is assumed
+to be the root of the file system?  Perhaps that is why they added the slash, to make
+that clear.
+
+*/
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  const char *homedir = pw->pw_dir;
+
+  size_t n = strlen(homedir);
+  if( n == 0 ) return 1;
+  while(n > 1){
+    fputc(*homedir ,stdout);
+  --n;
+  ++homedir;
+  };
+  if(*homedir == '/') return 1;
+  fputc(*homedir ,stdout);
+  return 1;
+}
diff --git a/developer/cc/user-stem.cli.c b/developer/cc/user-stem.cli.c
new file mode 100644 (file)
index 0000000..9f8a586
--- /dev/null
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_stem = strdup(pw->pw_name);
+
+  char *p = user_stem;
+  while(*p && *p != '-') p++;
+  if(*p) *p='\0';
+
+  puts(user_stem);
+  return 0;
+}
diff --git a/developer/cc/user-subu.cli.c b/developer/cc/user-subu.cli.c
new file mode 100644 (file)
index 0000000..c20bd03
--- /dev/null
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_subu = strdup(pw->pw_name);
+
+  char *p = user_subu;
+  while(*p && *p != '-') p++;
+  if(*p) p++;
+
+  puts(p);
+  return 0;
+}
diff --git a/developer/cc/user.cli.c b/developer/cc/user.cli.c
new file mode 100644 (file)
index 0000000..0a640e7
--- /dev/null
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  const char *pw_name = pw->pw_name;
+  puts(pw_name);
+  return 0;
+}
diff --git a/developer/deprecated/iseq_C/LICENSE b/developer/deprecated/iseq_C/LICENSE
new file mode 100644 (file)
index 0000000..a50fe80
--- /dev/null
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Thomas Walker Lynch
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/developer/deprecated/iseq_C/README.md b/developer/deprecated/iseq_C/README.md
new file mode 100644 (file)
index 0000000..abf32e7
--- /dev/null
@@ -0,0 +1,4 @@
+# home
+pulls home directory from etc/password
+
+Typically used by scripts that do not want to be sensitive to getting the home directory from the $HOME environment variable.  Install this in a places such as /usr/local/bin  and then so something such as HOME=home at the top of scripts.
diff --git a/developer/deprecated/iseq_C/makefile b/developer/deprecated/iseq_C/makefile
new file mode 100644 (file)
index 0000000..29af988
--- /dev/null
@@ -0,0 +1,28 @@
+
+executable = home user user-stem user-subu
+all: $(executable)
+
+home : home.c
+       gcc -o home home.c
+
+user : user.c
+       gcc -o user user.c
+
+user-stem : user-stem.c
+       gcc -o user-stem user-stem.c
+
+user-subu : user-subu.c
+       gcc -o user-subu user-subu.c
+
+.PHONY: clean
+clean:
+       rm -f home user user-stem usr-subu
+
+# installation must be done by an account that has sudo privs
+.PHONY: install
+install: $(executable)
+       for ex in $(executable); do \
+         sudo chmod 755 $$ex; \
+         sudo chown root:root $$ex; \
+         sudo mv $$ex /usr/local/bin; \
+       done
diff --git a/developer/deprecated/iseq_C/user-stem.c b/developer/deprecated/iseq_C/user-stem.c
new file mode 100644 (file)
index 0000000..9f8a586
--- /dev/null
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_stem = strdup(pw->pw_name);
+
+  char *p = user_stem;
+  while(*p && *p != '-') p++;
+  if(*p) *p='\0';
+
+  puts(user_stem);
+  return 0;
+}
diff --git a/developer/deprecated/iseq_C/user-subu.c b/developer/deprecated/iseq_C/user-subu.c
new file mode 100644 (file)
index 0000000..c20bd03
--- /dev/null
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_subu = strdup(pw->pw_name);
+
+  char *p = user_subu;
+  while(*p && *p != '-') p++;
+  if(*p) p++;
+
+  puts(p);
+  return 0;
+}
diff --git a/developer/deprecated/makefile b/developer/deprecated/makefile
new file mode 100644 (file)
index 0000000..b715f7c
--- /dev/null
@@ -0,0 +1,8 @@
+SHELL=/usr/bin/bash
+
+.PHONEY: install
+install:
+       sudo pwd
+       cd iseq_C && make install
+       cd iseq_interpreted; sudo install -m 755 * /usr/local/bin
+
diff --git a/developer/deprecated/release/make/environment.h b/developer/deprecated/release/make/environment.h
new file mode 100644 (file)
index 0000000..ba70241
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef RT·ENVIRONMENT_H
+#define RT·ENVIRONMENT_H
+  typedef unsigned int uint;
+
+#endif
diff --git a/developer/deprecated/release/make/makefile b/developer/deprecated/release/make/makefile
new file mode 100644 (file)
index 0000000..272163f
--- /dev/null
@@ -0,0 +1,178 @@
+
+
+#--------------------------------------------------------------------------------
+# This makefile must be called through a local makefile rather than directly.
+# the local make file should include:
+#
+#  1. $(RESOURCE)/library/makefile-environment  to give an environment to work with
+#  2. it should set the variables to custom values
+#  3. it should include this file, $(RESOURCE)/library/makefile
+#  4. if it needs tailored targets it should then define them
+#
+
+#--------------------------------------------------------------------------------
+# todo ...
+
+# should add test that incdir is not pwd before deleting the include
+# file. Currently it is working for us despite this problem because dist-clean is
+# looking for $(module).h while the include file is always $(module).lib.h.
+
+#--------------------------------------------------------------------------------
+# files named by convention
+#   this implements the .lib.c  and the .cli.c convention
+#
+
+# these are the sources edited by the programmer
+C_SOURCE_LIB=  $(wildcard $(SRCDIR)/*.lib.c)
+C_SOURCE_EXEC=  $(wildcard $(SRCDIR)/*.cli.c)
+CC_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.cc)
+CC_SOURCE_EXEC= $(wildcard $(SRCDIR)/*.cli.cc)
+
+#remove the suffix to get base name
+C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
+C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
+CC_BASE_LIB= $(sort $(patsubst %.lib.cc, %, $(notdir $(CC_SOURCE_LIB))))
+CC_BASE_EXEC= $(sort $(patsubst %.cli.cc, %, $(notdir $(CC_SOURCE_EXEC))))
+
+# two sets of object files, one for the lib, and one for the command line interface progs
+OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB) $(CC_BASE_LIB))
+OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC) $(CC_BASE_EXEC))
+
+# executables are made from EXEC sources
+EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC) $(CC_BASE_EXEC))
+
+
+#--------------------------------------------------------------------------------
+# targets
+
+.PHONY: all
+all: version
+
+.PHONY: version
+version:
+       @echo makefile version 7.0
+       if [ ! -z "$(C)" ]; then $(C) -v; fi
+       if [ ! -z "$(CC)" ]; then $(CC) -v; fi
+       make -v
+
+.PHONY: info
+info:
+       @echo "SHELL: " $(SHELL)
+       @echo "ECHO: " $(ECHO)
+       @echo "C: " $(C)
+       @echo "CFLAGS: " $(CFLAGS)
+       @echo "CC: " $(CC)
+       @echo "CCFLAGS: " $(CCFLAGS)
+       @echo "LINKFLAGS: " $(LINKFLAGS)
+       @echo "DOCDIR: " $(DOCDIR)
+       @echo "ENVDIR: " $(ENVDIR)
+       @echo "EXECDIR: " $(EXECDIR)
+       @echo "LIBDIR: " $(LIBDIR)
+       @echo "TESTDIR: " $(TESTDIR)
+       @echo "TMPDIR: " $(TMPDIR)
+       @echo "TRYDIR: " $(TRYDIR)
+       @echo "DEPFILE: " $(DEPFILE)
+       @echo "LIBFILE: " $(LIBFILE)
+       @echo "INCFILE: " $(INCFILE)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
+       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
+       @echo "CC_SOURCE_LIB: " $(CC_SOURCE_LIB)
+       @echo "CC_SOURCE_EXEC: " $(CC_SOURCE_EXEC)
+       @echo "C_BASE_LIB: " $(C_BASE_LIB)
+       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
+       @echo "CC_BASE_LIB: " $(CC_BASE_LIB)
+       @echo "CC_BASE_EXEC: " $(CC_BASE_EXEC)
+       @echo "OBJECT_LIB: " $(OBJECT_LIB)
+       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
+       @echo "EXEC: " $(EXEC)
+
+# should be safe to run this in an already setup or partially setup directory
+# gee looks like a candidate for a makefile function ..
+.PHONY: setup
+setup:
+       [ ! -e $(DOCDIR)  ]  && mkdir $(DOCDIR)  || true
+       [ ! -e $(EXECDIR) ]  && mkdir $(EXECDIR) || true
+       [ ! -e $(LIBDIR)  ]  && mkdir $(LIBDIR)  || true
+       [ ! -e $(SRCDIR)  ]  && mkdir $(SRCDIR)  || true
+       [ ! -e $(TESTDIR) ]  && mkdir $(TESTDIR) || true
+       [ ! -e $(TMPDIR)  ]  && mkdir $(TMPDIR)  || true
+       [ ! -e $(TRYDIR)  ]  && mkdir $(TRYDIR)  || true
+
+.PHONY: dependency
+dependency:
+       @rm -f $(DEPFILE)
+       @if [ -z "$(CC)" ]; then\
+         if [ -z "$(C)" ]; then\
+           $(ECHO) "No compiler specified";\
+           exit 1;\
+         else\
+           echo "C compiler only deps" ;\
+           $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+           echo "deps for C linking";\
+           for i in $(C_BASE_EXEC); do\
+             $(ECHO) >> $(DEPFILE);\
+             $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+             $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+           done;\
+         fi;\
+       else\
+         $(CC) $(CCFLAGS) -MM  $(CC_SOURCE_LIB) $(CC_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+         if [ -z "$C()" ]; then\
+           echo "CC compiler only deps" ;\
+         else\
+           echo "CC and C mixed compile deps" ;\
+           $(C) $(CFLAGS) -MM   $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+         fi;\
+         echo "deps for CC linking";\
+         for i in $(CC_BASE_EXEC) $(C_BASE_EXEC) ; do\
+           $(ECHO) >> $(DEPFILE);\
+           $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+           $(ECHO) "   $(CC) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+         done;\
+       fi
+
+.PHONY: library
+library: $(LIBFILE)
+
+$(LIBFILE): $(OBJECT_LIB)
+       ar rcs $(LIBFILE) $(OBJECT_LIB)
+
+.PHONY: cli
+cli: $(LIBFILE)
+       make sub_cli
+
+.PHONY: sub_cli
+sub_cli: $(EXEC)
+
+.PHONY: share
+share:
+       if [ ! -z "$(wildcard $(LIBDIR)/*)" ]; then cp $(LIBDIR)/* $(DIST_TARGET)/$(LIBDIR); fi
+       if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(DIST_TARGET)/$(EXECDIR); fi
+#      if [ ! -z "$(wildcard $(SRCDIR)/*.h)" ]; then cp $(SRCDIR)/*.h $(DIST_TARGET)/include; fi
+
+
+.PHONY: clean
+clean:
+       for i in $(wildcard $(TMPDIR)/*); do rm $$i || true; done 
+
+.PHONY: dist-clean
+dist-clean:
+       for i in $(wildcard $(TMPDIR)/*); do rm $$i || true; done 
+       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
+       rm -f $(LIBFILE)
+
+# recipes
+ $(TMPDIR)/%.o : $(SRCDIR)/%.c
+       $(C) $(CFLAGS) -o $@ -c $<
+
+ $(TMPDIR)/%.o : $(SRCDIR)/%.cc
+       $(CC) $(CCFLAGS) -o $@ -c $<
+
+# recipes
+#$(TMPDIR)/%.o : $(SRCDIR)/%.c
+#      $(C) $(CFLAGS) -o $@ -c <($(CPPP) $<)
+
+$(TMPDIR)/%.o : $(SRCDIR)/%.c
+       $(CPPP) $< $(TMPDIR)/tempfile.c
+       $(C) $(CFLAGS) -o $@ -c $(TMPDIR)/tempfile.c
+#      rm $(TMPDIR)/tempfile.c
diff --git a/developer/deprecated/release/make/makefile-environment b/developer/deprecated/release/make/makefile-environment
new file mode 100644 (file)
index 0000000..6a01632
--- /dev/null
@@ -0,0 +1,53 @@
+#makes use of variable PROJECT from the environment, see command `repo`
+
+SHELL=/bin/bash
+
+#--------------------------------------------------------------------------------
+# useful macros
+#
+
+# a single space literal, for example if you wanted to subsitute commas to
+# spaces: $(subst $(space),;,$(string))
+
+blank :=s
+pace :=$(blank)  $(blank)
+
+#--------------------------------------------------------------------------------
+# Programs make uses.  
+#
+ECHO= echo
+#ECHO= echo -e
+
+# If not using C, or C++, set the variable to a blank value
+# (value should be set in the local makefile)
+C=
+CC=
+CPPP= echo "#line 1 \"$1\""; cat
+
+
+#--------------------------------------------------------------------------------
+# main directories
+#   these may be created by make setup, which can be useful as git doesn't keep empty directories
+#
+ENVDIR=../env
+DOCDIR=document
+EXECDIR=executables
+LIBDIR=library
+SRCDIR=src
+TESTDIR=test
+TMPDIR=temporary
+TRYDIR=experiment
+
+#--------------------------------------------------------------------------------
+# local targets
+#
+DEPFILE=$(TMPDIR)/makefile-cc.deps
+LIBFILE=$(LIBDIR)/lib$(PROJECT).a
+INCFILE=$(SRCDIR)/$(PROJECT).h
+
+#--------------------------------------------------------------------------------
+# install target
+#   make install has not implemented yet, so no matter
+#
+DIST_TARGET=
+
diff --git a/developer/deprecated/release/repo/repo b/developer/deprecated/release/repo/repo
new file mode 100755 (executable)
index 0000000..7e124dd
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+# this will start a new shell that has an environment appropriate for the repo
+#set -x
+# current `use_tool` in the project environment also sets $PROJECT, and it comes later.
+
+
+repo="${1%/}"
+
+error=false
+if [ -z "$repo" ]; then
+   echo "no repo specified"
+   error=true
+fi
+if [ -z "$REPO_DIR" ]; then
+   echo "no REPO_DIR in the environment"
+   error=true
+fi
+if $error; then
+  exit 1
+fi
+
+
+# makes an init file for bash. 
+# Variables from the environment will not expand within this heredoc because of the quotes around the EOF.  (Yes, that is
+# a thing.)
+# moved this to the .bashrc:
+#   export PS1='\n$(/usr/local/bin/Z) [$(echo "$REPO")]\n\u@\h§\w§\n> '
+read -r -d '' InitFile <<-"EOF" 
+  export HOME=$(/usr/local/bin/home)
+  . "$HOME/.bashrc"
+  export HOME=$(/usr/local/bin/home) # make sure it wasn't changed in .bashrc
+  export SHELL=/bin/bash
+  export USERNAME=$(/usr/local/bin/user)
+  export REPO_HOME="$REPO_DIR/$REPO" 
+  if [ -z "$TMP" ] && [ -d "$REPO_HOME/developer" ]; then 
+    export TMP="$REPO_HOME/developer/scratch_pad"
+    if [ ! -d "$TMP" ]; then 
+      mkdir "$TMP"
+    fi
+  fi
+  cd "$REPO_HOME"
+  act="$REPO_HOME/developer/tool/env"
+  if [ -f "$act" ]; then
+    . "$act"
+  fi
+  # echo $PATH
+EOF
+
+# exec -c and env -i, where INSIDE_EMACS is set in the calling shell and is also set in
+# the init script of the newly launched shell, does not work.  In both cases emacs stops
+# tracking directory changes in the newly launched shell.  Emacs will continue to track
+# directory changes if we call bash directly, or if we use env -i with INSIDE_EMACS defined
+# as a parameter.
+#
+# PROJECT is for PS1 bash prompt
+env --ignore-environment \
+    REPO="$repo" \
+    REPO_DIR="$REPO_DIR" \
+    SUBU_SHARE_DIR="$SUBU_SHARE_DIR"\
+    PROJECT="$repo"\
+    INSIDE_EMACS="$INSIDE_EMACS" \
+    TMP="$TMP" \
+    HOSTNAME="$HOSTNAME" \
+    LOGNAME="$LOGNAME" \
+    DISPLAY="$DISPLAY" \
+    LANG="$LANG"\
+    TERM="$TERM" \
+    TERMCAP="$TERMCAP" \
+    EDITOR="$EDITOR" \
+    PATH="/usr/local/bin:/usr/bin:/bin" \
+    /bin/bash --init-file <(echo "$InitFile")
+
+#set +x
diff --git a/developer/deprecated/release/repo/repo_pull b/developer/deprecated/release/repo/repo_pull
new file mode 100755 (executable)
index 0000000..88d5cda
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/bash
+#set -x
+if [ -z "$REPO_DIR" ]; then
+    echo "can't $0, no REPO_DIR repo home directory found in the environment"
+    exit 1;
+fi
+if [ -z "$TMP" ]; then
+    echo "can't $0, no tmp directory found in the environment"
+    exit 1;
+fi
+
+# don't want the pull to clobber this, and gosh, what if there are multiple pulls
+# simultaneously?  this is a bit of a hack but good enough for now ..
+TimeStamp="$TMP"/git_pull_timestamp_"$(od -A n -t x -N 8 /dev/urandom |tr -d ' ')"
+touch "$TimeStamp"
+
+# would be better to make this repo specific so we don't pull other submodules than the
+# repo ..  or do we want the latest in the other submodules also?
+pushd "$REPO_DIR" > /dev/null
+
+  git pull --recurse-submodules || echo "git pull failed"
+
+  # make a file that looks like a newly pulled executable for testing purposes
+  #  touch temp
+  #  chmod +x temp
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -not -type d \
+       -executable \
+       -execdir echo "Pulled file is executable, removing x flag: {}" \; \
+       -execdir chmod -x {} \;
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -type d \
+       -not -name "\.git" \
+       -not -path "./.git/*" \
+       -execdir echo "New file: {}" \;
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -path "./tmp/*" \
+       -execdir echo "Error, this file was pulled into a tmp directory: {}" \; 
+
+  if [ -d env ]; then
+    find env \
+         -newer "$TimeStamp" \
+         -execdir echo "Error, this file was pulled into the env directory: {}" \; 
+  fi
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -not -name "\.git" \
+       -name "\.*" \
+       -execdir echo "Error, hidden file was pulled: {}" \; 
+
+  if [ .gitignore -nt "$TimeStamp" ]; then
+      echo "Warning, .gitignore was modified."
+  fi
+
+  rm "$TimeStamp"
+
+popd > /dev/null
+#set +x
diff --git a/developer/deprecated/release/repo/repo_push b/developer/deprecated/release/repo/repo_push
new file mode 100755 (executable)
index 0000000..7abf797
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash
+#set -x
+
+if [ -z "$REPO_DIR" ]; then
+    echo "can't $0, no REPO_DIR found in the environment"
+    exit 1;
+fi
+CommitMessage="$1"
+if [ -z "$CommitMessage" ]; then
+    echo "no commit message, enter it now:"
+    read CommitMessage
+    if [ -z "$CommitMessage" ]; then
+        echo "no commit message, exiting"
+        exit 1;
+     fi
+fi
+
+pushd "$REPO_DIR" > /dev/null
+
+  # make clean any directories with a makefile
+  find . \
+       -not -path "./.git/*" \
+       -not -path "./tmp/*" \
+       -type f \
+       -name 'makefile' \
+       -execdir make clean \;
+
+  # executables should not be checked into the repo, yet we found these:
+  find . \
+       -not -path "./.git/*" \
+       -not -path "./tmp/*" \
+       -type f \
+       -executable \
+       -exec echo "found executable, removing x flag" {} \; 
+       -execdir chmod -x {} \;
+
+  #     -execdir mv {} {}~ \;
+
+set -x
+  git stash
+  git pull
+  git stash pop
+  git add .
+  git commit -m "$CommitMessage"
+  git push
+set +x
+
+popd > /dev/null
+#set +x
+
+
+
diff --git a/developer/deprecated/release/util/rm_tilda_files_tree b/developer/deprecated/release/util/rm_tilda_files_tree
new file mode 100755 (executable)
index 0000000..6ce67f5
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# rm_tilda_files_tree .
+#
+
+if [ ! -d "$1" ]; then
+  echo "expected first arg to be a directory where rm_tilda_files_tree is to be applied, but found: " "$1"
+  exit 1
+fi
+
+find "$1" -not -path '*/\.git/*' -name '*~' -exec rm {} \;
+
diff --git a/developer/deprecated/repo/repo b/developer/deprecated/repo/repo
new file mode 100755 (executable)
index 0000000..7e124dd
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+# this will start a new shell that has an environment appropriate for the repo
+#set -x
+# current `use_tool` in the project environment also sets $PROJECT, and it comes later.
+
+
+repo="${1%/}"
+
+error=false
+if [ -z "$repo" ]; then
+   echo "no repo specified"
+   error=true
+fi
+if [ -z "$REPO_DIR" ]; then
+   echo "no REPO_DIR in the environment"
+   error=true
+fi
+if $error; then
+  exit 1
+fi
+
+
+# makes an init file for bash. 
+# Variables from the environment will not expand within this heredoc because of the quotes around the EOF.  (Yes, that is
+# a thing.)
+# moved this to the .bashrc:
+#   export PS1='\n$(/usr/local/bin/Z) [$(echo "$REPO")]\n\u@\h§\w§\n> '
+read -r -d '' InitFile <<-"EOF" 
+  export HOME=$(/usr/local/bin/home)
+  . "$HOME/.bashrc"
+  export HOME=$(/usr/local/bin/home) # make sure it wasn't changed in .bashrc
+  export SHELL=/bin/bash
+  export USERNAME=$(/usr/local/bin/user)
+  export REPO_HOME="$REPO_DIR/$REPO" 
+  if [ -z "$TMP" ] && [ -d "$REPO_HOME/developer" ]; then 
+    export TMP="$REPO_HOME/developer/scratch_pad"
+    if [ ! -d "$TMP" ]; then 
+      mkdir "$TMP"
+    fi
+  fi
+  cd "$REPO_HOME"
+  act="$REPO_HOME/developer/tool/env"
+  if [ -f "$act" ]; then
+    . "$act"
+  fi
+  # echo $PATH
+EOF
+
+# exec -c and env -i, where INSIDE_EMACS is set in the calling shell and is also set in
+# the init script of the newly launched shell, does not work.  In both cases emacs stops
+# tracking directory changes in the newly launched shell.  Emacs will continue to track
+# directory changes if we call bash directly, or if we use env -i with INSIDE_EMACS defined
+# as a parameter.
+#
+# PROJECT is for PS1 bash prompt
+env --ignore-environment \
+    REPO="$repo" \
+    REPO_DIR="$REPO_DIR" \
+    SUBU_SHARE_DIR="$SUBU_SHARE_DIR"\
+    PROJECT="$repo"\
+    INSIDE_EMACS="$INSIDE_EMACS" \
+    TMP="$TMP" \
+    HOSTNAME="$HOSTNAME" \
+    LOGNAME="$LOGNAME" \
+    DISPLAY="$DISPLAY" \
+    LANG="$LANG"\
+    TERM="$TERM" \
+    TERMCAP="$TERMCAP" \
+    EDITOR="$EDITOR" \
+    PATH="/usr/local/bin:/usr/bin:/bin" \
+    /bin/bash --init-file <(echo "$InitFile")
+
+#set +x
diff --git a/developer/deprecated/repo/repo_pull b/developer/deprecated/repo/repo_pull
new file mode 100755 (executable)
index 0000000..88d5cda
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/bash
+#set -x
+if [ -z "$REPO_DIR" ]; then
+    echo "can't $0, no REPO_DIR repo home directory found in the environment"
+    exit 1;
+fi
+if [ -z "$TMP" ]; then
+    echo "can't $0, no tmp directory found in the environment"
+    exit 1;
+fi
+
+# don't want the pull to clobber this, and gosh, what if there are multiple pulls
+# simultaneously?  this is a bit of a hack but good enough for now ..
+TimeStamp="$TMP"/git_pull_timestamp_"$(od -A n -t x -N 8 /dev/urandom |tr -d ' ')"
+touch "$TimeStamp"
+
+# would be better to make this repo specific so we don't pull other submodules than the
+# repo ..  or do we want the latest in the other submodules also?
+pushd "$REPO_DIR" > /dev/null
+
+  git pull --recurse-submodules || echo "git pull failed"
+
+  # make a file that looks like a newly pulled executable for testing purposes
+  #  touch temp
+  #  chmod +x temp
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -not -type d \
+       -executable \
+       -execdir echo "Pulled file is executable, removing x flag: {}" \; \
+       -execdir chmod -x {} \;
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -type d \
+       -not -name "\.git" \
+       -not -path "./.git/*" \
+       -execdir echo "New file: {}" \;
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -path "./tmp/*" \
+       -execdir echo "Error, this file was pulled into a tmp directory: {}" \; 
+
+  if [ -d env ]; then
+    find env \
+         -newer "$TimeStamp" \
+         -execdir echo "Error, this file was pulled into the env directory: {}" \; 
+  fi
+
+  find . \
+       -newer "$TimeStamp" \
+       -not -path "./.git/*" \
+       -not -name "\.git" \
+       -name "\.*" \
+       -execdir echo "Error, hidden file was pulled: {}" \; 
+
+  if [ .gitignore -nt "$TimeStamp" ]; then
+      echo "Warning, .gitignore was modified."
+  fi
+
+  rm "$TimeStamp"
+
+popd > /dev/null
+#set +x
diff --git a/developer/deprecated/repo/repo_push b/developer/deprecated/repo/repo_push
new file mode 100755 (executable)
index 0000000..7abf797
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash
+#set -x
+
+if [ -z "$REPO_DIR" ]; then
+    echo "can't $0, no REPO_DIR found in the environment"
+    exit 1;
+fi
+CommitMessage="$1"
+if [ -z "$CommitMessage" ]; then
+    echo "no commit message, enter it now:"
+    read CommitMessage
+    if [ -z "$CommitMessage" ]; then
+        echo "no commit message, exiting"
+        exit 1;
+     fi
+fi
+
+pushd "$REPO_DIR" > /dev/null
+
+  # make clean any directories with a makefile
+  find . \
+       -not -path "./.git/*" \
+       -not -path "./tmp/*" \
+       -type f \
+       -name 'makefile' \
+       -execdir make clean \;
+
+  # executables should not be checked into the repo, yet we found these:
+  find . \
+       -not -path "./.git/*" \
+       -not -path "./tmp/*" \
+       -type f \
+       -executable \
+       -exec echo "found executable, removing x flag" {} \; 
+       -execdir chmod -x {} \;
+
+  #     -execdir mv {} {}~ \;
+
+set -x
+  git stash
+  git pull
+  git stash pop
+  git add .
+  git commit -m "$CommitMessage"
+  git push
+set +x
+
+popd > /dev/null
+#set +x
+
+
+
diff --git a/developer/deprecated/subu_setup b/developer/deprecated/subu_setup
new file mode 100644 (file)
index 0000000..1a9a220
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+set -e
+
+# Check for subuser name
+if [ -z "$1" ]; then
+  echo "Usage: $0 <subu_name>"
+  exit 1
+fi
+
+SUBU_NAME=$1
+SUBU_USER="Thomas-$SUBU_NAME"
+SUBU_HOME="/home/$SUBU_USER"
+
+# Check if the subuser exists
+if ! id "$SUBU_USER" &>/dev/null; then
+  echo "Error: Subuser $SUBU_USER does not exist!"
+  exit 1
+fi
+
+echo "Setting up subuser: $SUBU_USER"
+
+# 1. Enable linger for the subuser
+echo "Enabling linger for $SUBU_USER..."
+sudo loginctl enable-linger "$SUBU_USER"
+
+# 2. Enable pipewire services for the subuser
+echo "Enabling pipewire services for $SUBU_USER..."
+sudo -u "$SUBU_USER" systemctl --user enable pipewire
+sudo -u "$SUBU_USER" systemctl --user enable pipewire-pulse
+
+# 3. Set up X11 access (XAUTHORITY)
+echo "Setting up X11 access for $SUBU_USER..."
+XAUTH_PATH="$SUBU_HOME/.Xauthority"
+if [ ! -f "$XAUTH_PATH" ]; then
+  sudo -u "$SUBU_USER" touch "$XAUTH_PATH"
+fi
+
+# Generate a trusted X11 cookie
+echo "Generating trusted X11 cookie..."
+xauth generate "$DISPLAY" . trusted
+xauth extract - "$DISPLAY" | sudo -u "$SUBU_USER" xauth merge -
+
+# 4. Set up a basic .bashrc if not already present
+echo "Setting up .bashrc for $SUBU_USER..."
+BASHRC_PATH="$SUBU_HOME/.bashrc"
+if [ ! -f "$BASHRC_PATH" ]; then
+  sudo -u "$SUBU_USER" cp /etc/skel/.bashrc "$BASHRC_PATH"
+  echo "# Custom settings for $SUBU_USER" | sudo -u "$SUBU_USER" tee -a "$BASHRC_PATH"
+fi
+
+# 5. Adjust permissions for the subuser home directory (optional)
+echo "Ensuring correct permissions for $SUBU_HOME..."
+sudo chown -R "$SUBU_USER:$SUBU_USER" "$SUBU_HOME"
+
+echo "Subuser setup complete for $SUBU_USER!"
diff --git a/developer/deprecated/subu_systemd b/developer/deprecated/subu_systemd
new file mode 100755 (executable)
index 0000000..0b88448
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+subu="$1"
+shell="${@:2}"
+
+# Basic error handling for subu name
+if [ -z "$subu" ]; then
+  echo "No subuser name supplied"
+  exit 1
+fi
+
+# Ensure the subu session is set up correctly
+xauth_output=$(xauth list)
+xkey=$(echo "$xauth_output" | head -1 | awk '{print $3}')
+
+if [ -z "$xkey" ]; then
+  echo "subu:: xauth key not found"
+  exit 1
+fi
+
+# Set up the display environment
+read -r -d '' script0 <<-EOF
+  export NO_AT_BRIDGE=1 \
+  ;touch .Xauthority \
+  ;xauth add "$DISPLAY" . "$xkey" \
+  ;export DISPLAY="$DISPLAY" \
+  ;eval \$(dbus-launch --sh-syntax) \
+  ;export DBUS_SESSION_BUS_ADDRESS \
+  ;export DBUS_SESSION_BUS_PID \
+  ;$shell
+EOF
+
+# Start the subuser session using machinectl without the '--' issue
+sudo machinectl shell $subu@ /bin/bash -c "$script0"
diff --git a/developer/emacs/emacs.el b/developer/emacs/emacs.el
new file mode 100644 (file)
index 0000000..5ca4331
--- /dev/null
@@ -0,0 +1,52 @@
+
+; The first time Emacs  encounters a link to a source file, Emacs asks if it should follow it.
+; This might suppress that initial question and follow the link.
+; (setq find-file-visit-truename t)
+
+(defun jdbx ()
+  "Set gud-jdb-sourcepath from the environment and run jdb with the correct source path."
+  (interactive)
+  (let* 
+    (
+      (sourcepath (getenv "SOURCEPATH"))
+      )
+    (if 
+      sourcepath
+      (setq gud-jdb-sourcepath (split-string sourcepath ":" t))
+      (message "Warning: SOURCEPATH is not set. `jdb` will run without source path information.")
+      )
+    (let 
+      (
+        (class-name (read-string "Enter the class to debug: " "Test_Util"))
+        )
+      (jdb (concat "jdb -sourcepath"
+             (if 
+               sourcepath 
+               (mapconcat 'identity gud-jdb-sourcepath ":") ""
+               )
+             " "
+             class-name
+             )
+        ))))
+
+(defun monitor-jdb-sourcepath (output)
+  "Monitor the jdb output for `sourcepath ARG` commands and update `gud-jdb-sourcepath` with each path in ARG."
+  (when 
+    (string-match "sourcepath \\(.+\\)" output)
+    (let* 
+      (
+        (new-paths (match-string 1 output))
+        (paths-list (split-string new-paths ":" t))
+        )
+      ;; Add each path in paths-list to gud-jdb-sourcepath if not already present
+      (dolist 
+        (path paths-list)
+        (unless 
+          (member path gud-jdb-sourcepath)
+          (setq gud-jdb-sourcepath (append gud-jdb-sourcepath (list path)))
+          )
+        )
+      (message "Updated gud-jdb-sourcepath: %s" gud-jdb-sourcepath)))
+  output)
+
+(add-hook 'gud-filter-functions 'monitor-jdb-sourcepath)
diff --git a/developer/make/RT_0.h b/developer/make/RT_0.h
new file mode 100644 (file)
index 0000000..ba70241
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef RT·ENVIRONMENT_H
+#define RT·ENVIRONMENT_H
+  typedef unsigned int uint;
+
+#endif
diff --git a/developer/make/environment_RT_0 b/developer/make/environment_RT_0
new file mode 100644 (file)
index 0000000..60d42b6
--- /dev/null
@@ -0,0 +1,70 @@
+# makefile environment variable defaults.
+# include this in the local make file with a line such as:
+#
+#   RESOURCE:=$(REPO_HOME)/tool_shared/third_party/resource/release
+#   include $(RESOURCE)/make/environment_RT_0
+#
+# The Unix environment has traditionally combined linking and loading into one
+# program called `ld`, and the compiler conventionally also has a switch for
+# doing the linking. A programmer or user typically does not run the loader
+# explicitly, because the shall does this automatically. Consequently, the poor
+# linker has not been giving an explicit name, and no one thinks much about
+# loading.
+#
+# The ATT c compiler was called 'cc'.  However, today in makefiles 'CC' is often
+# used as the variable name for the C++ compiler.
+#
+# This all causes a bit of a problem when following the RT directory naming
+# convention, where, when practical, directories are named after the program
+# that will use the contained files.
+#
+# Here 'cc' is the directory containing files for cc, the C compiler.  The
+# directory 'linker' containers files for the unnamed linker, and, as loaders
+# are architecture specific, 'amd64' containers files for the architecture
+# 'amd64' loader. The variable CPP holds the name of the C++ compiler.
+
+
+SHELL=/bin/bash
+
+#--------------------------------------------------------------------------------
+# useful macros
+#
+
+# a single space literal, for example if you wanted to subsitute commas to
+# spaces: $(subst $(space),;,$(string))
+
+blank :=
+space :=$(blank)  $(blank)
+
+#--------------------------------------------------------------------------------
+# main directories 
+# 
+DOCDIR=document
+EXECDIR=amd64
+LIBDIR=linker
+SRCDIR=cc
+INCDIR=cc
+TESTDIR=test
+TMPDIR=scratchpad
+TRYDIR=experiment
+
+#--------------------------------------------------------------------------------
+# Programs make uses.  
+#
+ECHO= echo -e
+#ECHO= echo
+
+# program to use to compile C, or to compile C++
+C=
+CPP=
+
+#--------------------------------------------------------------------------------
+# local targets
+#
+DEPFILE=$(TMPDIR)/makefile-cc.deps
+LIBFILE=$(LIBDIR)/lib$(PROJECT).a
+
+# we no longer use separate include file, but instead gate the C file
+# INCFILE=$(SRCDIR)/$(PROJECT).h
+
+
diff --git a/developer/make/targets b/developer/make/targets
new file mode 100644 (file)
index 0000000..2d06218
--- /dev/null
@@ -0,0 +1,173 @@
+#--------------------------------------------------------------------------------
+# This makefile must be called through a local makefile rather than directly.
+# the local make file should include:
+#
+#  1. cp $(RESOURCE)/release/make/makefile-environment_example to get started on a make environment.
+#  2. modify it and set the variables to custom values
+#  3. the environment file should include this file, probably at $(RESOURCE)/release/make/makefile
+#  4. if tailored targets are needed, add them 
+#
+
+#--------------------------------------------------------------------------------
+# todo ...
+
+# should add test that incdir is not pwd before deleting the include
+# file. Currently it is working for us despite this problem because dist-clean is
+# looking for $(module).h while the include file is always $(module).lib.h.
+
+#--------------------------------------------------------------------------------
+# files named by convention
+#   this implements the .lib.c  and the .cli.c convention
+#
+
+# these are the sources edited by the programmer
+C_SOURCE_LIB=  $(wildcard $(SRCDIR)/*.lib.c)
+C_SOURCE_EXEC=  $(wildcard $(SRCDIR)/*.cli.c)
+CPP_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.cc)
+CPP_SOURCE_EXEC= $(wildcard $(SRCDIR)/*.cli.cc)
+
+#remove the suffix to get base name
+C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
+C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
+CPP_BASE_LIB= $(sort $(patsubst %.lib.cc, %, $(notdir $(CPP_SOURCE_LIB))))
+CPP_BASE_EXEC= $(sort $(patsubst %.cli.cc, %, $(notdir $(CPP_SOURCE_EXEC))))
+
+# two sets of object files, one for the lib, and one for the command line interface progs
+OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB) $(CPP_BASE_LIB))
+OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC) $(CPP_BASE_EXEC))
+
+# executables are made from EXEC sources
+EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC) $(CPP_BASE_EXEC))
+
+
+#--------------------------------------------------------------------------------
+# targets
+
+.PHONY: all
+all: usage
+
+.PHONY: usage
+usage:
+       @echo example usage: make dist-clean dependency cli
+       @echo example usage: make cli
+
+.PHONY: version
+version:
+       @echo makefile version 7.1
+       if [ ! -z "$(C)" ]; then $(C) -v; fi
+       if [ ! -z "$(CPP)" ]; then $(CPP) -v; fi
+       /bin/make -v
+
+.PHONY: info
+info:
+       @echo "C: " $(C)
+       @echo "CPP: " $(CPP)
+       @echo "CPPFLAGS: " $(CPPFLAGS)
+       @echo "CPP_BASE_EXEC: " $(CPP_BASE_EXEC)
+       @echo "CPP_BASE_LIB: " $(CPP_BASE_LIB)
+       @echo "CPP_SOURCE_EXEC: " $(CPP_SOURCE_EXEC)
+       @echo "CPP_SOURCE_LIB: " $(CPP_SOURCE_LIB)
+       @echo "CFLAGS: " $(CFLAGS)
+       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
+       @echo "C_BASE_LIB: " $(C_BASE_LIB)
+       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
+       @echo "DEPFILE: " $(DEPFILE)
+       @echo "DOCDIR: " $(DOCDIR)
+       @echo "ECHO: " $(ECHO)
+       @echo "EXEC: " $(EXEC)
+       @echo "EXECDIR: " $(EXECDIR)
+       @echo "INCDIR: " $(INCFILE)
+       @echo "LIBDIR: " $(LIBDIR)
+       @echo "LIBFILE: " $(LIBFILE)
+       @echo "LINKFLAGS: " $(LINKFLAGS)
+       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
+       @echo "OBJECT_LIB: " $(OBJECT_LIB)
+       @echo "SHELL: " $(SHELL)
+       @echo "SRCDIR: " $(INCFILE)
+       @echo "TESTDIR: " $(TESTDIR)
+       @echo "TMPDIR: " $(TMPDIR)
+       @echo "TRYDIR: " $(TRYDIR)
+
+# should be safe to run this in an already setup or partially setup directory
+# gee looks like a candidate for a makefile function ..
+.PHONY: setup
+setup:
+       [ ! -e $(DOCDIR)  ]  && mkdir $(DOCDIR)  || true
+       [ ! -e $(EXECDIR) ]  && mkdir $(EXECDIR) || true
+       [ ! -e $(LIBDIR)  ]  && mkdir $(LIBDIR)  || true
+       [ ! -e $(SRCDIR)  ]  && mkdir $(SRCDIR)  || true
+       [ ! -e $(TESTDIR) ]  && mkdir $(TESTDIR) || true
+       [ ! -e $(TMPDIR)  ]  && mkdir $(TMPDIR)  || true
+       [ ! -e $(TRYDIR)  ]  && mkdir $(TRYDIR)  || true
+
+.PHONY: dependency
+dependency:
+       @rm -f $(DEPFILE)
+       @if [ -z "$(CPP)" ]; then\
+         if [ -z "$(C)" ]; then\
+           $(ECHO) "No compiler specified";\
+           exit 1;\
+         else\
+           echo "C compiler only deps" ;\
+           $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+           echo "deps for C linking";\
+           for i in $(C_BASE_EXEC); do\
+             $(ECHO) >> $(DEPFILE);\
+             $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+             $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+           done;\
+         fi;\
+       else\
+         $(CPP) $(CPPFLAGS) -MM  $(CPP_SOURCE_LIB) $(CPP_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+         if [ -z "$C()" ]; then\
+           echo "CPP compiler only deps" ;\
+         else\
+           echo "CPP and C mixed compile deps" ;\
+           $(C) $(CFLAGS) -MM   $(C_SOURCE_LIB) $(C_SOURCE_EXEC) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+         fi;\
+         echo "deps for CPP linking";\
+         for i in $(CPP_BASE_EXEC) $(C_BASE_EXEC) ; do\
+           $(ECHO) >> $(DEPFILE);\
+           $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+           $(ECHO) "   $(CPP) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+         done;\
+       fi
+
+.PHONY: library
+library: $(LIBFILE)
+
+$(LIBFILE): $(OBJECT_LIB)
+       ar rcs $(LIBFILE) $(OBJECT_LIB)
+
+.PHONY: cli
+cli: $(LIBFILE)
+       make sub_cli
+
+.PHONY: sub_cli
+sub_cli: $(EXEC)
+
+.PHONY: share
+share:
+       if [ ! -z "$(wildcard $(LIBDIR)/*)" ]; then cp $(LIBDIR)/* $(DIST_TARGET)/$(LIBDIR); fi
+       if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(DIST_TARGET)/$(EXECDIR); fi
+#      if [ ! -z "$(wildcard $(SRCDIR)/*.h)" ]; then cp $(SRCDIR)/*.h $(DIST_TARGET)/include; fi
+
+
+.PHONY: clean
+clean:
+       rm -f $(DEPFILE)
+       rm -f $(LIBFILE)
+       for i in $(wildcard $(TMPDIR)/*.o); do rm $$i || true; done 
+
+.PHONY: dist-clean
+dist-clean: clean
+       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
+
+# recipes
+ $(TMPDIR)/%.o : $(SRCDIR)/%.c
+       $(C) $(CFLAGS) -o $@ -c $<
+
+ $(TMPDIR)/%.o : $(SRCDIR)/%.cc
+       $(CPP) $(CPPFLAGS) -o $@ -c $<
+
diff --git a/developer/nautilus/Decrypt b/developer/nautilus/Decrypt
new file mode 100644 (file)
index 0000000..7796397
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+# decrypt file given as first argument
+#
+# This version overwrites the source file with the result. In this way there is only one file used, and Nautilus does not
+# get confused  and select an unrelated file.
+#
+# The decryption result is held in memory before the overwrite, which could be a problem if the source
+# file is very large. It would be better to create a /tmp file, then copy that for the overwrite step. For very large
+# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
+
+import sys
+import subprocess
+import os
+
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+def message(mess):
+  dlg = Gtk.MessageDialog(
+    message_type=Gtk.MessageType.ERROR
+    ,buttons=Gtk.ButtonsType.OK
+    ,text=mess
+    )
+  dlg.set_title('Decrypt Info')
+  dlg.run()
+  dlg.destroy()
+
+def run(command):
+  #print("command: " ,command)   
+  proc = subprocess.Popen(
+    command
+    ,stdout = subprocess.PIPE
+    ,stderr = subprocess.PIPE
+  )
+  stdout, stderr = proc.communicate()
+  # print("stdout: ", len(stdout) ," " ,stdout)
+  # print("stderr: ", len(stderr) ," " ,stderr)
+  # print("proc.returncode: ", proc.returncode)
+  return proc.returncode, stdout, stderr
+
+
+file_src = sys.argv[1] 
+if not os.path.exists(file_src):
+  message("file not found: " + file_src)
+  sys.exit(1)
+if os.path.getsize(file_src) > 2**30:
+  message("beyond current Nautilus Decrypt file size limit of 1 gigabyte")
+  sys.exit(1)
+
+
+ext = file_src[ -4:]
+
+if ext == ".gpg":
+  file_dst = file_src[0:-4]
+  code ,stdout ,stderr = run(["/usr/bin/gpg2" ,"--quiet" ,"--output" ,"-" ,"--decrypt" ,file_src])
+  # if all went well, the decrypted data is in stdout
+  if code == 0:
+    if not os.path.exists(file_dst):
+      os.rename(file_src ,file_dst) 
+      with open(file_dst ,"wb") as f:
+        f.write(stdout)
+    else:
+      message(file_dst + " already exists")
+
+  if len(stderr) > 0:
+     message(stderr.decode("utf-8"))
+   
+
+  
diff --git a/developer/nautilus/Encrypt b/developer/nautilus/Encrypt
new file mode 100644 (file)
index 0000000..31ab6ac
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# encyrpt file given as first argument
+#
+# This version overwites the source file with the result. In this way there is only one file used, and Nautilus does not
+# get confused and select an unrelated file.
+#
+# The encryption result is currently held in memory before the overwrite, which could be a problem if the source
+# file is very large.  It would be better to create a /tmp file, then copy that for the overwrite step.  For very large
+# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
+
+import sys
+import subprocess
+import os
+
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+def message(mess):
+  dlg = Gtk.MessageDialog(
+    message_type=Gtk.MessageType.ERROR
+    ,buttons=Gtk.ButtonsType.OK
+    ,text=mess
+    )
+  dlg.set_title('Encrypt Info')
+  dlg.run()
+  dlg.destroy()
+
+def run(command):
+  #print("command: " ,command)   
+  proc = subprocess.Popen(
+    command
+    ,stdout = subprocess.PIPE
+    ,stderr = subprocess.PIPE
+  )
+  stdout, stderr = proc.communicate()
+  # print("stdout: ", len(stdout) ," " ,stdout)
+  # print("stderr: ", len(stderr) ," " ,stderr)
+  # print("proc.returncode: ", proc.returncode)
+  return proc.returncode, stdout, stderr
+
+file_src = sys.argv[1]
+if not os.path.exists(file_src):
+  message("file not found: " + file_src)
+  sys.exit(1)
+if os.path.getsize(file_src) > 2**30:
+  message("beyond current Nautilus Encrypt file size limit of 1 gigbyte")
+  sys.exit(1)
+
+file_dst = sys.argv[1] + ".gpg"
+
+key_ids = [
+         "thomas-key-2911@reasoningtechnology.com"
+         ,"shihju@reasoningtechnology.com"
+         ]
+
+command = ["gpg2" ,"--quiet" ,"--encrypt" ,"--output" ,"-"]
+for id in key_ids:
+  command.append("-r")
+  command.append(id)
+command.append(file_src)
+code ,stdout ,stderr = run(command)
+
+# if all went well, the encrypted data is in stdout
+if code == 0:
+  if not os.path.exists(file_dst):
+    os.rename(file_src ,file_dst) 
+    with open(file_dst ,"wb") as f:
+      f.write(stdout)
+  else:
+    message(file_dst + " already exists")
+
+if len(stderr) > 0:
+  message(stderr.decode("utf-8"))
+
+
+
diff --git a/developer/nautilus/README.md b/developer/nautilus/README.md
new file mode 100644 (file)
index 0000000..ed5205d
--- /dev/null
@@ -0,0 +1 @@
+place these in user directories,  ~/.local/share/nautilus/scripts  or install the package nautilus-scripts-manager and put them in /usr/share/nautilus-script
diff --git a/developer/python3/gen_email b/developer/python3/gen_email
new file mode 100755 (executable)
index 0000000..a1057d9
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
+#
+
+import sys
+import random
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+# email addresses are not case sensitive
+# these are not all the legal characters, but rather the ones we think are legal and legible
+legal_chars_end = "abcdefghijkmnpqrstuvwxz"
+legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
+
+def index():
+  return random.randrange(0 ,len(legal_chars))
+
+def index_end():
+  return random.randrange(0 ,len(legal_chars_end))
+
+def char():
+  return legal_chars[index()]
+  
+def char_end():
+  return legal_chars_end[index_end()]
+
+def string(n=6):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0 : return ""
+
+  result = char_end()
+  if  n == 1: return result
+
+  for _ in range(n-2): result += char()
+  result += char_end()
+
+  return result
+
+def  test_0():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '~' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_1():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '0' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_2():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'z' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_3 ():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'A' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_4():
+  s0 = string()
+  s1 = string(10)
+  s2 = string(100)
+
+  print(s0)
+  print(s1)
+  print(s2)
+
+  return len(s0)==6 and len(s1)==10 and len(s2)==100
+
+
+n=6
+if len(sys.argv) > 1:
+   n = int(sys.argv[1])
+print(string(n))
+
diff --git a/developer/python3/gen_passwd b/developer/python3/gen_passwd
new file mode 100755 (executable)
index 0000000..d7cc5d4
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
+#
+
+import sys
+import random
+
+#debug = True
+debug = False
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+# zero and oh of course
+# SNCF does not take an & as a special hmm.
+chars_alpha_small = "abcdefghijkmnpqrstuvwxz"
+chars_alpha_big = "ABCDEFGHJKLMNPQRSTUVWXYZ"
+chars_special = "+-_$.,;?"
+chars_numeric = "23456789"
+
+sets_leftmost=[chars_alpha_small ,chars_alpha_big]
+sets_standard=[chars_alpha_small ,chars_alpha_big ,chars_special ,chars_numeric]
+sets_rightmost=[chars_alpha_small ,chars_alpha_big ,chars_numeric]
+
+def set_psets(sets):
+  len_sum = sum(len(x) for x in sets)
+  psets = [len(x)/len_sum + 1e-7 for x in sets]
+  if debug: print("psets" ,psets ,"sum:" ,sum(psets))
+  return psets
+
+def choose_set(sets):
+  psets = set_psets(sets)
+  x = random.random()
+  if debug: print("x:" ,x)
+  if len(psets) == 0: return 0
+  p = psets[0]
+  choice = len(psets) - 1
+  i = 0
+  while i != len(psets) - 1:
+    if x <= p : 
+      choice = i
+      break
+    i += 1
+    p += psets[i]
+  if debug: print("choice:" ,choice)
+  return choice
+
+def get_char_set(set):
+  index = random.randrange(0 ,len(set))
+  return set[index]
+
+def get_char(sets):
+  set = sets[choose_set(sets)]
+  return get_char_set(set)
+  
+def get_string(n):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0: return ""
+  if n == 1: return get_char_set(chars_alpha)
+
+  result = ""
+  result += get_char(sets_leftmost)
+  for _ in range(n-2): result += get_char(sets_standard)
+  result += get_char(sets_rightmost)
+
+  return result
+
+def get_passwd(n ,strict):
+  s = get_string(n)
+  while strict:
+    has_special = any(i in s for i in chars_special)
+    has_numeric = any(i in s for i in chars_numeric)
+    if debug: print("strict:" ,has_special ,has_numeric)
+    if has_special and has_numeric:
+      break
+    s = get_string(n)
+  return s
+
+strict = False
+n=9
+for arg in sys.argv[1:]:
+  if arg.isdigit(): n = int(arg)
+  if arg == "strict": strict = True
+
+if debug:
+  print("n:" ,n)
+  print("strict:" ,strict)
+  
+pw = get_passwd(n ,strict)
+print(pw)
+sys.exit(0)
+
+
diff --git a/developer/python3/gen_sig b/developer/python3/gen_sig
new file mode 100755 (executable)
index 0000000..c6b254b
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#
+
+import sys
+import random
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+legal_chars_end = "abcdefghjkmnpqrstuvwxz"
+legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
+
+def index():
+  return random.randrange(0 ,len(legal_chars))
+
+def index_end():
+  return random.randrange(0 ,len(legal_chars_end))
+
+def char():
+  return legal_chars[index()]
+  
+def char_end():
+  return legal_chars_end[index_end()]
+
+def string(n=6):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0 : return ""
+
+  result = char_end()
+  if  n == 1: return result
+
+  for _ in range(n-2): result += char()
+  result += char_end()
+
+  return result
+
+def  test_0():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '~' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_1():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '0' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_2():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'z' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_3 ():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'A' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_4():
+  s0 = string()
+  s1 = string(10)
+  s2 = string(100)
+
+  print(s0)
+  print(s1)
+  print(s2)
+
+  return len(s0)==6 and len(s1)==10 and len(s2)==100
+
+
+n=16
+if len(sys.argv) > 1:
+   n = int(sys.argv[1])
+print(string(n))
+
diff --git a/developer/scratchpad/.gitignore b/developer/scratchpad/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore
diff --git a/developer/tool/env b/developer/tool/env
new file mode 100644 (file)
index 0000000..7fd5455
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  env_must_be="tool_shared/bespoke/env"
+  error=false
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    error=true
+  fi
+  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+    echo "$script_afp:: This script must be sourced, not executed."
+    error=true
+  fi
+  if $error; then exit 1; fi
+
+# so we can do the build
+
+export PATH=\
+"$REPO_HOME"/developer/tool/\
+:"$REPO_HOME"/tool_shared/bespoke/\
+:"$PATH"
+
+# misc
+
+  # make .githolder and .gitignore visible
+  alias ls="ls -a"
+
+# some feedback to show all went well
+
+  export PROMPT_DECOR="$PROJECT"_developer
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+  cd "$REPO_HOME"/developer/
+
+
+
diff --git a/developer/tool/make b/developer/tool/make
new file mode 100755 (executable)
index 0000000..5ab34eb
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/env /bin/bash
+
+set -e
+cd ${REPO_HOME}/developer
+/bin/make -f tool/makefile $@
+
diff --git a/developer/tool/makefile b/developer/tool/makefile
new file mode 100644 (file)
index 0000000..8a64b72
--- /dev/null
@@ -0,0 +1,17 @@
+# /bin/make must be run from $REPO_HOME/developer
+
+RESOURCE:=$(REPO_HOME)/developer
+include $(RESOURCE)/make/environment_RT_0
+
+# override defaults
+LIBDIR=scratchpad
+
+# compiler to use
+C=gcc
+CFLAGS= -Werror -include "$(RESOURCE)/make/RT_0.h" -I$(INCDIR) 
+LINKFLAGS=-L$(LIBDIR) -L/usr/lib64 -L/usr/lib -l$(PROJECT)
+
+# Import the rules. The dash prefix means to ignore include errors. This is
+# required because the DEPFILE might not exist yet.
+include $(RESOURCE)/make/targets
+-include $(DEPFILE)
diff --git a/developer/tool/release b/developer/tool/release
new file mode 100755 (executable)
index 0000000..2846eac
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  if [ -z "$REPO_HOME" ]; then
+    echo "$(script_fp):: REPO_HOME is not set."
+    exit 1
+  fi
+
+  env_must_be="developer/tool/env"
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    exit 1
+  fi
+
+# script local environment
+
+  release_dir="$REPO_HOME/release"
+  shell_dir="$REPO_HOME/developer/shell"
+
+  if [ ! -d "$release_dir" ]; then
+    mkdir -p "$release_dir"
+  fi
+
+  # Function to copy and set permissions
+  install_file() {
+    source_fp="$1"
+    target_dp="$2"
+    perms="$3"
+
+    target_file="$target_dp/$(basename "$source_fp")"
+
+    if [ ! -f "$source_fp" ]; then
+      echo "install_file:: Source file '$source_fp' does not exist."
+      return 1
+    fi
+
+    if ! install -m "$perms" "$source_fp" "$target_file"; then
+      echo "Error: Failed to install $(basename "$source_fp") to $target_dp"
+      exit 1
+    else
+      echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms"
+    fi
+  }
+# do the release
+
+  echo "Starting release process..."
+
+  # Install shell scripts
+  for script in $shell_dir/*; do
+    install_file "$script" "$release_dir" "ug+r+x"
+  done
+
+echo "$(script_fp) done."
diff --git a/env_administrator b/env_administrator
new file mode 100644 (file)
index 0000000..bb09700
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+source tool_shared/bespoke/env
+source tool/env
+
diff --git a/env_developer b/env_developer
new file mode 100644 (file)
index 0000000..6240b20
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+source tool_shared/bespoke/env
+source developer/tool/env
+
diff --git a/tool/env b/tool/env
new file mode 100644 (file)
index 0000000..73eaff8
--- /dev/null
+++ b/tool/env
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  env_must_be="tool_shared/bespoke/env"
+  error=false
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    error=true
+  fi
+  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+    echo "$script_afp:: This script must be sourced, not executed."
+    error=true
+  fi
+  if $error; then exit 1; fi
+
+export PATH=\
+"$REPO_HOME"/tool_shared/bespoke/\
+:"$PATH"
+
+# expose sneaky hidden files
+alias ls="ls -a"
+
+# some feedback to show all went well
+
+  export PROMPT_DECOR="$PROJECT"_administrator
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+
+
+
+
diff --git a/tool_shared/bespoke/cat_w_fn b/tool_shared/bespoke/cat_w_fn
new file mode 100755 (executable)
index 0000000..3308525
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# Check if at least one file is provided
+if [ $# -eq 0 ]; then
+  echo "Usage: $(script_fp) <filename1> [filename2] ..."
+  exit 1
+fi
+
+# Loop through all the provided files
+for file in "$@"; do
+  # Check if the file exists
+  if [ ! -f "$file" ]; then
+    echo "Error: File '$file' not found!"
+    continue
+  fi
+
+  # Print 80 dashes
+  printf '%.0s-' {1..80}
+  echo
+
+  # Print the filename and a colon
+  echo "$file:"
+
+  # Print the contents of the file
+  cat "$file"
+
+  # Print a newline for spacing between files
+  echo
+done
diff --git a/tool_shared/bespoke/env b/tool_shared/bespoke/env
new file mode 100644 (file)
index 0000000..4fa561b
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+# --------------------------------------------------------------------------------
+# project definition
+
+# actual absolute director path for this script file
+
+  script_adp(){
+    dirname "$script_afp"
+  }
+
+# assume this script is located  $REPO_HOME/tools_shared/bespoke and work backwards
+# to get $REPO_HOME, etc.
+
+  REPO_HOME=$(dirname "$(dirname "$(script_adp)")")
+  echo REPO_HOME "$REPO_HOME"
+
+  PROJECT=$(basename "$REPO_HOME")
+  echo PROJECT "$PROJECT"
+
+  # set the prompt decoration to the name of the project
+  PROMPT_DECOR=$PROJECT
+
+# --------------------------------------------------------------------------------
+# The project administrator sets up the following tools for all roles to use:
+#
+  export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+
+# --------------------------------------------------------------------------------
+# the following functions are provided for other scripts to use.
+# at the top of files that make use of these functions put the following line:
+#  script_afp=$(realpath "${BASH_SOURCE[0]}")
+#
+
+  ## script's filename
+  script_fn(){
+    basename "$script_afp"
+  }
+
+  ## script's dirpath relative to $REPO_HOME
+  script_fp(){
+    realpath --relative-to="${REPO_HOME}" "$script_afp"
+  }
+
+  ## script's dirpath relative to $REPO_HOME
+  script_dp(){
+    dirname "$(script_fp)"
+  }
+
+# --------------------------------------------------------------------------------
+# Exports
+# Bash has no 'closure' hence when exporting a function, one must also export all the pieces.
+# do not export script_afp
+
+  export REPO_HOME PROJECT PROMPT_DECOR
+  export -f script_adp script_fn script_dp script_fp
+
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+
diff --git a/tool_shared/bespoke/githolder b/tool_shared/bespoke/githolder
new file mode 100755 (executable)
index 0000000..49fb12b
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/env /bin/bash
+
+# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
+# does not descend into hidden directories.
+
+# examples:
+#   > git_holder
+#   > git_holder --dry-run
+
+set -e
+
+find_empty_dirs() {
+  local dir="$1"
+  local dry_run="$2"
+
+  # Skip `.git` specifically
+  if [[ "$(basename "$dir")" == ".git" ]]; then
+    return
+  fi
+
+  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
+  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
+    if [[ "$dry_run" == "true" ]]; then
+      echo "Dry-run: Would add .githolder in $dir"
+    else
+      echo "Adding .githolder to $dir"
+      touch "$dir/.githolder"
+    fi
+  else
+    # Recurse into subdirectories
+    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
+      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
+        find_empty_dirs "$subdir" "$dry_run"
+      fi
+    done
+  fi
+}
+
+# Default parameters
+dry_run="false"
+target_dir="."
+
+# Parse arguments
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --dry-run)
+      dry_run="true"
+      shift
+      ;;
+    *)
+      if [[ -d "$1" ]]; then
+        target_dir="$1"
+        shift
+      else
+        echo "Invalid argument: $1 is not a directory"
+        exit 1
+      fi
+      ;;
+  esac
+done
+
+# Run the function
+find_empty_dirs "$target_dir" "$dry_run"
diff --git a/tool_shared/bespoke/version b/tool_shared/bespoke/version
new file mode 100755 (executable)
index 0000000..04237c4
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# 2024-11-21 fits project skeleton convention
+echo v3.0
+
diff --git a/tool_shared/bespoke/vl b/tool_shared/bespoke/vl
new file mode 100755 (executable)
index 0000000..2c968d3
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+# vl 'vertical list'
+
+# Check if the command is provided
+if [ -z "$1" ]; then
+  echo "Usage: vl <command> [args...]"
+  exit 1
+fi
+
+# Capture the command and its arguments
+cmd=$1
+shift
+
+# Run the command with the remaining arguments and replace colons or spaces with newlines
+"$cmd" "$@" | tr ' :' '\n'
+
+exit 0
diff --git a/tool_shared/third_party/.gitignore b/tool_shared/third_party/.gitignore
new file mode 100644 (file)
index 0000000..525ec6b
--- /dev/null
@@ -0,0 +1,4 @@
+*
+!/.gitignore
+# upstream has a .gitignore file in it, edit to keep anything precious
+!/upstream
diff --git a/tool_shared/third_party/upstream/.gitignore b/tool_shared/third_party/upstream/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore