11.10. Die UNIX®-Umgebung

Übersetzt von Fabian Ruch.

Ein entscheidendes Konzept hinter UNIX® ist die Umgebung, die durch Umgebungsvariablen festgelegt wird. Manche werden vom System gesetzt, andere von Ihnen und wieder andere von der shell oder irgendeinem Programm, das ein anderes lädt.

11.10.1. Umgebungsvariablen herausfinden

Ich sagte vorher, dass wenn ein Programm mit der Ausführung beginnt, der Stack argc gefolgt vom durch NULL beendeten argv-Array und etwas Anderem enthält. Das "etwas Andere" ist die Umgebung oder, um genauer zu sein, ein durch NULL beendetes Array von Zeigern auf Umgebungsvariablen. Davon wird oft als env gesprochen.

Der Aufbau von env entspricht dem von argv, eine Liste von Speicheradressen gefolgt von NULL (0). In diesem Fall gibt es kein "envc"--wir finden das Ende heraus, indem wir nach dem letzten NULL suchen.

Die Variablen liegen normalerweise in der Form name=value vor, aber manchmal kann der =value-Teil fehlen. Wir müssen diese Möglichkeit in Betracht ziehen.

11.10.2. webvars

Ich könnte Ihnen einfach etwas Code zeigen, der die Umgebung in der Art vom UNIX-Befehl env ausgibt. Aber ich dachte, dass es interessanter sei, ein einfaches CGI-Werkzeug in Assembler zu schreiben.

11.10.2.1. CGI: Ein kurzer Überblick

Ich habe eine detaillierte CGI-Anleitung auf meiner Webseite, aber hier ist ein sehr kurzer Überblick über CGI:

  • Der Webserver kommuniziert mit dem CGI-Programm, indem er Umgebungsvariablen setzt.

  • Das CGI-Programm schreibt seine Ausgabe auf stdout. Der Webserver liest von da.

  • Die Ausgabe muss mit einem HTTP-Kopfteil gefolgt von zwei Leerzeilen beginnen.

  • Das Programm gibt dann den HTML-Code oder was für einen Datentyp es auch immer verarbeitet aus.

  • Anmerkung: Während bestimmte Umgebungsvariablen Standardnamen benutzen, unterscheiden sich andere, abhängig vom Webserver. Dies macht webvars zu einem recht nützlichen Werkzeug.

11.10.2.2. Der Code

Unser webvars-Programm muss also den HTTP-Kopfteil gefolgt von etwas HTML-Auszeichnung versenden. Dann muss es die Umgebungsvariablen eine nach der anderen auslesen und sie als Teil der HTML-Seite versenden.

Nun der Code. Ich habe Kommentare und Erklärungen direkt in den Code eingefügt:

;;;;;;; webvars.asm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Copyright (c) 2000 G. Adam Stanislav
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; 1. Redistributions of source code must retain the above copyright
;    notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
;    notice, this list of conditions and the following disclaimer in the
;    documentation and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
; SUCH DAMAGE.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Version 1.0
;
; Started:       8-Dec-2000
; Updated:       8-Dec-2000
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%include        'system.inc'

section .data
http    db      'Content-type: text/html', 0Ah, 0Ah
        db      '<?xml version="1.0" encoding="UTF-8"?>', 0Ah
        db      '<!DOCTYPE html PUBLIC "-//W3C/DTD XHTML Strict//EN" '
        db      '"DTD/xhtml1-strict.dtd">', 0Ah
        db      '<html xmlns="http://www.w3.org/1999/xhtml" '
        db      'xml.lang="en" lang="en">', 0Ah
        db      '<head>', 0Ah
        db      '<title>Web Environment</title>', 0Ah
        db      '<meta name="author" content="G. Adam Stanislav" />', 0Ah
        db      '</head>', 0Ah, 0Ah
        db      '<body bgcolor="#ffffff" text="#000000" link="#0000ff" '
        db      'vlink="#840084" alink="#0000ff">', 0Ah
        db      '<div class="webvars">', 0Ah
        db      '<h1>Web Environment</h1>', 0Ah
        db      '<p>The following <b>environment variables</b> are defined '
        db      'on this web server:</p>', 0Ah, 0Ah
        db      '<table align="center" width="80" border="0" cellpadding="10" '
        db      'cellspacing="0" class="webvars">', 0Ah
httplen equ     $-http
left    db      '<tr>', 0Ah
        db      '<td class="name"><tt>'
leftlen equ     $-left
middle  db      '</tt></td>', 0Ah
        db      '<td class="value"><tt><b>'
midlen  equ     $-middle
undef   db      '<i>(undefined)</i>'
undeflen        equ     $-undef
right   db      '</b></tt></td>', 0Ah
        db      '</tr>', 0Ah
rightlen        equ     $-right
wrap    db      '</table>', 0Ah
        db      '</div>', 0Ah
        db      '</body>', 0Ah
        db      '</html>', 0Ah, 0Ah
wraplen equ     $-wrap

section .text
global  _start
_start:
        ; First, send out all the http and xhtml stuff that is
        ; needed before we start showing the environment
        push    dword httplen
        push    dword http
        push    dword stdout
        sys.write

        ; Now find how far on the stack the environment pointers
        ; are. We have 12 bytes we have pushed before "argc"
        mov     eax, [esp+12]

        ; We need to remove the following from the stack:
        ;
        ;       The 12 bytes we pushed for sys.write
        ;       The  4 bytes of argc
        ;       The EAX*4 bytes of argv
        ;       The  4 bytes of the NULL after argv
        ;
        ; Total:
        ;       20 + eax * 4
        ;
        ; Because stack grows down, we need to ADD that many bytes
        ; to ESP.
        lea     esp, [esp+20+eax*4]
        cld             ; This should already be the case, but let's be sure.

        ; Loop through the environment, printing it out
.loop:
        pop     edi
        or      edi, edi        ; Done yet?
        je      near .wrap

        ; Print the left part of HTML
        push    dword leftlen
        push    dword left
        push    dword stdout
        sys.write

        ; It may be tempting to search for the '=' in the env string next.
        ; But it is possible there is no '=', so we search for the
        ; terminating NUL first.
        mov     esi, edi        ; Save start of string
        sub     ecx, ecx
        not     ecx             ; ECX = FFFFFFFF
        sub     eax, eax
repne   scasb
        not     ecx             ; ECX = string length + 1
        mov     ebx, ecx        ; Save it in EBX

        ; Now is the time to find '='
        mov     edi, esi        ; Start of string
        mov     al, '='
repne   scasb
        not     ecx
        add     ecx, ebx        ; Length of name

        push    ecx
        push    esi
        push    dword stdout
        sys.write

        ; Print the middle part of HTML table code
        push    dword midlen
        push    dword middle
        push    dword stdout
        sys.write

        ; Find the length of the value
        not     ecx
        lea     ebx, [ebx+ecx-1]

        ; Print "undefined" if 0
        or      ebx, ebx
        jne     .value

        mov     ebx, undeflen
        mov     edi, undef

.value:
        push    ebx
        push    edi
        push    dword stdout
        sys.write

        ; Print the right part of the table row
        push    dword rightlen
        push    dword right
        push    dword stdout
        sys.write

        ; Get rid of the 60 bytes we have pushed
        add     esp, byte 60

        ; Get the next variable
        jmp     .loop

.wrap:
        ; Print the rest of HTML
        push    dword wraplen
        push    dword wrap
        push    dword stdout
        sys.write

        ; Return success
        push    dword 0
        sys.exit

Dieser Code erzeugt eine 1.396-Byte große Binärdatei. Das meiste davon sind Daten, d.h., die HTML-Auszeichnung, die wir versenden müssen.

Assemblieren Sie es wie immer:

% nasm -f elf webvars.asm
% ld -s -o webvars webvars.o

Um es zu benutzen, müssen Sie webvars auf Ihren Webserver hochladen. Abhängig von Ihrer Webserver-Konfiguration, müssen Sie es vielleicht in einem speziellen cgi-bin-Verzeichnis ablegen oder es mit einer .cgi-Dateierweiterung versehen.

Schließlich benötigen Sie Ihren Webbrowser, um sich die Ausgabe anzusehen. Um die Ausgabe auf meinem Webserver zu sehen, gehen Sie bitte auf http://www.int80h.org/webvars/. Falls Sie neugierig sind, welche zusätzlichen Variablen in einem passwortgeschützten Webverzeichnis vorhanden sind, gehen Sie auf http://www.int80h.org/private/ unter Benutzung des Benutzernamens asm und des Passworts programmer.

Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an <de-bsd-questions@de.FreeBSD.org>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an <de-bsd-translators@de.FreeBSD.org>.