UNIX® 中一个重要的概念就是环境, 环境中定义了许多 环境变量。 一些是由系统设置的, 一些则由你自己, 或者是由 shell, 再不然就是载入其它程序的进程设置的。
我曾经说过,当一个程序开始执行的时候, 堆栈包含了参数 argc 并且在 argc 之后包含了 argv 数组, 或者其他的一些东西。这些所谓的其他的东西,是所 环境 或者更确切的说是以 NULL 结尾的指向
环境变量 的指针数组。 这通常称作
env。
env 和 argv
的结构是相同的, 以 NULL ( 0 )结尾的一系列的内存地址。
在这种情况下,不存在 "envc" ── 我们将通过查找最后的 NULL
来定位数组的结尾。
变量常常以 name=value 的形式表现, 但是有的时候 =value 的部分会遗失。 我们需要考虑到这样的情况发生的可能性。
我可以给你展示一些如 UNIX env 命令一样输出环境变量的代码。 但是我想通过写一个简单的汇编 CGI 程序来说明, 将更有意义。
在我的站点上, 我有一个 详细CGI手册, 但这里有一个关于 CGI 的精简概述:
网络服务器根据已经设定的 环境变量 来和 CGI 程序进行通信。
CGI 程序向标准输出 stdout 进行输出。 而网络服务器从那里读取程序的输出。
它必须以 HTTP 头为开始,并在随后空两行。
然后, 它可以打印 HTML 代码, 或者其他由 CGI 产生的数据。
注意: 根据网络服务器的不同,当一些 环境变量 使用标准名称的时候,其他的一些会产生变化。 因此,这使得 webvars 成为一个非常有用的诊断工具。
我们的 webvars 程序, 将发送 HTTP 的头和一些 HTML 的标记, 然后它将一个接一个得读取 环境变量, 然后将它们输出在网页中。
代码如下, 我在代码中添加了注解:
;;;;;;; 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
这个代码将生成一个1396字节的可执行文件, 程序的大部分是数据: 比如那些我们需要发送的 HTML 标记。
然后如往常一样, 编译连接:
% nasm -f elf webvars.asm % ld -s -o webvars webvars.o
如果你要使用它,将它载入你的服务器。 根据你网络服务器的设置, 你可能需要将它放入一个叫 cgi-bin 的目录, 或者重命名一个以 .cgi 结尾的文件名。
然后,你需要用浏览器来看它的输出。 如果要看在我的网络服务器的输出,请访问 http://www.int80h.org/webvars/。 如果对显示密码保护的网络文件目录的环境变量有兴趣, 访问 http://www.int80h.org/private/, 用户名为 asm, 密码为 programmer。
本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.