BSH(1L)

📦 version 2022.10.16, in opensuse-leap 16.0

🌸 BSH(1L) — Schily´s USER COMMANDS 🌸

okay so bestie, welcome to section 1L of Schily´s USER COMMANDS, and today's main character is bsh 💅 no cap, this page is long so buckle up, we're doing it in parts fr fr.


✨ NAME ✨

bsh — ein Kommando-Interpreter mit Bildschirmeditor und History. 🎀


🦋 SYNOPSIS 🦋

bsh [ optionen ] [ arg1 ... argn ]

Liest Kommandos aus dem File arg1. Wenn keine Argumente angegeben sind, liest er Kommandos von stdin. that's it, that's the vibe check ✅


💜 OPTIONEN 💜

  • -i — Erzwingt interaktiven Prompt. 💬
  • -v — Startet mit eingeschaltetem Verbose-Mode. 👀
  • -c — Führt arg1 als Kommando mit arg2-n als Argumenten aus. 🔥
  • -e — Bricht ab wenn ein nichtinteraktives Kommando mißlingt. 💀
  • -n — Liest die Kommandos, führt sie aber nicht aus. (nur zugucken, not me doing the work 🙈)
  • -s — Führt Kommandos von stdin aus, auch wenn Argumente angegeben wurden. 🫶
  • -t — Liest ein Kommando und führt es aus. one (1) command, iconic
  • -2 — Liest nicht das ~/.init2 File. Auch wahr, wenn -c gesetzt und name == command. ⭐
  • -h — Liest/Schreibt nicht das ~/.history File. 🎀
  • -g — Liest/Schreibt nicht das ~/.globals File. 🌈
  • -l — Liest/Schreibt nicht das ~/.locals File. 🌸
  • -f — (fast) Entspricht -2h. ⚡
  • -F — (extra fast) Entspricht -2hgl. ⚡⚡
  • -o — Bei einem exec werden offene Files nicht geschlossen. 🚪✨

👑 BESCHREIBUNG 👑

bsh ist ein Kommandointerpreter, der anstelle von sh oder csh verwendet werden kann. Seine Vorteile gegenüber den beiden anderen Shells sind der Bildschirmeditor für die Kommandozeile und der in diesem Editor integrierte History-Mechanismus. so basically: glow-up für deine Shell, periodt 💅✨


🧚 Initialisierung 🧚

Wenn der bsh durch ein Login gestartet wird, (das erkennt er daran, dass sein argv[0] mit einem - beginnt) dann liest er zunächst die Datei /etc/initbsh und führt die darin enthaltenen Kommandos aus. — Das kann auf System V dazu benutzt werden um z.B. die Environment-Variable TZ zu setzen. 🕰️

Wenn in av[0] ein r enthalten ist (rbsh), dann folgt nach der Interpretation der Anweisungen aus der Datei /etc/initbsh die Ausführung der Kommandos aus /etc/initrbsh. Das kann z.B. dazu benutzt werden, weiter unten beschriebene mögliche Restriktionen zu aktivieren. Da das Verzeichnis /etc/ normalerweise nur durch den Superuser schreibbar ist, kann ein so eingeschränkter Benutzer nicht durch einfaches Löschen seiner ~/.init Datei diese Beschränkungen wieder unwirksam machen. 🔒 (security ate, fr)

Nach der Interpretation der obengenannten Dateien werden die Kommandos aus der Datei ~/.init ausgeführt. In dieser Datei kann der Benutzer private, immer nötige Anweisungen platzieren, wie z.B. das Einstellen des Prompts auf einen gegenüber dem Standardprompt bevorzugten Wert oder Terminalinitialisierung. 💖

Jeder weitere Kommandointerpreter (nicht der Loginshell aber auch das in den bsh eingebaute suid Kommando), der vom Benutzer gestartet wird, führt während seiner Initialisierung die Datei ~/.init2 (falls vorhanden) aus. 🌀

Wenn der bsh gestartet wird, liest er kurz vor dem ersten interaktiven Prompt das File /etc/termcap oder die Environmentvariable TERMCAP, um ein Standardmapping für die Cursortasten zu bekommen. Es ist möglich, zusätzlich zu den Standardeinträgen ku, kd, kr und kl für Key-up, Key-down, Key-right und Key-left in /etc/termcap die Einträge kB und kE einzuführen, falls das Terminal die Cursortasten Zeilenanfang bzw. Zeilenende hat. ⌨️✨

Der Loginshell führt, bevor er durch die Kommandos logout oder exit beendet wird, die Datei ~/.final aus. 👋

Außerdem liest jeder bsh noch folgende Dateien, wenn er gestartet wird:

  • ~/.bshmap — Datei mit Maps für den Editor. 🗺️
  • ~/.globals — Datei mit globalen Abkürzungen. 🌍
  • .locals — Datei mit lokalen Abkürzungen. (Siehe auch cd - Kommando.) 🏠

Der bsh liest seine Initialisierungsdateien in folgender Reihenfolge und zu folgenden Zeiten:

  • /etc/passwd — falls es beim Starten des bsh keine Environment-Variable HOME gibt.
  • ~/.globals — Immer falls vorhanden.
  • .locals — Immer falls vorhanden.
  • /etc/initbsh — Nur Loginshell.
  • /etc/initrbsh — Nur Loginshell, wenn restricted.
  • ~/.init — Nur Loginshell.
  • ~/.init2 — Jeder nicht Loginshell.
  • ~/.history — Jeder interaktive bsh.
  • /etc/termcap — Jeder interaktive bsh kurz nach dem ersten Prompt, wenn sich der extrahierte TERMCAP Eintrag noch nicht im Environment befindet. Wenn die Variable TERM auf einen anderen Eintrag verweist als die Variable TERMCAP, dann wird auch das File /etc/termcap gelesen.
  • ~/.bshmap — Nach der Initialisierung der Cursormappings. 🖱️

🎀 Bedienung, Kommandoeingabe 🎀

Eingabezeilen können mit folgenden Kommandos bzw. Kommandosequenzen editiert werden:

  • ^H — ein Zeichen nach links ⬅️
  • ^F — ein Zeichen nach rechts ➡️
  • ^D — das Zeichen unter dem Textzeiger löschen 🗑️
  • DEL — das Zeichen links vom Textzeiger löschen
  • ^U — ganze Zeile löschen
  • ^L — ganzen Bildschirm löschen 🖥️✨
  • ESC ^H — ein Wort nach links
  • ESC ^F — ein Wort nach rechts
  • ESC ^D — das Wort rechts vom Textzeiger löschen
  • ESC DEL — das Wort links vom Textzeiger löschen

Innerhalb der History kann man sich mit folgenden Kommandosequenzen bewegen (näheres über die History unter Punkt Eingebaute Kommandos):

  • ^P — vorhergehende Zeile ⬆️
  • ^N — nachfolgende Zeile ⬇️
  • ESC ^P — rückwärts nach Zeile suchen 🔍
  • ESC ^N — vorwärts nach Zeile suchen 🔎
  • ESC CR — zurück zur Zeile vor dem letzten Suchkommando ↩️

Jedes andere Zeichen wird in den vorhandenen Text eingeschoben. Die Tabulator-Taste erzeugt ein ^I. Sollen in der Eingabe Zeichen erscheinen, die Editierungsfunktion haben, so müssen sie gequotet werden, dazu muss zuerst ^^ und dann das Zeichen, das in der Eingabezeile erscheinen soll, eingegeben werden; es wird dann nicht interpretiert. 🫶

Eine Zeile wird durch die Tasten CR oder LF beendet. Hierbei ist die Stellung des Textzeigers innerhalb der Zeile unerheblich. ✅


🦄 Editierungsmapping 🦄

Bei der Initialisierung des bsh wird das File ~/.bshmap gelesen, in dem sich Editierungsmaps für den bsh befinden. Es lässt sich fast alles ummappen. Wird ein Match festgestellt, so erfolgt eine textuelle Ersetzung direkt in die Eingabezeile. Es ist möglich, das Mapping für den nächsten Buchstaben mit Hilfe eines Quotebuchstabens aufzuheben. Dieser Quotebuchstabe ist standartmäßig auf NULL (Control @) gesetzt, und lässt sich ändern (z.Zt. noch nicht implementiert). 🚧

Das File ~/.bshmap hat folgenden Aufbau:

mapstr:textersatz:Kommentar

mapstr ist dabei der String, der ersetzt werden soll. textersatz ist der String, der in der Eingabezeile erscheint. Kommentar ist ein optionaler Kommentar, der nicht beachtet wird. mapstr darf maximal 16 Zeichen lang sein, der textersatz darf maximal 128 Zeichen lang sein. Jeder Eintrag muss auf genau einer Textzeile stehen. 📏

Kontrollzeichen können wie in /etc/termcap durch eine Ersatzdarstellung eingetragen werden:

Ein ^ vor einem Buchstaben bedeutet, dass das entsprechende Kontrollzeichen gemeint ist. Das Zeichen ESCAPE lässt sich durch \E darstellen. Diese beiden ebengenannten Escapezeichen lassen sich durch \^ bzw. \\ erzeugen. Es ist außerdem möglich die in C bekannte Oktaldarstellung zu verwenden. Nur mit der Oktaldarstellung ist es möglich, einen Doppelpunkt zu erzeugen in dem man \072 einträgt. 😌👌

Weiterhin stehen für:

  • \t — ^I — Horizontaltabulator
  • \v — ^K — Vertikaltabulator
  • \b — ^H — Backspace
  • \r — ^M — Wagenrücklauf
  • \n — ^J — Zeilenvorschub
  • \f — ^L — Seitenvorschub

Das File ~/.bshmap, könnte folgendermaßen aussehen. 👀

\Ep:\E^P^U:Search up and clear buf
\En:\E^P^U:Search down and clear buf

Das Standardmapping wird aus /etc/termcap gewonnen. ⭐


🌈 Lexikalische Struktur 🌈

Der bsh teilt Zeilen in Worte an den Stellen, wo Leerzeichen, Tabs oder die besonderen Buchstaben & , | , ; , < , > , ( und ), sowie die Buchstabenpaare && , || , << oder >> stehen. Die besondere Bedeutung dieser Buchstaben lässt sich durch Voranstellen eines \ verhindern. Ein \, das direkt von einem Newline gefolgt wird, wird durch ein Blank ersetzt, falls es nicht in einem mit ' gequoteten String erscheint. 🪄

Strings, die in Paare von ' oder " eingeschlossen sind, formen Worte. Werden die Strings in Paare von " eingeschlossen, dann erfolgt in diesen Strings eventuell eine textuelle Ersetzung von Abkürzungen oder Environment-Variablen. Eine textuelle Ersetzung lässt sich auch in diesem Falle durch Voranstellen eines \ verhindern. In Strings, die durch Einschließen in ' gebildet werden, wird nichts ersetzt und der Buchstabe \ hat keine besondere Wirkung, es sei denn, er steht vor einem Newline oder einem '. Damit ist es möglich, diese Buchstaben in einen String einzugeben. In beiden Fällen erfolgt jedoch in diesen Strings keine Expansion von speziellen Pattern-Matching Buchstaben über das File-System. 🧚✨

Der Buchstabe # hat eine besondere Bedeutung, wenn er am Anfang einer Zeile steht (siehe # - Kommandos). Innerhalb von Kommando-Files leitet er eine Kommentarzeile ein, wenn direkt hinter ihm ein Blank, ein Tab oder ein Newline steht. 💬

Ein einfaches Kommando ist eine Sequenz von Worten, von denen das erste Wort der Kommando-Name des auszuführenden Kommandos ist. 🫡

Ein einfaches Kommando oder eine Sequenz von einfachen Kommandos, durch ein | getrennt, ergeben eine Pipeline. Der Output eines jeden Programms wird in den Input des folgenden geleitet. Sequenzen von Pipelines können durch ; oder & getrennt werden. Steht hinter einer Pipeline ein &, wird auf diese Pipeline nicht gewartet. 🏃‍♀️💨

Jedes dieser oben beschriebenen Kommandos oder Kommandosequenzen kann in Paare von ( und ) gepackt werden, um so ein einfaches Kommando zu erzeugen. Es ist auch möglich, einzelne Kommandos einer Pipeline durch && oder || zu trennen. Dabei wird wie in der Programmiersprache c das zweite bzw. folgende Kommando nur dann ausgeführt, wenn das Erste bzw. Vorangehende gelang oder scheiterte. Auch hier können durch Verwendung von ( und ) Gruppen gebildet werden. 👯‍♀️

Beispiele:

Joerg> cd cmd/bsh && make bsh
...

make bsh wird nur ausgeführt, wenn das cd - Kommando geglückt ist. ✅

Joerg> make bsh || echo bullshit
...

Das echo Kommando wird nur dann ausgeführt, wenn das make Kommando scheitert. 💀

Joerg> (make bsh && echo ok) || echo bullshit
...

okay so if the make command fails, the second echo command gets executed. If the make command succeeds, then ok gets printed. But bestie, this is not a replacement for an if then else structure, because if the echo ok command fails, bullshit gets printed too — the exit code of the command group in parentheses is the exit code of the last command. 💅


🎀 Jobs und Jobkontrolle 🎀

The functionality for jobs and job control is implemented, but rn it is genuinely not documented. no cap.


✨ Textuelle Ersetzungen ✨

Textual replacements happen on several levels.

  • First, through the editing mapping (directly visible in the command line).
  • Then, through abbreviation macros from ~/.globals and .locals (see '#' commands), and through replacements via the contents of environment variables. Here it is important to know which separators recognize words from the input line that are then examined for expansion possibilities. Separators for these expansions are: " \t\n\\'$~/|&;()><%\"=-"
  • In the last stage, textual replacements happen via expansion over the filesystem. (see Pattern-Matching) Pattern-Matching metacharacters are: ! # % * { } [ ] ?

For the expansion, this is the chronological order and preference:

  • First during editing — Editierungsmapping.
  • Before parsing — local and global abbreviations, alternatively with preference for the local abbreviations.
  • Still before parsing — currently !!! '$' variables.
  • From the interpreter (directly before execution of the program) — expansions via the file system.

All these replacements can be prevented by putting a \ in front of the corresponding identifier. 🫶


🌊 Input/Output 🌊

Every process has three files it is connected to by default.

  • stdin — the standard input file (Standardeingabedatei)
  • stdout — the standard output file (Standardausgabedatei)
  • stderr — the standard diagnostic file (Standarddiagnostikdatei)

These three files are normally assigned to the terminal. But you can redirect them with the following syntax:

  • < name — the file name is opened as the input file.
  • << delimiter — the bsh reads from stdin until a line contains delimiter. Everything entered up to that point is passed to the program as an input file after expansion via environment variables and abbreviations (globals and locals). One use is command files where input for a program, e.g. for an editor, is required; you can then keep everything in one file.
  • > name — the file name is opened as the output file. If it already exists, the old content is discarded.
  • >> name — the file name is opened as the output file. If it already exists, the program's upcoming output is appended to the already existing content.
  • % name — the file name is opened as the error file. If it already exists, the old content is discarded.
  • %% name — the file name is opened as the error file. If it already exists, the program's upcoming output is appended to the already existing content.
  • prog1 | prog2 — the output of prog1 is piped in a pipeline to the input of prog2.
  • prog1 |% prog2 — the error output of prog1 is piped in a pipeline to the input of prog2.

For name, expansion via the abbreviations and environment variables is performed each time. ✨


🧚 Variablen, Environment-Variablen 🧚

Variables can be stored and retrieved in the environment (EV). The bsh passes the current contents of its environment to the processes it starts.

Retrieval happens through expansion. If a word begins with $, the EV is searched for the corresponding variable, and the entire word (including $) is replaced by the value of that variable.

Variable expansion happens line by line. It is not possible to set a variable's value within one command line and then print its value afterward. If the word couldn't be expanded, it is taken over directly.

Examples, bestie:

Joerg> set x=hallo
Joerg> set
PATH=:/bin
HOME=:
TERM=vterm
PROMPT=Joerg>
PROMPT2=>
HISTORY=0
x=hallo
Joerg> echo $x $y
hallo $y
Joerg> set lalue=test;echo $lalue
$lalue
Joerg> _
  • $name — returns the value of the variable name.

The following variables can only be read, but not explicitly set:

  • $0 — returns the name of the running command file.
  • $1..$n — return the current arguments of a command file.
  • $r1 — returns all arguments of a command file (corresponding to argv+1 in c files).
  • $r3 — returns all arguments of a command file starting with the third argument (corresponding to argv+3 in c files).
  • $# — returns the number of arguments of the current command file (corresponding to argc in c — argument $0 counts too).
  • $$ — returns the process ID of the currently running bsh.

Example:

Joerg> kill $$
name: _

This terminates the running bsh.

  • $! — returns the process ID of the last started background process.

Example:

Joerg> ps -l $!

This prints the status of the last background process.

  • $? — returns the return value of the last commands.

Example:

Joerg> test 6 '*' 4
Joerg> echo $?
0

🦋 Expansion des Zeichens '~' 🦋

The character ~ expands to a pathname. It can be followed by a username. Without a username it produces the pathname of your own HOME directory from the file /etc/passwd; with a username it produces the pathname of that user's HOME directory.

Examples:

Joerg> pwd
/user/joerg
Joerg> echo ~
/user/joerg
Joerg> echo ~peter
/user/peter
Joerg> ls ~peter/bin
/user/peter/bin:
bsh
Joerg> ls ~/..
/user:
gerd
joerg
peter
reiner
Joerg> ls ~/cmd/bsh/doc
bsh.doc
Joerg> _

👑 Pattern-Matching 👑

There are certain letters that have a special meaning when expanding filenames, when searching in the history, and when outputting '#' abbreviations. They are:

! # % * { } [ ] ?

Their meaning is:

  • ! — ALT — or in matching dies!das!jenes
  • * — STAR — any arbitrary number of any arbitrary character.
  • ? — ANY — exactly one arbitrary character.
  • % — NIL — exactly no !!! character. (Must be quoted so that no redirection of stderr happens.)
  • {} — GROUP — for precedence grouping. Can be nested.
  • #c — MULT — any arbitrary number of a particular character.
  • [] — CLASS — encloses a set of characters.
  • - — RANGE — range for sets.
  • ^ — NOT/BEG — beginning of a line; in [] the boolean not.
  • \ — ESC — escape character for the pattern matcher.
  • $ — END — end of a line.

Examples:

Joerg> echo bsh.?
bsh.c bsh.h
Joerg> echo *.bak
test.c.bak bsh.c.bak mem.c.bak
Joerg> echo test#1
test1 test11 test111
Joerg> echo dies!das
dies das
Joerg> echo b*.{lint!c}
bsh.c bsh.lint btab.c builtin.c
Joerg> echo [a-i]*.c
abbrev.c abbtab.c builtin.c input.c
Joerg> echo ab[0-9].c
ab1.c ab2.c ab3.c
Joerg> echo [^i]*.c
builtin.c mem.c test.c

💅 Eingebaute Kommandos 💅

Built-in commands, bestie:

  • $ — see the fg command.
  • : — this is a dummy command. For example, it makes it possible to create files.

Example:

Joerg> :>hallo
Joerg> echo *
hallo test.c
Joerg> _
  • @ name = expr — assigns the value of the simple expression expr to the environment variable name.

Instead of = you can also use +=, -=, /=, %= or *=. For expr, every expression is allowed that is also possible in the test command.

Example:

Joerg> @ count = 1
Joerg> @ count = $count + 1
Joerg> echo $count
Joerg> 2
Joerg> _
  • [ expr ] — synonym for the test command. See test for the description.
  • alias [fromstr] [tostr] — replacement for the '#' commands (not fully implemented yet).
  • alloc [arg] — used for debugging the bsh allocation routine. Without arguments, it prints statistics about the allocated area. With an argument, it prints the addresses and sizes of the managed chunks, as well as the state of the chunks. Destroyed chunks are marked by a star after the status information. With an l as the argument, the readable content is additionally printed for each chunk; with an L as the argument, a replacement representation is shown for unreadable content.
  • bg [job] — sends the most recently stopped job, or the specified job, to the background. It restarts it. Currently the job can only be specified by the process ID of one of the job's processes.
  • break — breaks a loop. Interpretation continues with the command that follows the next end.

Example:

Joerg> for i in 1 2 3 4 5 6
> if test $i = 3
> then
> echo ende.
> break
> fi
> echo $i
> end
1
2
ende.
Joerg> _
  • case — needed for the switch command to recognize a possibility. Outside a switch command, case is not allowed.
  • cd [name], chdir [name], cwd [name] — change the bsh's working directory to directory name. If name is not given, it switches to the directory given in the environment variable HOME.

if the environment variable CDPATH exists, name also gets searched in the matching directories from the list in CDPATH. If a cd lands in one of those list directories, the whole name gets printed. And every single cd swaps the local abbreviations list (./.locals) with the current one. 💅

compute

obsolete intrinsic routine of bsh for basic arithmetic on integer numbers.

It sets variable $? to the result of the calculation. Since there is no way to detect bad parameters via the return code, it's getting removed soon.

bestie, please only use @ or test from now on. no cap.

concat name val1 ... valn

The string values val1 ... valn get squished together into one string in variable name.

Examples:

Joerg> concat test a b c . $$
Joerg> echo $test
abc.5123
Joerg> _

dirs

Prints the directory stack. The top is on the left and is the current working directory. The top of the directory stack has logical offset 0, and the directory directly to its right has logical offset -1. That logical offset is useful for the pushd and popd commands.

do

The first argument of the do command is treated as a command line and interpreted as if the remaining arguments of the do command were av[2] .. av[n] of bsh. The effect is the same as bsh -c arg1 .. argn, without starting a new shell.

Examples:

Joerg> do 'echo hallo: $r1' 1 2 3 4 5
hallo: 1 2 3 4 5
Joerg> _

echo [-n|-nnl] [args]

The echo command does the same job as /bin/echo, but because it's built into bsh its execution time is much shorter (important in command-files). If the first argument is -n or -nnl, no newline character is printed at the end of the line.

If no arguments are given, no newline character is printed either. If you only want to print a newline, you have to pass an empty string as parameter.

If no arguments are given and stdin is redirected, echo reads from stdin and writes what it read to stdout (similar to cat).

If you don't want to use the built-in echo command, you have to write /bin/echo.

Examples:

Joerg> echo test *.c
test program.c t.c zz.c
Joerg> echo -nnl huhu;echo .pas
huhu.pas
Joerg> echo < .EDTMP;echo ''
bsh.c
Joerg> _

else / end

See the description of if, switch, loop and for.

err

Same function as echo, but the output goes to stderr.

errstr errno

The error text for error number errno gets printed.

eval

XXX — that's literally all the page says, bestie 😭. Iconic mystery era.

exec [ av0=name] command [args]

Overwrites the current command interpreter with the command command.

With the option av0=name it's possible to give the command an av[0] that differs from its name. If exec is called in a login shell, you get a new login prompt when the command command ends.

Examples:

Joerg>
Joerg2> exec date
Tue Aug 6 1985 13:57:52
Joerg> exec av0=- bsh
Joerg 2> _

The last example starts a bsh that thinks it was started by a login process.

exit [Rückgabewert]

Ends a command interpreter or aborts a command file. The return value can be defined with exit <n>. exit without a parameter produces a return value of zero.

Examples:

Joerg> bsh
Joerg> exit 55
Joerg> echo $?
55
Joerg> _

fg

XXX — placeholder central, no cap 🙈.

fi

fi is the end of an if command.

for name in [Wortliste]

Loop. for i in a b c runs all following commands (until end). The environment variable i gets the values a, b, and c for the three loop passes.

Examples:

Joerg> for i in 1 2 3
> echo $i
> end
1
2
3
Joerg> _

function [name] ['cmdlist']

Defines a function with name name and body cmdlist. When entering it, cmdlist should definitely be wrapped in '''. cmdlist can also span multiple lines if there is a \ directly before the end of every line (see also quoting). Functions can be called recursively.

You call it by entering the function name. Right now it's not possible to pass arguments. A function can be ended with return.

glob [args]

Same function as echo, except the individual words in the output are separated by NUL bytes.

history

Prints the most recently executed commands (see point 4). If the output goes to stdout, the commands are printed in curly braces; with a pipe or to a file, the curly braces are dropped. For later use with source -h.

Examples:

Joerg> history
{ cat *.c }
{ who am i }
{ date }
Joerg> _

if

XXXX — the manpage really says that, bestie 💀.

if (expr)
if command args
if command args
then
....
fi
if command args
else
....
fi
if command args
then
....
else
....
fi

Condition check. The if command must be followed by a command or a simple expression like in test in (). If the return value of that command is equal to zero, it's TRUE; otherwise FALSE. If TRUE is detected, the commands between the next then and the matching else or fi are executed. If FALSE is detected, the commands between else and fi are executed, if else is present.

Achtung: then, else and fi must be on their own line.

Examples:

Joerg> if cc -c programm
> then
> cc -o programm programm.o
> echo fertig.
> else
> echo FEHLER im programm
> fi
programm.c:
linking programm:
fertig.
Joerg> _

kill [-l] [-sig] pid1 ... pidn

With kill you can send signals to processes. If no signal number is given, signal SIGTERM (15) is sent. But you can specify other signals either by using the signal number with a leading - or by using the symbolic name of the signal from signal.h without the SIG prefix.

With the option -l you can get a list of allowed signals.

Under 4.2BSD, if the specified signal is SIGHUP or SIGTERM, bsh additionally sends the signal SIGCONT to wake up the process in question if it's suspended.

Examples:

Joerg> kill -l
HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV
SYS PIPE ALRM TERM URG
STOP TSTP CONT CHLD TTIN TTOU TINT XCPU XFSZ
VTALRM PROF WINCH
Joerg> kill -HUP 1
Joerg> kill -9 123
Joerg> kill 817 900
Joerg> _

killpg [-l] [-sig] pgrp1 ... pgrpn

killpg has the same function as kill, except the signal sig is sent to the process groups pgrp1 through pgrpn.

limit

XXX — another placeholder, lowkey iconic 🫶.

login [name]

login is identical to exec /bin/login [name]. login is only allowed if this is the login shell.

Examples:

Joerg2> login
Not login shell.
Joerg2> <EOF>
Joerg> login hansi
Password:

logout

Ends the first command interpreter.

Examples:

Joerg2> logout
Not login shell.
use exit to exit.
Joerg2> <EOF>
Joerg> logout
name: _

loop

Infinite loop. All following commands (until end) are executed repeatedly. You can leave the loop with break, with ^C or with ^D.

Examples:

Joerg> loop
> echo -nnl "sag mal was: "
> read cmd
> echo soso, $cmd
> end
sag mal was: hallo
soso, hallo
sag mal was: huhu
soso, huhu
sag mal was: ^C
1234: killed
Joerg> _

map [fromstr] [tostr]

With map it's possible to remap arbitrary letters or strings of terminal input before they reach the bsh editor. Among other things, you can adapt the cursor keys to the bsh commands. If no argument is given, the current mapping is printed. It uses the replacement representation for control letters explained under point 3.

Examples:

Joerg> map
^[[220z^A
^[[222z^E
^[[226z^D
^[[A ^P
^[[B ^N
^[[C ^F
^[[D ^H
^[n  ^[^N^U
^[p  ^[^P^U
Joerg> map abc def
Joerg> _

newgrp

Changes the user group. Only on System V.

pgrp

XXX — placeholder again, bestie 😭.

popd [-offset]

popd without arguments does a cd to the directory to the right of the current working directory. But if you give an offset, it can go to another directory from the stack.

On every cd, the list of local abbreviations (./.locals) is swapped with the current one.

pushd [name] / pushd [-offset]

Like cd, but the working directory stays on the stack. Instead of a name, you can also give an offset in the stack.

  • cd (the tail end of it, bestie 💫) — every single time you cd, the list of local abbreviations (./.locals) gets swapped out for the current one. That's it, that's the vibe.
  • pwd — prints the current working directory. Works just like /bin/pwd, except it recognizes when you're hitting it repeatedly in the same directory and is therefore faster. Bonus: it also refreshes the $CWD variable. lowkey efficient icon behavior ✨
  • read name — the read function of the bsh lets you fill Environment variables interactively, so you can write command-files that do different things depending on what the user answers. And if read reads a ^D, then inside a loop the effect is the same as if a break had been executed. very much the polite way to bail 🫶

Examples:

Joerg> read cmdline
> huhu dies ist eine testeingabe
Joerg> echo $cmdline
huhu dies ist eine testeingabe
Joerg> _
  • remap — re-reads the file ~/.bshmap and the /etc/termcap entry. You need this when ~/.bshmap or /etc/termcap got extended by editing or changed some other way, or when the Environment variable TERM was changed. refresh the mapping, refresh your life 🦋

Examples:

Joerg> ved ~/.bshmap
.....
.....
Joerg> remap
Joerg> _
  • repeat [count=# | c=#|-#] [delay=# | d=#] command — runs the command command over and over. A variable substitution is only performed once. If count isn't given, then count = MAXLONG. If delay is given, the time between starting two consecutive commands is # seconds. set it and forget it, fr fr 🔁

Examples:

Joerg> repeat -5 echo hallo
hallo
hallo
hallo
hallo
hallo
Joerg> _
  • resume pid
  • resume pid & — continues the execution of a suspended process. The bsh then waits for it to finish. If the bsh shouldn't wait, the process can be started with resume <pid> &. The process ID that gets printed in that case is to be ignored. not me printing a pid you're supposed to ignore 💀

Examples:

Joerg> ved
.....
....
324: suspended.
Joerg> resume 324
.....
.....
Joerg> (sleep 100000;echo fertig)
^Y
Joerg> 328: suspended.
Joerg> resume 328 &
329
Joerg> _
  • return [retval] — with the return command you can end functions that were defined with the function command. You can pass a numeric argument. That argument can then be queried through the variable $?. If no argument is given, the return value is zero. graceful exits only, periodt 🎀
  • savehistory — with the savehistory command, the current contents of the History can be saved in the file ~/.history. One use case: you want to start a bsh that contains the history so far. carrying the lore forward 📜

Examples:

Joerg> history
set
test a
Joerg> savehistory
Joerg> bsh
Joerg 2 > history
set
test a
savehistory
Joerg 2 >
  • set [name=val] — sets an Environment variable. set x=huhu sets the Environment variable 'x' to the value 'huhu'. set with no parameters prints out the contents of the entire current Environment. the og variable setter 🌱

Examples:

Joerg> set x=7
Joerg> echo $x
7
Joerg> set x=9
Joerg> echo $x
9
Joerg> _
  • setenv [name val] — currently does the same thing as set. But since the number of variables the bsh manages has grown a lot, and it would be desirable for the functions, for example, to have Array variables too, so you could pass arguments to functions and stuff, the expansion of variables — and with it the behavior of the commands set and unset — has to change in the foreseeable future. The original function will then be taken over by the commands setenv and unsetenv. However, only certain variables will stay global. Local variables will then have to be handled with the command set or unset. future tea, currently same flavor 🍵

Examples:

Joerg> setenv x 7
Joerg> echo $x
7
Joerg> setenv x 9
Joerg> echo $x
9
Joerg> _
  • setmask
  • setmask ownermask groupmask worldmask
  • setmask [+-]{rwxd} [+-]{rwxd} [+-]{rwxd} — with the setmask command you can change or view the file-creation mask of the bsh. This mask is always used when a process creates a file. The current mask is produced by logically ANDing the mask and the requested modes. The file-creation mask is inherited by the children and matters for newly created files. permissions are the whole personality, iykyk 💅
    • + — in combination with r, w, x or d, adds this mode.
    • - — in combination with r, w, x or d, removes this mode.
    • r,w,x,d — without + or -, creates only this mode.
    • = — the modes stay as they are.
    • . — the modes are set to '....'.

Options have to be given in the right order. For Owner, Group and World a mode string has to be given. If no access is wanted, a . can be given; if a mode shouldn't change, a '=' can be given for that mode. setmask does not change the modes of existing files. existing files stay untouched, no cap 🙈

If no mask is given, the current mask is printed.

Examples:

Joerg> setmask
rwx r.x r.x
Joerg> setmask rwx x -x+w
Joerg> setmask
rwx ..x rw.
  • shift [n] — with the shift command, if shift was called without arguments, the argument $1 is eliminated from the argument list of the current bsh. If shift is called with an argument, that many arguments get removed starting from argument $1. bye bye first argies 👋

Examples:

Joerg> echo $r1
a b c d e f g h i j
Joerg> shift
Joerg> echo $r1
b c d e f g h i j
Joerg> shift 3
Joerg> echo $r1
e f g h i j
Joerg> shift 10
cannot shift.
Joerg> echo $r1
Joerg> _
  • signal [cmdlist] sig#1...sig#n — cmdlist gets executed when the bsh is waiting on a child and receives a signal from the given list. That's important, for example, to delete temporarily created files in commandfiles on an interrupt. The command given in cmdlist has to be in av[1], i.e. if it contains character or word separators, it has to be in '''. When cmdlist is executed, there's an Environment variable $signo containing the signal number. cmdlist can span multiple lines and contain if then else structures. See also function and call. catching signals like catching feelings 😭

A defined function can be deleted from the list with:

signal '' signalnummer

signal without parameters prints out the list of known signal handlers.

  • source name
  • source -h name
  • source -h — with this command the bsh can be made to read a command file and execute it. That way you can set Environment variables, for example. If the option -h is given, the file is only read and put into the History, but not executed. If the filename is left out while giving the -h option, the input comes via stdin. read it, don't do it — a whole mood 🦋

Examples:

Joerg> source -h ~/.history
Joerg> _
  • stop — XXX (that's literally all the docs say, bestie, we know nothing more 💀)
  • suid
  • suid name — Not under UNIX.

Changing the current user number. su without parameters starts a bsh with effective user number zero (Administrator). su with a parameter sets the real user number to that of the user given by the parameter. The Environment variable PROMPT is changed accordingly. The Administrator's password is recognized as correct in all possible cases. yes, in ALL possible cases — that's what it says 👀

Examples:

Joerg> su
Password:
admin> _

The effective user number is zero.

Joerg> su admin
Password:
++admin> exit
Joerg> su peter
Password:
++peter> _

The real user number is zero or that of the user 'peter'.

  • suspend [pid1 ... pidn] — if suspend is called without parameters, then the bsh itself gets suspended. With parameters, the processes with the process IDs pid1 ... pidn get suspended. That makes it possible to temporarily leave a su command and later start it again without a password. Unfortunately that doesn't work under SYSTEM V. SYSTEM V said no ✋ 😭
  • switch val of — conditional multi-way branching. The first parameter val is searched for, one after another, in a following pattern list (see case). All commands after the first successful pattern match for the parameter val are executed up to the keyword break. The usual pattern match rules explained above apply. For the default case there's a '*'. the og choose-your-own-adventure 🌈

Examples:

Joerg> set x=hallo
Joerg> switch $x of
> case a*
> case b*
> echo Erster Buchstabe ist ein A oder ein B
> break
> case h*
> echo Erster Buchstabe ist ein H
> break
> case *
> echo Erster Buchstabe ist nicht A B oder H
> end
Erster Buchstabe ist ein H
Joerg> _
  • sync — syncs the contents of the kernel file buffers for the filesystem with the real contents of the disk. flush it, don't rush it 💾
  • test expr — test evaluates the expression expr and assigns the variable $? a value not equal to zero if the expression expr is false, otherwise zero. If there's a syntax error, then the variable $? has the value -1. yes, -1 has entered the chat 🔥

The following expressions are possible for expr.

File tests:

  • -r file — wahr, wenn das File existiert und auch noch lesbar ist 👀
  • -w file — wahr, wenn das File existiert und beschreibbar ist ✍️
  • -x file — wahr, wenn das File existiert und ausführbar ist 🏃‍♀️
  • -e file — wahr, wenn das File überhaupt existiert (that's it, einfach nur da sein 💁‍♀️)
  • -s file — wahr, wenn das File existiert und eine Größe ungleich Null hat — also nicht leer, bestie 🎈
  • -S file — die Größe des Files ist der Exitcode. Wenn das File nicht existiert: -1. Ja, wirklich, der Exitcode ist literally die Filesize 😭
  • -d file — wahr, wenn das File existiert und eine Directory ist 📁
  • -c file — wahr, wenn das File existiert und ein character-special ist
  • -b file — wahr, wenn das File existiert und ein block-special ist
  • -f file — wahr, wenn das File existiert und ein reguläres File ist 📄
  • -h, -L file — wahr, wenn das File existiert und ein symbolischer Link ist 🔗
  • -p file — wahr, wenn das File existiert und eine named Pipe (fifo) ist
  • -C file — wahr, wenn das File existiert und ein Contiguous File ist
  • -u file — wahr, wenn das File existiert und das set-user-id Bit gesetzt ist
  • -g file — wahr, wenn das File existiert und das set-group-id Bit gesetzt ist
  • -k file — wahr, wenn das File existiert und das sticky Bit gesetzt ist ✨
  • -t fd — wahr, wenn der Filedescriptor fd im bsh mit einem Terminal verbunden ist 🖥️
  • -T fd — wahr, wenn der Filedescriptor fd im test Kommando mit einem Terminal verbunden ist

Stringtests: 🧵

  • -l string — die Länge des Strings ist der Exitcode 📏
  • -n string — wahr, wenn der String eine Länge ungleich Null hat
  • -z string — wahr, wenn der String eine Länge gleich Null hat
  • s1 = s2 — wahr, wenn s1 und s2 identisch sind
  • s1 == s2 — wahr, wenn s1 und s2 identisch sind (ja, beides, ist halt so 💅)
  • s1 != s2 — wahr, wenn s1 und s2 nicht identisch sind

Arithmetik: 🧮

Erlaubte Operatoren auf Ganzzahlen sind:

'+' , '-' , '*' , '/' , '%' , '&' , '|' , '&&' , '||' , '-eq' , '-ne' , '>' oder '-gt' , '<' oder '-lt' , '>=' oder '-ge' , '<=' oder '-le' , '>>' , '<<'.

Diese Operatoren können mit folgenden kombiniert werden:

  • ! — Negation 🙃
  • -a — Binäres und
  • -o — Binäres oder. (-a hat Vorrang gegenüber -o — ja, die Hierarchie ist real 👑)
  • -and — Logisches und
  • -or — Logisches oder. (-and hat Vorrang gegenüber -or)
  • ( expr ) — Klammerung zum Gruppieren 🫶

Alle Operatoren und Argumente müssen in separaten Argumenten stehen. No cap.

⚠️ Bei der Verwendung von Operatoren, die die Zeichen '>' , '<' , '%' , '*' , '&' , oder '|' enthalten, sind die Anführungszeichen bzw. ein '\' unbedingt anzugeben, um eine Interpretation durch den Parser des bsh zu verhindern. Sonst frisst der Parser deine Zeichen und du stehst da wie 🧍‍♀️
  • then — siehe if. Das wars, mehr gibt's nicht, go read if 💖
  • time — dieses Kommando ist zur Zeit noch nicht fertig implementiert, daher heißt es in der aktuellen Version time_ 😭 Geplant ist, damit eine Anzeige der Werte der Resource-Usage Struktur eines Prozesses anzeigen zu können. Also: kommt noch, versprochen 🫶
  • umask [mask] — ohne Argument wird die File-Erzeugungsmaske des bsh angezeigt, mit Argument kann die File-Erzeugungsmaske gesetzt werden. Im Gegensatz zu setmask ist mask hier oktal, wie bei /bin/sh oder /bin/csh 🐙 Das Kommando umask ist nur aus Kompatibilitätsgründen implementiert.
  • unalias — geplante Funktion als Ersatz für ein '#'-Kommando 🔮
  • unmap fromstr — mit dem unmap Kommando lassen sich Maps, die mit dem map Kommando gesetzt wurden, wieder aufheben. Da es möglich ist, verschiedene Fromstrings in den gleichen Tostring zu mappen, muss, um Eindeutigkeit zu bekommen, der Fromstring als Argument angeben werden. Das ist nur durch Quoten oder durch die Verwendung der Ersatzdarstellung möglich, es lässt sich also kein Beispiel zeigen 🙈 (ja, wirklich, kein Beispiel, ich schwör)
  • unset — löscht eine Environment-Variable 🧹

Beispiele:

Joerg> set test=uu
Joerg> set
PATH=:/bin:/usr/bin
HOME=/
TERM=vterm
IGNOREEOF=off
PROMPT=Joerg>
PROMPT2=>
HISTORY=30
test=uu
Joerg> unset test
Joerg> set
PATH=:/bin:/usr/bin
HOME=/
TERM=vterm
IGNOREEOF=off
PROMPT=Joerg>
PROMPT2=>
HISTORY=30
Joerg> _
  • unsetenv — siehe setenv 👋
  • wait
  • wait pid1..pidn — warten auf alle Kinder, die im Hintergrund ausgeführt werden, oder auf den/die, die sich in der Liste befinden. Das Warten kann mit Ctrl+C unterbrochen werden ⏳

Beispiele:

Joerg> sleep 100000&
518
Joerg> wait 518

Bei dem Versuch, das richtige Kommando zu finden, wird immer zuerst nach eingebauten Funktionen gesucht (siehe Kapitel Eingebaute Kommandos) 🔎; dann wird nach Funktionen gesucht, die mit dem function-Kommando definiert wurden. Alle Kommandos, die nicht auf eingebaute Funktionen referenzieren, werden mit execve gestartet und bekommen die Environment-Liste mit, die mit dem set-Kommando abgefragt werden kann 🚀

#️⃣ '#' Kommandos

Für alle Kommandos, die mit einem '#' beginnen, muss folgendes beachtet werden.: 👇

Sie werden nur erkannt, wenn sie das erste Kommando innerhalb einer Kommandozeile sind. In diesen Kommandos findet keine Expansion statt. Es ist keinerlei I/O Umleitung möglich 🚫 Für alle Kommandos ist eine Online-Helpfunktion eingebaut, die mit #c -help abgerufen werden kann, wobei c der Name des Kommandos ist. Slay, Hilfe ist immer nur einen Aufruf entfernt 💅

Es gibt eine Gruppe von '#'-Kommandos, die sich auf die Abkürzungsmöglichkeiten des bsh beziehen. Bei ihnen ist es möglich, sogenannte Modifier anzugeben, die das Kommando präzisieren oder als Option dienen. Der bsh kennt z.Zt. zwei Tabellen mit Abkürzungen. Solche, die überall gelten (~/.globals) , und solche, die nur in einer bestimmten Directory gelten (.locals). Bei dem Versuch, ein Wort zu expandieren, wird immer zuerst die lokale Tabelle durchsucht. Ist dort keine Abkürzung zu finden, wird versucht, eine globale Abkürzung zu finden. Abkürzungsexpansionen haben Vorrang vor den $-Expansionen 👑 Es gibt Abkürzungen, die nur am Anfang eines Kommandos stehen dürfen (auch nach einem ';' oder einem '&' sowie direkt nach einer '(' , die eine Kommandogruppe einleitet) und solche, die überall stehen dürfen. In absehbarer Zeit werden diese Kommandos mit Ausnahme des #! Kommandos in einen dem csh ähnlichen alias Mechanismus geändert 🔮

  • #a[g|l] Name Wert — fügt eine neue Abkürzung zur Tabelle hinzu. Name wird überall auf der Kommandozeile expandiert. Ist kein Modifier angegeben, erfolgt ein Eintrag in die Defaulttabelle ✨
  • #b[g|l] Name Wert — fügt eine neue Begin-Abkürzung zur Tabelle hinzu. Name wird nur am Anfang eines Kommandos expandiert. Ist kein Modifier angegeben, erfolgt ein Eintrag in die Defaulttabelle 🎬
  • #d[g|l] Name — löscht die Abkürzung Name aus der Tabelle. Ist kein Modifier angegeben, wird aus der Defaulttabelle gelöscht 🗑️
  • #h
  • #? — Ausgabe von Online-help Information über alle '#'-Kommandos 🙋‍♀️
  • #l[g|h] [h] [name] — Ausgabe aller Abkürzungen aus der Tabelle. Ist kein Modifier angegeben, wird die Defaulttabelle ausgegeben. Ist name angegeben, wird nur der Eintrag für name ausgegeben. Es ist erlaubt, das in name Wildcards des Pattern-Matchers stehen, um einen Teil der Tabelle auszugeben 🔍

Ist der Modifier 'h' angegeben, dann erfolgt zusätzlich zur Ausgabe ein Eintrag in die History. Damit lassen sich z.B. Einträge aus den Tabellen mit Hilfe des Editors des bsh verändern und neu eintragen 📝

  • #p[g|l] [a|b] Name Wert — mit dem '#p'-Kommando wird eine Abkürzung einer eventuell bestehenden überlagert, ohne sie in das dazugehörige File einzutragen. Damit lassen sich Änderungen für die Lebensdauer eines bsh erwirken. Die Information wird in einem Stack verwaltet. Wird ein gepushter Wert gelöscht, dann erscheint eine eventuell überlagerte Abkürzung wieder 🥞
  • #s[g|l] — Setzen der Default-Tabelle für '#'-Kommandos; also der Tabelle, auf die sich die Kommandos '#a','#b','#d','#l','#p' beziehen, wenn kein Modifier angegeben ist. Das '#s'-Kommando ohne Modifier bzw. mit dem Default-Wert, bewirkt eine Ausgabe der Default-Tabelle ⚙️
  • #v[on|off] — Setzen oder Lesen des Verbose-Modes, der falls eingeschaltet, jedes Kommando vor der Filenamenexpansion ausgibt 🗣️
  • #! shell [ args ] — ein alternativer Shell wird zur Ausführung des aktuellen Kommandofiles benutzt. Nur innerhalb von Command-Files möglich. Shell wird mit args und '$r0' gestartet 🐚
  • # — wird innerhalb von Command-Files ein '#' direkt von einem Blank, einem Tab oder einem Newline gefolgt, so gilt diese Zeile als Kommentar 💬

🕰️ History

Mit Hilfe der History können Kommandos gespeichert, abgerufen und geändert werden. Die History ist als begrenzter Ringpuffer implementiert 🔄 Kommandozeilen aus der History können mit den Cursor-Steuertasten (Cup und Cdown) abgerufen werden. Ein Zeilenende (CR oder LF) führt das Kommando aus ⚡

Jedes ausgeführte Kommando wird wieder an das Ende der History angefügt. Gleiche Kommandos werden weitgehend vermieden 🙅‍♀️ Das letzte Kommando aus der History lässt sich auch mit '!!' wiederholen. Mit '!<pattern>' lässt sich ein Kommando aus der History wiederholen, dass mit <pattern> beginnt 🔁

Beispiele:

Joerg> history
{ cd etc }
{ ved ttys }
{ p ttys }
{ who }
{ echo huhu >/etc/tty5 }
{ history }
Joerg> who
tty5 peter Fri Feb 1 1985 13:57:14
tty0 Joerg Fri Feb 1 1985 08:01:52
Joerg> history
{ cd etc }
{ ved ttys }
{ p ttys }
{ echo huhu >/etc/tty5 }
{ who }
{ history }
Joerg> !w
who
joerg ttyp3 Mar 5 16:55 (HARD)
klaus ttyp4 Mar 5 17:01 (TeSe)
Joerg> _

✨ Variablen mit besonderer Bedeutung für den bsh ✨

Okay bestie, jetzt kommt der spicy Teil 👀 — folgende Variablen kannst du sowohl erzeugen als auch lesen, aber lowkey haben sie alle eine implizite Wirkung darauf, wie der bsh so drauf ist. Also, sie sind nicht nur Deko, sie sind main character energy für die Shell selbst.


HISTORY 🔥

Bestimmt die maximale Anzahl der in der History gespeicherten Zeilen.

Beispiele:

Joerg> echo $HISTORY
20
Joerg> history
{ cd etc }
{ ved ttys }
{ p ttys }
{ who }
{ echo huhu >/etc/tty5 }
{ echo $HISTORY }
{ history }
Joerg> set HISTORY=4
Joerg> history
{ echo huhu >/etc/tty5 }
{ echo $HISTORY }
{ set HISTORY=4 }
{ history }
Joerg> _

Siehste? HISTORY=4 und zack — nur noch vier Zeilen übrig, die anderen sind einfach gone 💀


SAVEHISTORY 💾

Wenn diese Variable den Wert on hat, wird bei der Beendigung eines bsh der aktuelle Inhalt der History im File ~/.history gesichert. Und wenn ein interaktiver bsh gestartet wird und das File ~/.history existiert, wird es vor der Ausgabe des ersten Prompts gelesen. Also deine History überlebt den Logout, slay 🫶


PROMPT 🎀

Bestimmt den Benutzerprompt.

Beispiele:

Joerg> set "PROMPT=peter> "
peter> _

Dein Prompt, deine Regeln, periodt 💅


PROMPT2 🦋

Bestimmt den zweiten Benutzerprompt. Der wird ausgegeben, wenn der bsh zu einem Kommando noch weitere Eingaben braucht.

Beispiele:

Joerg> if echo ja
> then
> echo ja
> fi
ja
ja
Joerg> set "PROMPT2=more> "
Joerg> if echo ja
more> then
more> echo ja
more> fi
ja
ja
Joerg> _

Also standardmäßig dieses schlichte >, aber mit PROMPT2 machst du daraus dein eigenes kleines Markenzeichen ✨


PATH 🌈

In dieser Variablen ist eine Liste von Directories enthalten, die bei dem Versuch, ein Kommando zu starten, durchsucht werden. Die Liste wird von links nach rechts durchsucht. Der erste Eintrag sollte leer sein, um auf die aktuelle Workingdirectory zu verweisen. Die einzelnen Einträge werden durch das Zeichen : getrennt.

Beispiele:

Joerg> echo $PATH
:/bin:/usr/bin:/usr/joerg/bin
Joerg> _

Merke: leerer erster Eintrag = "hier, wo ich grad bin, auch gucken" — iykyk 👑


CDPATH 🧭

Diese Variable hat den gleichen Aufbau wie PATH. Sie ist für das Suchen nach Directories bei dem cd - Kommando zuständig. Der erste Eintrag muss !! leer sein, sonst funktioniert das cd - Kommando nicht.

🚨 Okay das ist wichtig: erster Eintrag leer, sonst ist cd einfach kaputt und du sitzt da wie "warum??". Kein cap.

Beispiele:

Joerg> echo $CDPATH
:/usr/joerg:/usr/joerg/cmd
Joerg> cd bsh
~/cmd/bsh
Joerg> _

CWD 🌸

Diese Variable enthält die aktuelle Working-Directory. Sie wird aber aus Effizienzgründen erst nach dem ersten cd - Kommando gesetzt.

Beispiele:

Joerg> #b wd echo $CWD
Joerg> wd
/usr/joerg/cmd/bsh
Joerg> _

Also nicht wundern, wenn $CWD am Anfang noch bisschen lost wirkt — sie ist einfach noch nicht aufgewacht 😴


CD 🔒

Hat die Variable CD den Wert on, oder ist nicht gesetzt, ist ein Wechsel der Workingdirectory jederzeit möglich. CD=off verbietet dem Benutzer ein cd - Kommando. CD=/usr/schwachsinn verbietet über die Directory /usr/schwachsinn hinaufzusteigen.

Beispiele:

Joerg> pwd
/user/joerg
Joerg> cd ..
Joerg> cd
Joerg> set CD=off
Joerg> cd ..
Can't change to '..'. Permission denied.
Joerg> pwd
/user/joerg
Joerg> _

Not me getting grounded in meinem eigenen Filesystem 😭


EVLOCK 🔐

Verbietet dem Benutzer das Ändern einer oder mehrerer EV-Variablen. Sollen mehrere EV-Variablen gesperrt werden, werden ihre Namen durch einen Doppelpunkt getrennt. Hat die Variable EVLOCK den Wert on, so sind alle EV-Variablen gesperrt.

Beispiele:

Joerg> echo $HISTORY
20
Joerg> set HISTORY=5
Joerg> echo $HISTORY
5
Joerg> set EVLOCK=HISTORY
Joerg> set HISTORY=15
Can't set environment 'HISTORY=15'. Variable is
locked
Joerg> echo $HISTORY
5
Joerg> set EVLOCK=EVLOCK:PATH:CD:SU:SLASH:PROMPT
Joerg> set PROMPT=la>
Can't set environment 'PROMPT=la>'. Variable is
locked
Joerg> set EVLOCK=off
Can't set environment 'EVLOCK=off'. Variable is
locked
Joerg> _
💀 Der letzte Teil ist so iconic: du willst EVLOCK ausschalten, aber EVLOCK selber ist gelockt. Du hast dich selbst ausgesperrt. Das ist Peak Unix Comedy, fr fr.

SLASH ⚡

SLASH=off bewirkt die Nichtbeachtung des Zeichens /. SLASH=on hat keine Wirkung. Diese Variable wird auch von den Utilities ved, copy, move und delete gelesen und entsprechend interpretiert.

Beispiele:

Joerg> set SLASH=off
Joerg> /bin/echo hallo
Can't execute ''. Permission denied.
Joerg> set SLASH=on
Joerg> /bin/echo hallo
hallo
Joerg> _

Der Slash wird einfach ignoriert und dann steht da '' — chaos, but make it fashion 🌀


SU 👑

Mit SU=off kann die Benutzung des su - Kommandos gesperrt werden.

Kurz. Knapp. Mächtig. 🫡


IGNOREEOF 🙈

Jeder Kommandointerpreter hat nach seinem Start diese Variable auf off gesetzt (Auch das su Kommando). Will man das verhindern, kann man in sein ~/.init - File set IGNOREEOF=on schreiben. Rekursiv aufgerufene Kommandointerpreter können dann mit ^D verlassen werden, falls sich der Cursor am Anfang einer leeren Zeile befindet, der erste jedoch nicht. Will man auch rekursiv erzeugte Kommandointerpreter schützen, gehört in das ~/.init2 - File die gleiche Zeile. Rekursiv aufgerufene Kommandinterpreter können jedoch mit dem pushd bzw. dem popd - Kommando weitgehend vermieden werde. Ist IGNOREEOF nicht auf on, wird beim Eintippen von ^D solange vorwärts gelöscht, bis evtl. der Cursor sich am Anfang einer leeren Zeile befindet; dann wird der bsh verlassen. (Befindet der Cursor sich nicht am Anfang einer Zeile, so ertönt die Glocke, wenn sich keine Zeichen mehr rechts vom Cursor befinden.)

🎀 TL;DR: ^D ist nicht einfach "exit", es ist "lösch dich Zeichen für Zeichen nach vorne", bis halt nix mehr da ist. Und dann poof. Sehr dramatisch, sehr efektiv.

📁 FILES 📁

  • ~/.init — wird beim Starten des Loginshells ausgeführt.
  • ~/.init2 — wird beim Starten jedes weiteren Shells ausgeführt.
  • ~/.final — wird beim Logout ausgeführt.
  • ~/.history — enthält die gerettete History nach dem Ausloggen.
  • ~/.bshmap — enthält die Tastaturmaps.
  • ~/.globals — enthält Macros, die in jeder Directory gelten.
  • ~/.locals — enthält Macros, die nur in der aktuellen Directory gelten.
  • /dev/null — Stdin für Hintergundjobs.
  • /etc/initbsh — Gemeinsames Init-Sriptfile für alle Loginshells.
  • /etc/initrbsh — Gemeinsames Init-Sriptfile für alle restricted Loginshells.
  • /etc/passwd — Für Homedirectory-Expansion (~name).
  • /etc/termcap — Für die Standard Cursormaps.
  • /tmp/bsh* — Temporäres File für <<.

💀 BUGS 💀

Allgemeines

Einige eingebaute Funktionen des bsh lassen sich nicht mit ^C abbrechen. Alle Eingaben, die nach einem > Prompt eingegeben wurden, erscheinen nicht in der History. Es ist nicht möglich Kontroll-Strukturen aus if, for, loop und switch durch ; oder & zu trennen.

Das Quoting von speziellen Buchstaben ist verwirrend, weil an vielen verschiedenen Stellen expandiert wird und jeweils das Zeichen \ entfernt wird. Besonders verwirrend ist das bei Meister werden.

Symbolische Links überlisten den bsh. Wenn ein cd über einen symbolischen Link führt, hat die Variable $CWD nicht mehr den korrekten Wert.

Das Kommando cat <<EOF& verwirrt den bsh. Er forkt, bevor der Input gelesen ist, was zur Folge hat, daß man zwei Prompts hat, und Vater und Sohn gleichzeitig lesen wollen.

Das killpg Kommando lässt sich nur bedingt verwenden, da es unter UNIX kein Kommando gibt, mit dem man die Prozessgruppe eines Prozesses bekommt.

😭 Ja, das steht da so. Nein, es wird nicht schöner. Aber hey — wenigstens ehrlich.

Hinweise

Strings werden ähnlich wie in Programmiersprachen und in grober Annäherung an den sh behandelt. d.h.:

  • Mit dem doppelten Anführungszeichen wird nur ein String zusammengefasst und die Expansion von Wildcards ($*?{}[]) verhindert. Environment-Variablen werden hier noch expandiert.
  • Mit dem einfachen Anführungszeichen wird jegliche Expansion verhindert, d.h. alle Macros, die mit dem do - Kommando arbeiten, müssen !! in einfachen Anführungszeichen stehen, damit sie nicht schon vor der Ausführung des eigentlichen Kommandos expandiert werden. Man sollte, falls man sich nicht sicher über den Grund einer möglichen Fehlfunktion eines do Macros ist, das Kommando:
change '"' "'" ~/.globals ~/.locals"

absetzen, da in Strings, die mit dem " gebildet werden, schon eine Expansion erfolgt und deshalb das do - Kommando nicht korrekt läuft.

Eine Verkettung von Strings wie im sh ist z.Zt. nicht möglich.

Änderungen, die dem technischen Fortschritt dienen, vorbehalten.

Weitere Bugs bitte an schilytools@mlists.in-berlin.de senden oder ein Ticket auf https://codeberg.org/schilytools/schilytools/issues öffnen.

Das Archiv der Mailing-Liste ist zu finden unter:

https://mlists.in-berlin.de/mailman/listinfo/schilytools-mlists.in-berlin.de

👑 AUTOREN 👑

Der bsh wurde von Jörg Schilling geschrieben und wird nun von den Autoren des schilytools Projekt unterhalten. Legend behaviour, honestly 🫶


⭐ SOURCE DOWNLOAD ⭐

Der Quellcode des bsh ist im schilytools Projekt enthalten und kann auf dessen Projektseite auf Codeberg heruntergeladen werden:

https://codeberg.org/schilytools/schilytools.

Aktuelle Releases sind hier zu finden:

https://codeberg.org/schilytools/schilytools/releases.

Und das war's, bestie — komplett durch, no skips, no cap 🎉💖 Diese Seite ist von Joerg Schilling, Stand 2022/09/12, und sie hört auf den Namen BSH(1L). Wenn du bis hierhin gelesen hast, bist du offiziell ein Unix-Girlie. Tschüssi, bis zum nächsten Joerg> _ 💅✨🦋

📦 where this page comes from