Sammlung von Kurzbeispielen
Auszüge aus Shell-Scripts für bsh
Hauptseite
|
|
catv 0,512,0 <\\.\C: ¦ tr '[\0-\31][\128-\255]' '[.*]'
catv 512,512,0 <\\.\physicaldrive0 ¦ tr '[\0-\31][\128-\255]' '[.*]'
Das catv-Kommando liest hier den Bootblock von Laufwerk C: und den zweiten
Sektor (Offset 512) der
ersten Festplatte.
Das tr-Kommando wandelt alle zur Ausgabe auf den Bildschirm problematischen
Zeichen in einen '.' um.
Man kann also mit der bsh sämtliche Laufwerke und alle
Festplatten binär lesen und schreiben.
Und zwar nicht nur mit dem oben gezeigten catv-Kommando.
Allerdings werden die speziellen Dateinamen "\\.\L:"
nur unter WinNT anerkannt!
Bei den kostenlosen bsh-Versionen gibt es aber eine 2-GigaByte-Grenze,
jeweils vom Beginn der angegebenen Spezialdatei gerechnet;
der Blockmodus ( B< /dev/rhd00 ), mit dem man bis 1 TeraByte
kommt,
ist nur in Vollversionen (Unix,bsh32) vorhanden.
|
list -R c: ¦ sortl ¦ tee odatei ¦ wc
list -R c: ¦ tr '[a-z][A-Z]' '[A-Z][a-z]' ¦ sortl ¦ tr '[A-Z][a-z]' '[a-z][A-Z]' > odatei
Das list-Kommando listet rekursiv Laufwerk c: auf, sortl sortiert, tee
schreibt alles in odatei und
gleichzeitig weiter in eine Pipe zum wc-Kommando, das Zeichen, Worte, Zeilen
zählt.
Beim zweiten Beispiel wird die Sortierreihenfolge geändert, mit
Hilfe des tr-Kommandos.
Das interne sortl kann mehr als die externen sort-Kommandos (Ausnahme:
sort unter Unix).
|
time to 50 repeat; do sort <datei.txt >NUL; done
time to 50 repeat; do sortl -oNUL datei.txt; done
Liefern die Zeitdauern 18 Sekunden und 6 Sekunden bei einer 200KB-Datei
und Celeron366 unter WinNT.
Das interne sortl ist hier also 3mal schneller, obwohl es komplexer ist
und mehr kann.
Man beachte, daß man bei (solchen) Zeitmessungen eine Ausgabe
auf den Bildschirm verhindern muß
und nicht mit Pipes (¦) arbeiten sollte, weil diese Dinge viel Zeit
verbrauchen und das Meßergebnis verfälschten.
|
GetIDs mt $1 "$lz" | { nop && pop3 - $IP "$User" "$Pass"; }
Der Exit-Wert des Kommandos GetIDs (in Wahrheit eine Shell-Funktion) wird durch && ausgewertet.
Das ist in dieser Form und in Verbindung mit Pipes nur mit der bsh möglich.
|
set Buf:a100000000
Setzt die Variable Buf mit 100 Millionen Zeichen 'a'. (Ab bsh v4.01)
local buf:a1000
Gleiches für lokale Variablen.
|
DIR \ ¦ grep -i '^ *[0-9][0-9,.]* bytes fre' ¦ read free rest conv -d,d. free
Diese beiden Zeilen liefern die Anzahl Bytes, die auf dem aktuellen
Laufwerk noch frei sind.
Beim DIR-Kommando lautet die letzte Textzeile ja so oder ähnlich:
43,171,860 Bytes free
Und genau diese Zeile wird vom grep-Kommando herausgefiltert.
Kommas oder Punkte werden zum Schluß vom conv-Kommando gelöscht.
Die Variable 'free' enthält letztlich: 43171860
|
namen='aaa bbb,ccc ddd,eee'
for n in $(ifs="$IFS";IFS=,) $namen $(IFS="$ifs") do echo "--$n--" done
--aaa bbb-- --ccc ddd-- --eee--
Dies ist ein Trick. Es wurden IFS-Zuweisungen in Kommando-Substitutionen
gepackt, die als
unmaskierte Argumente keinerlei Argument-Wirkung haben, weil Zuweisungen
nun mal nichts
ausgeben auf die Standard-Ausgabe.
Die vorübergehende Änderung von IFS hat hier nur Wirkung auf
'$namen' .
|
Fmain() { case "$1" in $(shift) abc) ... ;; ... ... esac return 0 }
Hier konnte eine Variable als Zwischenablage vermieden werden, da $(shift)
als Argument zu 'case'
nicht in Erscheinung tritt!
Innerhalb des 'case' ist '$1' das zweite Funktions-Argument!
|
expr "$Zeile" :Zeile % "%(<${s}[ %t].*${bgc}[ %t]*=[ %t]*%"#%)......%"" % "%1$rgb%"" ¦¦ continue
Mit diesem Aufruf des expr-Kommandos werden die Farbeinträge in
einer html-Datei überschrieben.
(siehe Script 'colors.bsh')
Die Variablen 's', 'bgc' und 'rgb' sind wegen Automatisierung in einer
Schleife vorhanden.
's' und 'bgc' stehen in {}, da sie sonst (zwischen "") als Arrays
(wegen [...) interpretiert würden.
In 'rgb' befindet sich der neue Farbwert als 3 Hexadezimalwerte: z.B.:
f9aa62
Zur besseren Übersicht:
<TABLE BORDER=2 BGCOLOR = "#FF00FF" >
t='[ %t]' expr "$Zeile" :Zeile "%(<$s$t.*$bgc$t*=$t*%"#%)......%"" "%1$rgb%""
Ohne $t: expr "$Zeile" :Zeile "%(<$s.*$bgc=%"#%)......%"" "%1$rgb%""
Ohne Variablen: expr "$Zeile" :Zeile '%(<TABLE .*BGCOLOR="#%)......"' '%1F0F0FA"' Ersetze dies durch dies
Das aktuelle expr-Kommando hat die neuen Optionen '=' (=::) und
%U %L %E :
expr "$Zeile" =:Zeile '%(<Table .*BGcolor="#%)......"' '%1%UF0f0Fa"'
Für Abschaltung der Unterscheidung zwischen Groß- und Kleinschreibung,
und im Ersatztext zur Umwandlung toUpperCase und toLowerCase
und deren Abschaltung.
Man sieht hier auch, daß Reguläre Ausdrücke eigentlich
doch nicht so schwer zu begreifen sind,
denn man beginnt ja mit '' oder
"" ...
|
bgrep -g 'http://' topatch_datei > pos
: > urls 3< topatch_datei < pos while readl num do catv $num,256,3 ¦ tr '\0[\1-\31][\128-\255]' '\10[ *]' ¦ catv =url: expr "$url" :url '^%([^%n]*%)' expr "$url" :: ' ' && continue [ "$url" == "http://" ] && continue echo "$num $url" >> urls done ><<
Diese beiden Abschnitte dienen dazu, in einer binären Datei bestimmte
Zeichenketten durch andere
zu ersetzen. Und zwar hier: URLs, die mit 'http://'
beginnen.
Zuerst hat man nur die Byte-Positionen, wo solche Zeichenketten beginnen
(bgrep; Datei 'pos').
In der Schleife werden die URLs geholt, umgewandelt und unerwünschte
ausgeschieden,
bis zum Schluß das echo-Kommando in die Datei 'urls' die Position
und den bereinigten URL schreibt.
In diese Datei kann dann als drittes Wort der jeweils gewünschte Ersatztext
hinzugefügt werden.
Der nächste Abschnitt zeigt,
wie der Ersatztext geschrieben (gepatcht) wird:
3<> topatch_datei < urls while read num url new do ifset new ¦¦ continue echo "$num $url $new" catv new /%0 =$num,,3 done ><<
Das echo-Kommando informiert hier lediglich.
Man beachte, daß das externe Kommando bgrep auch durch
interne bsh-Kommandos ersetzt
werden kann!
Beispielsweise die Kommandos catv, conv, cmpv arbeiten
binär!
das erkennt man (auch) daran, daß sie 'name' entgegennehmen
und nicht (nur) '$name' .
Diese Kommandos wenden sich mit den Variablennamen direkt an den Variablen-Manager,
der binär arbeitet.
|
conv -t b name conv -d name
Ersetzt in der Variablen 'name' alle NUL-Zeichen (\000) durch 'b';
löscht alle NUL-Zeichen.
Dies funktioniert, weil der Argumentspeicher folgendermaßen aussieht:
"conv\000-t\000b\000name\000" "conv\000-d\000name\000"
Dadurch wird eine Digit-Syntax -d%000 eingespart,
die nur wegen der Null da wäre;
alle anderen Zeichen kann man nämlich direkt oder per Variable den
Optionen hinzufügen.
Die bsh arbeitet nur an wenigen Stellen mit null-terminierten Strings.
|
fehler() { echo "%n $0: '$1'%n"; exit 1; }
stop() { read "-? <Enter> "; }
Zwei kleine Shell-Funktionen.
Aufrufe: fehler "meldetext" ; stop
|
frage() { while echo "%n$1 [jne]: %c" do read rest case "$rest" in [jJ]) return 0 ;; [nN]) return 1 ;; [eE]) exit 0 ;; *) continue ;; esac done return 2 }
Diese Frage-Funktion wird erst verlassen, wenn man eine der Antworten
jJnNeE eingibt.
Aufrufe:
frage "fragetext" && ja-komandos
if frage "fragetext"
then ...
else ...
fi
|
while echo "%r%n Zu testendes Verzeichnis: '$1'
%tListendatei zur Liegenschaft : l %tLiegenschaft zur Listendatei : a %tHinweise : ? %tDieses Menü verlassen : v %tBeenden : e
%t : %c" do read kdo rest case "$kdo" in l) tst_lst_lieg $1 ;; a) tst_lieg_lst $1 ;; v) return 0 ;; e) exit 0 ;; %?) echoh Keine Hinweise. ;; *) echo %a%c ;; esac done
Beispiel für ein Menü.
Die Bedingung der while-Schleife (echo "..." von 'while'
bis 'do') ist immer TRUE.
Die Schleife wird nur durch Eingabe von 'e' oder 'v' verlassen.
Bei falschen Eingaben piepst es (echo %a).
|
j=1970 repeat do (( cjsj=0, corr= SPT*365 + (j%4==0&&j%100¦¦j%400==0 ? (++cjsj,SPT) : 0), sec<corr )) && break (( sec-=corr, ++j )) done
m=1 repeat do (( corr=MA[m] + (m==2&&cjsj ? SPT : 0), sec<corr )) && break (( sec-=corr, ++m )) done
Dies sind zwei Schleifen mit mathematischen Berechnungen.
Sie laufen ewig weiter, bis sie durch 'break' verlassen werden.
Das break-Kommando wird aktiv, wenn 'sec<corr' zutrifft.
|
ifset -E S_DIR BSHTEMP ¦¦ { echo Sie haben dieses Script nicht mittels start.bat gestartet echo oder es liegt ein unerwarteter Fehler vor. exit }
Dieses Kommando prüft, ob die Umgebungsvariablen S_DIR und BSHTEMP
beide existieren
und einen Inhalt haben.
Es wird nur in der Umgebung nachgeschaut (-E).
|
whence -ep mem ¦¦ [ $? -eq 10 ] && mem /d ¦ grep -iq '[^a-zA-Z]ansi[^a-zA-Z]*' && whence -ep mode ¦¦ [ $? -eq 10 ] && mode con ¦ grep -q '[^0-9]25[^0-9]' && mode con ¦ grep -q '[^0-9]80[^0-9]' && R='%e[2C' S='%e[0;30;46m%e[2;3H'
Die Shell-Variablen R und S werden nur gesetzt, wenn die
Kommandos mem und mode vorhanden sind
und der ansi-Treiber geladen ist und 25 Zeilen und 80 Spalten eingestellt
sind.
|
ifset R && PS1='print -nu2 "%e[s%r%e[53C%e[40;36m"; prints su2-26- $PWD print -nu2 "%e[u%e[40;37m$:%e[1m#%e[0m "'
Es wird ein sehr aufwendiges Prompt in die Prompt-Spezialvariable PS1='...'
gespeichert.
Das funktioniert nur, wenn ein ansi-Treiber aktiv ist.
Der Inhalt von PS1 wird quasi wie ein Shell-Script behandelt und ausgeführt!
|
echo STRINGTABLE PURE echo BEGIN N=1 echo "$N, %"$#%""
for FN in $* do ((++N)) NAM=`expr $FN : '.*/%(..*%)%.'` expr $FN :: '..*mn[a-zA-Z]$' && { rc=`expr $FN : '..*mn%(.%)$'` conv -u rc NAM="$NAM($rc)" } echo "$N, %"$NAM%"" ((++N)) NZ=`wc -l $FN` echo "$N, %"$NZ%"" done
((++N)) for FN in $* do cat $FN ¦ rcstr -$N NZ=`wc -l $FN` ((N+=NZ)) done
echo END
Dies ist das Haupt-Script dafür, um automatisch die String-Ressourcen
und einige Steuerdaten
für das Win32-Programm manw.exe zu erzeugen.
Aufruf: rcstrings.bsh $manfiles > manw.str
|
mkofname() { local dir="$1" n=0 t=$T name of conv -F\F/ dir expr "$dir" :name '%([^/\]%{1,%}%)$' ¦¦ return expr "$dir" :dir '^%(.*%)'"$name"'$' ¦¦ return conv -F\F/ dir expr "$name" :name '^%(%.*[^.]*%)' ¦¦ return ifset dir ¦¦ t='' of=$dir$t$name.$2 conv -F\F/ of while [ -e "$of" ] do let "++n>9" && return 1 of=$dir$t$(catv 7,name)$n$(catv 8,,name).$2 conv -F\F/ of done $3=$of return 0 }
Der Aufruf dieser Shell-Funktion: mkofname $idatei erw odatei_variablen_name
Die Funktion erzeugt einen Dateinamen mit einer Erweiterung 'erw', der
ansonsten aber gleich demjenigen
Dateinamen ist, der in $idatei steht.
Wenn gleichnamige Dateien schon existieren, wird folgendermaßen weiterprobiert:
ddddddd1.erw
ddddddd2.erw
ddddddd3.erw
...
ddddddd9.erw
Der neue Name ist dann per $odatei_variablen_name erreichbar.
Der Name odatei_variablen_name darf nicht 'local'
sein !
|
#dos_unix tr -d '\26' < $2 ¦ { > $2 while readl Line do catv Line /%n; done >< }
#unix_dos cat $2 ¦ { > $2 while readl Line do catv Line /%r%n; done >< }
Hier werden Text-Dateien vom DOS- zum UNIX-Format umgewandelt und umgekehrt.
Der Name der Ursprungsdatei steht in $2 .
Eines fällt hier auf: Die Datei wird gelöscht (> $2),
bevor die Schleife erreicht ist.
Ein Trick: An der Stelle '¦' wird die
Datei in die bsh-interne Pipe-Datei kopiert,
und aus dieser liest ja das readl-Kommando!
Man spart sich also das Anlegen einer temporären Datei.
|
mkofname $2 uc OutFile ¦¦ return tr '[a-z]äöü' '[A-Z]ÄÖÜ' < $2 > $OutFile
Hier wird ein neuer Dateiname erzeugt 'dddddddd.uc' und
die Kleinbuchstaben der Datei $2
werden in Großbuchstaben umgewandelt und dies alles in $OutFile
geschrieben.
Das tr-Kommando ist ideal für solche Zwecke - es kann
noch viel mehr.
|
grep -i 'SRC="[^"]%{1,%}"' $2 ¦ while readl Line do expr "$Line" :Line '[Ss][Rr][Cc]="%([^"]%{1,%}%)"' catv Line /%j >> $OutFile done
Aus einer html-Datei werden alle Grafikdatei-Namen herausgesucht und
nach $OutFile geschrieben.
|
OutFile=binstr.acc echo ":::$2:::" >> $OutFile tr -cs '[a-z][A-Z][0-9]äöüßÄÖÜ_.-@/\\:' '[\10*]' < $2 ¦ grep '^[^%r%n]%{2,%}$' >> $OutFile
Aus einer Binär-Datei werden alle lesbaren Zeichenketten herausgefischt
und mit automatischer Zeilenbildung durch tr nach
$OutFile geschrieben.
Das grep-Kommando dient dazu, Einzelzeichen zu unterdrücken.
-c bewirkt, daß alle nichtangegebenen Zeichen in Zeilenvorschübe
(\10) umgewandelt werden, und
-s bewirkt, daß nicht mehrere Zeilenvorschübe hintereinander
in der Ausgabe vorkommen können.
|
< $file SS=`catv $((446+0+8)),4,0 $((446+0+12)),4,0 % $((446+16+8)),4,0 $((446+16+12)),4,0 % $((446+32+8)),4,0 $((446+32+12)),4,0 % $((446+48+8)),4,0 $((446+48+12)),4,0 % ¦ base -l +10` ><
Hier werden Daten aus der Partitionstabelle einer Festplatte gelesen
und aufbereitet,
um anschließend die Daten in LBA-Werte (255 Köpfe) umzuwandeln.
Die Variable SS enthält hiernach die Daten in lesbarer
Form, als Digit-Strings, durch Leerzeichen getrennt.
|
ziel=checksum.txt echo "Prüfsummen- und Zeitstempel-Liste:" > $ziel date >> $ziel echo %n >> $ziel
for wc in "*.exe" "*.zip" "*.Z" "*.bin" "*.drv" "*.bsh" do : $wc [ "$]" -eq 0 ] && continue for file in $wc do [ -s "$file" ] ¦¦ continue echo "$file" prints s16s17s17s3s `sum -b < "$file"`"(sum)" % `crc "$file"`"(crc)" % `fsize "$file"`"(size)" % "" "$file" >> $ziel done done
Dieser Ausschnitt produziert den ersten Teil der Datei 'checksum.txt',
die auf meiner Homepage ist.
|
vor00() { let "${{#1}==2" && $1=0${{1} let "${{#1}==1" && $1=00${{1} let "${{#1}==0" && $1=000 }
Ein Aufruf vor00 Vname fügt zum Inhalt der
Shell-Variablen Vname 0 bis 3 führende Nullen '0' hinzu.
Vname darf nicht 'local' erzeugt, sondern muß eine globale
Variable sein!
Hier wird indirekter Zugriff ${{ angewendet.
|
< $Script while seek + 0 GWpos; readl Zeile do expr "$Zeile" :: '^#@g ' && break; done catv $((GWpos+=4)),10,0 =Gsel: echo GruppenGWposition=$GWpos
Dieser erste Teil stellt diejenige Dateiposition (GWpos) fest, wo #@g
am Zeilenanfang zuerst vorkommt.
In der Datei ($Script) sieht das so aus: #@g --2-4---8-
catv liest die 10 Zeichen --2-4---8- und schreibt sie in
die Variable Gsel.
echo Inhalts-Test G... inp=0 seek $GWpos 0 while readl Zeile do expr "$Zeile" :: '^#@G ' && { let ++inp; continue; } let inp!=0 && break done >< let "inp!=100" && { echo "$inp:Script-Inhalt ungültig!"; exit 1; }
Der zweite Teil geht auf GWposition und sucht ab da Zeilen mit #@G
am Anfang.
Es müssen genau 100 solche Zeilen sein, und sie müssen ununterbrochen
als Block vorhanden sein.
|
Gwahl() { local g=00 Gsel=---------- for g from 0 by 1 to 9 repeat do expr "-$1" :: "$g" ¦¦ continue catv g =$g,1,Gsel done catv Gsel =$GWpos,10,0 <> $Script return 0 }
Aufruf: Gwahl 6318
Effekt: Gsel enthält nach der Schleife -1-3--6-8-
Und catv schreibt den neuen Inhalt von Gsel sogleich
in die Datei $Script auf Position $GWpos.
|
GcopyG() { local grp="$1" g=0 n=0 <> $Script for g from 0 by 1 to 9 repeat do expr "$grp" :: $g ¦¦ continue for n from 0 by 1 to 9 repeat do catv $((n*20)),20,CN =$((Gpos+g*260+n*26+4)),,0 done done >< return 0 }
Aufruf: GcopyG 346
Die Variable CN enthält 10 Zeichenfolgen mit je 20 Zeichen.
Diese werden in 10 aufeinanderfolgende Zeilen in Datei $Script geschrieben:
#@G ....................\r\n #@G ....................\r\n #@G ....................\r\n ...
Und zwar hier 3-mal, je einmal für 346 , in 3 verschiedene
10-Zeilen-Blöcke hinein.
Es werden nur die je 20 Punkte ..... überschrieben.
Die Zeilenlänge inklusive Zeilenvorschub ist 26 (4+20+2).
Es sind 100 solche Zeilen in der Datei ununterbrochen vorhanden, die hier
als Speicherfläche
benutzt werden.
|
ShowF() { local nf=-001 rgb=000000000000 nl=-001 sel nam inp 3<&0 grep '^#@[Ff] ' $Script ¦ Fconv ¦ { seek + 0 Pos while : do nf=-1 nl=-1 seek $Pos 0 while read nam rgb do let ++nf ifset inp && [[ "$nam" != "$inp" ]] && continue let ++nl prints s5s-20s4s4s4 $nf: $nam $rgb let "nl>0&&nl%20==0" && { echo "... Weiter:<Enter> %c" read -u3 inp [ "$inp" == e ] && break 2 [ "$inp" == s ] && { inp=; continue 2; } } done read -u3 inp [ "$inp" == e ] && break done } #hier wird Pipe-Handle 0 zurückverknüpft, mit der Tastatur. >< #und hier Handle 3 mit ... return 0 }
Hier gibt es zwei Besonderheiten:
grep liest Zeilen aus einer Datei und schickt sie per Handle 1
in eine Pipe, wo diese Daten durch
die Shell-Funktion Fconv konvertiert werden und in
der Pipe-Kette weitergereicht werden.
Das read-Kommando liest per Handle 0 aus der Pipe-Datei.
Die Pipe-Datei wird hier als Parkplatz benutzt und kann immer wieder vom
Datenstart an gelesen werden,
weil der Datenstartpunkt mittels seek abgesichert
wurde.
Bevor die Pipe Handle 0 belegt, wird Handle 3 mit Handle 0 verknüpft,
also der Tastatur,
damit mit read -u3 von der Tastatur gelesen werden
kann.
read inp </dev/console
read inp t<CON
wären auch möglich gewesen, aber obige Lösung ist eleganter
und portabel.
|
CGI-Scripting
ConvFormData() { local h z conv -'t+ ' $1 while expr "${{1}" :h '%%%([a-fA-F0-9]%{2%}%)' do base -16 h +b z expr "${{1}" :$1 '%%'$h += "$z" done return 0 }
Aufruf: ConvFormData varname
Diese Funktion dekodiert die Daten, die von einem Formular (SUBMIT)
gesandt werden.
Alter und neuer Inhalt sind in der globalen Shell-Variablen namens 'varname'
enthalten.
for 2 x y in name "$name" strasse "$strasse" plz "$plz" % ort "$ort" email "$email" % znum "$znum" kenn1 "$kenn1" kenn2 "$kenn2" % url1 "$url1" url2 "$url2" url3 "$url3" % submit "$submit" hidd "$hidd" % bsovw "$bsovw" % Kennwo1 "$Kennwo1" Kennwo2 "$Kennwo2" do expr "$htmlF" :htmlF "~$x~" = "$y" done
catv Thtml html1 htmlF htmlH html2 htmlE
HTML-Quelltext befindet sich in der Variablen 'htmlF', mit
Zeichenfolgen wie z.B. ~name~ .
Die Schleife ersetzt paarweise diese Zeichenfolgen mit den zugehörigen
Variableninhalten.
Danach wird mit dem catv-Kommando der gesamte Quelltext
zum Server geschickt, der ihn
über's Netz an den Browser sendet.
znummer zwert [kommentar] znummer,zwert von-bis zwert
$nam="$val" [ "$nam" == znum ] && { CkSetDat $znum ¦¦ return 6 Lock; catv $((znum*4000)),4000,3 =Data: 3<$dat } continue } expr "$Z" :val "^$f*%%($d%%)-%%($d%%)$t%%($d%%).*%$" % '%1 %2 %3' &¦ expr "$Z" :val "^$f*%%($d%%)$t%%($d%%).*%$" '%1 %2' ¦¦ continue for 3 von bis val in $val; do done ifset val ¦¦ val=$bis bis=$von let "val<0¦¦val>999999999" && return 7 let "von<0¦¦bis<0¦¦von>999¦¦bis>999¦¦bis<von" && return 8 base -10 val +L val for o from $von to $bis repeat do catv 4,val =$((o<<2)),4,Data; done done ifset znum kenn1 ¦¦ ErrExit "Keine Identifikation!(1)" GetKunDat ¦¦ ErrExit "Keine Identifikation!(2)" Lock; catv Data =$((znum*4000)),4000,3 3<>$dat return 0 }
Eine vom Browser hochgeladene Datei mit Nutzdaten für die Dateien
auf dem Server
wird ausgewertet.
|
Ein vollständiges Download-Script
#!/usr/bin/bsh
set -f
deroot="$DOCUMENT_ROOT/de"
expr "$deroot" :deroot '/de/de' '/de'
arg="$QUERY_STRING"
ok=0
expr "$arg" :zn '^%([0-9]%{1,2%}%.[0-9]%{1,3%}%):.' && {
expr "$arg" :nam ':%(..*%)$' ¦¦ nam=
expr "$nam" =:nam '%%2f' += '/'
expr "$nam" :dir '^%(.*/%)[^/]*$' ¦¦ dir=
expr "$nam" :nam '%([^/]*%)$' ¦¦ nam=
expr "$nam" :erw '%.%([^/.]%{1,%}%)$' ¦¦ erw=
pre=fjgklidzfhgsehfrherk
[ -s "$dir$pre$nam" ] && ok=1
}
[ ok -eq 0 ] && {
echo "Content-type: text/plain%n"
exit 0
}
HTTP_REFERER="$HTTP_REFERER::$dir$nam"
export HTTP_REFERER
extern icnt.cgi $zn.i0
ifset erw ¦¦ erw=bin
conv -l erw
case "$erw" in
shtml¦html¦htm¦php3) ctyp=text/html ;;
txt¦bsh¦pl¦text) ctyp=text/plain ;;
exe¦bin¦zip¦gz¦tar¦drv¦z¦obj¦o)
ctyp=application/octet-stream ;;
gif) ctyp=image/gif ;;
jpg¦jpeg) ctyp=image/jpeg ;;
*) ctyp=text/plain ;;
esac
systime Time
cd "$deroot"
set +f
for lkn in *[0-9][0-9]_[0-9]*
do
expr "$lkn" :time '^%([0-9]%{8,10}%)_[0-9]%{1,}_' ¦¦ continue
let "Time-time>400" && remove "$lkn"
done
set -f
cd -
http_lkn="${Time}_$$_$nam"
lkn="$deroot/$http_lkn"
[ -e "$lkn" ] && remove "$lkn"
link "$dir$pre$nam" "$lkn"
clen=0
fstat -sv clen "$dir$pre$nam"
Out="Content-Type: $ctyp
Location: ../$http_lkn
Content-Length: $clen
From: webmaster@schellong.com
"
#catv Out 0 =1 < "$dir$pre$nam"
catv Out
exit 0
.
|
Das wahnsinnig universelle Kommando catv
<>datei ... catv /%1 =:-1,,0. ... ><
Überschreibt das letzte Datei-Byte (:-1) mit einer 1
und stellt den Dateipointer wieder auf den Ursprungswert zurück (.)
.
catv /%0%0 =$((zn2<<1)),,3 3<>$fnamo
Schreibt zwei Null-Bytes mitten in eine Datei.
Datei wird nötigenfalls bis zur Schreibstelle mit Nullen erweitert/aufgefüllt.
let "sz<=zn1" && catv /%0 =$zn1,,3 3<>$kunflg
Schreibt ein Null-Byte ...
catv $zn1,1,0 =v: <$kunflg ¦¦ err=1
Liest ein Byte von Handle 0 (Datei $kunflg) und schreibt es (binär)
in Variable 'v'.
'v' wird danach auf Länge 1 gebracht (:).
Das ist nötig, wenn andere Kommandos ohne MAX-Option anschließend
aus 'v' lesen sollen.
catv 0 =0,,3:
Liest von Handle 0 und schreibt auf 3 ab Offset 0, mit festlegen der
Dateigröße bzw. des Dateiendes
hinter die letzte Schreibstelle.
catv $((zn2<<1)),2,0 =v: <$fnamo
Liest maximal 2 Bytes ab Offset 2*zn2 von 0 und schreibt
diese in Variable 'v'.
catv 2,n =$((zn2<<1)),2,3 3<>$fnamo
Liest 2 Bytes aus Variable 'n' und schreibt sie in Datei '$fnamo'.
ifset HTTP_REFERER && catv 99,z /%n =$v,100,3 3<>$fnams
Liest 99 Bytes aus 'z' und schreibt dies und 1 NewLine ab Offset '$v'
in Datei '$fnams'.
catv 0,1,v =f:
Hier sind Variablen Quelle und Ziel. Environment-Variablen sind
nicht zugreifbar mit catv!
catv 0,$n,$v =${f}r:
Liest aus einer Variablen, deren Name in der Variablen 'v' steht, $n
Bytes,
und schreibt in eine Variable, deren Name teilweise in der Variablen 'f'
steht
und deren letzter Buchstabe ein 'r' ist.
((v=[zn1+1]*4000-1, sz<=v)) && catv /%0 =$v,1,3 3<>$dat
Falls die Datei $dat kleiner-gleich 7999 Byte ist (bei zn1==1),
wird ein Null-Byte auf eben diesen Offset geschrieben, wodurch die Datei
8000 Byte groß wird.
catv $offs1,4000,3 =$offs1,4000,4 3<$dat 4<>$datb
Aus Datei $dat werden 4000 Bytes gelesen und in Datei $datb geschrieben,
auf gleichen Offset.
catv "/Content-type: image/gif%n%n" =0,,Z:
Schreibt eine MIME-Typ-Zeile in die Variable Z.
catv /GIF89a%%$sz%0%%$((height+2*rahm))%0%128%0%0 =:,,Z
Schreibt die Kopfzeile einer GIF-Datei hinter das bisherige Ende der
Variablen Z.
catv $((zn1*4000)),4000,0 =DAT <$dat ¦¦ catv / =4000,,DAT
Schreibt 4000 Bytes aus Datei $dat in Variable DAT.
Falls weniger als 4000 lesbar sind, wird DAT mit 4000 Nullen gefüllt.
while catv $((++o)),1,DAT =1,v:
Liest einzelne Bytes aus der Variablen DAT, bis deren Inhalt komplett
gelesen wurde.
(Bei Dateien braucht kein Offset explizit mitgeführt werden.)
catv $length,0 ¦
Liest maximal $length Bytes von Handle 0 und schreibt diese in eine
Pipe.
catv url1 /%n url2 /%n url3 /%n > $urltxt
Schreibt drei Variableninhalte und jeweils ein NL in die Datei $urltxt.
|