FreeBSD Developers' Handbook
Zurück | Kapitel 11. x86-Assembler-Programmierung | Weiter

# 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`.

Zurück | Zum Anfang | Weiter
Kommandozeilenparameter | Nach oben | Arbeiten mit Dateien

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>.