在 Linux 上运行 Open Genera 2.0
在 Linux 上运行 Open Genera 2.0
1.介绍
从20世纪80年代初到20世纪90年代初期,Symbolics 公司制造了一系列的工作站,上面运行的是一个叫做“genera”的相当高级的 Lisp 环境。 非常专业化的硬件与强大的软件系统相结合,使得这些 Lisp 机器相当的特别。 例如,它在硬件层面执行数组边界检查以及能够在硬件层面直接操作数据结构,而不是像其他通用计算机一样将内存视为一个扁平的数组(现在也还是这样)。Symbolics 为 Genera 环境提供了大尺寸的高分辨率位图显示器,重叠窗口和鼠标控制等工作站级别的功能。 在20世纪80年代初,早在 Macintosh 出现之前,这就是当时最先进的东西。
20世纪90年代初,Symbolics 迈出了大胆的一步,在 Digital Equipment Corporation (DEC)的 Alpha工作站上发布了名为“Open Generas”的通用软件环境。他们创建了一个在 OSF/1(后来的 Digital UNIX)下运行的“虚拟 Lisp 机器”(VLM),并模拟了完整的 Symbolics Lisp 机器体系结构。
VLM 的源代码是用Lisp编写的,执行时会生成Alpha汇编指令。在21世纪初,布拉德·帕克(Brad Parker)想出了一个绝妙的主意,他想看看是否可以调整Alpha汇编生成器,让其生成C代码片段。它成功了,结果 VLM 被移植到了64位Linux。
现在我们进入了一个灰色地带。Symbolics 已经于20世纪90年代中期解散了,目前其知识产权状况混乱不堪。VLM 和 Genera 本身的版权被不同的人分散持有。不再有任何的“Symbolics公司”了。
考虑到这些......
本文档旨在指导您在现代的64位 Linux 系统上安装 VLM 和 Symbolics Open Generas。如果您决定这样做,请注意您可能侵犯到他人的版权,也可能没有侵犯到。总之,玩得开心,玩得安全!
2.必读
如果您不熟悉Genera,则需要阅读以下内容。
-
Genera Concepts (pdf)
-
Genera User's Guide(pdf)
除了上面两篇,我还强烈推荐你阅读 Lisp Lore: A Guide to Programming the Lisp Machine
3.详细的安装指南
3.1.安装Linux
VLM 应该可以在任何现代的64位Linux系统上运行。下面的命令专门针对Ubuntu, 我已经在 Ubuntu 15.10 到 Ubuntu 18.04 LTS 上进行了测试。
选择Ubuntu只是因为我对它最熟悉。这些说明也适用于Debian,只有微小的变化(如果有的话)。同样,它们也可以用于CentOS或Fedora,但是这超出了本文的范畴。
3.2.安装必要的包
您需要curl来下载所需的软件包,所以让我们先安装它。(wget当然也行)
$ sudo apt-get install curl
3.3.为VLM和Genera创建一个目录
目录可以放在任何地方,我把它放在我的 home 目录中只是为了方便操作。
$ mkdir $HOME/genera
3.4.安装VLM
VLM 实际上只是一个叫做genera
的二进制可执行文件。整个的虚拟 Lisp 机都在这个单独的文件中。它的源代码可以在几个地方找到,比如GitHub,你可以从源代码编译(如果现成的程序无法在你的机器上运行的话),或者直接下载预编译的二进制文件。
预编译的二进制文件有两个版本,genera
是在 Core-i7 机器上编译的,genera-i5
是在 Core-i5 机器上编译的。有些用户报告,针对 Core-i7 的二进制文件不适用于较旧的 I5 机器,因此如果它出现了非法指令错误,请尝试针对 Core-I5 的二进制文件。[译注:AMD CPU 的机器也可以运行,需要自己编译]
3.4.1 Core i7 的二进制文件
$ cd $HOME/genera
$ curl -L -O https://archives.loomcom.com/genera/genera
$ chmod a+x genera
3.4.2 Core i5 的二进制文件
$ cd $HOME/genera
$ curl -L https://archives.loomcom.com/genera/genera-i5 -o genera
$ chmod a+x genera
3.5.下载World和调试器文件
Genera 自身发布为两个组件:
-
一个"World"文件,其中包含了序列化到磁盘的Lisp机的整个运行状态。该文件名为
Genera-8-5-xlib-patched.vlod
(可以改成任何名字) -
通过NFS导出的本地UNIX文件系统上的文件。这些文件位于
/var/lib/symbolics
下。
下面的步骤将会下载所需的文件,并将它们放在正确的地方。
$ cd $HOME/genera/
$ curl -L -O https://archives.loomcom.com/genera/worlds/Genera-8-5-xlib-patched.vlod
$ curl -L -O https://archives.loomcom.com/genera/worlds/VLM_debugger
$ curl -L -O https://archives.loomcom.com/genera/worlds/dot.VLM
$ mv dot.VLM .VLM
$ cd /var/lib
$ sudo curl -L -O https://archives.loomcom.com/genera/var_lib_symbolics.tar.gz
$ sudo tar xvf var_lib_symbolics.tar.gz
接下来,我们希望symbolics
目录的所有者是将要运行 Genera 的用户(即,你自己的帐号)。 在典型的 Ubuntu 安装中,你的 UID 和 GID 都是 1000,但是也不一定,请务必在此处使用正确的用户名和组名。 另请注意,还应该与下面设置NFS中使用的UID和GID相匹配。
$ sudo chown -R <user>:<group> symbolics
最后,编辑.VLM
文件,修改下面的行:
genera.worldSearchPath: /home/seth/genera
将它改成你放置 Genera 文件的实际目录。
注意:如果你决定使用与本教程不同的IP地址,请务必根据实际情况修改下面这行:
genera.network: tap0:INTERNET|192.168.2.2;gateway=192.168.2.1
3.6.设置hosts文件
编辑/etc/hosts
以匹配将要安装VLM的内部网络。这些IP地址可以更改为任何你喜欢的,事实上,一些非常高级的网络也是可能的,但是为了简单起见,我建议你坚持使用这些IP地址。如果你使用不同的IP地址,至少你需要编辑你的.VLM
文件。
你可以将下面的主机名genera-vlm
和genera
改成任何你喜欢的名字,但是你必须记住之后在设置 Lisp 机时使用正确的名字!
VLM 的 Genera 软件将使用 192.168.2.2
,UNIX (Linux) 主机将创建一个绑定到 192.168.2.1
的 tun0
接口。
192.168.2.1 genera-vlm
192.168.2.2 genera
3.7.配置time和daytime服务
Genera 通过老式的time
和daytime
服务从UNIX同步时钟。在现在的Linux系统上,这些服务默认是关闭的(甚至都没有安装),因此,你需要安装并启用它们。
sudo apt-get install inetutils-inetd
然后编辑/etc/inetd.conf
sudo vi /etc/inetd.conf
替换成下面的内容:
time stream tcp nowait root internal
time dgram udp wait root internal
daytime stream tcp nowait root internal
daytime dgram udp wait root internal
重启服务
$ sudo systemctl restart inetutils-inetd.service
通过telnet localhost 37
和telnet localhost 13
确认它已经正常工作
3.8.安装并配置NFS
Genera 通过 NFS 访问本地主机(Linux)上的文件。
首先,安装 NFS:
$ sudo apt-get install nfs-kernel-server
接下来是配置,你应该根据实际的用户 UID 和 GID 修改下面的anonuid
和anongid
的值,在典型的ubuntu安装中,主要用户的UID和GID都是1000,但是请自行核实一下。
编辑 /etc/exports
/ genera(rw,sync,no_subtree_check,all_squash,anonuid=1000,anongid=1000)
重启 NFS 服务
$ sudo systemctl restart nfs-kernel-server
然后,验证文件系统是否已正确导出, 运行
$ sudo exportfs -rav
3.8.1 17.04及更高版本的Ubuntu说明
OpenGenera 使用的是非常老旧的 NFSv2 协议,Ubuntu 17.04 及之后的版本默认不启用 NFSv2, 你需要执行一些额外的工作以启用 NFSv2。
编辑 /etc/default/nfs-kernel-server
, 你需要将下面的这两行:
RPCNFSDCOUNT=8
RPCMOUNTDOPTS="--manage-gids"
改成:
RPCNFSDCOUNT="--nfs-version 2 8"
RPCMOUNTDOPTS="--nfs-version 2 --manage-gids"
最后,重启 NFS
$ sudo systemctl restart nfs-kernel-server
3.9 创建 tap0 接口
我们将让 Genera 通过分配给 TUN/TAP 接口的地址来访问主机的 NFS 导出的文件系统。在 Linux 上,这很简单。
# sudo ip tuntap add dev tap0 mode tap
# sudo ip addr add 192.168.2.1/24 dev tap0
# sudo ip link set dev tap0 up
Genera 分配到 192.168.2.2 的地址,并且期望通过 192.168.2.1 找到 NFS 上的文件。
记住! 每次重新启动时都需要执行此操作。 有办法使这个永久性的,但我会把它作为对读者的锻炼。
[译注:编辑/etc/network/interfaces
,添加下面的代码]
allow-hotplug tap0
auto tap0
iface tap0 inet manual
pre-up ip tuntap add tap0 mode tap
pre-up ip addr add 192.168.2.1/24 dev tap0
up ip link set dev tap0 up
post-down ip link del dev tap0
3.10 启动 Genera
现在,你已经准备好第一次启动了!
不幸的是 Ubuntu 17.10 还需要一些特殊的步骤,所以我把它分成了两个分支分别讲解。
3.10.1 Ubuntu 17.04 之前以及 Ubuntu 18.04 之后(非 Ubuntu 17.10)
从$HOME/genera
直接运行:
$ ./genera
3.10.2 Ubuntu 17.10 only
Ubuntu 17.10 默认使用 Wayland 而非 X11,Wayland 通常是与 X11 兼容的,但是它和 OpenGenera 不兼容,因为 OpenGenera 使用了相当老旧的 X11 协议。
幸运的是,我们可以使用 Ubuntu 17.10 预装的 Xephyr X11 服务器来解决这个问题。
在你的~/genera
目录下创建一个名为 start-genera.sh
的脚本,内容如下:
#!/bin/bash
Xephyr -br -reset -terminate -ac -noreset -screen 1280x1024 :3 &
DISPLAY=:3.0
export DISPLAY
./genera -coldloadgeometry 640x480+0+0 -geometry 1280x1024+0+0
3.11 登陆并定义站点
你现在应该已经看到初始的 world 了,它看起来像这样:
重要!如果你输入错误,请使用 delete 键来向后删除,而不是退格键。这是 Genera 的标准!!
你刚刚启动的 world 是一个初始的 world。你已经可以用它来做很多事情了,但是你最好定义一个 site,然后将它保存为 working world。这样,你就可以让初始 workd 成为一个备份,以防你以后想要从头开始。
请注意,定义站点会将文件写入 NFS,位于genera-vlm:/var/lib/symbolics/sys.sct/
下面的文件将会被修改。如果你真的想要重新开始,你需要删除/var/lib/symbolics
然后再将 tar 重新解压到该目录。
3.11.1 登陆
当Genera启动时,您应该会看到一个如下所示的提示:
Please login.
Command:
您需要做的第一件事就是登录。有一个特殊的名为lisp-machine
的全局用户,这就是我们将要登录的帐户。
在提示符Command
后面输入:
login lisp-machine
你会看到,在输入login
以后,Genera 会提示你输入用户名(user name)
。这只是 Genera 众多的人性化措施之一。
3.11.2 定义你自己的站点
接下来,你需要定义一个站点,在Command
提示符后输入:
Define Site
Genera 会进行响应并自动填充(site name)
,你可以在后面输入站点的名字。站点名应该是一个单词(我使用的站点名是“Gecko”),然后按回车。
现在,点击
Namespace Server Name: the name of the primary namespace server
输入genera
然后按回车。Genera 会响应并添加多个可以编辑的字段。
在下面的字段上点击:
Unix Host Name: the name of the DEC-AXP host on which Open Genera is running
这一次,输入genera-vlm
执行完上面两步,点击"END"(或按End
键)保存更改。现在,你已经定义了自己的站点!
对话框应该如下所示:
现在,是时候保存 wrold 了。
3.12 保存 World
3.12.1 一次性设置
定义站点后,主机"genera"的IP地址是错误的。它被设置为Linux主机的外部IP地址。需要将它修改为 192.168.2.1 , 以免你无法重新加载你保存的 world, 避免很多麻烦。
输入
Edit Namespace Object Host genera
把地址改成
INTERNET 192.168.2.2 tap0
现在输入
Save Object
跳出提示后回答"Yes"。最后,输入 quit
退出编辑,返回顶层的LISP监听器.
你必须在保存 world 之前完成,否则从 world 中恢复运行时你将无法访问本地网络。
3.12.2 保存 World
现在,你已经准备好保存你的 working world 了。
在 Command
提示符后输入:
Save World
当你按下空格键以后,会收到下面的提示信息:
Save World (on file [default GENERA-VLM:Genera-8-5.vlod])
那是默认的 world 名字,你可以改成任意名字。例如,我将我的 world 命名为 GENERA-VLM:Genera-8-5-working.vlod
。输入完毕后,按回车。
你会被要求确认,输入Y
并回车。
此时,Genera 将重新启动。 但它尚未准备好使用! 您需要关闭 Genera,编辑.VLM
文件,然后再重新启动。
3.13 关闭 Genera
输入
Halt Genera
你会被要求进行几次确认,此时,会弹出调试窗口,并要求你再次确认是否真的想退出 Lisp(如果调试器窗口没有弹出来,请自行寻找隐藏的窗口并在其中输入Y
再一次确认。)
现在,你回到了 Linux,接下来是编辑 .VLM
文件。
3.14 编辑 .VLM 文件
打开你的 .VLM
文件,找到并注释掉 genera.world: Genera-8-5-xlib-patched.vlod
这一行,添加下面一行:
[注:用 #
或*
都可以注释]
genera.world: Genera-8-5-working.vlod
(请根据你保存 world 的文件名自行修改)
至此,你可以输入 ./genera
来重新启动 Genera.
祝贺!你已经处在一个正常运转的 Genera 世界中,是时候去探索了。
4. 有用的 Genera 知识
4.1 关机
要关机,请输入
Halt Genera
你会被要求几次确认,当 Genera 的窗口关闭后,你必须在冷启动窗口中再确认一次。
4.2 键盘映射
Symbolics 的 Lisp 机有非常惊人的键盘,上面布满了修饰键。
在 Symbolics 发布 VLM 时,他们意识到出了问题。DEC Alpha 工作站使用 PS/2 式的键盘,因此他们必须以某种方式将所有的修饰键映射到 PS/2 的键盘代码,并构建一个转换器盒子来使用他们的键盘和 DEC 硬件。
于是,下面的映射就诞生了。只要遵循下面的映射,就可以使用常规的 101 或 104 PC 键盘。(注意:"KP"代表的是数字键盘上的键)
[译注:下面列出了常用的键映射及快捷键]
Select F1 Network F2 Function F3 Suspend F4 Resume F5 Abort F6 Super L F7 s- Hyper L F8 h- Scroll F9 ClearInput F10 Complete F11 Help F12 Local Windows Shift Shift sh- Control Ctrl c- Meta Alt m- Return Enter
切换不同的活动: Select(F1): = select Key Selector C Converse D Document Examiner F File System Maintenance Operations I Inspector L Lisp M Zmail N Notifications p Peek Q Frame-Up T Terminal X Flavor Examiner Function(F3) S 回到上一个活动 C-M-y 上一个命令, 进入历史命令模式后,可以重复按 M-y 显示曾经执行过的命令
4.3 滚屏
一段时间不用,我就会忘记如何滚屏。其实很简单:
鼠标键 | 描述 |
---|---|
左键 | 将鼠标指示线所在的行移动到屏幕顶部(向上滚) |
右键 | 将当前位于屏幕顶部的行移动到鼠标指示线的位置 |
shift-左键 | 将指示线所在的行移动到屏幕底部 |
中键 | 显示与指示线相对于窗口位置百分比所对应的内容 |
4.4 设定Who-Calls
当一个站点被定义时,Genera 会为你自动调用(si:enable-who-calls :new)
。但是我们希望在所有函数上启用 who-calls,而不仅仅是新函数,所以,我们必须手动设置:
(si:enable-who-calls :all)
需要花几分钟的时间。
4.5 查找函数
要搜索所有名字中包含了"crypt"函数,可以简单地输入:
(apropos "crypt")
4.6 Who Calls
在上面的 Who Calls 设置完成后,你可以找到 rpc::encrypted-password
的所有调用者.
(who-calls 'rpc::encrypted-password)
4.7 认证
UNIX 身份验证似乎是在RPC::UNIX-AUTHENTICATION-MIXIN
中定义的。具体请参阅 RPC::USERNAME-AND-PASSWORD-VALID-P
函数
下面是初始的定义:
(defun-in-flavor (username-and-password-valid-p unix-authentication-mixin)
(username password)
(declare (values username-valid-p password-valid-p))
(if (null username)
(values nil nil)
(multiple-value-bind (encrypted-password defaulted-p)
(let ((*unix-authentication-allow-defaulting* t))
(username->password (unix-name-lookup-access-path) username))
(cond ((and defaulted-p
(not (string-equal username "anonymous"))
(not (string-equal username "lisp-machine"))
(not (string-equal username "nobody")))
(values nil nil))
((or (zerop (string-length encrypted-password))
(and password
(string= (unix-crypt password encrypted-password)
encrypted-password)))
(values t t))
(t
(values t nil))))))
我们可以 Hack 这个函数来克服 NIS 身份验证中对 crypt-style 密码的需要。我们可以在这里做一些事:
- 实现 MD5, SHA256 或者 SHA512 加密
- 添加某种类型的 no-op 来 hack
(unix-crypt)
- 弄清楚 Genera 的 Flavor 系统,并真正实现我们自己的登录mixin(这才是正确的方式?)
我个人所做的就是修改函数,让我可以使用密码“xyzzy”登录。 这是非常愚蠢的,但它可以工作。 这也是 hack Genera 的一个介绍。
下面就是我的修改,注意 (string= "xyzzy" password)
(defun-in-flavor (username-and-password-valid-p unix-authentication-mixin)
(username password)
(declare (values username-valid-p password-valid-p))
(if (null username)
(values nil nil)
(multiple-value-bind (encrypted-password defaulted-p)
(let ((*unix-authentication-allow-defaulting* t))
(username->password (unix-name-lookup-access-path) username))
(cond ((and defaulted-p
(not (string-equal username "anonymous"))
(not (string-equal username "lisp-machine"))
(not (string-equal username "nobody")))
(values nil nil))
((or (zerop (string-length encrypted-password))
(string= "xyzzy" password)
(and password
(string= (unix-crypt password encrypted-password)
encrypted-password)))
(values t t))
(t
(values t nil))))))
5 附录A: Genera's 的 XLIB 补丁
教程中使用的 Genera-8-5-xlib-patched.vlod 已经是打过补丁的了,所以这一段省略。
[译者后记] 我原本是在 Linux Mint 20 上安装成功的,后来系统更新后不知道从什么时候起就出问题了。在 Save world 的时候提示 nfs 上的目录写保护。我排查了许久没发现问题出在哪里。因为 Linux Mint 的基础系统是 Ubuntu, 所以估计新版本的 Ubuntu 也有同样的问题。目前我暂时的解决办法是在虚拟机里安装 Debian, 将 Genera 安装到虚拟机的 debian 系统里,再 ssh -X
运行,窗口显示在本地系统中。