aboutsummaryrefslogtreecommitdiff
path: root/zh_TW.UTF-8
diff options
context:
space:
mode:
authorLi-Wen Hsu <lwhsu@FreeBSD.org>2014-05-29 16:48:07 +0000
committerLi-Wen Hsu <lwhsu@FreeBSD.org>2014-05-29 16:48:07 +0000
commit163ba6b752e2d1b900f88ba29324ed5998b14551 (patch)
tree3010592efec60252103b5e76eab918b0491bb533 /zh_TW.UTF-8
parent536050cea8f16998f8fbddf6b4aff8469e149ec0 (diff)
downloaddoc-163ba6b752e2d1b900f88ba29324ed5998b14551.tar.gz
doc-163ba6b752e2d1b900f88ba29324ed5998b14551.zip
Convert zh_TW from Big5 to UTF-8.
Approved by: bcr
Notes
Notes: svn path=/head/; revision=44974
Diffstat (limited to 'zh_TW.UTF-8')
-rw-r--r--zh_TW.UTF-8/Makefile9
-rw-r--r--zh_TW.UTF-8/Makefile.inc3
-rw-r--r--zh_TW.UTF-8/articles/Makefile15
-rw-r--r--zh_TW.UTF-8/articles/Makefile.inc5
-rw-r--r--zh_TW.UTF-8/articles/contributing/Makefile22
-rw-r--r--zh_TW.UTF-8/articles/contributing/article.xml465
-rw-r--r--zh_TW.UTF-8/articles/cvs-freebsd/Makefile21
-rw-r--r--zh_TW.UTF-8/articles/cvs-freebsd/article.xml570
-rw-r--r--zh_TW.UTF-8/articles/freebsd-questions/Makefile22
-rw-r--r--zh_TW.UTF-8/articles/freebsd-questions/article.xml610
-rw-r--r--zh_TW.UTF-8/articles/hubs/Makefile17
-rw-r--r--zh_TW.UTF-8/articles/hubs/article.xml1051
-rw-r--r--zh_TW.UTF-8/articles/mailing-list-faq/Makefile26
-rw-r--r--zh_TW.UTF-8/articles/mailing-list-faq/article.xml416
-rw-r--r--zh_TW.UTF-8/articles/nanobsd/Makefile28
-rw-r--r--zh_TW.UTF-8/articles/nanobsd/article.xml434
-rw-r--r--zh_TW.UTF-8/articles/pr-guidelines/Makefile19
-rw-r--r--zh_TW.UTF-8/articles/pr-guidelines/article.xml875
-rw-r--r--zh_TW.UTF-8/articles/problem-reports/Makefile19
-rw-r--r--zh_TW.UTF-8/articles/problem-reports/article.xml1103
-rw-r--r--zh_TW.UTF-8/articles/remote-install/Makefile30
-rw-r--r--zh_TW.UTF-8/articles/remote-install/article.xml475
-rw-r--r--zh_TW.UTF-8/books/Makefile13
-rw-r--r--zh_TW.UTF-8/books/Makefile.inc5
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/Makefile42
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/book.xml183
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/chapters.ent33
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/introduction/chapter.xml186
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/ipv6/chapter.xml1571
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/kerneldebug/Makefile15
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/kerneldebug/chapter.xml848
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/l10n/chapter.xml75
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/policies/Makefile15
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/policies/chapter.xml402
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/secure/chapter.xml518
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/sockets/chapter.xml1780
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/testing/chapter.xml212
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/tools/chapter.xml2139
-rw-r--r--zh_TW.UTF-8/books/developers-handbook/x86/chapter.xml6486
-rw-r--r--zh_TW.UTF-8/books/faq/Makefile27
-rw-r--r--zh_TW.UTF-8/books/faq/book.xml11876
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/Makefile51
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/book.xml234
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/chapters.ent27
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/doc-build/chapter.xml486
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/examples/appendix.xml336
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/overview/chapter.xml241
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/psgml-mode/chapter.xml165
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/see-also/chapter.xml122
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/sgml-markup/chapter.xml2682
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/sgml-primer/chapter.xml1543
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/structure/chapter.xml281
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/stylesheets/chapter.xml92
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/the-website/chapter.xml191
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/tools/chapter.xml235
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/translations/chapter.xml383
-rw-r--r--zh_TW.UTF-8/books/fdp-primer/writing-style/chapter.xml440
-rw-r--r--zh_TW.UTF-8/books/handbook/Makefile269
-rw-r--r--zh_TW.UTF-8/books/handbook/advanced-networking/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/advanced-networking/chapter.xml5438
-rw-r--r--zh_TW.UTF-8/books/handbook/audit/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/audit/chapter.xml567
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/chapter.xml2366
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/example-dir1.dot7
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/example-dir2.dot8
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/example-dir3.dot8
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/example-dir4.dot9
-rw-r--r--zh_TW.UTF-8/books/handbook/basics/example-dir5.dot9
-rw-r--r--zh_TW.UTF-8/books/handbook/bibliography/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/bibliography/chapter.xml630
-rw-r--r--zh_TW.UTF-8/books/handbook/book.xml274
-rw-r--r--zh_TW.UTF-8/books/handbook/boot/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/boot/chapter.xml802
-rw-r--r--zh_TW.UTF-8/books/handbook/chapters.ent71
-rw-r--r--zh_TW.UTF-8/books/handbook/colophon.xml21
-rw-r--r--zh_TW.UTF-8/books/handbook/config/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/config/chapter.xml3095
-rw-r--r--zh_TW.UTF-8/books/handbook/cutting-edge/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/cutting-edge/chapter.xml1535
-rw-r--r--zh_TW.UTF-8/books/handbook/desktop/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/desktop/chapter.xml1037
-rw-r--r--zh_TW.UTF-8/books/handbook/disks/Makefile16
-rw-r--r--zh_TW.UTF-8/books/handbook/disks/chapter.xml3849
-rw-r--r--zh_TW.UTF-8/books/handbook/eresources/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/eresources/chapter.xml1676
-rw-r--r--zh_TW.UTF-8/books/handbook/firewalls/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/firewalls/chapter.xml3260
-rw-r--r--zh_TW.UTF-8/books/handbook/geom/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/geom/chapter.xml356
-rw-r--r--zh_TW.UTF-8/books/handbook/install/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/install/chapter.xml4503
-rw-r--r--zh_TW.UTF-8/books/handbook/install/example-dir1.dot7
-rw-r--r--zh_TW.UTF-8/books/handbook/install/example-dir2.dot8
-rw-r--r--zh_TW.UTF-8/books/handbook/install/example-dir3.dot8
-rw-r--r--zh_TW.UTF-8/books/handbook/install/example-dir4.dot9
-rw-r--r--zh_TW.UTF-8/books/handbook/install/example-dir5.dot9
-rw-r--r--zh_TW.UTF-8/books/handbook/introduction/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/introduction/chapter.xml842
-rw-r--r--zh_TW.UTF-8/books/handbook/jails/chapter.xml793
-rw-r--r--zh_TW.UTF-8/books/handbook/kernelconfig/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/kernelconfig/chapter.xml1387
-rw-r--r--zh_TW.UTF-8/books/handbook/l10n/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/l10n/chapter.xml884
-rw-r--r--zh_TW.UTF-8/books/handbook/linuxemu/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/linuxemu/chapter.xml3281
-rw-r--r--zh_TW.UTF-8/books/handbook/mac/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/mac/chapter.xml2274
-rw-r--r--zh_TW.UTF-8/books/handbook/mail/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/mail/chapter.xml2227
-rw-r--r--zh_TW.UTF-8/books/handbook/mirrors/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/mirrors/chapter.xml3190
-rw-r--r--zh_TW.UTF-8/books/handbook/multimedia/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/multimedia/chapter.xml1741
-rw-r--r--zh_TW.UTF-8/books/handbook/network-servers/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/network-servers/chapter.xml5074
-rw-r--r--zh_TW.UTF-8/books/handbook/pgpkeys/Makefile18
-rw-r--r--zh_TW.UTF-8/books/handbook/pgpkeys/chapter.xml41
-rw-r--r--zh_TW.UTF-8/books/handbook/ports/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/ports/chapter.xml1300
-rw-r--r--zh_TW.UTF-8/books/handbook/ppp-and-slip/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/ppp-and-slip/chapter.xml3116
-rw-r--r--zh_TW.UTF-8/books/handbook/preface/preface.xml510
-rw-r--r--zh_TW.UTF-8/books/handbook/printing/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/printing/chapter.xml4737
-rw-r--r--zh_TW.UTF-8/books/handbook/security/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/security/chapter.xml4992
-rw-r--r--zh_TW.UTF-8/books/handbook/serialcomms/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/serialcomms/chapter.xml2856
-rw-r--r--zh_TW.UTF-8/books/handbook/txtfiles.ent72
-rw-r--r--zh_TW.UTF-8/books/handbook/users/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/users/chapter.xml940
-rw-r--r--zh_TW.UTF-8/books/handbook/vinum/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/vinum/chapter.xml1458
-rw-r--r--zh_TW.UTF-8/books/handbook/virtualization/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/virtualization/chapter.xml886
-rw-r--r--zh_TW.UTF-8/books/handbook/x11/Makefile15
-rw-r--r--zh_TW.UTF-8/books/handbook/x11/chapter.xml1516
-rw-r--r--zh_TW.UTF-8/books/porters-handbook/Makefile39
-rw-r--r--zh_TW.UTF-8/books/porters-handbook/book.xml12963
-rw-r--r--zh_TW.UTF-8/htdocs/Makefile47
-rw-r--r--zh_TW.UTF-8/htdocs/Makefile.inc5
-rw-r--r--zh_TW.UTF-8/htdocs/about.xml99
-rw-r--r--zh_TW.UTF-8/htdocs/applications.xml129
-rw-r--r--zh_TW.UTF-8/htdocs/art.xml127
-rw-r--r--zh_TW.UTF-8/htdocs/availability.xml27
-rw-r--r--zh_TW.UTF-8/htdocs/community.xml27
-rw-r--r--zh_TW.UTF-8/htdocs/developers.xml566
-rw-r--r--zh_TW.UTF-8/htdocs/doc/Makefile47
-rw-r--r--zh_TW.UTF-8/htdocs/docs.xml25
-rw-r--r--zh_TW.UTF-8/htdocs/docs/Makefile16
-rw-r--r--zh_TW.UTF-8/htdocs/docs/books.xml364
-rw-r--r--zh_TW.UTF-8/htdocs/docs/webresources.xml111
-rw-r--r--zh_TW.UTF-8/htdocs/index.xsl292
-rw-r--r--zh_TW.UTF-8/htdocs/layout/Makefile15
-rw-r--r--zh_TW.UTF-8/htdocs/layout/Makefile.inc7
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/Makefile21
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/fixed.css23
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/fixed_large.css14
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/global.css22
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/layout.css54
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/navigation.css37
-rw-r--r--zh_TW.UTF-8/htdocs/layout/css/text.css28
-rw-r--r--zh_TW.UTF-8/htdocs/logo.xml118
-rw-r--r--zh_TW.UTF-8/htdocs/send-pr.xml162
-rw-r--r--zh_TW.UTF-8/htdocs/support.xml40
-rw-r--r--zh_TW.UTF-8/htdocs/where.xml234
-rw-r--r--zh_TW.UTF-8/share/xml/authors.ent94
-rw-r--r--zh_TW.UTF-8/share/xml/catalog.xml35
-rw-r--r--zh_TW.UTF-8/share/xml/entities.ent26
-rw-r--r--zh_TW.UTF-8/share/xml/freebsd-dblatex.xsl17
-rw-r--r--zh_TW.UTF-8/share/xml/freebsd-fo.xsl68
-rw-r--r--zh_TW.UTF-8/share/xml/freebsd-xhtml.xsl20
-rw-r--r--zh_TW.UTF-8/share/xml/glossary.ent1920
-rw-r--r--zh_TW.UTF-8/share/xml/header.l10n.ent41
-rw-r--r--zh_TW.UTF-8/share/xml/l10n.ent28
-rw-r--r--zh_TW.UTF-8/share/xml/libcommon.xsl106
-rw-r--r--zh_TW.UTF-8/share/xml/mailing-lists.ent443
-rw-r--r--zh_TW.UTF-8/share/xml/navibar.l10n.ent167
-rw-r--r--zh_TW.UTF-8/share/xml/news.xml2579
-rw-r--r--zh_TW.UTF-8/share/xml/press.xml528
-rw-r--r--zh_TW.UTF-8/share/xml/release.l10n.ent137
-rw-r--r--zh_TW.UTF-8/share/xml/trademarks.ent310
-rw-r--r--zh_TW.UTF-8/share/xml/urls.ent125
184 files changed, 136913 insertions, 0 deletions
diff --git a/zh_TW.UTF-8/Makefile b/zh_TW.UTF-8/Makefile
new file mode 100644
index 0000000000..55b5374fdf
--- /dev/null
+++ b/zh_TW.UTF-8/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+SUBDIR = articles
+SUBDIR += books
+
+COMPAT_SYMLINK= zh_TW
+
+DOC_PREFIX = ${.CURDIR}/..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/Makefile.inc b/zh_TW.UTF-8/Makefile.inc
new file mode 100644
index 0000000000..453700a49b
--- /dev/null
+++ b/zh_TW.UTF-8/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+DOC_PREFIX?= ${.CURDIR}/../..
diff --git a/zh_TW.UTF-8/articles/Makefile b/zh_TW.UTF-8/articles/Makefile
new file mode 100644
index 0000000000..dda9fb6ed3
--- /dev/null
+++ b/zh_TW.UTF-8/articles/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+SUBDIR =
+SUBDIR+= contributing
+SUBDIR+= cvs-freebsd
+SUBDIR+= freebsd-questions
+SUBDIR+= hubs
+SUBDIR+= mailing-list-faq
+SUBDIR+= nanobsd
+SUBDIR+= pr-guidelines
+SUBDIR+= problem-reports
+SUBDIR+= remote-install
+
+DOC_PREFIX?= ${.CURDIR}/../..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/Makefile.inc b/zh_TW.UTF-8/articles/Makefile.inc
new file mode 100644
index 0000000000..e9ca57f579
--- /dev/null
+++ b/zh_TW.UTF-8/articles/Makefile.inc
@@ -0,0 +1,5 @@
+#
+# $FreeBSD$
+#
+
+DESTDIR?= ${DOCDIR}/zh_TW.UTF-8/articles/${.CURDIR:T}
diff --git a/zh_TW.UTF-8/articles/contributing/Makefile b/zh_TW.UTF-8/articles/contributing/Makefile
new file mode 100644
index 0000000000..72cfc4b491
--- /dev/null
+++ b/zh_TW.UTF-8/articles/contributing/Makefile
@@ -0,0 +1,22 @@
+#
+# The FreeBSD Traditional Chinese Project
+#
+# Original Revision: 1.6
+# $FreeBSD$
+#
+# Article: Contributing to FreeBSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/contributing/article.xml b/zh_TW.UTF-8/articles/contributing/article.xml
new file mode 100644
index 0000000000..56ff1a66e0
--- /dev/null
+++ b/zh_TW.UTF-8/articles/contributing/article.xml
@@ -0,0 +1,465 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Traditional) Documentation Project
+
+ Original Revision: 1.506
+ Chased Revision: 1.508
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>幫助 FreeBSD</title>
+
+
+ <abstract>
+ <para>無論是個人或是各種組織,如果希望為 FreeBSD 提供幫助,都可以在本文中找到合適的方法。</para>
+ </abstract>
+
+ <authorgroup>
+ <author><personname><firstname>Jordan</firstname><surname>Hubbard</surname></personname><contrib>原著: </contrib></author>
+ </authorgroup>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.ieee;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ </info>
+
+ <indexterm><primary>貢獻</primary></indexterm>
+
+ <para>你希望替 FreeBSD 做點什麼嗎?太好了,我們歡迎你。FreeBSD
+ 正是有賴於廣大使用者的貢獻才得以發展壯大的。我們不僅非常感謝您所做的貢獻,而且,這些工作對於 FreeBSD 的持續發展也至關重要。</para>
+
+
+ <para>也許與您想像的不同,您既不必得是一名出色的 Programmer,也無須和
+ FreeBSD core team 成員有很好的私交,我們會一視同仁的對待您的工作。
+ FreeBSD 的開發人員遍布全球,大家技術專長各異,年齡分布也非常廣泛。
+ 然而,每天我們都在面對持續增加的工作,而苦於沒有足夠的人手,因此我們隨時歡迎您的幫助。</para>
+
+ <para>FreeBSD 計劃所處理的是一個完整的作業系統環境,而不只是一個 kernel 或是一些零散的工具包。
+ 因此,我們的 <filename>TODO</filename> 待辦任務列表裡包含各式各樣的工作:
+ 從文件、使用者測試、demo,到系統安裝程式和更專業的 kernel 開發。
+ 因此無論您的技術水準如何,從事何種領域,都可以幫助這個計劃。</para>
+
+ <para>我們鼓勵從事和 FreeBSD 相關工作的企業和我們聯繫。
+ 您需要一些特殊的擴展來使您的產品運轉起來嗎?
+ 您會發現我們很樂意答應您的請求,除非是特別稀奇古怪的。
+ 您是否正從事相關的增值業務? 讓我們來幫助您吧,
+ 我們也許可以在某些方面相互合作。
+ 自由軟體界正在努力打破舊有的框框(像是關於軟體開發、銷售和維護),
+ 我們希望懇請您至少能給它一次機會。</para>
+
+ <sect1 xml:id="contrib-what">
+ <title>我們的需求</title>
+
+ <para>下面列出了一些需要完成的任務和子計劃,
+ 它們代表 <filename>TODO</filename>(待辦任務列表)
+ 列表的意思,以及使用者的要求。</para>
+
+ <sect2 xml:id="non-programmer-tasks">
+ <title>正在進行中的任務(非程式開發人員)</title>
+
+ <para>很多參加 FreeBSD 計劃的人不是 Programmer。
+ 這個計劃裡有文件撰寫者、網頁設計師、以及技術支援人員。
+ 對於這些義工來說,他們只需要貢獻一些時間,並且具有學習的意願。</para>
+
+ <orderedlist>
+ <listitem>
+ <para>您可以時常翻閱 FAQ 和手冊(Handbook)
+ ,如果發現有解釋不清楚的地方,或是不合時宜的文件,甚至完全不正確的地方,
+ 都請告訴我們。當然,若能順手把他們修正,並把勘誤寄給我們,那就更好了。:)
+ (SGML 其實並不難學,但我們也不反對您直接提交一般 ASCII 的純文字版本)。</para>
+ </listitem>
+
+ <listitem>
+ <para>幫助我們把 FreeBSD 文件翻譯成你的母語。
+ 如果你的母語版本已經存在了,
+ 也可以翻譯一些額外的文件,或者檢查那些已有的文件是否為最新版。
+ 您可以先簡單看看 FreeBSD 文件計劃中有關 <link xlink:href="&url.books.fdp-primer;/translations.html">翻譯時的常見問題</link>。
+ 參加翻譯工作,並不是說您要孤軍奮戰翻譯所有 FreeBSD 文件。
+ 身為義工,要做多少工作完全取決於您的意願。一旦某個人開始翻譯了,
+ 之後幾乎一定會有其他人參與到這些工作中來。
+ 如果時間有限,或者精力不夠去翻譯整份文件,那可以首先去翻譯安裝指南。</para>
+ </listitem>
+
+ <listitem>
+ <para>閱讀 &a.questions; 並偶爾翻閱(甚至有規律地這樣做) &ng.misc;
+ 。與別人分享您的專業知識,
+ 並幫助他們解決問題,是件令人愉悅的事情;
+ 有時候,您甚至可以在這個過程中學到一些新東西!
+ 這些論壇有時也會為您激發出一些不錯的想法。</para>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2 xml:id="ongoing-programmer-tasks">
+ <title>正在進行中的任務(程式開發人員)</title>
+ <para>列在這裡的大部分任務都需要您投入可觀的時間,或者需要您在 FreeBSD kernel
+ 方面有豐富的知識,或者兩者都要。當然這裡也有很多重要的任務,適合像是
+ <quote>weekend hackers</quote> 這類只用週末就可以搞定的 Hacker。</para>
+
+ <orderedlist>
+ <listitem>
+ <para>如果您正在跑的是 FreeBSD -CURRENT 版本,並且網路速度還不錯,
+ 那麼可以到 <systemitem class="fqdomainname">current.FreeBSD.org</systemitem>,
+ 這台每天會有一個新版本 &mdash; 如果您有空,
+ 您可以三不五時下載並安裝,
+ 其間如果出了什麼問題,請告訴我們。</para>
+ </listitem>
+
+ <listitem>
+ <para>閱讀 &a.bugs;。這些問題,或許您能提供有建設性意義的意見,
+ 或者幫忙測試一些 patch 。此外,甚至可以嘗試修正其中的一些問題。</para>
+ </listitem>
+
+ <listitem>
+ <para>如果您知道有一些修正已經在 -CURRENT 上成功地使用,
+ 但在經過一段時間(通常是 2 週左右)之後,仍未合併到 -STABLE
+ (這步驟就是 MFC -- Merged From Current),那麼可以給相關的 committer 人員發封禮貌的提醒信。</para>
+ </listitem>
+
+ <listitem>
+ <para>將第三方(3rd party)軟體加入到原始碼中的
+ <filename>src/contrib</filename> 目錄。</para>
+ </listitem>
+
+ <listitem>
+ <para>確保 <filename>src/contrib</filename> 中的原始碼是最新的。</para>
+ </listitem>
+
+ <listitem>
+ <para>編譯原始碼(或是部分原始碼)時,請改用更高的警告等級(warning level)
+ 以便偵錯(debug)用,並在完成測試、確認正常完畢之後,清除這些編譯的警告等級。</para>
+ </listitem>
+
+ <listitem>
+ <para>更新那些在 ports 中使用過時的東西,
+ 例如 <function>gets()</function> 或包含
+ <filename>malloc.h</filename> 所產生的警告。</para>
+ </listitem>
+
+ <listitem>
+ <para>如果有為 ports 作了任何修正,
+ 請記得將您的 patch 發給原作者 (這樣下次升級時,您的工作會變得輕鬆一些)。</para>
+ </listitem>
+
+ <listitem>
+ <para>先取得正式的標準,如 &posix; 的副本。
+ 在 <link xlink:href="&url.base;/projects/c99/index.html">FreeBSD
+ C99 &amp; POSIX 標準相容計劃</link> 網站上,可以得到相關鏈接。
+ 請將 FreeBSD 的行為與上述的標準進行比較,若所得結果與 C99 &amp; POSIX 標準不同的話,
+ 特別是那些細節地方的微小差異,請發一個關於它的 PR (問題報告)。
+ 如果可能,請指出如何修正它,並隨 PR 提交 patch 。
+ 如果您認為標準有問題,請向這些規格標準的相關團體,請求對其進行重新的考慮。</para>
+ </listitem>
+
+ <listitem>
+ <para>為這份列表提供更多建議!</para>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2>
+ <title>查閱整個 PR 資料庫</title>
+
+ <indexterm><primary>問題報告資料庫</primary></indexterm>
+
+ <para><link xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi">FreeBSD
+ PR 列表</link> 這裡會顯示目前所有 PR 的問題狀態,以及由
+ FreeBSD 使用者提交的改進建議。
+ PR 資料庫同時包括了開發人員和非開發人員的任務。
+ 查看那些尚未解決的 PR,並看看是否有您感興趣的任務。
+ 這其中可能有一些是非常簡單的問題,只需要看一看並確認 PR 是正確的。
+ 另外一些可能會非常複雜,或者完全未附任何修正。</para>
+
+ <para>首先看一看那些還沒有人接手的 PR。
+ 如果 PR 已經分配給了其它人,但看起來是您能夠處理的,
+ 您可以寄信給那個人,並詢問您是否可以提供幫助 &mdash;
+ 他們可能已經有可供測試的 patch ,或有一些可供討論的意見。</para>
+ </sect2>
+
+ <sect2>
+ <title>由 <quote>Ideas</quote> 中選一項</title>
+
+ <para><link xlink:href="&url.base;/projects/ideas/">&os; list of
+ projects and ideas for volunteers</link> 同樣地開放給有意願參與
+ &os; 計劃的人。
+ 這份清單將持續地更新,同時提供各個項目的資訊給所有人
+ (不論是否為程式設計人員)。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="contrib-how">
+ <title>如何提供幫助</title>
+
+ <para>基本上可以分為以下 5 種方式:</para>
+
+ <sect2 xml:id="contrib-general">
+ <title>錯誤報告和意見發表</title>
+
+ <para>通常,<emphasis>一般</emphasis>
+ 的技術想法和建議應該發到 &a.hackers;。
+ 同樣地,對於這些東西有興趣的人 (當然,
+ 他們同時還要能夠容忍 <emphasis>大量的</emphasis> 郵件!)
+ 可以考慮訂閱 &a.hackers;。
+ 請參閱 <link xlink:href="&url.books.handbook;/eresources.html#ERESOURCES-MAIL">FreeBSD
+ 使用手冊</link> 以了解關於這個郵遞論壇,
+ 以及其它郵遞論壇的詳細情況。</para>
+
+ <para>如果您發現了 bug 或者想要提交某些修改,
+ 請透過 &man.send-pr.1; 程式或使用
+ <link xlink:href="&url.base;/send-pr.html">網頁介面
+ 的回報</link> 來提交。請試著填寫 PR 的每個項目。
+ 一般來說,除非 patch 檔超過 65 KB,我們建議在 PR 中直接附上 patch 就可以了。
+ 若可直接套用 patch 到原始碼的話,那麼建議在 PR 的
+ Synopsis 欄位註明 <literal>[PATCH]</literal>。
+ 對了,在附上 patch 時,請 <emphasis>不要</emphasis>
+ 透過滑鼠的『複製、貼上』來進行,因為這樣做會把 Tab 變成空格,
+ 會導致 patch 就不能用了。如果 patch 超過 20KB,
+ 請考慮壓縮它並使用 &man.uuencode.1; 來進行編碼。</para>
+
+ <para>在寫完 PR 之後,您會收到一封確認郵件以及事件追蹤編號。
+ 請保留這個編號,因為事後可以用這編號發信到 &a.bugfollowup;
+ 來回覆、提供關於該事件的後續資料。您需要做的是將編號放到郵件的標題中,
+ 例如 <literal>"Re:
+ kern/3377"</literal>。
+ 若是同一問題的回覆方面,應該透過這種方式來進行。</para>
+
+ <para>如果您在一段時間 (超過 3 天甚至 1 週,這取決於您的郵件服務)之後仍然沒有收到確認信
+ 或者由於一些原因無法使用 &man.send-pr.1; 程式,
+ 則可以發信到 &a.bugs; 來請別人幫你代寄。</para>
+
+ <para>請參閱 <link xlink:href="&url.articles.problem-reports;/article.html">這篇文章</link>
+ 了解如何撰寫好的問題報告。</para>
+ </sect2>
+
+ <sect2>
+ <title>對於文件的修訂</title>
+
+ <indexterm><primary>提交文件</primary></indexterm>
+
+ <para>文件的修改方面,是由 &a.doc; 來審查。
+ 請參閱 <link xlink:href="&url.books.fdp-primer;/index.html">FreeBSD Documentation Project Primer</link>
+ 來獲得完整的教學細節。
+ 請按照 <xref linkend="contrib-general"/> 中介紹的方法使用 &man.send-pr.1;
+ 來提交新的文件,或者改善現有的文件 (哪怕是很小的改進也是歡迎的!)。</para>
+ </sect2>
+
+ <sect2>
+ <title>對於現有原始碼的修改</title>
+
+ <indexterm><primary>FreeBSD-CURRENT</primary></indexterm>
+
+ <para>在現有原始碼上進行修改或增加功能,在某種程度上是需要更多技巧的事,
+ 並且還跟您對於目前 FreeBSD 的開發現狀了解程度有關。
+ 有多種方式可以得到被稱作 <quote>FreeBSD-CURRENT</quote>
+ 的 FreeBSD 開發版本。
+ 請參閱 FreeBSD 使用手冊的 <link xlink:href=" &url.books.handbook;/current-stable.html">相關部份</link> ,來了解使用 FreeBSD-CURRENT 的詳情。</para>
+
+ <para>在舊的原始碼上進行修改,則通常可能原始碼已過時,
+ 或與新的版本差異太大而無法被重新整合到 FreeBSD 中。
+ 如果您有訂 &a.announce; 以及 &a.current; 的話,
+ 則可以透過它們來大致了解目前的開發狀態。</para>
+
+ <para>若您能夠儘量以最新的原始碼來進行您的修改,
+ 則下一步要做的事情就是產生您所修改的 diff 檔,
+ 並將它發給 FreeBSD 的維護人員。這項工作可以透過 &man.diff.1;
+ 命令來完成。</para>
+
+ <para>提交 patch 時,建議 &man.diff.1; 格式採用 unified diff (可以用 <command>diff
+ -u</command> 來產生)。不過,如果您修改了大量的原始碼,
+ 則使用 <command>diff -c</command> 來生成的 context diff
+ 的 diff 可能更容易閱讀,因而推薦使用。一般而言,大都是採用 <command>diff -ruN</command> 即可。</para>
+
+ <indexterm>
+ <primary><command>diff</command></primary>
+ </indexterm>
+
+ <para>例如:</para>
+
+ <para>
+ <screen>&prompt.user; <userinput>diff -c oldfile newfile</userinput></screen>
+
+ 或
+
+ <screen>&prompt.user; <userinput>diff -c -r olddir newdir</userinput></screen>
+
+ 將會對特定目錄,產生 context 的 diff 檔。</para>
+
+ <para>或者像是...
+ <screen>&prompt.user; <userinput>diff -u oldfile newfile</userinput></screen>
+ 或
+ <screen>&prompt.user; <userinput>diff -u -r olddir newdir</userinput></screen>
+
+ 將產生一樣的 diff ,但是格式為 unified 。</para>
+
+ <para>更多的細節部份,請參閱 &man.diff.1;。</para>
+
+ <para>一旦您使用 &man.diff.1; 來產生 diff 檔 (可以使用
+ &man.patch.1; 命令來測試一下),就可以提交它們,以便被 FreeBSD 收錄。
+ 透過使用 <xref linkend="contrib-general"/>
+ 中所介紹的 &man.send-pr.1; 程式就可以完成這項工作。
+ 請注意:不要只把 diff 檔發到 &a.hackers;,
+ 否則它們可能會被遺忘! 我們會非常感激您提交的修改
+ (這是一個義工計劃!); 因為我們都很忙,
+ 因此有時不一定能夠立即修正問題,但 PR 資料庫將一直保持著這些記錄,
+ 因此只要有人有了時間它們就能被改正了。
+ 如果您的問題報告中包括 patch ,不要忘了在標題加上
+ <literal>[PATCH]</literal> 來強調一下。</para>
+
+ <indexterm>
+ <primary><command>uuencode</command></primary>
+ </indexterm>
+
+ <para>如果您認為合適 (例如增、刪檔案或更改檔名),
+ 還可以考慮使用
+ <command>tar</command> 來將檔案打包,然後用 &man.uuencode.1;
+ 來編碼。此外,也可以用 &man.shar.1; 產生的方式。</para>
+
+ <para>如果您的修改可能存在潛在的爭議,例如,
+ 您不確定相關的版權問題,或者感覺需要經過更嚴格的復審才可以發佈它們,
+ 則應直接發給 &a.core;,而不是透過 &man.send-pr.1; 來發送。
+ &a.core; 這小組成員大多從事 FreeBSD 的日常工作。
+ 需要注意的是,這個小組也因此十分忙碌,
+ 因此只有在非常必要的時候,才應寫信給他們。</para>
+
+ <para>請參考 &man.intro.9; 和 &man.style.9; 以了解關於撰寫程式碼的風格偏好。
+ 若能在送出相關程式碼之前,先了解這些,那對大家來說將是極大的幫助。</para>
+ </sect2>
+
+ <sect2>
+ <title>新原始碼或重要的加值軟體包</title>
+
+ <para>如果您打算提供規模較大的原始碼,或者為 FreeBSD 增加重要的新功能,
+ 則可能必須將它們透過 uuencode 進行編碼,或傳到某個 Web 或
+ FTP 站點,以便更多的人能夠得到它。如果您沒有這樣的主機,
+ 請到相關的 FreeBSD 郵遞論壇提出,看看是否有人願意幫您放置它們。</para>
+
+ <para>對於大量的原始碼而言,關於版權的問題肯定會被提出。
+ FreeBSD 基本系統中能夠使用的版權聲明包括:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>BSD<indexterm><primary>BSD 版權聲明</primary></indexterm> 版權。我們傾向於使用這類授權的原始碼,
+ 因為它『不附加多餘的條件』,因而更能夠吸引商業企業使用。
+ FreeBSD 並不反對商業公司使用它的原始碼,相反,
+ 我們積極地鼓勵商業公司使用我們的原始碼,
+ 當然,如果它們若最終能把部分原始碼,重新捐贈給 FreeBSD 就更好了。</para>
+ </listitem>
+
+ <listitem>
+ <para>GNU General Public License,或簡稱 <quote>GPL</quote>。<indexterm><primary>GPL</primary><see>GNU General Public License</see></indexterm><indexterm><primary>GNU General Public License</primary></indexterm>
+ 我們並不很歡迎使用這樣授權的原始碼,
+ 因為商業公司使用它需要做更多的工作。不過,由於很多使用
+ GPL 授權的原始碼目前是無法避免的 (compiler, assembler, text formatter等等)
+ ,拒絕使用所有採用這樣授權的軟體是很不明智的。
+ 採用 GPL 授權的原始碼會被放到原始碼的一些特定的位置,例如
+ <filename>/sys/gnu</filename> 或
+ <filename>/usr/src/gnu</filename>,以便那些認為 GPL
+ 可能會造成麻煩的人能夠作出適當的判斷。</para>
+ </listitem>
+ </orderedlist>
+
+ <para>使用其它授權的原始碼在進入 FreeBSD 之前必須經過慎重的復審和考慮。
+ 採用包含嚴厲限制的商業授權的原始碼,一般來說會被拒絕,
+ 但我們鼓勵這些原始碼的作者,透過自己的管道來發布它們。</para>
+
+ <para>若要在您的成果上加入 <quote>BSD-based</quote> 版權的話,
+ 請把下列文字放到每份原始碼的最開始部分,
+ 並用適當的文字替換 <literal>%%</literal> 之間的文字。</para>
+
+ <programlisting>Copyright (c) %%proper_years_here%%
+ %%your_name_here%%, %%your_state%% %%your_zip%%.
+ 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 as
+ the first lines of this file unmodified.
+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 %%your_name_here%% ``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 %%your_name_here%% 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.
+
+ &#36;Id&#36;</programlisting>
+
+ <para>為了方便您的使用,在
+ <filename>/usr/share/examples/etc/bsd-style-copyright</filename>
+ 也可以找到此授權的副本。</para>
+ </sect2>
+
+ <sect2>
+ <title>贊助資金、硬體或 Internet mirror</title>
+
+ <para>我們非常願意接受各種形式的捐贈,以進一步拓展 FreeBSD 計劃
+ ,因為有您的支持,像我們這樣的義工努力才能夠有更大的成就!
+ 捐贈硬體也非常重要,因為這樣能夠幫助我們增加可支援的硬體種類,
+ 而我們中的很多人並沒有足夠的資金來購置這些硬體。</para>
+
+ <sect3 xml:id="donations">
+ <title>捐款</title>
+
+ <para>FreeBSD 基金會是一個非營利的、有課稅豁免權的基金會,
+ 之所以會建立這個基金會,是為了讓 FreeBSD 計劃能夠可長可久。
+ 因為該基金會屬 501(c)3 實體,一般而言捐款給基金會的話,可以免繳美國聯邦收入稅,
+ 以及科羅拉多州收入稅。通常對於有課稅豁免權的實體進行捐贈的話,
+ 可以折抵聯邦收入中應課稅部分的金額。</para>
+
+ <para>您可以把支票寄往:
+ <address>
+ The FreeBSD Foundation
+ <street>7321 Brockway Dr.</street>
+ <city>Boulder</city>, <state>CO</state> <postcode>80303</postcode>
+ <country>USA</country>
+ </address>
+ </para>
+
+ <para>FreeBSD 基金會現在可以透過 PayPal 從網上接受捐款。
+ 如果您想向基金會捐款,請參閱 <link xlink:href="http://www.freebsdfoundation.org">FreeBSD 基金會</link> 網站。</para>
+
+ <para>關於 FreeBSD 基金會的更多詳情,可以在 <link xlink:href="http://people.FreeBSD.org/~jdp/foundation/announcement.html">FreeBSD
+ 基金會 -- 介紹</link> 找到。要聯絡基金會,
+ 請發送電子郵件到
+ <email>bod@FreeBSDFoundation.org</email>。</para>
+ </sect3>
+
+ <sect3>
+ <title>捐贈硬體</title>
+ <indexterm><primary>捐贈</primary></indexterm>
+
+ <para>FreeBSD 計劃歡迎任何人捐贈可以使用的硬體。
+ 如果您有興趣捐贈硬體,請聯繫 <link xlink:href="&url.base;/donations/">捐贈聯絡人辦公室</link>。</para>
+ </sect3>
+
+ <sect3>
+ <title>成為 FreeBSD mirror 的網站</title>
+
+ <para>我們歡迎新的 FTP、WWW 或
+ <command>cvsup</command> mirror 站。如果您希望成為這樣的 mirror 站,
+ 請參閱 <link xlink:href="&url.articles.hubs;/index.html">如何架設 FreeBSD mirror</link>
+ 一文,以了解進一步的情況。</para>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <index/>
+</article>
diff --git a/zh_TW.UTF-8/articles/cvs-freebsd/Makefile b/zh_TW.UTF-8/articles/cvs-freebsd/Makefile
new file mode 100644
index 0000000000..f7f1f12588
--- /dev/null
+++ b/zh_TW.UTF-8/articles/cvs-freebsd/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+#
+# Article: Setting up a CVS repository - the FreeBSD way
+#
+# Build the Traditional Chinese Version
+
+MAINTAINER= stijn@win.tue.nl
+
+DOC?= article
+
+FORMATS?= html
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/cvs-freebsd/article.xml b/zh_TW.UTF-8/articles/cvs-freebsd/article.xml
new file mode 100644
index 0000000000..8f589b7c26
--- /dev/null
+++ b/zh_TW.UTF-8/articles/cvs-freebsd/article.xml
@@ -0,0 +1,570 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!-- $FreeBSD$ -->
+<!-- The FreeBSD Documentation Project -->
+<!-- Setting up a CVS repository - the FreeBSD way -->
+<!-- Translate into Chinese by jose@jose.idv.tw -->
+<!-- English Version: 1.15 -->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>建立 CVS 儲存庫(repository) - 使用 FreeBSD 的方式</title>
+
+
+ <author><personname><firstname>Stijn</firstname><surname>Hoop</surname></personname><affiliation>
+ <address><email>stijn@win.tue.nl</email></address>
+ </affiliation></author>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <copyright>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder role="mailto:stijn@win.tue.nl">Stijn Hoop</holder>
+ </copyright>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>這份文件描述了使用和 FreeBSD 專案相同的命令稿來建立 CVS 儲存庫的步驟
+ 。這和標準 CVS 建立的儲存庫相較之下有許多優點,包含了更多對於原始碼樹的
+ granular access 控制,以及為每一次的提交產生易讀的電子郵件。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="introduction">
+ <title>簡介</title>
+
+ <para>大多數的開放原始碼軟體專案都使用 <application>CVS</application> 作為
+ 他們的原始碼控制系統。當 <application>CVS</application> 有這樣的優點存在
+ 時,它也有部份的瑕疵和缺點。其中之一的原因是和其他的開發者分享原始碼樹能
+ 夠快速地導致系統管理的惡夢,特別是如果其中一人希望保護部份的原始碼樹免受
+ 於一般的存取。</para>
+
+ <para>FreeBSD 是其中一個使用 <application>CVS</application> 的專案,同時也
+ 是基於它的開發者遍佈於全世界。他們撰寫了一些命令稿使得管理儲存庫變得更加
+ 容易。最近這些命令稿由 &a.joe; 重新整理過且更標準化,使得在其他的專案上再
+ 次使用這些命令稿會更加容易。本文件將描述使用這些新的命令稿的方法。</para>
+
+ <para>為了使本文件中的訊息有用,你需要熟悉 <application>CVS</application>
+ 基本的操作方式。</para>
+ </sect1>
+
+ <sect1 xml:id="first-setup">
+ <title>基本設定</title>
+
+ <warning>
+ <para>最好的方式是在一個全新的儲存庫中執行這些步驟,並確定你了解所有的後
+ 果。同時,請確定你有最新且可讀的資料備份!</para>
+ </warning>
+
+ <sect2>
+ <title>初始化儲存庫</title>
+
+ <para>首先要做的是建立一個新的儲存庫,執行下列命令告訴
+ <application>CVS</application> 建立並初始化:</para>
+
+ <screen>&prompt.user; <userinput>cvs -d path-to-repository init</userinput></screen>
+
+ <para>這命令告訴 <application>CVS</application> 建立
+ <filename>CVSROOT</filename> 的目錄,這個目錄裡放置了所有的組態檔。</para>
+ </sect2>
+
+ <sect2>
+ <title>設定儲存庫的群組</title>
+
+ <para>現在我們將建立一個擁有該儲存庫的群組,所有的開發者必須加入這個群組
+ ,這樣他們才能夠存取該儲存庫。我們假設群組名稱是以 FreeBSD 內定的
+ <literal>ncvs</literal>。</para>
+
+ <screen>&prompt.root; <userinput>pw groupadd ncvs</userinput></screen>
+
+ <para>接者你需要使用 &man.chown.8; 將目錄所有者指定給剛剛新增的群組:</para>
+
+ <screen>&prompt.root; <userinput>chown -R :ncvs path-to-your-repository</userinput></screen>
+
+ <para>如此一來沒有適當的群組許可將沒有其他人可以寫入該儲存庫。</para>
+ </sect2>
+
+ <sect2>
+ <title>取回原始檔案</title>
+
+ <para>現在你需要從 FreeBSD 儲存庫中取回 <filename>CVSROOT</filename> 目錄,
+ 從 FreeBSD 匿名的 CVS 映射站來取回會是最簡單的方法。請查閱 <link xlink:href="&url.books.handbook;/anoncvs.html">在 handbook 中的相關章節</link>來
+ 獲得更多資訊。我們假設取回的檔案存放在相同目錄下的
+ <filename>CVSROOT-freebsd</filename> 目錄中。</para>
+ </sect2>
+
+ <sect2>
+ <title>複製 FreeBSD 的命令稿</title>
+
+ <para>接下來我們要複製 FreeBSD <filename>CVSROOT</filename> 裡的檔案到你
+ 的儲存庫中。如果你是孰悉於 <application>CVS</application>,你也許會想你
+ 可以直接匯入這些命令稿,試圖更容易的同時和更新的版本同步;不過,事實是
+ <application>CVS</application> 在這個部份有缺點:當匯入檔案到
+ <filename>CVSROOT</filename> 時,它並不會更新組態檔。為了要認出這些檔案
+ ,你還需要在匯入它們後一一重新提交,這就失去了
+ <literal>cvs import</literal> 的價值。因此,建議的方法是僅複製這些命令
+ 稿過去。</para>
+
+ <para>若上述內容對你沒有意義是不重要的&mdash;因為最後的結果都是一樣的。
+ 首先匯出你的 <filename>CVSROOT</filename>,然後複製剛剛取回的 FreeBSD
+ 檔案到本地的目錄中(尚未變動過):</para>
+
+ <screen>&prompt.user; <userinput>cvs -d path-to-your-repository checkout CVSROOT</userinput>
+&prompt.user; <userinput>cd CVSROOT</userinput>
+&prompt.user; <userinput>cp ../CVSROOT-freebsd/* .</userinput>
+&prompt.user; <userinput>cvs add *</userinput></screen>
+
+ <para>注意:你很可能會得到一段關於某些目錄沒有被複製的警告,這是正常的,
+ 你並不需要用到這些目錄。</para>
+ </sect2>
+
+ <sect2>
+ <title>命令稿說明</title>
+
+ <para>現在你的工作目錄中有了完整 FreeBSD 專案在它們的儲存庫中使用的命令稿
+ 的複本,以下是每個檔案簡單的介紹。</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><filename>access</filename> - 此檔案在預設的安裝中沒有被用到。
+ 這是使用在<link linkend="freebsdspecific">FreeBSD 的特殊設定</link>中
+ ,用來控制儲存庫的存取。如果你不希望使用這個設定的話你可以刪除這個檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>avail</filename> - 此檔案控制儲存庫的存取。在此檔案中
+ 你可以指定允許存取儲存庫的群組,也可以針對目錄或檔案來拒絕提交。你應該
+ 調整為在你的儲存庫中將包含的群組和目錄。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cfg.pm</filename> - 此檔案說明了設定內容,並提供預設的設定。
+ 你<emphasis>不</emphasis>該修改此檔案,而該將修改的設定放到
+ <filename>cfg_local.pm</filename>。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cfg_local.pm</filename> - 此檔案包含所有的系統設定值
+ 。你應該設定所有列在此的設定,例如提交的郵件要寄到哪、在哪些主機上
+ 的使用者可以提交等等。更多的相關資訊在稍後會提到。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>checkoutlist</filename> - 此檔案列出所有在
+ <application>CVS</application> 控制下此目錄中的檔案,除了標準在
+ <literal>cvs init</literal> 建立出的檔案。你可以刪除某些不需要的
+ FreeBSD 特殊的檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commit_prep.pl</filename> - 此命令稿執行各種提交前的檢查,
+ 基於你是否在 <filename>cfg_local.pm</filename> 中啟用。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commitcheck</filename> - 此命令稿會直接影響
+ <application>CVS</application>。首先它會使用
+ <filename>cvs_acls.pl</filename> 來檢查提交者是否可以存取指定的原始碼樹,
+ 然後執行 <filename>commit_prep.pl</filename> 來確認各種提交前的檢查。
+ 如果一切正常,<application>CVS</application> 將允許此次提交繼續執行。
+ 你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>commitinfo</filename> - 此檔案是
+ <application>CVS</application> 用來定義在提交前所要執行的程式&mdash;在
+ 此例中是 <filename>commitcheck</filename>。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>config</filename> - 儲存庫的設定選項。你可以修改為你
+ 想要的,但大多數的管理者可能會保留預設值。更多關於可以在此設定的選項
+ 資訊可以查閱 <application>CVS</application> 手冊。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvs_acls.pl</filename> - 此命令稿定義提交者的身分,以
+ 及他/她是否允許存取原始碼樹,它是基於 <filename>avail</filename> 中
+ 的設定。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvsignore</filename> - 此檔案列出哪些檔案
+ <application>CVS</application> 不用處理到儲存庫中,你可以修改成你想
+ 要的。更多關於可以此檔案的說明可以查閱 <application>CVS</application>
+ 手冊。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>cvswrappers</filename> - 此檔案是
+ <application>CVS</application> 用來啟用或停用關鍵字展開,或者是否檔
+ 案該被視為二進位檔。你可以修改成你想要的。更多關於可以此檔案的說明
+ 可以查閱 <application>CVS</application> 手冊。注意 <literal>-t</literal>
+ 和 <literal>-f</literal> 選項在 <application>CVS</application>
+ client/server 並不能夠正確的運作。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>edithook</filename> - 此檔案已經沒有在使用了,留著只
+ 是為了某些有意義的原因。你可以安全地刪除此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>editinfo</filename> - <application>CVS</application>
+ 使用這個檔案來強迫你使用特定的編輯器。FreeBSD 沒有使用這個功能,因
+ 為輸入日誌訊息已經由 <filename>verifymsg</filename> 和
+ <filename>logcheck</filename> 來完成。這是因為
+ <filename>editinfo</filename> 功能在從遠端提交或是使用
+ <literal>-m</literal> 或 <literal>-F</literal> 選項時不會執行。你不
+ 該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>exclude</filename> - 此檔案列出被
+ <filename>commit_prep.pl</filename> 定義不能包含修正版標頭的檔案。
+ 在 FreeBSD 版本的設定中,所有在修正版控制下的檔案需有一個修正版標頭
+ ,(像是 &dollar;FreeBSD&dollar;)。在此檔案中所有符合一行一個的檔
+ 案名稱將不會被檢查。你可以在此檔案中為不需要修正版標頭的檔案新增一
+ 個正規運算式。為了安裝這些命令稿,最好的方法是排除
+ <filename>CVSROOT/</filename> 會受到標頭的檢查。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>log_accum.pl</filename> - 此命令稿會處理由
+ <filename>logcheck</filename> 所提供的日誌訊息,並且將之為備份目的
+ 附加於儲存庫中的記錄檔案。同時也執行要將郵件寄到你提供的信箱中的程
+ 式(在 <filename>cfg_local.pm</filename> 中)。它和
+ <application>CVS</application> 之間是由 <filename>loginfo</filename>
+ 負責溝通。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>logcheck</filename> - 此檔案分析提交者提供的日誌訊息
+ ,並試圖對其作清理動作。它和 <application>CVS</application> 之間是
+ 由 <filename>verifymsg</filename> 負責溝通。你不該更動此檔案。</para>
+
+ <note><para>此命令稿依附於本地的 FreeBSD <application>CVS</application>
+ 處理:FreeBSD 版本在此命令稿修改過後才讀取日誌訊息;標準的
+ <application>CVS</application> 版本雖然能夠檢查語法上是否正確,但並
+ 不會清理日誌訊息。<application>CVS</application> 1.11.2 可以透過在
+ <filename>config</filename> 設定 <literal>RereadLogAfterVerify=always</literal>
+ 來和 FreeBSD 版本有相同的作用。</para></note>
+ </listitem>
+
+ <listitem>
+ <para><filename>loginfo</filename> - 此檔案是
+ <application>CVS</application> 用來控制日誌訊息要寄到哪裡,而
+ <filename>log_accum.pl</filename> 負責處理。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>modules</filename> - 此檔案保留了
+ <application>CVS</application> 原始的意義。你應該刪除新增的 FreeBSD
+ 模組,並修改為你想要的內容。更多關於可以此檔案的說明可以查閱
+ <application>CVS</application> 手冊。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>notify</filename> - 此檔案為
+ <application>CVS</application> 用來控制監看某個檔案。在 FreeBSD 的
+ 儲存庫中沒有使用到此檔案,你可以修改成你想要的。更多關於可以此檔案
+ 的說明可以查閱 <application>CVS</application> 手冊。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>options</filename> - 此檔案僅限使用於 FreeBSD 和 Debian
+ 的 <application>CVS</application> 版本。它包含了需要在修正版標頭中
+ 展開的關鍵字。你可以修改為符合你指定在 <filename>cfg_local.pm</filename>
+ 的關鍵字。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>rcsinfo</filename> - 此檔案定義提交時儲存庫所要使用的
+ 日誌訊息樣式範本,如 <filename>rcstemplate</filename>。FreeBSD 預設
+ 為所有的儲存庫使用同一個樣式範本,你可以加入其他你想要的。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>rcstemplate</filename> - 此檔案是提交者在提交時會看到
+ 的日誌訊息樣式範本,你應該修改為你定義在 <filename>cfg_local.pm</filename>
+ 的各種參數。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>tagcheck</filename> - 此檔案控制在儲存庫中貼上標籤的
+ 存取。標準的 FreeBSD 版本拒絕名為 RELENG* 的標籤,因為這是 release
+ engineering 的工作。你可以根據需要來修改此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>taginfo</filename> - 此檔案控制執行在儲存庫中貼上標籤
+ 的存取的命令稿,如 <filename>tagcheck</filename>。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>unwrap</filename> - 此命令稿可以用來在匯出時自動<quote>解開</quote>
+ 二進位檔(請見 <filename>cvswrappers</filename>)。現在 FreeBSD 並
+ 沒有使用此設定,因為此功能在遠端提交時並不是執行的非常完善。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>verifymsg</filename> - 此檔案用來執行和日誌訊息相關的
+ 命令稿,如 <filename>logcheck</filename>。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>wrap</filename> - 此命令稿可以用來在提交時自動<quote>包裹</quote>
+ 二進位檔(請見 <filename>cvswrappers</filename>)。現在 FreeBSD 並
+ 沒有使用此設定,因為此功能在遠端提交時並不是執行的非常完善。你不該更動此檔案。</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>自訂命令稿</title>
+
+ <para>接下來的步驟要設定這些命令稿使得它們可以在你的環境中運作。你應該檢
+ 查所有在目錄中的檔案,並修改為符合你的設定。尤其,你會想要修改下列的檔案:</para>
+
+ <procedure>
+ <step>
+ <para>如果你不希望使用<link linkend="freebsdspecific">FreeBSD 的特殊設定</link>,
+ 你可以安全地刪除 <filename>access</filename>:</para>
+
+ <screen>&prompt.user; <userinput>cvs rm -f access</userinput></screen>
+ </step>
+
+ <step>
+ <para>編輯 <filename>avail</filename> 來包含你想控制存取的各種儲存庫
+ 目錄,請確定你有保留 <literal>avail||CVSROOT</literal> 這一行,否則
+ 你將會在下一步把你自己鎖在外面。</para>
+
+ <para>另外你可以在此檔案中新增開發者的群組,FreeBSD 預設使用
+ <filename>access</filename> 來列出所有的開發者,但你可以使用任何你
+ 想要用的檔案。如果你想的話也可以新增群組(請使用指定在
+ <filename>cvs_acls.pl</filename> 上層裡的語法)。</para>
+ </step>
+
+ <step>
+ <para>編輯 <filename>cfg_local.pm</filename> 來包含你需要的選項。尤其
+ 你應該檢視一下下列的設定項目:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>%TEMPLATE_HEADERS</literal> - 這是用來取得日誌訊
+ 息內容的程序,並加入將呈現的郵件項目和提供非空值的訊息。你可
+ 以刪除 <literal>PR</literal> 和 <literal>MFC after</literal>
+ 敘述,當然也可以加入你想要的。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$MAIL_BRANCH_HDR</literal> - 如果你想要在每一封
+ 提交的郵件中加入描述是在哪一個分支中提交的標頭,那麼請定義為
+ 符合你的設定。如果你不想使用這樣的標頭,那麼請設定為空值。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@COMMIT_HOSTS</literal> - 定義使用者能夠提交的主機。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$MAILADDRS</literal> - 設定應該收到提交郵件的郵
+ 件位址。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@LOG_FILE_MAP</literal> - 以你所需要的來修改這個
+ 陣列,每個設定值應該符合被提交的目錄,而提交的日誌訊息會以
+ <filename>commitlogs</filename> 的名稱儲存在每個被設定的目錄下。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>$COMMITCHECK_EXTRA</literal> - 如果你不想使用
+ <link linkend="freebsdspecific">FreeBSD 特殊的存取控制</link>
+ 功能,你可以在此檔案中刪除對 <literal>$COMMITCHECK_EXTRA</literal>
+ 的定義。</para>
+ </listitem>
+ </itemizedlist>
+
+ <note><para>修改 <literal>$IDHEADER</literal> 的功能只有在 FreeBSD
+ 平台上可以運作,它是相依在 FreeBSD 的特殊 <application>CVS</application>
+ 設定上。</para></note>
+
+ <para>你可以檢查 <filename>cfg.pm</filename> 是否有其他的參數可以修改
+ ,但是修改最好是有原因的。</para>
+ </step>
+
+ <step>
+ <para>刪除 <filename>exclude</filename> 中關於FreeBSD 的特殊設定的敘
+ 述(如以 <literal>^ports/</literal> 為開頭的每一行等)。此外,註解
+ 掉以 <literal>^CVSROOT/</literal> 為開頭的行列,然後新增一行只有
+ <literal>^CVSROOT/</literal>。等到關鍵字展開的命令稿安裝好後,你可
+ 以在 <filename>CVSROOT</filename> 目錄中的檔案裡加上標頭,然後再恢
+ 復剛剛註解的行列,但在你還沒有提交前則只保持這樣。</para>
+ </step>
+
+ <step>
+ <para>編輯 <filename>modules</filename>,並刪除所有 FreeBSD 的群組。
+ 加入你需要的模組。</para>
+ </step>
+
+ <step>
+ <note><para>此步驟只有在你於 <filename>cfg_local.pm</filename> 中指定
+ 了 <literal>$IDHEADER</literal> 才有必要設定(只有在 FreeBSD 的特殊
+ <application>CVS</application> 設定上才能夠執行)。</para></note>
+
+ <para>編輯 <filename>options</filename> 以符合你在
+ <filename>cfg_local.pm</filename> 中設定的標籤名稱。並在所有的檔案
+ 中搜尋 <literal>FreeBSD</literal> 並替換為你設定的標籤名稱。</para>
+ </step>
+
+ <step>
+ <para>修改 <filename>rcstemplate</filename> 為和在
+ <filename>cfg_local.pm</filename> 中相同的設定。</para>
+ </step>
+
+ <step>
+ <para>選擇性的刪除在 <filename>tagcheck</filename> 中針對 FreeBSD 檢
+ 查的設定。你可以僅僅在檔案的最上層加上 <literal>exit 0</literal> 來
+ 取消所有標籤的檢查。</para>
+ </step>
+
+ <step>
+ <para>在你完成前的最後一件事是確認 commitlogs 可以正確儲存。預設會儲
+ 存在儲存庫中的 <filename>commitlogs</filename> 子目錄中,而這個目錄
+ 需要先建立:</para>
+
+ <screen>&prompt.user; <userinput>mkdir commitlogs</userinput>
+&prompt.user; <userinput>cvs add commitlogs</userinput></screen>
+ </step>
+ </procedure>
+
+ <para>現在,在細心的檢視過後,你可以提交你的修改了。確定你先前有在
+ <filename>avail</filename> 中允許你自己存取 <filename>CVSROOT</filename>
+ 目錄,因為如果沒有這樣做的話你會把你自己鎖在外面。完整確認過後請執行下
+ 列命令:</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -m '- Initial FreeBSD scripts commit'</userinput></screen>
+ </sect2>
+
+ <sect2>
+ <title>測試設定</title>
+
+ <para>你已經準備好做基本的測試了:強制提交 <filename>avail</filename>
+ 以確認每件事都如預期的運作。</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -f -m 'Forced commit to test the new CVSROOT scripts' avail</userinput></screen>
+
+ <para>如果一切正常,那麼恭喜了!你現在已經為你的儲存庫建立好 FreeBSD 的命
+ 令稿了。如果 <application>CVS</application> 仍然有警告什麼,回頭檢視上
+ 述的步驟是否有正確的執行。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="freebsdspecific">
+ <title>FreeBSD 的特殊設定</title>
+
+ <para>FreeBSD 專案自己使用一個有點不同的設定,那就是同時也使用 FreeBSD
+ <filename>CVSROOT</filename> 中的 <filename>freebsd</filename> 子目錄。因
+ 為大量的提交者必須在相同的群組中,因此專案寫了一個簡單的 wrapper 來確認提
+ 交者可以正確的提交,並設定儲存庫的群組名稱。</para>
+
+ <para>如果你的儲存庫也需要這樣的功能,那麼下面就會介紹如何建立,不過首先要
+ 先來看一段複雜的概述。</para>
+
+ <sect2>
+ <title>FreeBSD 設定中使用的檔案</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><filename>access</filename> - 此檔案用來控制儲存庫的存取。你
+ 應該編輯並加入所有在專案中的成員。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/commitmail.pl</filename> - 此檔案已經沒有在
+ 使用了,留著只是為了某些有意義的原因。你不該更動此檔案。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/cvswrap.c</filename> - 此 CVS wrapper 原始
+ 碼是用來建立檢查所有存取的工作。更多的訊息在稍後會提出。你應該編
+ 輯 <literal>ACCESS</literal> 和 <literal>REALCVS</literal> 的路徑
+ 以符合你的設定。</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>freebsd/mailsend.c</filename> - 此檔案是 FreeBSD 設
+ 定 mailing lists 需要的,你不該更動此檔案。</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>步驟</title>
+
+ <procedure>
+ <step>
+ <para>只有加入你的使用者名稱到 <filename>access</filename> 中。</para>
+ </step>
+
+ <step>
+ <para>編輯 <filename>cvswrap.c</filename> 的路徑以符合你的設定,定義
+ 在大寫的 <literal>ACCESS</literal> 中。同時如果預設值不符合你的情況
+ 的話也應該修改本地實際的 <command>cvs</command> 程式所在位置。原始
+ 的 <filename>cvswrap.c</filename> 希望替代伺服端的 CVS 程式,例如可
+ 能會是 <filename>/usr/bin/ncvs</filename>。</para>
+
+ <para>我的 <filename>cvswrap.c</filename> 是這樣:</para>
+
+ <programlisting>#define ACCESS "/local/cvsroot/CVSROOT/access"
+#define REALCVS "/usr/bin/ncvs"</programlisting>
+ </step>
+
+ <step>
+ <para>接下來是建立 wrapper 來確認你在提交時是在正確的群組中。
+ 在你的 <filename>CVSROOT</filename> 中的
+ <filename>cvswrap.c</filename> 要能夠使用。</para>
+
+ <para>在你完成編輯並加入正確的路徑後我們要來編譯原始碼:</para>
+
+ <screen>&prompt.user; <userinput>cc -o cvs cvswrap.c</userinput></screen>
+
+ <para>然後進行需要設定(此步驟需要 root 權限):</para>
+
+ <screen>&prompt.root; <userinput>mv /usr/bin/cvs /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>mv cvs /usr/bin/cvs</userinput>
+&prompt.root; <userinput>chown root:ncvs /usr/bin/cvs /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>chmod o-rx /usr/bin/ncvs</userinput>
+&prompt.root; <userinput>chmod u-w,g+s /usr/bin/cvs</userinput></screen>
+
+ <para>這會將 wrapper 安裝成預設的 <command>cvs</command> 程式,請確定
+ 任何要使用儲存庫的人應該有正確的存取權限。</para>
+ </step>
+
+ <step>
+ <para>現在你可以刪除所有在儲存庫群組中的使用者,所有的存取控制會經由
+ wrapper 完成,同時 wrapper 會設定存取的正確群組。</para>
+ </step>
+ </procedure>
+ </sect2>
+
+ <sect2>
+ <title>測試設定</title>
+
+ <para>你的 wrapper 現在應該已經安裝好了,你當然也可以強制提交
+ <filename>access</filename> 來測試是否正常:</para>
+
+ <screen>&prompt.user; <userinput>cvs commit -f -m 'Forced commit to test the new CVSROOT scripts' access</userinput></screen>
+
+ <para>同樣地,如果有錯誤,檢查是否上述所有步驟都有正確的執行。</para>
+ </sect2>
+ </sect1>
+</article>
diff --git a/zh_TW.UTF-8/articles/freebsd-questions/Makefile b/zh_TW.UTF-8/articles/freebsd-questions/Makefile
new file mode 100644
index 0000000000..e0524136c2
--- /dev/null
+++ b/zh_TW.UTF-8/articles/freebsd-questions/Makefile
@@ -0,0 +1,22 @@
+#
+# $FreeBSD$
+# Original revision: 1.6
+#
+# Article: How to get best results from the FreeBSD-questions mailing list
+
+MAINTAINER=chinsan.tw@gmail.com
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/freebsd-questions/article.xml b/zh_TW.UTF-8/articles/freebsd-questions/article.xml
new file mode 100644
index 0000000000..ad017406e0
--- /dev/null
+++ b/zh_TW.UTF-8/articles/freebsd-questions/article.xml
@@ -0,0 +1,610 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ Original revision: 1.24
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>如何在 FreeBSD-questions mailing list 上得到正解</title>
+
+
+ <author><personname><firstname>Greg</firstname><surname>Lehey</surname></personname><affiliation>
+ <address><email>grog@FreeBSD.org</email></address>
+ </affiliation></author>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.microsoft;
+ &tm-attrib.netscape;
+ &tm-attrib.opengroup;
+ &tm-attrib.qualcomm;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>本文主要是給準備寫信到 FreeBSD-questions mailing list 的人提供一些參考。
+ 我們會給你一些發問的技巧與建議,以便讓你的答案得到更有用的答覆。</para>
+
+ <para>本文會定期發到 FreeBSD-questions mailing list 上。</para>
+ </abstract>
+ </info>
+
+ <sect1>
+ <title xml:id="Introduction">簡介</title>
+
+ <para><literal>FreeBSD-questions</literal> is a mailing list maintained by
+ the FreeBSD project to help people who have questions about the normal
+ use of FreeBSD. Another group, <literal>FreeBSD-hackers</literal>,
+ discusses more advanced questions such as future development
+ work.</para>
+
+ <note>
+ <para>The term <quote>hacker</quote> has nothing to do with breaking
+ into other people's computers. The correct term for the latter
+ activity is <quote>cracker</quote>, but the popular press has not found
+ out yet. The FreeBSD hackers disapprove strongly of cracking
+ security, and have nothing to do with it. For a longer description of
+ hackers, see Eric Raymond's <link xlink:href="http://www.catb.org/~esr/faqs/hacker-howto.html">How To Become
+ A Hacker</link></para>
+ </note>
+
+ <para>This is a regular posting aimed to help both those seeking advice
+ from FreeBSD-questions (the <quote>newcomers</quote>), and also those
+ who answer the questions (the <quote>hackers</quote>).</para>
+
+ <para>Inevitably there is some friction, which stems from the different
+ viewpoints of the two groups. The newcomers accuse the hackers of being
+ arrogant, stuck-up, and unhelpful, while the hackers accuse the
+ newcomers of being stupid, unable to read plain English, and expecting
+ everything to be handed to them on a silver platter. Of course, there is
+ an element of truth in both these claims, but for the most part these
+ viewpoints come from a sense of frustration.</para>
+
+ <para>In this document, I would like to do something to relieve this
+ frustration and help everybody get better results from
+ FreeBSD-questions. In the following section, I recommend how to submit
+ a question; after that, we will look at how to answer one.</para>
+ </sect1>
+
+ <sect1>
+ <title xml:id="subscribe">How to subscribe to FreeBSD-questions</title>
+
+ <para>FreeBSD-questions is a mailing list, so you need mail access. Point
+ your WWW browser to the <link xlink:href="&a.questions.url;">information page of the FreeBSD-questions mailing list</link>.
+ In the section titled <quote>Subscribing to freebsd-questions</quote> fill
+ in the <quote>Your email address</quote> field; the other fields are optional.
+ </para>
+
+ <note>
+ <para>The password fields in the subscription form provide only mild
+ security, but should prevent others from messing with your
+ subscription. <emphasis>Do not use a valuable password</emphasis> as
+ it will occasionally be emailed back to you in cleartext.</para>
+ </note>
+
+ <para>You will receive a confirmation message from
+ <application>mailman</application>; follow the included instructions
+ to complete your subscription.</para>
+
+ <para>Finally, when you get the <quote>Welcome</quote> message from
+ <application>mailman</application> telling you the details of the list
+ and subscription area password, <emphasis>please save it</emphasis>.
+ If you ever should want to leave the list, you will need the information
+ there. See the next section for more details.</para>
+ </sect1>
+
+ <sect1>
+ <title xml:id="unsubscribe">How to unsubscribe from FreeBSD-questions</title>
+
+ <para>When you subscribed to FreeBSD-questions, you got a welcome message
+ from <application>mailman</application>. In this message, amongst
+ other things, it told you how to unsubscribe. Here is a typical
+ message:</para>
+
+ <literallayout class="monospaced">Welcome to the freebsd-questions@freebsd.org mailing list!
+
+To post to this list, send your email to:
+
+ freebsd-questions@freebsd.org
+
+General information about the mailing list is at:
+
+ http://lists.freebsd.org/mailman/listinfo/freebsd-questions
+
+If you ever want to unsubscribe or change your options (e.g., switch to
+or from digest mode, change your password, etc.), visit your
+subscription page at:
+
+http://lists.freebsd.org/mailman/options/freebsd-questions/grog%40lemsi.de
+
+You can also make such adjustments via email by sending a message to:
+
+ freebsd-questions-request@freebsd.org
+
+with the word `help' in the subject or body (don't include the
+quotes), and you will get back a message with instructions.
+
+You must know your password to change your options (including changing
+the password, itself) or to unsubscribe. It is:
+
+ 12345
+
+Normally, Mailman will remind you of your freebsd.org mailing list
+passwords once every month, although you can disable this if you
+prefer. This reminder will also include instructions on how to
+unsubscribe or change your account options. There is also a button on
+your options page that will email your current password to you.</literallayout>
+
+ <para>From the URL specified in your <quote>Welcome</quote> message you
+ may visit the <quote>Account management page</quote> and enter a request
+ to <quote>Unsubscribe</quote> you from FreeBSD-questions mailing
+ list.</para>
+
+ <para>A confirmation message will be sent to you from
+ <application>mailman</application>; follow the included instructions
+ to finish unsubscribing.</para>
+
+ <para>If you have done this, and you still can not figure out what
+ is going on, send a message to
+ <email>freebsd-questions-request@FreeBSD.org</email>, and they will
+ sort things out for you. <emphasis>Do not</emphasis> send a message to
+ FreeBSD-questions: they can not help you.</para>
+ </sect1>
+
+ <sect1>
+ <title xml:id="askwho">Should I ask <literal>-questions</literal> or
+ <literal>-hackers</literal>?</title>
+
+ <para>Two mailing lists handle general questions about FreeBSD,
+ <literal>FreeBSD-questions</literal> and
+ <literal>FreeBSD-hackers</literal>. In some cases, it is not really
+ clear which group you should ask. The following criteria should help
+ for 99% of all questions, however:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>If the question is of a general nature, ask
+ <literal>FreeBSD-questions</literal>. Examples might be questions
+ about installing FreeBSD or the use of a particular &unix;
+ utility.</para>
+ </listitem>
+
+ <listitem>
+ <para>If you think the question relates to a bug, but you are not sure,
+ or you do not know how to look for it, send the message to
+ <literal>FreeBSD-questions</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the question relates to a bug, and you are
+ <emphasis>sure</emphasis> that it is a bug (for example, you can
+ pinpoint the place in the code where it happens, and you maybe have
+ a fix), then send the message to
+ <literal>FreeBSD-hackers</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the question relates to enhancements to FreeBSD, and you
+ can make suggestions about how to implement them, then send the
+ message to <literal>FreeBSD-hackers</literal>.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>There are also a number of other specialized mailing lists, for
+ example <literal>FreeBSD-isp</literal>, which caters to the interests of
+ ISPs (Internet Service Providers) who run FreeBSD. If you happen to be
+ an ISP, this does not mean you should automatically send your questions
+ to <literal>FreeBSD-isp</literal>. The criteria above still apply, and
+ it is in your interest to stick to them, since you are more likely to get
+ good results that way.</para>
+ </sect1>
+
+ <sect1>
+ <title xml:id="before">Before submitting a question</title>
+
+ <para>You can (and should) do some things yourself before asking a question
+ on one of the mailing lists:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Try solving the problem on your own. If you post a question which
+ shows that you have tried to solve the problem, your question will
+ generally attract more positive attention from people reading it.
+ Trying to solve the problem yourself will also enhance your understanding
+ of FreeBSD, and will eventually let you use your knowledge to help others
+ by answering questions posted to the mailing lists.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Read the manual pages, and the FreeBSD documentation (either
+ installed in <filename>/usr/doc</filename> or accessible via WWW at
+ <uri xlink:href="http://www.FreeBSD.org">http://www.FreeBSD.org</uri>), especially the
+ <link xlink:href="&url.books.handbook;/index.html">handbook</link>
+ and the <link xlink:href="&url.books.faq;/index.html">FAQ</link>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Browse and/or search the archives for the mailing list, to see if your
+ question or a similar one has been asked (and possibly answered) on the
+ list. You can browse and/or search the mailing list archives
+ at <uri xlink:href="http://www.FreeBSD.org/mail">http://www.FreeBSD.org/mail</uri>
+ and <uri xlink:href="http://www.FreeBSD.org/search/search.html#mailinglists">http://www.FreeBSD.org/search/search.html#mailinglists</uri>
+ respectively. This can be done at other WWW sites as well, for example
+ at <uri xlink:href="http://marc.theaimsgroup.com">http://marc.theaimsgroup.com</uri>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Use a search engine such as <link xlink:href="http://www.google.com">Google</link>
+ or <link xlink:href="http://www.yahoo.com">Yahoo</link> to find answers to your question.
+ Google even has a <link xlink:href="http://www.google.com/bsd">BSD-specific search interface</link>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1>
+ <title xml:id="submit">How to submit a question</title>
+
+ <para>When submitting a question to FreeBSD-questions, consider the
+ following points:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Remember that nobody gets paid for answering a FreeBSD
+ question. They do it of their own free will. You can influence this
+ free will positively by submitting a well-formulated question
+ supplying as much relevant information as possible. You can
+ influence this free will negatively by submitting an incomplete,
+ illegible, or rude question. It is perfectly possible to send a
+ message to FreeBSD-questions and not get an answer even if you
+ follow these rules. It is much more possible to not get an answer if
+ you do not. In the rest of this document, we will look at how to get
+ the most out of your question to FreeBSD-questions.</para>
+ </listitem>
+
+ <listitem>
+ <para>Not everybody who answers FreeBSD questions reads every message:
+ they look at the subject line and decide whether it interests them.
+ Clearly, it is in your interest to specify a subject. <quote>FreeBSD
+ problem</quote> or <quote>Help</quote> are not enough. If you provide no subject at
+ all, many people will not bother reading it. If your subject is not
+ specific enough, the people who can answer it may not read
+ it.</para>
+ </listitem>
+
+ <listitem>
+ <para>Format your message so that it is legible, and
+ PLEASE DO NOT SHOUT!!!!!. We appreciate that a lot of people do not
+ speak English as their first language, and we try to make
+ allowances for that, but it is really painful to try to read a
+ message written full of typos or without any line breaks.</para>
+
+ <para>Do not underestimate the effect that a poorly formatted mail
+ message has, not just on the FreeBSD-questions mailing list.
+ Your mail message is all people see of you, and if it is poorly
+ formatted, one line per paragraph, badly spelt, or full of
+ errors, it will give people a poor impression of you.</para>
+
+ <para>A lot of badly formatted messages come from
+ <link xlink:href="http://www.lemis.com/email.html">bad mailers or badly
+ configured mailers</link>. The following mailers are known to
+ send out badly formatted messages without you finding out about
+ them:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>cc:Mail</para>
+ </listitem>
+
+ <listitem>
+ <para>&eudora;</para>
+ </listitem>
+
+ <listitem>
+ <para>exmh</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; Exchange</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; Internet Mail</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; &outlook;</para>
+ </listitem>
+
+ <listitem>
+ <para>&netscape;</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>As you can see, the mailers in the Microsoft world are frequent
+ offenders. If at all possible, use a &unix; mailer. If you must use a
+ mailer under Microsoft environments, make sure it is set up
+ correctly. Try not to use <acronym>MIME</acronym>: a lot of people
+ use mailers which do not get on very well with
+ <acronym>MIME</acronym>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Make sure your time and time zone are set correctly. This may
+ seem a little silly, since your message still gets there, but many
+ of the people you are trying to reach get several hundred messages a
+ day. They frequently sort the incoming messages by subject and by
+ date, and if your message does not come before the first answer, they
+ may assume they missed it and not bother to look.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not include unrelated questions in the same message. Firstly,
+ a long message tends to scare people off, and secondly, it is more
+ difficult to get all the people who can answer all the questions to
+ read the message.</para>
+ </listitem>
+
+ <listitem>
+ <para>Specify as much information as possible. This is a difficult
+ area, and we need to expand on what information you need to submit,
+ but here is a start:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>In nearly every case, it is important to know the version of
+ FreeBSD you are running. This is particularly the case for
+ FreeBSD-CURRENT, where you should also specify the date of the
+ sources, though of course you should not be sending questions
+ about -CURRENT to FreeBSD-questions.</para>
+ </listitem>
+
+ <listitem><para>With any problem which <emphasis>could</emphasis> be
+ hardware related, tell us about your hardware. In case of
+ doubt, assume it is possible that it is hardware. What kind of
+ CPU are you using? How fast? What motherboard? How much
+ memory? What peripherals?</para>
+
+ <para>There is a judgement call here, of course, but the output of
+ the &man.dmesg.8; command can frequently be very useful, since it
+ tells not just what hardware you are running, but what version of
+ FreeBSD as well.</para>
+ </listitem>
+
+ <listitem>
+ <para>If you get error messages, do not say <quote>I get error
+ messages</quote>, say (for example) <quote>I get the error
+ message 'No route to host'</quote>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If your system panics, do not say <quote>My system
+ panicked</quote>, say (for example) <quote>my system panicked
+ with the message 'free vnode isn't'</quote>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If you have difficulty installing FreeBSD, please tell us
+ what hardware you have. In particular, it is important to know
+ the IRQs and I/O addresses of the boards installed in your
+ machine.</para>
+ </listitem>
+
+ <listitem>
+ <para>If you have difficulty getting PPP to run, describe the
+ configuration. Which version of PPP do you use? What kind of
+ authentication do you have? Do you have a static or dynamic IP
+ address? What kind of messages do you get in the log
+ file?</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>A lot of the information you need to supply is the output of
+ programs, such as &man.dmesg.8;, or console messages, which usually
+ appear in <filename>/var/log/messages</filename>. Do not try to copy
+ this information by typing it in again; it is a real pain, and you are
+ bound to make a mistake. To send log file contents, either make a
+ copy of the file and use an editor to trim the information to what
+ is relevant, or cut and paste into your message. For the output of
+ programs like &man.dmesg.8;, redirect the output to a file and
+ include that. For example,</para>
+
+ <screen>&prompt.user; <userinput>dmesg &gt; /tmp/dmesg.out</userinput></screen>
+
+ <para>This redirects the information to the file
+ <filename>/tmp/dmesg.out</filename>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If you do all this, and you still do not get an answer, there
+ could be other reasons. For example, the problem is so complicated
+ that nobody knows the answer, or the person who does know the answer
+ was offline. If you do not get an answer after, say, a week, it
+ might help to re-send the message. If you do not get an answer to
+ your second message, though, you are probably not going to get one
+ from this forum. Resending the same message again and again will
+ only make you unpopular.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>To summarize, let's assume you know the answer to the following
+ question (yes, it is the same one in each case).
+ You choose which of these two questions you would be more prepared to
+ answer:</para>
+
+ <example>
+ <title>Message 1</title>
+
+ <literallayout class="monospaced">Subject: HELP!!?!??
+I just can't get hits damn silly FereBSD system to
+workd, and Im really good at this tsuff, but I have never seen
+anythign sho difficult to install, it jst wont work whatever I try
+so why don't you guys tell me what I doing wrong.</literallayout>
+ </example>
+
+ <example>
+ <title>Message 2</title>
+
+ <literallayout class="monospaced">Subject: Problems installing FreeBSD
+
+I've just got the FreeBSD 2.1.5 CDROM from Walnut Creek, and I'm having a lot
+of difficulty installing it. I have a 66 MHz 486 with 16 MB of
+memory and an Adaptec 1540A SCSI board, a 1.2GB Quantum Fireball
+disk and a Toshiba 3501XA CDROM drive. The installation works just
+fine, but when I try to reboot the system, I get the message
+<quote>Missing Operating System</quote>.</literallayout>
+ </example>
+ </sect1>
+
+ <sect1>
+ <title xml:id="followup">How to follow up to a question</title>
+
+ <para>Often you will want to send in additional information to a question
+ you have already sent. The best way to do this is to reply to your
+ original message. This has three advantages:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>You include the original message text, so people will know what
+ you are talking about. Do not forget to trim unnecessary text out,
+ though.</para>
+ </listitem>
+
+ <listitem>
+ <para>The text in the subject line stays the same (you did remember to
+ put one in, did you not?). Many mailers will sort messages by
+ subject. This helps group messages together.</para>
+ </listitem>
+
+ <listitem>
+ <para>The message reference numbers in the header will refer to the
+ previous message. Some mailers, such as
+ <link xlink:href="http://www.mutt.org/">mutt</link>, can
+ <emphasis>thread</emphasis> messages, showing the exact
+ relationships between the messages.</para>
+ </listitem>
+ </orderedlist>
+ </sect1>
+
+ <sect1>
+ <title xml:id="answer">How to answer a question</title>
+
+
+ <para>Before you answer a question to FreeBSD-questions, consider:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>A lot of the points on submitting questions also apply to
+ answering questions. Read them.</para>
+ </listitem>
+
+ <listitem>
+ <para>Has somebody already answered the question? The easiest way to
+ check this is to sort your incoming mail by subject: then
+ (hopefully) you will see the question followed by any answers, all
+ together.</para>
+
+ <para>If somebody has already answered it, it does not automatically
+ mean that you should not send another answer. But it makes sense to
+ read all the other answers first.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do you have something to contribute beyond what has already been
+ said? In general, <quote>Yeah, me too</quote> answers do not help
+ much, although there are exceptions, like when somebody is
+ describing a problem he is having, and he does not know whether it is
+ his fault or whether there is something wrong with the hardware or
+ software. If you do send a <quote>me too</quote> answer, you should
+ also include any further relevant information.</para>
+ </listitem>
+
+ <listitem>
+ <para>Are you sure you understand the question? Very frequently, the
+ person who asks the question is confused or does not express himself
+ very well. Even with the best understanding of the system, it is
+ easy to send a reply which does not answer the question. This
+ does not help: you will leave the person who submitted the question
+ more frustrated or confused than ever. If nobody else answers, and
+ you are not too sure either, you can always ask for more
+ information.</para>
+ </listitem>
+
+ <listitem>
+ <para>Are you sure your answer is correct?
+ If not, wait a day or so. If nobody else comes up with a
+ better answer, you can still reply and say, for example, <quote>I
+ do not know if this is correct, but since nobody else has
+ replied, why don't you try replacing your ATAPI CDROM with
+ a frog?</quote>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Unless there is a good reason to do otherwise, reply to the
+ sender and to FreeBSD-questions. Many people on the
+ FreeBSD-questions are <quote>lurkers</quote>: they learn by reading
+ messages sent and replied to by others. If you take a message which
+ is of general interest off the list, you are depriving these people
+ of their information. Be careful with group replies; lots of people
+ send messages with hundreds of CCs. If this is the case, be sure to
+ trim the Cc: lines appropriately.</para>
+ </listitem>
+
+ <listitem>
+ <para>Include relevant text from the original message. Trim it to the
+ minimum, but do not overdo it. It should still be possible for
+ somebody who did not read the original message to understand what
+ you are talking about.</para>
+ </listitem>
+
+ <listitem>
+ <para>Use some technique to identify which text came from the original
+ message, and which text you add. I personally find that prepending
+ <quote><literal>&gt; </literal></quote> to the original message
+ works best. Leaving white space after the
+ <quote><literal>&gt; </literal></quote> and leave empty lines
+ between your text and the original text both make the result more
+ readable.</para>
+ </listitem>
+
+ <listitem>
+ <para>Put your response in the correct place (after the text to which
+ it replies). It is very difficult to read a thread of responses
+ where each reply comes before the text to which it replies.</para>
+ </listitem>
+
+ <listitem>
+ <para>Most mailers change the subject line on a reply by prepending a
+ text such as <quote>Re: </quote>. If your mailer does not do it
+ automatically, you should do it manually.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the submitter did not abide by format conventions (lines too
+ long, inappropriate subject line), <emphasis>please</emphasis> fix
+ it. In the case of an incorrect subject line (such as
+ <quote>HELP!!??</quote>), change the subject line to (say)
+ <quote>Re: Difficulties with sync PPP (was: HELP!!??)</quote>. That
+ way other people trying to follow the thread will have less
+ difficulty following it.</para>
+
+ <para>In such cases, it is appropriate to say what you did and why you
+ did it, but try not to be rude. If you find you can not answer
+ without being rude, do not answer.</para>
+
+ <para>If you just want to reply to a message because of its bad
+ format, just reply to the submitter, not to the list. You can just
+ send him this message in reply, if you like.</para>
+ </listitem>
+ </orderedlist>
+ </sect1>
+</article>
diff --git a/zh_TW.UTF-8/articles/hubs/Makefile b/zh_TW.UTF-8/articles/hubs/Makefile
new file mode 100644
index 0000000000..f04f8a971f
--- /dev/null
+++ b/zh_TW.UTF-8/articles/hubs/Makefile
@@ -0,0 +1,17 @@
+#
+# $FreeBSD$
+#
+# Article: Mirroring FreeBSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+DOC_PREFIX?= ${.CURDIR}/../../..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/hubs/article.xml b/zh_TW.UTF-8/articles/hubs/article.xml
new file mode 100644
index 0000000000..8e73b481b7
--- /dev/null
+++ b/zh_TW.UTF-8/articles/hubs/article.xml
@@ -0,0 +1,1051 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!-- $FreeBSD$ -->
+<!-- The FreeBSD Documentation Project -->
+<!-- Mirroring FreeBSD -->
+<!-- Translate into Chinese by chinsan.tw@gmail.com -->
+<!-- English Version: 1.62 -->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>Mirroring FreeBSD</title>
+
+ <authorgroup>
+ <author><personname><firstname>Jun</firstname><surname>Kuriyama</surname></personname><affiliation>
+ <address><email>kuriyama@FreeBSD.org</email></address>
+ </affiliation></author>
+ <author><personname><firstname>Valentino</firstname><surname>Vaschetto</surname></personname><affiliation>
+ <address><email>logo@FreeBSD.org</email></address>
+ </affiliation></author>
+ <author><personname><firstname>Daniel</firstname><surname>Lang</surname></personname><affiliation>
+ <address><email>dl@leo.org</email></address>
+ </affiliation></author>
+ <author><personname><firstname>Ken</firstname><surname>Smith</surname></personname><affiliation>
+ <address><email>kensmith@FreeBSD.org</email></address>
+ </affiliation></author>
+ </authorgroup>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.cvsup;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>這是份還在草稿中的文章,主要是(尤其是給各區網中心管理者的參考)介紹如何 mirror FreeBSD。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="mirror-contact">
+ <title>聯繫方式</title>
+
+ <para>若要找整個 Mirror 機制的協調者,可以 email 到 <email>mirror-admin@FreeBSD.org</email>。此外,這裡也有份
+ &a.hubs;。</para>
+ </sect1>
+
+ <sect1 xml:id="mirror-requirements">
+ <title>成為 FreeBSD mirrors 的必備條件</title>
+ <sect2 xml:id="mirror-diskspace">
+ <title>硬碟空間</title>
+ <para>
+ 硬碟空間是最重要的必備條件之一。
+ Depending on the set of releases, architectures,
+ and degree of completeness you want to mirror, a huge
+ amount of disk space may be consumed. Also keep in mind
+ that <emphasis>official</emphasis> mirrors are probably required to be
+ complete. The CVS repository and the web pages should
+ always be mirrored completely. Also note that the
+ numbers stated here are reflecting the current
+ state (at &rel2.current;-RELEASE/&rel.current;-RELEASE). Further development and
+ releases will only increase the required amount.
+ Also make sure to keep some (ca. 10-20%) extra space
+ around just to be sure.
+ Here are some approximate figures:
+ </para>
+ <itemizedlist>
+ <listitem><para>完整 FTP Distribution: 126 GB</para></listitem>
+ <listitem><para>CVS repository: 2.7 GB</para></listitem>
+ <listitem><para>CTM deltas: 1.8 GB</para></listitem>
+ <listitem><para>Web pages: 300 MB</para></listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2 xml:id="mirror-bandwidth">
+ <title>網路頻寬</title>
+ <para>
+ 當然,你一定要能連上 Internet。
+ 頻寬需求多少,這要看你所想要的 mirror 程度而定。
+ 若只想要 mirror 一部份的 FreeBSD 檔案以作為網站或 intranet 的局部用途,
+ 那麼頻寬需求會明顯比成為公共服務用途的小一些。
+ 若想成為 official mirror 之一的話,那麼頻寬就勢必得增加才夠用。以下,我們僅列出一些估計值以做為參考:
+ </para>
+ <itemizedlist>
+ <listitem><para>Local site, no public access: basically no minimum,
+ but &lt; 2 Mbps could make syncing too slow.</para></listitem>
+ <listitem><para>Unofficial public site: 34 Mbps is probably a good start.</para></listitem>
+ <listitem><para>Official site: &gt; 100 Mbps is recommended, and your host
+ should be connected as close as possible to your border router.</para></listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2 xml:id="mirror-system">
+ <title>系統需求、CPU、RAM</title>
+ <para>
+ One thing this depends on the expected number of clients,
+ which is determined by the server's policy. It is
+ also affected by the types of services you want to offer.
+ Plain FTP or HTTP services may not require a huge
+ amount of resources. Watch out if you provide
+ CVSup, rsync or even AnonCVS. This can have a huge
+ impact on CPU and memory requirements. Especially
+ rsync is considered a memory hog, and CVSup does
+ indeed consume some CPU. For AnonCVS it might
+ be a nice idea to set up a memory resident file system (MFS) of at least
+ 300 MB, so you need to take this into account
+ for your memory requirements. The following
+ are just examples to give you a very rough hint.
+ </para>
+ <para>
+ For a moderately visited site that offers
+ <application>Rsync</application>, you might
+ consider a current CPU with around 800MHz - 1 GHz,
+ and at least 512MB RAM. This is probably the
+ minimum you want for an <emphasis>official</emphasis>
+ site.
+ </para>
+ <para>
+ For a frequently used site you definitely need
+ more RAM (consider 2GB as a good start)
+ and possibly more CPU, which could also mean
+ that you need to go for a SMP system.
+ </para>
+ <para>
+ You also want to consider a fast disk subsystem.
+ Operations on the CVS repository require a fast
+ disk subsystem (RAID is highly advised). A SCSI
+ controller that has a cache of its own can also
+ speed up things since most of these services incur a
+ large number of small modifications to the disk.
+ </para>
+ </sect2>
+ <sect2 xml:id="mirror-services">
+ <title>Services to offer</title>
+ <para>
+ Every mirror site is required to have a set of core services
+ available. In addition to these required services, there are
+ a number of optional services that
+ server administrators may choose to offer. This section explains
+ which services you can provide and how to go about implementing them.
+ </para>
+ <sect3 xml:id="mirror-serv-ftp">
+ <title>FTP (required for FTP fileset)</title>
+ <para>
+ This is one of the most basic services, and
+ it is required for each mirror offering public
+ FTP distributions. FTP access must be
+ anonymous, and no upload/download ratios
+ are allowed (a ridiculous thing anyway).
+ Upload capability is not required (and <emphasis>must</emphasis>
+ never be allowed for the FreeBSD file space).
+ Also the FreeBSD archive should be available under
+ the path <filename>/pub/FreeBSD</filename>.
+ </para>
+ <para>
+ There is a lot of software available which
+ can be set up to allow anonymous FTP
+ (in alphabetical order).
+ <itemizedlist>
+ <listitem><para><command>/usr/libexec/ftpd</command>: FreeBSD's own ftpd
+ can be used. Be sure to read &man.ftpd.8;.</para>
+ </listitem>
+ <listitem>
+ <para><package>ftp/ncftpd</package>: A commercial package,
+ free for educational use.</para>
+ </listitem>
+ <listitem>
+ <para><package>ftp/oftpd</package>: An ftpd designed with
+ security as a main focus.</para>
+ </listitem>
+ <listitem>
+ <para><package>ftp/proftpd</package>: A modular and very flexible ftpd.</para>
+ </listitem>
+ <listitem>
+ <para><package>ftp/pure-ftpd</package>: Another ftpd developed with
+ security in mind.</para>
+ </listitem>
+ <listitem><para><package>ftp/twoftpd</package>: As above.</para></listitem>
+ <listitem><para><package>ftp/vsftpd</package>: The <quote>very secure</quote> ftpd.</para></listitem>
+ <listitem>
+ <para><package>ftp/wu-ftpd</package>: The ftpd from Washington
+ University. It has become infamous, because of the huge
+ amount of security issues that have been found in it.
+ If you do choose to use this software be sure to
+ keep it up to date.
+ </para>
+ </listitem>
+ </itemizedlist>
+ FreeBSD's <application>ftpd</application>, <application>proftpd</application>,
+ <application>wu-ftpd</application> and maybe <application>ncftpd</application>
+ are among the most commonly used FTPds.
+ The others do not have a large userbase among mirror sites. One
+ thing to consider is that you may need flexibility in limiting
+ how many simultaneous connections are allowed, thus limiting how
+ much network bandwidth and system resources are consumed.
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-serv-rsync">
+ <title>Rsync (optional for FTP fileset)</title>
+ <para>
+ <application>Rsync</application> is often offered for access to the
+ contents of the FTP area of FreeBSD, so other mirror sites can use your system as their source. The
+ protocol is different from FTP in many ways.
+ It is much more
+ bandwidth friendly, as only differences between files
+ are transferred instead of whole files when they change.
+ <application>Rsync</application> does require a significant amount of memory for
+ each instance. The size depends on the size of
+ the synced module in terms of the number of directories and
+ files. <application>Rsync</application> can use <command>rsh</command> and
+ <command>ssh</command> (now default) as a transport,
+ or use its own protocol for stand-alone access
+ (this is the preferred method for public rsync servers).
+ Authentication, connection limits, and other restrictions
+ may be applied. There is just one software package
+ available:
+ <itemizedlist>
+ <listitem><para><package>net/rsync</package></para></listitem>
+ </itemizedlist>
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-serv-http">
+ <title>HTTP (required for web pages, optional for FTP fileset)</title>
+ <para>
+ If you want to offer the FreeBSD web pages, you will need
+ to install a web server.
+ You may optionally offer the FTP fileset via HTTP.
+ The choice of web server software is left up to the mirror administrator.
+ Some of the most popular choices are:
+
+ <itemizedlist>
+ <listitem>
+ <para><package>www/apache13</package>:
+ <application>Apache</application> is the most widely
+ deployed web server on the Internet. It is used
+ extensively by the FreeBSD Project. You may also wish to
+ use the next generation of the
+ <application>Apache</application> web server, available
+ in the ports collection as <package>www/apache22</package>.</para>
+ </listitem>
+
+ <listitem>
+ <para><package>www/thttpd</package>:
+ If you are going to be serving a large amount of static content
+ you may find that using an application such as thttpd is more
+ efficient than <application>Apache</application>. It is
+ optimized for excellent performance on FreeBSD.</para>
+ </listitem>
+
+ <listitem>
+ <para><package>www/boa</package>:
+ <application>Boa</application> is another alternative to
+ <application>thttpd</application> and
+ <application>Apache</application>. It should provide
+ considerably better performance than
+ <application>Apache</application> for purely static
+ content. It does not, at the time of this writing,
+ contain the same set of optimizations for FreeBSD that
+ are found in <application>thttpd</application>.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-serv-cvsup">
+ <title>CVSup (desired for CVS repository)</title>
+ <para>
+ <application>CVSup</application> is a very efficient way of distributing files.
+ It works similar to <application>rsync</application>, but was specially designed for
+ use with CVS repositories. If you want to offer the
+ FreeBSD CVS repository, you really want to consider
+ offering it via <application>CVSup</application>. It is possible to offer
+ the CVS repository via <application>AnonCVS</application>, FTP,
+ <application>rsync</application> or HTTP, but
+ people would benefit much more from <application>CVSup</application> access.
+ <application>CVSup</application> was developed by &a.jdp;.
+ It is a bit tricky to install on non-FreeBSD platforms,
+ since it is written in Modula-3 and therefore requires
+ a Modula-3 environment. John Polstra has built a
+ stripped down version of M3 that is sufficient to
+ run <application>CVSup</application>, and can be installed much easier.
+ See <link xlink:href="http://www.polstra.com/projects/freeware/ezm3/">Ezm3</link>
+ for details. Related ports are:
+
+ <itemizedlist>
+ <listitem>
+ <para><package>net/cvsup</package>: The native CVSup port (client and server)
+ which requires <package>lang/ezm3</package> now.</para>
+ </listitem>
+ <listitem>
+ <para><package>net/cvsup-mirror</package>: The CVSup mirror kit, which requires
+ <package>net/cvsup-without-gui</package>, and configures it mirror-ready. Some
+ site administrators may want a different setup though.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ There are a few more like
+ <package>net/cvsup-without-gui</package> you might want to have
+ a look at. If you prefer a static binary package, take a look
+ <link xlink:href="http://people.FreeBSD.org/~jdp/s1g/">here</link>.
+ This page still refers to the S1G bug that was present
+ in <application>CVSup</application>. Maybe
+ John will set up a generic download-site to get
+ static binaries for various platforms.
+ </para>
+ <para>
+ It is possible to use <application>CVSup</application> to offer
+ any kind of fileset, not just CVS repositories,
+ but configuration can be complex.
+ <application>CVSup</application> is known to eat some CPU on both the server and the
+ client, since it needs to compare lots of files.
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-anoncvs">
+ <title>AnonCVS (optional for CVS repository)</title>
+ <para>
+ If you have the CVS repository, you may want to offer
+ anonymous CVS access. A short warning first:
+ There is not much demand for it,
+ it requires some experience, and you need to know
+ what you are doing.
+ </para>
+ <para>
+ Generally there are two ways
+ to access a CVS repository remotely: via
+ <emphasis>pserver</emphasis> or via <command>ssh</command>
+ (we do not consider <command>rsh</command>).
+ For anonymous access, <emphasis>pserver</emphasis> is
+ very well suited, but some still offer <command>ssh</command>
+ access as well. There is a custom crafted
+ <link xlink:href="ftp://ftp.FreeBSD.org/pub/FreeBSD/development/FreeBSD-CVS/anoncvs.shar">wrapper</link>
+ in the CVS repository, to be used as a login-shell for the
+ anonymous ssh account. It does a chroot, and therefore
+ requires the CVS repository to be available under the
+ anonymous user's home-directory. This may not be possible
+ for all sites. If you just offer <emphasis>pserver</emphasis>
+ this restriction does not apply, but you may run with
+ more security risks. You do not need to install any special
+ software, since &man.cvs.1; comes with
+ FreeBSD. You need to enable access via <command>inetd</command>,
+ so add an entry into your <filename>/etc/inetd.conf</filename>
+ like this:
+ <programlisting>
+cvspserver stream tcp nowait root /usr/bin/cvs cvs -f -l -R -T /anoncvstmp --allow-root=/home/ncvs pserver
+ </programlisting>
+ See the manpage for details of the options. Also see the CVS <emphasis>info</emphasis>
+ page about additional ways to make sure access is read-only.
+ It is advised that you create an unprivileged account,
+ preferably called <systemitem class="username">anoncvs</systemitem>.
+ Also you need to create a file <filename>passwd</filename>
+ in your <filename>/home/ncvs/CVSROOT</filename> and assign a
+ CVS password (empty or <literal>anoncvs</literal>) to that user.
+ The directory <filename>/anoncvstmp</filename> is a special
+ purpose memory based file system. It is not required but
+ advised since &man.cvs.1; creates a shadow directory
+ structure in your <filename>/tmp</filename> which is
+ not used after the operation but slows things
+ dramatically if real disk operations are required.
+ Here is an excerpt from <filename>/etc/fstab</filename>,
+ how to set up such a MFS:
+ <programlisting>
+/dev/da0s1b /anoncvstmp mfs rw,-s=786432,-b=4096,-f=512,-i=560,-c=3,-m=0,nosuid,nodev 0 0
+ </programlisting>
+ This is (of course) tuned a lot, and was suggested by &a.jdp;.
+ </para>
+ </sect3>
+ </sect2>
+ </sect1>
+ <sect1 xml:id="mirror-howto">
+ <title>How to Mirror FreeBSD</title>
+ <para>
+ Ok, now you know the requirements and how to offer
+ the services, but not how to get it. :-)
+ This section explains how to actually mirror
+ the various parts of FreeBSD, what tools to use,
+ and where to mirror from.
+ </para>
+ <sect2 xml:id="mirror-ftp">
+ <title>FTP</title>
+ <para>
+ The FTP area is the largest amount of data that
+ needs to be mirrored. It includes the <emphasis>distribution
+ sets</emphasis> required for network installation, the
+ <emphasis>branches</emphasis> which are actually snapshots
+ of checked-out source trees, the <emphasis>ISO Images</emphasis>
+ to write CD-ROMs with the installation distribution,
+ a live file system, lots of packages, the ports tree,
+ distfiles, and a huge amount of packages. All of course
+ for various FreeBSD versions,
+ and various architectures.
+ </para>
+ <sect3 xml:id="mirror-ftp-ftp">
+ <title>With FTP mirror</title>
+ <para>
+ You can use a <application>FTP mirror</application>
+ program to get the files. Some of the most commonly used are:
+ <itemizedlist>
+ <listitem><para><package>ftp/mirror</package></para></listitem>
+ <listitem><para><package>ftp/ftpmirror</package></para></listitem>
+ <listitem><para><package>ftp/emirror</package></para></listitem>
+ <listitem><para><package>ftp/spegla</package></para></listitem>
+ <listitem><para><package>ftp/omi</package></para></listitem>
+ <listitem><para><package>ftp/wget</package></para></listitem>
+ </itemizedlist>
+
+ <package>ftp/mirror</package> was very popular, but seemed
+ to have some drawbacks, as it is written in &man.perl.1;,
+ and had real problems with mirroring large
+ directories like a FreeBSD site. There are rumors that
+ the current version has fixed this by allowing
+ a different algorithm for comparing
+ the directory structure to be specified.
+ </para>
+ <para>
+ In general FTP is not really good for mirroring. It transfers
+ the whole file if it has changed, and does
+ not create a single data stream which would benefit from
+ a large TCP congestion window.
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-ftp-rsync">
+ <title>With rsync</title>
+ <para>
+ A better way to mirror the FTP area is <application>rsync</application>.
+ You can install the port <package>net/rsync</package> and then use
+ rsync to sync with your upstream host.
+ <application>rsync</application> is already mentioned
+ in <xref linkend="mirror-serv-rsync"/>.
+ Since <application>rsync</application> access is not
+ required, your preferred upstream site may not allow it.
+ You may need to hunt around a little bit to find a site
+ that allows <application>rsync</application> access.
+ <note>
+ <para>
+ Since the number of <application>rsync</application>
+ clients will have a significant impact on the server
+ machine, most admins impose limitations on their
+ server. For a mirror, you should ask the site maintainer
+ you are syncing from about their policy, and maybe
+ an exception for your host (since you are a mirror).
+ </para>
+ </note>
+ A command line to mirror FreeBSD might look like:
+ <screen>&prompt.user; <userinput>rsync -vaz --delete ftp4.de.FreeBSD.org::FreeBSD/ /pub/FreeBSD/</userinput>
+ </screen>
+ Consult the documentation for <application>rsync</application>,
+ which is also available at
+ <link xlink:href="http://rsync.samba.org/">http://rsync.samba.org/</link>,
+ about the various options to be used with rsync.
+ If you sync the whole module (unlike subdirectories),
+ be aware that the module-directory (here "FreeBSD")
+ will not be created, so you cannot omit the target directory.
+ Also you might
+ want to set up a script framework that calls such a command
+ via &man.cron.8;.
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-ftp-cvsup">
+ <title>With CVSup</title>
+ <para>
+ A few sites, including the one-and-only <systemitem class="fqdomainname">ftp-master.FreeBSD.org</systemitem>
+ even offer <application>CVSup</application> to mirror the contents of
+ the FTP space. You need to install a <application>CVSup</application>
+ client, preferably from the port <package>net/cvsup</package>.
+ (Also reread <xref linkend="mirror-serv-cvsup"/>.)
+ A sample <filename>supfile</filename> suitable for <systemitem class="fqdomainname">ftp-master.FreeBSD.org</systemitem>
+ looks like this:
+ <programlisting>
+ #
+ # FreeBSD archive supfile from master server
+ #
+ *default host=ftp-master.FreeBSD.org
+ *default base=/usr
+ *default prefix=/pub
+ #*default release=all
+ *default delete use-rel-suffix
+ *default umask=002
+
+ # If your network link is a T1 or faster, comment out the following line.
+ #*default compress
+
+ FreeBSD-archive release=all preserve
+ </programlisting>
+
+ It seems <application>CVSup</application> would be the best
+ way to mirror the archive in terms of efficiency, but
+ it is only available from few sites.
+ <note xml:id="mirror-cvsup-s-option">
+ <para>
+ Please have look at the <application>CVSup</application> documentation
+ like &man.cvsup.1; and consider using the <option>-s</option>
+ option. This reduces I/O operations by assuming the
+ recorded information about each file is correct.</para>
+ </note>
+ </para>
+ </sect3>
+ </sect2>
+ <sect2 xml:id="mirror-cvs">
+ <title>Mirroring the CVS repository</title>
+ <para>There are various ways to mirror the CVS repository.
+ <application>CVSup</application> is the most common method.</para>
+
+ <sect3 xml:id="mirror-cvs-cvsup">
+ <title>Using CVSup</title>
+ <para>
+ <application>CVSup</application> is described in some
+ detail in <xref linkend="mirror-serv-cvsup"/> and <xref linkend="mirror-ftp-cvsup"/>.
+ </para>
+ <para>It is very easy to setup a
+ <application>CVSup</application> mirror. Installing
+ <package>net/cvsup-mirror</package> will
+ make sure all of the needed programs are installed and then
+ gather all the needed information to configure the mirror.</para>
+ <note>
+ <para>
+ Please do not forget to consider the hint
+ mentioned in <link linkend="mirror-cvsup-s-option">this note</link>
+ above.
+ </para>
+ </note>
+ </sect3>
+ <sect3 xml:id="mirror-cvs-other">
+ <title>Using other methods</title>
+ <para>
+ Using other methods than <application>CVSup</application> is
+ generally not recommended. We describe them in short here
+ anyway. Since most sites offer the CVS repository as
+ part of the FTP fileset under the path
+ <filename>/pub/FreeBSD/development/FreeBSD-CVS</filename>,
+ the following methods could be used.
+ <itemizedlist>
+ <listitem><para><application>FTP</application></para></listitem>
+ <listitem><para><application>Rsync</application></para></listitem>
+ <listitem><para><application>HTTP</application></para></listitem>
+ </itemizedlist>
+
+ <important>
+ <para>AnonCVS cannot be used to mirror the CVS repository
+ since CVS does not allow you to access the repository
+ itself, only checked out versions of the modules.</para>
+ </important>
+ </para>
+ </sect3>
+ </sect2>
+ <sect2 xml:id="mirror-www">
+ <title>Mirroring the WWW pages</title>
+ <para>
+ The best way is to check out the <emphasis>www</emphasis>
+ distribution from CVS. If you have a local mirror of the
+ CVS repository, it is as easy as:
+ <screen>&prompt.user; <userinput>cvs -d /home/ncvs co www</userinput></screen>
+ and a <emphasis>cronjob</emphasis>, that calls <command>cvs up -d -P</command>
+ on a regular basis, maybe just after your repository was updated.
+ Of course, the files need to remain in a directory available
+ for public WWW access. The installation and configuration of a
+ web server is not discussed here.
+ </para>
+
+ <para>
+ If you do not have a local repository, you can use
+ <application>CVSup</application> to maintain an <quote>up to date copy</quote>
+ of the www pages. A sample supfile can be found in
+ <filename>/usr/share/examples/cvsup/www-supfile</filename> and
+ could look like this:
+ <programlisting>
+ #
+ # WWW module supfile for FreeBSD
+ #
+ *default host=cvsup3.de.FreeBSD.org
+ *default base=/usr
+ *default prefix=/usr/local
+ *default release=cvs tag=.
+ *default delete use-rel-suffix
+
+ # If your network link is a T1 or faster, comment out the following line.
+ *default compress
+
+ # This collection retrieves the www/ tree of the FreeBSD repository
+ www
+ </programlisting>
+ </para>
+ <para>
+ Using <package>ftp/wget</package> or other web-mirror tools is
+ not recommended.
+ </para>
+ <sect3 xml:id="mirror-www-doc">
+ <title>Mirroring the FreeBSD documentation</title>
+ <para>
+ Since the documentation is referenced a lot from the
+ web pages, it is recommended that you mirror the
+ FreeBSD documentation as well. However, this is not
+ as trivial as the www-pages alone.
+ </para>
+ <para>
+ First of all, you should get the doc sources,
+ again preferably via <application>CVSup</application>.
+ Here is a corresponding sample supfile:
+ <programlisting>
+ #
+ # FreeBSD documentation supfile
+ #
+ *default host=cvsup3.de.FreeBSD.org
+ *default base=/usr
+ *default prefix=/usr/share
+ *default release=cvs tag=.
+ *default delete use-rel-suffix
+
+ # If your network link is a T1 or faster, comment out the following line.
+ #*default compress
+
+ # This will retrieve the entire doc branch of the FreeBSD repository.
+ # This includes the handbook, FAQ, and translations thereof.
+ doc-all
+ </programlisting>
+ </para>
+ <para>
+ Then you need to install a couple of ports.
+ You are lucky, there is a meta-port:
+ <package>textproc/docproj</package> to do the work
+ for you. You need to set up some
+ environment variables, like
+ <literal>SGML_CATALOG_FILES</literal>.
+ Also have a look at your <filename>/etc/make.conf</filename>
+ (copy <filename>/usr/share/examples/etc/make.conf</filename> if
+ you do not have one), and look at the
+ <literal>DOC_LANG</literal> variable.
+ Now you are probably ready to run <command>make</command>
+ in your doc directory (<filename>/usr/share/doc</filename>
+ by default) and build the documentation.
+ Again you need to make it accessible for your web server
+ and make sure the links point to the right location.
+ <important>
+ <para>
+ The building of the documentation, as well as lots
+ of side issues, is documented itself in the
+ <link xlink:href="&url.books.fdp-primer;">&os; Documentation
+ Project Primer</link>.
+ Please read this piece of documentation, especially if you
+ have problems building the documentation.
+ </para>
+ </important>
+ </para>
+ </sect3>
+ </sect2>
+ <sect2 xml:id="mirror-how-often">
+ <title>How often should I mirror?</title>
+ <para>
+ Every mirror should be updated on a regular
+ basis. You will certainly need some script
+ framework for it that will be called by
+ &man.cron.8;. Since nearly every admin
+ does this his own way, we cannot give
+ specific instructions. It could work
+ like this:
+ </para>
+ <procedure>
+ <step>
+ <para>
+ Put the command to run your mirroring application
+ in a script. Use of a plain <command>/bin/sh</command>
+ script is recommended.
+ </para>
+ </step>
+ <step>
+ <para>
+ Add some output redirections so diagnostic
+ messages are logged to a file.
+ </para>
+ </step>
+ <step>
+ <para>
+ Test if your script works. Check the logs.
+ </para>
+ </step>
+ <step>
+ <para>
+ Use &man.crontab.1; to add the script to the
+ appropriate user's &man.crontab.5;. This should be a
+ different user than what your FTP daemon runs as so that
+ if file permissions inside your FTP area are not
+ world-readable those files can not be accessed by anonymous
+ FTP. This is used to <quote>stage</quote> releases &mdash;
+ making sure all of the official mirror sites have all of the
+ necessary release files on release day.
+ </para>
+ </step>
+ </procedure>
+ <para>
+ Here are some recommended schedules:
+ <itemizedlist>
+ <listitem><para>FTP fileset: daily</para></listitem>
+ <listitem><para>CVS repository: hourly</para></listitem>
+ <listitem><para>WWW pages: daily</para></listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+ <sect1 xml:id="mirror-where">
+ <title>Where to mirror from</title>
+ <para>
+ This is an important issue. So this section will
+ spend some effort to explain the backgrounds. We will say this
+ several times: under no circumstances should you mirror from
+ <systemitem class="fqdomainname">ftp.FreeBSD.org</systemitem>.
+ </para>
+ <sect2 xml:id="mirror-where-organization">
+ <title>A few words about the organization</title>
+ <para>
+ Mirrors are organized by country. All
+ official mirrors have a DNS entry of the form
+ <systemitem class="fqdomainname">ftpN.CC.FreeBSD.org</systemitem>.
+ <emphasis>CC</emphasis> (i.e. country code) is the
+ <emphasis>top level domain</emphasis> (TLD)
+ of the country where this mirror is located.
+ <emphasis>N</emphasis> is a number,
+ telling that the host would be the <emphasis>Nth</emphasis>
+ mirror in that country.
+ (Same applies to <systemitem>cvsupN.CC.FreeBSD.org</systemitem>,
+ <systemitem>wwwN.CC.FreeBSD.org</systemitem>, etc.)
+ There are mirrors with no <emphasis>CC</emphasis> part.
+ These are the mirror sites that are very well connected and
+ allow a large number of concurrent users.
+ <systemitem class="fqdomainname">ftp.FreeBSD.org</systemitem> is actually two machines, one currently
+ located in Denmark and the other in the United States.
+ It is <emphasis>NOT</emphasis> a master site and should never be
+ used to mirror from. Lots of online documentation leads
+ <quote>interactive</quote>users to
+ <systemitem class="fqdomainname">ftp.FreeBSD.org</systemitem> so automated mirroring
+ systems should find a different machine to mirror from.
+ </para>
+ <para>
+ Additionally there exists a hierarchy of mirrors, which
+ is described in terms of <emphasis>tiers</emphasis>.
+ The master sites are not referred to but can be
+ described as <emphasis>Tier-0</emphasis>. Mirrors
+ that mirror from these sites can be considered
+ <emphasis>Tier-1</emphasis>, mirrors of <emphasis>Tier-1</emphasis>-mirrors,
+ are <emphasis>Tier-2</emphasis>, etc.
+ Official sites are encouraged to be of a low <emphasis>tier</emphasis>,
+ but the lower the tier the higher the requirements in
+ terms as described in <xref linkend="mirror-requirements"/>.
+ Also access to low-tier-mirrors may be restricted, and
+ access to master sites is definitely restricted.
+ The <emphasis>tier</emphasis>-hierarchy is not reflected
+ by DNS and generally not documented anywhere except
+ for the master sites. However, official mirrors with low numbers
+ like 1-4, are usually <emphasis>Tier-1</emphasis>
+ (this is just a rough hint, and there is no rule).
+ </para>
+ </sect2>
+ <sect2 xml:id="mirror-where-where">
+ <title>Ok, but where should I get the stuff now?</title>
+ <para>
+ Under no circumstances should you mirror from <systemitem class="fqdomainname">ftp.FreeBSD.org</systemitem>.
+ The short answer is: from the
+ site that is closest to you in Internet terms, or gives you
+ the fastest access.
+ </para>
+ <sect3 xml:id="mirror-where-simple">
+ <title>I just want to mirror from somewhere!</title>
+ <para>
+ If you have no special intentions or
+ requirements, the statement in <xref linkend="mirror-where-where"/>
+ applies. This means:
+ </para>
+ <procedure>
+ <step>
+ <para>
+ Look at available mirrors in your country.
+ The <link xlink:href="http://mirrorlist.FreeBSD.org/">FreeBSD
+ Mirror Database</link> can help you with this.
+ </para>
+ </step>
+ <step>
+ <para>
+ Check for those which provide fastest access
+ (number of hops, round-trip-times)
+ and offer the services you intend to
+ use (like <application>rsync</application>
+ or <application>CVSup</application>).
+ </para>
+ </step>
+ <step>
+ <para>
+ Contact the administrators of your chosen site stating your
+ request, and asking about their terms and
+ policies.
+ </para>
+ </step>
+ <step>
+ <para>
+ Set up your mirror as described above.
+ </para>
+ </step>
+ </procedure>
+ </sect3>
+ <sect3 xml:id="mirror-where-official">
+ <title>I am an official mirror, what is the right site for me?</title>
+ <para>
+ In general the description in <xref linkend="mirror-where-simple"/>
+ still applies. Of course you may want to put some
+ weight on the fact that your upstream should be of
+ a low tier.
+ There are some other considerations about <emphasis>official</emphasis>
+ mirrors that are described in <xref linkend="mirror-official"/>.
+ </para>
+ </sect3>
+ <sect3 xml:id="mirror-where-master">
+ <title>I want to access the master sites!</title>
+ <para>
+ If you have good reasons and good prerequisites,
+ you may want and get access to one of the
+ master sites. Access to these sites is
+ generally restricted, and there are special policies
+ for access. If you are already an <emphasis>official</emphasis>
+ mirror, this certainly helps you getting access.
+ In any other case make sure your country really needs another mirror.
+ If it already has three or more, ask the <quote>zone administrator</quote> (<email>hostmaster@CC.FreeBSD.org</email>) or &a.hubs; first.</para>
+
+ <para>
+ Whoever helped you become, an <emphasis>official</emphasis>
+ should have helped you gain access to an appropriate upstream
+ host, either one of the master sites or a suitable Tier-1
+ site. If not, you can send email to
+ <email>mirror-admin@FreeBSD.org</email> to request help with
+ that.
+ </para>
+ <para>
+ There are three master sites for the FTP fileset and
+ one for the CVS repository (the web pages and docs are
+ obtained from CVS, so there is no need for master).
+ </para>
+ <sect4 xml:id="mirror-where-master-ftp">
+ <title>ftp-master.FreeBSD.org</title>
+ <para>
+ This is the master site for the FTP fileset.
+ </para>
+ <para>
+ <systemitem>ftp-master.FreeBSD.org</systemitem> provides
+ <application>rsync</application> and <application>CVSup</application>
+ access, in addition to FTP.
+ Refer to <xref linkend="mirror-ftp-rsync"/> and
+ <xref linkend="mirror-ftp-cvsup"/> how to access
+ via these protocols.
+ </para>
+ <para>
+ Mirrors are also encouraged to allow <application>rsync</application>
+ access for the FTP contents, since they are
+ <emphasis>Tier-1</emphasis>-mirrors.
+ </para>
+ </sect4>
+ <sect4 xml:id="mirror-where-master-cvsup">
+ <title>cvsup-master.FreeBSD.org</title>
+ <para>
+ This is the master site for the CVS repository.
+ </para>
+ <para>
+ <systemitem>cvsup-master.FreeBSD.org</systemitem> provides
+ <application>CVSup</application> access only.
+ See <xref linkend="mirror-cvs-cvsup"/> for details.
+ </para>
+ <para>
+ To get access, you need to contact the &a.cvsup-master;.
+ Make sure you read the
+ <link xlink:href="http://people.FreeBSD.org/~jdp/cvsup-access/">FreeBSD CVSup Access Policy</link>
+ first!
+ </para>
+ <para>
+ Set up the required authentication by following
+ <link xlink:href="http://people.FreeBSD.org/~jdp/cvpasswd/">these
+ instructions</link>. Make sure you specify the server as
+ <systemitem>freefall.FreeBSD.org</systemitem> on the <command>cvpasswd</command>
+ command line, as described in this document,
+ even when you are contacting
+ <systemitem>cvsup-master.FreeBSD.org</systemitem>
+ </para>
+ </sect4>
+ </sect3>
+ </sect2>
+ </sect1>
+ <sect1 xml:id="mirror-official">
+ <title>Official Mirrors</title>
+ <para>
+ Official mirrors 站為具有下列條件的 mirror 站
+ <itemizedlist>
+ <listitem>
+ <para>
+ a) 有 <systemitem>FreeBSD.org</systemitem> DNS entry
+ (通常為 CNAME 紀錄)。
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ b) 被 FreeBSD 文件列為 offical mirror 站(像是 handbook)。
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ 除了以上述方式來分辨是否為 official mirrors 站之外,
+ Official mirrors 站不一定得為 <emphasis>Tier-1</emphasis>-mirrors 站。
+ 然而,只要是 <emphasis>Tier-1</emphasis>-mirror 站的話,就一定會是
+ official mirrors 站。
+ </para>
+ <sect2 xml:id="mirror-official-requirements">
+ <title>Special Requirements for official (tier-1) mirrors</title>
+ <para>
+ It is not so easy to state requirements for all
+ official mirrors, since the project is sort of
+ tolerant here. It is more easy to say,
+ what <emphasis>official tier-1 mirrors</emphasis>
+ are required to. All other official mirrors
+ can consider this a big <emphasis>should</emphasis>.
+ <note>
+ <para>
+ The following applies mainly to the FTP fileset,
+ since a CVS repository should always be mirrored
+ completely, and the web pages are a case of
+ its own.
+ </para>
+ </note>
+ </para>
+ <para>
+ Tier-1 mirrors are required to:
+ <itemizedlist>
+ <listitem><para>carry the complete fileset</para></listitem>
+ <listitem><para>allow access to other mirror sites</para></listitem>
+ <listitem><para>provide <application>FTP</application> and
+ <application>rsync</application> access</para></listitem>
+ </itemizedlist>
+
+ Furthermore, admins should be subscribed to the &a.hubs;.
+ See <link xlink:href="http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/eresources.html#ERESOURCES-MAIL">this link</link> for details, how to subscribe.
+ </para>
+ <important>
+ <para>It is <emphasis>very</emphasis> important for a hub administrator, especially
+ Tier-1 hub admins, to check the
+ <link xlink:href="http://www.FreeBSD.org/releng/">release schedule</link>
+ for the next FreeBSD release. This is important because it will tell you when the
+ next release is scheduled
+ to come out, and thus giving you time to prepare for the big spike of traffic which follows it.
+ </para>
+ <para>
+ It is also important that hub administrators try to keep their mirrors as up-to-date as
+ possible (again, even more crucial for Tier-1 mirrors). If Mirror1 does not update for a
+ while, lower tier mirrors will begin to mirror old data from Mirror1 and thus begins
+ a downward spiral... Keep your mirrors up to date!
+ </para>
+ </important>
+ </sect2>
+ <sect2 xml:id="mirror-official-become">
+ <title>How to become official then?</title>
+ <para>
+ An interesting question, especially, since the state
+ of being official comes with some benefits, like a much
+ higher bill from your ISP as more people will be using
+ your site. Also it may be a key requirement to get access
+ to a master site.
+ </para>
+ <para>
+ Before applying, please consider (again) if
+ another official mirror is really needed for
+ your region. Check first with your zone administrator (<email>hostmaster@CC.FreeBSD.org</email>) or, if that fails, ask on the &a.hubs;.
+ </para>
+ <para>Ok, here is how to do it:</para>
+ <procedure>
+ <step>
+ <para>
+ Get the mirror running in first place (maybe not
+ using a master site, yet).
+ </para>
+ </step>
+ <step>
+ <para>
+ <link xlink:href="http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/eresources.html#ERESOURCES-MAIL">Subscribe</link> to the &a.hubs;.
+ </para>
+ </step>
+ <step>
+ <para>
+ If everything works so far, contact the DNS administrator responsible
+ for your region/country, and ask for a DNS entry for your
+ site. The admin should able to be contacted via
+ <email>hostmaster@CC.FreeBSD.org</email>, where
+ <emphasis>CC</emphasis> is your country code/TLD.
+ Your DNS entry will be as described
+ in <xref linkend="mirror-where-organization"/>.
+ </para>
+ <para>
+ If there is no subdomain set up for your
+ country yet, you should contact
+ <email>mirror-admin@FreeBSD.org</email>,
+ or you can try the &a.hubs; first.
+ </para>
+ </step>
+ <step>
+ <para>
+ Whoever helps you get an official name should send email
+ to <email>mirror-admin@FreeBSD.org</email> so your site will be
+ added to the mirror list in the
+ <link xlink:href="http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook">FreeBSD
+ Handbook</link>.
+ </para>
+ </step>
+ </procedure>
+ <para>That is it.</para>
+ </sect2>
+ </sect1>
+ <sect1 xml:id="mirror-statpages">
+ <title>Some statistics from mirror sites</title>
+ <para>
+ Here are links to the stat pages of your favorite mirrors
+ (a.k.a. the only ones who feel like providing stats).
+ </para>
+ <sect2 xml:id="mirror-statpagesftp">
+ <title>FTP site statistics</title>
+ <itemizedlist>
+ <listitem>
+ <para>ftp.is.FreeBSD.org - <email>hostmaster@is.FreeBSD.org</email> -
+ <link xlink:href="http://www.rhnet.is/status/draupnir/draupnir.html">
+ (Bandwidth)</link> <link xlink:href="http://www.rhnet.is/status/ftp/ftp-notendur.html">(FTP
+ processes)</link> <link xlink:href="http://www.rhnet.is/status/ftp/http-notendur.html">(HTTP processes)
+ </link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>ftp.cz.FreeBSD.org - <email>cejkar@fit.vutbr.cz</email> -
+ <link xlink:href="http://www.cz.FreeBSD.org/stats/mrtg/net.html">(Bandwidth)</link>
+ <link xlink:href="http://www.freebsd.cz/stats/mrtg/ftpd.html">(FTP processes)</link>
+ <link xlink:href="http://www.freebsd.cz/stats/mrtg/rsyncd.html">(rsync processes)</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>ftp2.ru.FreeBSD.org - <email>mirror@macomnet.ru</email> -
+ <link xlink:href="http://mirror.macomnet.net/mrtg/mirror.macomnet.net_195.128.64.25.html">(Bandwidth)</link>
+ <link xlink:href="http://mirror.macomnet.net/mrtg/mirror.macomnet.net_proc.html">(HTTP and FTP users)</link>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2 xml:id="mirror-statpagescvsup">
+ <title>CVSup site stats</title>
+ <itemizedlist>
+ <listitem>
+ <para>cvsup[23456].jp.FreeBSD.org - <email>kuriyama@FreeBSD.org</email> - <link xlink:href="http://home.jp.FreeBSD.org/stats/mrtg/cvsup/">(CVSup processes)</link></para>
+ </listitem>
+ <listitem>
+ <para>cvsup.cz.FreeBSD.org - <email>cejkar@fit.vutbr.cz</email> -
+ <link xlink:href="http://www.freebsd.cz/stats/mrtg/cvsupd.html">(CVSup processes)</link></para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+</article>
diff --git a/zh_TW.UTF-8/articles/mailing-list-faq/Makefile b/zh_TW.UTF-8/articles/mailing-list-faq/Makefile
new file mode 100644
index 0000000000..53a873470a
--- /dev/null
+++ b/zh_TW.UTF-8/articles/mailing-list-faq/Makefile
@@ -0,0 +1,26 @@
+#
+# $FreeBSD$
+#
+# Article: Frequently Asked Questions About The FreeBSD Mailing Lists
+
+DOC?= article
+
+FORMATS?= html
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+WITH_ARTICLE_TOC?=YES
+
+#
+# SRCS lists the individual XML files that make up the document. Changes
+# to any of these files will force a rebuild
+#
+
+# XML content
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/mailing-list-faq/article.xml b/zh_TW.UTF-8/articles/mailing-list-faq/article.xml
new file mode 100644
index 0000000000..d85000e6e7
--- /dev/null
+++ b/zh_TW.UTF-8/articles/mailing-list-faq/article.xml
@@ -0,0 +1,416 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!-- $FreeBSD$ -->
+<!-- The FreeBSD Documentation Project -->
+<!-- FreeBSD Mailing Lists 常見問答集 -->
+<!-- Translate into Chinese by chinsan.tw@gmail.com -->
+<!-- English Version: 1.7 -->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>&os; Mailing Lists 常見問答集</title>
+
+
+ <authorgroup>
+ <author><personname><surname>The &os; Documentation Project</surname></personname></author>
+ </authorgroup>
+
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <holder>&os; 文件計畫</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>這是有關 &os; mailing lists 的 FAQ。如果您對協助本文件/翻譯計畫
+ 的進行有興趣的話,請寄 e-mail 到
+ &a.doc;。此外,隨時可從 <link xlink:href="http://www.FreeBSD.org/doc/en_US.ISO8859-1/articles/mailing-list-faq/index.html">
+ FreeBSD 網站</link> 拿到這份文件的最新版本。
+ 也可以利用 HTTP 來下載 <link xlink:href="article.html">HTML</link>
+ 文件,或是經由 <link xlink:href="ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/">
+ FreeBSD FTP 站</link> 下載純文字、&postscript;、或 PDF 版本的檔案。
+ 您也可以在這裡使用
+ <link xlink:href="&url.base;/search/search.html">搜尋 FAQ 資料</link>
+ 的功能。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="introduction">
+ <title>前言</title>
+
+ <para>如同其他 FAQs 一樣,本文主要目的是希望涵蓋在 &os; mailing
+ lists 上面的常見問題(當然,包括答案)。
+ 雖然,原本構想是希望能降低這些重複問題的網路流量,但如今已被公認 FAQs 也是相當好用的資源之一。</para>
+
+ <para>本文主要是描述社群之間所培養的一些禮儀(或默契),但本文本身並非『聖旨』般的權威。
+ 若發現本文內有任何技術瑕疵,或者是想建議可以增加哪些部分的話,請送 PR,或是 email 到 &a.doc;。謝囉!</para>
+
+ <qandaset>
+ <qandaentry>
+ <question xml:id="purpose">
+ <para>&os; mailing lists 的目的為何?</para>
+ </question>
+
+ <answer>
+ <para>&os; mailing lists 主要是提供 &os; 社群間的溝通管道,這裡有各式專題領域的探討,以及興趣交流。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="audience">
+ <para>&os; mailing lists 的參與者有哪些?</para>
+ </question>
+
+ <answer>
+ <para>這個問題,要看各個 list 的『版規(charter)』定位而有所不同。有些 lists 主要是 developers 在參與討論的;
+ 而有些則主要是幾乎整體 &os; 社群都可以隨意參與討論的。請看 <link xlink:href="http://lists.FreeBSD.org/mailman/listinfo">這份清單</link> 上面有目前所有 list 的摘要說明。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="participation-who">
+ <para>&os; mailing lists 對任何人都是開放參與的嗎?</para>
+ </question>
+
+ <answer>
+ <para>再重複一次,這要看各個 list 的『版規(charter)』定位而有所不同。
+ 請在發文前,先注意閱讀該 list 的『版規(charter)』,並遵守相關原則。
+ 如此一來,才會讓大家都能溝通更無礙。</para>
+
+ <para>如果看了上一個問答內的清單之後,還是不清楚要到哪個 list 去發問的話,
+ 那麼可以試著把問題丟到 freebsd-questions 看看(但請先看下面講的補充)。</para>
+
+ <para>請注意:習慣上所有 mailing lists 都是開放發表討論的,也不必得先成為訂閱會員才行。
+ 這是相當審慎的選擇,來讓參與 &os; 社群更輕鬆容易,並鼓勵互相分享彼此的想法。
+ 然而,由於過去有些人的濫用,有些 lists 現在開始限制參與討論的部分,以避免不必要的困擾。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="subscribe">
+ <para>要怎麼訂閱呢?</para>
+ </question>
+
+ <answer>
+ <para>可以用 <link xlink:href="http://lists.FreeBSD.org/mailman/listinfo">
+ Mailman 網頁介面</link> 來訂閱任何公開的 lists。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="unsubscribe">
+ <para>要怎麼退訂?</para>
+ </question>
+
+ <answer>
+ <para>一樣請用剛上面說的網頁介面,或者 mailing list 上面每封信結尾處都會有相關 URL 連結的指示說明。</para>
+
+ <para>千萬請不要直接寫信到這些公開的 mailing lists 說你要退訂。
+ 首先呢..因為本來就不是這樣退訂的,其次你會惹來眾怒而招來圍剿、筆戰。
+ 這是很典型的退訂錯誤示範,請不要這樣做。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="archives">
+ <para>可以找到舊信的資料庫嗎?</para>
+ </question>
+
+ <answer>
+ <para>嗯,有!可以在 <link xlink:href="http://docs.FreeBSD.org/mail/">這邊</link>
+ 找到相關的舊信資料庫(archive)。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="digest">
+ <para>mailing lists 可有摘要版呢?</para>
+ </question>
+
+ <answer>
+ <para>當然也有,請看 <link xlink:href="http://lists.FreeBSD.org/mailman/listinfo">
+ Mailman 網頁介面</link>。</para>
+ </answer>
+ </qandaentry>
+ </qandaset>
+ </sect1>
+
+ <sect1 xml:id="etiquette">
+ <title>Mailing List 的參與禮儀</title>
+
+ <para>在 mailing lists 上參與討論,就像在其他社群一樣,我們都需要一些溝通上的共識。
+ 發言請注重禮儀(或默契),切勿無的放矢。</para>
+
+ <qandaset>
+ <qandaentry>
+ <question xml:id="before-posting">
+ <para>在發文之前,有什麼注意事項呢?</para>
+ </question>
+
+ <answer>
+ <para>最重要的是你已經看了這篇文章,然而,若您對 &os; 不熟的話,
+ 可能需要先廣泛閱讀
+ <link xlink:href="&url.base;/docs/books.html">相關書籍及文章</link>
+ 來先熟悉這套作業系統和一些典故,尤其是其中的 <link xlink:href="&url.books.faq;/index.html">
+ &os; 常見問答集 (FAQ)</link> 文件,
+ <link xlink:href="&url.books.handbook;/index.html">
+ &os; 使用手冊(Handbook)</link>,
+ 以及相關文章:<link xlink:href="&url.articles.freebsd-questions;/article.html">
+ How to get best results from the FreeBSD-questions mailing list</link>、
+ <link xlink:href="&url.articles.explaining-bsd;/article.html">
+ Explaining BSD</link>、以及 <link xlink:href="&url.articles.new-users;/article.html">
+ &os; First Steps</link>。</para>
+
+ <para>此外,對上述文件內已有解答的部份又提出來問的話,會被認為是相當不禮貌的。
+ 這並不是因為這群志工是相當吝於回答的,而是一再被相同的問題不斷疲勞轟炸之後,所產生的挫折感很重。
+ 尤其是現成答案明明就在眼前,卻仍同樣問題滿天飛,這實在是...。
+ 請注意:這些 &os; 相關文件幾乎都是由一群無薪志工的好心成果,而他們也是人。</para>
+ </answer>
+
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="inappropriate">
+ <para>如何避免不當發文呢?</para>
+ </question>
+
+ <answer>
+ <itemizedlist>
+ <listitem>
+ <para>發文時,請務必遵守該 mailing list 的遊戲規則。</para>
+ </listitem>
+
+ <listitem>
+ <para>不要作人身攻擊。好的網路公民,應該要有更高的言行標準。</para>
+ </listitem>
+
+ <listitem>
+ <para>請不要試圖作 Spam 行為(廣告、轉貼多處等不請自來行為)。
+ 所有 mailing lists 都會積極禁止這些違規者,一旦有的話,那麼後果請自行負責。</para>
+ </listitem>
+ </itemizedlist>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="etiquette-posting">
+ <para>發文時,有什麼該注意的嗎?</para>
+ </question>
+
+ <answer>
+ <itemizedlist>
+ <listitem>
+ <para>發文時,請保持一行約 75 個字元就自動斷行,因為並不是每個看的人都有很炫的圖形介面(GUI)看信軟體。</para>
+ </listitem>
+
+ <listitem>
+ <para>請注意:事實上,網路頻寬並不是無限的。
+ 並非每個讀者的頻寬都很大,所以若想貼一些像是 <filename>config.log</filename>
+ 之類的設定檔內容,或是大量的 stack trace 紀錄,那麼請把它放在自己網站上,然後貼出該網址 URL 就行了。
+ 還有一件事,請記住,這些信件都會被舊信資料庫保存下來,所以這樣作會造成保存的資料庫會很快被塞到很大,
+ 甚至可能塞爆 Server 的硬碟空間。</para>
+ </listitem>
+
+ <listitem>
+ <para>文章是要讓人看得懂,所以請注意版面編排的可讀性,還有..
+ 千 萬 不 要 大 聲 嚷 叫!!!!! 這點可不只 &os; mailing lists 才需如此注意,
+ 請勿低估文章『基本編排』的重要性、連鎖效應。
+ 信中的表達方式通常就代表著別人眼中的你,若文章讓人看了很吃力(霧煞煞)、拼字錯誤百出、
+ 充滿語意或邏輯錯誤、或是文內充滿一堆驚嘆號,這會讓人對你印象觀感極差。</para>
+ </listitem>
+
+ <listitem>
+ <para>在一些特定的 list 場合,請用適當的語言來溝通。許多非英語系的mailing
+ lists 可以到
+ <link xlink:href="&url.base;/community/mailinglists.html">
+ 這邊</link> 查看看。</para>
+
+ <para>對於許多母語不是英語的人,我們都能諒解他們的苦楚,並且試著儘量多多包涵。
+ 英文非母語的人,我們會儘量不惡意批評拼字或文法錯誤之處。
+ &os; 在這方面,一直有相當優秀的紀錄,請讓我們繼續保持這傳統吧。</para>
+ </listitem>
+
+ <listitem>
+ <para>寫信時,請用相容標準的 Mail User Agent (MUA)程式。
+ <link xlink:href="http://www.lemis.com/email.html">不良的(或設定錯誤的)寄信程式</link>
+ 這裡列有許多信件格式的錯誤示範。以下是一些已知的寄信程式的不良示範:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>cc:Mail</para>
+ </listitem>
+
+ <listitem>
+ <para>(舊版的)&eudora;</para>
+ </listitem>
+
+ <listitem>
+ <para>exmh</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; Exchange</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; Internet Mail</para>
+ </listitem>
+
+ <listitem>
+ <para>&microsoft; &outlook;</para>
+ </listitem>
+
+ <listitem>
+ <para>(舊版的)&netscape;</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>如同上述所見,Microsoft 出的一堆寄信程式通常都是不相容標準格式的。
+ 請儘量改用 &unix; 上的寄信程式。若必須在 Microsoft 環境下使用寄信程式的話,
+ 請記得確認設定是否正確。請儘量不要用 <acronym>MIME</acronym> 格式:
+ 因為有一堆人都在濫用 <acronym>MIME</acronym> 信件格式。</para>
+ </listitem>
+
+ <listitem>
+ <para>請確認:時間與時區設定是否正確。
+ 這問題看起來有點蠢,因為你寄出的信還是會到達 mailing list 上,
+ 但是呢,每位 mailing lists 上的訂戶每天都會看數百封的信,
+ 他們通常會把信件以標題跟時間作為排序依據。
+ 若你的信沒有在第一篇正解之前就先出現的話,他們就會假設可能是漏收你這封信,
+ 然後就沒再去看你那封信了。</para>
+ </listitem>
+
+ <listitem>
+ <para>請提供程式出現的相關訊息,像是 &man.dmesg.8; 或者 console
+ messages 也就是通常會出現在 <filename>/var/log/messages</filename> 出現的。
+ 請不要用手打,因為這不僅很苦,而且也可能打錯字或亂掉原有格式。請直接把相關的 log 檔丟出來,
+ 或是用編輯器來剪裁、或是用滑鼠複製/貼上來完成。舉個例子,如果是要把像是 <command>dmesg</command>
+ 的程式訊息倒入到某個檔案去的話,那麼作法如下:</para>
+
+ <screen>&prompt.user; <userinput>dmesg &gt; /tmp/dmesg.out</userinput></screen>
+
+ <para>這樣子會把訊息送到 <filename>/tmp/dmesg.out</filename> 檔內。</para>
+ </listitem>
+
+ <listitem>
+ <para>在用滑鼠剪貼時,請注意是否有犯一些細節的剪貼壞習慣。
+ 尤其是像貼 <filename>Makefiles</filename> 之類檔案時,由於 <literal>tab</literal>
+ 鍵所打出來的分格,是屬於特殊字元。因此,在 <link xlink:href="&url.base;/support.html#gnats">
+ GNATS PR 資料庫</link> 上很常看到這類很常見的惱人問題:
+ <filename>Makefiles</filename> 內的 tab 經過剪貼後,變成『空白(white space)』
+ 或是困擾的 <literal>=3B</literal> escape sequence,這些會讓 committers 們十分不爽。</para>
+ </listitem>
+ </itemizedlist>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question xml:id="etiquette-replying">
+ <para>在 mailing lists 上回文的話,有什麼要特別注意的嗎?</para>
+ </question>
+
+ <answer>
+ <itemizedlist>
+ <listitem>
+ <para>請適當調整文章引言長度。回文時,引言部份請引『有談到的』部分為主,但請不要過與不及。
+ 應該保留涉及討論範圍的原文,這樣子才能讓沒看過前面文章的人知道是在講什麼,而非一頭霧水。</para>
+
+ <para>還有一點也很重要,原文若是幅度相當長的話,記得註明 "yes, I see this too"。</para>
+ </listitem>
+
+ <listitem>
+ <para>善用技巧來確認原文與自己寫的部份:
+ 通常會在原文的每行前面加上 <quote><literal>&gt; </literal></quote> 以作記號。
+ 請記得保留 <quote><literal>&gt; </literal></quote> 符號後面的空白,並且在原文以及你所寫的段落之間加上空行,
+ 以便閱讀。</para>
+ </listitem>
+
+ <listitem>
+ <para>請不要斷章取義、穿鑿附會:通常對原始文章『斷章取義』、『穿鑿附會』會讓大家很不爽,因為他們原意並非如此,卻被曲解。</para>
+ </listitem>
+
+ <listitem>
+ <para>回文時,不要寫在原文上面(<literal>top post</literal>)。
+ 這個意思是:若要回文時,請寫在原文下方,不要寫在原文上面,以免讓人有時空錯置的錯亂混淆。</para>
+ <!-- 注意:下面這是故意幽默效果的問答 -->
+ <itemizedlist>
+ <listitem>
+ <para>答: Because it reverses the logical flow of
+ conversation.</para>
+ </listitem>
+ <listitem>
+ <para>問: Why is top posting frowned upon?</para>
+ </listitem>
+ </itemizedlist>
+ <para>(感謝 Randy Bush 提供笑話)</para>
+ </listitem>
+ </itemizedlist>
+ </answer>
+ </qandaentry>
+ </qandaset>
+ </sect1>
+
+ <sect1 xml:id="recurring">
+ <title>Mailing Lists 上的重複性問題</title>
+
+ <para>在 mailing lists 上參與討論,就像在其他社群一樣,我們都需要一些溝通上的共識。
+ 許多 mailing lists 都會假設參與討論者都大致知道 FreeBSD 計劃的一些歷史淵源。
+ 尤其是社群的新手總是定期會不斷重複問類似問題。
+ 每個發文的人,都有責任來避免掉入這樣的惡性循環輪迴內。
+ 因此,應儘可能讓 mailing list 上能正常討論,而避免讓自己陷入筆戰泥沼。</para>
+
+ <para>要怎麼避免呢?最好的方法就是善用這些 <link xlink:href="http://docs.FreeBSD.org/mail/">
+ mailing list 舊信資料庫(archives)</link>,來瞭解相關背景。
+ 正由於這原因,所以 <link xlink:href="http://www.FreeBSD.org/search/search.html#mailinglists">
+ mailing list 搜尋介面</link> 就顯得非常好用。
+ (若這方法仍無法找到有用的答案,那麼請改用自己愛用的搜尋引擎吧)</para>
+
+ <para>透過這些舊信資料庫,不只可瞭解先前討論過哪些話題,也可以知道:是怎麼討論的、
+ 哪些人參與討論過、主要看的人又是哪些人。
+ 入境隨俗這些原則不只是 &os; mailing list 上才這樣,一樣可以適合其他地方。</para>
+
+ <para>archives 的內容無疑地相當廣泛,而且會有些問題不斷反覆出現,
+ 有時討論到後面總會離題。無論如何,在發問前的義務就是先做好功課,
+ 以避免這類的月經文惡性循環,尤其是令人反感的 <literal>bikeshed(打嘴砲)</literal>。</para>
+ </sect1>
+
+ <sect1 xml:id="bikeshed">
+ <title>什麼是 "Bikeshed" 呀?</title>
+ <para>單就字面上意思解釋的話,<literal>bikeshed</literal> 是指專門給腳踏車、機車之類的兩輪交通工具使用的遮雨棚,
+ 然而呢,在 &os; 這邊的說法卻有其他意思(帶有貶抑)指的是:
+ 某些特定話題的重複討論,尤其是指在 &os; 社群內絕不會有共識,且有爭議的話題。
+ (這字彙的起源在 <link xlink:href="&url.books.faq;/misc.html#BIKESHED-PAINTING">
+ 這份文件</link> 內有更多說明)。你只要在發信到任一 &os; mailing lists 之前,知道這個基本概念就行了。</para>
+
+ <para>一般來講,『bikeshed』是很容易產生許多波的筆戰與額外討論的爭議話題,如果事先不知道這些背景的話。</para>
+
+ <para>拜託,請幫個忙讓討論回歸正常,而不要只是到處打嘴砲而已。感恩!</para>
+ </sect1>
+
+ <sect1 xml:id="acknowledgments">
+ <title>致謝</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>&a.grog;</term>
+ <listitem>
+ <para><link xlink:href="&url.articles.freebsd-questions;/article.html">
+ How to get best results from the FreeBSD-questions mailing list</link> 一文的原作者,
+ 我們從他這文內獲得許多 mailing list 上的禮儀(或默契)寫作題材。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>&a.linimon;</term>
+ <listitem>
+ <para>本 FAQ 雛形的原作</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect1>
+
+</article>
diff --git a/zh_TW.UTF-8/articles/nanobsd/Makefile b/zh_TW.UTF-8/articles/nanobsd/Makefile
new file mode 100644
index 0000000000..38de994f6c
--- /dev/null
+++ b/zh_TW.UTF-8/articles/nanobsd/Makefile
@@ -0,0 +1,28 @@
+#
+# The FreeBSD Traditional Chinese Project
+#
+# Original Revision: 1.2
+# $FreeBSD$
+#
+# Article: Introduction to NanoBSD
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+# Images from the cross-document image library
+IMAGES_LIB= callouts/1.png
+IMAGES_LIB+= callouts/2.png
+IMAGES_LIB+= callouts/3.png
+IMAGES_LIB+= callouts/4.png
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/nanobsd/article.xml b/zh_TW.UTF-8/articles/nanobsd/article.xml
new file mode 100644
index 0000000000..44702eb5df
--- /dev/null
+++ b/zh_TW.UTF-8/articles/nanobsd/article.xml
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Traditional) Documentation Project
+
+ Original Revision: 1.1
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>NanoBSD 簡介</title>
+
+
+ <authorgroup>
+ <author><personname><firstname>Daniel</firstname><surname>Gerzo</surname></personname></author>
+ </authorgroup>
+
+ <copyright>
+ <year>2006</year>
+ <holder>The FreeBSD Documentation Project</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>這篇文件提供了關於 <application>NanoBSD</application> 工具的情報介紹,
+ 這工具可用來建立用於嵌入式環境應用程式的 &os; 系統映像檔,
+ 以便存放到 Compact Flash 卡(或隨身碟)。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="intro">
+ <title>NanoBSD 簡介</title>
+
+ <indexterm><primary>NanoBSD</primary></indexterm>
+
+ <para><application>NanoBSD</application> 是 &a.phk; 目前正在開發的一項工具。
+ 它可用來建立用於嵌入式環境應用程式的 &os; 系統映像檔,
+ 以便存放到 Compact Flash 卡(或隨身碟,mass storage medium)。</para>
+
+ <para>這一工具也可以用來自製安裝映像檔,
+ 以簡化俗稱為 <quote>嵌入式系統(computer appliances)</quote> 的系統安裝、維護工作。
+ 通常,每個嵌入式系統產品都有限定硬體和軟體,
+ 或者換言之,所有的應用程式都是預先裝好的。
+ 這些設備可以直接放到現有的網路中,而且(幾乎是)立即使用。</para>
+
+ <para><application>NanoBSD</application> 提供的功能包括:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>可以和 &os; 一樣使用 Ports 和 Packages &mdash;
+ 所有的應用程序都可以在 <application>NanoBSD</application> 中直接使用,
+ 而方式與 &os; 完全一樣。</para>
+ </listitem>
+
+ <listitem>
+ <para>功能絲毫未損 &mdash; 在 &os; 做的任何工作,都可以在
+ <application>NanoBSD</application> 中使用,
+ 除非您在建立 <application>NanoBSD</application> 映像檔時,
+ 有指定要拿掉它們。</para>
+ </listitem>
+
+ <listitem>
+ <para>所有東西在運行時都是唯讀的 &mdash; 可以安全地拔掉電源插頭。
+ 系統不正常關機的話,不用再跑 &man.fsck.8; 了。</para>
+ </listitem>
+
+ <listitem>
+ <para>可輕鬆編譯、自行打造 &mdash; 只需使用一個 shell script 和一個設定檔,
+ 您可以輕鬆依需求來量身訂做適用的映像檔。</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 xml:id="howto">
+ <title>如何使用 NanoBSD</title>
+
+ <sect2 xml:id="design">
+ <title>NanoBSD 的設計</title>
+
+ <para>一旦將映像檔存入嵌入式硬體,就可以用它來引導 <application>NanoBSD</application>
+ 了。 預設情況下,隨身碟會劃分為三部分:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>兩個映像檔分割區: <literal>code#1</literal>
+ 和 <literal>code#2</literal>。</para>
+ </listitem>
+
+ <listitem>
+ <para>一個設定檔分割區,在運行環境中,
+ 可以將其掛載(mount)到 <filename>/cfg</filename> 目錄下。</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>這些分割區,在預設情況下是以唯讀方式掛載。</para>
+
+ <para><filename>/etc</filename> 和
+ <filename>/var</filename> 目錄均為
+ &man.md.4;(malloc)磁碟。</para>
+
+ <para>設定檔的分割區則是在
+ <filename>/cfg</filename> 目錄。
+ 它包含了用於 <filename>/etc</filename>
+ 目錄的檔案,在啟動之後暫時以唯讀方式掛載。 因此,若想要重開機保留新的設定,
+ 那麼要記得從 <filename>/etc</filename> 把改過的檔案複製回
+ <filename>/cfg</filename> 目錄才行。</para>
+
+ <example>
+ <title>把修改過 <filename>/etc/resolv.conf</filename> 設定保存起來</title>
+
+ <screen>&prompt.root; <userinput>vi /etc/resolv.conf</userinput>
+[...]
+&prompt.root; <userinput>mount /cfg</userinput>
+&prompt.root; <userinput>cp /etc/resolv.conf /cfg</userinput>
+&prompt.root; <userinput>umount /cfg</userinput></screen>
+ </example>
+
+ <note>
+ <para>只有在系統啟動過程中,以及需要修改設定檔的時候,才需要掛載含有
+ <filename>/cfg</filename> 的那個分割區。</para>
+
+ <para>一直都掛載 <filename>/cfg</filename>
+ 不是一個好主意,特別是當您把 <application>NanoBSD</application>
+ 放在不適合進行大量寫入動作的分割區時
+ (比如:由於檔案系統的同步化會定期在系統碟內寫入資料)。</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>打造 NanoBSD 映像檔</title>
+
+ <para><application>NanoBSD</application> 映像檔是透過使用非常簡單的
+ <filename>nanobsd.sh</filename> shell script 來打造的,這個 script 可以在
+ <filename>/usr/src/tools/tools/nanobsd</filename>
+ 目錄中找到。 這個 script 建立的映像檔,可以用 &man.dd.1; 工具來複製到隨身碟上。</para>
+
+ <para>打造
+ <application>NanoBSD</application> 映像檔所需的指令是:</para>
+
+ <screen>&prompt.root; <userinput>cd /usr/src/tools/tools/nanobsd</userinput> <co xml:id="nbsd-cd"/>
+&prompt.root; <userinput>sh nanobsd.sh</userinput> <co xml:id="nbsd-sh"/>
+&prompt.root; <userinput>cd /usr/obj/nanobsd.full</userinput> <co xml:id="nbsd-cd2"/>
+&prompt.root; <userinput>dd if=_.disk.full of=/dev/da0 bs=64k</userinput> <co xml:id="nbsd-dd"/></screen>
+
+ <calloutlist>
+ <callout arearefs="nbsd-cd">
+ <para>進入 <application>NanoBSD</application> 打造 script 的主目錄。</para>
+ </callout>
+
+ <callout arearefs="nbsd-sh">
+ <para>開始打造過程。</para>
+ </callout>
+
+ <callout arearefs="nbsd-cd2">
+ <para>進入打造好的映像檔所在的目錄。</para>
+ </callout>
+
+ <callout arearefs="nbsd-dd">
+ <para>在隨身碟上安裝 <application>NanoBSD</application>。</para>
+ </callout>
+ </calloutlist>
+ </sect2>
+
+ <sect2>
+ <title>自行打造 NanoBSD 映像檔</title>
+
+ <para>這可能是 <application>NanoBSD</application> 最為重要,
+ 同時也是您最感興趣的功能。 同時,在開發
+ <application>NanoBSD</application> 應用程式時,這也是相當耗時的過程。</para>
+
+ <para>執行下面的指令將會
+ <filename>nanobsd.sh</filename> 讀取目前所在目錄的
+ <filename>myconf.nano</filename> 檔的設定:</para>
+
+ <screen>&prompt.root; <userinput>sh nanobsd.sh -c myconf.nano</userinput></screen>
+
+ <para>自行打造的流程,只需兩個步驟:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>自訂選項</para>
+ </listitem>
+
+ <listitem>
+ <para>自訂功能</para>
+ </listitem>
+ </itemizedlist>
+
+ <sect3>
+ <title>自訂選項</title>
+
+ <para>透過修改設定,可以設定用於
+ <application>NanoBSD</application> 打造過程中 <literal>buildworld</literal>
+ 和 <literal>installworld</literal> 階段的編譯、安裝選項,以及
+ <application>NanoBSD</application> 主要打造過程中的選項。
+ 透過使用這些選項可以削減系統的尺寸,使之能夠放入
+ 64 MB 的隨身碟。 您還可以進一步透過這些選項來削減 &os;,
+ 直到它只包含 kernel 以及兩三個 userland 檔案為止。</para>
+
+ <para>設定檔案中包含用以代替預設值的設定選項。簡介最重要的幾項設定如下:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>NANO_NAME</literal> &mdash; 本次打造的名稱(所建立工作目錄的名稱)。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>NANO_SRC</literal> &mdash; 用以編譯、打造映像檔的 source tree 的位置。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>NANO_KERNEL</literal> &mdash; 設定用來編譯的 kernel 設定檔檔名。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_BUILD</literal> &mdash; 用於
+ <literal>buildworld</literal> 打造階段的選項。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_INSTALL</literal> &mdash; 用於
+ <literal>installworld</literal> 打造階段的選項。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>CONF_WORLD</literal> &mdash; 用於
+ <literal>buildworld</literal> 和
+ <literal>installworld</literal> 這兩個打造階段的選項。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>FlashDevice</literal> &mdash; 定義所用的嵌入式硬體類型。
+ 詳情請參考 <filename>FlashDevice.sub</filename> 檔。</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>自訂功能</title>
+
+ <para>透過在設定檔案中使用 shell 函數,可以進一步微調
+ <application>NanoBSD</application>。 舉例說明一下自行打造函數的基本方式:</para>
+
+ <programlisting>cust_foo()(
+ echo "bar=topless" &gt; \
+ &dollar;{NANO_WORLDDIR}/etc/foo
+)
+customize_cmd cust_foo</programlisting>
+
+ <para>下面舉更實際點的例子,它會把預設的
+ <filename>/etc</filename> 目錄大小,從 5MB 調整為 30MB:</para>
+
+ <programlisting>cust_etc_size()(
+ cd &dollar;{NANO_WORLDDIR}/conf
+ echo 30000 &gt; default/etc/md_size
+)
+customize_cmd cust_etc_size</programlisting>
+
+ <para>除此之外,還有幾個預設的功能定義可以用來自訂:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>cust_comconsole</literal> &mdash; 在預設 VGA 顯示卡上停用 &man.getty.8;
+ (<filename>/dev/ttyv*</filename>)並啟用 serial port 的 COM1 以作為系統 console。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>cust_allow_ssh_root</literal> &mdash; 允許 &man.sshd.8;
+ 可以用 <systemitem class="username">root</systemitem> 帳號登入。</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>cust_install_files</literal> &mdash;
+ 從 <filename>nanobsd/Files</filename>
+ 目錄中安裝檔案,這包含一些實用的系統管理 script 。</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>設定檔案舉例</title>
+
+ <para>下面是用於自行打造的 <application>NanoBSD</application> 映像檔的完整例子:</para>
+
+ <programlisting>NANO_NAME=custom
+NANO_SRC=/usr/src
+NANO_KERNEL=MYKERNEL
+NANO_IMAGES=2
+
+CONF_BUILD='
+NO_KLDLOAD=YES
+NO_NETGRAPH=YES
+NO_PAM=YES
+'
+
+CONF_INSTALL='
+NO_ACPI=YES
+NO_BLUETOOTH=YES
+NO_CVS=YES
+NO_FORTRAN=YES
+NO_HTML=YES
+NO_LPR=YES
+NO_MAN=YES
+NO_SENDMAIL=YES
+NO_SHAREDOCS=YES
+NO_EXAMPLES=YES
+NO_INSTALLLIB=YES
+NO_CALENDAR=YES
+NO_MISC=YES
+NO_SHARE=YES
+'
+
+CONF_WORLD='
+NO_BIND=YES
+NO_MODULES=YES
+NO_KERBEROS=YES
+NO_GAMES=YES
+NO_RESCUE=YES
+NO_LOCALES=YES
+NO_SYSCONS=YES
+NO_INFO=YES
+'
+
+FlashDevice SanDisk 1G
+
+cust_nobeastie()(
+ touch &dollar;{NANO_WORLDDIR}/boot/loader.conf
+ echo "beastie_disable=\"YES\"" &gt;&gt; &dollar;{NANO_WORLDDIR}/boot/loader.conf
+)
+
+customize_cmd cust_comconsole
+customize_cmd cust_install_files
+customize_cmd cust_allow_ssh_root
+customize_cmd cust_nobeastie</programlisting>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>更新 NanoBSD</title>
+
+ <para>更新 <application>NanoBSD</application> 相對 &os; 而言較為簡單:</para>
+
+ <procedure>
+ <step>
+ <para>和之前一樣打造新的 <application>NanoBSD</application> 映像檔。</para>
+ </step>
+
+ <step>
+ <para>將新的映像檔放入正運行的
+ <application>NanoBSD</application> 中未用的分割區之一。</para>
+
+ <para>與之前最初安裝 <application>NanoBSD</application> 的步驟相比,
+ 這一步驟最重要的區別在於:這次不用 <filename>_.disk.full</filename> 檔(它包含整個磁碟的映像檔),
+ 而應安裝 <filename>_.disk.image</filename> 映像檔(這個檔案中,只包含一個系統分割區)。</para>
+ </step>
+
+ <step>
+ <para>重新啟動,並從新安裝的分割區中啟動系統。</para>
+ </step>
+
+ <step>
+ <para>如果一切順利的話,升級工作就完成了。</para>
+ </step>
+
+ <step>
+ <para>如果發生了任何問題,則可以從先前的分割區啟動
+ (其中包含了舊的、 可用的映像檔),來盡快恢復系統功能。
+ 接下來可以修正新編譯的版本中存在的問題,並重複前述步驟。</para>
+ </step>
+ </procedure>
+
+ <para>要在正在運行的
+ <application>NanoBSD</application> 系統中安裝新的映像檔,可以使用位於
+ <filename>/root</filename> 目錄的
+ <filename>updatep1</filename> 或
+ <filename>updatep2</filename> script ,
+ 實際上要用哪一個 script,則取決於正在運行的系統是位於哪個分割區而定。</para>
+
+ <para>隨時提供新 <application>NanoBSD</application> 映像檔所提供的服務,
+ 以及採用的傳輸方法的不同,您可以參考並使用下列三種方式之一:</para>
+
+ <sect3>
+ <title>使用 &man.ftp.1;</title>
+
+ <para>如果傳輸速度是第一要求的話,請採用下面例子:</para>
+
+ <screen>&prompt.root; <userinput>ftp myhost
+get _.disk.image "| sh updatep1"</userinput></screen>
+ </sect3>
+
+ <sect3>
+ <title>使用 &man.ssh.1;</title>
+
+ <para>如果想更安全的話,應參考下面例子:</para>
+
+ <screen>&prompt.root; <userinput>ssh myhost cat _.disk.image.gz | zcat | sh updatep1</userinput></screen>
+ </sect3>
+
+ <sect3>
+ <title>使用 &man.nc.1;</title>
+
+ <para>如果遠程主機既不提供 &man.ftp.1; 服務,也不提供 &man.sshd.8; 服務的話:</para>
+
+ <procedure>
+ <step>
+ <para>首先,在提供映像檔的主機上開啟 TCP listen,並讓它把映像檔傳給 client:</para>
+
+ <screen>myhost&prompt.root; <userinput>nc -l 2222 &lt; _.disk.image</userinput></screen>
+
+ <note>
+ <para>請確認您所使用的 port 沒有被防火牆阻止來自
+ <application>NanoBSD</application> client 的連線請求。</para>
+ </note>
+ </step>
+ <step>
+ <para>連到提供新映像檔服務的主機,並執行 <filename>updatep1</filename> 這支 script:</para>
+
+ <screen>&prompt.root; <userinput>nc myhost 2222 | sh updatep1</userinput></screen>
+ </step>
+ </procedure>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <index/>
+</article>
diff --git a/zh_TW.UTF-8/articles/pr-guidelines/Makefile b/zh_TW.UTF-8/articles/pr-guidelines/Makefile
new file mode 100644
index 0000000000..17e369ff2c
--- /dev/null
+++ b/zh_TW.UTF-8/articles/pr-guidelines/Makefile
@@ -0,0 +1,19 @@
+#
+# $FreeBSD$
+#
+# Article: Problem Report Handling Guidelines
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/pr-guidelines/article.xml b/zh_TW.UTF-8/articles/pr-guidelines/article.xml
new file mode 100644
index 0000000000..9a2bebcc23
--- /dev/null
+++ b/zh_TW.UTF-8/articles/pr-guidelines/article.xml
@@ -0,0 +1,875 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!-- $FreeBSD$ -->
+<!-- The FreeBSD Documentation Project -->
+<!-- Translate into Chinese by chinsan.tw@gmail.com -->
+<!-- English Version: 1.24 -->
+<!--
+ 問題回報(PR)的處理原則
+ The FreeBSD Project - http://www.FreeBSD.org
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <!-- :START of Article Metadata -->
+ <info><title>問題回報(PR)的處理原則</title>
+
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.opengroup;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>這篇文章主要在講:由 FreeBSD PR 維護小組所提出的一些 FreeBSD 問題回報(PR)
+ 建議,希望大家在弄 PR 時都能遵守。</para>
+ </abstract>
+
+ <authorgroup>
+ <author><personname><firstname>Dag-Erling</firstname><surname>Sm&oslash;rgrav</surname></personname></author>
+
+ <author><personname><firstname>Hiten</firstname><surname>Pandya</surname></personname></author>
+ </authorgroup>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+ </info>
+ <!-- :END of Article Metadata-->
+
+ <section xml:id="intro">
+ <title>前言</title>
+
+ <para>GNATS 是 FReeBSD 計劃所採用的一套專門管理錯誤(回報bug) 系統。
+ 由於對 FreeBSD 品質保證而言,是否能準確掌握各項錯誤回報與進度是十分重要的,
+ 因此,如何正確有效使用 GNATS 也就必須注意。</para>
+
+ <para>Access to GNATS is available to FreeBSD developers, as well as
+ to the wider community. 為了讓 GNATS 資料庫使用上儘量一致,於是就產生了怎麼處理像是:followup(回文)、關閉PR等的參考原則。</para>
+ </section>
+
+ <section xml:id="pr-lifecycle">
+ <title>問題回報(PR)的生命週期</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>首先,回報者(originator)以 &man.send-pr.1; 送出 PR,然後會收到一封確認信。</para>
+ </listitem>
+
+ <listitem>
+ <para>然後,committer 們就會有人(假設叫做 Joe)發掘有興趣的 PR 並將該 PR 指派給自己來處理。
+ 或者 bugbuster 會有人(假設叫做 Jane) 就會下決定:她覺得 Joe 比較適合處理,就將該 PR 指派(assign)給他</para>
+ </listitem>
+
+ <listitem>
+ <para>Joe 會先與有問題的回報者作些意見交流(以確定這問題有進入 audit 追蹤流程內)
+ 以及判斷問題點。
+ 然後再確定問題點有寫入 audit 追蹤流程之後,然後把該 PR 狀態設為
+ <quote>analyzed(已分析)</quote>。</para>
+ </listitem>
+
+ <listitem>
+ <para>Joe 開始徹夜找出問題解法,然後將 patch 送到 follow-up(回文用),並請回報者協助測試是否正常。
+ 然後,他就會將 PR 狀態設為 <quote>feedback</quote> 囉。</para>
+ </listitem>
+
+ <listitem>
+ <para>如此重複 analyzed、feedback 幾趟之後,直到 Joe 與回報者雙方都相當滿意 patch 結果,
+ 於是就會將 patch 給 commits 進入 <literal>-CURRENT</literal> (或者若 <literal>-CURRENT</literal>
+ 上面沒這問題的話,就直接送到 <literal>-STABLE</literal>),在 commit log 內要把相關 PR 寫上去
+ (同時回報者若有送完整或部分 patch 的話,就順便記載),然後,若沒什麼事的話,就開始準備 MFC 哩。
+ (譯註:MFC意指 Merged From CURRENT ,也就是把 <literal>-CURRENT</literal> 上的東西併入 <literal>-STABLE</literal>。</para>
+ </listitem>
+
+ <listitem>
+ <para>若該 patch 不需要 MFC 的話,Joe 就會關掉(close)該 PR 了。</para>
+ </listitem>
+
+ <listitem>
+ <para>若該 patch 需要 MFC 的話,Joe 會把 PR 狀態改為 <quote>patched(已修正)</quote>,
+ 直到已經 MFC 完畢,才會 close(關掉)。</para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <para>很多送出來的 PR 都很少附上問題的相關訊息,而有些則是相當複雜難搞,
+ 或只是提到部分表面問題而已;
+ 遇到這種情況時,是非常需要得到所有相關訊息以便解決問題。
+ 若遇到這種無解的問題或再次發生的話,就必須要 re-open(重新開啟) 該 PR,以待解決。</para>
+ </note>
+ <note>
+ <para>PR 上所附的 <quote>email address</quote> 可能因某些原因而無法收信時,遇到這種狀況,通常就是
+ followup 該 PR ,並(在 followup 時)請回報者重新提供可正常收信的 email address。
+ 當系統上的 mail 系統關閉或沒裝的時候,這通常是在使用 &man.send-pr.1; 的替代方案。</para>
+ </note>
+ </section>
+
+ <section xml:id="pr-states">
+ <title>問題回報(PR)的狀態</title>
+
+ <para>若 PR 有任何變化的話,請務必記得更新 PR 的『狀態(state)』。
+ 『狀態』應該要能正確反映該 PR 的目前進度才是。</para>
+
+ <example>
+ <title>以下是更改 PR 狀態的小例子:</title>
+
+ <para>當有可以修正問題的 PR 出現,而相關負責的 developer(s)
+ 也覺得這樣的修正可以接受,他們會 followup 該 PR,並將其狀態改為
+ <quote>feedback</quote>。同時,回報者應重新評估最終的修正結果,並回應:所回報的錯誤是否已成功修正。</para>
+ </example>
+
+ <para>每份 PR 通常會有下面這幾種狀態之一:</para>
+
+ <glosslist>
+ <glossentry>
+ <glossterm>open</glossterm>
+ <glossdef>
+ <para>PR 最初的狀態:這個問題被提出來,並在等待處理中。</para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>analyzed</glossterm>
+ <glossdef>
+ <para>已經開始處理這問題,並且有找到疑似解決的方法。</para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>feedback</glossterm>
+ <glossdef>
+ <para>需要回報者提供更詳細的相關資料,正如教學要因材施教,治病也要因人下藥,越多相關訊息,才能有最佳效果。</para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>patched</glossterm>
+ <glossdef>
+ <para>已經送相關 patch 了,但仍因某些原因(MFC,或來自回報者的確認結果異常)因此尚未完畢。</para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>suspended(暫緩)</glossterm>
+ <glossdef>
+ <para>因為沒附上相關訊息或參考資料,所以還沒辦法處理這問題。
+ This is a prime candidate for
+ somebody who is looking for a project to take on. If the
+ problem cannot be solved at all, it will be closed, rather
+ than suspended. The documentation project uses
+ <quote>suspended</quote> for <quote>wish-list</quote>
+ items that entail a significant amount of work which no one
+ currently has time for.</para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>closed</glossterm>
+ <glossdef>
+ <para>A problem report is closed when any changes have been
+ integrated, documented, and tested, or when fixing the
+ problem is abandoned.</para>
+ </glossdef>
+ </glossentry>
+ </glosslist>
+
+ <note>
+ <para>The <quote>patched</quote> state is directly related to
+ feedback, so you may go directly to <quote>closed</quote> state if
+ the originator cannot test the patch, and it works in your own testing.</para>
+ </note>
+ </section>
+
+ <section xml:id="pr-types">
+ <title>問題回報(PR)的種類</title>
+
+ <para>While handling problem reports, either as a developer who has
+ direct access to the GNATS database or as a contributor who
+ browses the database and submits followups with patches, comments,
+ suggestions or change requests, you will come across several
+ different types of PRs.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="pr-unassigned">PRs not yet assigned to anyone.</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="pr-assigned">PRs already assigned to someone.</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="pr-dups">重複的 PR</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="pr-stale">Stale PRs</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="pr-misfiled">Misfiled PRs</link></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The following sections describe what each different type of
+ PRs is used for, when a PR belongs to one of these types, and what
+ treatment each different type receives.</para>
+
+ <section xml:id="pr-unassigned">
+ <title>Unassigned PRs</title>
+
+ <para>When PRs arrive, they are initially assigned to a generic
+ (placeholder) assignee. These are always prepended with
+ <literal>freebsd-</literal>. The exact value for this default
+ depends on the category; in most cases, it corresponds to a
+ specific &os; mailing list. Here is the current list, with
+ the most common ones listed first:</para>
+
+ <table xml:id="default-assignees-common">
+ <title>Default Assignees &mdash; most common</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Type</entry>
+ <entry>Categories</entry>
+ <entry>Default Assignee</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>base system</entry>
+ <entry>bin, conf, gnu, kern, misc</entry>
+ <entry>freebsd-bugs</entry>
+ </row>
+
+ <row>
+ <entry>architecture-specific</entry>
+ <entry>alpha, i386, ia64, powerpc, sparc64</entry>
+ <entry>freebsd-<replaceable>arch</replaceable></entry>
+ </row>
+
+ <row>
+ <entry>ports collection</entry>
+ <entry>ports</entry>
+ <entry>freebsd-ports-bugs</entry>
+ </row>
+
+ <row>
+ <entry>documentation shipped with the system</entry>
+ <entry>docs</entry>
+ <entry>freebsd-doc</entry>
+ </row>
+
+ <row>
+ <entry>&os; web pages (not including docs)</entry>
+ <entry>www</entry>
+ <entry>freebsd-www</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table xml:id="default-assignees-other">
+ <title>Default Assignees &mdash; other</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Type</entry>
+ <entry>Categories</entry>
+ <entry>Default Assignee</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>advocacy efforts</entry>
+ <entry>advocacy</entry>
+ <entry>freebsd-advocacy</entry>
+ </row>
+
+ <row>
+ <entry>&java.virtual.machine; problems</entry>
+ <entry>java</entry>
+ <entry>freebsd-java</entry>
+ </row>
+
+ <row>
+ <entry>standards compliance</entry>
+ <entry>standards</entry>
+ <entry>freebsd-standards</entry>
+ </row>
+
+ <row>
+ <entry>threading libraries</entry>
+ <entry>threads</entry>
+ <entry>freebsd-threads</entry>
+ </row>
+
+ <row>
+ <entry>&man.usb.4; subsystem</entry>
+ <entry>usb</entry>
+ <entry>freebsd-usb</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Do not be surprised to find that the submitter of the
+ PR has assigned it to the wrong category. If you fix the
+ category, do not forget to fix the assignment as well.
+ (In particular, our submitters seem to have a hard time
+ understanding that just because their problem manifested
+ on an i386 system, that it might be generic to all of &os;,
+ and thus be more appropriate for <literal>kern</literal>.
+ The converse is also true, of course.)</para>
+
+ <para>Certain PRs may be reassigned away from these generic
+ assignees by anyone. For assignees which are mailing lists,
+ please use the long form when making the assignment (e.g.,
+ <literal>freebsd-foo</literal> instead of <literal>foo</literal>);
+ this will avoid duplicate emails sent to the mailing list.</para>
+
+ <note>
+ <para>Here is a sample list of such entities; it is probably
+ not complete. In some cases, entries that have the short form are
+ <emphasis>aliases</emphasis>, not mailing lists.</para>
+ </note>
+
+ <table xml:id="common-assignees-base">
+ <title>Common Assignees &mdash; base system</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Type</entry>
+ <entry>Suggested Category</entry>
+ <entry>Suggested Assignee</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>problem specific to the &arm; architecture</entry>
+ <entry>kern</entry>
+ <entry>freebsd-arm</entry>
+ </row>
+
+ <row>
+ <entry>problem specific to the &mips; architecture</entry>
+ <entry>kern</entry>
+ <entry>freebsd-mips</entry>
+ </row>
+
+ <row>
+ <entry>problem specific to the &powerpc; architecture</entry>
+ <entry>kern</entry>
+ <entry>freebsd-ppc</entry>
+ </row>
+
+ <row>
+ <entry>problem with Advanced Configuration and Power
+ Management (&man.acpi.4;)</entry>
+ <entry>kern</entry>
+ <entry>freebsd-acpi</entry>
+ </row>
+
+ <row>
+ <entry>problem with Asynchronous Transfer Mode (ATM)
+ drivers</entry>
+ <entry>kern</entry>
+ <entry>freebsd-atm</entry>
+ </row>
+
+ <row>
+ <entry>problem with &firewire; drivers</entry>
+ <entry>kern</entry>
+ <entry>freebsd-firewire</entry>
+ </row>
+
+ <row>
+ <entry>problem with the filesystem code</entry>
+ <entry>kern</entry>
+ <entry>freebsd-fs</entry>
+ </row>
+
+ <row>
+ <entry>problem with the &man.geom.4; subsystem</entry>
+ <entry>kern</entry>
+ <entry>freebsd-geom</entry>
+ </row>
+
+ <row>
+ <entry>problem with the &man.ipfw.4; subsystem</entry>
+ <entry>kern</entry>
+ <entry>freebsd-ipfw</entry>
+ </row>
+
+ <row>
+ <entry>problem with Integrated Services Digital Network
+ (ISDN) drivers</entry>
+ <entry>kern</entry>
+ <entry>freebsd-isdn</entry>
+ </row>
+
+ <row>
+ <entry>problem with &linux; or SVR4 emulation</entry>
+ <entry>kern</entry>
+ <entry>freebsd-emulation</entry>
+ </row>
+
+ <row>
+ <entry>problem with the networking stack</entry>
+ <entry>kern</entry>
+ <entry>freebsd-net</entry>
+ </row>
+
+ <row>
+ <entry>problem with PicoBSD</entry>
+ <entry>kern</entry>
+ <entry>freebsd-small</entry>
+ </row>
+
+ <row>
+ <entry>problem with the &man.pf.4; subsystem</entry>
+ <entry>kern</entry>
+ <entry>freebsd-pf</entry>
+ </row>
+
+ <row>
+ <entry>problem with the &man.scsi.4; subsystem</entry>
+ <entry>kern</entry>
+ <entry>freebsd-scsi</entry>
+ </row>
+
+ <row>
+ <entry>problem with the &man.sound.4; subsystem</entry>
+ <entry>kern</entry>
+ <entry>freebsd-multimedia</entry>
+ </row>
+
+ <row>
+ <entry>problem with &man.sysinstall.8;</entry>
+ <entry>bin</entry>
+ <entry>freebsd-qa</entry>
+ </row>
+
+ <row>
+ <entry>problem with the system startup scripts
+ (&man.rc.8;)</entry>
+ <entry>kern</entry>
+ <entry>freebsd-rc</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table xml:id="common-assignees-ports">
+ <title>Common Assignees &mdash; Ports Collection</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Type</entry>
+ <entry>Suggested Category</entry>
+ <entry>Suggested Assignee</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>problem with the ports framework
+ (<emphasis>not</emphasis> with an individual port!)</entry>
+ <entry>ports</entry>
+ <entry>portmgr</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by apache@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>apache</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by eclipse@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>freebsd-eclipse</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by gnome@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>gnome</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by haskell@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>haskell</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by java@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>freebsd-java</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by kde@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>kde</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by
+ openoffice@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>freebsd-openoffice</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by perl@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>perl</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by python@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>freebsd-python</entry>
+ </row>
+
+ <row>
+ <entry>port which is maintained by x11@FreeBSD.org</entry>
+ <entry>ports</entry>
+ <entry>freebsd-x11</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Ports PRs which have a maintainer who is a ports committer
+ may be reassigned by anyone (but note that not every &os;
+ committer is necessarily a ports committer, so you cannot
+ simply go by the email address alone.)
+ </para>
+
+ <para>For other PRs, please do not reassign them to individuals
+ (other than yourself) unless you are certain that the assignee
+ really wants to track the PR. This will help to avoid the
+ case where no one looks at fixing a particular problem
+ because everyone assumes that the assignee is already working
+ on it.</para>
+
+ </section>
+
+ <section xml:id="pr-assigned">
+ <title>Assigned PRs</title>
+
+ <para>If a PR has the <literal>responsible</literal> field set
+ to the username of a FreeBSD developer, it means that the PR
+ has been handed over to that particular person for further
+ work.</para>
+
+ <para>Assigned PRs should not be touched by anyone but the
+ assignee. If you have comments, submit a followup. If for
+ some reason you think the PR should change state or be
+ reassigned, send a message to the assignee. If the assignee
+ does not respond within two weeks, unassign the PR and do as
+ you please.</para>
+ </section>
+
+ <section xml:id="pr-dups">
+ <title>重複的 PR</title>
+
+ <para>If you find more than one PR that describe the same issue,
+ choose the one that contains the largest amount of useful
+ information and close the others, stating clearly the number
+ of the superseding PR. If several PRs contain non-overlapping
+ useful information, submit all the missing information to one
+ in a followup, including references to the others; then close
+ the other PRs (which are now completely superseded).</para>
+ </section>
+
+ <section xml:id="pr-stale">
+ <title>Stale PRs</title>
+
+ <para>A PR is considered stale if it has not been modified in more
+ than six months. Apply the following procedure to deal with
+ stale PRs:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>If the PR contains sufficient detail, try to reproduce
+ the problem in <literal>-CURRENT</literal> and
+ <literal>-STABLE</literal>. If you succeed, submit a
+ followup detailing your findings and try to find someone
+ to assign it to. Set the state to <quote>analyzed</quote>
+ if appropriate.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the PR describes an issue which you know is the
+ result of a usage error (incorrect configuration or
+ otherwise), submit a followup explaining what the
+ originator did wrong, then close the PR with the reason
+ <quote>User error</quote> or <quote>Configuration
+ error</quote>.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the PR describes an error which you know has been
+ corrected in both <literal>-CURRENT</literal> and
+ <literal>-STABLE</literal>, close it with a message
+ stating when it was fixed in each branch.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the PR describes an error which you know has been
+ corrected in <literal>-CURRENT</literal>, but not in
+ <literal>-STABLE</literal>, try to find out when the person
+ who corrected it is planning to MFC it, or try to find
+ someone else (maybe yourself?) to do it. Set the state to
+ <quote>feedback</quote> and assign it to whomever will do
+ the MFC.</para>
+ </listitem>
+
+ <listitem>
+ <para>In other cases, ask the originator to confirm if
+ the problem still exists in newer versions. If the
+ originator does not reply within a month, close the PR
+ with the notation <quote>Feedback timeout</quote>.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section xml:id="pr-misfiled">
+ <title>Misfiled PRs</title>
+
+ <para>GNATS is picky about the format of a submitted bug report.
+ This is why a lot of PRs end up being <quote>misfiled</quote> if
+ the submitter forgets to fill in a field or puts the wrong sort of
+ data in some of the PR fields. This section aims to provide most
+ of the necessary details for FreeBSD developers that can help them to
+ close or refile these PRs.</para>
+
+ <para>When GNATS cannot deduce what to do with a problem report
+ that reaches the database, it sets the responsible of the PR to
+ <literal>gnats-admin</literal> and files it under the
+ <literal>pending</literal> category. This is now a
+ <quote>misfiled</quote> PR and will not appear in bug report
+ listings, unless someone explicitly asks for a list of all the
+ misfiled PRs. If you have access to the FreeBSD cluster
+ machines, you can use <command>query-pr</command> to view a
+ listing of PRs that have been misfiled:</para>
+
+ <screen>&prompt.user; <userinput>query-pr -x -q -r gnats-admin</userinput>
+ 52458 gnats-ad open serious medium Re: declaration clash f
+ 52510 gnats-ad open serious medium Re: lots of sockets in
+ 52557 gnats-ad open serious medium
+ 52570 gnats-ad open serious medium Jigdo maintainer update</screen>
+
+ <para>Commonly PRs like the ones shown above are misfiled for one
+ of the following reasons:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>A followup to an existing PR, sent through email, has
+ the wrong format on its <literal>Subject:</literal>
+ header.</para>
+ </listitem>
+
+ <listitem>
+ <para>A submitter sent a Cc: to a mailing list and someone
+ followed up to that post instead of the email issued by
+ GNATS after processing. The email to the list will not
+ have the category/PRnumber tracking tag. (This is why we
+ discourage submitters from doing this exact thing.)</para>
+ </listitem>
+
+ <listitem>
+ <para>When completing the &man.send-pr.1; template, the submitter
+ forgot to set the category or class of the PR to a proper
+ value.</para>
+ </listitem>
+
+ <listitem>
+ <para>When completing the &man.send-pr.1; template, the submitter
+ set Confidential to <literal>yes</literal>. (Since we allow
+ anyone to mirror GNATS via <application>cvsup</application>,
+ our PRs are public information. Security alerts should
+ therefore not be sent via GNATS but instead via email to
+ the Security Team.)</para>
+ </listitem>
+
+ <listitem>
+ <para>It is not a real PR, but some random message sent to
+ <email>bug-followup@FreeBSD.org</email> or
+ <email>freebsd-gnats-submit@FreeBSD.org</email>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <section xml:id="pr-misfiled-followups">
+ <title>Followups misfiled as new PRs</title>
+
+ <para>The first category of misfiled PRs, the one with the wrong
+ subject header, is actually the one that requires the greatest
+ amount of work from developers. These are not real PRs,
+ describing separate problem reports. When a reply is received
+ for an existing PR at one of the addresses that GNATS
+ <quote>listens</quote> to for incoming messages, the subject
+ of the reply should always be of the form:</para>
+
+ <programlisting>Subject: Re: category/number: old synopsis text</programlisting>
+
+ <para>Most mailers will add the
+ <quote><literal>Re:&nbsp;</literal></quote> part when you
+ reply to the original mail message of a PR. The
+ <quote><literal>category/number:&nbsp;</literal></quote> part
+ is a GNATS-specific convention that you have to manually
+ insert to the subject of your followup reports.</para>
+
+ <para>Any FreeBSD developer, who has direct access to the GNATS
+ database, can periodically check for PRs of this sort and move
+ interesting bits of the misfiled PR into the audit trail of
+ the original PR (by posting a proper followup to a bug report
+ to the address &a.bugfollowup;). Then
+ the misfiled PR can be closed with a message similar
+ to:</para>
+
+ <programlisting>Your problem report was misfiled. Please use the format
+"Subject: category/number: original text" when following
+up to older, existing PRs. I've added the relevant bits
+from the body of this PR to kern/12345</programlisting>
+
+ <para>Searching with <command>query-pr</command> for the
+ original PR, of which a misfiled followup is a reply, is as
+ easy as running:</para>
+
+ <screen>&prompt.user; query-pr -q -y "some text"</screen>
+
+ <para>After you locate the original PR and the misfiled
+ followups, use the <option>-F</option> option of
+ <command>query-pr</command> to save the full text of all the
+ relevant PRs in a &unix; mailbox file, i.e.:</para>
+
+ <screen>&prompt.user; <userinput>query-pr -F 52458 52474 &gt; mbox</userinput></screen>
+
+ <para>Now you can use any mail user agent to view all the PRs
+ you saved in <filename>mbox</filename>. Copy the text of all
+ the misfiled PRs in a followup to the original PR and make
+ sure you include the proper <literal>Subject:</literal>
+ header. Then close the misfiled PRs. When you close the misfiled
+ PRs remember that the submitter receives a mail notification that
+ his PR changed state to <quote>closed</quote>. Make sure you
+ provide enough details in the log about the reason of this state
+ change. Typically something like the following is ok:</para>
+
+ <programlisting>Followup to ports/45364 misfiled as a new PR.
+This was misfiled because the subject did not have the format:
+
+ Re: ports/45364: ...</programlisting>
+
+ <para>This way the submitter of the misfiled PR will know what to
+ avoid the next time a followup to an existing PR is sent.</para>
+ </section>
+
+ <section xml:id="pr-misfiled-format">
+ <title>PRs misfiled because of missing fields</title>
+
+ <para>The second type of misfiled PRs is usually the result of a
+ submitter forgetting to fill all the necessary fields when
+ writing the original PR.</para>
+
+ <para>Missing or bogus <quote>category</quote> or
+ <quote>class</quote> fields can result in a misfiled report.
+ Developers can use &man.edit-pr.1; to change the category or
+ class of these misfiled PRs to a more appropriate value and
+ save the PR.</para>
+
+ <para>Another common cause of misfiled PRs because of formatting
+ issues is quoting, changes or removal of the
+ <command>send-pr</command> template, either by the user who
+ edits the template or by mailers which do strange things to
+ plain text messages. This does not happen a lot of the time,
+ but it can be fixed with <command>edit-pr</command> too; it
+ does require a bit of work from the developer who refiles the
+ PR, but it is relatively easy to do most of the time.</para>
+ </section>
+
+ <section xml:id="pr-misfiled-notpr">
+ <title>Misfiled PRs that are not really problem reports</title>
+
+ <para>Sometimes a user wants to submit a report for a problem
+ and sends a simple email message to GNATS. The GNATS scripts
+ will recognize bug reports that are formatted using the
+ &man.send-pr.1; template. They cannot parse any sort of email
+ though. This is why submissions of bug reports that are sent
+ to <email>freebsd-gnats-submit@FreeBSD.org</email> have to
+ follow the template of <command>send-pr</command>, but email
+ reports can be sent to &a.bugs;.</para>
+
+ <para>Developers that come across PRs that look like they should have
+ been posted to &a.bugs.name; or some other list should close the
+ PR, informing the submitter in their state-change log why this
+ is not really a PR and where the message should be posted.</para>
+
+ <para>The email addresses that GNATS listens to for incoming PRs
+ have been published as part of the FreeBSD documentation, have
+ been announced and listed on the web-site. This means that
+ spammers found them. Spam messages
+ that reach GNATS are promptly filed
+ under the <quote>pending</quote> category until someone looks
+ at them. Closing one of these with &man.edit-pr.1; is very
+ annoying though, because GNATS replies to the submitter and
+ the sender's address of spam mail is never valid these days.
+ Bounces will come back for each PR that is closed.</para>
+
+ <para>Currently, with the installation of some antispam filters
+ that check all submissions to the GNATS database, the amount
+ of spam that reaches the <quote>pending</quote> state is very
+ small.</para>
+
+ <para>All developers who have access to the FreeBSD.org cluster
+ machines are encouraged to check for misfiled PRs and immediately
+ close those that are spam mail. Whenever you close one of
+ these PRs, please do the following:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Set Category to <literal>junk</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Set Confidential to <literal>no</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Set Responsible to yourself (and not, e.g.,
+ <literal>freebsd-bugs</literal>, which merely
+ sends more mail).</para>
+ </listitem>
+
+ <listitem>
+ <para>Set State to <literal>closed</literal>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Junk PRs are not
+ backed up, so filing spam mail under this category makes it
+ obvious that we do not care to keep it around or waste disk
+ space for it. If you merely close them without changing the
+ category, they remain both in the master database and in
+ any copies of the database mirrored through
+ <application>cvsup</application>.</para>
+ </section>
+ </section>
+ </section>
+
+ <section xml:id="references">
+ <title>延伸閱讀</title>
+
+ <para>下面這是在寫、處理 PR 時,可以參考的資料。當然很明顯,這份清單仍須補充。</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link xlink:href="&url.articles.problem-reports;/article.html">How to
+ Write FreeBSD Problem Reports</link>&mdash;給 PR 回報者用的參考原則。</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</article>
diff --git a/zh_TW.UTF-8/articles/problem-reports/Makefile b/zh_TW.UTF-8/articles/problem-reports/Makefile
new file mode 100644
index 0000000000..ab12340558
--- /dev/null
+++ b/zh_TW.UTF-8/articles/problem-reports/Makefile
@@ -0,0 +1,19 @@
+#
+# $FreeBSD$
+#
+# Article: Writing FreeBSD Problem Reports
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?=gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/problem-reports/article.xml b/zh_TW.UTF-8/articles/problem-reports/article.xml
new file mode 100644
index 0000000000..ebacf3e366
--- /dev/null
+++ b/zh_TW.UTF-8/articles/problem-reports/article.xml
@@ -0,0 +1,1103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>Writing &os; Problem Reports</title>
+
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.cvsup;
+ &tm-attrib.ibm;
+ &tm-attrib.intel;
+ &tm-attrib.sparc;
+ &tm-attrib.sun;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <abstract>
+ <para>This article describes how to best formulate and submit a
+ problem report to the &os; Project.</para>
+ </abstract>
+
+ <authorgroup>
+ <author><personname><firstname>Dag-Erling</firstname><surname>Sm&oslash;rgrav</surname></personname><contrib>Contributed by </contrib></author>
+
+ <author><personname><firstname>Mark</firstname><surname>Linimon</surname></personname></author>
+ </authorgroup>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+ </info>
+
+ <indexterm><primary>problem reports</primary></indexterm>
+
+ <section xml:id="pr-intro">
+ <title>Introduction</title>
+
+ <para>One of the most frustrating experiences one can have as a
+ software user is to submit a problem report only to have it
+ summarily closed with a terse and unhelpful explanation like
+ <quote>not a bug</quote> or <quote>bogus PR</quote>. Similarly,
+ one of the most frustrating experiences as a software developer
+ is to be flooded with problem reports that are not really
+ problem reports but requests for support, or that contain little
+ or no information about what the problem is and how to reproduce
+ it.</para>
+
+ <para>This document attempts to describe how to write good problem
+ reports. What, you ask, is a good problem report? Well, to go
+ straight to the bottom line, a good problem report is one that
+ can be analyzed and dealt with swiftly, to the mutual
+ satisfaction of both user and developer.</para>
+
+ <para>Although the primary focus of this article is on &os;
+ problem reports, most of it should apply quite well to other
+ software projects.</para>
+
+ <para>Note that this article is organized thematically, not
+ chronologically, so you should read through the entire document
+ before submitting a problem report, rather than treat it as a
+ step-by-step tutorial.</para>
+ </section>
+
+ <section xml:id="pr-when">
+ <title>When to submit a problem report</title>
+
+ <para>There are many types of problems, and not all of them should
+ engender a problem report. Of course, nobody is perfect, and
+ there will be times when you are convinced you have found a bug
+ in a program when in fact you have misunderstood the syntax for
+ a command or made a typographical error in a configuration file
+ (though that in
+ itself may sometimes be indicative of poor documentation or poor
+ error handling in the application). There are still many cases
+ where submitting a problem report is clearly
+ <emphasis>not</emphasis> the right
+ course of action, and will only serve to frustrate you and the
+ developers. Conversely, there are cases where it might be
+ appropriate to submit a problem report about something else than
+ a bug&mdash;an enhancement or a feature request, for
+ instance.</para>
+
+ <para>So how do you determine what is a bug and what is not? As a
+ simple rule of thumb your problem is <emphasis>not</emphasis> a
+ bug if it can be expressed as a question (usually of the form
+ <quote>How do I do X?</quote> or <quote>Where can I find
+ Y?</quote>). It is not always quite so black and white, but the
+ question rule covers a large majority of cases. If you are looking
+ for an answer, consider posing your question to the
+ &a.questions;.</para>
+
+ <para>Some cases where it may be appropriate to submit a problem
+ report about something that is not a bug are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Requests for feature enhancements. It is generally a
+ good idea to air these on the mailing lists before
+ submitting a problem report.</para>
+ </listitem>
+
+ <listitem>
+ <para>Notification of updates to externally maintained
+ software (mainly ports, but also externally maintained base
+ system components such as BIND or various GNU
+ utilities).</para>
+
+ <para>For unmaintained ports (<varname>MAINTAINER</varname> contains
+ <literal>ports@FreeBSD.org</literal>), such update notifications
+ might get picked up by an interested
+ committer, or you might be asked to provide a patch to update
+ the port; providing it upfront will greatly improve your chances
+ that the port will get updated in a timely manner.</para>
+
+ <para>If the port is maintained, PRs announcing new upstream releases
+ are usually not very useful since they generate supplementary work
+ for the committers, and the maintainer likely knows already there is
+ a new version, they have probably worked with the developers on it,
+ they are probably testing to see there is no regression, etc.</para>
+
+ <para>In either case, following the process described in <link xlink:href="&url.books.porters-handbook;/port-upgrading.html">Porter's
+ Handbook</link> will yield the best results.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>A bug that can not be reproduced can rarely be
+ fixed. If the bug only occurred once and you can not reproduce
+ it, and it does not seem to happen to anybody else, chances are
+ none of the developers will be able to reproduce it or figure
+ out what is wrong. That does not mean it did not happen, but it
+ does mean that the chances of your problem report ever leading
+ to a bug fix are very slim. To make matters worse, often
+ these kinds of bugs are actually caused by failing hard drives
+ or overheating processors &mdash; you should always try to rule
+ out these causes, whenever possible, before submitting a PR.</para>
+
+ <para>Next, to decide to whom you should file your problem
+ report, you need to understand that the software that makes
+ up &os; is composed of several different elements:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Code in the base system that is written and maintained
+ by &os; contributors, such as the kernel, the C library,
+ and the device drivers (categorized as <literal>kern</literal>);
+ the binary utilities (<literal>bin</literal>); the manual
+ pages and documentation (<literal>docs</literal>); and
+ the web pages (<literal>www</literal>). All bugs in
+ these areas should be reported to the &os; developers.</para>
+ </listitem>
+
+ <listitem>
+ <para>Code in the base system that is written and maintained
+ by others, and imported into &os; and adapted. Examples
+ include <application>bind</application>, &man.gcc.1;, and
+ &man.sendmail.8;. Most bugs in these areas should be reported
+ to the &os; developers; but in some cases they may need to be
+ reported to the original authors instead if the problems are
+ not &os;-specific. Usually these bugs will fall under either
+ the <literal>bin</literal> or <literal>gnu</literal>
+ categories.</para>
+ </listitem>
+
+ <listitem>
+ <para>Individual applications that are not in the base system
+ but are instead part of the &os; Ports Collection (category
+ <literal>ports</literal>). Most of these applications are
+ not written by &os; developers; what &os; provides is merely
+ a framework for installing the application. Therefore, you
+ should only report a problem to the &os; developers when you
+ believe the problem is &os;-specific; otherwise, you should
+ report it to the authors of the software.</para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>Then you should ascertain whether or not the problem is
+ timely. There are few things
+ that will annoy a developer more than receiving a problem report
+ about a bug she has already fixed.</para>
+
+ <para>If the problem is in the base system, you should first read
+ the FAQ section on
+ <link xlink:href="&url.books.faq;/introduction.html#LATEST-VERSION">
+ &os; versions</link>, if you are not already familiar with
+ the topic. It is not possible for &os; to fix problems in
+ anything other than certain recent branches of the base system,
+ so filing a bug report about an older version will probably
+ only result in a developer advising you to upgrade to a
+ supported version to see if the problem still recurs. The
+ Security Officer team maintains the
+ <link xlink:href="http://www.freebsd.org/security/">list of supported
+ versions</link>.</para>
+
+ <para>If the problem is in a port, note that you must first
+ upgrade to the latest version of the Ports Collection and see
+ if the problem still applies. Due to the rapid pace of changes
+ in these applications, it is infeasible for &os; to support
+ anything other than the absolute latest versions, and problems
+ with older version of applications simply cannot be fixed.</para>
+ </section>
+
+ <section xml:id="pr-prep">
+ <title>Preparations</title>
+
+ <para>A good rule to follow is to always do a background search
+ before submitting a problem report. Maybe your problem has
+ already been reported; maybe it is being discussed on the
+ mailing lists, or recently was; it may even already be fixed in
+ a newer version than what you are running. You should therefore
+ check all the obvious places before submitting your problem
+ report. For &os;, this means:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The &os;
+ <link xlink:href="&url.books.faq;/index.html">Frequently Asked
+ Questions</link> (FAQ) list.
+ The FAQ attempts to provide answers for a wide range of questions,
+ such as those concerning
+ <link xlink:href="&url.books.faq;/hardware.html">hardware
+ compatibility</link>,
+ <link xlink:href="&url.books.faq;/applications.html">user
+ applications</link>,
+ and <link xlink:href="&url.books.faq;/kernelconfig.html">kernel
+ configuration</link>.</para>
+ </listitem>
+
+ <listitem>
+ <para>The
+ <link xlink:href="&url.books.handbook;/eresources.html#ERESOURCES-MAIL">mailing
+ lists</link>&mdash;if you are not subscribed, use
+ <link xlink:href="http://www.FreeBSD.org/search/search.html#mailinglists">the
+ searchable archives</link> on the &os; web site. If your
+ problem has not been discussed on the lists, you might try
+ posting a message about it and waiting a few days to see if
+ someone can spot something you have overlooked.</para>
+ </listitem>
+
+ <listitem>
+ <para>Optionally, the entire web&mdash;use your favorite
+ search engine to locate any references to your problem. You
+ may even get hits from archived mailing lists or newsgroups
+ you did not know of or had not thought to search
+ through.</para>
+ </listitem>
+
+ <listitem>
+ <para>Next, the searchable
+ <link xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query">
+ &os; PR database</link> (GNATS). Unless your problem
+ is recent or obscure, there is a fair chance it has already
+ been reported.</para>
+ </listitem>
+
+ <listitem>
+ <para>Most importantly, you should attempt to see if existing
+ documentation in the source base addresses your problem.</para>
+
+ <para>For the base &os; code, you should
+ carefully study the contents of the
+ <filename>/usr/src/UPDATING</filename> file on your system
+ or its latest version at
+ <uri xlink:href="http://www.FreeBSD.org/cgi/cvsweb.cgi/src/UPDATING">http://www.FreeBSD.org/cgi/cvsweb.cgi/src/UPDATING</uri>.
+ (This is vital information
+ if you are upgrading from one version to
+ another&mdash;especially if you are upgrading to the
+ &os.current; branch).</para>
+
+ <para>However, if the problem is in something that was installed
+ as a part of the &os; Ports Collection, you should refer to
+ <filename>/usr/ports/UPDATING</filename> (for individual ports)
+ or <filename>/usr/ports/CHANGES</filename> (for changes
+ that affect the entire Ports Collection).
+ <uri xlink:href="http://www.FreeBSD.org/cgi/cvsweb.cgi/ports/UPDATING">http://www.FreeBSD.org/cgi/cvsweb.cgi/ports/UPDATING</uri>
+ and
+ <uri xlink:href="http://www.FreeBSD.org/cgi/cvsweb.cgi/ports/CHANGES">http://www.FreeBSD.org/cgi/cvsweb.cgi/ports/CHANGES</uri>
+ are also available via CVSweb.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section xml:id="pr-writing">
+ <title>Writing the problem report</title>
+
+ <para>Now that you have decided that your issue merits a problem
+ report, and that it is a &os; problem, it is time to write
+ the actual problem report. Before we get into the mechanics
+ of the program used to generate and submit PRs, here are some
+ tips and tricks to help make sure that your PR will be most
+ effective.</para>
+
+ <section>
+ <title>Tips and tricks for writing a good problem report</title>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Do not leave the <quote>Synopsis</quote>
+ line empty.</emphasis> The PRs go both onto a mailing list
+ that goes all over the world (where the <quote>Synopsis</quote>
+ is used
+ for the <literal>Subject:</literal> line), but also into a
+ database. Anyone who comes along later and browses the
+ database by synopsis, and finds a PR with a blank subject
+ line, tends just to skip over it. Remember that PRs stay
+ in this database until they are closed by someone; an
+ anonymous one will usually just disappear in the
+ noise.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Avoid using a weak <quote>Synopsis</quote>
+ line.</emphasis> You should not assume that anyone reading
+ your PR has any context for your submission, so the more
+ you provide, the better. For instance, what part of the
+ system does the problem apply to? Do you only see the
+ problem while installing, or while running? To
+ illustrate, instead of <literal>Synopsis: portupgrade is
+ broken</literal>, see how much more informative this
+ seems: <literal>Synopsis: port sysutils/portupgrade
+ coredumps on -current</literal>. (In the case of ports,
+ it is especially helpful to have both the category and
+ portname in the <quote>Synopsis</quote> line.)</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>If you have a patch, say so.</emphasis>
+ A PR with a patch included is much more likely to be
+ looked at than one without. If you are including one,
+ put the string <literal>[patch]</literal> at the
+ beginning of the <quote>Synopsis</quote>. (Although it is
+ not mandatory to use that exact string, by convention,
+ that is the one that is used.)</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>If you are a maintainer, say so.</emphasis>
+ If you are maintaining a part of the source code (for
+ instance, a port), you might consider adding the string
+ <literal>[maintainer update]</literal> at the beginning of
+ your synopsis line, and you definitely should set the
+ <quote>Class</quote> of
+ your PR to <literal>maintainer-update</literal>. This way
+ any committer that handles your PR will not have to check.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Be specific.</emphasis>
+ The more information you supply about what problem you
+ are having, the better your chance of getting a response.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Include the version of &os; you are running (there
+ is a place to put that, see below) and on which architecture.
+ You should include whether you are running from a release
+ (e.g. from a CDROM or download), or from
+ a system maintained by &man.cvsup.1; (and, if so, how
+ recently you updated). If you are tracking the
+ &os.current; branch, that is the very first thing someone
+ will ask, because fixes (especially for high-profile
+ problems) tend to get committed very quickly, and
+ &os.current; users are expected to keep up.</para>
+ </listitem>
+
+ <listitem>
+ <para>Include which global options you have specified in
+ your <filename>make.conf</filename>. Note: specifying
+ <literal>-O2</literal> and above to &man.gcc.1; is
+ known to be buggy in many situations. While the
+ &os; developers will accept patches, they are
+ generally unwilling to investigate such issues due
+ to simple lack of time and volunteers, and may
+ instead respond that this just is not supported.</para>
+ </listitem>
+
+ <listitem>
+ <para>If this is a kernel problem, then be prepared to
+ supply the following information. (You do not
+ have to include these by default, which only tends to
+ fill up the database, but you should include excerpts
+ that you think might be relevant):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>your kernel configuration (including which
+ hardware devices you have installed)</para>
+ </listitem>
+ <listitem>
+ <para>whether or not you have debugging options enabled
+ (such as <literal>WITNESS</literal>), and if so,
+ whether the problem persists when you change the
+ sense of that option</para>
+ </listitem>
+ <listitem>
+ <para>a backtrace, if one was generated</para>
+ </listitem>
+ <listitem>
+ <para>the fact that you have read
+ <filename>src/UPDATING</filename> and that your problem
+ is not listed there (someone is guaranteed to ask)</para>
+ </listitem>
+ <listitem>
+ <para>whether or not you can run any other kernel as
+ a fallback (this is to rule out hardware-related
+ issues such as failing disks and overheating CPUs,
+ which can masquerade as kernel problems)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>If this is a ports problem, then be prepared to
+ supply the following information. (You do not
+ have to include these by default, which only tends to
+ fill up the database, but you should include excerpts
+ that you think might be relevant):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>which ports you have installed</para>
+ </listitem>
+ <listitem>
+ <para>any environment variables that override the
+ defaults in <filename>bsd.port.mk</filename>, such
+ as <varname>PORTSDIR</varname></para>
+ </listitem>
+ <listitem>
+ <para>the fact that you have read
+ <filename>ports/UPDATING</filename> and that your problem
+ is not listed there (someone is guaranteed to ask)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ </itemizedlist>
+
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Avoid vague requests for features.</emphasis>
+ PRs of the form <quote>someone should really implement something
+ that does so-and-so</quote> are less likely to get results than
+ very specific requests. Remember, the source is available
+ to everyone, so if you want a feature, the best way to
+ ensure it being included is to get to work! Also consider
+ the fact that many things like this would make a better
+ topic for discussion on <literal>freebsd-questions</literal>
+ than an entry in the PR database, as discussed above.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Make sure no one else has already submitted
+ a similar PR.</emphasis> Although this has already been
+ mentioned above, it bears repeating here. It only take a
+ minute or two to use the web-based search engine at
+ <uri xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query">http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query</uri>.
+ (Of course, everyone is guilty of forgetting to do this
+ now and then.)</para> </listitem>
+
+ <listitem>
+ <para><emphasis>Avoid controversial requests.</emphasis>
+ If your PR addresses an area that has been controversial
+ in the past, you should probably be prepared to not only
+ offer patches, but also justification for why the patches
+ are <quote>The Right Thing To Do</quote>. As noted above,
+ a careful search of the mailing lists using the archives
+ at <uri xlink:href="http://www.FreeBSD.org/search/search.html#mailinglists">http://www.FreeBSD.org/search/search.html#mailinglists</uri>
+ is always good preparation.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Be polite.</emphasis>
+ Almost anyone who would potentially work on your PR is a
+ volunteer. No one likes to be told that they have to do
+ something when they are already doing it for some
+ motivation other than monetary gain. This is a good thing
+ to keep in mind at all times on Open Source
+ projects.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Before you begin</title>
+
+ <para>If you are using the &man.send-pr.1; program, make sure your
+ <envar>VISUAL</envar> (or <envar>EDITOR</envar> if
+ <envar>VISUAL</envar> is not set) environment variable is set
+ to something sensible.</para>
+
+ <para>You should also make sure that mail delivery works fine.
+ &man.send-pr.1; uses mail messages for the submission and
+ tracking of problem reports. If you cannot post mail messages
+ from the machine you are running &man.send-pr.1; on, your
+ problem report will not reach the GNATS database. For details
+ on the setup of mail on &os;, see the <quote>Electronic
+ Mail</quote> chapter of the &os; Handbook at
+ <uri xlink:href="http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mail.html">http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mail.html</uri>.</para>
+
+ <para>Make sure that your mailer will not mangle the message on
+ its way to GNATS. In particular, if your mailer automatically
+ breaks lines, changes tabs to spaces, or escapes newline
+ characters, any patch that you submit will be rendered
+ unusable. For the text sections, however, we request that
+ you insert manual linebreaks somewhere around 70 characters,
+ so that the web display of the PR will be readable.</para>
+
+ <para>Similar considerations apply if you are using the web-based
+ PR submittal form instead of &man.send-pr.1;. Note that
+ cut-and-paste operations can have their own side-effects on
+ text formatting. In certain cases it may be necessary to use
+ &man.uuencode.1; to ensure that patches arrive unmodified.</para>
+
+ <para>Finally, if your submission will be lengthy, you should
+ to prepare your work offline so that nothing will be lost in
+ case there is a problem submitting it. This can be an especial
+ problem with the web form.</para>
+ </section>
+
+ <section>
+ <title>Attaching patches or files</title>
+
+ <para>The following applies to submitting PRs via email:</para>
+
+ <para>The &man.send-pr.1; program has provisions for attaching
+ files to a problem report. You can attach as many files as
+ you want provided that each has a unique base name (i.e. the
+ name of the file proper, without the path). Just use the
+ <option>-a</option> command-line option to specify the names
+ of the files you wish to attach:</para>
+
+<screen>&prompt.user; <userinput>send-pr -a /var/run/dmesg -a /tmp/errors</userinput></screen>
+
+ <para>Do not worry about binary files, they will be automatically
+ encoded so as not to upset your mail agent.</para>
+
+ <para>If you attach a patch, make sure you use the
+ <option>-c</option> or <option>-u</option> option to
+ &man.diff.1; to create a context or unified diff (unified is
+ preferred), and make
+ sure to specify the exact CVS revision numbers of the files
+ you modified so the developers who read your report will be
+ able to apply them easily. For problems with the kernel or the
+ base utilities, a patch against &os.current; (the HEAD
+ CVS branch) is preferred since all new code should be applied
+ and tested there first. After appropriate or substantial testing
+ has been done, the code will be merged/migrated to the &os.stable;
+ branch.</para>
+
+ <para>If you attach a patch inline, instead of as an attachment,
+ note that the most common problem by far is the tendency of some
+ email programs to render tabs as spaces, which will completely
+ ruin anything intended to be part of a Makefile.</para>
+
+ <para>Do not send patches as attachments using
+ <command>Content-Transfer-Encoding: quoted-printable</command>.
+ These will perform character escaping and the entire patch
+ will be useless.</para>
+
+ <para>Also note that while including small patches in a PR is
+ generally all right&mdash;particularly when they fix the problem
+ described in the PR&mdash;large patches and especially new code
+ which may require substantial review before committing should
+ be placed on a web or ftp server, and the URL should be
+ included in the PR instead of the patch. Patches in email
+ tend to get mangled, especially when GNATS is involved, and
+ the larger the patch, the harder it will be for interested
+ parties to unmangle it. Also, posting a patch on the web
+ allows you to modify it without having to resubmit the entire
+ patch in a followup to the original PR. Finally, large
+ patches simply increase the size of the database, since
+ closed PRs are not actually deleted but instead kept and
+ simply marked as <literal>closed</literal>.</para>
+
+ <para>You should also take note that unless you explicitly
+ specify otherwise in your PR or in the patch itself, any
+ patches you submit will be assumed to be licensed under the
+ same terms as the original file you modified.</para>
+ </section>
+
+ <section>
+ <title>Filling out the template</title>
+
+ <para>The next section applies to the email method only:</para>
+
+ <para>When you run &man.send-pr.1;, you are presented with a
+ template. The template consists of a list of fields, some of
+ which are pre-filled, and some of which have comments explaining
+ their purpose or listing acceptable values. Do not worry
+ about the comments; they will be removed automatically if you
+ do not modify them or remove them yourself.</para>
+
+ <para>At the top of the template, below the
+ <literal>SEND-PR:</literal> lines, are the email headers. You
+ do not normally need to modify these, unless you are sending
+ the problem report from a machine or account that can send but
+ not receive mail, in which case you will want to set the
+ <literal>From:</literal> and <literal>Reply-To:</literal> to
+ your real email address. You may also want to send yourself
+ (or someone else) a carbon copy of the problem report by
+ adding one or more email addresses to the
+ <literal>Cc:</literal> header.</para>
+
+ <para>In the email template you will find the following two
+ single-line fields:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Submitter-Id:</emphasis> Do not change this.
+ The default value of <literal>current-users</literal> is
+ correct, even if you run &os.stable;.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Confidential:</emphasis> This is prefilled
+ to <literal>no</literal>. Changing it makes no sense as
+ there is no such thing as a confidential &os; problem
+ report&mdash;the PR database is distributed worldwide by
+ <application>CVSup</application>.</para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>The next section describes fields that are common to both
+ the email interface and the web interface:</para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para><emphasis>Originator:</emphasis>
+ Please specify your real name, optionally followed
+ by your email address in angle brackets.
+ In the email interface, this is normally
+ prefilled with the <literal>gecos</literal> field of the
+ currently logged-in
+ user.</para>
+
+ <note>
+ <para>The email address you use will become public information
+ and may become available to spammers. You should either
+ have spam handling procedures in place, or use a temporary
+ email account. However, please note that if you do not
+ use a valid email account at all, we will not be able to
+ ask you questions about your PR.</para>
+ </note>
+
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Organization:</emphasis> Whatever you feel
+ like. This field is not used for anything
+ significant.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Synopsis:</emphasis> Fill this out with a
+ short and accurate description of the problem. The
+ synopsis is used as the subject of the problem report
+ email, and is used in problem report listings and
+ summaries; problem reports with obscure synopses tend to
+ get ignored.</para>
+
+ <para>As noted above, if your problem report includes a patch,
+ please have the synopsis start with <literal>[patch]</literal>;
+ if this is a ports PR and you are the
+ maintainer, you may consider adding
+ <literal>[maintainer update]</literal> and set the
+ <quote>Class</quote> of your PR to
+ <literal>maintainer-update</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Severity:</emphasis> One of
+ <literal>non-critical</literal>,
+ <literal>serious</literal> or
+ <literal>critical</literal>. Do not overreact; refrain
+ from labeling your problem <literal>critical</literal>
+ unless it really is (e.g. data corruption issues, serious
+ regression from previous functionality in -CURRENT)
+ or <literal>serious</literal> unless
+ it is something that will affect many users (kernel
+ panics or freezes; problems with
+ particular device drivers or system utilities). &os;
+ developers will not necessarily work on your problem faster
+ if you inflate its importance since there are so many other
+ people who have done exactly that &mdash; in fact, some
+ developers pay little attention to this field
+ because of this.</para>
+
+ <note>
+ <para>Major security problems should <emphasis>not</emphasis>
+ be filed in GNATS, because all GNATS information is public
+ knowledge. Please send such problems in private email to
+ &a.security-officer;.</para>
+ </note>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Priority:</emphasis> One of
+ <literal>low</literal>, <literal>medium</literal> or
+ <literal>high</literal>. <literal>high</literal> should
+ be reserved for problems that will affect practically
+ every user of &os; and <literal>medium</literal> for
+ something that will affect many users.</para>
+
+ <note>
+ <para>This field has become so widely abused that it is
+ almost completely meaningless.</para>
+ </note>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Category:</emphasis> Choose an appropriate
+ category.</para>
+
+ <note>
+ <para>There are a number of "platform" categories into which
+ bugs in the base system that are specific to one particular
+ hardware architecture should be filed. Problems that are
+ generic all across versions of &os; should probably be
+ filed as <literal>kern</literal> or <literal>bin</literal>;
+ see discussion of those categories below.</para>
+
+ <para>Example: you have a common PC-based machine, and think
+ you have encountered a problem specific to a particular
+ chipset or a particular motherboard: <literal>i386</literal>
+ is the right category.</para>
+
+ <para>Example: You are having a problem with an add-in
+ peripheral card on a commonly seen bus, or a problem with
+ a particular type of hard disk drive: in this case, it
+ probably applies to more than one architecture, and
+ <literal>kern</literal> is the right category.</para>
+ </note>
+
+ <para>Here is the current list of categories (taken from
+ <uri xlink:href="http://www.FreeBSD.org/cgi/cvsweb.cgi/src/gnu/usr.bin/send-pr/categories">http://www.FreeBSD.org/cgi/cvsweb.cgi/src/gnu/usr.bin/send-pr/categories</uri>):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>advocacy:</literal> problems relating to
+ &os;'s public image. Rarely used.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>alpha:</literal> problems specific to the
+ Alpha platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>amd64:</literal> problems specific to the
+ AMD64 platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>bin:</literal> problems with userland
+ programs in the base system. If running &man.whereis.1;
+ shows <literal>/bin</literal>, <literal>/usr/sbin</literal>,
+ or something similar, then this is probably the right
+ category. (A few contributed programs might instead
+ need to be in <literal>gnu</literal>; see below.)</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>conf:</literal> problems with
+ configuration files, default values, and so forth.
+ Things that affect <literal>/usr/share</literal>
+ or <literal>/etc/rc*</literal> belong here.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>docs:</literal> problems with manual pages
+ or on-line documentation.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>gnu:</literal> problems with imported GNU software
+ such as &man.gcc.1; or &man.grep.1;.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>i386:</literal> problems specific to the
+ &i386; platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>ia64:</literal> problems specific to the
+ ia64 platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>java:</literal> problems related to the &java;
+ Virtual Machine. (Ports that merely depend on &java; to
+ run should be filed under <literal>ports</literal>.)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para><literal>kern:</literal> problems with
+ the kernel, (non-platform-specific) device drivers,
+ or the base libraries.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>misc:</literal> anything that does not fit
+ in any of the other categories. (Note that there is
+ almost nothing that truly belongs in this category,
+ except for problems with the release and build
+ infrastructure. Temporary build failures on
+ <literal>HEAD</literal> do not belong here. Also note
+ that it is
+ easy for things to get lost in this category).</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>ports:</literal> problems relating to the
+ ports tree.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>powerpc:</literal> problems specific to the
+ &powerpc; platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>sparc64:</literal> problems specific to the
+ &sparc64; platform.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>standards:</literal> Standards conformance
+ issues.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>threads:</literal> problems related to the
+ &os; threads implementation (especially on &os.current;).</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>usb:</literal> problems related to the
+ &os; USB implementation.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>www:</literal> Changes or enhancements to
+ the &os; website.
+ Problems with code found in <literal>/usr/ports/www</literal>
+ do <emphasis>not</emphasis> belong here, they belong in
+ <literal>ports</literal> instead.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Class:</emphasis> Choose one of the
+ following:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>sw-bug:</literal> software bugs.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>doc-bug:</literal> errors in
+ documentation.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>change-request:</literal> requests for
+ additional features or changes in existing
+ features.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>update:</literal> updates to ports or
+ other contributed software.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>maintainer-update:</literal> updates to
+ ports for which you are the maintainer.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Release:</emphasis> The version of &os;
+ that you are running. This is filled out automatically if
+ you are using
+ &man.send-pr.1; and need only be changed if you are
+ sending a problem report from a different system than the
+ one that exhibits the problem.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Finally, there is a series of multi-line fields:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Environment:</emphasis> This should
+ describe, as accurately as possible, the environment in
+ which the problem has been observed. This includes the
+ operating system version, the version of the specific
+ program or file that contains the problem, and any other
+ relevant items such as system configuration, other
+ installed software that influences the problem,
+ etc.&mdash;quite simply everything a developer needs to
+ know to reconstruct the environment in which the problem
+ occurs.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Description:</emphasis> A complete and
+ accurate description of the problem you are experiencing.
+ Try to avoid speculating about the causes of the problem
+ unless you are certain that you are on the right track, as
+ it may mislead a developer into making incorrect
+ assumptions about the problem.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>How-To-Repeat:</emphasis> A summary of the
+ actions you need to take to reproduce the problem.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Fix:</emphasis> Preferably a patch, or at
+ least a workaround (which not only helps other people with
+ the same problem work around it, but may also help a
+ developer understand the cause for the problem), but if
+ you do not have any firm ideas for either, it is better to
+ leave this field blank than to speculate.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Sending off the problem report</title>
+
+ <para>If you are using &man.send-pr.1;:</para>
+
+ <para>Once you are done filling out the template, have saved it,
+ and exit your editor, &man.send-pr.1; will prompt you with
+ <prompt>s)end, e)dit or a)bort?</prompt>. You can then hit
+ <userinput>s</userinput> to go ahead and submit the problem report,
+ <userinput>e</userinput> to restart the editor and make
+ further modifications, or <userinput>a</userinput> to abort.
+ If you choose the latter, your problem report will remain on
+ disk (&man.send-pr.1; will tell you the filename before it
+ terminates), so you can edit it at your leisure, or maybe
+ transfer it to a system with better net connectivity, before
+ sending it with the <option>-f</option> to
+ &man.send-pr.1;:</para>
+
+<screen>&prompt.user; <userinput>send-pr -f ~/my-problem-report</userinput></screen>
+
+ <para>This will read the specified file, validate the contents,
+ strip comments and send it off.</para>
+
+ <para>If you are using the web form:</para>
+
+ <para>Before you hit <literal>submit</literal>, you will need to
+ fill in a field containing text that is represented in image
+ form on the page. This unfortunate measure has had to be
+ adopted due to misuse by automated systems and a few misguided
+ individuals. It is a necessary evil that no one likes; please
+ do not ask us to remove it.</para>
+
+ <para>Note that you are <literal>strongly advised</literal> to
+ save your work somewhere before hitting <literal>submit</literal>.
+ A common problem for users is to have their web browser displaying
+ a stale image from its cache. If this happens to you, your
+ submission will be rejected and you may lose your work.</para>
+
+ <para>If you are unable to view images for any reason, and are also
+ unable to use &man.send-pr.1;, please accept our apologies for
+ the inconvenience and email your problem report to the bugbuster
+ team at <email>freebsd-bugbusters@FreeBSD.org</email>.</para>
+ </section>
+
+ </section>
+
+ <section xml:id="pr-followup">
+ <title>Follow-up</title>
+
+ <para>Once your problem report has been filed, you will receive a
+ confirmation by email which will include the tracking number
+ that was assigned to your problem report and a URL you can use
+ to check its status. With a little luck, someone will take an
+ interest in your problem and try to address it, or, as the case
+ may be, explain why it is not a problem. You will be
+ automatically notified of any change of status, and you will
+ receive copies of any comments or patches someone may attach to
+ your problem report's audit trail.</para>
+
+ <para>If someone requests additional information from you, or you
+ remember or discover something you did not mention in the
+ initial report, please use one of two methods to submit your
+ followup:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The easiest way is to use the followup link on
+ the individual PR's web page, which you can reach from the
+ <link xlink:href="http://www.FreeBSD.org/cgi/query-pr-summary.cgi?query">
+ PR search page</link>. Clicking on this link will bring up an
+ an email window with the correct To: and Subject: lines filled in
+ (if your browser is configured to do this).</para>
+ </listitem>
+
+ <listitem>
+ <para>Alternatively, you can just mail it to
+ &a.bugfollowup;, making sure that the
+ tracking number is included in the subject so the bug tracking
+ system will know what problem report to attach it to.</para>
+
+ <note>
+ <para>If you do <emphasis>not</emphasis> include the tracking
+ number, GNATS will become confused and create an entirely
+ new PR which it then assigns to the GNATS administrator,
+ and then your followup will become lost until someone
+ comes in to clean up the mess, which could be days or
+ weeks afterwards.</para>
+
+ <para>Wrong way: <programlisting>Subject: that PR I sent</programlisting>
+ Right way: <programlisting>Subject: Re: ports/12345: compilation problem with foo/bar</programlisting></para>
+ </note>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>If the problem report remains open after the problem has
+ gone away, just send a follow-up (in the manner prescribed
+ above) saying that the problem report can be closed, and, if
+ possible, explaining how or when the problem was fixed.</para>
+ </section>
+
+ <section xml:id="pr-problems">
+ <title>If you are having problems</title>
+
+ <para>Most PRs go through the system and are accepted quickly;
+ however, at times GNATS runs behind and you may not get your
+ email confirmation for 10 minutes or even longer. Please try to
+ be patient.</para>
+
+ <para>In addition, because GNATS receives all its input via email,
+ it is absolutely vital that &os; runs all its submissions through
+ spam filters. If you do not get a response within an hour or
+ two, you may have fallen afoul of them; if so, please contact
+ the GNATS administrators at <email>bugmeister@FreeBSD.org</email>
+ and ask for help.</para>
+
+ <note>
+ <para>Among the anti-spam measures is one that weighs against
+ many common abuses seen HTML-based email (although not necessarily
+ the mere inclusion of HTML in a PR). We strongly recommend
+ against the use of HTML-based email when sending PRs: not
+ only is it more likely to fall afoul of the filters, it also
+ tends to merely clutter up the database. Plain old email is
+ strongly preferred.</para>
+ </note>
+
+ <para>On rare occasions you will encounter a GNATS bug where a
+ PR is accepted and assigned a tracking number but it does not
+ show up on the list of PRs on any of the web query pages. What
+ may have happened is that the database index has gotten out of
+ synchronization with the database itself. The way that you
+ can test whether this has happened is to pull up the
+ <link xlink:href="http://www.FreeBSD.org/cgi/query-pr.cgi">
+ view a single PR</link> page and see whether the PR shows up.
+ If it does, please notify the GNATS administrators at
+ <email>bugmeister@FreeBSD.org</email>. Note that there is a
+ <literal>cron</literal> job that periodically rebuilds the database,
+ so unless you are in a hurry, no action needs to be taken.</para>
+ </section>
+
+ <section xml:id="pr-further">
+ <title>Further Reading</title>
+
+ <para>This is a list of resources relevant to the proper writing
+ and processing of problem reports. It is by no means complete.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link xlink:href="http://www.chiark.greenend.org.uk/~sgtatham/bugs.html">
+ How to Report Bugs Effectively</link>&mdash;an excellent
+ essay by Simon G. Tatham on composing useful (non-&os;-specific)
+ problem reports.</para>
+ </listitem>
+ <listitem>
+ <para><link xlink:href="&url.articles.pr-guidelines;/article.html">Problem
+ Report Handling Guidelines</link>&mdash;valuable insight
+ into how problem reports are handled by the &os;
+ developers.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <index/>
+</article>
diff --git a/zh_TW.UTF-8/articles/remote-install/Makefile b/zh_TW.UTF-8/articles/remote-install/Makefile
new file mode 100644
index 0000000000..3efa3a5e93
--- /dev/null
+++ b/zh_TW.UTF-8/articles/remote-install/Makefile
@@ -0,0 +1,30 @@
+#
+# The FreeBSD Traditional Chinese Project
+#
+# Original Revision: 1.1
+# $FreeBSD$
+#
+
+DOC?= article
+
+FORMATS?= html
+WITH_ARTICLE_TOC?= YES
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+SRCS= article.xml
+
+# Images from the cross-document image library
+IMAGES_LIB= callouts/1.png
+IMAGES_LIB+= callouts/2.png
+IMAGES_LIB+= callouts/3.png
+IMAGES_LIB+= callouts/4.png
+IMAGES_LIB+= callouts/5.png
+IMAGES_LIB+= callouts/6.png
+IMAGES_LIB+= callouts/7.png
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/articles/remote-install/article.xml b/zh_TW.UTF-8/articles/remote-install/article.xml
new file mode 100644
index 0000000000..d927f61be6
--- /dev/null
+++ b/zh_TW.UTF-8/articles/remote-install/article.xml
@@ -0,0 +1,475 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
+<!--
+ The FreeBSD Documentation Project
+ The FreeBSD Chinese (Traditional) Documentation Project
+
+ Original Revision: 1.5
+
+-->
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>遠端安裝 &os; 作業系統而不必接 Remote Console</title>
+
+
+ <author><personname><firstname>Daniel</firstname><surname>Gerzo</surname></personname><affiliation>
+ <address><email>danger@FreeBSD.org</email></address>
+ </affiliation></author>
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <copyright>
+ <year>2008</year>
+ <holder>The &os; Documentation Project</holder>
+ </copyright>
+
+ <pubdate>$FreeBSD$</pubdate>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>本文介紹如何在沒辦法連到遠端 console 的機器做 &os; 遠端安裝。
+ 本文構想來自於作者與 &a.mm; 的合作成果,
+ 以及 &a.pjd; 所投注的諸多心血。</para>
+ </abstract>
+ </info>
+
+ <sect1 xml:id="background">
+ <title>緣起</title>
+
+ <para>世上有許多 server hosting provider,但其中有官方支援 &os;
+ 則不是相當多。 他們通常會在所提供的機器上有 &linux; distribution
+ 的安裝支援。</para>
+
+ <para>有些會讓您可選擇喜好的 &linux; distribution 來裝,
+ 像這種情況就可以試著安裝 &os;。 而有些則是會提供救急用的系統,
+ 這種也可以用來安裝 &os;。</para>
+
+ <para>本文介紹這些遠端基本安裝 &os; 的方式,以及 RAID-1 與
+ <application>ZFS</application> 設定步驟。</para>
+ </sect1>
+
+ <sect1 xml:id="intro">
+ <title>介紹</title>
+
+ <para>茲摘錄一下本文的目的以及闡述這邊所涵蓋的東西。
+ 對於無官方支援 &os; 的代管服務(colocation)用戶而言,
+ 本文中所介紹到的指令會相當有用。</para>
+
+ <procedure>
+ <step>
+ <para>正如先前 <link linkend="background">緣起</link> 所提到的,許多名聲還不賴的
+ server hosting 公司會提供一些救急用系統,可以透過
+ <acronym>LAN</acronym> 方式開機,也可以透過
+ <application>SSH</application> 方式進行管理。 通常會有該加值服務,
+ 以讓他們的客戶可以連進來修復有問題的作業系統。
+ 本節之後將介紹如何透過救急系統來安裝 &os;。</para>
+ <!-- XXXTR: Solaris has a restore command, something like
+ sysrestore, FreeBSD Should have one too. -->
+ </step>
+
+ <step>
+ <para>下一節會介紹如何在本機設定以及打造最小巧的 &os; ——
+ 該版最後會在遠端機器上透過 ramdisk 方式啟動,並以
+ <application>sysinstall</application> 從 <acronym>FTP</acronym>
+ mirror 站來安裝完整的 &os; 作業系統。</para>
+ </step>
+
+ <step>
+ <para>本文其餘部分將介紹安裝程序,以及 <application>ZFS</application>
+ 檔案系統的設定。</para>
+ </step>
+ </procedure>
+
+ <sect2 xml:id="requirements">
+ <title>需求</title>
+
+ <para>為了成功完成遠端安裝,必須要有:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>要有可以上網的作業系統,並且 <application>SSH</application>
+ 可以連線。</para>
+ </listitem>
+
+ <listitem>
+ <para>瞭解 &os; 的安裝程序</para>
+ </listitem>
+
+ <listitem>
+ <para>熟悉如何使用 &man.sysinstall.8;</para>
+ </listitem>
+
+ <listitem>
+ <para>有 &os; 安裝光碟片或者 <acronym>ISO</acronym> image 檔</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="preparation">
+ <title>準備 - <application>mfsBSD</application></title>
+
+ <para>在裝 &os; 之前,要先打造最小化的 &os; 作業系統 image 檔,
+ 以便可以從硬碟上開機。 如此一來,新的系統就可以透過網路來操作,
+ 而剩下來的安裝部分即可不必透過 console。</para>
+
+ <para>而 <application>mfsBSD</application> 這套工具就是用來打造小型的
+ &os; image 檔。 <application>mfsBSD</application> (名字其中
+ <quote>mfs</quote> 就是 <quote>memory file system</quote>)所建造出來的
+ 整套系統會透過 ramdisk 方式來運作。 由於此一特色,硬碟的部分就不受限,
+ 因此可以用來安裝完整的 &os; 作業系統。 <application>mfsBSD</application>
+ 的首頁位於 <uri xlink:href="http://people.freebsd.org/~mm/mfsbsd/">http://people.freebsd.org/~mm/mfsbsd/</uri>,
+ 其中連結有該工具的最新 release 部分。</para>
+
+ <para>請注意:<application>mfsBSD</application> 內部運作方式的細節,不
+ 在本文介紹範圍之內。 若對這方面有興趣的讀者,可至
+ <application>mfsBSD</application> 官網查閱相關文件。</para>
+
+ <para>首先下載最新的 <application>mfsBSD</application> 並解壓縮之,
+ 然後切到解壓縮後的工作目錄,也就是 <application>mfsBSD</application>
+ script 檔所在處:</para>
+
+ <screen>&prompt.root; <userinput>fetch http://people.freebsd.org/~mm/mfsbsd/mfsbsd-latest.tar.gz</userinput>
+&prompt.root; <userinput>tar xvzf mfsbsd-1.0-beta1.tar.gz</userinput>
+&prompt.root; <userinput>cd mfsbsd-1.0-beta1/</userinput></screen>
+
+ <sect2 xml:id="mfsbsd-config">
+ <title>設定 <application>mfsBSD</application></title>
+
+ <para>在將 <application>mfsBSD</application> 開機之前,
+ 有幾個重要設定要先設妥。 此時最重要的設定,很明顯就是網路設定。
+ 到底網路怎麼設最好,則取決於所處的網路環境,
+ 以及該網路卡會以哪一種驅動程式載入而定。 我們將會看到
+ <application>mfsBSD</application> 如何在任何網路情況下進行設定。</para>
+
+ <para>另一件重要事就是設定 <systemitem class="username">root</systemitem> 密碼。
+ 這點可以透過 <filename>conf/rootpw.conf</filename> 來完成。
+ 請切記:該檔密碼是以明文方式存放,因此不建議放真正平常有在用的密碼。
+ 然而這密碼只是臨時密碼而已,可以在之後開機時再做更換。</para>
+
+ <sect3>
+ <title>設定網路(<filename>conf/interfaces.conf</filename> 方式)</title>
+
+ <para>若對要裝的機器網卡為何還不知道是哪一款,但可以善加利用
+ <application>mfsBSD</application> 的自動偵測功能。
+ <application>mfsBSD</application> 的開機 script 會根據網卡的 MAC
+ 位址範圍來偵測正確的驅動程式,像是下列的
+ <filename>conf/interfaces.conf</filename> 設定內容:</para>
+
+ <programlisting>initconf_interfaces="ext1"
+initconf_mac_ext1="00:00:00:00:00:00"
+initconf_ip_ext1="192.168.0.2"
+initconf_netmask_ext1="255.255.255.0"</programlisting>
+
+ <para>別忘了在 <filename>conf/rc.conf</filename> 內要加上
+ <literal>defaultrouter</literal> 的相關設定:</para>
+
+ <programlisting>defaultrouter="192.168.0.1"</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>設定網路(<filename>conf/rc.conf</filename> 方式)</title>
+
+ <para>若已經知道網卡是哪一種,那麼要設定網路的話直接改
+ <filename>conf/rc.conf</filename> 會比較方便。
+ 該檔設定語法與 &os; 標準的 &man.rc.conf.5; 是一致的。</para>
+
+ <para>舉個例子,若知道該機器網卡是用 &man.re.4;,那麼就在
+ <filename>conf/rc.conf</filename> 做下列類似設定:</para>
+
+ <programlisting>defaultrouter="192.168.0.1"
+ifconfig_re0="inet 192.168.0.2 netmask 255.255.255.0"</programlisting>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="mfsbsd-build">
+ <title>打造 <application>mfsBSD</application> image</title>
+
+ <para>打造 <application>mfsBSD</application>
+ image 檔的過程相當簡單。</para>
+
+ <para>首先是把 &os; 安裝光碟或者安裝用的 <acronym>ISO</acronym> image
+ 檔丟到 <filename>/cdrom</filename>。
+ 為維持所有例子的一致,本文假設都是用 &os; 7.0-RELEASE
+ <acronym>ISO</acronym>。 而把 ISO image 檔掛載到 <filename>/cdrom</filename> 目錄相當簡單,
+ 就是用 &man.mdconfig.8;:</para>
+
+ <screen>&prompt.root; <userinput>mdconfig -a -t vnode -u 10 -f 7.0-RELEASE-amd64-disc1.iso</userinput>
+&prompt.root; <userinput>mount_cd9660 /dev/md10 /cdrom</userinput></screen>
+
+ <para>接著就開始打造可開機的 <application>mfsBSD</application>
+ image:</para>
+
+ <screen>&prompt.root; <userinput>make BASE=/cdrom/7.0-RELEASE</userinput></screen>
+
+ <note>
+ <para>上述的 <command>make</command> 指令要在
+ <application>mfsBSD</application> 的最上層目錄執行,比方說 <filename>~/mfsbsd-1.0-beta1/</filename>。</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title><application>mfsBSD</application> 開動</title>
+
+ <para>現在 <application>mfsBSD</application> image 已經備妥,
+ 要上傳到遠端機器的救急系統或者預先安裝的 &linux; distribution。
+ 要完成這工作最適合的工具就是 <application>scp</application>:</para>
+
+ <screen>&prompt.root; <userinput>scp disk.img root@192.168.0.2:.</userinput></screen>
+
+ <para>為了能順利啟動 <application>mfsBSD</application> image,
+ 要把檔案放在欲安裝機器的第一顆(可開機)硬碟上。
+ 假設例子的第一顆開機硬碟代號為 <filename>sda</filename>,
+ 那麼作法就類似下面這樣:</para>
+
+ <screen>&prompt.root; <userinput>dd if=/root/disk.img of=/dev/sda bs=1m</userinput></screen>
+
+ <para>若一切順利,該 image 檔現在應該會在第一顆硬碟的
+ <acronym>MBR</acronym> 磁區並可以開始進行重開機了。 可以用
+ &man.ping.8; 工具來檢測該機器開機完畢與否。 一旦 ping 到之後,
+ 就可以透過 &man.ssh.1; 連進去,並且用 <systemitem class="username">root</systemitem>
+ 以及剛設定的密碼登入。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="installation">
+ <title>&os; 作業系統的安裝</title>
+
+ <para>現在 <application>mfsBSD</application> 已順利啟動,並且應該可以透過
+ &man.ssh.1; 方式來連。 本節將介紹如何建立 slice 分割、設定
+ <application>gmirror</application> 以作 RAID-1、如何以
+ <application>sysinstall</application> 來安裝 &os;
+ 作業系統的最小化安裝。</para>
+
+ <sect2>
+ <title>準備硬碟</title>
+
+ <para>首先要作的是配置硬碟空間給 &os;,像是建立 slice 跟分割區。
+ 很明顯地,目前在跑的作業系統是載入到系統記憶體內執行,
+ 因此要對硬碟配置並無任何問題。 這些工作可以用
+ <application>sysinstall</application> 或者以 &man.fdisk.8; 搭配
+ &man.bsdlabel.8; 來完成。</para>
+
+ <para>首先先把各硬碟都先清空。 請對各硬碟作下列指令:</para>
+
+ <screen>&prompt.root; <userinput>dd if=/dev/zero of=/dev/ad0 count=2</userinput></screen>
+
+ <para>接著,以您慣用的工具來建立 slice 以及設定 label。 通常會建議以
+ 的 <application>sysinstall</application> 工具來作會比較輕鬆,
+ 或者是強而又不太會出槌的文字介面 &unix; 標準工具(像是 &man.fdisk.8;,
+ &man.bsdlabel.8;),這部分稍後也會一併介紹。 前者部分在 &os; Handbook
+ 的 <link xlink:href="&url.books.handbook;/install-steps.html">安裝
+ &os;</link> 章節有相當詳盡的介紹,所以這邊主要要介紹的是如何建立
+ RAID-1 系統以及 <application>ZFS</application>。
+ 這邊會介紹建立以 &man.gmirror.8; 做成的小型 mirrored 檔案系統:
+ <filename>/</filename> (根目錄), <filename>/usr</filename> 以及 <filename>/var</filename>,而硬碟的其餘剩餘空間則通通以
+ &man.zpool.8; 做成 <application>ZFS</application> 的 mirrored 檔案系統
+ 。 請注意:必須要先把 &os; 作業系統裝好並開完機後,才能進行設定
+ <application>ZFS</application> 檔案系統。</para>
+
+ <para>下面的例子會介紹如何建立 slice 以及 label、在每個分割區上啟用
+ &man.gmirror.8;、如何在每個 mirrored 分割區上建立
+ <application>UFS2</application> 檔案系統:</para>
+
+ <screen>&prompt.root; <userinput>fdisk -BI /dev/ad0</userinput> <co xml:id="fdisk"/>
+&prompt.root; <userinput>fdisk -BI /dev/ad1</userinput>
+&prompt.root; <userinput>bsdlabel -wB /dev/ad0s1</userinput> <co xml:id="bsdlabel-writing"/>
+&prompt.root; <userinput>bsdlabel -wB /dev/ad1s1</userinput>
+&prompt.root; <userinput>bsdlabel -e /dev/ad0s1</userinput> <co xml:id="bsdlabel-editing"/>
+&prompt.root; <userinput>bsdlabel /dev/ad0s1 &gt; /tmp/bsdlabel.txt &amp;&amp; bsdlabel -R /dev/ad1s1 /tmp/bsdlabel.txt</userinput> <co xml:id="bsdlabel-restore"/>
+&prompt.root; <userinput>gmirror label root /dev/ad[01]s1a</userinput> <co xml:id="gmirror1"/>
+&prompt.root; <userinput>gmirror label var /dev/ad[01]s1d</userinput>
+&prompt.root; <userinput>gmirror label usr /dev/ad[01]s1e</userinput>
+&prompt.root; <userinput>gmirror label -F swap /dev/ad[01]s1b</userinput> <co xml:id="gmirror2"/>
+&prompt.root; <userinput>newfs /dev/mirror/root</userinput> <co xml:id="newfs"/>
+&prompt.root; <userinput>newfs /dev/mirror/var</userinput>
+&prompt.root; <userinput>newfs /dev/mirror/usr</userinput></screen>
+
+ <calloutlist>
+ <callout arearefs="fdisk">
+ <para>對該硬碟建立 slice 並且在第零軌處將開機表作初始。
+ 請對該機器所有硬碟都作此一動作。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-writing">
+ <para>對各硬碟寫入 label 以及 bootstrap 碼。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-editing">
+ <para>現在手動修改該硬碟的 label,至於如何建立分割區(partitions)
+ 請參閱 &man.bsdlabel.8; 說明。
+ 分割區分別建立:<literal>a</literal> 是給 <filename>/</filename> (根目錄),
+ <literal>b</literal> 給 swap,
+ <literal>d</literal> 給 <filename>/var</filename>,
+ <literal>e</literal> 給 <filename>/usr</filename>,
+ 最後,會在稍後步驟把 <literal>f</literal> 給
+ <application>ZFS</application> 使用。</para>
+ </callout>
+
+ <callout arearefs="bsdlabel-restore">
+ <para>把剛剛的 label 設定先匯出,再匯入到第二顆硬碟上,
+ 如此一來兩邊的硬碟 label 設定就會同樣。</para>
+ </callout>
+
+ <callout arearefs="gmirror1">
+ <para>在各分割區上啟用 &man.gmirror.8;</para>
+ </callout>
+
+ <callout arearefs="gmirror2">
+ <para>請注意:<option>-F</option> 選項是用在 swap 上。
+ 這參數會讓 &man.gmirror.8; 認為該硬體是處於可靠狀態,
+ 即使發生電源故障或系統當掉,也不會去同步。</para>
+ </callout>
+
+ <callout arearefs="newfs">
+ <para>在各個有做 mirror 的分割區上建立 <application>UFS2</application>
+ 檔案系統</para>
+ </callout>
+ </calloutlist>
+ </sect2>
+
+ <sect2>
+ <title>系統安裝</title>
+
+ <para>這裡是最重要的一環,
+ 本節介紹實際上如何在先前一節所做好的硬碟安裝最小化的 &os;,
+ 為了完成此一目標,所有檔案系統都必須掛載妥當,才能讓
+ <application>sysinstall</application> 可以把 &os; 裝到硬碟內:</para>
+
+ <screen>&prompt.root; <userinput>mount /dev/mirror/root /mnt</userinput>
+&prompt.root; <userinput>mkdir /mnt/var /mnt/usr</userinput>
+&prompt.root; <userinput>mount /dev/mirror/var /mnt/var</userinput>
+&prompt.root; <userinput>mount /dev/mirror/usr /mnt/usr</userinput></screen>
+
+ <para>做完上述動作之後,請執行 &man.sysinstall.8;。 請從主選單中選擇
+ <guimenuitem>Custom</guimenuitem> 安裝,選
+ <guimenuitem>Options</guimenuitem> 按 <keycap>Enter</keycap>。
+ 然後以方向鍵移動到 <literal>Install Root</literal> 處,按
+ <keycap>Space</keycap> 鍵然後改為 <filename>/mnt</filename>,再按 <keycap>Enter</keycap>
+ 鍵以將修改值存起來,然後按 <keycap>q</keycap> 鍵即可離開這個
+ <guimenuitem>Options</guimenuitem> 畫面。</para>
+
+ <warning>
+ <para>請注意:本步驟極為重要,若忽略的話那麼
+ <application>sysinstall</application> 就沒辦法安裝 &os;。</para>
+ </warning>
+
+ <para>接著選 <guimenuitem>Distributions</guimenuitem>,然後移動游標到
+ <option>Minimal</option> 處,按 <keycap>Space</keycap> 鍵。
+ 本文之所以介紹最小化安裝是為了要節省網路流量,因為系統安裝是透過
+ <application>ftp</application> 方式來進行。 要離開本畫面,請選
+ <option>Exit</option> 即可。</para>
+
+ <note>
+ <para>至於 <guimenuitem>Partition</guimenuitem> 及
+ <guimenuitem>Label</guimenuitem> 步驟則可略過,
+ 因為這些目前已經都設定完畢了。</para>
+ </note>
+
+ <para>在 <guimenuitem>Media</guimenuitem> 選單中請選
+ <option>FTP</option>。 請選最近的 mirror 站,並且讓
+ <application>sysinstall</application> 假設網路已經設妥。
+ 接下來就會回到 <guimenuitem>Custom</guimenuitem> 選單。</para>
+
+ <para>最後,按下 <guimenuitem>Commit</guimenuitem> 即可開始進行安裝。
+ 完成安裝後,即可離開 <application>sysinstall</application>。</para>
+ </sect2>
+
+ <sect2>
+ <title>後續安裝步驟</title>
+
+ <para>此時 &os; 作業系統應該已經裝完,然而還有些後續流程要做。
+ 必須要做一些後續設定,才能讓 &os; 可以開機跟登入。</para>
+
+ <para>現在必須要用 &man.chroot.8; 以切到剛剛新裝好的系統內。
+ 指令如下:</para>
+
+ <screen>&prompt.root; <userinput>chroot /mnt</userinput></screen>
+
+ <para>然後再打下列指令以繼續完成:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>把 <literal>GENERIC</literal> kernel 複製到
+ <filename>/boot/kernel</filename>
+ 目錄:</para>
+
+ <screen>&prompt.root; <userinput>cp -Rp /boot/GENERIC/* /boot/kernel</userinput></screen>
+ </listitem>
+
+ <listitem>
+ <para>建立 <filename>/etc/rc.conf</filename>,
+ <filename>/etc/resolv.conf</filename> 及
+ <filename>/etc/fstab</filename> 檔案。 別忘了,要記得在
+ <filename>/etc/rc.conf</filename> 檔設相關網路設定,以及把
+ <application>sshd</application> 啟用。 此外,
+ <filename>/etc/fstab</filename> 檔應該會長像下面這樣:</para>
+
+ <programlisting># Device Mountpoint FStype Options Dump Pass#
+/dev/mirror/swap none swap sw 0 0
+/dev/mirror/root / ufs rw 1 1
+/dev/mirror/usr /usr ufs rw 2 2
+/dev/mirror/var /var ufs rw 2 2
+/dev/cd0 /cdrom cd9660 ro,noauto 0 0</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>新增 <filename>/boot/loader.conf</filename> 檔,
+ 並且內容填入下列:</para>
+
+ <programlisting>geom_mirror_load="YES"
+zfs_load="YES"</programlisting>
+ </listitem>
+
+ <listitem>
+ <para>執行下列指令,以在下次開機時啟用 <application>ZFS</application>
+ :</para>
+
+ <screen>&prompt.root; <userinput>echo 'zfs_enable="YES"' &gt;&gt; /etc/rc.conf </userinput></screen>
+ </listitem>
+
+ <listitem>
+ <para>使用 &man.adduser.8; 工具來新增其他使用者帳號。 別忘了,
+ 至少要有一個帳號得加入 <systemitem class="groupname">wheel</systemitem> 群組,
+ 才能在重開機後以該帳號切換為 root。</para>
+ </listitem>
+
+ <listitem>
+ <para>再次檢查上述相關的設定,是否有遺漏或打錯。</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>現在該系統終於可以重開機了,請用 &man.reboot.8;
+ 指令以重開機。</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="zfs">
+ <title>ZFS</title>
+
+ <para>系統重開機完畢之後,應該就可以登入了。 歡迎使用全新的 &os; 安裝方式,
+ 完全透過遠端而不必接上 remote console!</para>
+
+ <para>接下來只剩要調整 &man.zpool.8; 以及建立 &man.zfs.8; 檔案系統而已。
+ <application>ZFS</application> 的建立及管理是相當淺顯易懂。 首先,
+ 建立 mirrored pool:</para>
+
+ <screen>&prompt.root; <userinput>zpool create tank mirror /dev/ad[01]s1f</userinput></screen>
+
+ <para>接著,建立檔案系統:</para>
+
+ <screen>&prompt.root; <userinput>zfs create tank/ports</userinput>
+&prompt.root; <userinput>zfs create tank/src</userinput>
+&prompt.root; <userinput>zfs set compression=gzip tank/ports</userinput>
+&prompt.root; <userinput>zfs set compression=on tank/src</userinput>
+&prompt.root; <userinput>zfs set mountpoint=/usr/ports tank/ports</userinput>
+&prompt.root; <userinput>zfs set mountpoint=/usr/src tank/src</userinput></screen>
+
+ <para>一切就是這樣簡單。 若對 &os; 上的 <application>ZFS</application>
+ 細節部分有興趣,請參閱 &os; Wiki 上的 <link xlink:href="http://wiki.freebsd.org/ZFS">ZFS</link> 一節說明。</para>
+ </sect1>
+</article>
diff --git a/zh_TW.UTF-8/books/Makefile b/zh_TW.UTF-8/books/Makefile
new file mode 100644
index 0000000000..176ffedb82
--- /dev/null
+++ b/zh_TW.UTF-8/books/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+SUBDIR = developers-handbook
+#SUBDIR+= faq
+SUBDIR+= fdp-primer
+SUBDIR+= handbook
+SUBDIR+= porters-handbook
+#SUBDIR+= zh-tut
+
+ROOT_SYMLINKS = faq fdp-primer handbook porters-handbook
+
+DOC_PREFIX?= ${.CURDIR}/../..
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/books/Makefile.inc b/zh_TW.UTF-8/books/Makefile.inc
new file mode 100644
index 0000000000..dd9acff37a
--- /dev/null
+++ b/zh_TW.UTF-8/books/Makefile.inc
@@ -0,0 +1,5 @@
+#
+# $FreeBSD$
+#
+
+DESTDIR?= ${DOCDIR}/zh_TW.UTF-8/books/${.CURDIR:T}
diff --git a/zh_TW.UTF-8/books/developers-handbook/Makefile b/zh_TW.UTF-8/books/developers-handbook/Makefile
new file mode 100644
index 0000000000..81fed7b836
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/Makefile
@@ -0,0 +1,42 @@
+#
+# $FreeBSD$
+#
+# Build the FreeBSD Developers' Handbook.
+#
+
+MAINTAINER=doc@FreeBSD.org
+
+DOC?= book
+
+FORMATS?= html-split
+
+INSTALL_COMPRESSED?= gz
+INSTALL_ONLY_COMPRESSED?=
+
+# Images
+IMAGES_EN= sockets/layers.eps sockets/sain.eps sockets/sainfill.eps sockets/sainlsb.eps sockets/sainmsb.eps sockets/sainserv.eps sockets/serv.eps sockets/serv2.eps sockets/slayers.eps
+
+#
+# SRCS lists the individual XML files that make up the document. Changes
+# to any of these files will force a rebuild
+#
+
+# XML content
+SRCS= book.xml
+SRCS+= introduction/chapter.xml
+SRCS+= ipv6/chapter.xml
+SRCS+= kerneldebug/chapter.xml
+SRCS+= l10n/chapter.xml
+SRCS+= policies/chapter.xml
+SRCS+= secure/chapter.xml
+SRCS+= sockets/chapter.xml
+SRCS+= testing/chapter.xml
+SRCS+= tools/chapter.xml
+SRCS+= x86/chapter.xml
+
+# Entities
+
+URL_RELPREFIX?= ../../../..
+DOC_PREFIX?= ${.CURDIR}/../../..
+
+.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/zh_TW.UTF-8/books/developers-handbook/book.xml b/zh_TW.UTF-8/books/developers-handbook/book.xml
new file mode 100644
index 0000000000..6b48de373f
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/book.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE book PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
+ "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd" [
+<!ENTITY % chapters SYSTEM "chapters.ent"> %chapters;
+]>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+ Original revision: 1.52
+-->
+<book xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="zh_tw">
+ <info><title>FreeBSD Developers' Handbook</title>
+
+
+ <author><orgname>FreeBSD 文件計畫</orgname></author>
+
+ <pubdate>August 2000</pubdate>
+
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <holder>The FreeBSD Documentation Project</holder>
+ </copyright>
+
+ &legalnotice;
+
+ <legalnotice xml:id="trademarks" role="trademarks">
+ &tm-attrib.freebsd;
+ &tm-attrib.apple;
+ &tm-attrib.ibm;
+ &tm-attrib.ieee;
+ &tm-attrib.intel;
+ &tm-attrib.linux;
+ &tm-attrib.microsoft;
+ &tm-attrib.opengroup;
+ &tm-attrib.sun;
+ &tm-attrib.general;
+ </legalnotice>
+
+ <releaseinfo>$FreeBSD$</releaseinfo>
+
+ <abstract>
+ <para>
+ 歡迎使用 Developers' Handbook!
+ 這份文件是由許多人 <emphasis>不斷撰寫</emphasis> 而成的,
+ 而且許多章節仍需更新或者內容還是一片空白,
+ 如果你想幫忙 FreeBSD 文件計劃,
+ 請寄信到 &a.doc;。
+ </para>
+
+ <para>
+ 最新版的文件都在 <link xlink:href="&url.base;/index.html">FreeBSD 官網</link> 上面,
+ 也可從 <link xlink:href="ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/">FreeBSD FTP server</link> 下載不同格式的資料。
+ 當然也可以在其他的 <link xlink:href="&url.books.handbook;/mirrors-ftp.html">mirror站</link>下載。
+ </para>
+
+ </abstract>
+ </info>
+
+ <part xml:id="Basics">
+ <title>基本概念</title>
+
+ &chap.introduction;
+ &chap.tools;
+ &chap.secure;
+ &chap.l10n;
+ &chap.policies;
+ &chap.testing;
+ </part>
+
+ <part xml:id="ipc">
+ <title>Interprocess Communication(IPC)</title>
+
+ &chap.sockets;
+ &chap.ipv6;
+
+ </part>
+
+ <part xml:id="kernel">
+ <title>Kernel(核心)</title>
+
+ &chap.kerneldebug;
+
+ </part>
+
+ <part xml:id="architectures">
+ <title>Architectures(電腦架構)</title>
+
+ &chap.x86;
+
+ </part>
+
+ <part xml:id="appendices">
+ <title>附錄</title>
+
+ <bibliography>
+
+ <biblioentry xml:id="COD" xreflabel="1">
+ <authorgroup>
+ <author><personname><firstname>Dave</firstname><othername role="MI">A</othername><surname>Patterson</surname></personname></author>
+ <author><personname><firstname>John</firstname><othername role="MI">L</othername><surname>Hennessy</surname></personname></author>
+ </authorgroup>
+ <copyright><year>1998</year><holder>Morgan Kaufmann Publishers,
+ Inc.</holder></copyright>
+ <biblioid class="isbn">1-55860-428-6</biblioid>
+ <publisher>
+ <publishername>Morgan Kaufmann Publishers, Inc.</publishername>
+ </publisher>
+ <citetitle>Computer Organization and Design</citetitle>
+ <subtitle>The Hardware / Software Interface</subtitle>
+ <pagenums>1-2</pagenums>
+ </biblioentry>
+
+ <biblioentry xreflabel="2">
+ <authorgroup>
+ <author><personname><firstname>W.</firstname><othername role="Middle">Richard</othername><surname>Stevens</surname></personname></author>
+ </authorgroup>
+ <copyright><year>1993</year><holder>Addison Wesley Longman,
+ Inc.</holder></copyright>
+ <biblioid class="isbn">0-201-56317-7</biblioid>
+ <publisher>
+ <publishername>Addison Wesley Longman, Inc.</publishername>
+ </publisher>
+ <citetitle>Advanced Programming in the Unix Environment</citetitle>
+ <pagenums>1-2</pagenums>
+ </biblioentry>
+
+ <biblioentry xreflabel="3">
+ <authorgroup>
+ <author><personname><firstname>Marshall</firstname><othername role="Middle">Kirk</othername><surname>McKusick</surname></personname></author>
+ <author><personname><firstname>Keith</firstname><surname>Bostic</surname></personname></author>
+ <author><personname><firstname>Michael</firstname><othername role="MI">J</othername><surname>Karels</surname></personname></author>
+ <author><personname><firstname>John</firstname><othername role="MI">S</othername><surname>Quarterman</surname></personname></author>
+ </authorgroup>
+ <copyright><year>1996</year><holder>Addison-Wesley Publishing Company,
+ Inc.</holder></copyright>
+ <biblioid class="isbn">0-201-54979-4</biblioid>
+ <publisher>
+ <publishername>Addison-Wesley Publishing Company, Inc.</publishername>
+ </publisher>
+ <citetitle>The Design and Implementation of the 4.4 BSD Operating System</citetitle>
+ <pagenums>1-2</pagenums>
+ </biblioentry>
+
+ <biblioentry xml:id="Phrack" xreflabel="4">
+ <authorgroup>
+ <author><personname><firstname>Aleph</firstname><surname>One</surname></personname></author>
+ </authorgroup>
+ <citetitle>Phrack 49; "Smashing the Stack for Fun and Profit"</citetitle>
+ </biblioentry>
+
+ <biblioentry xml:id="StackGuard" xreflabel="5">
+ <authorgroup>
+ <author><personname><firstname>Chrispin</firstname><surname>Cowan</surname></personname></author>
+ <author><personname><firstname>Calton</firstname><surname>Pu</surname></personname></author>
+ <author><personname><firstname>Dave</firstname><surname>Maier</surname></personname></author>
+ </authorgroup>
+ <citetitle>StackGuard; Automatic Adaptive Detection and Prevention of
+ Buffer-Overflow Attacks</citetitle>
+ </biblioentry>
+
+ <biblioentry xml:id="OpenBSD" xreflabel="6">
+ <authorgroup>
+ <author><personname><firstname>Todd</firstname><surname>Miller</surname></personname></author>
+ <author><personname><firstname>Theo</firstname><surname>de Raadt</surname></personname></author>
+ </authorgroup>
+ <citetitle>strlcpy and strlcat -- consistent, safe string copy and
+ concatenation.</citetitle>
+ </biblioentry>
+
+ </bibliography>
+
+ &chap.index;
+ </part>
+
+</book>
diff --git a/zh_TW.UTF-8/books/developers-handbook/chapters.ent b/zh_TW.UTF-8/books/developers-handbook/chapters.ent
new file mode 100644
index 0000000000..481ce9a436
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/chapters.ent
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Creates entities for each chapter in the FreeBSD Developer's
+ Handbook. Each entity is named chap.foo, where foo is the value
+ of the id attribute on that chapter, and corresponds to the name of
+ the directory in which that chapter's .xml file is stored.
+
+ Chapters should be listed in the order in which they are referenced.
+
+ $FreeBSD$
+-->
+
+<!-- Part one -->
+<!ENTITY chap.introduction SYSTEM "introduction/chapter.xml">
+<!ENTITY chap.tools SYSTEM "tools/chapter.xml">
+<!ENTITY chap.secure SYSTEM "secure/chapter.xml">
+<!ENTITY chap.l10n SYSTEM "l10n/chapter.xml">
+<!ENTITY chap.policies SYSTEM "policies/chapter.xml">
+<!ENTITY chap.testing SYSTEM "testing/chapter.xml">
+
+<!-- Part two - IPC -->
+<!ENTITY chap.sockets SYSTEM "sockets/chapter.xml">
+<!ENTITY chap.ipv6 SYSTEM "ipv6/chapter.xml">
+
+<!-- Part three - Kernel -->
+<!ENTITY chap.dma SYSTEM "dma/chapter.xml">
+<!ENTITY chap.kerneldebug SYSTEM "kerneldebug/chapter.xml">
+
+<!-- Part five - Architectures -->
+<!ENTITY chap.x86 SYSTEM "x86/chapter.xml">
+
+<!-- Part six - Appendices -->
+<!ENTITY chap.index "<index xmlns='http://docbook.org/ns/docbook'/>">
diff --git a/zh_TW.UTF-8/books/developers-handbook/introduction/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/introduction/chapter.xml
new file mode 100644
index 0000000000..636eff06d5
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/introduction/chapter.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+ Original revision: 1.18
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="introduction">
+ <info><title>簡介</title>
+ <authorgroup>
+ <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname><contrib>Contributed by </contrib></author>
+ <author><personname><firstname>Jeroen</firstname><surname>Ruigrok van der Werven</surname></personname></author>
+ </authorgroup>
+ </info>
+
+
+ <sect1 xml:id="introduction-devel">
+ <title>在 FreeBSD 開發程式</title>
+ <para>好了我們開始吧!我想你的 FreeBSD 已經安裝好了,而且已經準備好要用它寫點程式了吧?
+ 但是要從哪裡開始呢?&os; 有提供寫程式的程式或環境嗎?
+ 身為 programer 的我可以做什麼呢?</para>
+
+ <para>本章試著回答你一些問題,當然,單就 programming 程度來說可分很多種層次,
+ 有的人只是單純當興趣,有的則是他的專業,
+ 本章主要內容是針對程式初學者,
+ 當然,對於那些不熟 &os; 的程式開發者而言,本文件內容也是十分實用的。</para>
+ </sect1>
+
+ <sect1 xml:id="introduction-bsdvision">
+ <title>The BSD Vision</title>
+
+ <para>為了讓你寫出來的程式在 &unix; like系統上具有良好的使用性、效能和穩定性,
+ 我們必須跟你介紹一些程式概念(original software tools ideology)。 </para>
+ </sect1>
+
+ <sect1 xml:id="introduction-archguide">
+ <title>程式架構指南</title>
+
+ <para>我們想介紹的概念如下</para>
+
+ <itemizedlist>
+
+ <listitem><para>在整個程式還沒寫完前,不要增加新的功能。</para></listitem>
+
+ <listitem><para>另外一個重點就是,讓你自己選擇你的程式將會具有何種功能,
+ 而不是讓別人決定,不想要去滿足全世界的需求,除非你想讓你的程式具有擴充性或相容性。</para></listitem>
+
+ <listitem><para>千萬記住:在沒有相關經驗時,參考範例程式碼所寫出來的程式,
+ 會比自己憑空寫出來的好。</para></listitem>
+
+ <listitem><para>當你寫的程式沒辦法完全解決問題時,最好的方法就是不要試著要去解決它。</para></listitem>
+
+ <listitem><para>若用 10% 的心力就能輕鬆完成 90% 的工作份量,就用這個簡單法子吧。</para></listitem>
+
+ <listitem><para>盡可能地簡化問題的複雜。</para></listitem>
+
+ <listitem><para>提供機制(mechanism),而非原則(policy)。
+ 比方說,把使用者介面選擇權交由使用者來決定。</para></listitem>
+
+ </itemizedlist>
+
+ <para>以上摘自 Scheifler &amp; Gettys 的 "X Window System" 論文</para>
+
+ </sect1>
+
+ <sect1 xml:id="introduction-layout">
+ <title><filename>/usr/src</filename> 的架構</title>
+
+ <para>完整的 FreeBSD 原始碼都在公開的 CVS repository 中。
+ 通常 FreeBSD 原始碼都會裝在 <filename>/usr/src</filename>,
+ 而且包含下列子目錄:</para>
+
+ <para>
+ <informaltable frame="none" pgwide="1">
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Directory</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><filename>bin/</filename></entry>
+ <entry>Source for files in
+ <filename>/bin</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>contrib/</filename></entry>
+ <entry>Source for files from contributed software.</entry>
+ </row>
+
+ <row>
+ <entry><filename>crypto/</filename></entry>
+ <entry>Cryptographical sources</entry>
+ </row>
+
+ <row>
+ <entry><filename>etc/</filename></entry>
+ <entry>Source for files in <filename>/etc</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>games/</filename></entry>
+ <entry>Source for files in <filename>/usr/games</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>gnu/</filename></entry>
+ <entry>Utilities covered by the GNU Public License</entry>
+ </row>
+
+ <row>
+ <entry><filename>include/</filename></entry>
+ <entry>Source for files in <filename>/usr/include</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>kerberos5/</filename></entry>
+ <entry>Source for Kerberos version 5</entry>
+ </row>
+
+ <row>
+ <entry><filename>lib/</filename></entry>
+ <entry>Source for files in <filename>/usr/lib</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>libexec/</filename></entry>
+ <entry>Source for files in <filename>/usr/libexec</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>release/</filename></entry>
+ <entry>Files required to produce a FreeBSD release</entry>
+ </row>
+
+ <row>
+ <entry><filename>rescue/</filename></entry>
+ <entry>Build system for the
+ <filename>/rescue</filename> utilities</entry>
+ </row>
+
+ <row>
+ <entry><filename>sbin/</filename></entry>
+ <entry>Source for files in <filename>/sbin</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>secure/</filename></entry>
+ <entry>FreeSec sources</entry>
+ </row>
+
+ <row>
+ <entry><filename>share/</filename></entry>
+ <entry>Source for files in <filename>/usr/share</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>sys/</filename></entry>
+ <entry>Kernel source files</entry>
+ </row>
+
+ <row>
+ <entry><filename>tools/</filename></entry>
+ <entry>Tools used for maintenance and testing of
+ FreeBSD</entry>
+ </row>
+
+ <row>
+ <entry><filename>usr.bin/</filename></entry>
+ <entry>Source for files in <filename>/usr/bin</filename></entry>
+ </row>
+
+ <row>
+ <entry><filename>usr.sbin/</filename></entry>
+ <entry>Source for files in <filename>/usr/sbin</filename></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect1>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/ipv6/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/ipv6/chapter.xml
new file mode 100644
index 0000000000..a7b78244fb
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/ipv6/chapter.xml
@@ -0,0 +1,1571 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="ipv6">
+ <title>IPv6 Internals</title>
+
+ <sect1 xml:id="ipv6-implementation">
+ <info><title>IPv6/IPsec Implementation</title>
+ <authorgroup>
+ <author><personname><firstname>Yoshinobu</firstname><surname>Inoue</surname></personname><contrib>Contributed by </contrib></author>
+ </authorgroup>
+
+ </info>
+
+
+
+ <para>This section should explain IPv6 and IPsec related implementation
+ internals. These functionalities are derived from <link xlink:href="http://www.kame.net/">KAME project</link></para>
+
+ <sect2 xml:id="ipv6details">
+ <title>IPv6</title>
+
+ <sect3>
+ <title>Conformance</title>
+
+ <para>The IPv6 related functions conforms, or tries to conform to
+ the latest set of IPv6 specifications. For future reference we list
+ some of the relevant documents below (<emphasis>NOTE</emphasis>: this
+ is not a complete list - this is too hard to maintain...).</para>
+
+ <para>For details please refer to specific chapter in the document,
+ RFCs, manual pages, or comments in the source code.</para>
+
+ <para>Conformance tests have been performed on the KAME STABLE kit
+ at TAHI project. Results can be viewed at
+ <uri xlink:href="http://www.tahi.org/report/KAME/">http://www.tahi.org/report/KAME/</uri>.
+ We also attended Univ. of New Hampshire IOL tests
+ (<uri xlink:href="http://www.iol.unh.edu/">http://www.iol.unh.edu/</uri>) in the
+ past, with our past snapshots.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>RFC1639: FTP Operation Over Big Address Records
+ (FOOBAR)</para>
+ <itemizedlist>
+ <listitem>
+ <para>RFC2428 is preferred over RFC1639. FTP clients will
+ first try RFC2428, then RFC1639 if failed.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC1886: DNS Extensions to support IPv6</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC1933: Transition Mechanisms for IPv6 Hosts and
+ Routers</para>
+ <itemizedlist>
+ <listitem>
+ <para>IPv4 compatible address is not supported.</para>
+ </listitem>
+ <listitem>
+ <para>automatic tunneling (described in 4.3 of this RFC) is not
+ supported.</para>
+ </listitem>
+ <listitem>
+ <para>&man.gif.4; interface implements IPv[46]-over-IPv[46]
+ tunnel in a generic way, and it covers "configured tunnel"
+ described in the spec. See <link linkend="gif">23.5.1.5</link>
+ in this document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC1981: Path MTU Discovery for IPv6</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2080: RIPng for IPv6</para>
+ <itemizedlist>
+ <listitem>
+ <para>usr.sbin/route6d support this.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2292: Advanced Sockets API for IPv6</para>
+ <itemizedlist>
+ <listitem>
+ <para>For supported library functions/kernel APIs, see
+ <filename>sys/netinet6/ADVAPI</filename>.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2362: Protocol Independent Multicast-Sparse
+ Mode (PIM-SM)</para>
+ <itemizedlist>
+ <listitem>
+ <para>RFC2362 defines packet formats for PIM-SM.
+ <filename>draft-ietf-pim-ipv6-01.txt</filename> is
+ written based on this.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2373: IPv6 Addressing Architecture</para>
+ <itemizedlist>
+ <listitem>
+ <para>supports node required addresses, and conforms to
+ the scope requirement.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2374: An IPv6 Aggregatable Global Unicast Address
+ Format</para>
+ <itemizedlist>
+ <listitem>
+ <para>supports 64-bit length of Interface ID.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2375: IPv6 Multicast Address Assignments</para>
+ <itemizedlist>
+ <listitem>
+ <para>Userland applications use the well-known addresses
+ assigned in the RFC.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2428: FTP Extensions for IPv6 and NATs</para>
+ <itemizedlist>
+ <listitem>
+ <para>RFC2428 is preferred over RFC1639. FTP clients will
+ first try RFC2428, then RFC1639 if failed.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2460: IPv6 specification</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2461: Neighbor discovery for IPv6</para>
+ <itemizedlist>
+ <listitem>
+ <para>See <link linkend="neighbor-discovery">23.5.1.2</link>
+ in this document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2462: IPv6 Stateless Address Autoconfiguration</para>
+ <itemizedlist>
+ <listitem>
+ <para>See <link linkend="ipv6-pnp">23.5.1.4</link> in this
+ document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2463: ICMPv6 for IPv6 specification</para>
+ <itemizedlist>
+ <listitem>
+ <para>See <link linkend="icmpv6">23.5.1.9</link> in this
+ document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2464: Transmission of IPv6 Packets over Ethernet
+ Networks</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2465: MIB for IPv6: Textual Conventions and General
+ Group</para>
+ <itemizedlist>
+ <listitem>
+ <para>Necessary statistics are gathered by the kernel. Actual
+ IPv6 MIB support is provided as a patchkit for ucd-snmp.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2466: MIB for IPv6: ICMPv6 group</para>
+ <itemizedlist>
+ <listitem>
+ <para>Necessary statistics are gathered by the kernel. Actual
+ IPv6 MIB support is provided as patchkit for ucd-snmp.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2467: Transmission of IPv6 Packets over FDDI
+ Networks</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2497: Transmission of IPv6 packet over ARCnet
+ Networks</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2553: Basic Socket Interface Extensions for IPv6</para>
+ <itemizedlist>
+ <listitem>
+ <para>IPv4 mapped address (3.7) and special behavior of IPv6
+ wildcard bind socket (3.8) are supported. See <link linkend="ipv6-wildcard-socket">23.5.1.12</link>
+ in this document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2675: IPv6 Jumbograms</para>
+ <itemizedlist>
+ <listitem>
+ <para>See <link linkend="ipv6-jumbo">23.5.1.7</link> in
+ this document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>RFC2710: Multicast Listener Discovery for IPv6</para>
+ </listitem>
+
+ <listitem>
+ <para>RFC2711: IPv6 router alert option</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-ietf-ipngwg-router-renum-08</filename>: Router
+ renumbering for IPv6</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-ietf-ipngwg-icmp-namelookups-02</filename>:
+ IPv6 Name Lookups Through ICMP</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-ietf-ipngwg-icmp-name-lookups-03</filename>:
+ IPv6 Name Lookups Through ICMP</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-ietf-pim-ipv6-01.txt</filename>:
+ PIM for IPv6</para>
+ <itemizedlist>
+ <listitem>
+ <para>&man.pim6dd.8; implements dense mode. &man.pim6sd.8;
+ implements sparse mode.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-itojun-ipv6-tcp-to-anycast-00</filename>:
+ Disconnecting TCP connection toward IPv6 anycast address</para>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-yamamoto-wideipv6-comm-model-00</filename>
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>See <link linkend="ipv6-sas">23.5.1.6</link> in this
+ document for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para><filename>draft-ietf-ipngwg-scopedaddr-format-00.txt
+ </filename>: An Extension of Format for IPv6 Scoped
+ Addresses</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 xml:id="neighbor-discovery">
+ <title>Neighbor Discovery</title>
+
+ <para>Neighbor Discovery is fairly stable. Currently Address
+ Resolution, Duplicated Address Detection, and Neighbor Unreachability
+ Detection are supported. In the near future we will be adding Proxy
+ Neighbor Advertisement support in the kernel and Unsolicited Neighbor
+ Advertisement transmission command as admin tool.</para>
+
+ <para>If DAD fails, the address will be marked "duplicated" and
+ message will be generated to syslog (and usually to console). The
+ "duplicated" mark can be checked with &man.ifconfig.8;. It is
+ administrators' responsibility to check for and recover from DAD
+ failures. The behavior should be improved in the near future.</para>
+
+ <para>Some of the network driver loops multicast packets back to itself,
+ even if instructed not to do so (especially in promiscuous mode).
+ In such cases DAD may fail, because DAD engine sees inbound NS packet
+ (actually from the node itself) and considers it as a sign of duplicate.
+ You may want to look at #if condition marked "heuristics" in
+ sys/netinet6/nd6_nbr.c:nd6_dad_timer() as workaround (note that the code
+ fragment in "heuristics" section is not spec conformant).</para>
+
+ <para>Neighbor Discovery specification (RFC2461) does not talk about
+ neighbor cache handling in the following cases:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>when there was no neighbor cache entry, node
+ received unsolicited RS/NS/NA/redirect packet without
+ link-layer address</para>
+ </listitem>
+ <listitem>
+ <para>neighbor cache handling on medium without link-layer
+ address (we need a neighbor cache entry for IsRouter bit)</para>
+ </listitem>
+ </orderedlist>
+
+ <para>For first case, we implemented workaround based on discussions
+ on IETF ipngwg mailing list. For more details, see the comments in
+ the source code and email thread started from (IPng 7155), dated
+ Feb 6 1999.</para>
+
+ <para>IPv6 on-link determination rule (RFC2461) is quite different
+ from assumptions in BSD network code. At this moment, no on-link
+ determination rule is supported where default router list is empty
+ (RFC2461, section 5.2, last sentence in 2nd paragraph - note that
+ the spec misuse the word "host" and "node" in several places in
+ the section).</para>
+
+ <para>To avoid possible DoS attacks and infinite loops, only 10
+ options on ND packet is accepted now. Therefore, if you have 20
+ prefix options attached to RA, only the first 10 prefixes will be
+ recognized. If this troubles you, please ask it on FREEBSD-CURRENT
+ mailing list and/or modify nd6_maxndopt in
+ <filename>sys/netinet6/nd6.c</filename>. If there are high demands
+ we may provide sysctl knob for the variable.</para>
+ </sect3>
+
+ <sect3 xml:id="ipv6-scope-index">
+ <title>Scope Index</title>
+
+ <para>IPv6 uses scoped addresses. Therefore, it is very important to
+ specify scope index (interface index for link-local address, or
+ site index for site-local address) with an IPv6 address. Without
+ scope index, scoped IPv6 address is ambiguous to the kernel, and
+ kernel will not be able to determine the outbound interface for a
+ packet.</para>
+
+ <para>Ordinary userland applications should use advanced API
+ (RFC2292) to specify scope index, or interface index. For similar
+ purpose, sin6_scope_id member in sockaddr_in6 structure is defined
+ in RFC2553. However, the semantics for sin6_scope_id is rather vague.
+ If you care about portability of your application, we suggest you to
+ use advanced API rather than sin6_scope_id.</para>
+
+ <para>In the kernel, an interface index for link-local scoped address is
+ embedded into 2nd 16bit-word (3rd and 4th byte) in IPv6 address. For
+ example, you may see something like:
+ </para>
+
+ <screen> fe80:1::200:f8ff:fe01:6317
+ </screen>
+
+ <para>in the routing table and interface address structure (struct
+ in6_ifaddr). The address above is a link-local unicast address
+ which belongs to a network interface whose interface identifier is 1.
+ The embedded index enables us to identify IPv6 link local
+ addresses over multiple interfaces effectively and with only a
+ little code change.</para>
+
+ <para>Routing daemons and configuration programs, like &man.route6d.8;
+ and &man.ifconfig.8;, will need to manipulate the "embedded" scope
+ index. These programs use routing sockets and ioctls (like
+ SIOCGIFADDR_IN6) and the kernel API will return IPv6 addresses with
+ 2nd 16bit-word filled in. The APIs are for manipulating kernel
+ internal structure. Programs that use these APIs have to be prepared
+ about differences in kernels anyway.</para>
+
+ <para>When you specify scoped address to the command line, NEVER write
+ the embedded form (such as ff02:1::1 or fe80:2::fedc). This is not
+ supposed to work. Always use standard form, like ff02::1 or
+ fe80::fedc, with command line option for specifying interface (like
+ <command>ping6 -I ne0 ff02::1</command>). In general, if a command
+ does not have command line option to specify outgoing interface, that
+ command is not ready to accept scoped address. This may seem to be
+ opposite from IPv6's premise to support "dentist office" situation.
+ We believe that specifications need some improvements for this.</para>
+
+ <para>Some of the userland tools support extended numeric IPv6 syntax,
+ as documented in
+ <filename>draft-ietf-ipngwg-scopedaddr-format-00.txt</filename>. You
+ can specify outgoing link, by using name of the outgoing interface
+ like "fe80::1%ne0". This way you will be able to specify link-local
+ scoped address without much trouble.</para>
+
+ <para>To use this extension in your program, you will need to use
+ &man.getaddrinfo.3;, and &man.getnameinfo.3; with NI_WITHSCOPEID.
+ The implementation currently assumes 1-to-1 relationship between a
+ link and an interface, which is stronger than what specs say.</para>
+ </sect3>
+
+ <sect3 xml:id="ipv6-pnp">
+ <title>Plug and Play</title>
+
+ <para>Most of the IPv6 stateless address autoconfiguration is implemented
+ in the kernel. Neighbor Discovery functions are implemented in the
+ kernel as a whole. Router Advertisement (RA) input for hosts is
+ implemented in the kernel. Router Solicitation (RS) output for
+ endhosts, RS input for routers, and RA output for routers are
+ implemented in the userland.</para>
+
+ <sect4>
+ <title>Assignment of link-local, and special addresses</title>
+
+ <para>IPv6 link-local address is generated from IEEE802 address
+ (Ethernet MAC address). Each of interface is assigned an IPv6
+ link-local address automatically, when the interface becomes up
+ (IFF_UP). Also, direct route for the link-local address is added
+ to routing table.</para>
+
+ <para>Here is an output of netstat command:</para>
+
+<screen>Internet6:
+Destination Gateway Flags Netif Expire
+fe80:1::%ed0/64 link#1 UC ed0
+fe80:2::%ep0/64 link#2 UC ep0</screen>
+
+ <para>Interfaces that has no IEEE802 address (pseudo interfaces
+ like tunnel interfaces, or ppp interfaces) will borrow IEEE802
+ address from other interfaces, such as Ethernet interfaces,
+ whenever possible. If there is no IEEE802 hardware attached,
+ a last resort pseudo-random value, MD5(hostname), will
+ be used as source of link-local address. If it is not suitable
+ for your usage, you will need to configure the link-local address
+ manually.</para>
+
+ <para>If an interface is not capable of handling IPv6 (such as
+ lack of multicast support), link-local address will not be
+ assigned to that interface. See section 2 for details.</para>
+
+ <para>Each interface joins the solicited multicast address and the
+ link-local all-nodes multicast addresses (e.g. fe80::1:ff01:6317
+ and ff02::1, respectively, on the link the interface is attached).
+ In addition to a link-local address, the loopback address (::1)
+ will be assigned to the loopback interface. Also, ::1/128 and
+ ff01::/32 are automatically added to routing table, and loopback
+ interface joins node-local multicast group ff01::1.</para>
+ </sect4>
+
+ <sect4>
+ <title>Stateless address autoconfiguration on hosts</title>
+
+ <para>In IPv6 specification, nodes are separated into two categories:
+ <emphasis>routers</emphasis> and <emphasis>hosts</emphasis>. Routers
+ forward packets addressed to others, hosts does not forward the
+ packets. net.inet6.ip6.forwarding defines whether this node is
+ router or host (router if it is 1, host if it is 0).</para>
+
+ <para>When a host hears Router Advertisement from the router, a host
+ may autoconfigure itself by stateless address autoconfiguration.
+ This behavior can be controlled by net.inet6.ip6.accept_rtadv (host
+ autoconfigures itself if it is set to 1). By autoconfiguration,
+ network address prefix for the receiving interface (usually global
+ address prefix) is added. Default route is also configured.
+ Routers periodically generate Router Advertisement packets. To
+ request an adjacent router to generate RA packet, a host can
+ transmit Router Solicitation. To generate a RS packet at any time,
+ use the <emphasis>rtsol</emphasis> command. &man.rtsold.8; daemon is
+ also available. &man.rtsold.8; generates Router Solicitation whenever
+ necessary, and it works great for nomadic usage (notebooks/laptops).
+ If one wishes to ignore Router Advertisements, use sysctl to set
+ net.inet6.ip6.accept_rtadv to 0.</para>
+
+ <para>To generate Router Advertisement from a router, use the
+ &man.rtadvd.8; daemon.</para>
+
+ <para>Note that, IPv6 specification assumes the following items, and
+ nonconforming cases are left unspecified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Only hosts will listen to router advertisements</para>
+ </listitem>
+ <listitem>
+ <para>Hosts have single network interface (except loopback)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Therefore, this is unwise to enable net.inet6.ip6.accept_rtadv
+ on routers, or multi-interface host. A misconfigured node can
+ behave strange (nonconforming configuration allowed for those who
+ would like to do some experiments).</para>
+
+ <para>To summarize the sysctl knob:</para>
+
+ <screen> accept_rtadv forwarding role of the node
+ --- --- ---
+ 0 0 host (to be manually configured)
+ 0 1 router
+ 1 0 autoconfigured host
+ (spec assumes that host has single
+ interface only, autoconfigured host
+ with multiple interface is
+ out-of-scope)
+ 1 1 invalid, or experimental
+ (out-of-scope of spec)</screen>
+
+ <para>RFC2462 has validation rule against incoming RA prefix
+ information option, in 5.5.3 (e). This is to protect hosts from
+ malicious (or misconfigured) routers that advertise very short
+ prefix lifetime. There was an update from Jim Bound to ipngwg
+ mailing list (look for "(ipng 6712)" in the archive) and it is
+ implemented Jim's update.</para>
+
+ <para>See <link linkend="neighbor-discovery">23.5.1.2</link> in
+ the document for relationship between DAD and
+ autoconfiguration.</para>
+ </sect4>
+ </sect3>
+
+ <sect3 xml:id="gif">
+ <title>Generic tunnel interface</title>
+
+ <para>GIF (Generic InterFace) is a pseudo interface for configured
+ tunnel. Details are described in &man.gif.4;. Currently</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>v6 in v6</para>
+ </listitem>
+ <listitem>
+ <para>v6 in v4</para>
+ </listitem>
+ <listitem>
+ <para>v4 in v6</para>
+ </listitem>
+ <listitem>
+ <para>v4 in v4</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>are available. Use &man.gifconfig.8; to assign physical (outer)
+ source and destination address to gif interfaces. Configuration that
+ uses same address family for inner and outer IP header (v4 in v4, or
+ v6 in v6) is dangerous. It is very easy to configure interfaces and
+ routing tables to perform infinite level of tunneling.
+ <emphasis>Please be warned</emphasis>.</para>
+
+ <para>gif can be configured to be ECN-friendly. See <link linkend="ipsec-ecn">23.5.4.5</link> for ECN-friendliness of
+ tunnels, and &man.gif.4; for how to configure.</para>
+
+ <para>If you would like to configure an IPv4-in-IPv6 tunnel with gif
+ interface, read &man.gif.4; carefully. You will need to
+ remove IPv6 link-local address automatically assigned to the gif
+ interface.</para>
+ </sect3>
+
+ <sect3 xml:id="ipv6-sas">
+ <title>Source Address Selection</title>
+
+ <para>Current source selection rule is scope oriented (there are some
+ exceptions - see below). For a given destination, a source IPv6
+ address is selected by the following rule:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>If the source address is explicitly specified by
+ the user (e.g. via the advanced API), the specified address
+ is used.</para>
+ </listitem>
+
+ <listitem>
+ <para>If there is an address assigned to the outgoing
+ interface (which is usually determined by looking up the
+ routing table) that has the same scope as the destination
+ address, the address is used.</para>
+
+ <para>This is the most typical case.</para>
+ </listitem>
+
+ <listitem>
+ <para>If there is no address that satisfies the above
+ condition, choose a global address assigned to one of
+ the interfaces on the sending node.</para>
+ </listitem>
+
+ <listitem>
+ <para>If there is no address that satisfies the above condition,
+ and destination address is site local scope, choose a site local
+ address assigned to one of the interfaces on the sending node.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>If there is no address that satisfies the above condition,
+ choose the address associated with the routing table entry for the
+ destination. This is the last resort, which may cause scope
+ violation.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>For instance, ::1 is selected for ff01::1,
+ fe80:1::200:f8ff:fe01:6317 for fe80:1::2a0:24ff:feab:839b (note
+ that embedded interface index - described in <link linkend="ipv6-scope-index">23.5.1.3</link> - helps us
+ choose the right source address. Those embedded indices will not
+ be on the wire). If the outgoing interface has multiple address for
+ the scope, a source is selected longest match basis (rule 3). Suppose
+ 3ffe:501:808:1:200:f8ff:fe01:6317 and 3ffe:2001:9:124:200:f8ff:fe01:6317
+ are given to the outgoing interface. 3ffe:501:808:1:200:f8ff:fe01:6317
+ is chosen as the source for the destination 3ffe:501:800::1.</para>
+
+ <para>Note that the above rule is not documented in the IPv6 spec.
+ It is considered "up to implementation" item. There are some cases
+ where we do not use the above rule. One example is connected TCP
+ session, and we use the address kept in tcb as the source. Another
+ example is source address for Neighbor Advertisement. Under the spec
+ (RFC2461 7.2.2) NA's source should be the target address of the
+ corresponding NS's target. In this case we follow the spec rather
+ than the above longest-match rule.</para>
+
+ <para>For new connections (when rule 1 does not apply), deprecated
+ addresses (addresses with preferred lifetime = 0) will not be chosen
+ as source address if other choices are available. If no other choices
+ are available, deprecated address will be used as a last resort. If
+ there are multiple choice of deprecated addresses, the above scope
+ rule will be used to choose from those deprecated addresses. If you
+ would like to prohibit the use of deprecated address for some reason,
+ configure net.inet6.ip6.use_deprecated to 0. The issue related to
+ deprecated address is described in RFC2462 5.5.4 (NOTE: there is
+ some debate underway in IETF ipngwg on how to use "deprecated"
+ address).</para>
+ </sect3>
+
+ <sect3 xml:id="ipv6-jumbo">
+ <title>Jumbo Payload</title>
+
+ <para>The Jumbo Payload hop-by-hop option is implemented and can
+ be used to send IPv6 packets with payloads longer than 65,535 octets.
+ But currently no physical interface whose MTU is more than 65,535 is
+ supported, so such payloads can be seen only on the loopback
+ interface (i.e. lo0).</para>
+
+ <para>If you want to try jumbo payloads, you first have to reconfigure
+ the kernel so that the MTU of the loopback interface is more than
+ 65,535 bytes; add the following to the kernel configuration file:</para>
+
+ <para><literal>
+ options "LARGE_LOMTU" #To test jumbo payload
+ </literal></para>
+
+ <para>and recompile the new kernel.</para>
+
+ <para>Then you can test jumbo payloads by the &man.ping6.8; command
+ with -b and -s options. The -b option must be specified to enlarge
+ the size of the socket buffer and the -s option specifies the length
+ of the packet, which should be more than 65,535. For example,
+ type as follows:</para>
+
+ <screen>&prompt.user; <userinput>ping6 -b 70000 -s 68000 ::1</userinput></screen>
+
+ <para>The IPv6 specification requires that the Jumbo Payload option
+ must not be used in a packet that carries a fragment header. If
+ this condition is broken, an ICMPv6 Parameter Problem message must
+ be sent to the sender. specification is followed, but you cannot
+ usually see an ICMPv6 error caused by this requirement.</para>
+
+ <para>When an IPv6 packet is received, the frame length is checked and
+ compared to the length specified in the payload length field of the
+ IPv6 header or in the value of the Jumbo Payload option, if any. If
+ the former is shorter than the latter, the packet is discarded and
+ statistics are incremented. You can see the statistics as output of
+ &man.netstat.8; command with `-s -p ip6' option:</para>
+
+ <screen>&prompt.user; <userinput>netstat -s -p ip6</userinput>
+ ip6:
+ (snip)
+ 1 with data size &lt; data length</screen>
+
+ <para>So, kernel does not send an ICMPv6 error unless the erroneous
+ packet is an actual Jumbo Payload, that is, its packet size is more
+ than 65,535 bytes. As described above, currently no physical interface
+ with such a huge MTU is supported, so it rarely returns an
+ ICMPv6 error.</para>
+
+ <para>TCP/UDP over jumbogram is not supported at this moment. This
+ is because we have no medium (other than loopback) to test this.
+ Contact us if you need this.</para>
+
+ <para>IPsec does not work on jumbograms. This is due to some
+ specification twists in supporting AH with jumbograms (AH header
+ size influences payload length, and this makes it real hard to
+ authenticate inbound packet with jumbo payload option as well as AH).
+ </para>
+
+ <para>There are fundamental issues in *BSD support for jumbograms.
+ We would like to address those, but we need more time to finalize
+ these. To name a few:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>mbuf pkthdr.len field is typed as "int" in 4.4BSD, so
+ it will not hold jumbogram with len &gt; 2G on 32bit architecture
+ CPUs. If we would like to support jumbogram properly, the field
+ must be expanded to hold 4G + IPv6 header + link-layer header.
+ Therefore, it must be expanded to at least int64_t
+ (u_int32_t is NOT enough).</para>
+ </listitem>
+
+ <listitem>
+ <para>We mistakingly use "int" to hold packet length in many
+ places. We need to convert them into larger integral type.
+ It needs a great care, as we may experience overflow during
+ packet length computation.</para>
+ </listitem>
+
+ <listitem>
+ <para>We mistakingly check for ip6_plen field of IPv6 header
+ for packet payload length in various places. We should be
+ checking mbuf pkthdr.len instead. ip6_input() will perform
+ sanity check on jumbo payload option on input, and we can
+ safely use mbuf pkthdr.len afterwards.</para>
+ </listitem>
+
+ <listitem>
+ <para>TCP code needs a careful update in bunch of places, of
+ course.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>Loop prevention in header processing</title>
+
+ <para>IPv6 specification allows arbitrary number of extension headers
+ to be placed onto packets. If we implement IPv6 packet processing
+ code in the way BSD IPv4 code is implemented, kernel stack may
+ overflow due to long function call chain. sys/netinet6 code
+ is carefully designed to avoid kernel stack overflow. Because of
+ this, sys/netinet6 code defines its own protocol switch
+ structure, as "struct ip6protosw" (see
+ <filename>netinet6/ip6protosw.h</filename>). There is no such
+ update to IPv4 part (sys/netinet) for compatibility, but small
+ change is added to its pr_input() prototype. So "struct ipprotosw"
+ is also defined. Because of this, if you receive IPsec-over-IPv4
+ packet with massive number of IPsec headers, kernel stack may blow
+ up. IPsec-over-IPv6 is okay. (Off-course, for those all IPsec
+ headers to be processed, each such IPsec header must pass each
+ IPsec check. So an anonymous attacker will not be able to do such an
+ attack.)</para>
+ </sect3>
+
+ <sect3 xml:id="icmpv6">
+ <title>ICMPv6</title>
+
+ <para>After RFC2463 was published, IETF ipngwg has decided to
+ disallow ICMPv6 error packet against ICMPv6 redirect, to prevent
+ ICMPv6 storm on a network medium. This is already implemented
+ into the kernel.</para>
+ </sect3>
+
+ <sect3>
+ <title>Applications</title>
+
+ <para>For userland programming, we support IPv6 socket API as
+ specified in RFC2553, RFC2292 and upcoming Internet drafts.</para>
+
+ <para>TCP/UDP over IPv6 is available and quite stable. You can
+ enjoy &man.telnet.1;, &man.ftp.1;, &man.rlogin.1;, &man.rsh.1;,
+ &man.ssh.1;, etc. These applications are protocol independent.
+ That is, they automatically chooses IPv4 or IPv6 according to DNS.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Kernel Internals</title>
+
+ <para>While ip_forward() calls ip_output(), ip6_forward() directly
+ calls if_output() since routers must not divide IPv6 packets into
+ fragments.</para>
+
+ <para>ICMPv6 should contain the original packet as long as possible
+ up to 1280. UDP6/IP6 port unreach, for instance, should contain
+ all extension headers and the *unchanged* UDP6 and IP6 headers.
+ So, all IP6 functions except TCP never convert network byte
+ order into host byte order, to save the original packet.</para>
+
+ <para>tcp_input(), udp6_input() and icmp6_input() can not assume that
+ IP6 header is preceding the transport headers due to extension
+ headers. So, in6_cksum() was implemented to handle packets whose IP6
+ header and transport header is not continuous. TCP/IP6 nor UDP6/IP6
+ header structures do not exist for checksum calculation.</para>
+
+ <para>To process IP6 header, extension headers and transport headers
+ easily, network drivers are now required to store packets in one
+ internal mbuf or one or more external mbufs. A typical old driver
+ prepares two internal mbufs for 96 - 204 bytes data, however, now
+ such packet data is stored in one external mbuf.</para>
+
+ <para><command>netstat -s -p ip6</command> tells you whether or not
+ your driver conforms such requirement. In the following example,
+ "cce0" violates the requirement. (For more information, refer to
+ Section 2.)</para>
+
+ <screen>Mbuf statistics:
+ 317 one mbuf
+ two or more mbuf::
+ lo0 = 8
+ cce0 = 10
+ 3282 one ext mbuf
+ 0 two or more ext mbuf
+ </screen>
+
+ <para>Each input function calls IP6_EXTHDR_CHECK in the beginning to
+ check if the region between IP6 and its header is continuous.
+ IP6_EXTHDR_CHECK calls m_pullup() only if the mbuf has M_LOOP flag,
+ that is, the packet comes from the loopback interface. m_pullup()
+ is never called for packets coming from physical network interfaces.
+ </para>
+
+ <para>Both IP and IP6 reassemble functions never call m_pullup().</para>
+ </sect3>
+
+ <sect3 xml:id="ipv6-wildcard-socket">
+ <title>IPv4 mapped address and IPv6 wildcard socket</title>
+
+ <para>RFC2553 describes IPv4 mapped address (3.7) and special behavior
+ of IPv6 wildcard bind socket (3.8). The spec allows you to:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Accept IPv4 connections by AF_INET6 wildcard bind
+ socket.</para>
+ </listitem>
+ <listitem>
+ <para>Transmit IPv4 packet over AF_INET6 socket by using
+ special form of the address like ::ffff:10.1.1.1.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>but the spec itself is very complicated and does not specify
+ how the socket layer should behave. Here we call the former one
+ "listening side" and the latter one "initiating side", for
+ reference purposes.</para>
+
+ <para>You can perform wildcard bind on both of the address families,
+ on the same port.</para>
+
+ <para>The following table show the behavior of FreeBSD 4.x.</para>
+
+ <screen>listening side initiating side
+ (AF_INET6 wildcard (connection to ::ffff:10.1.1.1)
+ socket gets IPv4 conn.)
+ --- ---
+FreeBSD 4.x configurable supported
+ default: enabled
+ </screen>
+
+ <para>The following sections will give you more details, and how you can
+ configure the behavior.</para>
+
+ <para>Comments on listening side:</para>
+
+ <para>It looks that RFC2553 talks too little on wildcard bind issue,
+ especially on the port space issue, failure mode and relationship
+ between AF_INET/INET6 wildcard bind. There can be several separate
+ interpretation for this RFC which conform to it but behaves differently.
+ So, to implement portable application you should assume nothing
+ about the behavior in the kernel. Using &man.getaddrinfo.3; is the
+ safest way. Port number space and wildcard bind issues were discussed
+ in detail on ipv6imp mailing list, in mid March 1999 and it looks
+ that there is no concrete consensus (means, up to implementers).
+ You may want to check the mailing list archives.</para>
+
+ <para>If a server application would like to accept IPv4 and IPv6
+ connections, there will be two alternatives.</para>
+
+ <para>One is using AF_INET and AF_INET6 socket (you will need two
+ sockets). Use &man.getaddrinfo.3; with AI_PASSIVE into ai_flags,
+ and &man.socket.2; and &man.bind.2; to all the addresses returned.
+ By opening multiple sockets, you can accept connections onto the
+ socket with proper address family. IPv4 connections will be
+ accepted by AF_INET socket, and IPv6 connections will be accepted
+ by AF_INET6 socket.</para>
+
+ <para>Another way is using one AF_INET6 wildcard bind socket. Use
+ &man.getaddrinfo.3; with AI_PASSIVE into ai_flags and with
+ AF_INET6 into ai_family, and set the 1st argument hostname to
+ NULL. And &man.socket.2; and &man.bind.2; to the address returned.
+ (should be IPv6 unspecified addr). You can accept either of IPv4
+ and IPv6 packet via this one socket.</para>
+
+ <para>To support only IPv6 traffic on AF_INET6 wildcard binded socket
+ portably, always check the peer address when a connection is made
+ toward AF_INET6 listening socket. If the address is IPv4 mapped
+ address, you may want to reject the connection. You can check the
+ condition by using IN6_IS_ADDR_V4MAPPED() macro.</para>
+
+ <para>To resolve this issue more easily, there is system dependent
+ &man.setsockopt.2; option, IPV6_BINDV6ONLY, used like below.</para>
+
+ <screen> int on;
+
+ setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,
+ (char *)&amp;on, sizeof (on)) &lt; 0));
+ </screen>
+
+ <para>When this call succeed, then this socket only receive IPv6
+ packets.</para>
+
+ <para>Comments on initiating side:</para>
+
+ <para>Advise to application implementers: to implement a portable
+ IPv6 application (which works on multiple IPv6 kernels), we believe
+ that the following is the key to the success:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>NEVER hardcode AF_INET nor AF_INET6.</para>
+ </listitem>
+
+ <listitem>
+ <para>Use &man.getaddrinfo.3; and &man.getnameinfo.3;
+ throughout the system. Never use gethostby*(), getaddrby*(),
+ inet_*() or getipnodeby*(). (To update existing applications
+ to be IPv6 aware easily, sometime getipnodeby*() will be
+ useful. But if possible, try to rewrite the code to use
+ &man.getaddrinfo.3; and &man.getnameinfo.3;.)</para>
+ </listitem>
+
+ <listitem>
+ <para>If you would like to connect to destination, use
+ &man.getaddrinfo.3; and try all the destination returned,
+ like &man.telnet.1; does.</para>
+ </listitem>
+
+ <listitem>
+ <para>Some of the IPv6 stack is shipped with buggy
+ &man.getaddrinfo.3;. Ship a minimal working version with
+ your application and use that as last resort.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If you would like to use AF_INET6 socket for both IPv4 and
+ IPv6 outgoing connection, you will need to use &man.getipnodebyname.3;.
+ When you would like to update your existing application to be IPv6
+ aware with minimal effort, this approach might be chosen. But please
+ note that it is a temporal solution, because &man.getipnodebyname.3;
+ itself is not recommended as it does not handle scoped IPv6 addresses
+ at all. For IPv6 name resolution, &man.getaddrinfo.3; is the
+ preferred API. So you should rewrite your application to use
+ &man.getaddrinfo.3;, when you get the time to do it.</para>
+
+ <para>When writing applications that make outgoing connections,
+ story goes much simpler if you treat AF_INET and AF_INET6 as totally
+ separate address family. {set,get}sockopt issue goes simpler,
+ DNS issue will be made simpler. We do not recommend you to rely
+ upon IPv4 mapped address.</para>
+
+ <sect4>
+ <title>unified tcp and inpcb code</title>
+
+ <para>FreeBSD 4.x uses shared tcp code between IPv4 and IPv6
+ (from sys/netinet/tcp*) and separate udp4/6 code. It uses
+ unified inpcb structure.</para>
+
+ <para>The platform can be configured to support IPv4 mapped address.
+ Kernel configuration is summarized as follows:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>By default, AF_INET6 socket will grab IPv4
+ connections in certain condition, and can initiate
+ connection to IPv4 destination embedded in IPv4 mapped
+ IPv6 address.</para>
+ </listitem>
+
+ <listitem>
+ <para>You can disable it on entire system with sysctl like
+ below.</para>
+
+ <para>
+ <command>sysctl net.inet6.ip6.mapped_addr=0</command>
+ </para>
+
+ </listitem>
+ </itemizedlist>
+
+ <sect5>
+ <title>listening side</title>
+
+ <para>Each socket can be configured to support special AF_INET6
+ wildcard bind (enabled by default). You can disable it on
+ each socket basis with &man.setsockopt.2; like below.</para>
+
+ <screen> int on;
+
+ setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,
+ (char *)&amp;on, sizeof (on)) &lt; 0));
+ </screen>
+
+ <para>Wildcard AF_INET6 socket grabs IPv4 connection if and only
+ if the following conditions are satisfied:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>there is no AF_INET socket that matches the IPv4
+ connection</para>
+ </listitem>
+
+ <listitem>
+ <para>the AF_INET6 socket is configured to accept IPv4
+ traffic, i.e. getsockopt(IPV6_BINDV6ONLY) returns 0.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>There is no problem with open/close ordering.</para>
+ </sect5>
+
+ <sect5>
+ <title>initiating side</title>
+
+ <para>FreeBSD 4.x supports outgoing connection to IPv4 mapped
+ address (::ffff:10.1.1.1), if the node is configured to support
+ IPv4 mapped address.</para>
+ </sect5>
+ </sect4>
+ </sect3>
+
+ <sect3>
+ <title>sockaddr_storage</title>
+
+ <para>When RFC2553 was about to be finalized, there was discussion on
+ how struct sockaddr_storage members are named. One proposal is to
+ prepend "__" to the members (like "__ss_len") as they should not be
+ touched. The other proposal was not to prepend it (like "ss_len")
+ as we need to touch those members directly. There was no clear
+ consensus on it.</para>
+
+ <para>As a result, RFC2553 defines struct sockaddr_storage as
+ follows:</para>
+
+ <screen> struct sockaddr_storage {
+ u_char __ss_len; /* address length */
+ u_char __ss_family; /* address family */
+ /* and bunch of padding */
+ };
+ </screen>
+
+ <para>On the contrary, XNET draft defines as follows:</para>
+
+ <screen> struct sockaddr_storage {
+ u_char ss_len; /* address length */
+ u_char ss_family; /* address family */
+ /* and bunch of padding */
+ };
+ </screen>
+
+ <para>In December 1999, it was agreed that RFC2553bis should pick
+ the latter (XNET) definition.</para>
+
+ <para>Current implementation conforms to XNET definition, based on
+ RFC2553bis discussion.</para>
+
+ <para>If you look at multiple IPv6 implementations, you will be able
+ to see both definitions. As an userland programmer, the most
+ portable way of dealing with it is to:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>ensure ss_family and/or ss_len are available on the
+ platform, by using GNU autoconf,</para>
+ </listitem>
+
+ <listitem>
+ <para>have -Dss_family=__ss_family to unify all occurrences
+ (including header file) into __ss_family, or</para>
+ </listitem>
+
+ <listitem>
+ <para>never touch __ss_family. cast to sockaddr * and use sa_family
+ like:</para>
+
+ <screen> struct sockaddr_storage ss;
+ family = ((struct sockaddr *)&amp;ss)-&gt;sa_family
+ </screen>
+
+ </listitem>
+ </orderedlist>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Network Drivers</title>
+
+ <para>Now following two items are required to be supported by standard
+ drivers:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>mbuf clustering requirement. In this stable release, we
+ changed MINCLSIZE into MHLEN+1 for all the operating systems
+ in order to make all the drivers behave as we expect.</para>
+ </listitem>
+
+ <listitem>
+ <para>multicast. If &man.ifmcstat.8; yields no multicast group for
+ a interface, that interface has to be patched.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>If any of the drivers do not support the requirements, then
+ the drivers can not be used for IPv6 and/or IPsec communication. If
+ you find any problem with your card using IPv6/IPsec, then, please
+ report it to the &a.bugs;.</para>
+
+ <para>(NOTE: In the past we required all PCMCIA drivers to have a
+ call to in6_ifattach(). We have no such requirement any more)</para>
+ </sect2>
+
+ <sect2>
+ <title>Translator</title>
+
+ <para>We categorize IPv4/IPv6 translator into 4 types:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Translator A</emphasis> --- It is used in the early
+ stage of transition to make it possible to establish a
+ connection from an IPv6 host in an IPv6 island to an IPv4 host
+ in the IPv4 ocean.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Translator B</emphasis> --- It is used in the early
+ stage of transition to make it possible to establish a connection
+ from an IPv4 host in the IPv4 ocean to an IPv6 host in an
+ IPv6 island.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Translator C</emphasis> --- It is used in the late
+ stage of transition to make it possible to establish a
+ connection from an IPv4 host in an IPv4 island to an IPv6 host
+ in the IPv6 ocean.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Translator D</emphasis> --- It is used in the late
+ stage of transition to make it possible to establish a
+ connection from an IPv6 host in the IPv6 ocean to an IPv4 host
+ in an IPv4 island.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>TCP relay translator for category A is supported. This is called
+ "FAITH". We also provide IP header translator for category A.
+ (The latter is not yet put into FreeBSD 4.x yet.)</para>
+
+ <sect3>
+ <title>FAITH TCP relay translator</title>
+
+ <para>FAITH system uses TCP relay daemon called &man.faithd.8; helped
+ by the kernel. FAITH will reserve an IPv6 address prefix, and relay
+ TCP connection toward that prefix to IPv4 destination.</para>
+
+ <para>For example, if the reserved IPv6 prefix is
+ 3ffe:0501:0200:ffff::, and the IPv6 destination for TCP connection
+ is 3ffe:0501:0200:ffff::163.221.202.12, the connection will be
+ relayed toward IPv4 destination 163.221.202.12.</para>
+
+ <screen> destination IPv4 node (163.221.202.12)
+ ^
+ | IPv4 tcp toward 163.221.202.12
+ FAITH-relay dual stack node
+ ^
+ | IPv6 TCP toward 3ffe:0501:0200:ffff::163.221.202.12
+ source IPv6 node
+ </screen>
+
+ <para>&man.faithd.8; must be invoked on FAITH-relay dual stack
+ node.</para>
+
+ <para>For more details, consult
+ <filename>src/usr.sbin/faithd/README</filename></para>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="ipsec-implementation">
+ <title>IPsec</title>
+
+ <para>IPsec is mainly organized by three components.</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Policy Management</para>
+ </listitem>
+
+ <listitem>
+ <para>Key Management</para>
+ </listitem>
+
+ <listitem>
+ <para>AH and ESP handling</para>
+ </listitem>
+ </orderedlist>
+
+ <sect3>
+ <title>Policy Management</title>
+
+ <para>The kernel implements experimental policy management code.
+ There are two way to manage security policy. One is to configure
+ per-socket policy using &man.setsockopt.2;. In this cases, policy
+ configuration is described in &man.ipsec.set.policy.3;. The other
+ is to configure kernel packet filter-based policy using PF_KEY
+ interface, via &man.setkey.8;.</para>
+
+ <para>The policy entry is not re-ordered with its
+ indexes, so the order of entry when you add is very significant.</para>
+ </sect3>
+
+ <sect3>
+ <title>Key Management</title>
+
+ <para>The key management code implemented in this kit (sys/netkey)
+ is a home-brew PFKEY v2 implementation. This conforms to RFC2367.
+ </para>
+
+ <para>The home-brew IKE daemon, "racoon" is included in the
+ kit (kame/kame/racoon). Basically you will need to run racoon as
+ daemon, then set up a policy to require keys (like
+ <command>ping -P 'out ipsec esp/transport//use'</command>).
+ The kernel will contact racoon daemon as necessary to exchange
+ keys.</para>
+ </sect3>
+
+ <sect3>
+ <title>AH and ESP handling</title>
+
+ <para>IPsec module is implemented as "hooks" to the standard IPv4/IPv6
+ processing. When sending a packet, ip{,6}_output() checks if ESP/AH
+ processing is required by checking if a matching SPD (Security
+ Policy Database) is found. If ESP/AH is needed,
+ {esp,ah}{4,6}_output() will be called and mbuf will be updated
+ accordingly. When a packet is received, {esp,ah}4_input() will be
+ called based on protocol number, i.e. (*inetsw[proto])().
+ {esp,ah}4_input() will decrypt/check authenticity of the packet,
+ and strips off daisy-chained header and padding for ESP/AH. It is
+ safe to strip off the ESP/AH header on packet reception, since we
+ will never use the received packet in "as is" form.</para>
+
+ <para>By using ESP/AH, TCP4/6 effective data segment size will be
+ affected by extra daisy-chained headers inserted by ESP/AH. Our
+ code takes care of the case.</para>
+
+ <para>Basic crypto functions can be found in directory "sys/crypto".
+ ESP/AH transform are listed in {esp,ah}_core.c with wrapper functions.
+ If you wish to add some algorithm, add wrapper function in
+ {esp,ah}_core.c, and add your crypto algorithm code into
+ sys/crypto.</para>
+
+ <para>Tunnel mode is partially supported in this release, with the
+ following restrictions:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>IPsec tunnel is not combined with GIF generic tunneling
+ interface. It needs a great care because we may create an
+ infinite loop between ip_output() and tunnelifp-&gt;if_output().
+ Opinion varies if it is better to unify them, or not.</para>
+ </listitem>
+
+ <listitem>
+ <para>MTU and Don't Fragment bit (IPv4) considerations need more
+ checking, but basically works fine.</para>
+ </listitem>
+
+ <listitem>
+ <para>Authentication model for AH tunnel must be revisited.
+ We will need to improve the policy management engine,
+ eventually.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>Conformance to RFCs and IDs</title>
+
+ <para>The IPsec code in the kernel conforms (or, tries to conform)
+ to the following standards:</para>
+
+ <para>"old IPsec" specification documented in
+ <filename>rfc182[5-9].txt</filename></para>
+
+ <para>"new IPsec" specification documented in
+ <filename>rfc240[1-6].txt</filename>,
+ <filename>rfc241[01].txt</filename>, <filename>rfc2451.txt</filename>
+ and <filename>draft-mcdonald-simple-ipsec-api-01.txt</filename>
+ (draft expired, but you can take from <link xlink:href="ftp://ftp.kame.net/pub/internet-drafts/">
+ ftp://ftp.kame.net/pub/internet-drafts/</link>).
+ (NOTE: IKE specifications, <filename>rfc241[7-9].txt</filename> are
+ implemented in userland, as "racoon" IKE daemon)</para>
+
+ <para>Currently supported algorithms are:</para>
+ <itemizedlist>
+ <listitem>
+ <para>old IPsec AH</para>
+ <itemizedlist>
+ <listitem>
+ <para>null crypto checksum (no document, just for
+ debugging)</para>
+ </listitem>
+ <listitem>
+ <para>keyed MD5 with 128bit crypto checksum
+ (<filename>rfc1828.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>keyed SHA1 with 128bit crypto checksum
+ (no document)</para>
+ </listitem>
+ <listitem>
+ <para>HMAC MD5 with 128bit crypto checksum
+ (<filename>rfc2085.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>HMAC SHA1 with 128bit crypto checksum
+ (no document)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>old IPsec ESP</para>
+ <itemizedlist>
+ <listitem>
+ <para>null encryption (no document, similar to
+ <filename>rfc2410.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>DES-CBC mode (<filename>rfc1829.txt</filename>)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>new IPsec AH</para>
+ <itemizedlist>
+ <listitem>
+ <para>null crypto checksum (no document,
+ just for debugging)</para>
+ </listitem>
+ <listitem>
+ <para>keyed MD5 with 96bit crypto checksum
+ (no document)</para>
+ </listitem>
+ <listitem>
+ <para>keyed SHA1 with 96bit crypto checksum
+ (no document)</para>
+ </listitem>
+ <listitem>
+ <para>HMAC MD5 with 96bit crypto checksum
+ (<filename>rfc2403.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>HMAC SHA1 with 96bit crypto checksum
+ (<filename>rfc2404.txt</filename>)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>new IPsec ESP</para>
+ <itemizedlist>
+ <listitem>
+ <para>null encryption
+ (<filename>rfc2410.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>DES-CBC with derived IV
+ (<filename>draft-ietf-ipsec-ciph-des-derived-01.txt</filename>,
+ draft expired)</para>
+ </listitem>
+ <listitem>
+ <para>DES-CBC with explicit IV
+ (<filename>rfc2405.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>3DES-CBC with explicit IV
+ (<filename>rfc2451.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>BLOWFISH CBC
+ (<filename>rfc2451.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>CAST128 CBC
+ (<filename>rfc2451.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>RC5 CBC
+ (<filename>rfc2451.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>each of the above can be combined with:</para>
+ <itemizedlist>
+ <listitem>
+ <para>ESP authentication with HMAC-MD5(96bit)</para>
+ </listitem>
+ <listitem>
+ <para>ESP authentication with HMAC-SHA1(96bit)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ <para>The following algorithms are NOT supported:</para>
+ <itemizedlist>
+ <listitem>
+
+ <para>old IPsec AH</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>HMAC MD5 with 128bit crypto checksum + 64bit
+ replay prevention (<filename>rfc2085.txt</filename>)</para>
+ </listitem>
+ <listitem>
+ <para>keyed SHA1 with 160bit crypto checksum + 32bit padding
+ (<filename>rfc1852.txt</filename>)</para>
+ </listitem>
+ </itemizedlist>
+
+ </listitem>
+ </itemizedlist>
+
+ <para>IPsec (in kernel) and IKE (in userland as "racoon") has been
+ tested at several interoperability test events, and it is known to
+ interoperate with many other implementations well. Also, current
+ IPsec implementation as quite wide coverage for IPsec crypto
+ algorithms documented in RFC (we cover algorithms without intellectual
+ property issues only).</para>
+ </sect3>
+
+ <sect3 xml:id="ipsec-ecn">
+ <title>ECN consideration on IPsec tunnels</title>
+
+ <para>ECN-friendly IPsec tunnel is supported as described in
+ <filename>draft-ipsec-ecn-00.txt</filename>.</para>
+
+ <para>Normal IPsec tunnel is described in RFC2401. On encapsulation,
+ IPv4 TOS field (or, IPv6 traffic class field) will be copied from inner
+ IP header to outer IP header. On decapsulation outer IP header
+ will be simply dropped. The decapsulation rule is not compatible
+ with ECN, since ECN bit on the outer IP TOS/traffic class field will be
+ lost.</para>
+
+ <para>To make IPsec tunnel ECN-friendly, we should modify encapsulation
+ and decapsulation procedure. This is described in <link xlink:href="http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt">
+ http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt</link>,
+ chapter 3.</para>
+
+ <para>IPsec tunnel implementation can give you three behaviors, by
+ setting net.inet.ipsec.ecn (or net.inet6.ipsec6.ecn) to some
+ value:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>RFC2401: no consideration for ECN (sysctl value -1)</para>
+ </listitem>
+ <listitem>
+ <para>ECN forbidden (sysctl value 0)</para>
+ </listitem>
+ <listitem>
+ <para>ECN allowed (sysctl value 1)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Note that the behavior is configurable in per-node manner,
+ not per-SA manner (draft-ipsec-ecn-00 wants per-SA configuration,
+ but it looks too much for me).</para>
+
+ <para>The behavior is summarized as follows (see source code for
+ more detail):</para>
+
+ <screen>
+ encapsulate decapsulate
+ --- ---
+RFC2401 copy all TOS bits drop TOS bits on outer
+ from inner to outer. (use inner TOS bits as is)
+
+ECN forbidden copy TOS bits except for ECN drop TOS bits on outer
+ (masked with 0xfc) from inner (use inner TOS bits as is)
+ to outer. set ECN bits to 0.
+
+ECN allowed copy TOS bits except for ECN use inner TOS bits with some
+ CE (masked with 0xfe) from change. if outer ECN CE bit
+ inner to outer. is 1, enable ECN CE bit on
+ set ECN CE bit to 0. the inner.
+
+ </screen>
+
+ <para>General strategy for configuration is as follows:</para>
+ <itemizedlist>
+ <listitem>
+ <para>if both IPsec tunnel endpoint are capable of ECN-friendly
+ behavior, you should better configure both end to <quote>ECN allowed</quote>
+ (sysctl value 1).</para>
+ </listitem>
+ <listitem>
+ <para>if the other end is very strict about TOS bit, use "RFC2401"
+ (sysctl value -1).</para>
+ </listitem>
+ <listitem>
+ <para>in other cases, use "ECN forbidden" (sysctl value 0).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The default behavior is "ECN forbidden" (sysctl value 0).</para>
+
+ <para>For more information, please refer to:</para>
+
+ <para><link xlink:href="http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt">
+ http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt</link>,
+ RFC2481 (Explicit Congestion Notification),
+ src/sys/netinet6/{ah,esp}_input.c</para>
+
+ <para>(Thanks goes to Kenjiro Cho <email>kjc@csl.sony.co.jp</email>
+ for detailed analysis)</para>
+ </sect3>
+
+ <sect3>
+ <title>Interoperability</title>
+
+ <para>Here are (some of) platforms that KAME code have tested
+ IPsec/IKE interoperability in the past. Note that both ends may
+ have modified their implementation, so use the following list just
+ for reference purposes.</para>
+
+ <para>Altiga, Ashley-laurent (vpcom.com), Data Fellows (F-Secure),
+ Ericsson ACC, FreeS/WAN, HITACHI, IBM &aix;, IIJ, Intel,
+ &microsoft; &windowsnt;, NIST (linux IPsec + plutoplus), Netscreen, OpenBSD,
+ RedCreek, Routerware, SSH, Secure Computing, Soliton, Toshiba,
+ VPNet, Yamaha RT100i</para>
+ </sect3>
+ </sect2>
+ </sect1>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/kerneldebug/Makefile b/zh_TW.UTF-8/books/developers-handbook/kerneldebug/Makefile
new file mode 100644
index 0000000000..0f3b90b3e1
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/kerneldebug/Makefile
@@ -0,0 +1,15 @@
+#
+# Build the Handbook with just the content from this chapter.
+#
+# $FreeBSD$
+#
+
+CHAPTERS= kerneldebug/chapter.xml
+
+VPATH= ..
+
+MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
+
+DOC_PREFIX?= ${.CURDIR}/../../../..
+
+.include "../Makefile"
diff --git a/zh_TW.UTF-8/books/developers-handbook/kerneldebug/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/kerneldebug/chapter.xml
new file mode 100644
index 0000000000..a2cd16fa99
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/kerneldebug/chapter.xml
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="kerneldebug">
+ <info><title>Kernel Debugging</title>
+ <authorgroup>
+ <author><personname><firstname>Paul</firstname><surname>Richards</surname></personname><contrib>Contributed by </contrib></author>
+ <author><personname><firstname>J&ouml;rg</firstname><surname>Wunsch</surname></personname></author>
+ </authorgroup>
+ </info>
+
+
+
+ <sect1 xml:id="kerneldebug-obtain">
+ <title>Obtaining a Kernel Crash Dump</title>
+
+ <para>When running a development kernel (eg: &os.current;), such as a
+ kernel under extreme conditions (eg: very high load averages,
+ tens of thousands of connections, exceedingly high number of
+ concurrent users, hundreds of &man.jail.8;s, etc.), or using a
+ new feature or device driver on &os.stable; (eg:
+ <acronym>PAE</acronym>), sometimes a kernel will panic. In the
+ event that it does, this chapter will demonstrate how to extract
+ useful information out of a crash.</para>
+
+ <para>A system reboot is inevitable once a kernel panics. Once a
+ system is rebooted, the contents of a system's physical memory
+ (<acronym>RAM</acronym>) is lost, as well as any bits that are
+ on the swap device before the panic. To preserve the bits in
+ physical memory, the kernel makes use of the swap device as a
+ temporary place to store the bits that are in RAM across a
+ reboot after a crash. In doing this, when &os; boots after a
+ crash, a kernel image can now be extracted and debugging can
+ take place.</para>
+
+ <note><para>A swap device that has been configured as a dump
+ device still acts as a swap device. Dumps to non-swap devices
+ (such as tapes or CDRWs, for example) are not supported at this time. A
+ <quote>swap device</quote> is synonymous with a <quote>swap
+ partition.</quote></para></note>
+
+ <para>To be able to extract a usable core, it is required that at
+ least one swap partition be large enough to hold all of the bits
+ in physical memory. When a kernel panics, before the system
+ reboots, the kernel is smart enough to check to see if a swap
+ device has been configured as a dump device. If there is a
+ valid dump device, the kernel dumps the contents of what is in
+ physical memory to the swap device.</para>
+
+ <sect2 xml:id="config-dumpdev">
+ <title>Configuring the Dump Device</title>
+
+ <para>Before the kernel will dump the contents of its physical
+ memory to a dump device, a dump device must be configured. A
+ dump device is specified by using the &man.dumpon.8; command
+ to tell the kernel where to save kernel crash dumps. The
+ &man.dumpon.8; program must be called after the swap partition
+ has been configured with &man.swapon.8;. This is normally
+ handled by setting the <varname>dumpdev</varname> variable in
+ &man.rc.conf.5; to the path of the swap device (the
+ recommended way to extract a kernel dump).</para>
+
+ <para>Alternatively, the dump device can be hard-coded via the
+ <literal>dump</literal> clause in the &man.config.5; line of
+ a kernel configuration file. This approach is deprecated and should
+ be used only if a kernel is crashing before &man.dumpon.8; can be executed.</para>
+
+ <tip><para>Check <filename>/etc/fstab</filename> or
+ &man.swapinfo.8; for a list of swap devices.</para></tip>
+
+ <important><para>Make sure the <varname>dumpdir</varname>
+ specified in &man.rc.conf.5; exists before a kernel
+ crash!</para>
+
+ <screen>&prompt.root; <userinput>mkdir /var/crash</userinput>
+&prompt.root; <userinput>chmod 700 /var/crash</userinput></screen>
+
+ <para>Also, remember that the contents of
+ <filename>/var/crash</filename> is sensitive and very likely
+ contains confidential information such as passwords.</para>
+ </important>
+ </sect2>
+
+ <sect2 xml:id="extract-dump">
+ <title>Extracting a Kernel Dump</title>
+
+ <para>Once a dump has been written to a dump device, the dump
+ must be extracted before the swap device is mounted.
+ To extract a dump
+ from a dump device, use the &man.savecore.8; program. If
+ <varname>dumpdev</varname> has been set in &man.rc.conf.5;,
+ &man.savecore.8; will be called automatically on the first
+ multi-user boot after the crash and before the swap device
+ is mounted. The location of the extracted core is placed in
+ the &man.rc.conf.5; value <varname>dumpdir</varname>, by
+ default <filename>/var/crash</filename> and will be named
+ <filename>vmcore.0</filename>.</para>
+
+ <para>In the event that there is already a file called
+ <filename>vmcore.0</filename> in
+ <filename>/var/crash</filename> (or whatever
+ <varname>dumpdir</varname> is set to), the kernel will
+ increment the trailing number for every crash to avoid
+ overwriting an existing <filename>vmcore</filename> (eg:
+ <filename>vmcore.1</filename>). While debugging, it is
+ highly likely that you will want to use the highest version
+ <filename>vmcore</filename> in
+ <filename>/var/crash</filename> when searching for the right
+ <filename>vmcore</filename>.</para>
+
+ <tip>
+ <para>If you are testing a new kernel but need to boot a different one in
+ order to get your system up and running again, boot it only into single
+ user mode using the <option>-s</option> flag at the boot prompt, and
+ then perform the following steps:</para>
+
+ <screen>&prompt.root; <userinput>fsck -p</userinput>
+&prompt.root; <userinput>mount -a -t ufs</userinput> # make sure /var/crash is writable
+&prompt.root; <userinput>savecore /var/crash /dev/ad0s1b</userinput>
+&prompt.root; <userinput>exit</userinput> # exit to multi-user</screen>
+
+ <para>This instructs &man.savecore.8; to extract a kernel dump
+ from <filename>/dev/ad0s1b</filename> and place the contents in
+ <filename>/var/crash</filename>. Do not forget to make sure the
+ destination directory <filename>/var/crash</filename> has enough
+ space for the dump. Also, do not forget to specify the correct path to your swap
+ device as it is likely different than
+ <filename>/dev/ad0s1b</filename>!</para></tip>
+
+ <para>The recommended, and certainly the easiest way to automate
+ obtaining crash dumps is to use the <varname>dumpdev</varname>
+ variable in &man.rc.conf.5;.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-gdb">
+ <title>Debugging a Kernel Crash Dump with <command>kgdb</command></title>
+
+ <note>
+ <para>This section covers &man.kgdb.1; as found in &os;&nbsp;5.3
+ and later. In previous versions, one must use
+ <command>gdb -k</command> to read a core dump file.</para>
+ </note>
+
+ <para>Once a dump has been obtained, getting useful information
+ out of the dump is relatively easy for simple problems. Before
+ launching into the internals of &man.kgdb.1; to debug
+ the crash dump, locate the debug version of your kernel
+ (normally called <filename>kernel.debug</filename>) and the path
+ to the source files used to build your kernel (normally
+ <filename>/usr/obj/usr/src/sys/KERNCONF</filename>,
+ where <filename>KERNCONF</filename>
+ is the <varname>ident</varname> specified in a kernel
+ &man.config.5;). With those two pieces of info, let the
+ debugging commence!</para>
+
+ <para>To enter into the debugger and begin getting information
+ from the dump, the following steps are required at a minimum:</para>
+
+ <screen>&prompt.root; <userinput>cd /usr/obj/usr/src/sys/KERNCONF</userinput>
+&prompt.root; <userinput>kgdb kernel.debug /var/crash/vmcore.0</userinput></screen>
+
+ <para>You can debug the crash dump using the kernel sources just like
+ you can for any other program.</para>
+
+ <para>This first dump is from a 5.2-BETA kernel and the crash
+ comes from deep within the kernel. The output below has been
+ modified to include line numbers on the left. This first trace
+ inspects the instruction pointer and obtains a back trace. The
+ address that is used on line 41 for the <command>list</command>
+ command is the instruction pointer and can be found on line
+ 17. Most developers will request having at least this
+ information sent to them if you are unable to debug the problem
+ yourself. If, however, you do solve the problem, make sure that
+ your patch winds its way into the source tree via a problem
+ report, mailing lists, or by being able to commit it!</para>
+
+ <screen> 1:&prompt.root; <userinput>cd /usr/obj/usr/src/sys/KERNCONF</userinput>
+ 2:&prompt.root; <userinput>kgdb kernel.debug /var/crash/vmcore.0</userinput>
+ 3:GNU gdb 5.2.1 (FreeBSD)
+ 4:Copyright 2002 Free Software Foundation, Inc.
+ 5:GDB is free software, covered by the GNU General Public License, and you are
+ 6:welcome to change it and/or distribute copies of it under certain conditions.
+ 7:Type "show copying" to see the conditions.
+ 8:There is absolutely no warranty for GDB. Type "show warranty" for details.
+ 9:This GDB was configured as "i386-undermydesk-freebsd"...
+10:panic: page fault
+11:panic messages:
+12:---
+13:Fatal trap 12: page fault while in kernel mode
+14:cpuid = 0; apic id = 00
+15:fault virtual address = 0x300
+16:fault code: = supervisor read, page not present
+17:instruction pointer = 0x8:0xc0713860
+18:stack pointer = 0x10:0xdc1d0b70
+19:frame pointer = 0x10:0xdc1d0b7c
+20:code segment = base 0x0, limit 0xfffff, type 0x1b
+21: = DPL 0, pres 1, def32 1, gran 1
+22:processor eflags = resume, IOPL = 0
+23:current process = 14394 (uname)
+24:trap number = 12
+25:panic: page fault
+26 cpuid = 0;
+27:Stack backtrace:
+28
+29:syncing disks, buffers remaining... 2199 2199 panic: mi_switch: switch in a critical section
+30:cpuid = 0;
+31:Uptime: 2h43m19s
+32:Dumping 255 MB
+33: 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240
+34:---
+35:Reading symbols from /boot/kernel/snd_maestro3.ko...done.
+36:Loaded symbols for /boot/kernel/snd_maestro3.ko
+37:Reading symbols from /boot/kernel/snd_pcm.ko...done.
+38:Loaded symbols for /boot/kernel/snd_pcm.ko
+39:#0 doadump () at /usr/src/sys/kern/kern_shutdown.c:240
+40:240 dumping++;
+41:<prompt>(kgdb)</prompt> <userinput>list *0xc0713860</userinput>
+42:0xc0713860 is in lapic_ipi_wait (/usr/src/sys/i386/i386/local_apic.c:663).
+43:658 incr = 0;
+44:659 delay = 1;
+45:660 } else
+46:661 incr = 1;
+47:662 for (x = 0; x &lt; delay; x += incr) {
+48:663 if ((lapic-&gt;icr_lo &amp; APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
+49:664 return (1);
+50:665 ia32_pause();
+51:666 }
+52:667 return (0);
+53:<prompt>(kgdb)</prompt> <userinput>backtrace</userinput>
+54:#0 doadump () at /usr/src/sys/kern/kern_shutdown.c:240
+55:#1 0xc055fd9b in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:372
+56:#2 0xc056019d in panic () at /usr/src/sys/kern/kern_shutdown.c:550
+57:#3 0xc0567ef5 in mi_switch () at /usr/src/sys/kern/kern_synch.c:470
+58:#4 0xc055fa87 in boot (howto=256) at /usr/src/sys/kern/kern_shutdown.c:312
+59:#5 0xc056019d in panic () at /usr/src/sys/kern/kern_shutdown.c:550
+60:#6 0xc0720c66 in trap_fatal (frame=0xdc1d0b30, eva=0)
+61: at /usr/src/sys/i386/i386/trap.c:821
+62:#7 0xc07202b3 in trap (frame=
+63: {tf_fs = -1065484264, tf_es = -1065484272, tf_ds = -1065484272, tf_edi = 1, tf_esi = 0, tf_ebp = -602076292, tf_isp = -602076324, tf_ebx = 0, tf_edx = 0, tf_ecx = 1000000, tf_eax = 243, tf_trapno = 12, tf_err = 0, tf_eip = -1066321824, tf_cs = 8, tf_eflags = 65671, tf_esp = 243, tf_ss = 0})
+64: at /usr/src/sys/i386/i386/trap.c:250
+65:#8 0xc070c9f8 in calltrap () at {standard input}:94
+66:#9 0xc07139f3 in lapic_ipi_vectored (vector=0, dest=0)
+67: at /usr/src/sys/i386/i386/local_apic.c:733
+68:#10 0xc0718b23 in ipi_selected (cpus=1, ipi=1)
+69: at /usr/src/sys/i386/i386/mp_machdep.c:1115
+70:#11 0xc057473e in kseq_notify (ke=0xcc05e360, cpu=0)
+71: at /usr/src/sys/kern/sched_ule.c:520
+72:#12 0xc0575cad in sched_add (td=0xcbcf5c80)
+73: at /usr/src/sys/kern/sched_ule.c:1366
+74:#13 0xc05666c6 in setrunqueue (td=0xcc05e360)
+75: at /usr/src/sys/kern/kern_switch.c:422
+76:#14 0xc05752f4 in sched_wakeup (td=0xcbcf5c80)
+77: at /usr/src/sys/kern/sched_ule.c:999
+78:#15 0xc056816c in setrunnable (td=0xcbcf5c80)
+79: at /usr/src/sys/kern/kern_synch.c:570
+80:#16 0xc0567d53 in wakeup (ident=0xcbcf5c80)
+81: at /usr/src/sys/kern/kern_synch.c:411
+82:#17 0xc05490a8 in exit1 (td=0xcbcf5b40, rv=0)
+83: at /usr/src/sys/kern/kern_exit.c:509
+84:#18 0xc0548011 in sys_exit () at /usr/src/sys/kern/kern_exit.c:102
+85:#19 0xc0720fd0 in syscall (frame=
+86: {tf_fs = 47, tf_es = 47, tf_ds = 47, tf_edi = 0, tf_esi = -1, tf_ebp = -1077940712, tf_isp = -602075788, tf_ebx = 672411944, tf_edx = 10, tf_ecx = 672411600, tf_eax = 1, tf_trapno = 12, tf_err = 2, tf_eip = 671899563, tf_cs = 31, tf_eflags = 642, tf_esp = -1077940740, tf_ss = 47})
+87: at /usr/src/sys/i386/i386/trap.c:1010
+88:#20 0xc070ca4d in Xint0x80_syscall () at {standard input}:136
+89:---Can't read userspace from dump, or kernel process---
+90:<prompt>(kgdb)</prompt> <userinput>quit</userinput></screen>
+
+
+ <para>This next trace is an older dump from the FreeBSD 2 time
+ frame, but is more involved and demonstrates more of the
+ features of <command>gdb</command>. Long lines have been folded
+ to improve readability, and the lines are numbered for
+ reference. Despite this, it is a real-world error trace taken
+ during the development of the pcvt console driver.</para>
+
+<screen> 1:Script started on Fri Dec 30 23:15:22 1994
+ 2:&prompt.root; <userinput>cd /sys/compile/URIAH</userinput>
+ 3:&prompt.root; <userinput>gdb -k kernel /var/crash/vmcore.1</userinput>
+ 4:Reading symbol data from /usr/src/sys/compile/URIAH/kernel
+...done.
+ 5:IdlePTD 1f3000
+ 6:panic: because you said to!
+ 7:current pcb at 1e3f70
+ 8:Reading in symbols for ../../i386/i386/machdep.c...done.
+ 9:<prompt>(kgdb)</prompt> <userinput>backtrace</userinput>
+10:#0 boot (arghowto=256) (../../i386/i386/machdep.c line 767)
+11:#1 0xf0115159 in panic ()
+12:#2 0xf01955bd in diediedie () (../../i386/i386/machdep.c line 698)
+13:#3 0xf010185e in db_fncall ()
+14:#4 0xf0101586 in db_command (-266509132, -266509516, -267381073)
+15:#5 0xf0101711 in db_command_loop ()
+16:#6 0xf01040a0 in db_trap ()
+17:#7 0xf0192976 in kdb_trap (12, 0, -272630436, -266743723)
+18:#8 0xf019d2eb in trap_fatal (...)
+19:#9 0xf019ce60 in trap_pfault (...)
+20:#10 0xf019cb2f in trap (...)
+21:#11 0xf01932a1 in exception:calltrap ()
+22:#12 0xf0191503 in cnopen (...)
+23:#13 0xf0132c34 in spec_open ()
+24:#14 0xf012d014 in vn_open ()
+25:#15 0xf012a183 in open ()
+26:#16 0xf019d4eb in syscall (...)
+27:<prompt>(kgdb)</prompt> <userinput>up 10</userinput>
+28:Reading in symbols for ../../i386/i386/trap.c...done.
+29:#10 0xf019cb2f in trap (frame={tf_es = -260440048, tf_ds = 16, tf_\
+30:edi = 3072, tf_esi = -266445372, tf_ebp = -272630356, tf_isp = -27\
+31:2630396, tf_ebx = -266427884, tf_edx = 12, tf_ecx = -266427884, tf\
+32:_eax = 64772224, tf_trapno = 12, tf_err = -272695296, tf_eip = -26\
+33:6672343, tf_cs = -266469368, tf_eflags = 66066, tf_esp = 3072, tf_\
+34:ss = -266427884}) (../../i386/i386/trap.c line 283)
+35:283 (void) trap_pfault(&amp;frame, FALSE);
+36:<prompt>(kgdb)</prompt> <userinput>frame frame-&gt;tf_ebp frame-&gt;tf_eip</userinput>
+37:Reading in symbols for ../../i386/isa/pcvt/pcvt_drv.c...done.
+38:#0 0xf01ae729 in pcopen (dev=3072, flag=3, mode=8192, p=(struct p\
+39:roc *) 0xf07c0c00) (../../i386/isa/pcvt/pcvt_drv.c line 403)
+40:403 return ((*linesw[tp-&gt;t_line].l_open)(dev, tp));
+41:<prompt>(kgdb)</prompt> <userinput>list</userinput>
+42:398
+43:399 tp-&gt;t_state |= TS_CARR_ON;
+44:400 tp-&gt;t_cflag |= CLOCAL; /* cannot be a modem (:-) */
+45:401
+46:402 #if PCVT_NETBSD || (PCVT_FREEBSD &gt;= 200)
+47:403 return ((*linesw[tp-&gt;t_line].l_open)(dev, tp));
+48:404 #else
+49:405 return ((*linesw[tp-&gt;t_line].l_open)(dev, tp, flag));
+50:406 #endif /* PCVT_NETBSD || (PCVT_FREEBSD &gt;= 200) */
+51:407 }
+52:<prompt>(kgdb)</prompt> <userinput>print tp</userinput>
+53:Reading in symbols for ../../i386/i386/cons.c...done.
+54:$1 = (struct tty *) 0x1bae
+55:<prompt>(kgdb)</prompt> <userinput>print tp-&gt;t_line</userinput>
+56:$2 = 1767990816
+57:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+58:#1 0xf0191503 in cnopen (dev=0x00000000, flag=3, mode=8192, p=(st\
+59:ruct proc *) 0xf07c0c00) (../../i386/i386/cons.c line 126)
+60: return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p));
+61:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+62:#2 0xf0132c34 in spec_open ()
+63:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+64:#3 0xf012d014 in vn_open ()
+65:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+66:#4 0xf012a183 in open ()
+67:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+68:#5 0xf019d4eb in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi =\
+69: 2158592, tf_esi = 0, tf_ebp = -272638436, tf_isp = -272629788, tf\
+70:_ebx = 7086, tf_edx = 1, tf_ecx = 0, tf_eax = 5, tf_trapno = 582, \
+71:tf_err = 582, tf_eip = 75749, tf_cs = 31, tf_eflags = 582, tf_esp \
+72:= -272638456, tf_ss = 39}) (../../i386/i386/trap.c line 673)
+73:673 error = (*callp-&gt;sy_call)(p, args, rval);
+74:<prompt>(kgdb)</prompt> <userinput>up</userinput>
+75:Initial frame selected; you cannot go up.
+76:<prompt>(kgdb)</prompt> <userinput>quit</userinput></screen>
+ <para>Comments to the above script:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>line 6:</term>
+
+ <listitem>
+ <para>This is a dump taken from within DDB (see below), hence the
+ panic comment <quote>because you said to!</quote>, and a rather
+ long stack trace; the initial reason for going into DDB has been a
+ page fault trap though.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>line 20:</term>
+
+ <listitem>
+ <para>This is the location of function <function>trap()</function>
+ in the stack trace.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>line 36:</term>
+
+ <listitem>
+ <para>Force usage of a new stack frame; this is no longer necessary.
+ The stack frames are supposed to point to the right
+ locations now, even in case of a trap.
+ From looking at the code in source line 403, there is a
+ high probability that either the pointer access for
+ <quote>tp</quote> was messed up, or the array access was out of
+ bounds.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>line 52:</term>
+
+ <listitem>
+ <para>The pointer looks suspicious, but happens to be a valid
+ address.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>line 56:</term>
+
+ <listitem>
+ <para>However, it obviously points to garbage, so we have found our
+ error! (For those unfamiliar with that particular piece of code:
+ <literal>tp-&gt;t_line</literal> refers to the line discipline of
+ the console device here, which must be a rather small integer
+ number.)</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <tip><para>If your system is crashing regularly and you are running
+ out of disk space, deleting old <filename>vmcore</filename>
+ files in <filename>/var/crash</filename> could save a
+ considerable amount of disk space!</para></tip>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-ddd">
+ <title>Debugging a Crash Dump with DDD</title>
+
+ <para>Examining a kernel crash dump with a graphical debugger like
+ <command>ddd</command> is also possible (you will need to install
+ the <package>devel/ddd</package> port in order to use the
+ <command>ddd</command> debugger). Add the <option>-k</option>
+ option to the <command>ddd</command> command line you would use
+ normally. For example;</para>
+
+ <screen>&prompt.root; <userinput>ddd -k /var/crash/kernel.0 /var/crash/vmcore.0</userinput></screen>
+
+ <para>You should then be able to go about looking at the crash dump using
+ <command>ddd</command>'s graphical interface.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-post-mortem">
+ <title>Post-Mortem Analysis of a Dump</title>
+
+ <para>What do you do if a kernel dumped core but you did not expect it,
+ and it is therefore not compiled using <command>config -g</command>? Not
+ everything is lost here. Do not panic!</para>
+
+ <para>Of course, you still need to enable crash dumps. See above for the
+ options you have to specify in order to do this.</para>
+
+ <para>Go to your kernel config directory
+ (<filename>/usr/src/sys/arch/conf</filename>)
+ and edit your configuration file. Uncomment (or add, if it does not
+ exist) the following line:</para>
+
+ <programlisting>makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols</programlisting>
+
+ <para>Rebuild the kernel. Due to the time stamp change on the Makefile,
+ some other object files will be rebuilt, for example
+ <filename>trap.o</filename>. With a bit of luck, the added
+ <option>-g</option> option will not change anything for the generated
+ code, so you will finally get a new kernel with similar code to the
+ faulting one but with some debugging symbols. You should at least verify the
+ old and new sizes with the &man.size.1; command. If there is a
+ mismatch, you probably need to give up here.</para>
+
+ <para>Go and examine the dump as described above. The debugging symbols
+ might be incomplete for some places, as can be seen in the stack trace
+ in the example above where some functions are displayed without line
+ numbers and argument lists. If you need more debugging symbols, remove
+ the appropriate object files, recompile the kernel again and repeat the
+ <command>gdb -k</command>
+ session until you know enough.</para>
+
+ <para>All this is not guaranteed to work, but it will do it fine in most
+ cases.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-online-ddb">
+ <title>On-Line Kernel Debugging Using DDB</title>
+
+ <para>While <command>gdb -k</command> as an off-line debugger provides a very
+ high level of user interface, there are some things it cannot do. The
+ most important ones being breakpointing and single-stepping kernel
+ code.</para>
+
+ <para>If you need to do low-level debugging on your kernel, there is an
+ on-line debugger available called DDB. It allows setting of
+ breakpoints, single-stepping kernel functions, examining and changing
+ kernel variables, etc. However, it cannot access kernel source files,
+ and only has access to the global and static symbols, not to the full
+ debug information like <command>gdb</command> does.</para>
+
+ <para>To configure your kernel to include DDB, add the option line
+
+ <programlisting>options DDB</programlisting>
+
+ to your config file, and rebuild. (See <link xlink:href="&url.books.handbook;/index.html">The FreeBSD Handbook</link> for details on
+ configuring the FreeBSD kernel).</para>
+
+ <note>
+ <para>If you have an older version of the boot blocks, your
+ debugger symbols might not be loaded at all. Update the boot blocks;
+ the recent ones load the DDB symbols automatically.</para>
+ </note>
+
+ <para>Once your DDB kernel is running, there are several ways to enter
+ DDB. The first, and earliest way is to type the boot flag
+ <option>-d</option> right at the boot prompt. The kernel will start up
+ in debug mode and enter DDB prior to any device probing. Hence you can
+ even debug the device probe/attach functions.</para>
+
+ <para>The second scenario is to drop to the debugger once the
+ system has booted. There are two simple ways to accomplish
+ this. If you would like to break to the debugger from the
+ command prompt, simply type the command:</para>
+
+ <screen>&prompt.root; <userinput>sysctl debug.enter_debugger=ddb</userinput></screen>
+
+ <para>Alternatively, if you are at the system console, you may use
+ a hot-key on the keyboard. The default break-to-debugger
+ sequence is <keycombo action="simul"><keycap>Ctrl</keycap>
+ <keycap>Alt</keycap><keycap>ESC</keycap></keycombo>. For
+ syscons, this sequence can be remapped and some of the
+ distributed maps out there do this, so check to make sure you
+ know the right sequence to use. There is an option available
+ for serial consoles that allows the use of a serial line BREAK on the
+ console line to enter DDB (<literal>options BREAK_TO_DEBUGGER</literal>
+ in the kernel config file). It is not the default since there are a lot
+ of serial adapters around that gratuitously generate a BREAK
+ condition, for example when pulling the cable.</para>
+
+ <para>The third way is that any panic condition will branch to DDB if the
+ kernel is configured to use it. For this reason, it is not wise to
+ configure a kernel with DDB for a machine running unattended.</para>
+
+ <para>The DDB commands roughly resemble some <command>gdb</command>
+ commands. The first thing you probably need to do is to set a
+ breakpoint:</para>
+
+ <screen><userinput>b function-name</userinput>
+<userinput>b address</userinput></screen>
+
+ <para>Numbers are taken hexadecimal by default, but to make them distinct
+ from symbol names; hexadecimal numbers starting with the letters
+ <literal>a-f</literal> need to be preceded with <literal>0x</literal>
+ (this is optional for other numbers). Simple expressions are allowed,
+ for example: <literal>function-name + 0x103</literal>.</para>
+
+ <para>To continue the operation of an interrupted kernel, simply
+ type:</para>
+
+ <screen><userinput>c</userinput></screen>
+
+ <para>To get a stack trace, use:</para>
+
+ <screen><userinput>trace</userinput></screen>
+
+ <note>
+ <para>Note that when entering DDB via a hot-key, the kernel is currently
+ servicing an interrupt, so the stack trace might be not of much use
+ to you.</para>
+ </note>
+
+ <para>If you want to remove a breakpoint, use</para>
+
+
+ <screen><userinput>del</userinput>
+<userinput>del address-expression</userinput></screen>
+
+ <para>The first form will be accepted immediately after a breakpoint hit,
+ and deletes the current breakpoint. The second form can remove any
+ breakpoint, but you need to specify the exact address; this can be
+ obtained from:</para>
+
+ <screen><userinput>show b</userinput></screen>
+
+ <para>To single-step the kernel, try:</para>
+
+ <screen><userinput>s</userinput></screen>
+
+ <para>This will step into functions, but you can make DDB trace them until
+ the matching return statement is reached by:</para>
+
+ <screen><userinput>n</userinput></screen>
+
+ <note>
+ <para>This is different from <command>gdb</command>'s
+ <command>next</command> statement; it is like <command>gdb</command>'s
+ <command>finish</command>.</para>
+ </note>
+
+ <para>To examine data from memory, use (for example):
+
+ <screen><userinput>x/wx 0xf0133fe0,40</userinput>
+<userinput>x/hd db_symtab_space</userinput>
+<userinput>x/bc termbuf,10</userinput>
+<userinput>x/s stringbuf</userinput></screen>
+
+ for word/halfword/byte access, and hexadecimal/decimal/character/ string
+ display. The number after the comma is the object count. To display
+ the next 0x10 items, simply use:</para>
+
+ <screen><userinput>x ,10</userinput></screen>
+
+ <para>Similarly, use
+
+ <screen><userinput>x/ia foofunc,10</userinput></screen>
+
+ to disassemble the first 0x10 instructions of
+ <function>foofunc</function>, and display them along with their offset
+ from the beginning of <function>foofunc</function>.</para>
+
+ <para>To modify memory, use the write command:</para>
+
+ <screen><userinput>w/b termbuf 0xa 0xb 0</userinput>
+<userinput>w/w 0xf0010030 0 0</userinput></screen>
+
+ <para>The command modifier
+ (<literal>b</literal>/<literal>h</literal>/<literal>w</literal>)
+ specifies the size of the data to be written, the first following
+ expression is the address to write to and the remainder is interpreted
+ as data to write to successive memory locations.</para>
+
+ <para>If you need to know the current registers, use:</para>
+
+ <screen><userinput>show reg</userinput></screen>
+
+ <para>Alternatively, you can display a single register value by e.g.
+
+ <screen><userinput>p $eax</userinput></screen>
+
+ and modify it by:</para>
+
+ <screen><userinput>set $eax new-value</userinput></screen>
+
+ <para>Should you need to call some kernel functions from DDB, simply
+ say:</para>
+
+ <screen><userinput>call func(arg1, arg2, ...)</userinput></screen>
+
+ <para>The return value will be printed.</para>
+
+ <para>For a &man.ps.1; style summary of all running processes, use:</para>
+
+ <screen><userinput>ps</userinput></screen>
+
+ <para>Now you have examined why your kernel failed, and you wish to
+ reboot. Remember that, depending on the severity of previous
+ malfunctioning, not all parts of the kernel might still be working as
+ expected. Perform one of the following actions to shut down and reboot
+ your system:</para>
+
+ <screen><userinput>panic</userinput></screen>
+
+ <para>This will cause your kernel to dump core and reboot, so you can
+ later analyze the core on a higher level with <command>gdb</command>. This command
+ usually must be followed by another <command>continue</command>
+ statement.</para>
+
+ <screen><userinput>call boot(0)</userinput></screen>
+
+ <para>Which might be a good way to cleanly shut down the running system,
+ <function>sync()</function> all disks, and finally reboot. As long as
+ the disk and filesystem interfaces of the kernel are not damaged, this
+ might be a good way for an almost clean shutdown.</para>
+
+ <screen><userinput>call cpu_reset()</userinput></screen>
+
+ <para>This is the final way out of disaster and almost the same as hitting the
+ Big Red Button.</para>
+
+ <para>If you need a short command summary, simply type:</para>
+
+ <screen><userinput>help</userinput></screen>
+
+ <para>However, it is highly recommended to have a printed copy of the
+ &man.ddb.4; manual page ready for a debugging
+ session. Remember that it is hard to read the on-line manual while
+ single-stepping the kernel.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-online-gdb">
+ <title>On-Line Kernel Debugging Using Remote GDB</title>
+
+ <para>This feature has been supported since FreeBSD 2.2, and it is
+ actually a very neat one.</para>
+
+ <para>GDB has already supported <emphasis>remote debugging</emphasis> for
+ a long time. This is done using a very simple protocol along a serial
+ line. Unlike the other methods described above, you will need two
+ machines for doing this. One is the host providing the debugging
+ environment, including all the sources, and a copy of the kernel binary
+ with all the symbols in it, and the other one is the target machine that
+ simply runs a similar copy of the very same kernel (but stripped of the
+ debugging information).</para>
+
+ <para>You should configure the kernel in question with <command>config
+ -g</command>, include <option>DDB</option> into the configuration, and
+ compile it as usual. This gives a large binary, due to the
+ debugging information. Copy this kernel to the target machine, strip
+ the debugging symbols off with <command>strip -x</command>, and boot it
+ using the <option>-d</option> boot option. Connect the serial line
+ of the target machine that has "flags 080" set on its sio device
+ to any serial line of the debugging host.
+ Now, on the debugging machine, go to the compile directory of the target
+ kernel, and start <command>gdb</command>:</para>
+
+ <screen>&prompt.user; <userinput>gdb -k kernel</userinput>
+GDB is free software and you are welcome to distribute copies of it
+ under certain conditions; type "show copying" to see the conditions.
+There is absolutely no warranty for GDB; type "show warranty" for details.
+GDB 4.16 (i386-unknown-freebsd),
+Copyright 1996 Free Software Foundation, Inc...
+<prompt>(kgdb)</prompt> </screen>
+
+ <para>Initialize the remote debugging session (assuming the first serial
+ port is being used) by:</para>
+
+ <screen><prompt>(kgdb)</prompt> <userinput>target remote /dev/cuaa0</userinput></screen>
+
+ <para>Now, on the target host (the one that entered DDB right before even
+ starting the device probe), type:</para>
+
+ <screen>Debugger("Boot flags requested debugger")
+Stopped at Debugger+0x35: movb $0, edata+0x51bc
+<prompt>db&gt;</prompt> <userinput>gdb</userinput></screen>
+
+ <para>DDB will respond with:</para>
+
+ <screen>Next trap will enter GDB remote protocol mode</screen>
+
+ <para>Every time you type <command>gdb</command>, the mode will be toggled
+ between remote GDB and local DDB. In order to force a next trap
+ immediately, simply type <command>s</command> (step). Your hosting GDB
+ will now gain control over the target kernel:</para>
+
+ <screen>Remote debugging using /dev/cuaa0
+Debugger (msg=0xf01b0383 "Boot flags requested debugger")
+ at ../../i386/i386/db_interface.c:257
+<prompt>(kgdb)</prompt></screen>
+
+ <para>You can use this session almost as any other GDB session, including
+ full access to the source, running it in gud-mode inside an Emacs window
+ (which gives you an automatic source code display in another Emacs
+ window), etc.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-kld">
+ <title>Debugging Loadable Modules Using GDB</title>
+
+ <para>When debugging a panic that occurred within a module, or
+ using remote GDB against a machine that uses dynamic modules,
+ you need to tell GDB how to obtain symbol information for those
+ modules.</para>
+
+ <para>First, you need to build the module(s) with debugging
+ information:</para>
+
+ <screen>&prompt.root; <userinput>cd /sys/modules/linux</userinput>
+&prompt.root; <userinput>make clean; make COPTS=-g</userinput></screen>
+
+ <para>If you are using remote GDB, you can run
+ <command>kldstat</command> on the target machine to find out
+ where the module was loaded:</para>
+
+ <screen>&prompt.root; <userinput>kldstat</userinput>
+Id Refs Address Size Name
+ 1 4 0xc0100000 1c1678 kernel
+ 2 1 0xc0a9e000 6000 linprocfs.ko
+ 3 1 0xc0ad7000 2000 warp_saver.ko
+ 4 1 0xc0adc000 11000 linux.ko</screen>
+
+ <para>If you are debugging a crash dump, you will need to walk the
+ <literal>linker_files</literal> list, starting at
+ <literal>linker_files-&gt;tqh_first</literal> and following the
+ <literal>link.tqe_next</literal> pointers until you find the
+ entry with the <literal>filename</literal> you are looking for.
+ The <literal>address</literal> member of that entry is the load
+ address of the module.</para>
+
+ <para>Next, you need to find out the offset of the text section
+ within the module:</para>
+
+ <screen>&prompt.root; <userinput>objdump --section-headers /sys/modules/linux/linux.ko | grep text</userinput>
+ 3 .rel.text 000016e0 000038e0 000038e0 000038e0 2**2
+ 10 .text 00007f34 000062d0 000062d0 000062d0 2**2</screen>
+
+ <para>The one you want is the <literal>.text</literal> section,
+ section 10 in the above example. The fourth hexadecimal field
+ (sixth field overall) is the offset of the text section within
+ the file. Add this offset to the load address of the module to
+ obtain the relocation address for the module's code. In our
+ example, we get 0xc0adc000 + 0x62d0 = 0xc0ae22d0. Use the
+ <command>add-symbol-file</command> command in GDB to tell the
+ debugger about the module:</para>
+
+ <screen><prompt>(kgdb)</prompt> <userinput>add-symbol-file /sys/modules/linux/linux.ko 0xc0ae22d0</userinput>
+add symbol table from file "/sys/modules/linux/linux.ko" at text_addr = 0xc0ae22d0?
+(y or n) <userinput>y</userinput>
+Reading symbols from /sys/modules/linux/linux.ko...done.
+<prompt>(kgdb)</prompt></screen>
+
+ <para>You should now have access to all the symbols in the
+ module.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-console">
+ <title>Debugging a Console Driver</title>
+
+ <para>Since you need a console driver to run DDB on, things are more
+ complicated if the console driver itself is failing. You might remember
+ the use of a serial console (either with modified boot blocks, or by
+ specifying <option>-h</option> at the <prompt>Boot:</prompt> prompt),
+ and hook up a standard terminal onto your first serial port. DDB works
+ on any configured console driver, including a serial
+ console.</para>
+ </sect1>
+
+ <sect1 xml:id="kerneldebug-deadlocks">
+ <title>Debugging the Deadlocks</title>
+
+ <para>You may experience so called deadlocks, the situation where
+ system stops doing useful work. To provide the helpful bug report
+ in this situation, you shall use ddb as described above. Please,
+ include the output of <command>ps</command> and
+ <command>trace</command> for suspected processes in the
+ report.</para>
+
+ <para>If possible, consider doing further investigation. Receipt
+ below is especially useful if you suspect deadlock occurs in the
+ VFS layer. Add the options
+ <programlisting>makeoptions DEBUG=-g
+ options INVARIANTS
+ options INVARIANT_SUPPORT
+ options WITNESS
+ options DEBUG_LOCKS
+ options DEBUG_VFS_LOCKS
+ options DIAGNOSTIC</programlisting>
+
+ to the kernel config. When deadlock occurs, in addition to the
+ output of the <command>ps</command> command, provide information
+ from the <command>show allpcpu</command>, <command>show
+ alllocks</command>, <command>show lockedvnods</command> and
+ <command>show alltrace</command>.</para>
+
+ <para>For threaded processes, to obtain meaningful backtraces, use
+ <command>thread thread-id</command> to switch to the thread
+ stack, and do backtrace with <command>where</command>.</para>
+ </sect1>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/l10n/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/l10n/chapter.xml
new file mode 100644
index 0000000000..548fd08e3a
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/l10n/chapter.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="l10n">
+ <title>Localization and Internationalization - L10N and I18N</title>
+
+ <sect1 xml:id="l10n-programming">
+ <title>Programming I18N Compliant Applications</title>
+ <indexterm><primary>Qt</primary></indexterm>
+ <indexterm><primary>GTK</primary></indexterm>
+ <para>To make your application more useful for speakers of other
+ languages, we hope that you will program I18N compliant. The GNU
+ gcc compiler and GUI libraries like QT and GTK support I18N through
+ special handling of strings. Making a program I18N compliant is
+ very easy. It allows contributors to port your application to
+ other languages quickly. Refer to the library specific I18N
+ documentation for more details.</para>
+
+ <para>In contrast with common perception, I18N compliant code is
+ easy to write. Usually, it only involves wrapping your strings
+ with library specific functions. In addition, please be sure to
+ allow for wide or multibyte character support.</para>
+
+ <sect2>
+ <title>A Call to Unify the I18N Effort</title>
+
+ <para>It has come to our attention that the individual I18N/L10N
+ efforts for each country has been repeating each others'
+ efforts. Many of us have been reinventing the wheel repeatedly
+ and inefficiently. We hope that the various major groups in
+ I18N could congregate into a group effort similar to the Core
+ Team's responsibility.</para>
+
+ <para>Currently, we hope that, when you write or port I18N
+ programs, you would send it out to each country's related
+ FreeBSD mailing list for testing. In the future, we hope to
+ create applications that work in all the languages
+ out-of-the-box without dirty hacks.</para>
+
+ <para>The &a.i18n; has been established. If you are an I18N/L10N
+ developer, please send your comments, ideas, questions, and
+ anything you deem related to it.</para>
+ </sect2>
+
+ <sect2>
+ <title>Perl and Python</title>
+ <indexterm>
+ <primary>Perl</primary>
+ </indexterm>
+ <indexterm>
+ <primary>Python</primary>
+ </indexterm>
+
+ <para>Perl and Python have I18N and wide character handling
+ libraries. Please use them for I18N compliance.</para>
+
+ <para>In older FreeBSD versions,
+ Perl may give warnings about not having a wide character locale
+ installed on your system. You can set the
+ environment variable <envar>LD_PRELOAD</envar> to
+ <filename>/usr/lib/libxpg4.so</filename> in your shell.</para>
+
+ <para>In <literal>sh</literal>-based shells:</para>
+
+ <programlisting><envar>LD_PRELOAD=/usr/lib/libxpg4.so</envar></programlisting>
+
+ <para>In <literal>C</literal>-based shells:</para>
+
+ <programlisting><envar>setenv LD_PRELOAD /usr/lib/libxpg4.so</envar></programlisting>
+ </sect2>
+ </sect1>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/policies/Makefile b/zh_TW.UTF-8/books/developers-handbook/policies/Makefile
new file mode 100644
index 0000000000..771a262e60
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/policies/Makefile
@@ -0,0 +1,15 @@
+#
+# Build the Handbook with just the content from this chapter.
+#
+# $FreeBSD$
+#
+
+CHAPTERS= policies/chapter.xml
+
+VPATH= ..
+
+MASTERDOC= ${.CURDIR}/../${DOC}.${DOCBOOKSUFFIX}
+
+DOC_PREFIX?= ${.CURDIR}/../../../..
+
+.include "../Makefile"
diff --git a/zh_TW.UTF-8/books/developers-handbook/policies/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/policies/chapter.xml
new file mode 100644
index 0000000000..9dffb99394
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/policies/chapter.xml
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="policies">
+ <info><title>Source Tree Guidelines and Policies</title>
+ <authorgroup>
+ <author><personname><firstname>Poul-Henning</firstname><surname>Kamp</surname></personname><contrib>Contributed by </contrib></author>
+ </authorgroup>
+
+ </info>
+
+
+
+ <para>This chapter documents various guidelines and policies in force for
+ the FreeBSD source tree.</para>
+
+ <sect1 xml:id="policies-maintainer">
+ <title><varname>MAINTAINER</varname> on Makefiles</title>
+ <indexterm><primary>ports maintainer</primary></indexterm>
+
+ <para>If a particular portion of the FreeBSD distribution is being
+ maintained by a person or group of persons, they can communicate this
+ fact to the world by adding a
+
+ <programlisting>MAINTAINER= email-addresses</programlisting>
+
+ line to the <filename>Makefile</filename>s covering this portion of the
+ source tree.</para>
+
+ <para>The semantics of this are as follows:</para>
+
+ <para>The maintainer owns and is responsible for that code. This means
+ that he is responsible for fixing bugs and answering problem reports
+ pertaining to that piece of the code, and in the case of contributed
+ software, for tracking new versions, as appropriate.</para>
+
+ <para>Changes to directories which have a maintainer defined shall be sent
+ to the maintainer for review before being committed. Only if the
+ maintainer does not respond for an unacceptable period of time, to
+ several emails, will it be acceptable to commit changes without review
+ by the maintainer. However, it is suggested that you try to have the
+ changes reviewed by someone else if at all possible.</para>
+
+ <para>It is of course not acceptable to add a person or group as
+ maintainer unless they agree to assume this duty. On the other hand it
+ does not have to be a committer and it can easily be a group of
+ people.</para>
+ </sect1>
+
+ <sect1 xml:id="policies-contributed">
+ <info><title>Contributed Software</title>
+ <authorgroup>
+ <author><personname><firstname>Poul-Henning</firstname><surname>Kamp</surname></personname><contrib>Contributed by </contrib></author>
+ <author><personname><firstname>David</firstname><surname>O'Brien</surname></personname></author>
+ </authorgroup>
+
+ </info>
+
+
+
+ <indexterm><primary>contributed software</primary></indexterm>
+
+ <para>Some parts of the FreeBSD distribution consist of software that is
+ actively being maintained outside the FreeBSD project. For historical
+ reasons, we call this <emphasis>contributed</emphasis> software. Some
+ examples are <application>sendmail</application>, <application>gcc</application> and <application>patch</application>.</para>
+
+ <para>Over the last couple of years, various methods have been used in
+ dealing with this type of software and all have some number of
+ advantages and drawbacks. No clear winner has emerged.</para>
+
+ <para>Since this is the case, after some debate one of these methods has
+ been selected as the <quote>official</quote> method and will be required
+ for future imports of software of this kind. Furthermore, it is
+ strongly suggested that existing contributed software converge on this
+ model over time, as it has significant advantages over the old method,
+ including the ability to easily obtain diffs relative to the
+ <quote>official</quote> versions of the source by everyone (even without
+ cvs access). This will make it significantly easier to return changes
+ to the primary developers of the contributed software.</para>
+
+ <para>Ultimately, however, it comes down to the people actually doing the
+ work. If using this model is particularly unsuited to the package being
+ dealt with, exceptions to these rules may be granted only with the
+ approval of the core team and with the general consensus of the other
+ developers. The ability to maintain the package in the future will be a
+ key issue in the decisions.</para>
+
+ <note>
+ <para>Because of some unfortunate design limitations with the RCS file
+ format and CVS's use of vendor branches, minor, trivial and/or
+ cosmetic changes are <emphasis>strongly discouraged</emphasis> on
+ files that are still tracking the vendor branch. <quote>Spelling
+ fixes</quote> are explicitly included here under the
+ <quote>cosmetic</quote> category and are to be avoided for files with
+ revision 1.1.x.x. The repository bloat impact from a single character
+ change can be rather dramatic.</para>
+ </note>
+
+ <para>The <application>Tcl</application> embedded programming
+ language will be used as example of how this model works:</para>
+
+ <para><filename>src/contrib/tcl</filename> contains the source as
+ distributed by the maintainers of this package. Parts that are entirely
+ not applicable for FreeBSD can be removed. In the case of Tcl, the
+ <filename>mac</filename>, <filename>win</filename> and
+ <filename>compat</filename> subdirectories were eliminated before the
+ import.</para>
+
+ <para><filename>src/lib/libtcl</filename> contains only a <application>bmake</application> style
+ <filename>Makefile</filename> that uses the standard
+ <filename>bsd.lib.mk</filename> makefile rules to produce the library
+ and install the documentation.</para>
+
+ <para><filename>src/usr.bin/tclsh</filename> contains only a bmake style
+ <filename>Makefile</filename> which will produce and install the
+ <command>tclsh</command> program and its associated man-pages using the
+ standard <filename>bsd.prog.mk</filename> rules.</para>
+
+ <para><filename>src/tools/tools/tcl_bmake</filename> contains a couple of
+ shell-scripts that can be of help when the tcl software needs updating.
+ These are not part of the built or installed software.</para>
+
+ <para>The important thing here is that the
+ <filename>src/contrib/tcl</filename> directory is created according to
+ the rules: it is supposed to contain the sources as distributed (on a
+ proper CVS vendor-branch and without RCS keyword expansion) with as few
+ FreeBSD-specific changes as possible. The 'easy-import' tool on
+ <systemitem>freefall</systemitem> will assist in doing the import, but if there are any doubts on
+ how to go about it, it is imperative that you ask first and not blunder
+ ahead and hope it <quote>works out</quote>. CVS is not forgiving of
+ import accidents and a fair amount of effort is required to back out
+ major mistakes.</para>
+
+ <para>Because of the previously mentioned design limitations with CVS's
+ vendor branches, it is required that <quote>official</quote> patches from
+ the vendor be applied to the original distributed sources and the result
+ re-imported onto the vendor branch again. Official patches should never
+ be patched into the FreeBSD checked out version and <quote>committed</quote>, as this
+ destroys the vendor branch coherency and makes importing future versions
+ rather difficult as there will be conflicts.</para>
+
+ <para>Since many packages contain files that are meant for compatibility
+ with other architectures and environments that FreeBSD, it is
+ permissible to remove parts of the distribution tree that are of no
+ interest to FreeBSD in order to save space. Files containing copyright
+ notices and release-note kind of information applicable to the remaining
+ files shall <emphasis>not</emphasis> be removed.</para>
+
+ <para>If it seems easier, the <command>bmake</command>
+ <filename>Makefile</filename>s can be produced from the dist tree
+ automatically by some utility, something which would hopefully make it
+ even easier to upgrade to a new version. If this is done, be sure to
+ check in such utilities (as necessary) in the
+ <filename>src/tools</filename> directory along with the port itself so
+ that it is available to future maintainers.</para>
+
+ <para>In the <filename>src/contrib/tcl</filename> level directory, a file
+ called <filename>FREEBSD-upgrade</filename> should be added and it
+ should state things like:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Which files have been left out.</para>
+ </listitem>
+
+ <listitem>
+ <para>Where the original distribution was obtained from and/or the
+ official master site.</para>
+ </listitem>
+
+ <listitem>
+ <para>Where to send patches back to the original authors.</para>
+ </listitem>
+
+ <listitem>
+ <para>Perhaps an overview of the FreeBSD-specific changes that have
+ been made.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>However, please do not import <filename>FREEBSD-upgrade</filename>
+ with the contributed source. Rather you should <command>cvs add
+ FREEBSD-upgrade ; cvs ci</command> after the initial import. Example
+ wording from <filename>src/contrib/cpio</filename> is below:</para>
+
+ <programlisting>This directory contains virgin sources of the original distribution files
+on a "vendor" branch. Do not, under any circumstances, attempt to upgrade
+the files in this directory via patches and a cvs commit. New versions or
+official-patch versions must be imported. Please remember to import with
+"-ko" to prevent CVS from corrupting any vendor RCS Ids.
+
+For the import of GNU cpio 2.4.2, the following files were removed:
+
+ INSTALL cpio.info mkdir.c
+ Makefile.in cpio.texi mkinstalldirs
+
+To upgrade to a newer version of cpio, when it is available:
+ 1. Unpack the new version into an empty directory.
+ [Do not make ANY changes to the files.]
+
+ 2. Remove the files listed above and any others that don't apply to
+ FreeBSD.
+
+ 3. Use the command:
+ cvs import -ko -m 'Virgin import of GNU cpio v&lt;version&gt;' \
+ src/contrib/cpio GNU cpio_&lt;version&gt;
+
+ For example, to do the import of version 2.4.2, I typed:
+ cvs import -ko -m 'Virgin import of GNU v2.4.2' \
+ src/contrib/cpio GNU cpio_2_4_2
+
+ 4. Follow the instructions printed out in step 3 to resolve any
+ conflicts between local FreeBSD changes and the newer version.
+
+Do not, under any circumstances, deviate from this procedure.
+
+To make local changes to cpio, simply patch and commit to the main
+branch (aka HEAD). Never make local changes on the GNU branch.
+
+All local changes should be submitted to "cpio@gnu.ai.mit.edu" for
+inclusion in the next vendor release.
+
+obrien@FreeBSD.org - 30 March 1997</programlisting>
+ </sect1>
+
+ <sect1 xml:id="policies-encumbered">
+ <title>Encumbered Files</title>
+
+ <para>It might occasionally be necessary to include an encumbered file in
+ the FreeBSD source tree. For example, if a device requires a small
+ piece of binary code to be loaded to it before the device will operate,
+ and we do not have the source to that code, then the binary file is said
+ to be encumbered. The following policies apply to including encumbered
+ files in the FreeBSD source tree.</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Any file which is interpreted or executed by the system CPU(s)
+ and not in source format is encumbered.</para>
+ </listitem>
+
+ <listitem>
+ <para>Any file with a license more restrictive than BSD or GNU is
+ encumbered.</para>
+ </listitem>
+
+ <listitem>
+ <para>A file which contains downloadable binary data for use by the
+ hardware is not encumbered, unless (1) or (2) apply to it. It must
+ be stored in an architecture neutral ASCII format (file2c or
+ uuencoding is recommended).</para>
+ </listitem>
+
+ <listitem>
+ <para>Any encumbered file requires specific approval from the
+ <link xlink:href="&url.articles.contributors;/staff-core.html">Core team</link> before it is added to the
+ CVS repository.</para>
+ </listitem>
+
+ <listitem>
+ <para>Encumbered files go in <filename>src/contrib</filename> or
+ <filename>src/sys/contrib</filename>.</para>
+ </listitem>
+
+ <listitem>
+ <para>The entire module should be kept together. There is no point in
+ splitting it, unless there is code-sharing with non-encumbered
+ code.</para>
+ </listitem>
+
+ <listitem>
+ <para>Object files are named
+ <filename>arch/filename.o.uu&gt;</filename>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Kernel files:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Should always be referenced in
+ <filename>conf/files.*</filename> (for build simplicity).</para>
+ </listitem>
+
+ <listitem>
+ <para>Should always be in <filename>LINT</filename>, but the
+ <link xlink:href="&url.articles.contributors;/staff-core.html">Core team</link> decides per case if it
+ should be commented out or not. The
+ <link xlink:href="&url.articles.contributors;/staff-core.html">Core team</link> can, of course, change
+ their minds later on.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <firstterm>Release Engineer</firstterm>
+ decides whether or not it goes into the release.</para>
+ </listitem>
+ </orderedlist>
+ </listitem>
+
+ <listitem>
+ <para>User-land files:</para>
+
+ <orderedlist>
+ <listitem>
+ <indexterm><primary>core team</primary></indexterm>
+ <para>The <link xlink:href="&url.articles.contributors;/staff-core.html">Core team</link> decides if
+ the code should be part of <command>make world</command>.</para>
+ </listitem>
+
+ <listitem>
+ <indexterm><primary>release engineer</primary></indexterm>
+ <para>The <link xlink:href="&url.articles.contributors;/staff-who.html">Release Engineer</link>
+ decides if it goes into the release.</para>
+ </listitem>
+ </orderedlist>
+ </listitem>
+ </orderedlist>
+ </sect1>
+
+ <sect1 xml:id="policies-shlib">
+ <info><title>Shared Libraries</title>
+ <authorgroup>
+ <author><personname><firstname>Satoshi</firstname><surname>Asami</surname></personname><contrib>Contributed by </contrib></author>
+ <author><personname><firstname>Peter</firstname><surname>Wemm</surname></personname></author>
+ <author><personname><firstname>David</firstname><surname>O'Brien</surname></personname></author>
+ </authorgroup>
+
+ </info>
+
+
+
+ <para>If you are adding shared library support to a port or other piece of
+ software that does not have one, the version numbers should follow these
+ rules. Generally, the resulting numbers will have nothing to do with
+ the release version of the software.</para>
+
+ <para>The three principles of shared library building are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Start from <literal>1.0</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>If there is a change that is backwards compatible, bump minor
+ number (note that ELF systems ignore the minor number)</para>
+ </listitem>
+
+ <listitem>
+ <para>If there is an incompatible change, bump major number</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>For instance, added functions and bugfixes result in the minor
+ version number being bumped, while deleted functions, changed function
+ call syntax, etc. will force the major version number to change.</para>
+
+ <para>Stick to version numbers of the form major.minor
+ (<replaceable>x</replaceable>.<replaceable>y</replaceable>). Our a.out
+ dynamic linker does not handle version numbers of the form
+ <replaceable>x</replaceable>.<replaceable>y</replaceable>.<replaceable>z</replaceable>
+ well. Any version number after the <replaceable>y</replaceable>
+ (i.e. the third digit) is totally ignored when comparing shared lib
+ version numbers to decide which library to link with. Given two shared
+ libraries that differ only in the <quote>micro</quote> revision,
+ <command>ld.so</command> will link with the higher one. That is, if you link
+ with <filename>libfoo.so.3.3.3</filename>, the linker only records
+ <literal>3.3</literal> in the headers, and will link with anything
+ starting with
+ <replaceable>libfoo.so.3</replaceable>.<replaceable>(anything &gt;=
+ 3)</replaceable>.<replaceable>(highest
+ available)</replaceable>.</para>
+
+ <note>
+ <para><command>ld.so</command> will always use the highest
+ <quote>minor</quote> revision. For instance, it will use
+ <filename>libc.so.2.2</filename> in preference to
+ <filename>libc.so.2.0</filename>, even if the program was initially
+ linked with <filename>libc.so.2.0</filename>.</para>
+ </note>
+
+ <para>In addition, our ELF dynamic linker does not handle minor version
+ numbers at all. However, one should still specify a major and minor
+ version number as our <filename>Makefile</filename>s <quote>do the right thing</quote>
+ based on the type of system.</para>
+
+ <para>For non-port libraries, it is also our policy to change the shared
+ library version number only once between releases. In addition, it is
+ our policy to change the major shared library version number only once
+ between major OS releases (i.e. from 3.0 to 4.0). When you make a
+ change to a system library that requires the version number to be
+ bumped, check the <filename>Makefile</filename>'s commit logs. It is the
+ responsibility of the committer to ensure that the first such change
+ since the release will result in the shared library version number in
+ the <filename>Makefile</filename> to be updated, and any subsequent
+ changes will not.</para>
+ </sect1>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/secure/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/secure/chapter.xml
new file mode 100644
index 0000000000..e382c5fc69
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/secure/chapter.xml
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="secure">
+ <info><title>Secure Programming</title>
+ <authorgroup>
+ <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname><contrib>Contributed by </contrib></author>
+ </authorgroup>
+ </info>
+
+
+
+ <sect1 xml:id="secure-synopsis"><title>Synopsis</title>
+
+ <para>This chapter describes some of the security issues that
+ have plagued &unix; programmers for decades and some of the new
+ tools available to help programmers avoid writing exploitable
+ code.</para>
+ </sect1>
+
+ <sect1 xml:id="secure-philosophy"><title>Secure Design
+ Methodology</title>
+
+ <para>Writing secure applications takes a very scrutinous and
+ pessimistic outlook on life. Applications should be run with
+ the principle of <quote>least privilege</quote> so that no
+ process is ever running with more than the bare minimum access
+ that it needs to accomplish its function. Previously tested
+ code should be reused whenever possible to avoid common
+ mistakes that others may have already fixed.</para>
+
+ <para>One of the pitfalls of the &unix; environment is how easy it
+ is to make assumptions about the sanity of the environment.
+ Applications should never trust user input (in all its forms),
+ system resources, inter-process communication, or the timing of
+ events. &unix; processes do not execute synchronously so logical
+ operations are rarely atomic.</para>
+ </sect1>
+
+ <sect1 xml:id="secure-bufferov"><title>Buffer Overflows</title>
+
+ <para>Buffer Overflows have been around since the very
+ beginnings of the Von-Neuman <xref linkend="COD"/> architecture.
+
+ <indexterm><primary>buffer overflow</primary></indexterm>
+ <indexterm><primary>Von-Neuman</primary></indexterm>
+
+ They first gained widespread notoriety in 1988 with the Morris
+ Internet worm. Unfortunately, the same basic attack remains
+
+ <indexterm><primary>Morris Internet worm</primary></indexterm>
+
+ effective today. Of the 17 CERT security advisories of 1999, 10
+
+ <indexterm>
+ <primary>CERT</primary><secondary>security advisories</secondary>
+ </indexterm>
+
+ of them were directly caused by buffer-overflow software bugs.
+ By far the most common type of buffer overflow attack is based
+ on corrupting the stack.</para>
+
+ <indexterm><primary>stack</primary></indexterm>
+ <indexterm><primary>arguments</primary></indexterm>
+
+ <para>Most modern computer systems use a stack to pass arguments
+ to procedures and to store local variables. A stack is a last
+ in first out (LIFO) buffer in the high memory area of a process
+ image. When a program invokes a function a new "stack frame" is
+
+ <indexterm><primary>LIFO</primary></indexterm>
+ <indexterm>
+ <primary>process image</primary>
+ <secondary>stack pointer</secondary>
+ </indexterm>
+
+ created. This stack frame consists of the arguments passed to
+ the function as well as a dynamic amount of local variable
+ space. The "stack pointer" is a register that holds the current
+
+ <indexterm><primary>stack frame</primary></indexterm>
+ <indexterm><primary>stack pointer</primary></indexterm>
+
+ location of the top of the stack. Since this value is
+ constantly changing as new values are pushed onto the top of the
+ stack, many implementations also provide a "frame pointer" that
+ is located near the beginning of a stack frame so that local
+ variables can more easily be addressed relative to this
+ value. <xref linkend="COD"/> The return address for function
+
+ <indexterm><primary>frame pointer</primary></indexterm>
+ <indexterm>
+ <primary>process image</primary>
+ <secondary>frame pointer</secondary>
+ </indexterm>
+ <indexterm><primary>return address</primary></indexterm>
+ <indexterm><primary>stack-overflow</primary></indexterm>
+
+ calls is also stored on the stack, and this is the cause of
+ stack-overflow exploits since overflowing a local variable in a
+ function can overwrite the return address of that function,
+ potentially allowing a malicious user to execute any code he or
+ she wants.</para>
+
+ <para>Although stack-based attacks are by far the most common,
+ it would also be possible to overrun the stack with a heap-based
+ (malloc/free) attack.</para>
+
+ <para>The C programming language does not perform automatic
+ bounds checking on arrays or pointers as many other languages
+ do. In addition, the standard C library is filled with a
+ handful of very dangerous functions.</para>
+
+ <informaltable frame="none" pgwide="1">
+ <tgroup cols="2">
+ <tbody>
+ <row><entry><function>strcpy</function>(char *dest, const char
+ *src)</entry>
+ <entry><simpara>May overflow the dest buffer</simpara></entry>
+ </row>
+
+ <row><entry><function>strcat</function>(char *dest, const char
+ *src)</entry>
+ <entry><simpara>May overflow the dest buffer</simpara></entry>
+ </row>
+
+ <row><entry><function>getwd</function>(char *buf)</entry>
+ <entry><simpara>May overflow the buf buffer</simpara></entry>
+ </row>
+
+ <row><entry><function>gets</function>(char *s)</entry>
+ <entry><simpara>May overflow the s buffer</simpara></entry>
+ </row>
+
+ <row><entry><function>[vf]scanf</function>(const char *format,
+ ...)</entry>
+ <entry><simpara>May overflow its arguments.</simpara></entry>
+ </row>
+
+ <row><entry><function>realpath</function>(char *path, char
+ resolved_path[])</entry>
+ <entry><simpara>May overflow the path buffer</simpara></entry>
+ </row>
+
+ <row><entry><function>[v]sprintf</function>(char *str, const char
+ *format, ...)</entry>
+ <entry><simpara>May overflow the str buffer.</simpara></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <sect2><title>Example Buffer Overflow</title>
+
+ <para>The following example code contains a buffer overflow
+ designed to overwrite the return address and skip the
+ instruction immediately following the function call. (Inspired
+ by <xref linkend="Phrack"/>)</para>
+
+<programlisting>#include <tag>stdio.h</tag>
+
+void manipulate(char *buffer) {
+ char newbuffer[80];
+ strcpy(newbuffer,buffer);
+}
+
+int main() {
+ char ch,buffer[4096];
+ int i=0;
+
+ while ((buffer[i++] = getchar()) != '\n') {};
+
+ i=1;
+ manipulate(buffer);
+ i=2;
+ printf("The value of i is : %d\n",i);
+ return 0;
+}</programlisting>
+
+ <para>Let us examine what the memory image of this process would
+ look like if we were to input 160 spaces into our little program
+ before hitting return.</para>
+
+ <para>[XXX figure here!]</para>
+
+ <para>Obviously more malicious input can be devised to execute
+ actual compiled instructions (such as exec(/bin/sh)).</para>
+ </sect2>
+
+ <sect2><title>Avoiding Buffer Overflows</title>
+
+ <para>The most straightforward solution to the problem of
+ stack-overflows is to always use length restricted memory and
+ string copy functions. <function>strncpy</function> and
+ <function>strncat</function> are part of the standard C library.
+
+ <indexterm>
+ <primary>string copy functions</primary>
+ <secondary>strncpy</secondary>
+ </indexterm>
+ <indexterm>
+ <primary>string copy functions</primary>
+ <secondary>strncat</secondary>
+ </indexterm>
+
+ These functions accept a length value as a parameter which
+ should be no larger than the size of the destination buffer.
+ These functions will then copy up to `length' bytes from the
+ source to the destination. However there are a number of
+ problems with these functions. Neither function guarantees NUL
+ termination if the size of the input buffer is as large as the
+
+ <indexterm><primary>NUL termination</primary></indexterm>
+
+ destination. The length parameter is also used inconsistently
+ between strncpy and strncat so it is easy for programmers to get
+ confused as to their proper usage. There is also a significant
+ performance loss compared to <function>strcpy</function> when
+ copying a short string into a large buffer since
+ <function>strncpy</function> NUL fills up the size
+ specified.</para>
+
+ <para>In OpenBSD, another memory copy implementation has been
+
+ <indexterm><primary>OpenBSD</primary></indexterm>
+
+ created to get around these problem. The
+ <function>strlcpy</function> and <function>strlcat</function>
+ functions guarantee that they will always null terminate the
+ destination string when given a non-zero length argument. For
+ more information about these functions see <xref linkend="OpenBSD"/>. The OpenBSD <function>strlcpy</function> and
+ <function>strlcat</function> instructions have been in FreeBSD
+ since 3.3.</para>
+
+ <indexterm>
+ <primary>string copy functions</primary>
+ <secondary>strlcpy</secondary>
+ </indexterm>
+
+ <indexterm>
+ <primary>string copy functions</primary>
+ <secondary>strlcat</secondary>
+ </indexterm>
+
+ <sect3><title>Compiler based run-time bounds checking</title>
+
+ <indexterm><primary>bounds checking</primary>
+ <secondary>compiler-based</secondary></indexterm>
+
+ <para>Unfortunately there is still a very large assortment of
+ code in public use which blindly copies memory around without
+ using any of the bounded copy routines we just discussed.
+ Fortunately, there is another solution. Several compiler
+ add-ons and libraries exist to do Run-time bounds checking in
+ C/C++.</para>
+
+ <indexterm><primary>StackGuard</primary></indexterm>
+ <indexterm><primary>gcc</primary></indexterm>
+
+ <para>StackGuard is one such add-on that is implemented as a
+ small patch to the gcc code generator. From the <link xlink:href="http://immunix.org/stackguard.html">StackGuard
+ website</link>:
+
+ <blockquote><para>"StackGuard detects and defeats stack
+ smashing attacks by protecting the return address on the stack
+ from being altered. StackGuard places a "canary" word next to
+ the return address when a function is called. If the canary
+ word has been altered when the function returns, then a stack
+ smashing attack has been attempted, and the program responds
+ by emitting an intruder alert into syslog, and then
+ halts."</para></blockquote>
+
+ <blockquote><para>"StackGuard is implemented as a small patch
+ to the gcc code generator, specifically the function_prolog()
+ and function_epilog() routines. function_prolog() has been
+ enhanced to lay down canaries on the stack when functions
+ start, and function_epilog() checks canary integrity when the
+ function exits. Any attempt at corrupting the return address
+ is thus detected before the function
+ returns."</para></blockquote>
+ </para>
+
+ <indexterm><primary>buffer overflow</primary></indexterm>
+
+ <para>Recompiling your application with StackGuard is an
+ effective means of stopping most buffer-overflow attacks, but
+ it can still be compromised.</para>
+
+ </sect3>
+
+ <sect3><title>Library based run-time bounds checking</title>
+
+ <indexterm>
+ <primary>bounds checking</primary>
+ <secondary>library-based</secondary>
+ </indexterm>
+
+ <para>Compiler-based mechanisms are completely useless for
+ binary-only software for which you cannot recompile. For
+ these situations there are a number of libraries which
+ re-implement the unsafe functions of the C-library
+ (<function>strcpy</function>, <function>fscanf</function>,
+ <function>getwd</function>, etc..) and ensure that these
+ functions can never write past the stack pointer.</para>
+
+ <itemizedlist>
+ <listitem><simpara>libsafe</simpara></listitem>
+ <listitem><simpara>libverify</simpara></listitem>
+ <listitem><simpara>libparanoia</simpara></listitem>
+ </itemizedlist>
+
+ <para>Unfortunately these library-based defenses have a number
+ of shortcomings. These libraries only protect against a very
+ small set of security related issues and they neglect to fix
+ the actual problem. These defenses may fail if the
+ application was compiled with -fomit-frame-pointer. Also, the
+ LD_PRELOAD and LD_LIBRARY_PATH environment variables can be
+ overwritten/unset by the user.</para>
+ </sect3>
+
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="secure-setuid"><title>SetUID issues</title>
+
+ <indexterm><primary>seteuid</primary></indexterm>
+
+ <para>There are at least 6 different IDs associated with any
+ given process. Because of this you have to be very careful with
+ the access that your process has at any given time. In
+ particular, all seteuid applications should give up their
+ privileges as soon as it is no longer required.</para>
+
+ <indexterm>
+ <primary>user IDs</primary>
+ <secondary>real user ID</secondary>
+ </indexterm>
+ <indexterm>
+ <primary>user IDs</primary>
+ <secondary>effective user ID</secondary>
+ </indexterm>
+
+ <para>The real user ID can only be changed by a superuser
+ process. The <application>login</application> program sets this
+ when a user initially logs in and it is seldom changed.</para>
+
+ <para>The effective user ID is set by the
+ <function>exec()</function> functions if a program has its
+ seteuid bit set. An application can call
+ <function>seteuid()</function> at any time to set the effective
+ user ID to either the real user ID or the saved set-user-ID.
+ When the effective user ID is set by <function>exec()</function>
+ functions, the previous value is saved in the saved set-user-ID.</para>
+
+ </sect1>
+
+ <sect1 xml:id="secure-chroot"><title>Limiting your program's environment</title>
+
+ <indexterm><primary>chroot()</primary></indexterm>
+
+ <para>The traditional method of restricting a process
+ is with the <function>chroot()</function> system call. This
+ system call changes the root directory from which all other
+ paths are referenced for a process and any child processes. For
+ this call to succeed the process must have execute (search)
+ permission on the directory being referenced. The new
+ environment does not actually take effect until you
+ <function>chdir()</function> into your new environment. It
+ should also be noted that a process can easily break out of a
+ chroot environment if it has root privilege. This could be
+ accomplished by creating device nodes to read kernel memory,
+ attaching a debugger to a process outside of the jail, or in
+ many other creative ways.</para>
+
+ <para>The behavior of the <function>chroot()</function> system
+ call can be controlled somewhat with the
+ kern.chroot_allow_open_directories <command>sysctl</command>
+ variable. When this value is set to 0,
+ <function>chroot()</function> will fail with EPERM if there are
+ any directories open. If set to the default value of 1, then
+ <function>chroot()</function> will fail with EPERM if there are
+ any directories open and the process is already subject to a
+ <function>chroot()</function> call. For any other value, the
+ check for open directories will be bypassed completely.</para>
+
+ <sect2><title>FreeBSD's jail functionality</title>
+
+ <indexterm><primary>jail</primary></indexterm>
+
+ <para>The concept of a Jail extends upon the
+ <function>chroot()</function> by limiting the powers of the
+ superuser to create a true `virtual server'. Once a prison is
+ set up all network communication must take place through the
+ specified IP address, and the power of "root privilege" in this
+ jail is severely constrained.</para>
+
+ <para>While in a prison, any tests of superuser power within the
+ kernel using the <function>suser()</function> call will fail.
+ However, some calls to <function>suser()</function> have been
+ changed to a new interface <function>suser_xxx()</function>.
+ This function is responsible for recognizing or denying access
+ to superuser power for imprisoned processes.</para>
+
+ <para>A superuser process within a jailed environment has the
+ power to:</para>
+
+ <itemizedlist>
+ <listitem><simpara>Manipulate credential with
+ <function>setuid</function>, <function>seteuid</function>,
+ <function>setgid</function>, <function>setegid</function>,
+ <function>setgroups</function>, <function>setreuid</function>,
+ <function>setregid</function>, <function>setlogin</function></simpara></listitem>
+ <listitem><simpara>Set resource limits with <function>setrlimit</function></simpara></listitem>
+ <listitem><simpara>Modify some sysctl nodes
+ (kern.hostname)</simpara></listitem>
+ <listitem><simpara><function>chroot()</function></simpara></listitem>
+ <listitem><simpara>Set flags on a vnode:
+ <function>chflags</function>,
+ <function>fchflags</function></simpara></listitem>
+ <listitem><simpara>Set attributes of a vnode such as file
+ permission, owner, group, size, access time, and modification
+ time.</simpara></listitem>
+ <listitem><simpara>Bind to privileged ports in the Internet
+ domain (ports &lt; 1024)</simpara></listitem>
+ </itemizedlist>
+
+ <para><function>Jail</function> is a very useful tool for
+ running applications in a secure environment but it does have
+ some shortcomings. Currently, the IPC mechanisms have not been
+ converted to the <function>suser_xxx</function> so applications
+ such as MySQL cannot be run within a jail. Superuser access
+ may have a very limited meaning within a jail, but there is
+ no way to specify exactly what "very limited" means.</para>
+ </sect2>
+
+ <sect2><title>&posix;.1e Process Capabilities</title>
+
+ <indexterm><primary>POSIX.1e Process Capabilities</primary></indexterm>
+ <indexterm><primary>TrustedBSD</primary></indexterm>
+
+ <para>&posix; has released a working draft that adds event
+ auditing, access control lists, fine grained privileges,
+ information labeling, and mandatory access control.</para>
+ <para>This is a work in progress and is the focus of the <link xlink:href="http://www.trustedbsd.org/">TrustedBSD</link> project. Some
+ of the initial work has been committed to &os.current;
+ (cap_set_proc(3)).</para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 xml:id="secure-trust"><title>Trust</title>
+
+ <para>An application should never assume that anything about the
+ users environment is sane. This includes (but is certainly not
+ limited to): user input, signals, environment variables,
+ resources, IPC, mmaps, the filesystem working directory, file
+ descriptors, the # of open files, etc.</para>
+
+ <indexterm><primary>positive filtering</primary></indexterm>
+ <indexterm><primary>data validation</primary></indexterm>
+
+ <para>You should never assume that you can catch all forms of
+ invalid input that a user might supply. Instead, your
+ application should use positive filtering to only allow a
+ specific subset of inputs that you deem safe. Improper data
+ validation has been the cause of many exploits, especially with
+ CGI scripts on the world wide web. For filenames you need to be
+ extra careful about paths ("../", "/"), symbolic links, and
+ shell escape characters.</para>
+
+ <indexterm><primary>Perl Taint mode</primary></indexterm>
+
+ <para>Perl has a really cool feature called "Taint" mode which
+ can be used to prevent scripts from using data derived outside
+ the program in an unsafe way. This mode will check command line
+ arguments, environment variables, locale information, the
+ results of certain syscalls (<function>readdir()</function>,
+ <function>readlink()</function>,
+ <function>getpwxxx()</function>, and all file input.</para>
+
+ </sect1>
+
+ <sect1 xml:id="secure-race-conditions">
+ <title>Race Conditions</title>
+
+ <para>A race condition is anomalous behavior caused by the
+ unexpected dependence on the relative timing of events. In
+ other words, a programmer incorrectly assumed that a particular
+ event would always happen before another.</para>
+
+ <indexterm><primary>race conditions</primary>
+ <secondary>signals</secondary></indexterm>
+
+ <indexterm><primary>race conditions</primary>
+ <secondary>access checks</secondary></indexterm>
+
+ <indexterm><primary>race conditions</primary>
+ <secondary>file opens</secondary></indexterm>
+
+ <para>Some of the common causes of race conditions are signals,
+ access checks, and file opens. Signals are asynchronous events
+ by nature so special care must be taken in dealing with them.
+ Checking access with <function>access(2)</function> then
+ <function>open(2)</function> is clearly non-atomic. Users can
+ move files in between the two calls. Instead, privileged
+ applications should <function>seteuid()</function> and then call
+ <function>open()</function> directly. Along the same lines, an
+ application should always set a proper umask before
+ <function>open()</function> to obviate the need for spurious
+ <function>chmod()</function> calls.</para>
+
+ </sect1>
+
+ </chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/sockets/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/sockets/chapter.xml
new file mode 100644
index 0000000000..38d74e686c
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/sockets/chapter.xml
@@ -0,0 +1,1780 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="sockets">
+ <info><title>Sockets</title>
+ <authorgroup>
+ <author><personname><firstname>G. Adam</firstname><surname>Stanislav</surname></personname><contrib>Contributed by </contrib></author>
+ </authorgroup>
+ </info>
+
+
+
+ <sect1 xml:id="sockets-synopsis">
+ <title>Synopsis</title>
+
+ <para><acronym>BSD</acronym> sockets take interprocess
+ communications to a new level. It is no longer necessary for the
+ communicating processes to run on the same machine. They still
+ <emphasis>can</emphasis>, but they do not have to.</para>
+
+ <para>Not only do these processes not have to run on the same
+ machine, they do not have to run under the same operating
+ system. Thanks to <acronym>BSD</acronym> sockets, your FreeBSD
+ software can smoothly cooperate with a program running on a
+ &macintosh;, another one running on a &sun; workstation, yet another
+ one running under &windows; 2000, all connected with an
+ Ethernet-based local area network.</para>
+
+ <para>But your software can equally well cooperate with processes
+ running in another building, or on another continent, inside a
+ submarine, or a space shuttle.</para>
+
+ <para>It can also cooperate with processes that are not part of a
+ computer (at least not in the strict sense of the word), but of
+ such devices as printers, digital cameras, medical equipment.
+ Just about anything capable of digital communications.</para>
+
+ </sect1>
+
+ <sect1 xml:id="sockets-diversity">
+ <title>Networking and Diversity</title>
+
+ <para>We have already hinted on the <emphasis>diversity</emphasis>
+ of networking. Many different systems have to talk to each
+ other. And they have to speak the same language. They also have
+ to <emphasis>understand</emphasis> the same language the same
+ way.</para>
+
+ <para>People often think that <emphasis>body language</emphasis>
+ is universal. But it is not. Back in my early teens, my father
+ took me to Bulgaria. We were sitting at a table in a park in
+ Sofia, when a vendor approached us trying to sell us some
+ roasted almonds.</para>
+
+ <para>I had not learned much Bulgarian by then, so, instead of
+ saying no, I shook my head from side to side, the
+ <quote>universal</quote> body language for
+ <emphasis>no</emphasis>. The vendor quickly started serving us
+ some almonds.</para>
+
+ <para>I then remembered I had been told that in Bulgaria shaking
+ your head sideways meant <emphasis>yes</emphasis>. Quickly, I
+ started nodding my head up and down. The vendor noticed, took
+ his almonds, and walked away. To an uninformed observer, I did
+ not change the body language: I continued using the language of
+ shaking and nodding my head. What changed was the
+ <emphasis>meaning</emphasis> of the body language. At first, the
+ vendor and I interpreted the same language as having completely
+ different meaning. I had to adjust my own interpretation of that
+ language so the vendor would understand.</para>
+
+ <para>It is the same with computers: The same symbols may have
+ different, even outright opposite meaning. Therefore, for
+ two computers to understand each other, they must not only
+ agree on the same <emphasis>language</emphasis>, but on the
+ same <emphasis>interpretation</emphasis> of the language.
+ </para>
+ </sect1>
+
+ <sect1 xml:id="sockets-protocols">
+ <title>Protocols</title>
+
+ <para>While various programming languages tend to have complex
+ syntax and use a number of multi-letter reserved words (which
+ makes them easy for the human programmer to understand), the
+ languages of data communications tend to be very terse. Instead
+ of multi-byte words, they often use individual
+ <emphasis>bits</emphasis>. There is a very convincing reason
+ for it: While data travels <emphasis>inside</emphasis> your
+ computer at speeds approaching the speed of light, it often
+ travels considerably slower between two computers.</para>
+
+ <para>Because the languages used in data communications are so
+ terse, we usually refer to them as
+ <emphasis>protocols</emphasis> rather than languages.</para>
+
+ <para>As data travels from one computer to another, it always uses
+ more than one protocol. These protocols are
+ <emphasis>layered</emphasis>. The data can be compared to the
+ inside of an onion: You have to peel off several layers of
+ <quote>skin</quote> to get to the data. This is best
+ illustrated with a picture:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/layers"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced">+----------------+
+| Ethernet |
+|+--------------+|
+|| IP ||
+||+------------+||
+||| TCP |||
+|||+----------+|||
+|||| HTTP ||||
+||||+--------+||||
+||||| PNG |||||
+|||||+------+|||||
+|||||| Data ||||||
+|||||+------+|||||
+||||+--------+||||
+|||+----------+|||
+||+------------+||
+|+--------------+|
++----------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Protocol Layers</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>In this example, we are trying to get an image from a web
+ page we are connected to via an Ethernet.</para>
+
+ <para>The image consists of raw data, which is simply a sequence
+ of <acronym>RGB</acronym> values that our software can process,
+ i.e., convert into an image and display on our monitor.</para>
+
+ <para>Alas, our software has no way of knowing how the raw data is
+ organized: Is it a sequence of <acronym>RGB</acronym> values, or
+ a sequence of grayscale intensities, or perhaps of
+ <acronym>CMYK</acronym> encoded colors? Is the data represented
+ by 8-bit quanta, or are they 16 bits in size, or perhaps 4 bits?
+ How many rows and columns does the image consist of? Should
+ certain pixels be transparent?</para>
+
+ <para>I think you get the picture...</para>
+
+ <para>To inform our software how to handle the raw data, it is
+ encoded as a <acronym>PNG</acronym> file. It could be a
+ <acronym>GIF</acronym>, or a <acronym>JPEG</acronym>, but it is
+ a <acronym>PNG</acronym>.</para>
+
+ <para>And <acronym>PNG</acronym> is a protocol.</para>
+
+ <para>At this point, I can hear some of you yelling,
+ <emphasis><quote>No, it is not! It is a file
+ format!</quote></emphasis></para>
+
+ <para>Well, of course it is a file format. But from the
+ perspective of data communications, a file format is a protocol:
+ The file structure is a <emphasis>language</emphasis>, a terse
+ one at that, communicating to our <emphasis>process</emphasis>
+ how the data is organized. Ergo, it is a
+ <emphasis>protocol</emphasis>.</para>
+
+ <para>Alas, if all we received was the <acronym>PNG</acronym>
+ file, our software would be facing a serious problem: How is it
+ supposed to know the data is representing an image, as opposed
+ to some text, or perhaps a sound, or what not? Secondly, how is
+ it supposed to know the image is in the <acronym>PNG</acronym>
+ format as opposed to <acronym>GIF</acronym>, or
+ <acronym>JPEG</acronym>, or some other image format?</para>
+
+ <para>To obtain that information, we are using another protocol:
+ <acronym>HTTP</acronym>. This protocol can tell us exactly that
+ the data represents an image, and that it uses the
+ <acronym>PNG</acronym> protocol. It can also tell us some other
+ things, but let us stay focused on protocol layers here.
+ </para>
+
+ <para>So, now we have some data wrapped in the <acronym>PNG</acronym>
+ protocol, wrapped in the <acronym>HTTP</acronym> protocol.
+ How did we get it from the server?</para>
+
+ <para>By using <acronym>TCP/IP</acronym> over Ethernet, that is
+ how. Indeed, that is three more protocols. Instead of
+ continuing inside out, I am now going to talk about Ethernet,
+ simply because it is easier to explain the rest that way.</para>
+
+ <para>Ethernet is an interesting system of connecting computers in
+ a <emphasis>local area network</emphasis>
+ (<acronym>LAN</acronym>). Each computer has a <emphasis>network
+ interface card</emphasis> (<acronym>NIC</acronym>), which has a
+ unique 48-bit <acronym>ID</acronym> called its
+ <emphasis>address</emphasis>. No two Ethernet
+ <acronym>NIC</acronym>s in the world have the same address.
+ </para>
+
+ <para>These <acronym>NIC</acronym>s are all connected with each
+ other. Whenever one computer wants to communicate with another
+ in the same Ethernet <acronym>LAN</acronym>, it sends a message
+ over the network. Every <acronym>NIC</acronym> sees the
+ message. But as part of the Ethernet
+ <emphasis>protocol</emphasis>, the data contains the address of
+ the destination <acronym>NIC</acronym> (among other things). So,
+ only one of all the network interface cards will pay attention
+ to it, the rest will ignore it.</para>
+
+ <para>But not all computers are connected to the same
+ network. Just because we have received the data over our
+ Ethernet does not mean it originated in our own local area
+ network. It could have come to us from some other network (which
+ may not even be Ethernet based) connected with our own network
+ via the Internet.</para>
+
+ <para>All data is transferred over the Internet using
+ <acronym>IP</acronym>, which stands for <emphasis>Internet
+ Protocol</emphasis>. Its basic role is to let us know where in
+ the world the data has arrived from, and where it is supposed to
+ go to. It does not <emphasis>guarantee</emphasis> we will
+ receive the data, only that we will know where it came from
+ <emphasis>if</emphasis> we do receive it.</para>
+
+ <para>Even if we do receive the data, <acronym>IP</acronym> does
+ not guarantee we will receive various chunks of data in the same
+ order the other computer has sent it to us. So, we can receive
+ the center of our image before we receive the upper left corner
+ and after the lower right, for example.</para>
+
+ <para>It is <acronym>TCP</acronym> (<emphasis>Transmission Control
+ Protocol</emphasis>) that asks the sender to resend any lost
+ data and that places it all into the proper order.</para>
+
+ <para>All in all, it took <emphasis>five</emphasis> different
+ protocols for one computer to communicate to another what an
+ image looks like. We received the data wrapped into the
+ <acronym>PNG</acronym> protocol, which was wrapped into the
+ <acronym>HTTP</acronym> protocol, which was wrapped into the
+ <acronym>TCP</acronym> protocol, which was wrapped into the
+ <acronym>IP</acronym> protocol, which was wrapped into the
+ <acronym>Ethernet</acronym> protocol.</para>
+
+ <para>Oh, and by the way, there probably were several other
+ protocols involved somewhere on the way. For example, if our
+ <acronym>LAN</acronym> was connected to the Internet through a
+ dial-up call, it used the <acronym>PPP</acronym> protocol over
+ the modem which used one (or several) of the various modem
+ protocols, et cetera, et cetera, et cetera...</para>
+
+ <para>As a developer you should be asking by now,
+ <emphasis><quote>How am I supposed to handle it
+ all?</quote></emphasis></para>
+
+ <para>Luckily for you, you are <emphasis>not</emphasis> supposed
+ to handle it all. You <emphasis>are</emphasis> supposed to
+ handle some of it, but not all of it. Specifically, you need not
+ worry about the physical connection (in our case Ethernet and
+ possibly <acronym>PPP</acronym>, etc). Nor do you need to handle
+ the Internet Protocol, or the Transmission Control
+ Protocol.</para>
+
+ <para>In other words, you do not have to do anything to receive
+ the data from the other computer. Well, you do have to
+ <emphasis>ask</emphasis> for it, but that is almost as simple as
+ opening a file.</para>
+
+ <para>Once you have received the data, it is up to you to figure
+ out what to do with it. In our case, you would need to
+ understand the <acronym>HTTP</acronym> protocol and the
+ <acronym>PNG</acronym> file structure.</para>
+
+ <para>To use an analogy, all the internetworking protocols become
+ a gray area: Not so much because we do not understand how it
+ works, but because we are no longer concerned about it. The
+ sockets interface takes care of this gray area for us:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/slayers"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced">+----------------+
+|xxxxEthernetxxxx|
+|+--------------+|
+||xxxxxxIPxxxxxx||
+||+------------+||
+|||xxxxxTCPxxxx|||
+|||+----------+|||
+|||| HTTP ||||
+||||+--------+||||
+||||| PNG |||||
+|||||+------+|||||
+|||||| Data ||||||
+|||||+------+|||||
+||||+--------+||||
+|||+----------+|||
+||+------------+||
+|+--------------+|
++----------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Sockets Covered Protocol Layers</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>We only need to understand any protocols that tell us how to
+ <emphasis>interpret the data</emphasis>, not how to
+ <emphasis>receive</emphasis> it from another process, nor how to
+ <emphasis>send</emphasis> it to another process.</para>
+
+ </sect1>
+
+ <sect1 xml:id="sockets-model">
+ <title>The Sockets Model</title>
+
+ <para><acronym>BSD</acronym> sockets are built on the basic &unix;
+ model: <emphasis>Everything is a file.</emphasis> In our
+ example, then, sockets would let us receive an <emphasis>HTTP
+ file</emphasis>, so to speak. It would then be up to us to
+ extract the <emphasis><acronym>PNG</acronym> file</emphasis>
+ from it.
+ </para>
+
+ <para>Because of the complexity of internetworking, we cannot just
+ use the <function role="syscall">open</function> system call, or
+ the <function>open()</function> C function. Instead, we need to
+ take several steps to <quote>opening</quote> a socket.</para>
+
+ <para>Once we do, however, we can start treating the
+ <emphasis>socket</emphasis> the same way we treat any
+ <emphasis>file descriptor</emphasis>: We can
+ <function>read</function> from it, <function>write</function> to
+ it, <function>pipe</function> it, and, eventually,
+ <function>close</function> it.</para>
+
+ </sect1>
+
+ <sect1 xml:id="sockets-essential-functions">
+ <title>Essential Socket Functions</title>
+
+ <para>While FreeBSD offers different functions to work with
+ sockets, we only <emphasis>need</emphasis> four to
+ <quote>open</quote> a socket. And in some cases we only need
+ two.</para>
+
+ <sect2 xml:id="sockets-client-server">
+ <title>The Client-Server Difference</title>
+
+ <para>Typically, one of the ends of a socket-based data
+ communication is a <emphasis>server</emphasis>, the other is a
+ <emphasis>client</emphasis>.</para>
+
+ <sect3 xml:id="sockets-common-elements">
+ <title>The Common Elements</title>
+
+ <sect4 xml:id="sockets-socket">
+ <title><function>socket</function></title>
+
+ <para>The one function used by both, clients and servers, is
+ &man.socket.2;. It is declared this way:</para>
+
+<programlisting>
+int socket(int domain, int type, int protocol);
+</programlisting>
+
+ <para>The return value is of the same type as that of
+ <function>open</function>, an integer. FreeBSD allocates
+ its value from the same pool as that of file handles.
+ That is what allows sockets to be treated the same way as
+ files.</para>
+
+ <para>The <varname>domain</varname> argument tells the
+ system what <emphasis>protocol family</emphasis> you want
+ it to use. Many of them exist, some are vendor specific,
+ others are very common. They are declared in
+ <filename>sys/socket.h</filename>.</para>
+
+ <para>Use <constant>PF_INET</constant> for
+ <acronym>UDP</acronym>, <acronym>TCP</acronym> and other
+ Internet protocols (<acronym>IP</acronym>v4).</para>
+
+ <para>Five values are defined for the
+ <varname>type</varname> argument, again, in
+ <filename>sys/socket.h</filename>. All of them start with
+ <quote><constant>SOCK_</constant></quote>. The most
+ common one is <constant>SOCK_STREAM</constant>, which
+ tells the system you are asking for a <emphasis>reliable
+ stream delivery service</emphasis> (which is
+ <acronym>TCP</acronym> when used with
+ <constant>PF_INET</constant>).</para>
+
+ <para>If you asked for <constant>SOCK_DGRAM</constant>, you
+ would be requesting a <emphasis>connectionless datagram
+ delivery service</emphasis> (in our case,
+ <acronym>UDP</acronym>).</para>
+
+ <para>If you wanted to be in charge of the low-level
+ protocols (such as <acronym>IP</acronym>), or even network
+ interfaces (e.g., the Ethernet), you would need to specify
+ <constant>SOCK_RAW</constant>.</para>
+
+ <para>Finally, the <varname>protocol</varname> argument
+ depends on the previous two arguments, and is not always
+ meaningful. In that case, use <constant>0</constant> for
+ its value.</para>
+
+ <note xml:id="sockets-unconnected">
+ <title>The Unconnected Socket</title>
+
+ <para>Nowhere, in the <function>socket</function> function
+ have we specified to what other system we should be
+ connected. Our newly created socket remains
+ <emphasis>unconnected</emphasis>.</para>
+
+ <para>This is on purpose: To use a telephone analogy, we
+ have just attached a modem to the phone line. We have
+ neither told the modem to make a call, nor to answer if
+ the phone rings.</para>
+ </note>
+
+ </sect4>
+
+ <sect4 xml:id="sockets-sockaddr">
+ <title><varname>sockaddr</varname></title>
+
+ <para>Various functions of the sockets family expect the
+ address of (or pointer to, to use C terminology) a small
+ area of the memory. The various C declarations in the
+ <filename>sys/socket.h</filename> refer to it as
+ <varname>struct sockaddr</varname>. This structure is
+ declared in the same file:</para>
+
+<programlisting>
+/*
+ * Structure used by kernel to store most
+ * addresses.
+ */
+struct sockaddr {
+ unsigned char sa_len; /* total length */
+ sa_family_t sa_family; /* address family */
+ char sa_data[14]; /* actually longer; address value */
+};
+#define SOCK_MAXADDRLEN 255 /* longest possible addresses */
+</programlisting>
+
+ <para>Please note the <emphasis>vagueness</emphasis> with
+ which the <varname>sa_data</varname> field is declared,
+ just as an array of <constant>14</constant> bytes, with
+ the comment hinting there can be more than
+ <constant>14</constant> of them.</para>
+
+ <para>This vagueness is quite deliberate. Sockets is a very
+ powerful interface. While most people perhaps think of it
+ as nothing more than the Internet interface&mdash;and most
+ applications probably use it for that
+ nowadays&mdash;sockets can be used for just about
+ <emphasis>any</emphasis> kind of interprocess
+ communications, of which the Internet (or, more precisely,
+ <acronym>IP</acronym>) is only one.</para>
+
+ <para>The <filename>sys/socket.h</filename> refers to the
+ various types of protocols sockets will handle as
+ <emphasis>address families</emphasis>, and lists them
+ right before the definition of
+ <varname>sockaddr</varname>:</para>
+
+<programlisting>
+/*
+ * Address families.
+ */
+#define AF_UNSPEC 0 /* unspecified */
+#define AF_LOCAL 1 /* local to host (pipes, portals) */
+#define AF_UNIX AF_LOCAL /* backward compatibility */
+#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
+#define AF_IMPLINK 3 /* arpanet imp addresses */
+#define AF_PUP 4 /* pup protocols: e.g. BSP */
+#define AF_CHAOS 5 /* mit CHAOS protocols */
+#define AF_NS 6 /* XEROX NS protocols */
+#define AF_ISO 7 /* ISO protocols */
+#define AF_OSI AF_ISO
+#define AF_ECMA 8 /* European computer manufacturers */
+#define AF_DATAKIT 9 /* datakit protocols */
+#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
+#define AF_SNA 11 /* IBM SNA */
+#define AF_DECnet 12 /* DECnet */
+#define AF_DLI 13 /* DEC Direct data link interface */
+#define AF_LAT 14 /* LAT */
+#define AF_HYLINK 15 /* NSC Hyperchannel */
+#define AF_APPLETALK 16 /* Apple Talk */
+#define AF_ROUTE 17 /* Internal Routing Protocol */
+#define AF_LINK 18 /* Link layer interface */
+#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
+#define AF_COIP 20 /* connection-oriented IP, aka ST II */
+#define AF_CNT 21 /* Computer Network Technology */
+#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */
+#define AF_IPX 23 /* Novell Internet Protocol */
+#define AF_SIP 24 /* Simple Internet Protocol */
+#define pseudo_AF_PIP 25 /* Help Identify PIP packets */
+#define AF_ISDN 26 /* Integrated Services Digital Network*/
+#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */
+#define pseudo_AF_KEY 27 /* Internal key-management function */
+#define AF_INET6 28 /* IPv6 */
+#define AF_NATM 29 /* native ATM access */
+#define AF_ATM 30 /* ATM */
+#define pseudo_AF_HDRCMPLT 31 /* Used by BPF to not rewrite headers
+ * in interface output routine
+ */
+#define AF_NETGRAPH 32 /* Netgraph sockets */
+#define AF_SLOW 33 /* 802.3ad slow protocol */
+#define AF_SCLUSTER 34 /* Sitara cluster protocol */
+#define AF_ARP 35
+#define AF_BLUETOOTH 36 /* Bluetooth sockets */
+#define AF_MAX 37
+
+</programlisting>
+
+ <para>The one used for <acronym>IP</acronym> is
+ <symbol>AF_INET</symbol>. It is a symbol for the constant
+ <constant>2</constant>.</para>
+
+ <para>It is the <emphasis>address family</emphasis> listed
+ in the <varname>sa_family</varname> field of
+ <varname>sockaddr</varname> that decides how exactly the
+ vaguely named bytes of <varname>sa_data</varname> will be
+ used.</para>
+
+ <para>Specifically, whenever the <emphasis>address
+ family</emphasis> is <symbol>AF_INET</symbol>, we can use
+ <varname>struct sockaddr_in</varname> found in
+ <filename>netinet/in.h</filename>, wherever
+ <varname>sockaddr</varname> is expected:</para>
+
+<programlisting>
+/*
+ * Socket address, internet style.
+ */
+struct sockaddr_in {
+ uint8_t sin_len;
+ sa_family_t sin_family;
+ in_port_t sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+</programlisting>
+
+ <para>We can visualize its organization this way:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sain"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+-----------------+
+ 0 | 0 | Family | Port |
+ +--------+--------+-----------------+
+ 4 | IP Address |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>sockaddr_in</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>The three important fields are
+ <varname>sin_family</varname>, which is byte 1 of the
+ structure, <varname>sin_port</varname>, a 16-bit value
+ found in bytes 2 and 3, and <varname>sin_addr</varname>, a
+ 32-bit integer representation of the <acronym>IP</acronym>
+ address, stored in bytes 4-7.</para>
+
+ <para>Now, let us try to fill it out. Let us assume we are
+ trying to write a client for the
+ <emphasis>daytime</emphasis> protocol, which simply states
+ that its server will write a text string representing the
+ current date and time to port 13. We want to use
+ <acronym>TCP/IP</acronym>, so we need to specify
+ <constant>AF_INET</constant> in the address family
+ field. <constant>AF_INET</constant> is defined as
+ <constant>2</constant>. Let us use the
+ <acronym>IP</acronym> address of <systemitem class="ipaddress">192.43.244.18</systemitem>, which is the time
+ server of US federal government (<systemitem class="fqdomainname">time.nist.gov</systemitem>).</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainfill"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+-----------------+
+ 0 | 0 | 2 | 13 |
+ +-----------------+-----------------+
+ 4 | 192.43.244.18 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Specific example of sockaddr_in</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>By the way the <varname>sin_addr</varname> field is
+ declared as being of the <varname>struct in_addr</varname>
+ type, which is defined in
+ <filename>netinet/in.h</filename>:</para>
+
+<programlisting>
+/*
+ * Internet address (a structure for historical reasons)
+ */
+struct in_addr {
+ in_addr_t s_addr;
+};
+</programlisting>
+
+ <para>In addition, <varname>in_addr_t</varname> is a 32-bit
+ integer.</para>
+
+ <para>The <systemitem class="ipaddress">192.43.244.18</systemitem> is
+ just a convenient notation of expressing a 32-bit integer
+ by listing all of its 8-bit bytes, starting with the
+ <emphasis>most significant</emphasis> one.</para>
+
+ <para>So far, we have viewed <varname>sockaddr</varname> as
+ an abstraction. Our computer does not store
+ <varname>short</varname> integers as a single 16-bit
+ entity, but as a sequence of 2 bytes. Similarly, it stores
+ 32-bit integers as a sequence of 4 bytes.</para>
+
+ <para>Suppose we coded something like this:</para>
+
+<programlisting>
+ sa.sin_family = AF_INET;
+ sa.sin_port = 13;
+ sa.sin_addr.s_addr = (((((192 &lt;&lt; 8) | 43) &lt;&lt; 8) | 244) &lt;&lt; 8) | 18;
+</programlisting>
+
+ <para>What would the result look like?</para>
+
+ <para>Well, that depends, of course. On a &pentium;, or other
+ x86, based computer, it would look like this:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainlsb"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+--------+--------+
+ 0 | 0 | 2 | 13 | 0 |
+ +--------+--------+--------+--------+
+ 4 | 18 | 244 | 43 | 192 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>sockaddr_in on an Intel system</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>On a different system, it might look like this:
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainmsb"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+--------+--------+
+ 0 | 0 | 2 | 0 | 13 |
+ +--------+--------+--------+--------+
+ 4 | 192 | 43 | 244 | 18 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>sockaddr_in on an MSB system</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>And on a PDP it might look different yet. But the
+ above two are the most common ways in use today.</para>
+
+ <para>Ordinarily, wanting to write portable code,
+ programmers pretend that these differences do not
+ exist. And they get away with it (except when they code in
+ assembly language). Alas, you cannot get away with it that
+ easily when coding for sockets.</para>
+
+ <para>Why?</para>
+
+ <para>Because when communicating with another computer, you
+ usually do not know whether it stores data <emphasis>most
+ significant byte</emphasis> (<acronym>MSB</acronym>) or
+ <emphasis>least significant byte</emphasis>
+ (<acronym>LSB</acronym>) first.</para>
+
+ <para>You might be wondering, <emphasis><quote>So, will
+ sockets not handle it for me?</quote></emphasis></para>
+
+ <para>It will not.</para>
+
+ <para>While that answer may surprise you at first, remember
+ that the general sockets interface only understands the
+ <varname>sa_len</varname> and <varname>sa_family</varname>
+ fields of the <varname>sockaddr</varname> structure. You
+ do not have to worry about the byte order there (of
+ course, on FreeBSD <varname>sa_family</varname> is only 1
+ byte anyway, but many other &unix; systems do not have
+ <varname>sa_len</varname> and use 2 bytes for
+ <varname>sa_family</varname>, and expect the data in
+ whatever order is native to the computer).</para>
+
+ <para>But the rest of the data is just
+ <varname>sa_data[14]</varname> as far as sockets
+ goes. Depending on the <emphasis>address
+ family</emphasis>, sockets just forwards that data to its
+ destination.</para>
+
+ <para>Indeed, when we enter a port number, it is because we
+ want the other computer to know what service we are asking
+ for. And, when we are the server, we read the port number
+ so we know what service the other computer is expecting
+ from us. Either way, sockets only has to forward the port
+ number as data. It does not interpret it in any way.</para>
+
+ <para>Similarly, we enter the <acronym>IP</acronym> address
+ to tell everyone on the way where to send our data
+ to. Sockets, again, only forwards it as data.</para>
+
+ <para>That is why, we (the <emphasis>programmers</emphasis>,
+ not the <emphasis>sockets</emphasis>) have to distinguish
+ between the byte order used by our computer and a
+ conventional byte order to send the data in to the other
+ computer.</para>
+
+ <para>We will call the byte order our computer uses the
+ <emphasis>host byte order</emphasis>, or just the
+ <emphasis>host order</emphasis>.</para>
+
+ <para>There is a convention of sending the multi-byte data
+ over <acronym>IP</acronym>
+ <emphasis><acronym>MSB</acronym> first</emphasis>. This,
+ we will refer to as the <emphasis>network byte
+ order</emphasis>, or simply the <emphasis>network
+ order</emphasis>.</para>
+
+ <para>Now, if we compiled the above code for an Intel based
+ computer, our <emphasis>host byte order</emphasis> would
+ produce:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainlsb"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+--------+--------+
+ 0 | 0 | 2 | 13 | 0 |
+ +--------+--------+--------+--------+
+ 4 | 18 | 244 | 43 | 192 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Host byte order on an Intel system</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>But the <emphasis>network byte order</emphasis>
+ requires that we store the data <acronym>MSB</acronym>
+ first:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainmsb"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+--------+--------+
+ 0 | 0 | 2 | 0 | 13 |
+ +--------+--------+--------+--------+
+ 4 | 192 | 43 | 244 | 18 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Network byte order</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>Unfortunately, our <emphasis>host order</emphasis> is
+ the exact opposite of the <emphasis>network
+ order</emphasis>.</para>
+
+ <para>We have several ways of dealing with it. One would be
+ to <emphasis>reverse</emphasis> the values in our code:
+ </para>
+
+<programlisting>
+ sa.sin_family = AF_INET;
+ sa.sin_port = 13 &lt;&lt; 8;
+ sa.sin_addr.s_addr = (((((18 &lt;&lt; 8) | 244) &lt;&lt; 8) | 43) &lt;&lt; 8) | 192;
+</programlisting>
+
+ <para>This will <emphasis>trick</emphasis> our compiler
+ into storing the data in the <emphasis>network byte
+ order</emphasis>. In some cases, this is exactly the way
+ to do it (e.g., when programming in assembly
+ language). In most cases, however, it can cause a
+ problem.</para>
+
+ <para>Suppose, you wrote a sockets-based program in C. You
+ know it is going to run on a &pentium;, so you enter all
+ your constants in reverse and force them to the
+ <emphasis>network byte order</emphasis>. It works
+ well.</para>
+
+ <para>Then, some day, your trusted old &pentium; becomes a
+ rusty old &pentium;. You replace it with a system whose
+ <emphasis>host order</emphasis> is the same as the
+ <emphasis>network order</emphasis>. You need to recompile
+ all your software. All of your software continues to
+ perform well, except the one program you wrote.</para>
+
+ <para>You have since forgotten that you had forced all of
+ your constants to the opposite of the <emphasis>host
+ order</emphasis>. You spend some quality time tearing out
+ your hair, calling the names of all gods you ever heard
+ of (and some you made up), hitting your monitor with a
+ nerf bat, and performing all the other traditional
+ ceremonies of trying to figure out why something that has
+ worked so well is suddenly not working at all.</para>
+
+ <para>Eventually, you figure it out, say a couple of swear
+ words, and start rewriting your code.</para>
+
+ <para>Luckily, you are not the first one to face the
+ problem. Someone else has created the &man.htons.3; and
+ &man.htonl.3; C functions to convert a
+ <varname>short</varname> and <varname>long</varname>
+ respectively from the <emphasis>host byte
+ order</emphasis> to the <emphasis>network byte
+ order</emphasis>, and the &man.ntohs.3; and &man.ntohl.3;
+ C functions to go the other way.</para>
+
+ <para>On <emphasis><acronym>MSB</acronym>-first</emphasis>
+ systems these functions do nothing. On
+ <emphasis><acronym>LSB</acronym>-first</emphasis> systems
+ they convert values to the proper order.</para>
+
+ <para>So, regardless of what system your software is
+ compiled on, your data will end up in the correct order
+ if you use these functions.</para>
+
+ </sect4>
+
+ </sect3>
+
+ <sect3 xml:id="sockets-client-functions">
+ <title>Client Functions</title>
+
+ <para>Typically, the client initiates the connection to the
+ server. The client knows which server it is about to call:
+ It knows its <acronym>IP</acronym> address, and it knows the
+ <emphasis>port</emphasis> the server resides at. It is akin
+ to you picking up the phone and dialing the number (the
+ <emphasis>address</emphasis>), then, after someone answers,
+ asking for the person in charge of wingdings (the
+ <emphasis>port</emphasis>).</para>
+
+ <sect4 xml:id="sockets-connect">
+ <title><function>connect</function></title>
+
+ <para>Once a client has created a socket, it needs to
+ connect it to a specific port on a remote system. It uses
+ &man.connect.2;:</para>
+
+<programlisting>
+int connect(int s, const struct sockaddr *name, socklen_t namelen);
+</programlisting>
+
+ <para>The <varname>s</varname> argument is the socket, i.e.,
+ the value returned by the <function>socket</function>
+ function. The <varname>name</varname> is a pointer to
+ <varname>sockaddr</varname>, the structure we have talked
+ about extensively. Finally, <varname>namelen</varname>
+ informs the system how many bytes are in our
+ <varname>sockaddr</varname> structure.</para>
+
+ <para>If <function>connect</function> is successful, it
+ returns <constant>0</constant>. Otherwise it returns
+ <constant>-1</constant> and stores the error code in
+ <varname>errno</varname>.</para>
+
+ <para>There are many reasons why
+ <function>connect</function> may fail. For example, with
+ an attempt to an Internet connection, the
+ <acronym>IP</acronym> address may not exist, or it may be
+ down, or just too busy, or it may not have a server
+ listening at the specified port. Or it may outright
+ <emphasis>refuse</emphasis> any request for specific
+ code.</para>
+
+ </sect4>
+
+ <sect4 xml:id="sockets-first-client">
+ <title>Our First Client</title>
+
+ <para>We now know enough to write a very simple client, one
+ that will get current time from <systemitem class="ipaddress">192.43.244.18</systemitem> and print it to
+ <filename>stdout</filename>.</para>
+
+<programlisting>
+/*
+ * daytime.c
+ *
+ * Programmed by G. Adam Stanislav
+ */
+#include &lt;stdio.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/socket.h&gt;
+#include &lt;netinet/in.h&gt;
+
+int main() {
+ register int s;
+ register int bytes;
+ struct sockaddr_in sa;
+ char buffer[BUFSIZ+1];
+
+ if ((s = socket(PF_INET, SOCK_STREAM, 0)) &lt; 0) {
+ perror("socket");
+ return 1;
+ }
+
+ bzero(&amp;sa, sizeof sa);
+
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(13);
+ sa.sin_addr.s_addr = htonl((((((192 &lt;&lt; 8) | 43) &lt;&lt; 8) | 244) &lt;&lt; 8) | 18);
+ if (connect(s, (struct sockaddr *)&amp;sa, sizeof sa) &lt; 0) {
+ perror("connect");
+ close(s);
+ return 2;
+ }
+
+ while ((bytes = read(s, buffer, BUFSIZ)) &gt; 0)
+ write(1, buffer, bytes);
+
+ close(s);
+ return 0;
+}
+</programlisting>
+
+ <para>Go ahead, enter it in your editor, save it as
+ <filename>daytime.c</filename>, then compile and run
+ it:</para>
+
+<screen>&prompt.user; <userinput>cc -O3 -o daytime daytime.c</userinput>
+&prompt.user; <userinput>./daytime</userinput>
+
+52079 01-06-19 02:29:25 50 0 1 543.9 UTC(NIST) *
+&prompt.user;</screen>
+
+ <para>In this case, the date was June 19, 2001, the time was
+ 02:29:25 <acronym>UTC</acronym>. Naturally, your results
+ will vary.</para>
+
+ </sect4>
+
+ </sect3>
+
+ <sect3 xml:id="sockets-server-functions">
+ <title>Server Functions</title>
+
+ <para>The typical server does not initiate the
+ connection. Instead, it waits for a client to call it and
+ request services. It does not know when the client will
+ call, nor how many clients will call. It may be just sitting
+ there, waiting patiently, one moment, The next moment, it
+ can find itself swamped with requests from a number of
+ clients, all calling in at the same time.</para>
+
+ <para>The sockets interface offers three basic functions to
+ handle this.</para>
+
+ <sect4 xml:id="sockets-bind">
+ <title><function>bind</function></title>
+
+ <para>Ports are like extensions to a phone line: After you
+ dial a number, you dial the extension to get to a specific
+ person or department.</para>
+
+ <para>There are 65535 <acronym>IP</acronym> ports, but a
+ server usually processes requests that come in on only one
+ of them. It is like telling the phone room operator that
+ we are now at work and available to answer the phone at a
+ specific extension. We use &man.bind.2; to tell sockets
+ which port we want to serve.</para>
+
+<programlisting>
+int bind(int s, const struct sockaddr *addr, socklen_t addrlen);
+</programlisting>
+
+ <para>Beside specifying the port in <varname>addr</varname>,
+ the server may include its <acronym>IP</acronym>
+ address. However, it can just use the symbolic constant
+ <symbol>INADDR_ANY</symbol> to indicate it will serve all
+ requests to the specified port regardless of what its
+ <acronym>IP</acronym> address is. This symbol, along with
+ several similar ones, is declared in
+ <filename>netinet/in.h</filename></para>
+
+<programlisting>
+#define INADDR_ANY (u_int32_t)0x00000000
+</programlisting>
+
+ <para>Suppose we were writing a server for the
+ <emphasis>daytime</emphasis> protocol over
+ <acronym>TCP</acronym>/<acronym>IP</acronym>. Recall that
+ it uses port 13. Our <varname>sockaddr_in</varname>
+ structure would look like this:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/sainserv"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced"> 0 1 2 3
+ +--------+--------+--------+--------+
+ 0 | 0 | 2 | 0 | 13 |
+ +--------+--------+--------+--------+
+ 4 | 0 |
+ +-----------------------------------+
+ 8 | 0 |
+ +-----------------------------------+
+12 | 0 |
+ +-----------------------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Example Server sockaddr_in</phrase>
+ </textobject>
+ </mediaobject>
+ </sect4>
+
+ <sect4 xml:id="sockets-listen">
+ <title><function>listen</function></title>
+
+ <para>To continue our office phone analogy, after you have
+ told the phone central operator what extension you will be
+ at, you now walk into your office, and make sure your own
+ phone is plugged in and the ringer is turned on. Plus, you
+ make sure your call waiting is activated, so you can hear
+ the phone ring even while you are talking to someone.</para>
+
+ <para>The server ensures all of that with the &man.listen.2;
+ function.</para>
+
+<programlisting>
+int listen(int s, int backlog);
+</programlisting>
+
+ <para>In here, the <varname>backlog</varname> variable tells
+ sockets how many incoming requests to accept while you are
+ busy processing the last request. In other words, it
+ determines the maximum size of the queue of pending
+ connections.</para>
+
+ </sect4>
+
+ <sect4 xml:id="sockets-accept">
+ <title><function>accept</function></title>
+
+ <para>After you hear the phone ringing, you accept the call
+ by answering the call. You have now established a
+ connection with your client. This connection remains
+ active until either you or your client hang up.</para>
+
+ <para>The server accepts the connection by using the
+ &man.accept.2; function.</para>
+
+<programlisting>
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+</programlisting>
+
+ <para>Note that this time <varname>addrlen</varname> is a
+ pointer. This is necessary because in this case it is the
+ socket that fills out <varname>addr</varname>, the
+ <varname>sockaddr_in</varname> structure.</para>
+
+ <para>The return value is an integer. Indeed, the
+ <function>accept</function> returns a <emphasis>new
+ socket</emphasis>. You will use this new socket to
+ communicate with the client.</para>
+
+ <para>What happens to the old socket? It continues to listen
+ for more requests (remember the <varname>backlog</varname>
+ variable we passed to <function>listen</function>?) until
+ we <function>close</function> it.</para>
+
+ <para>Now, the new socket is meant only for
+ communications. It is fully connected. We cannot pass it
+ to <function>listen</function> again, trying to accept
+ additional connections.</para>
+
+ </sect4>
+
+ <sect4 xml:id="sockets-first-server">
+ <title>Our First Server</title>
+
+ <para>Our first server will be somewhat more complex than
+ our first client was: Not only do we have more sockets
+ functions to use, but we need to write it as a
+ daemon.</para>
+
+ <para>This is best achieved by creating a <emphasis>child
+ process</emphasis> after binding the port. The main
+ process then exits and returns control to the
+ <application>shell</application> (or whatever program
+ invoked it).</para>
+
+ <para>The child calls <function>listen</function>, then
+ starts an endless loop, which accepts a connection, serves
+ it, and eventually closes its socket.</para>
+
+<programlisting>
+/*
+ * daytimed - a port 13 server
+ *
+ * Programmed by G. Adam Stanislav
+ * June 19, 2001
+ */
+#include &lt;stdio.h&gt;
+#include &lt;time.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/socket.h&gt;
+#include &lt;netinet/in.h&gt;
+
+#define BACKLOG 4
+
+int main() {
+ register int s, c;
+ int b;
+ struct sockaddr_in sa;
+ time_t t;
+ struct tm *tm;
+ FILE *client;
+
+ if ((s = socket(PF_INET, SOCK_STREAM, 0)) &lt; 0) {
+ perror("socket");
+ return 1;
+ }
+
+ bzero(&amp;sa, sizeof sa);
+
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(13);
+
+ if (INADDR_ANY)
+ sa.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (bind(s, (struct sockaddr *)&amp;sa, sizeof sa) &lt; 0) {
+ perror("bind");
+ return 2;
+ }
+
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ return 3;
+ break;
+ default:
+ close(s);
+ return 0;
+ break;
+ case 0:
+ break;
+ }
+
+ listen(s, BACKLOG);
+
+ for (;;) {
+ b = sizeof sa;
+
+ if ((c = accept(s, (struct sockaddr *)&amp;sa, &amp;b)) &lt; 0) {
+ perror("daytimed accept");
+ return 4;
+ }
+
+ if ((client = fdopen(c, "w")) == NULL) {
+ perror("daytimed fdopen");
+ return 5;
+ }
+
+ if ((t = time(NULL)) &lt; 0) {
+ perror("daytimed time");
+
+ return 6;
+ }
+
+ tm = gmtime(&amp;t);
+ fprintf(client, "%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ\n",
+ tm-&gt;tm_year + 1900,
+ tm-&gt;tm_mon + 1,
+ tm-&gt;tm_mday,
+ tm-&gt;tm_hour,
+ tm-&gt;tm_min,
+ tm-&gt;tm_sec);
+
+ fclose(client);
+ }
+}
+</programlisting>
+
+ <para>We start by creating a socket. Then we fill out the
+ <varname>sockaddr_in</varname> structure in
+ <varname>sa</varname>. Note the conditional use of
+ <symbol>INADDR_ANY</symbol>:</para>
+
+<programlisting>
+ if (INADDR_ANY)
+ sa.sin_addr.s_addr = htonl(INADDR_ANY);
+</programlisting>
+
+ <para>Its value is <constant>0</constant>. Since we have
+ just used <function>bzero</function> on the entire
+ structure, it would be redundant to set it to
+ <constant>0</constant> again. But if we port our code to
+ some other system where <symbol>INADDR_ANY</symbol> is
+ perhaps not a zero, we need to assign it to
+ <varname>sa.sin_addr.s_addr</varname>. Most modern C
+ compilers are clever enough to notice that
+ <symbol>INADDR_ANY</symbol> is a constant. As long as it
+ is a zero, they will optimize the entire conditional
+ statement out of the code.</para>
+
+ <para>After we have called <function>bind</function>
+ successfully, we are ready to become a
+ <emphasis>daemon</emphasis>: We use
+ <function>fork</function> to create a child process. In
+ both, the parent and the child, the <varname>s</varname>
+ variable is our socket. The parent process will not need
+ it, so it calls <function>close</function>, then it
+ returns <constant>0</constant> to inform its own parent it
+ had terminated successfully.</para>
+
+ <para>Meanwhile, the child process continues working in the
+ background. It calls <function>listen</function> and sets
+ its backlog to <constant>4</constant>. It does not need a
+ large value here because <emphasis>daytime</emphasis> is
+ not a protocol many clients request all the time, and
+ because it can process each request instantly anyway.</para>
+
+ <para>Finally, the daemon starts an endless loop, which
+ performs the following steps:</para>
+
+ <procedure>
+ <step><para> Call <function>accept</function>. It waits
+ here until a client contacts it. At that point, it
+ receives a new socket, <varname>c</varname>, which it
+ can use to communicate with this particular client.
+ </para></step>
+
+ <step><para>It uses the C function
+ <function>fdopen</function> to turn the socket from a
+ low-level <emphasis>file descriptor</emphasis> to a
+ C-style <varname>FILE</varname> pointer. This will allow
+ the use of <function>fprintf</function> later on.
+ </para></step>
+
+ <step><para>It checks the time, and prints it in the
+ <emphasis><acronym>ISO</acronym> 8601</emphasis> format
+ to the <varname>client</varname> <quote>file</quote>. It
+ then uses <function>fclose</function> to close the
+ file. That will automatically close the socket as well.
+ </para></step>
+
+ </procedure>
+
+ <para>We can <emphasis>generalize</emphasis> this, and use
+ it as a model for many other servers:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/serv"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced">+-----------------+
+| Create Socket |
++-----------------+
+ |
++-----------------+
+| Bind Port | Daemon Process
++-----------------+
+ | +--------+
+ +-------------+--&gt;| Init |
+ | | +--------+
++-----------------+ | |
+| Exit | | +--------+
++-----------------+ | | Listen |
+ | +--------+
+ | |
+ | +--------+
+ | | Accept |
+ | +--------+
+ | |
+ | +--------+
+ | | Serve |
+ | +--------+
+ | |
+ | +--------+
+ | | Close |
+ |&lt;--------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Sequential Server</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>This flowchart is good for <emphasis>sequential
+ servers</emphasis>, i.e., servers that can serve one
+ client at a time, just as we were able to with our
+ <emphasis>daytime</emphasis> server. This is only possible
+ whenever there is no real <quote>conversation</quote>
+ going on between the client and the server: As soon as the
+ server detects a connection to the client, it sends out
+ some data and closes the connection. The entire operation
+ may take nanoseconds, and it is finished.</para>
+
+ <para>The advantage of this flowchart is that, except for
+ the brief moment after the parent
+ <function>fork</function>s and before it exits, there is
+ always only one <emphasis>process</emphasis> active: Our
+ server does not take up much memory and other system
+ resources.</para>
+
+ <para>Note that we have added <emphasis>initialize
+ daemon</emphasis> in our flowchart. We did not need to
+ initialize our own daemon, but this is a good place in the
+ flow of the program to set up any
+ <function>signal</function> handlers, open any files we
+ may need, etc.</para>
+
+ <para>Just about everything in the flow chart can be used
+ literally on many different servers. The
+ <emphasis>serve</emphasis> entry is the exception. We
+ think of it as a <emphasis><quote>black
+ box</quote></emphasis>, i.e., something you design
+ specifically for your own server, and just <quote>plug it
+ into the rest.</quote></para>
+
+ <para>Not all protocols are that simple. Many receive a
+ request from the client, reply to it, then receive another
+ request from the same client. Because of that, they do not
+ know in advance how long they will be serving the
+ client. Such servers usually start a new process for each
+ client. While the new process is serving its client, the
+ daemon can continue listening for more connections.</para>
+
+ <para>Now, go ahead, save the above source code as
+ <filename>daytimed.c</filename> (it is customary to end
+ the names of daemons with the letter
+ <constant>d</constant>). After you have compiled it, try
+ running it:</para>
+
+<screen>&prompt.user; <userinput>./daytimed</userinput>
+bind: Permission denied
+&prompt.user;</screen>
+
+ <para>What happened here? As you will recall, the
+ <emphasis>daytime</emphasis> protocol uses port 13. But
+ all ports below 1024 are reserved to the superuser
+ (otherwise, anyone could start a daemon pretending to
+ serve a commonly used port, while causing a security
+ breach).</para>
+
+ <para>Try again, this time as the superuser:</para>
+
+<screen>&prompt.root; <userinput>./daytimed</userinput>
+&prompt.root;</screen>
+
+ <para>What... Nothing? Let us try again:</para>
+
+<screen>&prompt.root; <userinput>./daytimed</userinput>
+
+bind: Address already in use
+&prompt.root;</screen>
+
+ <para>Every port can only be bound by one program at a
+ time. Our first attempt was indeed successful: It started
+ the child daemon and returned quietly. It is still running
+ and will continue to run until you either kill it, or any
+ of its system calls fail, or you reboot the system.</para>
+
+ <para>Fine, we know it is running in the background. But is
+ it working? How do we know it is a proper
+ <emphasis>daytime</emphasis> server? Simple:</para>
+
+<screen>&prompt.user; <userinput>telnet localhost 13</userinput>
+
+Trying ::1...
+telnet: connect to address ::1: Connection refused
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+2001-06-19T21:04:42Z
+Connection closed by foreign host.
+&prompt.user;</screen>
+
+ <para><application>telnet</application> tried the new
+ <acronym>IP</acronym>v6, and failed. It retried with
+ <acronym>IP</acronym>v4 and succeeded. The daemon
+ works.</para>
+
+ <para>If you have access to another &unix; system via
+ <application>telnet</application>, you can use it to test
+ accessing the server remotely. My computer does not have a
+ static <acronym>IP</acronym> address, so this is what I
+ did:</para>
+
+<screen>&prompt.user; <userinput>who</userinput>
+
+whizkid ttyp0 Jun 19 16:59 (216.127.220.143)
+xxx ttyp1 Jun 19 16:06 (xx.xx.xx.xx)
+&prompt.user; <userinput>telnet 216.127.220.143 13</userinput>
+
+Trying 216.127.220.143...
+Connected to r47.bfm.org.
+Escape character is '^]'.
+2001-06-19T21:31:11Z
+Connection closed by foreign host.
+&prompt.user;</screen>
+
+ <para>Again, it worked. Will it work using the domain name?
+ </para>
+
+<screen>&prompt.user; <userinput>telnet r47.bfm.org 13</userinput>
+
+Trying 216.127.220.143...
+Connected to r47.bfm.org.
+Escape character is '^]'.
+2001-06-19T21:31:40Z
+Connection closed by foreign host.
+&prompt.user;</screen>
+
+ <para>By the way, <application>telnet</application> prints
+ the <emphasis>Connection closed by foreign host</emphasis>
+ message after our daemon has closed the socket. This shows
+ us that, indeed, using
+ <function>fclose(client);</function> in our code works as
+ advertised.</para>
+
+ </sect4>
+
+ </sect3>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 xml:id="sockets-helper-functions">
+ <title>Helper Functions</title>
+
+ <para>FreeBSD C library contains many helper functions for sockets
+ programming. For example, in our sample client we hard coded
+ the <systemitem class="fqdomainname">time.nist.gov</systemitem>
+ <acronym>IP</acronym> address. But we do not always know the
+ <acronym>IP</acronym> address. Even if we do, our software is
+ more flexible if it allows the user to enter the
+ <acronym>IP</acronym> address, or even the domain name.
+ </para>
+
+ <sect2 xml:id="sockets-gethostbyname">
+ <title><function>gethostbyname</function></title>
+
+ <para>While there is no way to pass the domain name directly to
+ any of the sockets functions, the FreeBSD C library comes with
+ the &man.gethostbyname.3; and &man.gethostbyname2.3; functions,
+ declared in <filename>netdb.h</filename>.</para>
+
+<programlisting>
+struct hostent * gethostbyname(const char *name);
+struct hostent * gethostbyname2(const char *name, int af);
+</programlisting>
+
+ <para>Both return a pointer to the <varname>hostent</varname>
+ structure, with much information about the domain. For our
+ purposes, the <varname>h_addr_list[0]</varname> field of the
+ structure points at <varname>h_length</varname> bytes of the
+ correct address, already stored in the <emphasis>network byte
+ order</emphasis>.</para>
+
+ <para>This allows us to create a much more flexible&mdash;and
+ much more useful&mdash;version of our
+ <application>daytime</application> program:</para>
+
+<programlisting>
+/*
+ * daytime.c
+ *
+ * Programmed by G. Adam Stanislav
+ * 19 June 2001
+ */
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/socket.h&gt;
+#include &lt;netinet/in.h&gt;
+#include &lt;netdb.h&gt;
+
+int main(int argc, char *argv[]) {
+ register int s;
+ register int bytes;
+ struct sockaddr_in sa;
+ struct hostent *he;
+ char buf[BUFSIZ+1];
+ char *host;
+
+ if ((s = socket(PF_INET, SOCK_STREAM, 0)) &lt; 0) {
+ perror("socket");
+ return 1;
+ }
+
+ bzero(&amp;sa, sizeof sa);
+
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(13);
+
+ host = (argc &gt; 1) ? (char *)argv[1] : "time.nist.gov";
+
+ if ((he = gethostbyname(host)) == NULL) {
+ perror(host);
+ return 2;
+ }
+
+ bcopy(he-&gt;h_addr_list[0],&amp;sa.sin_addr, he-&gt;h_length);
+
+ if (connect(s, (struct sockaddr *)&amp;sa, sizeof sa) &lt; 0) {
+ perror("connect");
+ return 3;
+ }
+
+ while ((bytes = read(s, buf, BUFSIZ)) &gt; 0)
+ write(1, buf, bytes);
+
+ close(s);
+ return 0;
+}
+</programlisting>
+
+ <para>We now can type a domain name (or an <acronym>IP</acronym>
+ address, it works both ways) on the command line, and the
+ program will try to connect to its
+ <emphasis>daytime</emphasis> server. Otherwise, it will still
+ default to <systemitem class="fqdomainname">time.nist.gov</systemitem>. However, even in
+ this case we will use <function>gethostbyname</function>
+ rather than hard coding <systemitem class="ipaddress">192.43.244.18</systemitem>. That way, even if its
+ <acronym>IP</acronym> address changes in the future, we will
+ still find it.</para>
+
+ <para>Since it takes virtually no time to get the time from your
+ local server, you could run <application>daytime</application>
+ twice in a row: First to get the time from <systemitem class="fqdomainname">time.nist.gov</systemitem>, the second time from
+ your own system. You can then compare the results and see how
+ exact your system clock is:</para>
+
+<screen>&prompt.user; <userinput>daytime ; daytime localhost</userinput>
+
+
+52080 01-06-20 04:02:33 50 0 0 390.2 UTC(NIST) *
+2001-06-20T04:02:35Z
+&prompt.user;</screen>
+
+ <para>As you can see, my system was two seconds ahead of the
+ <acronym>NIST</acronym> time.</para>
+
+ </sect2>
+
+ <sect2 xml:id="sockets-getservbyname">
+ <title><function>getservbyname</function></title>
+
+ <para>Sometimes you may not be sure what port a certain service
+ uses. The &man.getservbyname.3; function, also declared in
+ <filename>netdb.h</filename> comes in very handy in those
+ cases:</para>
+
+<programlisting>
+struct servent * getservbyname(const char *name, const char *proto);
+</programlisting>
+
+ <para>The <varname>servent</varname> structure contains the
+ <varname>s_port</varname>, which contains the proper port,
+ already in <emphasis>network byte order</emphasis>.</para>
+
+ <para>Had we not known the correct port for the
+ <emphasis>daytime</emphasis> service, we could have found it
+ this way:</para>
+
+<programlisting>
+ struct servent *se;
+ ...
+ if ((se = getservbyname("daytime", "tcp")) == NULL {
+ fprintf(stderr, "Cannot determine which port to use.\n");
+ return 7;
+ }
+ sa.sin_port = se-&gt;s_port;
+</programlisting>
+
+ <para>You usually do know the port. But if you are developing a
+ new protocol, you may be testing it on an unofficial
+ port. Some day, you will register the protocol and its port
+ (if nowhere else, at least in your
+ <filename>/etc/services</filename>, which is where
+ <function>getservbyname</function> looks). Instead of
+ returning an error in the above code, you just use the
+ temporary port number. Once you have listed the protocol in
+ <filename>/etc/services</filename>, your software will find
+ its port without you having to rewrite the code.</para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 xml:id="sockets-concurrent-servers">
+ <title>Concurrent Servers</title>
+
+ <para>Unlike a sequential server, a <emphasis>concurrent
+ server</emphasis> has to be able to serve more than one client
+ at a time. For example, a <emphasis>chat server</emphasis> may
+ be serving a specific client for hours&mdash;it cannot wait till
+ it stops serving a client before it serves the next one.</para>
+
+ <para>This requires a significant change in our flowchart:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sockets/serv2"/>
+ </imageobject>
+
+ <textobject>
+ <literallayout class="monospaced">+-----------------+
+| Create Socket |
++-----------------+
+ |
++-----------------+
+| Bind Port | Daemon Process
++-----------------+
+ | +--------+
+ +-------------+--&gt;| Init |
+ | | +--------+
++-----------------+ | |
+| Exit | | +--------+
++-----------------+ | | Listen |
+ | +--------+
+ | |
+ | +--------+
+ | | Accept |
+ | +--------+
+ | | +------------------+
+ | +------&gt;| Close Top Socket |
+ | | +------------------+
+ | +--------+ |
+ | | Close | +------------------+
+ | +--------+ | Serve |
+ | | +------------------+
+ |&lt;--------+ |
+ +------------------+
+ | Close Acc Socket |
+ +--------+ +------------------+
+ | Signal | |
+ +--------+ +------------------+
+ | Exit |
+ +------------------+</literallayout>
+ </textobject>
+
+ <textobject>
+ <phrase>Concurrent Server</phrase>
+ </textobject>
+ </mediaobject>
+
+ <para>We moved the <emphasis>serve</emphasis> from the
+ <emphasis>daemon process</emphasis> to its own <emphasis>server
+ process</emphasis>. However, because each child process inherits
+ all open files (and a socket is treated just like a file), the
+ new process inherits not only the <emphasis><quote>accepted
+ handle,</quote></emphasis> i.e., the socket returned by the
+ <function>accept</function> call, but also the <emphasis>top
+ socket</emphasis>, i.e., the one opened by the top process right
+ at the beginning.</para>
+
+ <para>However, the <emphasis>server process</emphasis> does not
+ need this socket and should <function>close</function> it
+ immediately. Similarly, the <emphasis>daemon process</emphasis>
+ no longer needs the <emphasis>accepted socket</emphasis>, and
+ not only should, but <emphasis>must</emphasis>
+ <function>close</function> it&mdash;otherwise, it will run out
+ of available <emphasis>file descriptors</emphasis> sooner or
+ later.</para>
+
+ <para>After the <emphasis>server process</emphasis> is done
+ serving, it should close the <emphasis>accepted
+ socket</emphasis>. Instead of returning to
+ <function>accept</function>, it now exits.
+ </para>
+
+ <para>Under &unix;, a process does not really
+ <emphasis>exit</emphasis>. Instead, it
+ <emphasis>returns</emphasis> to its parent. Typically, a parent
+ process <function>wait</function>s for its child process, and
+ obtains a return value. However, our <emphasis>daemon
+ process</emphasis> cannot simply stop and wait. That would
+ defeat the whole purpose of creating additional processes. But
+ if it never does <function>wait</function>, its children will
+ become <emphasis>zombies</emphasis>&mdash;no longer functional
+ but still roaming around.</para>
+
+ <para>For that reason, the <emphasis>daemon process</emphasis>
+ needs to set <emphasis>signal handlers</emphasis> in its
+ <emphasis>initialize daemon</emphasis> phase. At least a
+ <symbol>SIGCHLD</symbol> signal has to be processed, so the
+ daemon can remove the zombie return values from the system and
+ release the system resources they are taking up.</para>
+
+ <para>That is why our flowchart now contains a <emphasis>process
+ signals</emphasis> box, which is not connected to any other box.
+ By the way, many servers also process <symbol>SIGHUP</symbol>,
+ and typically interpret as the signal from the superuser that
+ they should reread their configuration files. This allows us to
+ change settings without having to kill and restart these
+ servers.</para>
+
+ </sect1>
+
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/testing/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/testing/chapter.xml
new file mode 100644
index 0000000000..fde68a1b61
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/testing/chapter.xml
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="testing">
+ <title>Regression and Performance Testing</title>
+
+ <para>Regression tests are used to exercise a particular bit of the
+ system to check that it works as expected, and to make sure that
+ old bugs are not reintroduced.</para>
+
+ <para>The &os; regression testing tools can be found in the &os;
+ source tree in the directory <filename>src/tools/regression</filename>.</para>
+
+ <section xml:id="testing-micro-benchmark">
+ <title>Micro Benchmark Checklist</title>
+
+ <para>This section contains hints for doing proper
+ micro-benchmarking on &os; or of &os; itself.</para>
+
+ <para>It is not possible to use all of the suggestions below every
+ single time, but the more used, the better the benchmark's
+ ability to test small differences will be.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Disable <acronym>APM</acronym> and any other kind of
+ clock fiddling (<acronym>ACPI</acronym> ?).</para>
+ </listitem>
+
+ <listitem>
+ <para>Run in single user mode. E.g. &man.cron.8;, and and
+ other daemons only add noise. The &man.sshd.8; daemon can
+ also cause problems. If ssh access is required during test
+ either disable the SSHv1 key regeneration, or kill the
+ parent <command>sshd</command> daemon during the tests.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not run &man.ntpd.8;.</para>
+ </listitem>
+
+ <listitem>
+ <para>If &man.syslog.3; events are generated, run
+ &man.syslogd.8; with an empty
+ <filename>/etc/syslogd.conf</filename>, otherwise, do not
+ run it.</para>
+ </listitem>
+
+ <listitem>
+ <para>Minimize disk-I/O, avoid it entirely if possible.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not mount file systems that are not needed.</para>
+ </listitem>
+
+ <listitem>
+ <para>Mount <filename>/</filename>,
+ <filename>/usr</filename>, and any other
+ file system as read-only if possible. This removes atime
+ updates to disk (etc.) from the I/O picture.</para>
+ </listitem>
+
+ <listitem>
+ <para>Reinitialize the read/write test file system with
+ &man.newfs.8; and populate it from a &man.tar.1; or
+ &man.dump.8; file before every run. Unmount and mount it
+ before starting the test. This results in a consistent file
+ system layout. For a worldstone test this would apply to
+ <filename>/usr/obj</filename> (just
+ reinitialize with <command>newfs</command> and mount). To
+ get 100% reproducibility, populate the file system from a
+ &man.dd.1; file (i.e.: <command>dd
+ if=myimage of=/dev/ad0s1h
+ bs=1m</command>)</para>
+ </listitem>
+
+ <listitem>
+ <para>Use malloc backed or preloaded &man.md.4;
+ partitions.</para>
+ </listitem>
+
+ <listitem>
+ <para>Reboot between individual iterations of the test, this
+ gives a more consistent state.</para>
+ </listitem>
+
+ <listitem>
+ <para>Remove all non-essential device drivers from the kernel.
+ For instance if USB is not needed for the test, do not put
+ USB in the kernel. Drivers which attach often have timeouts
+ ticking away.</para>
+ </listitem>
+
+ <listitem>
+ <para>Unconfigure hardware that are not in use. Detach disks
+ with &man.atacontrol.8; and &man.camcontrol.8; if the disks
+ are not used for the test.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not configure the network unless it is being tested,
+ or wait until after the test has been performed to ship the
+ results off to another computer.</para>
+
+ <para>If the system must be connected to a public network,
+ watch out for spikes of broadcast traffic. Even though it
+ is hardly noticeable, it will take up CPU cycles. Multicast
+ has similar caveats.</para>
+ </listitem>
+
+ <listitem>
+ <para>Put each file system on its own disk. This minimizes
+ jitter from head-seek optimizations.</para>
+ </listitem>
+
+ <listitem>
+ <para>Minimize output to serial or VGA consoles. Running
+ output into files gives less jitter. (Serial consoles
+ easily become a bottleneck.) Do not touch keyboard while
+ the test is running, even <keycap>space</keycap> or
+ <keycap>back-space</keycap> shows up in the numbers.</para>
+ </listitem>
+
+ <listitem>
+ <para>Make sure the test is long enough, but not too long. If
+ the test is too short, timestamping is a problem. If it is
+ too long temperature changes and drift will affect the
+ frequency of the quartz crystals in the computer. Rule of
+ thumb: more than a minute, less than an hour.</para>
+ </listitem>
+
+ <listitem>
+ <para>Try to keep the temperature as stable as possible around
+ the machine. This affects both quartz crystals and disk
+ drive algorithms. To get real stable clock, consider
+ stabilized clock injection. E.g. get a OCXO + PLL, inject
+ output into clock circuits instead of motherboard xtal.
+ Contact &a.phk; for more information about this.</para>
+ </listitem>
+
+ <listitem>
+ <para>Run the test at least 3 times but it is better to run
+ more than 20 times both for <quote>before</quote> and
+ <quote>after</quote> code. Try to interleave if possible
+ (i.e.: do not run 20 times before then 20 times after), this
+ makes it possible to spot environmental effects. Do not
+ interleave 1:1, but 3:3, this makes it possible to spot
+ interaction effects.</para>
+
+ <para>A good pattern is: <literal>bababa{bbbaaa}*</literal>.
+ This gives hint after the first 1+1 runs (so it is possible
+ to stop the test if it goes entirely the wrong way), a
+ standard deviation after the first 3+3 (gives a good
+ indication if it is going to be worth a long run) and
+ trending and interaction numbers later on.</para>
+ </listitem>
+
+ <listitem>
+ <para>Use <filename>usr/src/tools/tools/ministat</filename>
+ to see if the numbers are significant. Consider buying
+ <quote>Cartoon guide to statistics</quote> ISBN:
+ 0062731025, highly recommended, if you have forgotten or
+ never learned about standard deviation and Student's
+ T.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not use background &man.fsck.8; unless the test is a
+ benchmark of background <command>fsck</command>. Also,
+ disable <varname>background_fsck</varname> in
+ <filename>/etc/rc.conf</filename> unless the benchmark is
+ not started at least 60+<quote><command>fsck</command>
+ runtime</quote> seconds after the boot, as &man.rc.8; wakes
+ up and checks if <command>fsck</command> needs to run on any
+ file systems when background <command>fsck</command> is
+ enabled. Likewise, make sure there are no snapshots lying
+ around unless the benchmark is a test with snapshots.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the benchmark show unexpected bad performance, check
+ for things like high interrupt volume from an unexpected
+ source. Some versions of <acronym>ACPI</acronym> have been
+ reported to <quote>misbehave</quote> and generate excess
+ interrupts. To help diagnose odd test results, take a few
+ snapshots of <command>vmstat -i</command> and look for
+ anything unusual.</para>
+ </listitem>
+
+ <listitem>
+ <para>Make sure to be careful about optimization parameters
+ for kernel and userspace, likewise debugging. It is easy to
+ let something slip through and realize later the test was
+ not comparing the same thing.</para>
+ </listitem>
+
+ <listitem>
+ <para>Do not ever benchmark with the
+ <literal>WITNESS</literal> and <literal>INVARIANTS</literal>
+ kernel options enabled unless the test is interested to
+ benchmarking those features. <literal>WITNESS</literal> can
+ cause 400%+ drops in performance. Likewise, userspace
+ &man.malloc.3; parameters default differently in -CURRENT
+ from the way they ship in production releases.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
diff --git a/zh_TW.UTF-8/books/developers-handbook/tools/chapter.xml b/zh_TW.UTF-8/books/developers-handbook/tools/chapter.xml
new file mode 100644
index 0000000000..c9ca702ca2
--- /dev/null
+++ b/zh_TW.UTF-8/books/developers-handbook/tools/chapter.xml
@@ -0,0 +1,2139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The FreeBSD Documentation Project
+
+ $FreeBSD$
+ Original revision: 1.46
+-->
+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="tools">
+ <info><title>程式開發工具</title>
+ <authorgroup>
+ <author><personname><firstname>James</firstname><surname>Raynard</surname></personname><contrib>Contributed by </contrib></author>
+ <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname></author>
+ </authorgroup>
+ </info>
+
+
+ <sect1 xml:id="tools-synopsis"><title>概敘</title>
+
+ <para>本章將介紹如何使用一些 FreeBSD 所提供的程式開發工具(programing tools),
+ 本章所介紹的工具程式在其他版本的 &unix; 上也可使用,
+ 在此 <emphasis>並不會</emphasis> 嘗試描述寫程式時的每個細節,
+ 本章大部分篇幅都是假設你以前沒有或只有少數的寫程式經驗,
+ 不過,還是希望大多數的程式開發人員都能從中重新得到一些啟發。</para>
+
+ </sect1>
+
+ <sect1 xml:id="tools-intro"><title>簡介</title>
+
+ <para>FreeBSD 提供一個非常棒的開發環境,
+ 比如說像是 C、C++、Fortran 和 assembler(組合語言)的編譯器(compiler),
+ 在 FreeBSD 中都已經包含在基本的系統中了
+ 更別提 Perl 和其他標準 &unix; 工具,像是<command>sed</command> 以及 <command>awk</command>,
+ 如果你還是覺得不夠,FreeBSD在 Ports collection 中還提供其他的編譯器和直譯器(interpreter),
+ FreeBSD 相容許多標準,像是 <acronym>&posix;</acronym> 和 <acronym>ANSI</acronym> C,
+ 當然還有它所繼承的 BSD 傳統。
+ 所以在 FreeBSD 上寫的程式不需修改或頂多稍微修改,就可以在許多平台上編譯、執行。</para>
+
+ <para>無論如何,就算你從來沒在 &unix; 平台上寫過程式,也可以徹底感受到FreeBSD 令人無法抗拒的迷人魔力。
+ 本章的目標就是協助你快速上手,而暫時不需深入太多進階主題,
+ 並且講解一些基礎概念,以讓你可以瞭解我們在講些什麼。</para>
+
+ <para>本章內容並不要求你得有程式開發經驗,或者你只有一點點的經驗而已。
+ 不過,我們假設你已經會 &unix; 系統的基本操作,
+ 而且更重要的是,請保持樂於學習的心態!</para>
+
+ </sect1>
+
+ <sect1 xml:id="tools-programming">
+ <title>Programming 概念</title>
+
+ <para>簡單的說,程式只是一堆指令的集合體;而這些指令是用來告訴電腦應該要作那些事情。
+ 有時候,指令的執行取決於前一個指令的結果而定。
+ 本章將會告訴你有 2 個主要的方法,讓你可以對電腦下達這些指示(instruction) 或 <quote>命令(commands)</quote>。
+ 第一個方法就是 <firstterm>直譯器(interpreter)</firstterm>,
+ 而第二個方法是 <firstterm>編譯器(compiler)</firstterm>。
+ 由於對於電腦而言,人類語言的語意過於模糊而太難理解,
+ 因此命令(commands)就常會以一種(或多種)程式語言寫成,用來指示電腦所要執行的特定動作為何。</para>
+
+ <sect2>
+ <title>直譯器</title>
+
+ <para>使用直譯器時,所使用的程式語言就像變成一個會和你互動的環境。
+ 當在命令提示列上打上命令時,直譯器會即時執行該命令。
+ 在比較複雜的程式中,可以把所有想下達的命令統統輸入到某檔案裡面去,
+ 然後呼叫直譯器去讀取該檔案,並且執行你寫在這個檔案中的指令。
+ 如果所下的指令有錯誤產生,大多數的直譯器會進入偵錯模式(debugger),
+ 並且顯示相關錯誤訊息,以便對程式除錯。</para>
+
+ <para>這種方式好處在於:可以立刻看到指令的執行結果,以及錯誤也可迅速修正。
+ 相對的,最大的壞處便是當你想把你寫的程式分享給其他人時,這些人必須要有跟你一樣的直譯器。
+ 而且別忘了,他們也要會使用直譯器直譯程式才行。
+ 當然使用者也不希望不小心按錯鍵,就進入偵錯模式而不知所措。
+ 就執行效率而言,直譯器會使用到很多的記憶體,
+ 而且這類直譯式程式,通常並不會比編譯器所編譯的程式的更有效率。</para>
+
+ <para>筆者個人認為,如果你之前沒有學過任何程式語言,最好先學學習直譯式語言(interpreted languages),
+ 像是 Lisp,Smalltalk,Perl 和 Basic 都是,&unix; 的 shell 像是 <command>sh</command> 和 <command>csh</command>
+ 它們本身就是直譯器,事實上,很多人都在它們自己機器上撰寫各式的 shell <quote>script</quote>,
+ 來順利完成各項 <quote>housekeeping(維護)</quote> 任務。
+ &unix; 的使用哲學之一就是提供大量的小工具,
+ 並使用 shell script 來組合運用這些小工具,以便工作更有效率。</para>
+ </sect2>
+
+ <sect2>
+ <title>FreeBSD 提供的直譯器</title>
+
+ <para>下面這邊有份 &os; Ports Collection 所提供的直譯器清單,還有討論一些比較受歡迎的直譯式語言</para>
+
+ <para>至於如何使用 Ports Collection 安裝的說明,可參閱 FreeBSD Handbook 中的
+ <link xlink:href="&url.books.handbook;/ports-using.html">Ports章節</link>。</para>
+ <variablelist>
+ <varlistentry>
+ <term><acronym>BASIC</acronym></term>
+
+ <listitem>
+ <para>BASIC 是 Beginner's ALL-purpose Symbolic Instruction Code 的縮寫。
+ BASIC 於 1950 年代開始發展,最初開發這套語言的目的是為了教導當時的大學學生如何寫程式。
+ 到了 1980,<acronym>BASIC</acronym>已經是很多 programmer 第一個學習的程式語言了。
+ 此外,BASIC 也是 Visual Basic 的基礎。</para>
+
+ <para>FreeBSD Ports Collection 也有收錄相關的 BASIC 直譯器。
+ Bywater Basic 直譯器放在 <package>lang/bwbasic</package>。
+ 而 Phil Cockroft's Basic 直譯器(早期也叫 Rabbit Basic)放在 <package>lang/pbasic</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Lisp</term>
+
+ <listitem>
+ <para>LISP 是在 1950 年代開始發展的一個直譯式語言,而且 LISP 就是一種
+ <quote>number-crunching</quote> languages(迅速進行大量運算的程式語言),在當時算是一個普遍的程式語言。
+ LISP 的表達不是基於數字(numbers),而是基於表(lists)。
+ 而最能表示出 LISP 特色的地方就在於: LISP 是 <quote>List Processing</quote> 的縮寫。
+ 在<acronym>人工智慧(Artificial Intelligence, AI)</acronym>領域上 LISP 的各式應用非常普遍。</para>
+
+ <para>LISP 是非常強悍且複雜的程式語言,但是缺點是程式碼會非常大而且難以操作。</para>
+
+ <para>絕大部分的 LISP 直譯器都可以在 &unix; 系統上運作,當然 &os; 的 Ports Collection 也有收錄。
+ GNU Common Lisp 收錄在 <package>lang/gcl</package>,
+ Bruno Haible 和 Michael Stoll 的 CLISP 收錄在 <package>lang/clisp</package>
+ ,此外 CMUCL(包含一個已經最佳化的編譯器),
+ 以及其他簡化版的 LISP 直譯器(比如以 C 語言寫的 SLisp,只用幾百行程式碼就實作大多數 Common Lisp 的功能)
+ 則是分別收錄在 <package>lang/cmucl</package> 以及
+ <package>lang/slisp</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Perl</term>
+
+ <listitem>
+ <para>對系統管理者而言,最愛用 perl 來撰寫 scripts 以管理主機,
+ 同時也經常用來寫 WWW 主機上的 <acronym>CGI</acronym> Script 程式。</para>
+
+ <para>Perl 在 Ports Collection 內的 <package>lang/perl5</package>。
+ 而 &os; 4.X 則是把 Perl 裝在 <command>/usr/bin/perl</command>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Scheme</term>
+
+ <listitem>
+ <para>Scheme 是 LISP 的另一分支,Scheme 的特點就是比 Common LISP 還要簡潔有力。
+ 由於 Scheme 簡單,所以很多大學拿來當作第一堂程式語言教學教材。
+ 而且對於研究人員來說也可以快速的開發他們所需要的程式。</para>
+
+ <para>Scheme 收錄在 <package>lang/elk</package>,
+ Elk Scheme 直譯器(由麻省理工學院所發展的 Scheme 直譯器)收錄在
+ <package>lang/mit-scheme</package>,
+ SCM Scheme Interpreter 收錄在 <package>lang/scm</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Icon</term>
+
+ <listitem>
+ <para>Icon 屬高階程式語言,Icon 具有強大的字串(String)和結構(Structure)處理能力。
+ &os; Ports Collection 所收錄的 Icon 直譯器版本則是放在
+ <package>lang/icon</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Logo</term>
+
+ <listitem>
+ <para>Logo 是種容易學習的程式語言,最常在一些教學課程中被拿來當作開頭範例。
+ 如果要給小朋友開始上程式語言課的話,Logo 是相當不錯的選擇。
+ 因為,即使對小朋友來說,要用 Logo 來秀出複雜多邊形圖形是相當輕鬆容易的。</para>
+
+ <para>Logo 在 &os; Ports Collection 的最新版則是放在 <package>lang/logo</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Python</term>
+
+ <listitem>
+ <para>Python 是物件導向的直譯式語言,
+ Python 的擁護者總是宣稱 Python 是最好入門的程式語言。
+ 雖然 Python 可以很簡單的開始,但是不代表它就會輸給其他直譯式語言(像是 Perl 和 Tcl),
+ 事實證明 Python 也可以拿來開發大型、複雜的應用程式。</para>
+
+ <para>&os; Ports Collection 收錄在 <package>lang/python</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Ruby</term>
+
+ <listitem>
+ <para>Ruby 是純物件導向的直譯式語言。
+ Ruby 目前非常流行,原因在於他易懂的程式語法結構,在撰寫程式時的彈性,
+ 以及天生具有輕易的發展維護大型專案的能力。</para>
+
+ <para>&os; Ports Collection 收錄在 <package>lang/ruby8</package>。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Tcl and Tk</term>
+
+ <listitem>
+ <para>Tcl 是內嵌式的直譯式語言,讓 Tcl 可以如此廣泛運用的原因是 Tcl 的移植性。
+ Tcl 也可以快速發展一個簡單但是具有雛型的程式或者具有完整功能的程式。</para>
+
+ <para>Tcl 許多的版本都可在 &os; 上運作,而最新的 Tcl 版本為 Tcl 8.4,
+ &os; Ports Collection 收錄在 <package>lang/tcl84</package>。</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2>
+ <title>編譯器</title>
+
+ <para>編譯器和直譯器兩者相比的話,有些不同,首先就是必須先把程式碼統統寫入到檔案裡面,
+ 然後必須執行編譯器來試著編譯程式,如果編譯器不接受所寫的程式,那就必須一直修改程式,
+ 直到編譯器接受且把你的程式編譯成執行檔。
+ 此外,也可以在提示命令列,或在除錯器中執行你編譯好的程式看看它是否可以運作。
+ <footnote>
+ <para>如果在提示命令列下執行,那麼有可能會產生 core dump。</para>
+ </footnote></para>
+
+ <para>很明顯的,使用編譯器並不像直譯器般可以馬上得到結果。
+ 不管如何,編譯器允許你作很多直譯器不可能或者是很難達到的事情。
+ 例如:撰寫和作業系統密切互動的程式,甚至是你自己寫的作業系統!
+ 當你想要寫出高效率的程式時,編譯器便派上用場了。
+ 編譯器可以在編譯時順便最佳化你的程式,但是直譯器卻不行。
+ 而編譯器與直譯器最大的差別在於:當你想把你寫好的程式拿到另外一台機器上跑時,
+ 你只要將編譯器編譯出來的可執行檔,拿到新機器上便可以執行,
+ 而直譯器則必須要求新機器上,必須要有跟另一台機器上相同的直譯器,
+ 才能組譯執行你的程式!</para>
+
+ <para>編譯式的程式語言包含 Pascal、C 和 C++,
+ C 和 C++ 不是一個親和力十足的語言,但是很適合具有經驗的 Programmer。
+ Pascal 其實是一個設計用來教學用的程式語言,而且也很適合用來入門,
+ &os; 預設並沒有把 Pascal 整合進 base system 中,
+ 但是 GNU Pascal Compiler 和 Free Pascal Compiler 都可分別在
+ <package>lang/gpc</package> 和 <package>lang/fpc</package> 中找到。</para>
+
+ <para>如果你用不同的程式來寫編譯式程式,那麼不斷地編輯-編譯-執行-除錯的這個循環肯定會很煩人,
+ 為了更簡化、方便程式開發流程,很多商業編譯器廠商開始發展所謂的 <acronym>IDE</acronym>
+ (Integrated Development Environments) 開發環境,
+ FreeBSD 預設並沒有把 IDE 整合進 base system 中,
+ 但是你可透過 <package>devel/kdevelop</package> 安裝 kdevelop
+ 或使用 <application>Emacs</application> 來體驗 IDE 開發環境。
+ 在後面的 <xref linkend="emacs"/> 專題將介紹,如何以 <application>Emacs</application> 來作為 IDE 開發環境。</para>
+ </sect2>
+
+
+ </sect1>
+
+
+ <sect1 xml:id="tools-compiling">
+ <title>用 <command>cc</command> 來編譯程式</title>
+
+ <para>本章範例只有針對 GNU C compiler 和 GNU C++ compiler 作說明,
+ 這兩個在 FreeBSD base system 中就有了,
+ 直接打 <command>cc</command> 或 <command>gcc</command> 就可以執行。
+ 至於,如何用直譯器產生程式的說明,通常可在直譯器的文件或線上文件找到說明,因此不再贅述。</para>
+
+ <para>當你寫完你的傑作後,接下來便是讓這個程式可以在 FreeBSD 上執行,
+ 通常這些要一些步驟才能完成,有些步驟則需要不同程式來完成。</para>
+
+ <procedure>
+ <step>
+ <para>預先處理(Pre-process)你的程式碼,移除程式內的註解,和其他技巧,
+ 像是 expanding(擴大) C 的 marco。</para>
+ </step>
+
+ <step>
+ <para>確認你的程式語法是否確實遵照 C/C++ 的規定,如果沒有符合的話,編譯器會出現警告。</para>
+ </step>
+
+ <step>
+ <para>將原始碼轉成組合語言 &mdash; 它跟機器語言(machine code)非常相近,但仍在人類可理解的範圍內(據說應該是這樣)。
+ <footnote>
+ <para>嚴格說起來,在這個階段 <command>cc</command> 並不是真的把原始程式轉成組合語言,
+ 而是轉為 machine-independent 的 <firstterm>p-code</firstterm>。</para>
+ </footnote></para>
+ </step>
+
+ <step>
+ <para>把組合語言轉成機器語言 &mdash; 是的,這裡說的機器語言就是常提到的 bit 和 byte,也就是 1 和 0。</para>
+ </step>
+
+ <step>
+ <para>確認程式中用到的函式呼叫、全域變數是否正確,舉例來說:如若呼叫了不存在的函式,編譯器會顯示警告。</para>
+ </step>
+
+ <step>
+ <para>如果程式是由程式碼檔案來編譯,編譯器會整合起來。</para>
+ </step>
+
+ <step>
+ <para>編譯器會負責產生東西,讓系統上的 run-time loader 可以把程式載入記憶體內執行。</para>
+ </step>
+
+ <step>
+ <para>最後會把編譯完的執行檔存在硬碟上。</para>
+ </step>
+ </procedure>
+
+ <para>通常 <firstterm>編譯(compiling)</firstterm> 是指第 1 到第 4 個步驟。
+ &mdash; 其他步驟則稱為 <firstterm>連結(linking)</firstterm>,
+ 有時候步驟 1 也可以是指 <firstterm>預先處理(pre-processing)</firstterm>,
+ 而步驟 3 到步驟 4 則是 <firstterm>組譯(assembling)</firstterm>。</para>
+
+ <para>幸運的是,你可以不用理會以上細節,編譯器都會自動完成。
+ 因為 <command>cc</command> 只是是個前端程式(front end),它會依照正確的參數來呼叫相關程式幫你處理。
+ 只需打:</para>
+ <screen>&prompt.user; <userinput>cc foobar.c</userinput></screen>
+
+ <para>上述指令會把 <filename>foobar.c</filename> 開始編譯,並完成上述動作。
+ 如果你有許多檔案需要編譯,那請打類似下列指令即可:</para>
+
+ <screen>&prompt.user; <userinput>cc foo.c bar.c</userinput></screen>
+
+ <para>記住語法錯誤檢查就是 &mdash; 純粹檢查語法錯誤與否,
+ 而不會幫你檢測任何邏輯錯誤,比如:無限迴圈,或是排序方式想用 binary sort 卻弄成 bubble sort。
+ <footnote>
+ <para>剛所說的 binary sort 和 bubble sort 問題,
+ 在已排序好的序列中,binary sort 搜索效率會比 bubble sort 好。</para>
+ </footnote></para>
+
+ <para><command>cc</command> 有非常多的選項,都可透過線上手冊來查。
+ 下面只提一些必要且重要的選項,以作為例子。</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-o <replaceable>檔名</replaceable></option></term>
+
+ <listitem>
+ <para><option>-o</option> 編譯後的執行檔檔名,如果沒有使用這選項的話,
+ 編譯好的程式預設檔名將會是 <filename>a.out</filename>
+
+ <footnote>
+ <para>至於 <option>-o</option> 的原因,則是一團歷史迷霧了。</para>
+ </footnote></para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc foobar.c</userinput> <lineannotation>執行檔就是 a.out</lineannotation>
+&prompt.user; <userinput>cc -o foobar foobar.c</userinput> <lineannotation>執行檔就是 foobar</lineannotation>
+ </screen>
+ </informalexample>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-c</option></term>
+
+ <listitem>
+ <para>使用 <option>-c</option> 時,只會編譯原始碼,而不作連結(linking)。
+ 當只想確認語法是否正確或使用 Makefile 來編譯程式時,這個選項非常有用。</para>
+
+ <informalexample>
+ <screen>
+ &prompt.user; <userinput>cc -c foobar.c</userinput>
+ </screen>
+ </informalexample>
+
+ <para>這會產生叫做 <filename>foobar</filename> 的 <firstterm>object file</firstterm>(非執行檔)。
+ 這檔可以與其他的 object file 連結在一起,而成執行檔。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-g</option></term>
+
+ <listitem>
+ <para><option>-g</option> 將會把一些給 gdb 用的除錯訊息包進去執行檔裡面,所謂的除錯訊息例如:
+ 程式在第幾行出錯、那個程式第幾行做什麼函式呼叫等等。除錯資訊<emphasis>非常</emphasis>好用。
+ 但缺點就是:對於程式來說,額外的除錯訊息會讓編譯出來的程式比較肥些。
+ <option>-g</option> 的適用時機在於:當程式還在開發時使用就好,
+ 而當你要釋出你的 <quote>發行版本(release version)</quote>
+ 或者確認程式可運作正常的話,就不必用 <option>-g</option> 這選項了。</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -g foobar.c</userinput>
+ </screen>
+ </informalexample>
+
+ <para>這動作會產生有含除錯訊息的執行檔。
+ <footnote>
+ <para>請注意,因為上例沒用 <option>-o</option> 以指定執行檔名稱,
+ 所以執行檔會是 <filename>a.out</filename> 這檔。
+ 那麼,要如何產生 <filename>foobar</filename> 的執行檔並內含除錯訊息,
+ 這就留待看倌們練習一下囉。</para>
+ </footnote></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-O</option></term>
+
+ <listitem>
+ <para><option>-O</option> 會產生最佳化的執行檔,
+ 編譯器會使用一些技巧,來讓程式可以跑的比未經最佳化的程式還快,
+ 可以在大寫 O 後面加上數字來指明想要的最佳化層級。
+ 但是最佳化還是會有一些錯誤,舉例來說在 FreeBSD 2.10 release 中用 <command>cc</command>
+ 且指定 <option>-O2</option> 時,在某些情形下會產生錯誤的執行檔。</para>
+
+ <para>只有當要釋出發行版本、或者加速程式時,才需要使用最佳化選項。</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput>
+ </screen>
+ </informalexample>
+
+ <para>這會產生 <filename>foobar</filename> 執行檔的最佳化版本。</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>以下三個參數將會強迫 <command>cc</command> 確認程式碼是否符合一些國際標準的規範,
+ 也就是通常說的 <acronym>ANSI</acronym> 標準,
+ 而 <acronym>ANSI</acronym> 嚴格來講屬 <acronym>ISO</acronym> 標準。</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-Wall</option></term>
+
+ <listitem>
+ <para><option>-Wall</option> 顯示 <command>cc</command> 維護者所認為值得注意的所有警告訊息。
+ 不過這名字可能會造成誤解,事實上它並未完全顯示 <command>cc</command> 所能注意到的各項警告訊息。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-ansi</option></term>
+
+ <listitem>
+ <para><option>-ansi</option> 關閉 <command>cc</command> 特有的某些特殊非 ANSI C 標準功能。
+ 不過這名字可能會造成誤解,事實上它並不保證你的程式會完全符合 ANSI 標準。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-pedantic</option></term>
+
+ <listitem>
+ <para>全面關閉 <command>cc</command> 所特有的非 <acronym>ANSI</acronym> C 標準功能。</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>除了這些參數,<command>cc</command> 還允許你使用一些額外的參數取代標準參數,有些額外參數非常有用,
+ 但是實際上並不是所有的編譯器都有提供這些參數。
+ 照標準來寫程式的最主要目的就是,希望你寫出來的程式可以在所有編譯器上編譯、執行無誤,
+ 當程式可以達成上述目的時,就稱為 <firstterm>portable code(移植性良好的程式碼)</firstterm>。</para>
+
+ <para>一般來說,在撰寫程式時就應要注意『移植性』。
+ 否則。當想把程式拿到另外一台機器上跑的時候,就可能得需要重寫程式。</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput></screen>
+ </informalexample>
+
+ <para>上述指令會確認 <filename>foobar.c</filename> 內的語法是否符合標準,
+ 並且產生名為 <filename>foobar</filename> 的執行檔。</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-l<replaceable>library</replaceable></option></term>
+
+ <listitem>
+ <para>告訴 gcc 在連結(linking)程式時你需要用到的函式庫名稱。</para>
+
+ <para>最常見的情況就是,當你在程式中使用了 C 數學函式庫,
+ 跟其他作業平台不一樣的是,這函示學函式都不在標準函式庫(library)中,
+ 因此編譯器並不知道這函式庫名稱,你必須告訴編譯器要加上它才行。</para>
+
+ <para>規則很簡單,如果有個函式庫叫做 <filename>libsomething.a</filename>,
+ 就必須在編譯時加上參數 <option>-l<replaceable>something</replaceable></option> 才行。
+ 舉例來說,數學函式庫叫做 <filename>libm.a</filename>,
+ 所以你必須給 <command>cc</command> 的參數就是 <option>-lm</option>。
+ 一般情況下,通常會把這參數必須放在指令的最後。</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
+ </screen>
+ </informalexample>
+
+ <para>上面這指令會讓 gcc 跟數學函式庫作連結,以便你的程式可以呼叫函式庫內含的數學函式。</para>
+
+ <para>如果你正在編譯的程式是 C++ 程式碼,你還必須額外指定 <option>-lg++</option> 或者是
+ <option>-lstdc++</option>。
+ 如果你的 FreeBSD 是 2.2(含)以後版本,
+ 你可以用指令 <command>c++</command> 來取代 <command>cc</command>。
+ 在 FreeBSD 上 <command>c++</command> 也可以用 <command>g++</command> 取代。</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>適用 FreeBSD 2.1.6 或更早期的版本</lineannotation>
+&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>適用 FreeBSD 2.2 及之後的版本</lineannotation>
+&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput>
+ </screen>
+ </informalexample>
+
+ <para>上述指令都會從原始檔 <filename>foobar.cc</filename> 編譯產生名為 <filename>fooboar</filename> 的執行檔。
+ 這邊要提醒的是在 &unix; 系統中 C++ 程式傳統都以 <filename>.C</filename>、
+ <filename>.cxx</filename> 或者是 <filename>.cc</filename> 作為副檔名,
+ 而非 &ms-dos; 那種以 <filename>.cpp</filename> 作為副檔名的命名方式(不過也越來越普遍了)。
+ <command>gcc</command> 會依副檔名來決定用哪一種編譯器編譯,
+ 然而,現在已經不再限制副檔名了,
+ 所以可以自由的使用 <filename>.cpp</filename> 作為 C++ 程式碼的副檔名!</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <sect2>
+ <title>常見的 <command>cc</command> 問題</title>
+
+ <qandaset>
+ <qandaentry>
+ <question>
+ <para>我用 <function>sin()</function> 函示撰寫我的程式,
+ 但是有個錯誤訊息(如下),這代表著?</para>
+
+ <informalexample>
+ <screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
+ </screen>
+ </informalexample>
+ </question>
+
+ <answer>
+ <para>當使用 <function>sin()</function> 這類的數學函示時,
+ 你必須告訴 cc 要和數學函式庫作連結(linking),就像這樣:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
+ </screen>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>好吧,我試著寫些簡單的程式,來練習使用 -lm 選項(該程式會運算 2.1 的 6 次方)</para>
+
+ <informalexample>
+ <programlisting>#include &lt;stdio.h&gt;
+
+int main() {
+ float f;
+
+ f = pow(2.1, 6);
+ printf("2.1 ^ 6 = %f\n", f);
+ return 0;
+}
+ </programlisting>
+ </informalexample>
+
+ <para>然後進行編譯:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc temp.c -lm</userinput>
+ </screen>
+ </informalexample>
+
+ <para>編譯後執行程式,得到下面這結果:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>./a.out</userinput>
+2.1 ^ 6 = 1023.000000
+ </screen>
+ </informalexample>
+
+ <para>很明顯的,程式結果<emphasis>不是</emphasis>正確答案,到底是哪邊出錯?</para>
+ </question>
+
+ <answer>
+ <para>當編譯器發現你呼叫一個函示時,它會確認該函示的回傳值類型(prototype),
+ 如果沒有特別指明,則預設的回傳值類型為 <type>int(整數)</type>。
+ 很明顯的,你的程式所需要的並不是回傳值類別為 <type>int</type>。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>那如何才可以修正剛所說的問題?</para>
+ </question>
+
+ <answer>
+ <para>數學函示的回傳值類型(prototype)會定義在 <filename>math.h</filename>,
+ 如果你有 include 這檔,編譯器就會知道該函示的回傳值類型,如此一來該運算就會得到正確的結果!</para>
+
+ <informalexample>
+ <programlisting>#include &lt;math.h&gt;
+#include &lt;stdio.h&gt;
+
+int main() {
+...
+ </programlisting>
+ </informalexample>
+
+ <para>加了上述內容之後,再重新編譯,最後執行:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>./a.out</userinput>
+2.1 ^ 6 = 85.766121
+ </screen>
+ </informalexample>
+
+ <para>如果有用到數學函式,<emphasis>請確定</emphasis>要有 include <filename>math.h</filename> 這檔,
+ 而且記得要和數學函式庫作連結。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>已經編譯好 <filename>foobar.c</filename>,
+ 但是編譯後找不到 <filename>foobar</filename> 執行檔。 該去哪邊找呢?</para>
+ </question>
+
+ <answer>
+ <para>記得,除非有指定編譯結果的執行檔檔名,否則預設的執行檔檔名是 a.out。
+ 用 <option>-o&nbsp;<replaceable>filename</replaceable></option> 參數,
+ 就可以達到所想要的結果,比如:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput>
+ </screen>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>好,有個編譯好的程式叫做 <filename>foobar</filename>,
+ 用 <command>ls</command> 指令時可以看到,
+ 但執行時,訊息卻說卻沒有這檔案。為什麼?</para>
+ </question>
+
+ <answer>
+ <para>與 &ms-dos; 不同的是,除非有指定執行檔的路徑,
+ 否則 &unix; 系統並不會在目前的目錄下尋找你想執行的檔案。
+ 在指令列下打 <command>./foobar</command> 代表
+ <quote>執行在這個目錄底下名為 <filename>foobar</filename> 的程式</quote>,
+ 或者也可以更改 <envar>PATH</envar> 環境變數設定如下,以達成類似效果:</para>
+
+ <informalexample>
+ <screen>bin:/usr/bin:/usr/local/bin:.
+ </screen>
+ </informalexample>
+
+ <para>上一行最後的 "." 代表<quote>如果在前面寫的其他目錄找不到,就找目前的目錄</quote>。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>試著執行 <filename>test</filename> 執行檔,
+ 但是卻沒有任何事發生,到底是哪裡出錯了?</para>
+ </question>
+
+ <answer>
+ <para>大多數的 &unix; 系統都會在路徑 <filename>/usr/bin</filename> 擺放執行檔。
+ 除非有指定使用在目前目錄內的 <filename>test</filename>,否則 shell 會優先選擇位在
+ <filename>/usr/bin</filename> 的 <filename>test</filename>,
+ 要指定檔名的話,作法類似:</para>
+
+ <informalexample>
+ <screen>&prompt.user; <userinput>./test</userinput>
+ </screen>
+ </informalexample>
+
+ <para>為了避免上述困擾,請為你的程式取更好的名稱吧!</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>當執行我寫的程式時剛開始正常,
+ 接下來卻出現 <errorname>core dumped</errorname> 錯誤訊息。這錯誤訊息到底代表什麼?</para>
+ </question>
+
+ <answer>
+ <para>關於 <firstterm>core dumped</firstterm> 這個名稱的由來,
+ 可以追溯到早期的 &unix; 系統開始使用 core memory 對資料排序時。
+ 基本上當程式在很多情況下發生錯誤後,
+ 作業系統會把 core memory 中的資訊寫入 <filename>core</filename> 這檔案中,
+ 以便讓 programmer 知道程式到底是為何出錯。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>真是太神奇了!程式居然發生 <errorname>core dumped</errorname> 了,該怎麼辦?</para>
+ </question>
+
+ <answer>
+ <para>請用 <command>gdb</command> 來分析 core 結果(詳情請參考 <xref linkend="debugging"/>)。</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>當程式已經把 core memory 資料 dump 出來後,
+ 同時也出現另一個錯誤 <errorname>segmentation fault</errorname> 這意思是?</para>
+ </question>
+
+ <answer>
+ <para>基本上,這個錯誤表示你的程式在記憶體中試著做一個嚴重的非法運作(illegal operation),
+ &unix; 就是被設計來保護整個作業系統免於被惡質的程式破壞,所以才會告訴你這個訊息。</para>
+
+ <para>最常造成<quote>segmentation fault</quote>的原因通常為:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>試著對一個 <symbol>NULL</symbol> 的指標(pointer)作寫入的動作,如</para>
+
+ <programlisting>char *foo = NULL;
+strcpy(foo, "bang!");
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>使用一個尚未初始化(initialized)的指標,如:</para>
+
+ <programlisting>char *foo;
+strcpy(foo, "bang!");
+ </programlisting>
+
+ <para>尚未初始化的指標的初始值將會是隨機的,如果你夠幸運的話,
+ 這個指標的初始值會指向 kernel 已經用到的記憶體位置,
+ kernel 會結束掉這個程式以確保系統運作正常。如果你不夠幸運,
+ 初始指到的記憶體位置是你程式必須要用到的資料結構(data structures)的位置,
+ 當這個情形發生時程式將會當的不知其所以然。</para>
+ </listitem>
+
+ <listitem>
+ <para>試著寫入超過陣列(array)元素個數,如:</para>
+
+ <programlisting>int bar[20];
+bar[27] = 6;
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>試著讀寫在唯讀記憶體(read-only memory)中的資料,如:</para>
+
+ <programlisting>char *foo = "My string";
+strcpy(foo, "bang!");
+ </programlisting>
+
+ <para>&unix; compilers often put string literals like
+ <literal>"My string"</literal> into read-only areas
+ of memory.</para>
+ </listitem>
+
+ <listitem>
+ <para>Doing naughty things with
+ <function>malloc()</function> and
+ <function>free()</function>, eg</para>
+
+ <programlisting>char bar[80];
+free(bar);
+ </programlisting>
+
+ <para>or</para>
+
+ <programlisting>char *foo = malloc(27);
+free(foo);
+free(foo);
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>Making one of these mistakes will not always lead to
+ an error, but they are always bad practice. Some
+ systems and compilers are more tolerant than others,
+ which is why programs that ran well on one system can
+ crash when you try them on an another.</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>Sometimes when I get a core dump it says
+ <errorname>bus error</errorname>. It says in my &unix;
+ book that this means a hardware problem, but the
+ computer still seems to be working. Is this
+ true?</para>
+ </question>
+
+ <answer>
+ <para>No, fortunately not (unless of course you really do
+ have a hardware problem&hellip;). This is usually
+ another way of saying that you accessed memory in a way
+ you should not have.</para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>This dumping core business sounds as though it could
+ be quite useful, if I can make it happen when I want to.
+ Can I do this, or do I have to wait until there is an
+ error?</para>
+ </question>
+
+ <answer>
+ <para>Yes, just go to another console or xterm, do</para>
+
+ <screen>&prompt.user; <userinput>ps</userinput>
+ </screen>
+
+ <para>to find out the process ID of your program, and
+ do</para>
+
+ <screen>&prompt.user; <userinput>kill -ABRT pid</userinput>
+ </screen>
+
+ <para>where
+ <parameter><replaceable>pid</replaceable></parameter> is
+ the process ID you looked up.</para>
+
+ <para>This is useful if your program has got stuck in an
+ infinite loop, for instance. If your program happens to
+ trap <symbol>SIGABRT</symbol>, there are several other
+ signals which have a similar effect.</para>
+
+ <para>Alternatively, you can create a core dump from
+ inside your program, by calling the
+ <function>abort()</function> function. See the manual page
+ of &man.abort.3; to learn more.</para>
+
+ <para>If you want to create a core dump from outside your
+ program, but do not want the process to terminate, you
+ can use the <command>gcore</command> program. See the
+ manual page of &man.gcore.1; for more information.</para>
+
+ </answer>
+ </qandaentry>
+ </qandaset>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="tools-make">
+ <title>Make</title>
+
+ <sect2>
+ <title>What is <command>make</command>?</title>
+
+ <para>When you are working on a simple program with only one or
+ two source files, typing in</para>
+
+ <screen>&prompt.user; <userinput>cc file1.c file2.c</userinput></screen>
+
+ <para>is not too bad, but it quickly becomes very tedious when
+ there are several files&mdash;and it can take a while to
+ compile, too.</para>
+
+ <para>One way to get around this is to use object files and only
+ recompile the source file if the source code has changed. So
+ we could have something like:</para>
+
+ <screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> &hellip; <userinput>file37.c</userinput> &hellip;</screen>
+
+ <para>if we had changed <filename>file37.c</filename>, but not any
+ of the others, since the last time we compiled. This may
+ speed up the compilation quite a bit, but does not solve the
+ typing problem.</para>
+
+ <para>Or we could write a shell script to solve the typing
+ problem, but it would have to re-compile everything, making it
+ very inefficient on a large project.</para>
+
+ <para>What happens if we have hundreds of source files lying
+ about? What if we are working in a team with other people who
+ forget to tell us when they have changed one of their source
+ files that we use?</para>
+
+ <para>Perhaps we could put the two solutions together and write
+ something like a shell script that would contain some kind of
+ magic rule saying when a source file needs compiling. Now all
+ we need now is a program that can understand these rules, as
+ it is a bit too complicated for the shell.</para>
+
+ <para>This program is called <command>make</command>. It reads
+ in a file, called a <firstterm>makefile</firstterm>, that
+ tells it how different files depend on each other, and works
+ out which files need to be re-compiled and which ones do not.
+ For example, a rule could say something like <quote>if
+ <filename>fromboz.o</filename> is older than
+ <filename>fromboz.c</filename>, that means someone must have
+ changed <filename>fromboz.c</filename>, so it needs to be
+ re-compiled.</quote> The makefile also has rules telling
+ make <emphasis>how</emphasis> to re-compile the source file,
+ making it a much more powerful tool.</para>
+
+ <para>Makefiles are typically kept in the same directory as the
+ source they apply to, and can be called
+ <filename>makefile</filename>, <filename>Makefile</filename>
+ or <filename>MAKEFILE</filename>. Most programmers use the
+ name <filename>Makefile</filename>, as this puts it near the
+ top of a directory listing, where it can easily be
+ seen.
+
+ <footnote>
+ <para>They do not use the <filename>MAKEFILE</filename> form
+ as block capitals are often used for documentation files
+ like <filename>README</filename>.</para>
+ </footnote></para>
+ </sect2>
+
+ <sect2>
+ <title>Example of using <command>make</command></title>
+
+ <para>Here is a very simple make file:</para>
+
+ <programlisting>foo: foo.c
+ cc -o foo foo.c</programlisting>
+
+ <para>It consists of two lines, a dependency line and a creation
+ line.</para>
+
+ <para>The dependency line here consists of the name of the
+ program (known as the <firstterm>target</firstterm>), followed
+ by a colon, then whitespace, then the name of the source file.
+ When <command>make</command> reads this line, it looks to see
+ if <filename>foo</filename> exists; if it exists, it compares
+ the time <filename>foo</filename> was last modified to the
+ time <filename>foo.c</filename> was last modified. If
+ <filename>foo</filename> does not exist, or is older than
+ <filename>foo.c</filename>, it then looks at the creation line
+ to find out what to do. In other words, this is the rule for
+ working out when <filename>foo.c</filename> needs to be
+ re-compiled.</para>
+
+ <para>The creation line starts with a <token>tab</token> (press
+ the <keycap>tab</keycap> key) and then the command you would
+ type to create <filename>foo</filename> if you were doing it
+ at a command prompt. If <filename>foo</filename> is out of
+ date, or does not exist, <command>make</command> then executes
+ this command to create it. In other words, this is the rule
+ which tells make how to re-compile
+ <filename>foo.c</filename>.</para>
+
+ <para>So, when you type <userinput>make</userinput>, it will
+ make sure that <filename>foo</filename> is up to date with
+ respect to your latest changes to <filename>foo.c</filename>.
+ This principle can be extended to
+ <filename>Makefile</filename>s with hundreds of
+ targets&mdash;in fact, on FreeBSD, it is possible to compile
+ the entire operating system just by typing <userinput>make
+ world</userinput> in the appropriate directory!</para>
+
+ <para>Another useful property of makefiles is that the targets
+ do not have to be programs. For instance, we could have a make
+ file that looks like this:</para>
+
+ <programlisting>foo: foo.c
+ cc -o foo foo.c
+
+install:
+ cp foo /home/me</programlisting>
+
+ <para>We can tell make which target we want to make by
+ typing:</para>
+
+ <screen>&prompt.user; <userinput>make target</userinput></screen>
+
+ <para><command>make</command> will then only look at that target
+ and ignore any others. For example, if we type
+ <userinput>make foo</userinput> with the makefile above, make
+ will ignore the <buildtarget>install</buildtarget> target.</para>
+
+ <para>If we just type <userinput>make</userinput> on its own,
+ make will always look at the first target and then stop
+ without looking at any others. So if we typed
+ <userinput>make</userinput> here, it will just go to the
+ <buildtarget>foo</buildtarget> target, re-compile
+ <filename>foo</filename> if necessary, and then stop without
+ going on to the <buildtarget>install</buildtarget> target.</para>
+
+ <para>Notice that the <buildtarget>install</buildtarget> target does not
+ actually depend on anything! This means that the command on
+ the following line is always executed when we try to make that
+ target by typing <userinput>make install</userinput>. In this
+ case, it will copy <filename>foo</filename> into the user's
+ home directory. This is often used by application makefiles,
+ so that the application can be installed in the correct
+ directory when it has been correctly compiled.</para>
+
+ <para>This is a slightly confusing subject to try to explain.
+ If you do not quite understand how <command>make</command>
+ works, the best thing to do is to write a simple program like
+ <quote>hello world</quote> and a make file like the one above
+ and experiment. Then progress to using more than one source
+ file, or having the source file include a header file. The
+ <command>touch</command> command is very useful here&mdash;it
+ changes the date on a file without you having to edit
+ it.</para>
+ </sect2>
+
+ <sect2>
+ <title>Make and include-files</title>
+
+ <para>C code often starts with a list of files to include, for
+ example stdio.h. Some of these files are system-include
+ files, some of them are from the project you are now working
+ on:
+ </para>
+
+ <programlisting>#include &lt;stdio.h&gt;
+#include "foo.h"
+
+int main(....</programlisting>
+
+ <para>To make sure that this file is recompiled the moment
+ <filename>foo.h</filename> is changed, you have to add it in
+ your <filename>Makefile</filename>:</para>
+
+ <programlisting>foo: foo.c foo.h</programlisting>
+
+ <para>The moment your project is getting bigger and you have
+ more and more own include-files to maintain, it will be a
+ pain to keep track of all include files and the files which
+ are depending on it. If you change an include-file but
+ forget to recompile all the files which are depending on
+ it, the results will be devastating. <command>gcc</command>
+ has an option to analyze your files and to produce a list
+ of include-files and their dependencies: <option>-MM</option>.
+ </para>
+
+ <para>If you add this to your Makefile:</para>
+
+ <programlisting>depend:
+ gcc -E -MM *.c &gt; .depend</programlisting>
+
+ <para>and run <userinput>make depend</userinput>, the file
+ <filename>.depend</filename> will appear with a list of
+ object-files, C-files and the include-files:</para>
+
+ <programlisting>foo.o: foo.c foo.h</programlisting>
+
+ <para>If you change <filename>foo.h</filename>, next time
+ you run <command>make</command> all files depending on
+ <filename>foo.h</filename> will be recompiled.</para>
+
+ <para>Do not forget to run <command>make depend</command> each
+ time you add an include-file to one of your files.</para>
+ </sect2>
+
+ <sect2>
+ <title>FreeBSD Makefiles</title>
+
+ <para>Makefiles can be rather complicated to write. Fortunately,
+ BSD-based systems like FreeBSD come with some very powerful
+ ones as part of the system. One very good example of this is
+ the FreeBSD ports system. Here is the essential part of a
+ typical ports <filename>Makefile</filename>:</para>
+
+ <programlisting>MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
+DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz
+
+.include &lt;bsd.port.mk&gt;</programlisting>
+
+ <para>Now, if we go to the directory for this port and type
+ <userinput>make</userinput>, the following happens:</para>
+
+ <procedure>
+ <step>
+ <para>A check is made to see if the source code for this
+ port is already on the system.</para>
+ </step>
+
+ <step>
+ <para>If it is not, an FTP connection to the URL in
+ <symbol>MASTER_SITES</symbol> is set up to download the
+ source.</para>
+ </step>
+
+ <step>
+ <para>The checksum for the source is calculated and compared
+ it with one for a known, good, copy of the source. This
+ is to make sure that the source was not corrupted while in
+ transit.</para>
+ </step>
+
+ <step>
+ <para>Any changes required to make the source work on
+ FreeBSD are applied&mdash;this is known as
+ <firstterm>patching</firstterm>.</para>
+ </step>
+
+ <step>
+ <para>Any special configuration needed for the source is
+ done. (Many &unix; program distributions try to work out
+ which version of &unix; they are being compiled on and which
+ optional &unix; features are present&mdash;this is where
+ they are given the information in the FreeBSD ports
+ scenario).</para>
+ </step>
+
+ <step>
+ <para>The source code for the program is compiled. In
+ effect, we change to the directory where the source was
+ unpacked and do <command>make</command>&mdash;the
+ program's own make file has the necessary information to
+ build the program.</para>
+ </step>
+
+ <step>
+ <para>We now have a compiled version of the program. If we
+ wish, we can test it now; when we feel confident about the
+ program, we can type <userinput>make install</userinput>.
+ This will cause the program and any supporting files it
+ needs to be copied into the correct location; an entry is
+ also made into a <database>package database</database>, so
+ that the port can easily be uninstalled later if we change
+ our mind about it.</para>
+ </step>
+ </procedure>
+
+ <para>Now I think you will agree that is rather impressive for a
+ four line script!</para>
+
+ <para>The secret lies in the last line, which tells
+ <command>make</command> to look in the system makefile called
+ <filename>bsd.port.mk</filename>. It is easy to overlook this
+ line, but this is where all the clever stuff comes
+ from&mdash;someone has written a makefile that tells
+ <command>make</command> to do all the things above (plus a
+ couple of other things I did not mention, including handling
+ any errors that may occur) and anyone can get access to that
+ just by putting a single line in their own make file!</para>
+
+ <para>If you want to have a look at these system makefiles,
+ they are in <filename>/usr/share/mk</filename>, but it is
+ probably best to wait until you have had a bit of practice with
+ makefiles, as they are very complicated (and if you do look at
+ them, make sure you have a flask of strong coffee
+ handy!)</para>
+ </sect2>
+
+ <sect2>
+ <title>More advanced uses of <command>make</command></title>
+
+ <para><command>Make</command> is a very powerful tool, and can
+ do much more than the simple example above shows.
+ Unfortunately, there are several different versions of
+ <command>make</command>, and they all differ considerably.
+ The best way to learn what they can do is probably to read the
+ documentation&mdash;hopefully this introduction will have
+ given you a base from which you can do this.</para>
+
+ <para>The version of make that comes with FreeBSD is the
+ <application>Berkeley make</application>; there is a tutorial
+ for it in <filename>/usr/share/doc/psd/12.make</filename>. To
+ view it, do</para>
+
+ <screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput></screen>
+
+ <para>in that directory.</para>
+
+ <para>Many applications in the ports use <application>GNU
+ make</application>, which has a very good set of
+ <quote>info</quote> pages. If you have installed any of these
+ ports, <application>GNU make</application> will automatically
+ have been installed as <command>gmake</command>. It is also
+ available as a port and package in its own right.</para>
+
+ <para>To view the info pages for <application>GNU
+ make</application>, you will have to edit the
+ <filename>dir</filename> file in the
+ <filename>/usr/local/info</filename> directory to add an entry
+ for it. This involves adding a line like</para>
+
+ <programlisting> * Make: (make). The GNU Make utility.</programlisting>
+
+ <para>to the file. Once you have done this, you can type
+ <userinput>info</userinput> and then select
+ <guimenuitem>make</guimenuitem> from the menu (or in
+ <application>Emacs</application>, do <userinput>C-h
+ i</userinput>).</para>
+ </sect2>
+ </sect1>
+
+ <sect1 xml:id="debugging">
+ <title>Debugging</title>
+
+ <sect2>
+ <title>The Debugger</title>
+
+ <para>The debugger that comes with FreeBSD is called
+ <command>gdb</command> (<application>GNU
+ debugger</application>). You start it up by typing</para>
+
+ <screen>&prompt.user; <userinput>gdb progname</userinput></screen>
+
+ <para>although most people prefer to run it inside
+ <application>Emacs</application>. You can do this by:</para>
+
+ <screen><userinput>M-x gdb RET progname RET</userinput></screen>
+
+ <para>Using a debugger allows you to run the program under more
+ controlled circumstances. Typically, you can step through the
+ program a line at a time, inspect the value of variables,
+ change them, tell the debugger to run up to a certain point
+ and then stop, and so on. You can even attach to a program
+ that is already running, or load a core file to investigate why
+ the program crashed. It is even possible to debug the kernel,
+ though that is a little trickier than the user applications
+ we will be discussing in this section.</para>
+
+ <para><command>gdb</command> has quite good on-line help, as
+ well as a set of info pages, so this section will concentrate
+ on a few of the basic commands.</para>
+
+ <para>Finally, if you find its text-based command-prompt style
+ off-putting, there is a graphical front-end for it (<link xlink:href="&url.base;/ports/devel.html">xxgdb</link>) in the ports
+ collection.</para>
+
+ <para>This section is intended to be an introduction to using
+ <command>gdb</command> and does not cover specialized topics
+ such as debugging the kernel.</para>
+ </sect2>
+
+ <sect2>
+ <title>Running a program in the debugger</title>
+
+ <para>You will need to have compiled the program with the
+ <option>-g</option> option to get the most out of using
+ <command>gdb</command>. It will work without, but you will only
+ see the name of the function you are in, instead of the source
+ code. If you see a line like:</para>
+
+ <screen>&hellip; (no debugging symbols found) &hellip;</screen>
+
+ <para>when <command>gdb</command> starts up, you will know that
+ the program was not compiled with the <option>-g</option>
+ option.</para>
+
+ <para>At the <command>gdb</command> prompt, type
+ <userinput>break main</userinput>. This will tell the
+ debugger to skip over the preliminary set-up code in the
+ program and start at the beginning of your code. Now type
+ <userinput>run</userinput> to start the program&mdash;it will
+ start at the beginning of the set-up code and then get stopped
+ by the debugger when it calls <function>main()</function>.
+ (If you have ever wondered where <function>main()</function>
+ gets called from, now you know!).</para>
+
+ <para>You can now step through the program, a line at a time, by
+ pressing <command>n</command>. If you get to a function call,
+ you can step into it by pressing <command>s</command>. Once
+ you are in a function call, you can return from stepping into a
+ function call by pressing <command>f</command>. You can also
+ use <command>up</command> and <command>down</command> to take
+ a quick look at the caller.</para>
+
+ <para>Here is a simple example of how to spot a mistake in a
+ program with <command>gdb</command>. This is our program
+ (with a deliberate mistake):</para>
+
+ <programlisting>#include &lt;stdio.h&gt;
+
+int bazz(int anint);
+
+main() {
+ int i;
+
+ printf("This is my program\n");
+ bazz(i);
+ return 0;
+}
+
+int bazz(int anint) {
+ printf("You gave me %d\n", anint);
+ return anint;
+}</programlisting>
+
+ <para>This program sets <symbol>i</symbol> to be
+ <literal>5</literal> and passes it to a function
+ <function>bazz()</function> which prints out the number we
+ gave it.</para>
+
+ <para>When we compile and run the program we get</para>
+
+ <screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput>
+&prompt.user; <userinput>./temp</userinput>
+This is my program
+anint = 4231</screen>
+
+ <para>That was not what we expected! Time to see what is going
+ on!</para>
+
+ <screen>&prompt.user; <userinput>gdb temp</userinput>
+GDB is free software and you are welcome to distribute copies of it
+ under certain conditions; type "show copying" to see the conditions.
+There is absolutely no warranty for GDB; type "show warranty" for details.
+GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
+(gdb) <userinput>break main</userinput> <lineannotation>Skip the set-up code</lineannotation>
+Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation>gdb puts breakpoint at main()</lineannotation>
+(gdb) <userinput>run</userinput> <lineannotation>Run as far as main()</lineannotation>
+Starting program: /home/james/tmp/temp <lineannotation>Program starts running</lineannotation>
+
+Breakpoint 1, main () at temp.c:9 <lineannotation>gdb stops at main()</lineannotation>
+(gdb) <userinput>n</userinput> <lineannotation>Go to next line</lineannotation>
+This is my program <lineannotation>Program prints out</lineannotation>
+(gdb) <userinput>s</userinput> <lineannotation>step into bazz()</lineannotation>
+bazz (anint=4231) at temp.c:17 <lineannotation>gdb displays stack frame</lineannotation>
+(gdb)</screen>
+
+ <para>Hang on a minute! How did <symbol>anint</symbol> get to be
+ <literal>4231</literal>? Did we not we set it to be
+ <literal>5</literal> in <function>main()</function>? Let's
+ move up to <function>main()</function> and have a look.</para>
+
+ <screen>(gdb) <userinput>up</userinput> <lineannotation>Move up call stack</lineannotation>
+#1 0x1625 in main () at temp.c:11 <lineannotation>gdb displays stack frame</lineannotation>
+(gdb) <userinput>p i</userinput> <lineannotation>Show us the value of i</lineannotation>
+$1 = 4231 <lineannotation>gdb displays 4231</lineannotation></screen>
+
+ <para>Oh dear! Looking at the code, we forgot to initialize
+ <symbol>i</symbol>. We meant to put</para>
+
+ <programlisting><lineannotation>&hellip;</lineannotation>
+main() {
+ int i;
+
+ i = 5;
+ printf("This is my program\n");
+<lineannotation>&hellip;</lineannotation></programlisting>
+
+ <para>but we left the <literal>i=5;</literal> line out. As we
+ did not initialize <symbol>i</symbol>, it had whatever number
+ happened to be in that area of memory when the program ran,
+ which in this case happened to be
+ <literal>4231</literal>.</para>
+
+ <note>
+ <para><command>gdb</command> displays the stack frame every
+ time we go into or out of a function, even if we are using
+ <command>up</command> and <command>down</command> to move
+ around the call stack. This shows the name of the function
+ and the values of its arguments, which helps us keep track
+ of where we are and what is going on. (The stack is a
+ storage area where the program stores information about the
+ arguments passed to functions and where to go when it
+ returns from a function call).</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>Examining a core file</title>
+
+ <para>A core file is basically a file which contains the
+ complete state of the process when it crashed. In <quote>the
+ good old days</quote>, programmers had to print out hex
+ listings of core files and sweat over machine code manuals,
+ but now life is a bit easier. Incidentally, under FreeBSD and
+ other 4.4BSD systems, a core file is called
+ <filename>progname.core</filename> instead of just
+ <filename>core</filename>, to make it clearer which program a
+ core file belongs to.</para>
+
+ <para>To examine a core file, start up <command>gdb</command> in
+ the usual way. Instead of typing <command>break</command> or
+ <command>run</command>, type</para>
+
+ <screen>(gdb) <userinput>core progname.core</userinput></screen>
+
+ <para>If you are not in the same directory as the core file,
+ you will have to do <userinput>dir
+ /path/to/core/file</userinput> first.</para>
+
+ <para>You should see something like this:</para>
+
+ <screen>&prompt.user; <userinput>gdb a.out</userinput>
+GDB is free software and you are welcome to distribute copies of it
+ under certain conditions; type "show copying" to see the conditions.
+There is absolutely no warranty for GDB; type "show warranty" for details.
+GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
+(gdb) <userinput>core a.out.core</userinput>
+Core was generated by `a.out'.
+Program terminated with signal 11, Segmentation fault.
+Cannot access memory at address 0x7020796d.
+#0 0x164a in bazz (anint=0x5) at temp.c:17
+(gdb)</screen>
+
+ <para>In this case, the program was called
+ <filename>a.out</filename>, so the core file is called
+ <filename>a.out.core</filename>. We can see that the program
+ crashed due to trying to access an area in memory that was not
+ available to it in a function called
+ <function>bazz</function>.</para>
+
+ <para>Sometimes it is useful to be able to see how a function was
+ called, as the problem could have occurred a long way up the
+ call stack in a complex program. The <command>bt</command>
+ command causes <command>gdb</command> to print out a
+ back-trace of the call stack:</para>
+
+ <screen>(gdb) <userinput>bt</userinput>
+#0 0x164a in bazz (anint=0x5) at temp.c:17
+#1 0xefbfd888 in end ()
+#2 0x162c in main () at temp.c:11
+(gdb)</screen>
+
+ <para>The <function>end()</function> function is called when a
+ program crashes; in this case, the <function>bazz()</function>
+ function was called from <function>main()</function>.</para>
+ </sect2>
+
+ <sect2>
+ <title>Attaching to a running program</title>
+
+ &