From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- doc/.cvsignore | 3 + doc/BGP-TypeCode | 24 + doc/ChangeLog | 90 + doc/Makefile.am | 14 + doc/Makefile.in | 482 +++++ doc/appendix.texi | 238 +++ doc/basic.texi | 510 +++++ doc/bgpd.8 | 169 ++ doc/bgpd.texi | 1288 +++++++++++ doc/draft-zebra-00.ms | 209 ++ doc/filter.texi | 192 ++ doc/install.texi | 218 ++ doc/ipv6.texi | 32 + doc/kernel.texi | 48 + doc/main.texi | 186 ++ doc/ospf6d.8 | 127 ++ doc/ospf6d.texi | 102 + doc/ospfd.8 | 131 ++ doc/ospfd.texi | 345 +++ doc/overview.texi | 352 ++++ doc/protocol.texi | 52 + doc/ripd.8 | 212 ++ doc/ripd.texi | 584 +++++ doc/ripngd.8 | 143 ++ doc/ripngd.texi | 85 + doc/routemap.texi | 91 + doc/snmp.texi | 68 + doc/texinfo.tex | 5625 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/vtysh.1 | 68 + doc/vtysh.texi | 27 + doc/zebra.8 | 146 ++ doc/zebra.info | 170 ++ doc/zebra.texi | 150 ++ 33 files changed, 12181 insertions(+) create mode 100644 doc/.cvsignore create mode 100644 doc/BGP-TypeCode create mode 100644 doc/ChangeLog create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/appendix.texi create mode 100644 doc/basic.texi create mode 100644 doc/bgpd.8 create mode 100644 doc/bgpd.texi create mode 100644 doc/draft-zebra-00.ms create mode 100644 doc/filter.texi create mode 100644 doc/install.texi create mode 100644 doc/ipv6.texi create mode 100644 doc/kernel.texi create mode 100644 doc/main.texi create mode 100644 doc/ospf6d.8 create mode 100644 doc/ospf6d.texi create mode 100644 doc/ospfd.8 create mode 100644 doc/ospfd.texi create mode 100644 doc/overview.texi create mode 100644 doc/protocol.texi create mode 100644 doc/ripd.8 create mode 100644 doc/ripd.texi create mode 100644 doc/ripngd.8 create mode 100644 doc/ripngd.texi create mode 100644 doc/routemap.texi create mode 100644 doc/snmp.texi create mode 100644 doc/texinfo.tex create mode 100644 doc/vtysh.1 create mode 100644 doc/vtysh.texi create mode 100644 doc/zebra.8 create mode 100644 doc/zebra.info create mode 100644 doc/zebra.texi (limited to 'doc') diff --git a/doc/.cvsignore b/doc/.cvsignore new file mode 100644 index 00000000..2916b2f7 --- /dev/null +++ b/doc/.cvsignore @@ -0,0 +1,3 @@ +Makefile +draft-zebra-00.txt +zebra.info-* diff --git a/doc/BGP-TypeCode b/doc/BGP-TypeCode new file mode 100644 index 00000000..0904e19f --- /dev/null +++ b/doc/BGP-TypeCode @@ -0,0 +1,24 @@ + + BGP-4[+] UPDATE Attribute TypeCode list + + Value Attribute References +========================================================================= + 1 ORIGIN [RFC 1771] + 2 AS_PATH [RFC 1771] + 3 NEXT_HOP [RFC 1771] + 4 MULTI_EXIT_DISC [RFC 1771] + 5 LOCAL_PREF [RFC 1771] + 6 ATOMIC_AGGREGATE [RFC 1771] + 7 AGGREGATOR [RFC 1771] + 8 COMMUNITIES [RFC 1997] + 9 ORIGINATOR_ID [RFC 1966] + 10 CLUSTER_LIST [RFC 1966] + 11 DPA [draft-ietf-idr-bgp-dpa-05.txt(expired)] + 12 ADVERTISER [Changed from RFC 1863 bgp@ans.net ML?] + 13 RCID_PATH [Changed from RFC 1863 bgp@ans.net ML?] + 14 MP_REACH_NLRI [RFC 2283] + 15 MP_UNREACH_NLRI [RFC 2283] + 16 EXT_COMMUNITIES [draft-ramachandra-bgp-ext-communities-09.txt] + 254 RCID_PATH [RFC 1863] + 255 ADVERTISER [RFC 1863] +========================================================================= diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 00000000..cfe6e0e2 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,90 @@ +2002-07-07 Kunihiro Ishiguro + + * zebra-0.93 released. + +2001-02-07 Pekka Savola + + * Correct bad English ;-). + +2001-02-01 Kunihiro Ishiguro + + * zebra-0.91 released. + +2001-01-09 Kunihiro Ishiguro + + * zebra-0.90 released. + +2000-10-02 Kunihiro Ishiguro + + * zebra-0.89 released. + +2000-10-02 Horms + + * Makefile.am: Fix texinfo file installation problem. + +2000-08-17 Kunihiro Ishiguro + + * zebra-0.88 released. + + * ospfd.texi (Redistribute routes to OSPF): distance <1-255> + @var{source} command is temporary disabled. So it is removed from + document. + +2000-07-04 Kunihiro Ishiguro + + * vtysh.1: Add man entry for vtysh. + + * bgpd.1: Change section to 8. + * ospfd.1: Likewise. + * ospf6d.1: Likewise. + * ripd.1: Likewise. + * ripngd.1: Likewise. + * zebra.1: Likewise. + +1999-09-01 "A.Waddington" + + * zebra.texi: Replace @command with @code until it gets ready. + Remove @macro. + +1999-08-26 Andrew Waddington + + * bgpd.1: Add man page. + ospf6d.1: Likewise. + ospfd.1: Likewise. + ripd.1: Likewise. + ripngd.1: Likewise. + zebra.1: Likewise. + +1999-08-14 Andrew Waddington + + * zebra.texi: Many typo is fixed. Some grammatical rectifications + is made. + +1999-07-27 Gerhard Poul + + * zebra.texi: Update zebra.texi. + +1999-07-02 Gerhard Poul + + * draft-zebra-00.ms: New file added. This is groff version of + draft-zebra-00.txt. This is a master file of draft-zebra-00.txt. + + * draft-zebra-00.txt: Generated from draft-zebra-00.txt. + +1999-05-07 Kunihiro Ishiguro + + * zebra.texi (Top): Add ospf6d chapter. + +1999-03-31 Jeroen Ruigrok/Asmodai + + * zebra.texi: Improve some sections. + +1999-03-04 Kunihiro Ishiguro + + * archfig.tex, zebra.sty, zebra.tex: Temporary removed due to the + description is out of date. + +1999-02-24 Kunihiro Ishiguro + + * texinfo.tex: New file added. Automake complains the absence of + texinfo.tex. diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..ee49cbd6 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in. + +info_TEXINFOS = zebra.texi + +zebra_TEXINFOS = appendix.texi basic.texi bgpd.texi filter.texi install.texi \ + ipv6.texi kernel.texi main.texi ospf6d.texi ospfd.texi overview.texi \ + protocol.texi ripd.texi ripngd.texi routemap.texi snmp.texi vtysh.texi + +man_MANS = vtysh.1 bgpd.8 ospf6d.8 ospfd.8 ripd.8 ripngd.8 zebra.8 + +EXTRA_DIST = BGP-TypeCode draft-zebra-00.ms draft-zebra-00.txt $(man_MANS) + +draft-zebra-00.txt: + groff -T ascii -ms draft-zebra-00.ms > draft-zebra-00.txt diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..66e35ec3 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,482 @@ +# Makefile.in generated by automake 1.7 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BGPD = @BGPD@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSES = @CURSES@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +IF_METHOD = @IF_METHOD@ +IF_PROC = @IF_PROC@ +INCLUDES = @INCLUDES@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPFORWARD = @IPFORWARD@ +KERNEL_METHOD = @KERNEL_METHOD@ +LDFLAGS = @LDFLAGS@ +LIBPAM = @LIBPAM@ +LIBS = @LIBS@ +LIB_IPV6 = @LIB_IPV6@ +LIB_REGEX = @LIB_REGEX@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MULTIPATH_NUM = @MULTIPATH_NUM@ +OBJEXT = @OBJEXT@ +OSPF6D = @OSPF6D@ +OSPFD = @OSPFD@ +OTHER_METHOD = @OTHER_METHOD@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +RIPD = @RIPD@ +RIPNGD = @RIPNGD@ +RTREAD_METHOD = @RTREAD_METHOD@ +RT_METHOD = @RT_METHOD@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VTYSH = @VTYSH@ +ZEBRA = @ZEBRA@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +info_TEXINFOS = zebra.texi + +zebra_TEXINFOS = appendix.texi basic.texi bgpd.texi filter.texi install.texi \ + ipv6.texi kernel.texi main.texi ospf6d.texi ospfd.texi overview.texi \ + protocol.texi ripd.texi ripngd.texi routemap.texi snmp.texi vtysh.texi + + +man_MANS = vtysh.1 bgpd.8 ospf6d.8 ospfd.8 ripd.8 ripngd.8 zebra.8 + +EXTRA_DIST = BGP-TypeCode draft-zebra-00.ms draft-zebra-00.txt $(man_MANS) +subdir = doc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +am__TEXINFO_TEX_DIR = $(srcdir) +INFO_DEPS = zebra.info +DVIS = zebra.dvi +PDFS = zebra.pdf +PSS = zebra.ps +TEXINFOS = zebra.texi + +NROFF = nroff +MANS = $(man_MANS) +DIST_COMMON = $(zebra_TEXINFOS) ChangeLog Makefile.am Makefile.in \ + texinfo.tex +all: all-am + +.SUFFIXES: +.SUFFIXES: .dvi .info .pdf .ps .texi +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +.texi.info: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + `test -f '$<' || echo '$(srcdir)/'`$< -o $@ + +.texi.dvi: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2DVI) `test -f '$<' || echo '$(srcdir)/'`$< + +.texi.pdf: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2PDF) `test -f '$<' || echo '$(srcdir)/'`$< +zebra.info: zebra.texi $(zebra_TEXINFOS) +zebra.dvi: zebra.texi $(zebra_TEXINFOS) +zebra.pdf: zebra.texi $(zebra_TEXINFOS) +TEXI2DVI = texi2dvi + +TEXI2PDF = $(TEXI2DVI) --pdf --batch +DVIPS = dvips +.dvi.ps: + $(DVIPS) $< -o $@ + +uninstall-info-am: + $(PRE_UNINSTALL) + @if (install-info --version && \ + install-info --version | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + echo " install-info --info-dir=$(DESTDIR)$(infodir) --remove $(DESTDIR)$(infodir)/$$file"; \ + install-info --info-dir=$(DESTDIR)$(infodir) --remove $(DESTDIR)$(infodir)/$$file; \ + done; \ + else :; fi + @$(NORMAL_UNINSTALL) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + (if cd $(DESTDIR)$(infodir); then \ + echo " rm -f $$file $$file-[0-9] $$file-[0-9][0-9])"; \ + rm -f $$file $$file-[0-9] $$file-[0-9][0-9]; \ + else :; fi); \ + done + +dist-info: $(INFO_DEPS) + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + for file in $$d/$$base*; do \ + relfile=`expr "$$file" : "$$d/\(.*\)"`; \ + test -f $(distdir)/$$relfile || \ + cp -p $$file $(distdir)/$$relfile; \ + done; \ + done + +mostlyclean-aminfo: + -rm -f zebra.aux zebra.cp zebra.cps zebra.fn zebra.ky zebra.log zebra.op \ + zebra.pg zebra.tmp zebra.toc zebra.tp zebra.vr zebra.dvi \ + zebra.pdf zebra.ps + +maintainer-clean-aminfo: + list='$(INFO_DEPS)'; for i in $$list; do \ + rm -f $$i; \ + if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \ + rm -f $$i-[0-9]*; \ + fi; \ + done + +man1dir = $(mandir)/man1 +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done + +man8dir = $(mandir)/man8 +install-man8: $(man8_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-info +check-am: all-am +check: check-am +all-am: Makefile $(INFO_DEPS) $(MANS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(infodir) $(DESTDIR)$(man1dir) $(DESTDIR)$(man8dir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: $(DVIS) + +info: info-am + +info-am: $(INFO_DEPS) + +install-data-am: install-info-am install-man + +install-exec-am: + +install-info: install-info-am + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(infodir) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + for ifile in echo $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9]; do \ + if test -f $$ifile; then \ + relfile=`expr "$$ifile" : "$$d/\(.*\)"`; \ + echo " $(INSTALL_DATA) $$ifile $(DESTDIR)$(infodir)/$$relfile"; \ + $(INSTALL_DATA) $$ifile $(DESTDIR)$(infodir)/$$relfile; \ + else : ; fi; \ + done; \ + done + @$(POST_INSTALL) + @if (install-info --version && \ + install-info --version | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ + install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ + done; \ + else : ; fi +install-man: install-man1 install-man8 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-aminfo \ + maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-aminfo mostlyclean-generic + +pdf: pdf-am + +pdf-am: $(PDFS) + +ps: ps-am + +ps-am: $(PSS) + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 uninstall-man8 + +.PHONY: all all-am check check-am clean clean-generic dist-info \ + distclean distclean-generic distdir dvi dvi-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man1 install-man8 install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-aminfo maintainer-clean-generic mostlyclean \ + mostlyclean-aminfo mostlyclean-generic pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-info-am uninstall-man \ + uninstall-man1 uninstall-man8 + + +draft-zebra-00.txt: + groff -T ascii -ms draft-zebra-00.ms > draft-zebra-00.txt +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/appendix.texi b/doc/appendix.texi new file mode 100644 index 00000000..7a052bcd --- /dev/null +++ b/doc/appendix.texi @@ -0,0 +1,238 @@ +@node Packet Binary Dump Format, , Zebra Protocol, Top +@comment node-name, next, previous, up +@appendix Packet Binary Dump Format + + Zebra can dump routing protocol packet into file with a binary format +(@pxref{Dump BGP packets and table}). + + It seems to be better that we share the MRT's header format for +backward compatibility with MRT's dump logs. We should also define the +binary format excluding the header, because we must support both IP +v4 and v6 addresses as socket addresses and / or routing entries. + + In the last meeting, we discussed to have a version field in the +header. But Masaki told us that we can define new `type' value rather +than having a `version' field, and it seems to be better because we +don't need to change header format. + + Here is the common header format. This is same as that of MRT. + +@example +@group +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Time | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type | Subtype | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Length | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + + If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE, and +Address Family == IP (version 4) + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source AS number | Destination AS number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Interface Index | Address Family | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Old State | New State | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +Where State is the value defined in RFC1771. + +If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE, +and Address Family == IP version 6 + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source AS number | Destination AS number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Interface Index | Address Family | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Old State | New State | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_MESSAGE, +and Address Family == IP (version 4) + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source AS number | Destination AS number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Interface Index | Address Family | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| BGP Message Packet | +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +Where BGP Message Packet is the whole contents of the +BGP4 message including header portion. + +If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_MESSAGE, +and Address Family == IP version 6 + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source AS number | Destination AS number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Interface Index | Address Family | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Source IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination IP address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| BGP Message Packet | +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_ENTRY, +and Address Family == IP (version 4) + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| View # | Status | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Time Last Change | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Address Family | SAFI | Next-Hop-Len | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Next Hop Address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Prefix Length | Address Prefix [variable] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Attribute Length | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| BGP Attribute [variable length] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_ENTRY, +and Address Family == IP version 6 + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| View # | Status | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Time Last Change | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Address Family | SAFI | Next-Hop-Len | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Next Hop Address | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Next Hop Address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Next Hop Address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Next Hop Address (Cont'd) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Prefix Length | Address Prefix [variable] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Address Prefix (cont'd) [variable] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Attribute Length | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| BGP Attribute [variable length] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + + BGP4 Attribute must not contain MP_UNREACH_NLRI. + If BGP Attribute has MP_REACH_NLRI field, it must has + zero length NLRI, e.g., MP_REACH_NLRI has only Address + Family, SAFI and next-hop values. + +If `type' is PROTOCOL_BGP4MP and `subtype' is BGP4MP_SNAPSHOT, + +@example +@group + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| View # | File Name [variable] | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + + The file specified in "File Name" contains all routing entries, + which are in the format of ``subtype == BGP4MP_ENTRY''. + +@example +@group +Constants: + /* type value */ + #define MSG_PROTOCOL_BGP4MP 16 + /* subtype value */ + #define BGP4MP_STATE_CHANGE 0 + #define BGP4MP_MESSAGE 1 + #define BGP4MP_ENTRY 2 + #define BGP4MP_SNAPSHOT 3 +@end group +@end example diff --git a/doc/basic.texi b/doc/basic.texi new file mode 100644 index 00000000..8812b78c --- /dev/null +++ b/doc/basic.texi @@ -0,0 +1,510 @@ +@node Basic commands +@comment node-name, next, previous, up +@chapter Basic commands + +There are five routing daemons in use, and there is one manager daemon. +These daemons may be located on separate machines from the manager +daemon. Each of these daemons will listen on a particular port for +incoming VTY connections. The routing daemons are: + +@itemize @bullet +@item @command{ripd}, @command{ripngd}, @command{ospfd}, @command{ospf6d}, @command{bgpd} +@item @command{zebra} +@end itemize + +The following sections discuss commands common to all the routing +daemons. + +@menu +* Config Commands:: Commands used in config files +* Common Invocation Options:: Starting the daemons +* Virtual Terminal Interfaces:: Interacting with the daemons +@end menu + + + +@node Config Commands, Common Invocation Options, Basic commands, Basic commands +@comment node-name, next, previous, up +@section Config Commands + +@cindex Configuration files for running the software +@c A -not configuration files for installing the software +@cindex Files for running configurations +@cindex Modifying the herd's behavior +@cindex Getting the herd running + + +@menu +* Basic Config Commands:: Some of the generic config commands +* Sample Config File:: An example config file +@end menu + + +In a config file, you can write the debugging options, a vty's password, +routing daemon configurations, a log file name, and so forth. This +information forms the initial command set for a routing beast as it is +starting. + +Config files are generally found in: + +@itemize @asis +@item @file{@value{INSTALL_PREFIX_ETC}/*.conf} +@end itemize + +Each of the daemons has its own +config file. For example, zebra's default config file name is: + +@itemize @asis +@item @file{@value{INSTALL_PREFIX_ETC}/zebra.conf} +@end itemize + +The daemon name plus @file{.conf} is the default config file name. You +can specify a config file using the @kbd{-f} or @kbd{--config-file} +options when starting the daemon. + + + +@node Basic Config Commands, Sample Config File, Config Commands, Config Commands +@comment node-name, next, previous, up +@subsection Basic Config Commands + +@deffn Command {hostname @var{hostname}} {} +Set hostname of the router. +@end deffn + +@deffn Command {password @var{password}} {} +Set password for vty interface. If there is no password, a vty won't +accept connections. +@end deffn + +@deffn Command {enable password @var{password}} {} +Set enable password. +@end deffn + +@deffn Command {log stdout} {} +@deffnx Command {no log stdout} {} +Set logging output to stdout. +@end deffn + +@deffn Command {log file @var{filename}} {} +If you want to log into a file please specify @code{filename} as +follows. +@example +log file /usr/local/etc/bgpd.log +@end example +@end deffn + +@deffn Command {log syslog} {} +@deffnx Command {no log syslog} {} +Set logging output to syslog. +@end deffn + +@deffn Command {write terminal} {} +Displays the current configuration to the vty interface. +@end deffn + +@deffn Command {write file} {} +Write current configuration to configuration file. +@end deffn + +@deffn Command {configure terminal} {} +Change to configuration mode. This command is the first step to +configuration. +@end deffn + +@deffn Command {terminal length @var{<0-512>}} {} +Set terminal display length to @var{<0-512>}. If length is 0, no +display control is performed. +@end deffn + +@deffn Command {who} {} +@end deffn + +@deffn Command {list} {} +List commands. +@end deffn + +@deffn Command {service password-encryption} {} +Encrypt password. +@end deffn + +@deffn Command {service advanced-vty} {} +Enable advanced mode VTY. +@end deffn + +@deffn Command {service terminal-length @var{<0-512>}} {} +Set system wide line configuration. This configuration command applies +to all VTY interfaces. +@end deffn + +@deffn Command {show version} {} +Show the current version of the Zebra and its build host information. +@end deffn + +@deffn Command {line vty} {} +Enter vty configuration mode. +@end deffn + +@deffn Command {banner motd default} {} +Set default motd string. +@end deffn + +@deffn Command {no banner motd} {} +No motd banner string will be printed. +@end deffn + +@deffn {Line Command} {exec-timeout @var{minute}} {} +@deffnx {Line Command} {exec-timeout @var{minute} @var{second}} {} +Set VTY connection timeout value. When only one argument is specified +it is used for timeout value in minutes. Optional second argument is +used for timeout value in seconds. Default timeout value is 10 minutes. +When timeout value is zero, it means no timeout. +@end deffn + +@deffn {Line Command} {no exec-timeout} {} +Do not perform timeout at all. This command is as same as +@command{exec-timeout 0 0}. +@end deffn + +@deffn {Line Command} {access-class @var{access-list}} {} +Restrict vty connections with an access list. +@end deffn + + + +@node Sample Config File, , Basic Config Commands, Config Commands +@comment node-name, next, previous, up +@subsection Sample Config File + + +Below is a sample configuration file for the zebra daemon. + +@example +@group +! +! Zebra configuration file +! +hostname Router +password zebra +enable password zebra +! +log stdout +! +! +@end group +@end example + +'!' and '#' are comment characters. If the first character of the word +is one of the comment characters then from the rest of the line forward +will be ignored as a comment. + +@example +password zebra!password +@end example + +If a comment character is not the first character of the word, it's a +normal character. So in the above example '!' will not be regarded as a +comment and the password is set to 'zebra!password'. + + + +@node Common Invocation Options, Virtual Terminal Interfaces, Config Commands, Basic commands +@comment node-name, next, previous, up +@section Common Invocation Options +@c COMMON_OPTIONS +@c OPTIONS section of the man page + +These options apply to all Zebra daemons. + +@table @samp + +@item -d +@itemx --daemon +Runs in daemon mode. + +@item -f @var{file} +@itemx --config_file=@var{file} +Set configuration file name. + +@item -h +@itemx --help +Display this help and exit. + +@item -i @var{file} +@itemx --pid_file=@var{file} + +Upon startup the process identifier of the daemon is written to a file, +typically in @file{/var/run}. This file can be used by the init system +to implement commands such as @command{@dots{}/init.d/zebra status}, +@command{@dots{}/init.d/zebra restart} or @command{@dots{}/init.d/zebra +stop}. + +The file name is an run-time option rather than a configure-time option +so that multiple routing daemons can be run simultaneously. This is +useful when using Zebra to implement a routing looking glass. One +machine can be used to collect differing routing views from differing +points in the network. + +@item -P @var{port} +@itemx --vty_port=@var{port} +Set the VTY port number. + +@item -v +@itemx --version +Print program version. + +@end table + + + +@node Virtual Terminal Interfaces, , Common Invocation Options, Basic commands +@comment node-name, next, previous, up +@section Virtual Terminal Interfaces + +VTY -- Virtual Terminal [aka TeletYpe] Interface is a command line +interface (CLI) for user interaction with the routing daemon. + +@menu +* VTY Overview:: Basics about VTYs +* VTY Modes:: View, Enable, and Other VTY modes +* VTY CLI Commands:: Commands for movement, edition, and management +@end menu + + + +@node VTY Overview, VTY Modes, Virtual Terminal Interfaces, Virtual Terminal Interfaces +@comment node-name, next, previous, up +@subsection VTY Overview + + +VTY stands for Virtual TeletYpe interface. It means you can connect to +the daemon via the telnet protocol. + +To enable a VTY interface, you have to setup a VTY password. If there +is no VTY password, one cannot connect to the VTY interface at all. + +@example +@group +% telnet localhost 2601 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. + +Hello, this is zebra (version @value{VERSION}) +Copyright 1997-2000 Kunihiro Ishiguro + + +User Access Verification + +Password: XXXXX +Router> ? + enable Turn on privileged commands + exit Exit current mode and down to previous mode + help Description of the interactive help system + list Print command list + show Show running system information + who Display who is on a vty +Router> enable +Password: XXXXX +Router# configure terminal +Router(config)# interface eth0 +Router(config-if)# ip address 10.0.0.1/8 +Router(config-if)# ^Z +Router# +@end group +@end example + +'?' is very useful for looking up commands. + + + +@node VTY Modes, VTY CLI Commands, VTY Overview, Virtual Terminal Interfaces +@comment node-name, next, previous, up +@subsection VTY Modes + + +There are three basic VTY modes: + +@menu +* VTY View Mode:: Mode for read-only interaction +* VTY Enable Mode:: Mode for read-write interaction +* VTY Other Modes:: Special modes (tftp, etc) +@end menu + +There are commands that may be restricted to specific VTY modes. + + + +@node VTY View Mode, VTY Enable Mode, VTY Modes, VTY Modes +@comment node-name, next, previous, up +@subsubsection VTY View Mode +@c to be written (gpoul) + + +This mode is for read-only access to the CLI. One may exit the mode by +leaving the system, or by entering @code{enable} mode. + + + +@node VTY Enable Mode, VTY Other Modes, VTY View Mode, VTY Modes +@comment node-name, next, previous, up +@subsubsection VTY Enable Mode + + +@c to be written (gpoul) +This mode is for read-write access to the CLI. One may exit the mode by +leaving the system, or by escaping to view mode. + + + +@node VTY Other Modes, , VTY Enable Mode, VTY Modes +@comment node-name, next, previous, up +@subsubsection VTY Other Modes + + +@c to be written (gpoul) +This page is for describing other modes. + +@node VTY CLI Commands, , VTY Modes, Virtual Terminal Interfaces +@comment node-name, next, previous, up +@subsection VTY CLI Commands + + +Commands that you may use at the command-line are described in the following three subsubsections. + +@menu +* CLI Movement Commands:: Commands for moving the cursor about +* CLI Editing Commands:: Commands for changing text +* CLI Advanced Commands:: Other commands, session management and so on +@end menu + + + +@node CLI Movement Commands, CLI Editing Commands, VTY CLI Commands, VTY CLI Commands +@comment node-name, next, previous, up +@subsubsection CLI Movement Commands + + +These commands are used for moving the CLI cursor. The @key{C} character +means press the Control Key. + +@table @kbd + +@item C-f +@itemx @key{RIGHT} +@kindex C-f +@kindex @key{RIGHT} +Move forward one character. + +@item C-b +@itemx @key{LEFT} +@kindex C-b +@kindex @key{LEFT} +Move backward one character. + +@item M-f +@kindex M-f +Move forward one word. + +@item M-b +@kindex M-b +Move backward one word. + +@item C-a +@kindex C-a +Move to the beginning of the line. + +@item C-e +@kindex C-e +Move to the end of the line. + +@end table + + + +@node CLI Editing Commands, CLI Advanced Commands, CLI Movement Commands, VTY CLI Commands +@comment node-name, next, previous, up +@subsubsection CLI Editing Commands + + +These commands are used for editing text on a line. The @key{C} +character means press the Control Key. + +@table @kbd + +@item C-h +@itemx @key{DEL} +@kindex C-h +@kindex @key{DEL} +Delete the character before point. + +@item C-d +@kindex C-d +Delete the character after point. + +@item M-d +@kindex M-d +Forward kill word. + +@item C-w +@kindex C-w +Backward kill word. + +@item C-k +@kindex C-k +Kill to the end of the line. + +@item C-u +@kindex C-u +Kill line from the beginning, erasing input. + +@item C-t +@kindex C-t +Transpose character. + +@end table + + + +@node CLI Advanced Commands, , CLI Editing Commands, VTY CLI Commands +@comment node-name, next, previous, up +@subsubsection CLI Advanced Commands + + +There are several additional CLI commands for command line completions, +insta-help, and VTY session management. + +@table @kbd + +@item C-c +@kindex C-c +Interrupt current input and moves to the next line. + +@item C-z +@kindex C-z +End current configuration session and move to top node. + + +@item C-n +@itemx @key{DOWN} +@kindex C-n +@kindex @key{DOWN} +Move down to next line in the history buffer. + +@item C-p +@itemx @key{UP} +@kindex C-p +@kindex @key{UP} +Move up to previous line in the history buffer. + +@item TAB +@kindex @key{TAB} +Use command line completion by typing @key{TAB}. + +@item +@kindex ? +You can use command line help by typing @code{help} at the beginning of +the line. Typing @kbd{?} at any point in the line will show possible +completions. + +@end table diff --git a/doc/bgpd.8 b/doc/bgpd.8 new file mode 100644 index 00000000..cba3bdac --- /dev/null +++ b/doc/bgpd.8 @@ -0,0 +1,169 @@ +.TH BGPD 8 "July 2000" "Zebra Beast - BGPD" "Version 0.88" + +.SH NAME +bgpd \- a BGPv4, BGPv4+, BGPv4- routing engine for use with Zebra + +.SH SYNOPSIS +.B bgpd +[ +.B \-dhpPv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-p bgp-port-number +] +[ +.B \--bgp_port=port-number +] +[ +.B \-P vty-port-number +] + +.SH DESCRIPTION +.B bgpd +is a routing component that works with the +.B zebra +routing engine. + + +.SH OPTIONS + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this +option will likely default to \fB\fI/usr/local/etc/bgpd.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When bgpd starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart bgpd. The likely default is \fB\fI/var/run/bgpd.pid\fR. + +.TP +\fB\-p\fR, \fB\-\-bgp_port=\fR\fIport\fR +Set the port that bgpd will listen to for bgp data. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the bgpd VTY will listen on. This defaults to +2605, as specified in \fI/etc/services\fR. + +.TP +\fB\-r\fR, \fB\-\-retain\fR +When the program terminates, retain routes added by \fBbgpd\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB router zebra \fR -- (Move routes into kernel table) +\fB router bgp [AS-NUMBER] \fR + +\fB bgp router-id [BGP-ROUTER-ID] \fR + +\fB network [NETWORK] area [BGP-AREA-ID] \fR +\fB no network [NETWORK] \fR + +\fB aggregate-address [NETWORK] \fR + +\fB neighbor [PEER-IP-ADDRESS] remote-as [REMOTE-AS] \fR +\fB neighbor [PEER-IP-ADDRESS] version [ 4 | 4+ | 4- ] \fR + +\fB neighbor [PEER-IP-ADDRESS] description \fR +\fB no neighbor [PEER-IP-ADDRESS] description \fR + +\fB neighbor [PEER-IP-ADDRESS] route-map [in | out] \fR +\fB neighbor [PEER-IP-ADDRESS] distribute-list [in | out] \fR +\fB neighbor [PEER-IP-ADDRESS] next-hop-self \fR +\fB neighbor [PEER-IP-ADDRESS] weight [WEIGHT] \fR +\fB neighbor [PEER-IP-ADDRESS] default-originate \fR +\fB neighbor [PEER-IP-ADDRESS] ebgp-multihop \fR + +\fB neighbor [PEER-IP-ADDRESS] shutdown \fR +\fB no neighbor [PEER-IP-ADDRESS] shutdown \fR + +\fB clear ip bgp [PEER-IP-ADDRESS] \fR + +\fB show ip bgp [NETWORK] \fR +\fB show ip bgp reg-exp [AS-REGEXP] \fR +\fB show ip bgp summary \fR +\fB show ip bgp neighbor [PEER-IP-ADDRESS] \fR +\fB show ip bgp route \fR + +\fB show debug \fR + +\fB debug bgp \fR +\fB debug event \fR +\fB debug update \fR +\fB debug keepalive \fR + +\fB no debug event \fR +\fB no debug update \fR +\fB no debug keepalive \fR + + +.SH FILES + +.TP +.BI /usr/local/sbin/bgpd +The default location of the +.B bgpd +binary. + +.TP +.BI /usr/local/etc/bgpd.conf +The default location of the +.B bgpd +config file. + +.TP +.BI $(PWD)/bgpd.log +If the +.B bgpd +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBbgpd\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line +options, and for config file commands. The definitive document is the +Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The bgpd process may log to standard output, to a VTY, to a log +file, or through syslog to the system logs. \fBbgpd\fR supports many +debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripd(8), ripngd(8), ospfd(8), ospf6d(8), zebra(8), vtysh(1) + + +.SH BUGS +.B bgpd +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/bgpd.texi b/doc/bgpd.texi new file mode 100644 index 00000000..c10fba96 --- /dev/null +++ b/doc/bgpd.texi @@ -0,0 +1,1288 @@ +@c -*-texinfo-*- +@c This is part of the GNU Zebra Manual. +@c Copyright (C) 1999, 2000, 2001 2002 Kunihiro Ishiguro +@c See file zebra.texi for copying conditions. +@node BGP +@comment node-name, next, previous, up +@chapter BGP + + BGP stands for a Border Gateway Protocol. The lastest BGP version +is 4. It is referred as BGP-4. BGP-4 is one of the Exterior Gateway +Protocols and de-fact standard of Inter Domain routing protocol. +BGP-4 is described in @code{RFC1771} - @cite{A Border Gateway Protocol +4 (BGP-4)}. + + Many extentions are added to @code{RFC1771}. @code{RFC2858} - +@cite{Multiprotocol Extensions for BGP-4} provide multiprotocol +support to BGP-4. + +@menu +* Starting BGP:: +* BGP router:: +* BGP network:: +* BGP Peer:: +* BGP Peer Group:: +* BGP Address Family:: +* Autonomous System:: +* BGP Communities Attribute:: +* BGP Extended Communities Attribute:: +* Displaying BGP routes:: +* Capability Negotiation:: +* Route Reflector:: +* Route Server:: +* How to set up a 6-Bone connection:: +* Dump BGP packets and table:: +@end menu + +@node Starting BGP, BGP router, BGP, BGP +@comment node-name, next, previous, up +@section Starting BGP + +Default configuration file of @command{bgpd} is @file{bgpd.conf}. +@command{bgpd} searches the current directory first then +@value{INSTALL_PREFIX_ETC}/bgpd.conf. All of bgpd's command must be +configured in @file{bgpd.conf}. + +@command{bgpd} specific invocation options are described below. Common +options may also be specified (@pxref{Common Invocation Options}). + +@table @samp +@item -p @var{PORT} +@itemx --bgp_port=@var{PORT} +Set the bgp protocol's port number. + +@item -r +@itemx --retain +When program terminates, retain BGP routes added by zebra. +@end table + +@node BGP router, BGP network, Starting BGP, BGP +@comment node-name, next, previous, up +@section BGP router + + First of all you must configure BGP router with @command{router bgp} +command. To configure BGP router, you need AS number. AS number is an +identification of autonomous system. BGP protocol uses the AS number +for detecting whether the BGP connection is internal one or external one. + +@deffn Command {router bgp @var{asn}} {} +Enable a BGP protocol process with the specified @var{asn}. After +this statement you can input any @code{BGP Commands}. You can not +create different BGP process under different @var{asn} without +specifying @code{multiple-instance} (@pxref{Multiple instance}). +@end deffn + +@deffn Command {no router bgp @var{asn}} {} +Destroy a BGP protocol process with the specified @var{asn}. +@end deffn + +@deffn {BGP} {bgp router-id @var{A.B.C.D}} {} +This command specifies the router-ID. If @command{bgpd} connects to @command{zebra} it gets +interface and address information. In that case default router ID value +is selected as the largest IP Address of the interfaces. When +@code{router zebra} is not enabled @command{bgpd} can't get interface information +so @code{router-id} is set to 0.0.0.0. So please set router-id by hand. +@end deffn + +@menu +* BGP distance:: +* BGP decision process:: +@end menu + +@node BGP distance, BGP decision process, BGP router, BGP router +@comment node-name, next, previous, up +@subsection BGP distance + +@deffn {BGP} {distance bgp <1-255> <1-255> <1-255>} {} +This command change distance value of BGP. Each argument is distance +value for external routes, internal routes and local routes. +@end deffn + +@deffn {BGP} {distance <1-255> @var{A.B.C.D/M}} {} +@deffnx {BGP} {distance <1-255> @var{A.B.C.D/M} @var{word}} {} +This command set distance value to +@end deffn + +@node BGP decision process, , BGP distance, BGP router +@comment node-name, next, previous, up +@subsection BGP decision process + +@table @asis +@item 1. Weight check + +@item 2. Local preference check. + +@item 3. Local route check. + +@item 4. AS path length check. + +@item 5. Origin check. + +@item 6. MED check. +@end table + +@node BGP network, BGP Peer, BGP router, BGP +@comment node-name, next, previous, up +@section BGP network + +@menu +* BGP route:: +* Route Aggregation:: +* Redistribute to BGP:: +@end menu + +@node BGP route, Route Aggregation, BGP network, BGP network +@comment node-name, next, previous, up +@subsection BGP route + +@deffn {BGP} {network @var{A.B.C.D/M}} {} +This command adds the announcement network. +@example +@group +router bgp 1 + network 10.0.0.0/8 +@end group +@end example +This configuration example says that network 10.0.0.0/8 will be +announced to all neighbors. Some vendors' routers don't advertise +routes if they aren't present in their IGP routing tables; @code{bgp} +doesn't care about IGP routes when announcing its routes. +@end deffn + +@deffn {BGP} {no network @var{A.B.C.D/M}} {} +@end deffn + +@node Route Aggregation, Redistribute to BGP, BGP route, BGP network +@comment node-name, next, previous, up +@subsection Route Aggregation + +@deffn {BGP} {aggregate-address @var{A.B.C.D/M}} {} +This command specifies an aggregate address. +@end deffn + +@deffn {BGP} {aggregate-address @var{A.B.C.D/M} as-set} {} +This command specifies an aggregate address. Resulting routes inlucde +AS set. +@end deffn + +@deffn {BGP} {aggregate-address @var{A.B.C.D/M} summary-only} {} +This command specifies an aggregate address. Aggreated routes will +not be announce. +@end deffn + +@deffn {BGP} {no aggregate-address @var{A.B.C.D/M}} {} +@end deffn + +@node Redistribute to BGP, , Route Aggregation, BGP network +@comment node-name, next, previous, up +@subsection Redistribute to BGP + +@deffn {BGP} {redistribute kernel} {} +Redistribute kernel route to BGP process. +@end deffn + +@deffn {BGP} {redistribute static} {} +Redistribute static route to BGP process. +@end deffn + +@deffn {BGP} {redistribute connected} {} +Redistribute connected route to BGP process. +@end deffn + +@deffn {BGP} {redistribute rip} {} +Redistribute RIP route to BGP process. +@end deffn + +@deffn {BGP} {redistribute ospf} {} +Redistribute OSPF route to BGP process. +@end deffn + +@node BGP Peer, BGP Peer Group, BGP network, BGP +@comment node-name, next, previous, up +@section BGP Peer + +@menu +* Defining Peer:: +* BGP Peer commands:: +* Peer filtering:: +@end menu + +@node Defining Peer, BGP Peer commands, BGP Peer, BGP Peer +@comment node-name, next, previous, up +@subsection Defining Peer + +@deffn {BGP} {neighbor @var{peer} remote-as @var{asn}} {} +Creates a new neighbor whose remote-as is @var{asn}. @var{peer} +can be an IPv4 address or an IPv6 address. +@example +@group +router bgp 1 + neighbor 10.0.0.1 remote-as 2 +@end group +@end example +In this case my router, in AS-1, is trying to peer with AS-2 at +10.0.0.1. + +This command must be the first command used when configuring a neighbor. +If the remote-as is not specified, @command{bgpd} will complain like this: +@example +can't find neighbor 10.0.0.1 +@end example +@end deffn + +@node BGP Peer commands, Peer filtering, Defining Peer, BGP Peer +@comment node-name, next, previous, up +@subsection BGP Peer commands + +In a @code{router bgp} clause there are neighbor specific configurations +required. + +@deffn {BGP} {neighbor @var{peer} shutdown} {} +@deffnx {BGP} {no neighbor @var{peer} shutdown} {} +Shutdown the peer. We can delete the neighbor's configuration by +@code{no neighbor @var{peer} remote-as @var{as-number}} but all +configuration of the neighbor will be deleted. When you want to +preserve the configuration, but want to drop the BGP peer, use this +syntax. +@end deffn + +@deffn {BGP} {neighbor @var{peer} ebgp-multihop} {} +@deffnx {BGP} {no neighbor @var{peer} ebgp-multihop} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} description ...} {} +@deffnx {BGP} {no neighbor @var{peer} description ...} {} +Set description of the peer. +@end deffn + +@deffn {BGP} {neighbor @var{peer} version @var{version}} {} +Set up the neighbor's BGP version. @var{version} can be @var{4}, +@var{4+} or @var{4-}. BGP version @var{4} is the default value used for +BGP peering. BGP version @var{4+} means that the neighbor supports +Multiprotocol Extensions for BGP-4. BGP version @var{4-} is similar but +the neighbor speaks the old Internet-Draft revision 00's Multiprotocol +Extensions for BGP-4. Some routing software is still using this +version. +@end deffn + +@deffn {BGP} {neighbor @var{peer} interface @var{ifname}} {} +@deffnx {BGP} {no neighbor @var{peer} interface @var{ifname}} {} +When you connect to a BGP peer over an IPv6 link-local address, you have +to specify the @var{ifname} of the interface used for the connection. +@end deffn + +@deffn {BGP} {neighbor @var{peer} next-hop-self} {} +@deffnx {BGP} {no neighbor @var{peer} next-hop-self} {} +This command specifies an announced route's nexthop as being equivalent +to the address of the bgp router. +@end deffn + +@deffn {BGP} {neighbor @var{peer} update-source} {} +@deffnx {BGP} {no neighbor @var{peer} update-source} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} default-originate} {} +@deffnx {BGP} {no neighbor @var{peer} default-originate} {} +@command{bgpd}'s default is to not announce the default route (0.0.0.0/0) even it +is in routing table. When you want to announce default routes to the +peer, use this command. +@end deffn + +@deffn {BGP} {neighbor @var{peer} port @var{port}} {} +@deffnx {BGP} {neighbor @var{peer} port @var{port}} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} send-community} {} +@deffnx {BGP} {neighbor @var{peer} send-community} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} weight @var{weight}} {} +@deffnx {BGP} {no neighbor @var{peer} weight @var{weight}} {} +This command specifies a default @var{weight} value for the neighbor's +routes. +@end deffn + +@deffn {BGP} {neighbor @var{peer} maximum-prefix @var{number}} {} +@deffnx {BGP} {no neighbor @var{peer} maximum-prefix @var{number}} {} +@end deffn + +@node Peer filtering, , BGP Peer commands, BGP Peer +@comment node-name, next, previous, up +@subsection Peer filtering + +@deffn {BGP} {neighbor @var{peer} distribute-list @var{name} [in|out]} {} +This command specifies a distribute-list for the peer. @var{direct} is +@samp{in} or @samp{out}. +@end deffn + +@deffn {BGP command} {neighbor @var{peer} prefix-list @var{name} [in|out]} {} +@end deffn + +@deffn {BGP command} {neighbor @var{peer} filter-list @var{name} [in|out]} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} route-map @var{name} [in|out]} {} +Apply a route-map on the neighbor. @var{direct} must be @code{in} or +@code{out}. +@end deffn + +@c ----------------------------------------------------------------------- +@node BGP Peer Group, BGP Address Family, BGP Peer, BGP +@comment node-name, next, previous, up +@section BGP Peer Group + +@deffn {BGP} {neighbor @var{word} peer-group} {} +This command defines a new peer group. +@end deffn + +@deffn {BGP} {neighbor @var{peer} peer-group @var{word}} {} +This command bind specific peer to peer group @var{word}. +@end deffn + +@node BGP Address Family, Autonomous System, BGP Peer Group, BGP +@comment node-name, next, previous, up +@section BGP Address Family + + + +@page +@c ----------------------------------------------------------------------- +@node Autonomous System, BGP Communities Attribute, BGP Address Family, BGP +@comment node-name, next, previous, up +@section Autonomous System + + AS (Autonomous System) is one of the essential element of BGP. BGP +is a distance vector routing protocol. AS framework provides distance +vector metric and loop detection to BGP. @code{RFC1930} - +@cite{Guidelines for creation, selection, and registration of an +Autonomous System (AS)} describes how to use AS. + + AS number is tow octet digita value. So the value range is from 1 +to 65535. AS numbers 64512 through 65535 are defined as private AS +numbers. Private AS numbers must not to be advertised in the global +Internet. + +@menu +* AS Path Regular Expression:: +* Display BGP Routes by AS Path:: +* AS Path Access List:: +* Using AS Path in Route Map:: +* Private AS Numbers:: +@end menu + +@node AS Path Regular Expression, Display BGP Routes by AS Path, Autonomous System, Autonomous System +@comment node-name, next, previous, up +@subsection AS Path Regular Expression + + AS path regular expression can be used for displaying BGP routes and +AS path access list. AS path regular expression is based on +@code{POSIX 1003.2} regular expressions. Following description is +just a subset of @code{POSIX} regular expression. User can use full +@code{POSIX} regular expression. Adding to that special character '_' +is added for AS path regular expression. + +@table @code +@item . +Matches any single character. +@item * +Matches 0 or more occurrences of pattern. +@item + +Matches 1 or more occurrences of pattern. +@item ? +Match 0 or 1 occurrences of pattern. +@item ^ +Matches the beginning of the line. +@item $ +Matches the end of the line. +@item _ +Character @code{_} has special meanings in AS path regular expression. +It matches to space and comma , and AS set delimiter @{ and @} and AS +confederation delimiter @code{(} and @code{)}. And it also matches to +the beginning of the line and the end of the line. So @code{_} can be +used for AS value boundaries match. @code{show ip bgp regexp _7675_} +matches to all of BGP routes which as AS number include @var{7675}. +@end table + +@node Display BGP Routes by AS Path, AS Path Access List, AS Path Regular Expression, Autonomous System +@comment node-name, next, previous, up +@subsection Display BGP Routes by AS Path + + To show BGP routes which has specific AS path information @code{show +ip bgp} command can be used. + +@deffn Command {show ip bgp regexp @var{line}} {} +This commands display BGP routes that matches AS path regular +expression @var{line}. +@end deffn + +@node AS Path Access List, Using AS Path in Route Map, Display BGP Routes by AS Path, Autonomous System +@comment node-name, next, previous, up +@subsection AS Path Access List + + AS path access list is user defined AS path. + +@deffn {Command} {ip as-path access-list @var{word} @{permit|deny@} @var{line}} {} +This command defines a new AS path access list. +@end deffn + +@deffn {Command} {no ip as-path access-list @var{word}} {} +@deffnx {Command} {no ip as-path access-list @var{word} @{permit|deny@} @var{line}} {} +@end deffn + +@node Using AS Path in Route Map, Private AS Numbers, AS Path Access List, Autonomous System +@comment node-name, next, previous, up +@subsection Using AS Path in Route Map + +@deffn {Route Map} {match as-path @var{word}} {} +@end deffn + +@deffn {Route Map} {set as-path prepend @var{as-path}} {} +@end deffn + +@node Private AS Numbers, , Using AS Path in Route Map, Autonomous System +@comment node-name, next, previous, up +@subsection Private AS Numbers + +@page +@c ----------------------------------------------------------------------- +@node BGP Communities Attribute, BGP Extended Communities Attribute, Autonomous System, BGP +@comment node-name, next, previous, up +@section BGP Communities Attribute + + BGP communities attribute is widely used for implementing policy +routing. Network operators can manipulate BGP communities attribute +based on their network policy. BGP communities attribute is defined +in @code{RFC1997} - @cite{BGP Communities Attribute} and +@code{RFC1998} - @cite{An Application of the BGP Community Attribute +in Multi-home Routing}. It is an optional transitive attribute, +therefore local policy can travel through different autonomous system. + + Communities attribute is a set of communities values. Each +communities value is 4 octet long. The following format is used to +define communities value. + +@table @code +@item AS:VAL +This format represents 4 octet communities value. @code{AS} is high +order 2 octet in digit format. @code{VAL} is low order 2 octet in +digit format. This format is useful to define AS oriented policy +value. For example, @code{7675:80} can be used when AS 7675 wants to +pass local policy value 80 to neighboring peer. +@item internet +@code{internet} represents well-known communities value 0. +@item no-export +@code{no-export} represents well-known communities value @code{NO_EXPORT}@* +@r{(0xFFFFFF01)}. All routes carry this value must not be advertised +to outside a BGP confederation boundary. If neighboring BGP peer is +part of BGP confederation, the peer is considered as inside a BGP +confederation boundary, so the route will be announced to the peer. +@item no-advertise +@code{no-advertise} represents well-known communities value +@code{NO_ADVERTISE}@*@r{(0xFFFFFF02)}. All routes carry this value +must not be advertise to other BGP peers. +@item local-AS +@code{local-AS} represents well-known communities value +@code{NO_EXPORT_SUBCONFED} @r{(0xFFFFFF03)}. All routes carry this +value must not be advertised to external BGP peers. Even if the +neighboring router is part of confederation, it is considered as +external BGP peer, so the route will not be announced to the peer. +@end table + + When BGP communities attribute is received, duplicated communities +value in the communities attribute is ignored and each communities +values are sorted in numerical order. + +@menu +* BGP Community Lists:: +* Numbered BGP Community Lists:: +* BGP Community in Route Map:: +* Display BGP Routes by Community:: +* Using BGP Communities Attribute:: +@end menu + +@node BGP Community Lists, Numbered BGP Community Lists, BGP Communities Attribute, BGP Communities Attribute +@comment node-name, next, previous, up +@subsection BGP Community Lists + + BGP community list is a user defined BGP communites attribute list. +BGP community list can be used for matching or manipulating BGP +communities attribute in updates. + + There are two types of community list. One is standard community +list and another is expanded community list. Standard community list +defines communities attribute. Expanded community list defines +communities attribute string with regular expression. Standard +community list is compiled into binary format when user define it. +Standard community list will be directly compared to BGP communities +attribute in BGP updates. Therefore the comparison is faster than +expanded community list. + +@deffn Command {ip community-list standard @var{name} @{permit|deny@} @var{community}} {} +This command defines a new standard community list. @var{community} +is communities value. The @var{community} is compiled into community +structure. We can define multiple community list under same name. In +that case match will happen user defined order. Once the +community list matches to communities attribute in BGP updates it +return permit or deny by the community list definition. When there is +no matched entry, deny will be returned. When @var{community} is +empty it matches to any routes. +@end deffn + +@deffn Command {ip community-list expanded @var{name} @{permit|deny@} @var{line}} {} +This command defines a new expanded community list. @var{line} is a +string expression of communities attribute. @var{line} can include +regular expression to match communities attribute in BGP updates. +@end deffn + +@deffn Command {no ip community-list @var{name}} {} +@deffnx Command {no ip community-list standard @var{name}} {} +@deffnx Command {no ip community-list expanded @var{name}} {} +These commands delete community lists specified by @var{name}. All of +community lists shares a single name space. So community lists can be +removed simpley specifying community lists name. +@end deffn + +@deffn {Command} {show ip community-list} {} +@deffnx {Command} {show ip community-list @var{name}} {} +This command display current community list information. When +@var{name} is specified the specified community list's information is +shown. + +@example +# show ip community-list +Named Community standard list CLIST + permit 7675:80 7675:100 no-export + deny internet +Named Community expanded list EXPAND + permit : + +# show ip community-list CLIST +Named Community standard list CLIST + permit 7675:80 7675:100 no-export + deny internet +@end example +@end deffn + +@node Numbered BGP Community Lists, BGP Community in Route Map, BGP Community Lists, BGP Communities Attribute +@comment node-name, next, previous, up +@subsection Numbered BGP Community Lists + + When number is used for BGP community list name, the number has +special meanings. Community list number in the range from 1 and 99 is +standard community list. Community list number in the range from 100 +to 199 is expanded community list. These community lists are called +as numbered community lists. On the other hand normal community lists +is called as named community lists. + +@deffn Command {ip community-list <1-99> @{permit|deny@} @var{community}} {} +This command defines a new community list. <1-99> is standard +community list number. Community list name within this range defines +standard community list. When @var{community} is empty it matches to +any routes. +@end deffn + +@deffn Command {ip community-list <100-199> @{permit|deny@} @var{community}} {} +This command defines a new community list. <100-199> is expanded +community list number. Community list name within this range defines +expanded community list. +@end deffn + +@deffn Command {ip community-list @var{name} @{permit|deny@} @var{community}} {} +When community list type is not specifed, the community list type is +automatically detected. If @var{community} can be compiled into +communities attribute, the community list is defined as a standard +community list. Otherwise it is defined as an expanded community +list. This feature is left for backward compability. Use of this +feature is not recommended. +@end deffn + +@node BGP Community in Route Map, Display BGP Routes by Community, Numbered BGP Community Lists, BGP Communities Attribute +@comment node-name, next, previous, up +@subsection BGP Community in Route Map + + In Route Map (@pxref{Route Map}), we can match or set BGP +communities attribute. Using this feature network operator can +implement their network policy based on BGP communities attribute. + + Following commands can be used in Route Map. + +@deffn {Route Map} {match community @var{word}} {} +@deffnx {Route Map} {match community @var{word} exact-match} {} +This command perform match to BGP updates using community list +@var{word}. When the one of BGP communities value match to the one of +communities value in community list, it is match. When +@code{exact-match} keyword is spcified, match happen only when BGP +updates have completely same communities value specified in the +community list. +@end deffn + +@deffn {Route Map} {set community none} {} +@deffnx {Route Map} {set community @var{community}} {} +@deffnx {Route Map} {set community @var{community} additive} {} +This command manipulate communities value in BGP updates. When +@code{none} is specified as communities value, it removes entire +communities attribute from BGP updates. When @var{community} is not +@code{none}, specified communities value is set to BGP updates. If +BGP updates already has BGP communities value, the existing BGP +communities value is replaced with specified @var{community} value. +When @code{additive} keyword is specified, @var{community} is appended +to the existing communities value. +@end deffn + +@deffn {Route Map} {set comm-list @var{word} delete} {} +This command remove communities value from BGP communities attribute. +The @var{word} is community list name. When BGP route's communities +value matches to the community list @var{word}, the communities value +is removed. When all of communities value is removed eventually, the +BGP update's communities attribute is completely removed. +@end deffn + +@node Display BGP Routes by Community, Using BGP Communities Attribute, BGP Community in Route Map, BGP Communities Attribute +@comment node-name, next, previous, up +@subsection Display BGP Routes by Community + + To show BGP routes which has specific BGP communities attribute, +@code{show ip bgp} command can be used. The @var{community} value and +community list can be used for @code{show ip bgp} command. + +@deffn Command {show ip bgp community} {} +@deffnx Command {show ip bgp community @var{community}} {} +@deffnx Command {show ip bgp community @var{community} exact-match} {} +@code{show ip bgp community} displays BGP routes which has communities +attribute. When @var{community} is specified, BGP routes that matches +@var{community} value is displayed. For this command, @code{internet} +keyword can't be used for @var{community} value. When +@code{exact-match} is specified, it display only routes that have an +exact match. +@end deffn + +@deffn Command {show ip bgp community-list @var{word}} {} +@deffnx Command {show ip bgp community-list @var{word} exact-match} {} +This commands display BGP routes that matches community list +@var{word}. When @code{exact-match} is specified, display only routes +that have an exact match. +@end deffn + +@node Using BGP Communities Attribute, , Display BGP Routes by Community, BGP Communities Attribute +@comment node-name, next, previous, up +@subsection Using BGP Communities Attribute + + Following configuration is the most typical usage of BGP communities +attribute. AS 7675 provides upstream Internet connection to AS 100. +When following configuration exists in AS 7675, AS 100 networks +operator can set local preference in AS 7675 network by setting BGP +communities attribute to the updates. + +@example +router bgp 7675 + neighbor 192.168.0.1 remote-as 100 + neighbor 192.168.0.1 route-map RMAP in +! +ip community-list 70 permit 7675:70 +ip community-list 70 deny +ip community-list 80 permit 7675:80 +ip community-list 80 deny +ip community-list 90 permit 7675:90 +ip community-list 90 deny +! +route-map RMAP permit 10 + match community 70 + set local-preference 70 +! +route-map RMAP permit 20 + match community 80 + set local-preference 80 +! +route-map RMAP permit 30 + match community 90 + set local-preference 90 +@end example + + Following configuration announce 10.0.0.0/8 from AS 100 to AS 7675. +The route has communities value 7675:80 so when above configuration +exists in AS 7675, announced route's local preference will be set to +value 80. + +@example +router bgp 100 + network 10.0.0.0/8 + neighbor 192.168.0.2 remote-as 7675 + neighbor 192.168.0.2 route-map RMAP out +! +ip prefix-list PLIST permit 10.0.0.0/8 +! +route-map RMAP permit 10 + match ip address prefix-list PLIST + set community 7675:80 +@end example + + Following configuration is an example of BGP route filtering using +communities attribute. This configuration only permit BGP routes +which has BGP communities value 0:80 or 0:90. Network operator can +put special internal communities value at BGP border router, then +limit the BGP routes announcement into the internal network. + +@example +router bgp 7675 + neighbor 192.168.0.1 remote-as 100 + neighbor 192.168.0.1 route-map RMAP in +! +ip community-list 1 permit 0:80 0:90 +! +route-map RMAP permit in + match community 1 +@end example + + Following exmaple filter BGP routes which has communities value 1:1. +When there is no match community-list returns deny. To avoid +filtering all of routes, we need to define permit any at last. + +@example +router bgp 7675 + neighbor 192.168.0.1 remote-as 100 + neighbor 192.168.0.1 route-map RMAP in +! +ip community-list standard FILTER deny 1:1 +ip community-list standard FILTER permit +! +route-map RMAP permit 10 + match community FILTER +@end example + + Communities value keyword @code{internet} has special meanings in +standard community lists. In below example @code{internet} act as +match any. It matches all of BGP routes even if the route does not +have communities attribute at all. So community list @code{INTERNET} +is same as above example's @code{FILTER}. + +@example +ip community-list standard INTERNET deny 1:1 +ip community-list standard INTERNET permit internet +@end example + + Following configuration is an example of communities value deletion. +With this configuration communities value 100:1 and 100:2 is removed +from BGP updates. For communities value deletion, only @code{permit} +community-list is used. @code{deny} community-list is ignored. + +@example +router bgp 7675 + neighbor 192.168.0.1 remote-as 100 + neighbor 192.168.0.1 route-map RMAP in +! +ip community-list standard DEL permit 100:1 100:2 +! +route-map RMAP permit 10 + set comm-list DEL delete +@end example + +@c ----------------------------------------------------------------------- +@node BGP Extended Communities Attribute, Displaying BGP routes, BGP Communities Attribute, BGP +@comment node-name, next, previous, up +@section BGP Extended Communities Attribute + + BGP extended communities attribute is introduced with MPLS VPN/BGP +technology. MPLS VPN/BGP expands capability of network infrastructure +to provide VPN functionality. At the same time it requires a new +framework for policy routing. With BGP Extended Communities Attribute +we can use Route Target or Site of Origin for implementing network +policy for MPLS VPN/BGP. + + BGP Extended Communities Attribute is similar to BGP Communities +Attribute. It is an optional transitive attribute. BGP Extended +Communities Attribute can carry multiple Extended Community value. +Each Extended Community value is eight octet length. + + BGP Extended Communities Attribute provides an extended range +compared with BGP Communities Attribute. Adding to that there is a +type field in each value to provides community space structure. + + There are two format to define Extended Community value. One is AS +based format the other is IP address based format. + +@table @code +@item AS:VAL +This is a format to define AS based Extended Community value. +@code{AS} part is 2 octets Global Administrator subfield in Extended +Community value. @code{VAL} part is 4 octets Local Administrator +subfield. @code{7675:100} represents AS 7675 policy value 100. +@item IP-Address:VAL +This is a format to define IP address based Extended Community value. +@code{IP-Address} part is 4 octets Global Administrator subfield. +@code{VAL} part is 2 octets Local Administrator subfield. +@code{10.0.0.1:100} represents +@end table + +@menu +* BGP Extended Community Lists:: +* BGP Extended Communities in Route Map:: +@end menu + +@node BGP Extended Community Lists, BGP Extended Communities in Route Map, BGP Extended Communities Attribute, BGP Extended Communities Attribute +@comment node-name, next, previous, up +@subsection BGP Extended Community Lists + + Expanded Community Lists is a user defined BGP Expanded Community +Lists. + +@deffn Command {ip extcommunity-list standard @var{name} @{permit|deny@} @var{extcommunity}} {} +This command defines a new standard extcommunity-list. +@var{extcommunity} is extended communities value. The +@var{extcommunity} is compiled into extended community structure. We +can define multiple extcommunity-list under same name. In that case +match will happen user defined order. Once the extcommunity-list +matches to extended communities attribute in BGP updates it return +permit or deny based upon the extcommunity-list definition. When +there is no matched entry, deny will be returned. When +@var{extcommunity} is empty it matches to any routes. +@end deffn + +@deffn Command {ip extcommunity-list expanded @var{name} @{permit|deny@} @var{line}} {} +This command defines a new expanded extcommunity-list. @var{line} is +a string expression of extended communities attribute. @var{line} can +include regular expression to match extended communities attribute in +BGP updates. +@end deffn + +@deffn Command {no ip extcommunity-list @var{name}} {} +@deffnx Command {no ip extcommunity-list standard @var{name}} {} +@deffnx Command {no ip extcommunity-list expanded @var{name}} {} +These commands delete extended community lists specified by +@var{name}. All of extended community lists shares a single name +space. So extended community lists can be removed simpley specifying +the name. +@end deffn + +@deffn {Command} {show ip extcommunity-list} {} +@deffnx {Command} {show ip extcommunity-list @var{name}} {} +This command display current extcommunity-list information. When +@var{name} is specified the community list's information is shown. + +@example +# show ip extcommunity-list +@end example +@end deffn + +@node BGP Extended Communities in Route Map, , BGP Extended Community Lists, BGP Extended Communities Attribute +@comment node-name, next, previous, up +@subsection BGP Extended Communities in Route Map + +@deffn {Route Map} {match extcommunity @var{word}} {} +@end deffn + +@deffn {Route Map} {set extcommunity rt @var{extcommunity}} {} +This command set Route Target value. +@end deffn + +@deffn {Route Map} {set extcommunity soo @var{extcommunity}} {} +This command set Site of Origin value. +@end deffn + +@c ----------------------------------------------------------------------- +@node Displaying BGP routes, Capability Negotiation, BGP Extended Communities Attribute, BGP +@comment node-name, next, previous, up +@section Displaying BGP Routes + +@menu +* Show IP BGP:: +* More Show IP BGP:: +@end menu + +@node Show IP BGP, More Show IP BGP, Displaying BGP routes, Displaying BGP routes +@comment node-name, next, previous, up +@subsection Show IP BGP + +@deffn {Command} {show ip bgp} {} +@deffnx {Command} {show ip bgp @var{A.B.C.D}} {} +@deffnx {Command} {show ip bgp @var{X:X::X:X}} {} +This command displays BGP routes. When no route is specified it +display all of IPv4 BGP routes. +@end deffn + +@example +BGP table version is 0, local router ID is 10.1.1.1 +Status codes: s suppressed, d damped, h history, * valid, > best, i - internal +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> 1.1.1.1/32 0.0.0.0 0 32768 i + +Total number of prefixes 1 +@end example + +@node More Show IP BGP, , Show IP BGP, Displaying BGP routes +@comment node-name, next, previous, up +@subsection More Show IP BGP + +@deffn {Command} {show ip bgp regexp @var{line}} {} +This command display BGP routes using AS path regular expression (@pxref{Display BGP Routes by AS Path}). +@end deffn + +@deffn Command {show ip bgp community @var{community}} {} +@deffnx Command {show ip bgp community @var{community} exact-match} {} +This command display BGP routes using @var{community} (@pxref{Display +BGP Routes by Community}). +@end deffn + +@deffn Command {show ip bgp community-list @var{word}} {} +@deffnx Command {show ip bgp community-list @var{word} exact-match} {} +This command display BGP routes using community list (@pxref{Display +BGP Routes by Community}). +@end deffn + +@deffn {Command} {show ip bgp summary} {} +@end deffn + +@deffn {Command} {show ip bgp neighbor [@var{peer}]} {} +@end deffn + +@deffn {Command} {clear ip bgp @var{peer}} {} +Clear peers which have addresses of X.X.X.X +@end deffn + +@deffn {Command} {clear ip bgp @var{peer} soft in} {} +Clear peer using soft reconfiguration. +@end deffn + +@deffn {Command} {show debug} {} +@end deffn + +@deffn {Command} {debug event} {} +@end deffn + +@deffn {Command} {debug update} {} +@end deffn + +@deffn {Command} {debug keepalive} {} +@end deffn + +@deffn {Command} {no debug event} {} +@end deffn + +@deffn {Command} {no debug update} {} +@end deffn + +@deffn {Command} {no debug keepalive} {} +@end deffn + +@node Capability Negotiation, Route Reflector, Displaying BGP routes, BGP +@comment node-name, next, previous, up +@section Capability Negotiation + + When adding IPv6 routing information exchange feature to BGP. There +were some proposals. @acronym{IETF} @acronym{IDR} working group finally +take a proposal called Multiprotocol Extension for BGP. The +specification is described in RFC2283. The protocol does not define new +protocols. It defines new attributes to existing BGP. When it is used +exchanging IPv6 routing information it is called BGP-4+. When it is +used for exchanging multicast routing information it is called MBGP. + + @command{bgpd} supports Multiprotocol Extension for BGP. So if remote peer +supports the protocol, @command{bgpd} can exchange IPv6 and/or multicast routing +information. + + Traditional BGP does not have the feature to detect remote peer's +capability whether it can handle other than IPv4 unicast routes. This +is a big problem using Multiprotocol Extension for BGP to operational +network. @cite{draft-ietf-idr-bgp4-cap-neg-04.txt} is proposing a +feature called Capability Negotiation. @command{bgpd} use this Capability +Negotiation to detect remote peer's capabilities. If the peer is only +configured as IPv4 unicast neighbor, @command{bgpd} does not send these Capability +Negotiation packets. + + By default, Zebra will bring up peering with minimal common capability +for the both sides. For example, local router has unicast and multicast +capabilitie and remote router has unicast capability. In this case, +the local router will establish the connection with unicast only capability. +When there are no common capabilities, Zebra sends Unsupported Capability +error and then resets the connection. + + If you want to completely match capabilities with remote peer. Please +use @command{strict-capability-match} command. + +@deffn {BGP} {neighbor @var{peer} strict-capability-match} {} +@deffnx {BGP} {no neighbor @var{peer} strict-capability-match} {} +Strictly compares remote capabilities and local capabilities. If capabilities +are different, send Unsupported Capability error then reset connection. +@end deffn + + You may want to disable sending Capability Negotiation OPEN message +optional parameter to the peer when remote peer does not implement +Capability Negotiation. Please use @command{dont-capability-negotiate} +command to disable the feature. + +@deffn {BGP} {neighbor @var{peer} dont-capability-negotiate} {} +@deffnx {BGP} {no neighbor @var{peer} dont-capability-negotiate} {} +Suppress sending Capability Negotiation as OPEN message optional +parameter to the peer. This command only affects the peer is configured +other than IPv4 unicast configuration. +@end deffn + + When remote peer does not have capability negotiation feature, remote +peer will not send any capabilities at all. In that case, bgp configures +the peer with configured capabilities. + + You may prefer locally configured capabilities more than the negotiated +capabilities even though remote peer sends capabilities. If the peer is +configured by @command{override-capability}, @command{bgpd} ignores received +capabilities then override negotiated capabilities with configured values. + +@deffn {BGP} {neighbor @var{peer} override-capability} {} +@deffnx {BGP} {no neighbor @var{peer} override-capability} {} +Override the result of Capability Negotiation with local configuration. +Ignore remote peer's capability value. +@end deffn + +@node Route Reflector, Route Server, Capability Negotiation, BGP +@comment node-name, next, previous, up +@section Route Reflector + +@deffn {BGP} {bgp cluster-id @var{a.b.c.d}} {} +@end deffn + +@deffn {BGP} {neighbor @var{peer} route-reflector-client} {} +@deffnx {BGP} {no neighbor @var{peer} route-reflector-client} {} +@end deffn + +@node Route Server, How to set up a 6-Bone connection, Route Reflector, BGP +@comment node-name, next, previous, up +@section Route Server + +At an Internet Exchange point, many ISPs are connected to each other by +external BGP peering. Normally these external BGP connection are done by +@code{full mesh} method. As with internal BGP full mesh formation, +this method has a scaling problem. + +This scaling problem is well known. Route Server is a method to resolve +the problem. Each ISP's BGP router only peers to Route Server. Route +Server serves as BGP information exchange to other BGP routers. By +applying this method, numbers of BGP connections is reduced from +O(n*(n-1)/2) to O(n). + +Unlike normal BGP router, Route Server must have several routing tables +for managing different routing policies for each BGP speaker. We call the +routing tables as different @code{view}s. @command{bgpd} can work as +normal BGP router or Route Server or both at the same time. + +@menu +* Multiple instance:: +* BGP instance and view:: +* Routing policy:: +* Viewing the view:: +@end menu + +@node Multiple instance, BGP instance and view, Route Server, Route Server +@comment node-name, next, previous, up +@subsection Multiple instance + +To enable multiple view function of @code{bgpd}, you must turn on +multiple instance feature beforehand. + +@deffn {Command} {bgp multiple-instance} {} +Enable BGP multiple instance feature. After this feature is enabled, +you can make multiple BGP instances or multiple BGP views. +@end deffn + +@deffn {Command} {no bgp multiple-instance} {} +Disable BGP multiple instance feature. You can not disable this feature +when BGP multiple instances or views exist. +@end deffn + +When you want to make configuration more Cisco like one, + +@deffn {Command} {bgp config-type cisco} {} +Cisco compatible BGP configuration output. +@end deffn + +When bgp config-type cisco is specified, + +``no synchronization'' is displayed. +``no auto-summary'' is desplayed. + +``network'' and ``aggregate-address'' argument is displayed as +``A.B.C.D M.M.M.M'' + +Zebra: network 10.0.0.0/8 +Cisco: network 10.0.0.0 + +Zebra: aggregate-address 192.168.0.0/24 +Cisco: aggregate-address 192.168.0.0 255.255.255.0 + +Community attribute handling is also different. If there is no +configuration is specified community attribute and extended community +attribute are sent to neighbor. When user manually disable the +feature community attribute is not sent to the neighbor. In case of +``bgp config-type cisco'' is specified, community attribute is not +sent to the neighbor by default. To send community attribute user has +to specify ``neighbor A.B.C.D send-community'' command. + +! +router bgp 1 + neighbor 10.0.0.1 remote-as 1 + no neighbor 10.0.0.1 send-community +! + +! +router bgp 1 + neighbor 10.0.0.1 remote-as 1 + neighbor 10.0.0.1 send-community +! + +@deffn {Command} {bgp config-type zebra} {} +Zebra style BGP configuration. This is default. +@end deffn + +@node BGP instance and view, Routing policy, Multiple instance, Route Server +@comment node-name, next, previous, up +@subsection BGP instance and view + +BGP instance is a normal BGP process. The result of route selection +goes to the kernel routing table. You can setup different AS at the +same time when BGP multiple instance feature is enabled. + +@deffn {Command} {router bgp @var{as-number}} {} +Make a new BGP instance. You can use arbitrary word for the @var{name}. +@end deffn + +@example +@group +bgp multiple-instance +! +router bgp 1 + neighbor 10.0.0.1 remote-as 2 + neighbor 10.0.0.2 remote-as 3 +! +router bgp 2 + neighbor 10.0.0.3 remote-as 4 + neighbor 10.0.0.4 remote-as 5 +@end group +@end example + +BGP view is almost same as normal BGP process. The result of +route selection does not go to the kernel routing table. BGP view is +only for exchanging BGP routing information. + +@deffn {Command} {router bgp @var{as-number} view @var{name}} {} +Make a new BGP view. You can use arbitrary word for the @var{name}. This +view's route selection result does not go to the kernel routing table. +@end deffn + +With this command, you can setup Route Server like below. + +@example +@group +bgp multiple-instance +! +router bgp 1 view 1 + neighbor 10.0.0.1 remote-as 2 + neighbor 10.0.0.2 remote-as 3 +! +router bgp 2 view 2 + neighbor 10.0.0.3 remote-as 4 + neighbor 10.0.0.4 remote-as 5 +@end group +@end example + +@node Routing policy, Viewing the view, BGP instance and view, Route Server +@comment node-name, next, previous, up +@subsection Routing policy + +You can set different routing policy for a peer. For example, you can +set different filter for a peer. + +@example +@group +bgp multiple-instance +! +router bgp 1 view 1 + neighbor 10.0.0.1 remote-as 2 + neighbor 10.0.0.1 distribute-list 1 in +! +router bgp 1 view 2 + neighbor 10.0.0.1 remote-as 2 + neighbor 10.0.0.1 distribute-list 2 in +@end group +@end example + +This means BGP update from a peer 10.0.0.1 goes to both BGP view 1 and view +2. When the update is inserted into view 1, distribute-list 1 is +applied. On the other hand, when the update is inserted into view 2, +distribute-list 2 is applied. + +@node Viewing the view, , Routing policy, Route Server +@comment node-name, next, previous, up +@subsection Viewing the view + +To display routing table of BGP view, you must specify view name. + +@deffn {Command} {show ip bgp view @var{name}} {} +Display routing table of BGP view @var{name}. +@end deffn + +@node How to set up a 6-Bone connection, Dump BGP packets and table, Route Server, BGP +@comment node-name, next, previous, up +@section How to set up a 6-Bone connection + +@example +@group +zebra configuration +=================== +! +! Actually there is no need to configure zebra +! + +bgpd configuration +================== +! +! This means that routes go through zebra and into the kernel. +! +router zebra +! +! MP-BGP configuration +! +router bgp 7675 + bgp router-id 10.0.0.1 + neighbor 3ffe:1cfa:0:2:2a0:c9ff:fe9e:f56 remote-as @var{as-number} +! + address-family ipv6 + network 3ffe:506::/32 + neighbor 3ffe:1cfa:0:2:2a0:c9ff:fe9e:f56 activate + neighbor 3ffe:1cfa:0:2:2a0:c9ff:fe9e:f56 route-map set-nexthop out + neighbor 3ffe:1cfa:0:2:2c0:4fff:fe68:a231 remote-as @var{as-number} + neighbor 3ffe:1cfa:0:2:2c0:4fff:fe68:a231 route-map set-nexthop out + exit-address-family +! +ipv6 access-list all permit any +! +! Set output nexthop address. +! +route-map set-nexthop permit 10 + match ipv6 address all + set ipv6 nexthop global 3ffe:1cfa:0:2:2c0:4fff:fe68:a225 + set ipv6 nexthop local fe80::2c0:4fff:fe68:a225 +! +! logfile FILENAME is obsolete. Please use log file FILENAME +! +log file bgpd.log +! +@end group +@end example + +@node Dump BGP packets and table, , How to set up a 6-Bone connection, BGP +@comment node-name, next, previous, up +@section Dump BGP packets and table + +@deffn Command {dump bgp all @var{path}} {} +@deffnx Command {dump bgp all @var{path} @var{interval}} {} +Dump all BGP packet and events to @var{path} file. +@end deffn + +@deffn Command {dump bgp updates @var{path}} {} +@deffnx Command {dump bgp updates @var{path} @var{interval}} {} +Dump BGP updates to @var{path} file. +@end deffn + +@deffn Command {dump bgp routes @var{path}} {} +@deffnx Command {dump bgp routes @var{path}} {} +Dump whole BGP routing table to @var{path}. This is heavy process. +@end deffn diff --git a/doc/draft-zebra-00.ms b/doc/draft-zebra-00.ms new file mode 100644 index 00000000..25994727 --- /dev/null +++ b/doc/draft-zebra-00.ms @@ -0,0 +1,209 @@ +.pl 10.0i +.po 0 +.ll 7.2i +.lt 7.2i +.nr LL 7.2i +.nr LT 7.2i +.ds LF Ishiguro +.ds RF FORMFEED[Page %] +.ds CF +.ds LH RFC DRAFT +.ds RH March 1998 +.ds CH +.hy 0 +.ad l +Network Working Group K. Ishiguro +Request for Comments: DRAFT Digital Magic Labs, Inc. + March 1998 +.sp 2 +.ce +Zebra Protocol Draft +.sp 2 +.fi +.ne 4 +Status of this Memo +.sp +.in 3 +This draft is very eary beta version. +.sp +.in 0 +.ne 4 +Introduction +.sp +.in 3 +The zebra protocol is a communication protocol between kernel +routing table manager and routing protocol daemon. It is built over +TCP/IP protocol suite. +.sp +.in 0 +.ne 4 +Request message formats +.sp +.in 3 +zebra is TCP-based protocol. +.sp +Below is request packet format. +.sp +.in 0 +.DS +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Length (2) | Command (1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.DE +.sp +.in 3 +Length is total packet length. +.sp +Here is summary of command list. +.sp +.in 0 +.DS +1 - ZEBRA_IPV4_ROUTE_ADD +2 - ZEBRA_IPV4_ROUTE_DELETE +3 - ZEBRA_IPV6_ROUTE_ADD +4 - ZEBRA_IPV6_ROUTE_DELETE +5 - ZEBRA_GET_ONE_INTERFACE +6 - ZEBRA_GET_ALL_INTERFACE +7 - ZEBRA_GET_HOSTINFO +.DE +.sp +.in 0 +.ne 4 +IPv4 reply message formats +.sp +.in 0 +.DS +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+ +| Type (1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Gateway (4) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.DE +.sp +.in 3 +Type field specify route's origin type. +.sp +.in 0 +.DS +1 - ZEBRA_ROUTE_RESERVE +2 - ZEBRA_ROUTE_CONNECT +3 - ZEBRA_ROUTE_STATIC +4 - ZEBRA_ROUTE_RIP +5 - ZEBRA_ROUTE_RIPNG +6 - ZEBRA_ROUTE_BGP +7 - ZEBRA_ROUTE_RADIX +.DE +.sp +.in 3 +After above message there can be variale length IPv4 prefix data. +Each IPv4 prefix is encoded as a two tuple of the form +.sp +.in 0 +.DS ++----------------------+ +|Subnet mask (1 octet) | ++----------------------+ +|IPv4 prefix (variable)| ++----------------------+ +.DE +.sp +.in 0 +.ne 4 +IPv6 reply message formats +.sp +.in 0 +.DS +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+ +| Type (1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Gateway (16) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.DE +.sp +.in 3 +Type field specify route's origin type. +.sp +.in 0 +.DS +1 - ZEBRA_ROUTE_RESERVE +2 - ZEBRA_ROUTE_CONNECT +3 - ZEBRA_ROUTE_STATIC +4 - ZEBRA_ROUTE_RIP +5 - ZEBRA_ROUTE_RIPNG +6 - ZEBRA_ROUTE_BGP +7 - ZEBRA_ROUTE_RADIX +.DE +.sp +.in 0 +.DS ++----------------------+ +| ifindex (4 octet) | ++----------------------+ +| prefixlen (1 octet)| ++----------------------+ +|IPv6 prefix (variable)| ++----------------------+ +.DE +.sp +.in 3 +I am not sure but it seems some operation systems IPv6 +implementation may need interface index when add and delete +linklocal routes. +.sp +I have added ifindex field to specify IPv6 routes interface +index. If this index is value zero, it will ignored. +.sp +.in 0 +.ne 4 +Interface information message format. +.sp +.in 0 +.DS +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Interface name (20) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Index (1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Inteface flag (4) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Inteface metric (4) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Inteface MTU (4) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Inteface Address count (4) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.DE +.sp +.in 3 +Address message format. +.sp +.in 0 +.ne 4 +Host inforamtion message format. +.sp +.in 0 +.DS +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|IPv4 forwarding|IPv6 forwarding| ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.DE +.sp +.in 3 +Host information contain IPv4/IPv6 forwarding information. diff --git a/doc/filter.texi b/doc/filter.texi new file mode 100644 index 00000000..1bc70cdb --- /dev/null +++ b/doc/filter.texi @@ -0,0 +1,192 @@ +@node Filtering +@comment node-name, next, previous, up +@chapter Filtering + +Zebra provides many very flexible filtering features. Filtering is used +for both input and output of the routing information. Once filtering is +defined, it can be applied in any direction. + +@menu +* IP Access List:: +* IP Prefix List:: +@end menu + +@node IP Access List, IP Prefix List, Filtering, Filtering +@comment node-name, next, previous, up +@subsection IP Access List + +@deffn {Command} {access-list @var{name} permit @var{ipv4-network}} {} +@deffnx {Command} {access-list @var{name} deny @var{ipv4-network}} {} +@end deffn + +Basic filtering is done by @code{access-list} as shown in the +following example. + +@example +access-list filter deny 10.0.0.0/9 +access-list filter permit 10.0.0.0/8 +@end example + +@node IP Prefix List, , IP Access List, Filtering +@comment node-name, next, previous, up +@subsection IP Prefix List + +@command{ip prefix-list} provides the most powerful prefix based +filtering mechanism. In addition to @command{access-list} functionality, +@command{ip prefix-list} has prefix length range specification and +sequential number specification. You can add or delete prefix based +filters to arbitrary points of prefix-list using sequential number specification. + +If no ip prefix-list is specified, it acts as permit. If @command{ip prefix-list} +is defined, and no match is found, default deny is applied. + +@c @deffn {Command} {ip prefix-list @var{name} [seq @var{number}] permit|deny [le @var{prefixlen}] [ge @var{prefixlen}]} {} +@deffn {Command} {ip prefix-list @var{name} (permit|deny) @var{prefix} [le @var{len}] [ge @var{len}]} {} +@deffnx {Command} {ip prefix-list @var{name} seq @var{number} (permit|deny) @var{prefix} [le @var{len}] [ge @var{len}]} {} + +You can create @command{ip prefix-list} using above commands. + +@table @asis + +@item @asis{seq} +seq @var{number} can be set either automatically or manually. In the +case that sequential numbers are set manually, the user may pick any +number less than 4294967295. In the case that sequential number are set +automatically, the sequential number will increase by a unit of five (5) +per list. If a list with no specified sequential number is created +after a list with a specified sequential number, the list will +automatically pick the next multiple of five (5) as the list number. +For example, if a list with number 2 already exists and a new list with +no specified number is created, the next list will be numbered 5. If +lists 2 and 7 already exist and a new list with no specified number is +created, the new list will be numbered 10. + +@item @asis{le} +@command{le} command specifies prefix length. The prefix list will be +applied if the prefix length is less than or equal to the le prefix length. + +@item @asis{ge} +@command{ge} command specifies prefix length. The prefix list will be +applied if the prefix length is greater than or equal to the ge prefix length. + +@end table + +@end deffn + +Less than or equal to prefix numbers and greater than or equal to +prefix numbers can be used together. The order of the le and ge +commands does not matter. + +If a prefix list with a different sequential number but with the exact +same rules as a previous list is created, an error will result. +However, in the case that the sequential number and the rules are +exactly similar, no error will result. + +If a list with the same sequential number as a previous list is created, +the new list will overwrite the old list. + +Matching of IP Prefix is performed from the smaller sequential number to the +larger. The matching will stop once any rule has been applied. + +In the case of no le or ge command, + +Version 0.85: the matching rule will apply to all prefix lengths that +matched the prefix list. + +Version 0.86 or later: In the case of no le or ge command, the prefix +length must match exactly the length specified in the prefix list. + + +@deffn {Command} {no ip prefix-list @var{name}} {} +@end deffn + +@menu +* ip prefix-list description:: +* ip prefix-list sequential number control:: +* Showing ip prefix-list:: +* Clear counter of ip prefix-list:: +@end menu + +@node ip prefix-list description, ip prefix-list sequential number control, IP Prefix List, IP Prefix List +@comment node-name, next, previous, up +@subsubsection ip prefix-list description + +@deffn {Command} {ip prefix-list @var{name} description @var{desc}} {} +Descriptions may be added to prefix lists. This command adds a +description to the prefix list. +@end deffn + +@deffn {Command} {no ip prefix-list @var{name} description [@var{desc}]} {} +Deletes the description from a prefix list. It is possible to use the +command without the full description. +@end deffn + +@node ip prefix-list sequential number control, Showing ip prefix-list, ip prefix-list description, IP Prefix List +@comment node-name, next, previous, up +@subsubsection ip prefix-list sequential number control + +@deffn {Command} {ip prefix-list sequence-number} {} +With this command, the IP prefix list sequential number is displayed. +This is the default behavior. +@end deffn + +@deffn {Command} {no ip prefix-list sequence-number} {} +With this command, the IP prefix list sequential number is not +displayed. +@end deffn + +@node Showing ip prefix-list, Clear counter of ip prefix-list, ip prefix-list sequential number control, IP Prefix List +@comment node-name, next, previous, up +@subsubsection Showing ip prefix-list + +@deffn {Command} {show ip prefix-list} {} +Display all IP prefix lists. +@end deffn + +@deffn {Command} {show ip prefix-list @var{name}} {} +Show IP prefix list can be used with a prefix list name. +@end deffn + +@deffn {Command} {show ip prefix-list @var{name} seq @var{num}} {} +Show IP prefix list can be used with a prefix list name and sequential +number. +@end deffn + +@deffn {Command} {show ip prefix-list @var{name} @var{a.b.c.d/m}} {} +If the command longer is used, all prefix lists with prefix lengths equal to +or longer than the specified length will be displayed. +If the command first match is used, the first prefix length match will be +displayed. +@end deffn + +@deffn {Command} {show ip prefix-list @var{name} @var{a.b.c.d/m} longer} {} +@end deffn + +@deffn {Command} {show ip prefix-list @var{name} @var{a.b.c.d/m} first-match} {} +@end deffn + +@deffn {Command} {show ip prefix-list summary} {} +@end deffn +@deffn {Command} {show ip prefix-list summary @var{name}} {} +@end deffn + +@deffn {Command} {show ip prefix-list detail} {} +@end deffn +@deffn {Command} {show ip prefix-list detail @var{name}} {} +@end deffn + +@node Clear counter of ip prefix-list, , Showing ip prefix-list, IP Prefix List +@comment node-name, next, previous, up +@subsubsection Clear counter of ip prefix-list + +@deffn {Command} {clear ip prefix-list} {} +Clears the counters of all IP prefix lists. Clear IP Prefix List can be +used with a specified name and prefix. +@end deffn + +@deffn {Command} {clear ip prefix-list @var{name}} {} +@end deffn + +@deffn {Command} {clear ip prefix-list @var{name} @var{a.b.c.d/m}} {} +@end deffn + diff --git a/doc/install.texi b/doc/install.texi new file mode 100644 index 00000000..72c826d6 --- /dev/null +++ b/doc/install.texi @@ -0,0 +1,218 @@ +@node Installation, Basic commands, Overview, Top +@comment node-name, next, previous, up +@chapter Installation + +@cindex How to install Zebra +@cindex Installation +@cindex Installing Zebra +@cindex Building the system +@cindex Making Zebra + + There are three steps for installing the software: configuration, +compilation, and installation. + +@menu +* Configure the Software:: +* Build the Software:: +* Install the Software:: +@end menu + + The easiest way to get Zebra running is to issue the following +commands: + +@example +% configure +% make +% make install +@end example + +@node Configure the Software, Build the Software, Installation, Installation +@comment node-name, next, previous, up +@section Configure the Software + +@cindex Configuration options +@cindex Options for configuring +@cindex Build options +@cindex Distribution configuration +@cindex Options to @code{./configure} + + Zebra has an excellent configure script which +automatically detects most host configurations. There are several +additional configure options you can use to turn off IPv6 support, to +disable the compilation of specific daemons, and to enable SNMP support. + +@table @option +@item --enable-guile +Turn on compilation of the zebra-guile interpreter. You will need the +guile library to make this. zebra-guile implementation is not yet +finished. So this option is only useful for zebra-guile developers. +@item --disable-ipv6 +Turn off IPv6 related features and daemons. Zebra configure script +automatically detects IPv6 stack. But sometimes you might want to +disable IPv6 support of Zebra. +@item --disable-zebra +Do not build zebra daemon. +@item --disable-ripd +Do not build ripd. +@item --disable-ripngd +Do not build ripngd. +@item --disable-ospfd +Do not build ospfd. +@item --disable-ospf6d +Do not build ospf6d. +@item --disable-bgpd +Do not build bgpd. +@item --disable-bgp-announce +Make @command{bgpd} which does not make bgp announcements at all. This +feature is good for using @command{bgpd} as a BGP announcement listener. +@item --enable-netlink +Force to enable @sc{gnu}/Linux netlink interface. Zebra configure +script detects netlink interface by checking a header file. When the header +file does not match to the current running kernel, configure script will +not turn on netlink support. +@item --enable-snmp +Enable SNMP support. By default, SNMP support is disabled. +@end table + +You may specify any combination of the above options to the configure +script. By default, the executables are placed in @file{/usr/local/sbin} +and the configuration files in @file{/usr/local/etc}. The @file{/usr/local/} +installation prefix and other directories may be changed using the following +options to the configuration script. + +@table @option +@item --prefix=@var{prefix} +Install architecture-independent files in @var{prefix} [/usr/local]. +@item --sysconfdir=@var{dir} +Read-only sample configuration file in @var{dir} [@var{prefix}/etc]. +@end table + +@example +% ./configure --disable-ipv6 +@end example + +This command will configure zebra and the routing daemons. + +@cindex Configuring Zebra +@cindex Configuration the software build +@cindex Building on Linux boxes +@cindex Linux configurations + +There are several options available only to @sc{gnu}/Linux systems: +@footnote{GNU/Linux has very flexible kernel configuration features. If +you use GNU/Linux, make sure that the current kernel configuration is +what you want. Zebra will run with any kernel configuration but some +recommendations do exist. + +@table @var + +@item CONFIG_NETLINK +Kernel/User netlink socket. +This is a brand new feature which enables +an advanced interface between the Linux kernel and Zebra (@pxref{Kernel Interface}). + +@item CONFIG_RTNETLINK +Routing messages. +This makes it possible to receive netlink routing messages. If you +specify this option, @command{zebra} can detect routing information +updates directly from the kernel (@pxref{Kernel Interface}). + +@item CONFIG_IP_MULTICAST +IP: multicasting. +This option should be specified when you use @command{ripd} or +@command{ospfd} because these protocols use multicast. + +@end table + +IPv6 support has been added in @sc{gnu}/Linux kernel version 2.2. If you +try to use the Zebra IPv6 feature on a @sc{gnu}/Linux kernel, please +make sure the following libraries have been installed. Please note that +these libraries will not be needed when you uses @sc{gnu} C library 2.1 +or upper. + +@table @code + +@item inet6-apps +The @code{inet6-apps} package includes basic IPv6 related libraries such +as @code{inet_ntop} and @code{inet_pton}. Some basic IPv6 programs such +as @command{ping}, @command{ftp}, and @command{inetd} are also +included. The @code{inet-apps} can be found at +@url{ftp://ftp.inner.net/pub/ipv6/}. + +@item net-tools +The @code{net-tools} package provides an IPv6 enabled interface and +routing utility. It contains @command{ifconfig}, @command{route}, +@command{netstat}, and other tools. @code{net-tools} may be found at +@url{http://www.tazenda.demon.co.uk/phil/net-tools/}. + +@end table +@c A - end of footnote +}. + +@node Build the Software, Install the Software, Configure the Software, Installation +@comment node-name, next, previous, up +@section Build the Software + +After configuring the software, you will need to compile it for your +system. Simply issue the command @command{make} in the root of the source +directory and the software will be compiled. If you have *any* problems +at this stage, be certain to send a bug report @xref{Bug Reports}. + +@example +% ./configure +. +. +. +./configure output +. +. +. +% make +@end example +@c A - End of node, Building the Software + + +@node Install the Software, , Build the Software, Installation +@comment node-name, next, previous, up +@section Install the Software + +Installing the software to your system consists of copying the compiled +programs and supporting files to a standard location. After the +installation process has completed, these files have been copied +from your work directory to @file{/usr/local/bin}, and @file{/usr/local/etc}. + +To install the Zebra suite, issue the following command at your shell +prompt: @command{make install}. + +@example +% +% make install +% +@end example + +@c A - removed this section and placed it with Install the Software +@c @node Additional Notes, , Install the Software, Installation +@comment node-name, next, previous, up +@c @section Additional Notes + +Zebra daemons have their own terminal interface or VTY. After +installation, you have to setup each beast's port number to connect to +them. Please add the following entries to @file{/etc/services}. + +@example +zebrasrv 2600/tcp # zebra service +zebra 2601/tcp # zebra vty +ripd 2602/tcp # RIPd vty +ripngd 2603/tcp # RIPngd vty +ospfd 2604/tcp # OSPFd vty +bgpd 2605/tcp # BGPd vty +ospf6d 2606/tcp # OSPF6d vty +@end example + +If you use a FreeBSD newer than 2.2.8, the above entries are already +added to @file{/etc/services} so there is no need to add it. If you +specify a port number when starting the daemon, these entries may not be +needed. + +You may need to make changes to the config files in +@file{@value{INSTALL_PREFIX_ETC}/*.conf}. @xref{Config Commands}. diff --git a/doc/ipv6.texi b/doc/ipv6.texi new file mode 100644 index 00000000..c24d1453 --- /dev/null +++ b/doc/ipv6.texi @@ -0,0 +1,32 @@ +@node IPv6 Support, Kernel Interface, Route Map, Top +@comment node-name, next, previous, up +@chapter IPv6 Support + +Zebra fully supports IPv6 routing. As described so far, Zebra supports +RIPng, OSPFv3 and BGP-4+. You can give IPv6 addresses to an interface +and configure static IPv6 routing information. Zebra-IPv6 also provides +automatic address configuration via a feature called @code{address +auto configuration}. To do it, the router must send router advertisement +messages to the all nodes that exist on the network. + +@menu +* Router Advertisement:: +@end menu + +@node Router Advertisement, , IPv6 Support, IPv6 Support +@comment node-name, next, previous, up +@section Router Advertisement + +@deffn {Interface Command} {ipv6 nd send-ra} {} +@end deffn + +@deffn {Interface Command} {ipv6 nd prefix-advertisement @var{ipv6prefix}} {} +@end deffn + +@example +@group +interface eth0 + ipv6 nd send-ra + ipv6 nd prefix-advertisement 3ffe:506:5009::/64 +@end group +@end example diff --git a/doc/kernel.texi b/doc/kernel.texi new file mode 100644 index 00000000..b863a1f6 --- /dev/null +++ b/doc/kernel.texi @@ -0,0 +1,48 @@ +@node Kernel Interface, SNMP Support, IPv6 Support, Top +@comment node-name, next, previous, up +@chapter Kernel Interface + +There are several different methods for reading kernel routing table +information, updating kernel routing tables, and for looking up +interfaces. + +@table @samp + +@item ioctl +The @samp{ioctl} method is a very traditional way for reading or writing +kernel information. @samp{ioctl} can be used for looking up interfaces +and for modifying interface addresses, flags, mtu settings and other +types of information. Also, @samp{ioctl} can insert and delete kernel +routing table entries. It will soon be available on almost any platform +which zebra supports, but it is a little bit ugly thus far, so if a +better method is supported by the kernel, zebra will use that. + +@item sysctl +@samp{sysctl} can lookup kernel information using MIB (Management +Information Base) syntax. Normally, it only provides a way of getting +information from the kernel. So one would usually want to change kernel +information using another method such as @samp{ioctl}. + +@item proc filesystem +@samp{proc filesystem} provides an easy way of getting kernel +information. + +@item routing socket + +@item netlink +On recent Linux kernels (2.0.x and 2.2.x), there is a kernel/user +communication support called @code{netlink}. It makes asynchronous +communication between kernel and Zebra possible, similar to a routing +socket on BSD systems. + +Before you use this feature, be sure to select (in kernel configuration) +the kernel/netlink support option 'Kernel/User network link driver' and +'Routing messages'. + +Today, the /dev/route special device file is obsolete. Netlink +communication is done by reading/writing over netlink socket. + +After the kernel configuration, please reconfigure and rebuild Zebra. +You can use netlink as a dynamic routing update channel between Zebra +and the kernel. +@end table diff --git a/doc/main.texi b/doc/main.texi new file mode 100644 index 00000000..7043bf14 --- /dev/null +++ b/doc/main.texi @@ -0,0 +1,186 @@ +@node Zebra +@comment node-name, next, previous, up +@chapter Zebra + +@c SYNOPSIS +@command{zebra} is an IP routing manager. It provides kernel routing +table updates, interface lookups, and redistribution of routes between +different routing protocols. + +@menu +* Invoking zebra:: Running the program +* Interface Commands:: Commands for zebra interfaces +* Static Route Commands:: Commands for adding static routes +* zebra Terminal Mode Commands:: Commands for zebra's VTY +@end menu + + +@node Invoking zebra, Interface Commands, Zebra, Zebra +@comment node-name, next, previous, up +@section Invoking zebra + +Besides the common invocation options (@pxref{Common Invocation Options}), the +@command{zebra} specific invocation options are listed below. + +@table @samp +@item -b +@itemx --batch +Runs in batch mode. @command{zebra} parses configuration file and terminates +immediately. + +@item -k +@itemx --keep_kernel +When zebra starts up, don't delete old self inserted routes. + +@item -l +@itemx --log_mode +Set verbose logging on. + +@item -r +@itemx --retain +When program terminates, retain routes added by zebra. + +@end table + +@node Interface Commands, Static Route Commands, Invoking zebra, Zebra +@comment node-name, next, previous, up +@section Interface Commands + +@deffn Command {interface @var{ifname}} {} +@end deffn + +@deffn {Interface Command} {shutdown} {} +@deffnx {Interface Command} {no shutdown} {} +Up or down the current interface. +@end deffn + +@deffn {Interface Command} {ip address @var{address}} {} +Set ip address for the interface. +@end deffn + +@deffn {Interface Command} {description @var{description} ...} {} +Set description for the interface. +@end deffn + +@deffn {Interface Command} {multicast} {} +@deffnx {Interface Command} {no multicast} {} +Enable or disables multicast flag for the interface. +@end deffn + +@deffn {Interface Command} {bandwidth <1-10000000>} {} +@deffnx {Interface Command} {no bandwidth <1-10000000>} {} +Set bandwidth value to the interface. This is for calculating OSPF +cost. This command does not affect the actual device configuration. +@end deffn + +@node Static Route Commands, zebra Terminal Mode Commands, Interface Commands, Zebra +@comment node-name, next, previous, up +@section Static Route Commands + +Static routing is a very fundamental feature of routing technology. It +defines static prefix and gateway. + +@deffn Command {ip route @var{network} @var{gateway}} {} +@var{network} is destination prefix with format of A.B.C.D/M. +@var{gateway} is gateway for the prefix. When @var{gateway} is +A.B.C.D format. It is taken as a IPv4 address gateway. Otherwise it +is treated as an interface name. + +@example +ip route 10.0.0.0/8 10.0.0.2 +ip route 10.0.0.0/8 ppp0 +@end example + +First example defines 10.0.0.0/8 static route with gateway 10.0.0.2. +Second one defines the same prefix but with gateway to interface ppp0. +@end deffn + +@deffn Command {ip route @var{network} @var{netmask} @var{gateway}} {} +This is alternate version of above command. When @var{network} is +A.B.C.D format, user must define @var{netmask} value with A.B.C.D +format. @var{gateway} is same option as above command + +@example +ip route 10.0.0.0 255.255.255.0 10.0.0.2 +ip route 10.0.0.0 255.255.255.0 ppp0 +@end example + +This is a same setting using this statement. +@end deffn + +@deffn Command {ip route @var{network} @var{gateway} @var{distance}} {} + +@end deffn + +Multiple nexthop static route + +@example +ip route 10.0.0.1/32 10.0.0.2 +ip route 10.0.0.1/32 10.0.0.3 +ip route 10.0.0.1/32 eth0 +@end example + +If there is no route to 10.0.0.2 and 10.0.0.3, and interface eth0 +is reachable, then the last route is installed into the kernel. + +@example +zebra> show ip route +S> 10.0.0.1/32 [1/0] via 10.0.0.2 inactive + via 10.0.0.3 inactive + * is directly connected, eth0 +@end example + +Floating static route + +@deffn Command {ipv6 route @var{network} @var{gateway}} {} + +@end deffn + +@deffn Command {ipv6 route @var{network} @var{gateway} @var{distance}} {} + +@end deffn + + +@deffn Command {table @var{tableno}} {} +Select the primary kernel routing table to be used. This only works +for kernels supporting multiple routing tables (like GNU/Linux 2.2.x +and later). After setting @var{tableno} with this command, +static routes defined after this are added to the specified table. +@end deffn + +@node zebra Terminal Mode Commands, , Static Route Commands, Zebra +@comment node-name, next, previous, up +@section zebra Terminal Mode Commands + +@deffn Command {show ip route} {} +Display current routes which zebra holds in its database. + +@example +@group +Router# show ip route +Codes: K - kernel route, C - connected, S - static, R - RIP, + B - BGP * - FIB route. + +K* 0.0.0.0/0 203.181.89.241 +S 0.0.0.0/0 203.181.89.1 +C* 127.0.0.0/8 lo +C* 203.181.89.240/28 eth0 +@end group +@end example +@end deffn + +@deffn Command {show ipv6 route} {} +@end deffn + +@deffn Command {show interface} {} +@end deffn + +@deffn Command {show ipforward} {} +Display whether the host's IP forwarding function is enabled or not. +Almost any UNIX kernel can be configured with IP forwarding disabled. +If so, the box can't work as a router. +@end deffn + +@deffn Command {show ipv6forward} {} +Display whether the host's IP v6 forwarding is enabled or not. +@end deffn diff --git a/doc/ospf6d.8 b/doc/ospf6d.8 new file mode 100644 index 00000000..1882c10e --- /dev/null +++ b/doc/ospf6d.8 @@ -0,0 +1,127 @@ +.TH OSPF6D 8 "July 2000" "Zebra Beast - OSPF6D" "Version 0.88" + +.SH NAME +ospf6d \- an OSPF routing engine for use with Zebra and IPv6 + +.SH SYNOPSIS +.B ospf6d +[ +.B \-dhv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-P port-number +] + +.SH DESCRIPTION +.B ospf6d +is a routing component that works with the +.B zebra +routing engine. +\fBospf6d\fR. + + +.SH OPTIONS + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this +option will likely default to \fB\fI/usr/local/etc/ospf6d.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When ospf6d starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart ospf6d. The likely default is \fB\fI/var/run/ospf6d.pid\fR. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the ospf6d VTY will listen on. This defaults to +2606, as specified in \fB\fI/etc/services\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB router ospf6 \fR +\fB router zebra \fR -- (Move routes into kernel table) + +\fB network [NETWORK] area [OSPF6-AREA-ID] \fR +\fB no network [NETWORK] \fR + +\fB show ip ospf6 interface \fR +\fB show ip ospf6 neighbor \fR +\fB show ip ospf6 database \fR +\fB show ip ospf6 route \fR + +\fB debug ospf6 ism \fR +\fB debug ospf6 packet \fR +\fB debug ospf6 nsm \fR + + + +.SH FILES + +.TP +.BI /usr/local/sbin/ospf6d +The default location of the +.B ospf6d +binary. + +.TP +.BI /usr/local/etc/ospf6d.conf +The default location of the +.B ospf6d +config file. + +.TP +.BI $(PWD)/ospf6d.log +If the +.B ospf6d +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBospf6d\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line +options, and for config file commands. The definitive document is the +Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The ospf6d process may log to standard output, to a VTY, to a log +file, or through syslog to the system logs. \fBospf6d\fR supports many +debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripd(8), ripngd(8), ospfd(8), bgpd(8), zebra(8), vtysh(1) + + +.SH BUGS +.B ospf6d +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/ospf6d.texi b/doc/ospf6d.texi new file mode 100644 index 00000000..e3ac3d27 --- /dev/null +++ b/doc/ospf6d.texi @@ -0,0 +1,102 @@ +@node OSPFv3, BGP, OSPFv2, Top +@comment node-name, next, previous, up +@chapter OSPFv3 + +@command{ospf6d} is a daemon support OSPF version 3 for IPv6 network. +OSPF for IPv6 is described in RFC2740. + +@menu +* OSPF6 router:: +* OSPF6 area:: +* OSPF6 interface:: +* Redistribute routes to OSPF6:: +* Showing OSPF6 information:: +@end menu + +@node OSPF6 router, OSPF6 area, OSPFv3, OSPFv3 +@comment node-name, next, previous, up +@section OSPF6 router + +@deffn {Command} {router ospf6} {} +@end deffn + +@deffn {OSPF6 Command} {router-id @var{a.b.c.d}} {} +Set router's Router-ID. +@end deffn + +@deffn {OSPF6 Command} {interface @var{ifname} area @var{area}} {} +Bind interface to specified area, and start sending OSPF packets. @var{area} can +be specified as 0. +@end deffn + +@node OSPF6 area, OSPF6 interface, OSPF6 router, OSPFv3 +@comment node-name, next, previous, up +@section OSPF6 area + +Area support for OSPFv3 is not yet implemented. + +@node OSPF6 interface, Redistribute routes to OSPF6, OSPF6 area, OSPFv3 +@comment node-name, next, previous, up +@section OSPF6 interface + +@deffn {Interface Command} {ipv6 ospf6 cost COST} {} +Sets interface's output cost. Default value is 1. +@end deffn + +@deffn {Interface Command} {ipv6 ospf6 hello-interval HELLOINTERVAL} {} +Sets interface's Hello Interval. Default 40 +@end deffn + +@deffn {Interface Command} {ipv6 ospf6 dead-interval DEADINTERVAL} {} +Sets interface's Router Dead Interval. Default value is 40. +@end deffn + +@deffn {Interface Command} {ipv6 ospf6 retransmit-interval RETRANSMITINTERVAL} {} +Sets interface's Rxmt Interval. Default value is 5. +@end deffn + +@deffn {Interface Command} {ipv6 ospf6 priority PRIORITY} {} +Sets interface's Router Priority. Default value is 1. +@end deffn + +@deffn {Interface Command} {ipv6 ospf6 transmit-delay TRANSMITDELAY} {} +Sets interface's Inf-Trans-Delay. Default value is 1. +@end deffn + +@node Redistribute routes to OSPF6, Showing OSPF6 information, OSPF6 interface, OSPFv3 +@comment node-name, next, previous, up +@section Redistribute routes to OSPF6 + +@deffn {OSPF6 Command} {redistribute static} {} +@deffnx {OSPF6 Command} {redistribute connected} {} +@deffnx {OSPF6 Command} {redistribute ripng} {} +@end deffn + +@node Showing OSPF6 information, , Redistribute routes to OSPF6, OSPFv3 +@comment node-name, next, previous, up +@section Showing OSPF6 information + +@deffn {Command} {show ipv6 ospf6 [INSTANCE_ID]} {} +INSTANCE_ID is an optional OSPF instance ID. To see router ID and OSPF +instance ID, simply type "show ipv6 ospf6 ". +@end deffn + +@deffn {Command} {show ipv6 ospf6 database} {} +This command shows LSA database summary. You can specify the type of LSA. +@end deffn + +@deffn {Command} {show ipv6 ospf6 interface} {} +To see OSPF interface configuration like costs. +@end deffn + +@deffn {Command} {show ipv6 ospf6 neighbor} {} +Shows state and chosen (Backup) DR of neighbor. +@end deffn + +@deffn {Command} {show ipv6 ospf6 request-list A.B.C.D} {} +Shows requestlist of neighbor. +@end deffn + +@deffn {Command} {show ipv6 route ospf6} {} +This command shows internal routing table. +@end deffn diff --git a/doc/ospfd.8 b/doc/ospfd.8 new file mode 100644 index 00000000..0fbfce4c --- /dev/null +++ b/doc/ospfd.8 @@ -0,0 +1,131 @@ +.TH OSPFD 8 "July 2000" "Zebra Beast - OSPFD" "Version 0.88" + +.SH NAME +ospfd \- an OSPF v2 routing engine for use with Zebra + +.SH SYNOPSIS +.B ospfd +[ +.B \-dhlv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-P port-number +] + +.SH DESCRIPTION +.B ospfd +is a routing component that works with the +.B zebra +routing engine. + + +.SH OPTIONS + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this +option will likely default to \fB\fI/usr/local/etc/ospfd.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When ospfd starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart ospfd. The likely default is \fB\fI/var/run/ospfd.pid\fR. + +.TP +\fB\-l\fR, \fB\-\-log_mode\fR +Turn verbose logging on. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the ospfd VTY will listen on. This defaults to +2604, as specified in \fB\fI/etc/services\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB router ospf \fR +\fB router zebra \fR -- (Move routes into kernel table) + +\fB network [NETWORK] area [OSPF-AREA-ID] \fR +\fB no network [NETWORK] \fR + +\fB show ip ospf interface \fR +\fB show ip ospf neighbor \fR +\fB show ip ospf database \fR +\fB show ip ospf route \fR + + +\fB debug ospf ism \fR +\fB debug ospf packet \fR +\fB debug ospf nsm \fR + + + +.SH FILES + +.TP +.BI /usr/local/sbin/ospfd +The default location of the +.B ospfd +binary. + +.TP +.BI /usr/local/etc/ospfd.conf +The default location of the +.B ospfd +config file. + +.TP +.BI $(PWD)/ospfd.log +If the +.B ospfd +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBospfd\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line +options, and for config file commands. The definitive document is the +Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The ospfd process may log to standard output, to a VTY, to a log +file, or through syslog to the system logs. \fBospfd\fR supports many +debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripd(8), ripngd(8), ospf6d(8), bgpd(8), zebra(8), vtysh(1) + + +.SH BUGS +.B ospfd +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/ospfd.texi b/doc/ospfd.texi new file mode 100644 index 00000000..5952c051 --- /dev/null +++ b/doc/ospfd.texi @@ -0,0 +1,345 @@ +@node OSPFv2, OSPFv3, RIPng, Top +@comment node-name, next, previous, up +@chapter OSPFv2 + + OSPF version 2 is a routing protocol which described in +@asis{RFC2328} - @cite{OSPF Version 2}. OSPF is IGP (Interior Gateway +Protocols). Compared with RIP, OSPF can provide scalable network +support and faster convergence time. OSPF is widely used in large +networks such as ISP backbone and enterprise networks. + +@menu +* Configuring ospfd:: +* OSPF router:: +* OSPF area:: +* OSPF interface:: +* Redistribute routes to OSPF:: +* Showing OSPF information:: +* Debugging OSPF:: +@end menu + +@node Configuring ospfd, OSPF router, OSPFv2, OSPFv2 +@comment node-name, next, previous, up +@section Configuring ospfd + +There is no @command{ospfd} specific options. Common options can be +specified (@pxref{Common Invocation Options}) to @command{ospfd}. +@command{ospfd} needs interface information from @command{zebra}. So +please make it sure @command{zebra} is running before invoking +@command{ospfd}. + +Like other daemons, @command{ospfd} configuration is done in OSPF +specific configuration file @file{ospfd.conf}. + +@node OSPF router, OSPF area, Configuring ospfd, OSPFv2 +@comment node-name, next, previous, up +@section OSPF router + +To start OSPF process you have to specify the OSPF router. As of this +writing, @command{ospfd} does not support multiple OSPF processes. + +@deffn Command {router ospf} {} +@deffnx Command {no router ospf} {} +Enable or disable the OSPF process. @command{ospfd} does not yet +support multiple OSPF processes. So you can not specify an OSPF process +number. +@end deffn + +@deffn {OSPF Command} {ospf router-id @var{a.b.c.d}} {} +@deffnx {OSPF Command} {no ospf router-id} {} +@end deffn + +@deffn {OSPF Command} {ospf abr-type @var{type}} {} +@deffnx {OSPF Command} {no ospf abr-type @var{type}} {} +@var{type} can be cisco|ibm|shortcut|standard +@end deffn + +@deffn {OSPF Command} {ospf rfc1583compatibility} {} +@deffnx {OSPF Command} {no ospf rfc1583compatibility} {} +@end deffn + +@deffn {OSPF Command} {passive interface @var{interface}} {} +@deffnx {OSPF Command} {no passive interface @var{interface}} {} +@end deffn + +@deffn {OSPF Command} {timers spf <0-4294967295> <0-4294967295>} {} +@deffnx {OSPF Command} {no timers spf} {} +@end deffn + +@deffn {OSPF Command} {refresh group-limit <0-10000>} {} +@deffnx {OSPF Command} {refresh per-slice <0-10000>} {} +@deffnx {OSPF Command} {refresh age-diff <0-10000>} {} +@end deffn + +@deffn {OSPF Command} {auto-cost refrence-bandwidth <1-4294967>} {} +@deffnx {OSPF Command} {no auto-cost refrence-bandwidth} {} +@end deffn + +@deffn {OSPF Command} {network @var{a.b.c.d/m} area @var{a.b.c.d}} {} +@deffnx {OSPF Command} {network @var{a.b.c.d/m} area @var{<0-4294967295>}} {} +@deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{a.b.c.d}} {} +@deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{<0-4294967295>}} {} +This command specifies the OSPF enabled interface. If the interface has +an address of 10.0.0.1/8 then the command below provides network +information to the ospf routers +@example +@group +router ospf + network 10.0.0.0/8 area 0 +@end group +@end example +the network command's mask length should be the same as the interface +address's mask. +@end deffn + +@node OSPF area, OSPF interface, OSPF router, OSPFv2 +@comment node-name, next, previous, up +@section OSPF area + +@deffn {OSPF Command} {area @var{a.b.c.d} range @var{a.b.c.d/m}} {} +@deffnx {OSPF Command} {area <0-4294967295> range @var{a.b.c.d/m}} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} range @var{a.b.c.d/m}} {} +@deffnx {OSPF Command} {no area <0-4294967295> range @var{a.b.c.d/m}} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} range IPV4_PREFIX suppress} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} range IPV4_PREFIX suppress} {} +@deffnx {OSPF Command} {area @var{a.b.c.d} range IPV4_PREFIX substitute IPV4_PREFIX} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} range IPV4_PREFIX substitute IPV4_PREFIX} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} virtual-link @var{a.b.c.d}} {} +@deffnx {OSPF Command} {area <0-4294967295> virtual-link @var{a.b.c.d}} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} virtual-link @var{a.b.c.d}} {} +@deffnx {OSPF Command} {no area <0-4294967295> virtual-link @var{a.b.c.d}} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} shortcut} {} +@deffnx {OSPF Command} {area <0-4294967295> shortcut} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} shortcut} {} +@deffnx {OSPF Command} {no area <0-4294967295> shortcut} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} stub} {} +@deffnx {OSPF Command} {area <0-4294967295> stub} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} stub} {} +@deffnx {OSPF Command} {no area <0-4294967295> stub} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} stub no-summary} {} +@deffnx {OSPF Command} {area <0-4294967295> stub no-summary} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} stub no-summary} {} +@deffnx {OSPF Command} {no area <0-4294967295> stub no-summary} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} default-cost <0-16777215>} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} default-cost <0-16777215>} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} export-list NAME} {} +@deffnx {OSPF Command} {area <0-4294967295> export-list NAME} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} export-list NAME} {} +@deffnx {OSPF Command} {no area <0-4294967295> export-list NAME} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} import-list NAME} {} +@deffnx {OSPF Command} {area <0-4294967295> import-list NAME} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} import-list NAME} {} +@deffnx {OSPF Command} {no area <0-4294967295> import-list NAME} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} authentication} {} +@deffnx {OSPF Command} {area <0-4294967295> authentication} {} +@deffnx {OSPF Command} {no area @var{a.b.c.d} authentication} {} +@deffnx {OSPF Command} {no area <0-4294967295> authentication} {} +@end deffn + +@deffn {OSPF Command} {area @var{a.b.c.d} authentication message-digest} {} +@deffnx {OSPF Command} {area <0-4294967295> authentication message-digest} {} +@end deffn + +@node OSPF interface, Redistribute routes to OSPF, OSPF area, OSPFv2 +@comment node-name, next, previous, up +@section OSPF interface + +@deffn {Interface Command} {ip ospf authentication-key AUTH_KEY} {} +@deffnx {Interface Command} {no ip ospf authentication-key} {} +Set OSPF authentication key to a simple password. After setting @var{AUTH_KEY}, +all OSPF packets are authenticated. @var{AUTH_KEY} has length up to 8 chars. +@end deffn + +@deffn {Interface Command} {ip ospf message-digest-key KEYID md5 KEY} {} +@deffnx {Interface Command} {no ip ospf message-digest-key} {} +Set OSPF authentication key to a cryptographic password. The cryptographic +algorithm is MD5. KEYID identifies secret key used to create the message +digest. KEY is the actual message digest key up to 16 chars. +@end deffn + +@deffn {Interface Command} {ip ospf cost <1-65535>} {} +@deffnx {Interface Command} {no ip ospf cost} {} +Set link cost for the specified interface. The cost value is set to router-LSA's +metric field and used for SPF calculation. +@end deffn + +@deffn {Interface Command} {ip ospf dead-interval <1-65535>} {} +@deffnx {Interface Command} {no ip ospf dead-interval} {} +Set number of seconds for RouterDeadInterval timer value used for Wait Timer +and Inactivity Timer. This value must be the same for all routers attached +to a common network. The default value is 40 seconds. +@end deffn + +@deffn {Interface Command} {ip ospf hello-interval <1-65535>} {} +@deffnx {Interface Command} {no ip ospf hello-interval} {} +Set number of seconds for HelloInterval timer value. Setting this value, +Hello packet will be sent every timer value seconds on the specified interface. +This value must be the same for all routers attached to a common network. +The default value is 10 seconds. +@end deffn + +@deffn {Interface Command} {ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)} {} +@deffnx {Interface Command} {no ip ospf network} {} +Set explicitly network type for specifed interface. +@end deffn + +@deffn {Interface Command} {ip ospf priority <0-255>} {} +@deffnx {Interface Command} {no ip ospf priority} {} +Set RouterPriority integer value. Setting higher value, router will be more +eligible to become Designated Router. Setting the value to 0, router is no +longer eligible to Designated Router. +The default value is 1. +@end deffn + +@deffn {Interface Command} {ip ospf retransmit-interval <1-65535>} {} +@deffnx {Interface Command} {no ip ospf retransmit interval} {} +Set number of seconds for RxmtInterval timer value. This value is used +when retransmitting Database Description and Link State Request packets. +The default value is 5 seconds. +@end deffn + +@deffn {Interface Command} {ip ospf transmit-delay} {} +@deffnx {Interface Command} {no ip ospf transmit-delay} {} +Set number of seconds for InfTransDelay value. LSAs' age should be +incremented by this value when transmitting. +The default value is 1 seconds. +@end deffn + +@node Redistribute routes to OSPF, Showing OSPF information, OSPF interface, OSPFv2 +@comment node-name, next, previous, up +@section Redistribute routes to OSPF + +@deffn {OSPF Command} {redistribute (kernel|connected|static|rip|bgp)} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) @var{route-map}} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric-type (1|2)} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) route-map @var{word}} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric <0-16777214>} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> route-map @var{word}} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214>} {} +@deffnx {OSPF Command} {redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214> route-map @var{word}} {} +@deffnx {OSPF Command} {no redistribute (kernel|connected|static|rip|bgp)} {} +@end deffn + +@deffn {OSPF Command} {default-information originate} {} +@deffnx {OSPF Command} {default-information originate metric <0-16777214>} {} +@deffnx {OSPF Command} {default-information originate metric <0-16777214> metric-type (1|2)} {} +@deffnx {OSPF Command} {default-information originate metric <0-16777214> metric-type (1|2) route-map @var{word}} {} +@deffnx {OSPF Command} {default-information originate always} {} +@deffnx {OSPF Command} {default-information originate always metric <0-16777214>} {} +@deffnx {OSPF Command} {default-information originate always metric <0-16777214> metric-type (1|2)} {} +@deffnx {OSPF Command} {default-information originate always metric <0-16777214> metric-type (1|2) route-map @var{word}} {} +@deffnx {OSPF Command} {no default-information originate} {} +@end deffn + +@deffn {OSPF Command} {distribute-list NAME out (kernel|connected|static|rip|ospf} {} +@deffnx {OSPF Command} {no distribute-list NAME out (kernel|connected|static|rip|ospf} {} +@end deffn + +@deffn {OSPF Command} {default-metric <0-16777214>} {} +@deffnx {OSPF Command} {no default-metric} {} +@end deffn + +@deffn {OSPF Command} {distance <1-255>} {} +@deffnx {OSPF Command} {no distance <1-255>} {} +@end deffn + +@deffn {OSPF Command} {distance ospf (intra-area|inter-area|external) <1-255>} {} +@deffnx {OSPF Command} {no distance ospf} {} +@end deffn + +@deffn {Command} {router zebra} {} +@deffnx {Command} {no router zebra} {} +@end deffn + +@node Showing OSPF information, Debugging OSPF, Redistribute routes to OSPF, OSPFv2 +@comment node-name, next, previous, up +@section Showing OSPF information + +@deffn {Command} {show ip ospf} {} +@end deffn + +@deffn {Command} {show ip ospf interface [INTERFACE]} {} +@end deffn + +@deffn {Command} {show ip ospf neighbor} {} +@deffnx {Command} {show ip ospf neighbor INTERFACE} {} +@deffnx {Command} {show ip ospf neighbor detail} {} +@deffnx {Command} {show ip ospf neighbor INTERFACE detail} {} +@end deffn + +@deffn {Command} {show ip ospf database} {} +@end deffn + +@deffn {Command} {show ip ospf database (asbr-summary|external|network|router|summary)} {} +@deffnx {Command} {show ip ospf database (asbr-summary|external|network|router|summary) @var{link-state-id}} {} +@deffnx {Command} {show ip ospf database (asbr-summary|external|network|router|summary) @var{link-state-id} adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (asbr-summary|external|network|router|summary) adv-router @var{adv-router}} {} +@deffnx {Command} {show ip ospf database (asbr-summary|external|network|router|summary) @var{link-state-id} self-originate} {} +@deffnx {Command} {show ip ospf database (asbr-summary|external|network|router|summary) self-originate} {} +@end deffn + +@deffn {Command} {show ip ospf database max-age} {} +@end deffn + +@deffn {Command} {show ip ospf database self-originate} {} +@end deffn + +@deffn {Command} {show ip ospf refresher} {} +@end deffn + +@deffn {Command} {show ip ospf route} {} +@end deffn + +@node Debugging OSPF, , Showing OSPF information, OSPFv2 +@comment node-name, next, previous, up +@section Debugging OSPF + +@deffn {Command} {debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} +@deffnx {Command} {no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]} {} +@end deffn + +@deffn {Command} {debug ospf ism} {} +@deffnx {Command} {debug ospf ism (status|events|timers)} {} +@deffnx {Command} {no debug ospf ism} {} +@deffnx {Command} {no debug ospf ism (status|events|timers)} {} +@end deffn + +@deffn {Command} {debug ospf nsm} {} +@deffnx {Command} {debug ospf nsm (status|events|timers)} {} +@deffnx {Command} {no debug ospf nsm} {} +@deffnx {Command} {no debug ospf nsm (status|events|timers)} {} +@end deffn + +@deffn {Command} {debug ospf lsa} {} +@deffnx {Command} {debug ospf lsa (generate|flooding|refresh)} {} +@deffnx {Command} {no debug ospf lsa} {} +@deffnx {Command} {no debug ospf lsa (generate|flooding|refresh)} {} +@end deffn + +@deffn {Command} {debug ospf zebra} {} +@deffnx {Command} {debug ospf zebra (interface|redistribute)} {} +@deffnx {Command} {no debug ospf zebra} {} +@deffnx {Command} {no debug ospf zebra (interface|redistribute)} {} +@end deffn + +@deffn {Command} {show debugging ospf} {} +@end deffn + diff --git a/doc/overview.texi b/doc/overview.texi new file mode 100644 index 00000000..68e6e391 --- /dev/null +++ b/doc/overview.texi @@ -0,0 +1,352 @@ +@node Overview, Installation, Top, Top +@comment node-name, next, previous, up +@chapter Overview +@cindex Overview + + Zebra is a routing software package that provides TCP/IP based +routing services with routing protocols support such as RIPv1, RIPv2, +RIPng, OSPFv2, OSPFv3, BGP-4, and BGP-4+ (@pxref{Supported RFC}). +Zebra also supports special BGP Route Reflector and Route Server +behavior. In addition to traditional IPv4 routing protocols, Zebra +also supports IPv6 routing protocols. With SNMP daemon which supports +SMUX protocol, Zebra provides routing protocol MIBs (@pxref{SNMP +Support}). + + Zebra uses an advanced software architecture to provide you with a +high quality, multi server routing engine. Zebra has an interactive +user interface for each routing protocol and supports common client +commands. Due to this design, you can add new protocol daemons to Zebra +easily. You can use Zebra library as your program's client user +interface. + + Zebra is an official @sc{gnu} software and distributed under the +@sc{gnu} General Public License. + +@menu +* About Zebra:: Basic information about Zebra +* System Architecture:: The Zebra system architecture +* Supported Platforms:: Supported platforms and future plans +* Supported RFC:: Supported RFCs +* How to get Zebra:: +* Mailing List:: Mailing list information +* Bug Reports:: Mail address for bug data +@end menu + +@node About Zebra, System Architecture, Overview, Overview +@comment node-name, next, previous, up +@section About Zebra +@cindex About Zebra + + Today, TCP/IP networks are covering all of the world. The Internet +has been deployed in many countries, companies, and to the home. When +you connect to the Internet your packet will pass many routers which +have TCP/IP routing functionality. + + A system with Zebra installed acts as a dedicated router. With Zebra, +your machine exchanges routing information with other routers using +routing protocols. Zebra uses this information to update the kernel +routing table so that the right data goes to the right place. You can +dynamically change the configuration and you may view routing table +information from the Zebra terminal interface. + + Adding to routing protocol support, Zebra can setup interface's flags, +interface's address, static routes and so on. If you have a small +network, or a stub network, or xDSL connection, configuring the Zebra +routing software is very easy. The only thing you have to do is to set +up the interfaces and put a few commands about static routes and/or +default routes. If the network is rather large, or if the network +structure changes frequently, you will want to take advantage of Zebra's +dynamic routing protocol support for protocols such as RIP, OSPF or BGP. +Zebra is with you. + + Traditionally, UNIX based router configuration is done by +@command{ifconfig} and @command{route} commands. Status of routing +table is displayed by @command{netstat} utility. Almost of these +commands work only if the user has root privileges. Zebra has a different +system administration method. There are two user modes in Zebra. One is +normal mode, the other is enable mode. Normal mode user can only view +system status, enable mode user can change system configuration. This +UNIX account independent feature will be great help to the router +administrator. + + Currently, Zebra supports common unicast routing protocols. Multicast +routing protocols such as BGMP, PIM-SM, PIM-DM will be supported in +Zebra 2.0. MPLS support is going on. In the future, TCP/IP filtering +control, QoS control, diffserv configuration will be added to Zebra. +Zebra project's final goal is making a productive, quality free TCP/IP +routing software. + +@node System Architecture, Supported Platforms, About Zebra, Overview +@comment node-name, next, previous, up +@section System Architecture +@cindex System architecture +@cindex Software architecture +@cindex Software internals + + Traditional routing software is made as a one process program which +provides all of the routing protocol functionalities. Zebra takes a +different approach. It is made from a collection of several daemons +that work together to build the routing table. There may be several +protocol-specific routing daemons and zebra the kernel routing manager. + + The @command{ripd} daemon handles the RIP protocol, while +@command{ospfd} is a daemon which supports OSPF version 2. +@command{bgpd} supports the BGP-4 protocol. For changing the kernel +routing table and for redistribution of routes between different routing +protocols, there is a kernel routing table manager @command{zebra} +daemon. It is easy to add a new routing protocol daemons to the entire +routing system without affecting any other software. You need to run only +the protocol daemon associated with routing protocols in use. Thus, +user may run a specific daemon and send routing reports to a central +routing console. + + There is no need for these daemons to be running on the same machine. +You can even run several same protocol daemons on the same machine. This +architecture creates new possibilities for the routing system. + +@example +@group ++----+ +----+ +-----+ +-----+ +|bgpd| |ripd| |ospfd| |zebra| ++----+ +----+ +-----+ +-----+ + | ++---------------------------|--+ +| v | +| UNIX Kernel routing table | +| | ++------------------------------+ + + Zebra System Architecture +@end group +@end example + + Multi-process architecture brings extensibility, modularity and +maintainability. At the same time it also brings many configuration +files and terminal interfaces. Each daemon has it's own configuration +file and terminal interface. When you configure a static route, it must +be done in @command{zebra} configuration file. When you configure BGP +network it must be done in @command{bgpd} configuration file. This can be a +very annoying thing. To resolve the problem, Zebra provides integrated +user interface shell called @command{vtysh}. @command{vtysh} connects to +each daemon with UNIX domain socket and then works as a proxy for user input. + + Zebra was planned to use multi-threaded mechanism when it runs with a +kernel that supports multi-threads. But at the moment, the thread +library which comes with @sc{gnu}/Linux or FreeBSD has some problems with +running reliable services such as routing software, so we don't use +threads at all. Instead we use the @command{select(2)} system call for +multiplexing the events. + + When @command{zebra} runs under a @sc{gnu} Hurd kernel it will act as a +kernel routing table itself. Under @sc{gnu} Hurd, all TCP/IP services are +provided by user processes called @command{pfinet}. Zebra will provide +all the routing selection mechanisms for the process. This feature will +be implemented when @sc{gnu} Hurd becomes stable. + +@node Supported Platforms, Supported RFC, System Architecture, Overview +@comment node-name, next, previous, up +@section Supported Platforms + +@cindex Supported platforms +@cindex Zebra on other systems +@cindex Compatibility with other systems +@cindex Operating systems that support Zebra + + Currently Zebra supports @sc{gnu}/Linux, BSD and Solaris. Below is a list +of OS versions on which Zebra runs. Porting Zebra to other platforms is +not so too difficult. Platform dependent codes exist only in +@command{zebra} daemon. Protocol daemons are platform independent. +Please let us know when you find out Zebra runs on a platform which is not +listed below. + +@sp 1 +@itemize @bullet +@item +GNU/Linux 2.0.37 +@item +GNU/Linux 2.2.x +@item +GNU/Linux 2.3.x +@item +FreeBSD 2.2.8 +@item +FreeBSD 3.x +@item +FreeBSD 4.x +@item +NetBSD 1.4 +@item +OpenBSD 2.5 +@item +Solaris 2.6 +@item +Solaris 7 +@end itemize + +@sp 1 + Some IPv6 stacks are in development. Zebra supports following IPv6 +stacks. For BSD, we recommend KAME IPv6 stack. Solaris IPv6 stack is +not yet supported. +@sp 1 +@itemize @bullet +@item +Linux IPv6 stack for GNU/Linux 2.2.x and higher. +@item +KAME IPv6 stack for BSD. +@item +INRIA IPv6 stack for BSD. +@end itemize + +@node Supported RFC, How to get Zebra, Supported Platforms, Overview +@comment node-name, next, previous, up +@section Supported RFC + + Below is the list of currently supported RFC's. + +@table @asis +@item @asis{RFC1058} +@cite{Routing Information Protocol. C.L. Hedrick. Jun-01-1988.} + +@item @asis{RF2082} +@cite{RIP-2 MD5 Authentication. F. Baker, R. Atkinson. January 1997.} + +@item @asis{RFC2453} +@cite{RIP Version 2. G. Malkin. November 1998.} + +@item @asis{RFC2080} +@cite{RIPng for IPv6. G. Malkin, R. Minnear. January 1997.} + +@item @asis{RFC2328} +@cite{OSPF Version 2. J. Moy. April 1998.} + +@item @asis{RFC2740} +@cite{OSPF for IPv6. R. Coltun, D. Ferguson, J. Moy. December 1999.} + +@item @asis{RFC1771} +@cite{A Border Gateway Protocol 4 (BGP-4). Y. Rekhter & T. Li. March 1995.} + +@item @asis{RFC1965} +@cite{Autonomous System Confederations for BGP. P. Traina. June 1996.} + +@item @asis{RFC1997} +@cite{BGP Communities Attribute. R. Chandra, P. Traina & T. Li. August 1996.} + +@item @asis{RFC2545} +@cite{Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing. P. Marques, F. Dupont. March 1999.} + +@item @asis{RFC2796} +@cite{BGP Route Reflection An alternative to full mesh IBGP. T. Bates & R. Chandrasekeran. June 1996.} + +@item @asis{RFC2858} +@cite{Multiprotocol Extensions for BGP-4. T. Bates, Y. Rekhter, R. Chandra, D. Katz. June 2000.} + +@item @asis{RFC2842} +@cite{Capabilities Advertisement with BGP-4. R. Chandra, J. Scudder. May 2000.} + +@end table + + When SNMP support is enabled, below RFC is also supported. + +@table @asis + +@item @asis{RFC1227} +@cite{SNMP MUX protocol and MIB. M.T. Rose. May-01-1991.} + +@item @asis{RFC1657} +@cite{Definitions of Managed Objects for the Fourth Version of the +Border Gateway Protocol (BGP-4) using SMIv2. S. Willis, J. Burruss, +J. Chu, Editor. July 1994.} + +@item @asis{RFC1724} +@cite{RIP Version 2 MIB Extension. G. Malkin & F. Baker. November 1994.} + +@item @asis{RFC1850} +@cite{OSPF Version 2 Management Information Base. F. Baker, R. Coltun. +November 1995.} + +@end table + +@node How to get Zebra, Mailing List, Supported RFC, Overview +@comment node-name, next, previous, up +@section How to get Zebra + + Zebra is still beta software and there is no officially +released version. So currently Zebra is distributed from Zebra beta ftp +site located at: + +@url{ftp://ftp.zebra.org/pub/zebra} + + Once Zebra is released you can get it from @sc{gnu} FTP site and +its mirror sites. We are planning Zebra-1.0 as the first released +version. + + Zebra's official web page is located at: + +@url{http://www.gnu.org/software/zebra/zebra.html}. + + There is a Zebra beta tester web page at: + +@url{http://www.zebra.org/}. + + You can get the latest beta software information from this page. + +@node Mailing List, Bug Reports, How to get Zebra, Overview +@comment node-name, next, previous, up +@section Mailing List +@cindex How to get in touch with Zebra +@cindex Mailing Zebra +@cindex Contact information +@cindex Mailing lists + + There is a mailing list for discussions about Zebra. If you have any +comments or suggestions to Zebra, please send mail to +@email{zebra@@zebra.org}. New snapshot announcements, improvement +notes, and patches are sent to the list. + + To subscribe to the @email{zebra@@zebra.org, Zebra mailing list}, +please send a mail to @email{majordomo@@zebra.org} with a message body +that includes only: + +@quotation +subscribe zebra +@end quotation + + To unsubscribe from the list, please send a mail to +@email{majordomo@@zebra.org} with a message body that includes only: + +@quotation +unsubscribe zebra +@end quotation + +@node Bug Reports, , Mailing List, Overview +@comment node-name, next, previous, up +@section Bug Reports + +@cindex Bug Reports +@cindex Bug hunting +@cindex Found a bug? +@cindex Reporting bugs +@cindex Reporting software errors +@cindex Errors in the software + + If you think you have found a bug, please send a bug report to +@email{bug-zebra@@gnu.org}. When you send a bug report, please be +careful about the points below. + +@itemize @bullet +@item +Please note what kind of OS you are using. If you use the IPv6 stack +please note that as well. +@item +Please show us the results of @code{netstat -rn} and @code{ifconfig -a}. +Information from zebra's VTY command @code{show ip route} will also be +helpful. +@item +Please send your configuration file with the report. If you specify +arguments to the configure script please note that too. +@end itemize + + Bug reports are very important for us to improve the quality of Zebra. +Zebra is still in the development stage, but please don't hesitate to +send a bug report to @email{bug-zebra@@gnu.org}. + diff --git a/doc/protocol.texi b/doc/protocol.texi new file mode 100644 index 00000000..7cae9c9d --- /dev/null +++ b/doc/protocol.texi @@ -0,0 +1,52 @@ +@node Zebra Protocol, Packet Binary Dump Format, SNMP Support, Top +@comment node-name, next, previous, up +@appendix Zebra Protocol + +Zebra Protocol is a protocol which is used between protocol daemon and +zebra. Each protocol daemon sends selected routes to zebra daemon. Then +zebra manages which route is installed into the forwarding table. + +Zebra Protocol is a TCP-based protocol. Below is common header of Zebra +Protocol. + +@example +@group +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Length (2) | Command (1) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example + +Length is total packet length including this header length. So minimum +length is three. Command is Zebra Protocol command. + +@example +ZEBRA_INTERFACE_ADD 1 +ZEBRA_INTERFACE_DELETE 2 +ZEBRA_INTERFACE_ADDRESS_ADD 3 +ZEBRA_INTERFACE_ADDRESS_DELETE 4 +ZEBRA_INTERFACE_UP 5 +ZEBRA_INTERFACE_DOWN 6 +ZEBRA_IPV4_ROUTE_ADD 7 +ZEBRA_IPV4_ROUTE_DELETE 8 +ZEBRA_IPV6_ROUTE_ADD 9 +ZEBRA_IPV6_ROUTE_DELETE 10 +ZEBRA_REDISTRIBUTE_ADD 11 +ZEBRA_REDISTRIBUTE_DELETE 12 +ZEBRA_REDISTRIBUTE_DEFAULT_ADD 13 +ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 14 +ZEBRA_IPV4_NEXTHOP_LOOKUP 15 +ZEBRA_IPV6_NEXTHOP_LOOKUP 16 +@end example + +@example +@group +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type | Flags | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +@end group +@end example diff --git a/doc/ripd.8 b/doc/ripd.8 new file mode 100644 index 00000000..e15989ff --- /dev/null +++ b/doc/ripd.8 @@ -0,0 +1,212 @@ +.TH RIPD 8 "July 2000" "Zebra" "Version 0.88" + +.SH NAME +ripd \- a RIP routing engine for use with Zebra + +.SH SYNOPSIS +.B ripd +[ +.B \-dhrv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-P port-number +] + +.SH DESCRIPTION +.B ripd +is a routing component that supports the +.B zebra +route engine. +.B ripd +supports RIPv1, RIPv2, and so forth. + + +.SH OPTIONS + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this option will likely default to \fB\fI/usr/local/etc/ripd.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When ripd starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart ripd. The likely default is \fB\fI/var/run/ripd.pid\fR. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the ripd VTY will listen on. This defaults to +2602, as specified in \fB\fI/etc/services\fR. + +.TP +\fB\-r\fR, \fB\-\-retain\fR +When the program terminates, retain routes added by \fBripd\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB router rip \fR +\fB no router rip \fR + +\fB rip version [1|2] \fR +\fB no rip version [1|2] \fR + +\fB network [A.B.C.D/M] \fR +\fB no network [A.B.C.D/M] \fR + +\fB network [IFNAME] \fR +\fB no network [IFNAME] \fR + +\fB neighbor [A.B.C.D] \fR +\fB no neighbor [A.B.C.D] \fR + +\fB redistribute kernel \fR +\fB redistribute kernel metric [METRIC]\fR +\fB redistribute kernel route-map [ROUTE-MAP]\fR +\fB no redistribute kernel \fR + +\fB redistribute static \fR +\fB redistribute static metric [METRIC]\fR +\fB redistribute static route-map [ROUTE-MAP]\fR +\fB no redistribute static \fR + +\fB redistribute connected \fR +\fB redistribute connected metric [METRIC]\fR +\fB redistribute connected route-map [ROUTE-MAP]\fR +\fB no redistribute connected \fR + +\fB redistribute ospf \fR +\fB redistribute ospf metric [METRIC]\fR +\fB redistribute ospf route-map [ROUTE-MAP]\fR +\fB no redistribute ospf \fR + +\fB redistribute bgp \fR +\fB redistribute bgp metric [METRIC]\fR +\fB redistribute bgp route-map [ROUTE-MAP]\fR +\fB no redistribute bgp \fR + +\fB route [A.B.C.D/M] \fR +\fB no route [A.B.C.D/M] \fR + +\fB default-information originate \fR +\fB no default-information originate \fR + +\fB default-metric [METRIC] \fR +\fB no default-metric [METRIC] \fR + +\fB passive-interface [IFNAME] \fR +\fB no passive-interface [IFNAME] \fR + +\fB offset-list [ACCESS-LIST] [in|out]\fR +\fB offset-list [ACCESS-LIST] [in|out] [IFNAME]\fR +\fB no offset-list [ACCESS-LIST] [in|out]\fR + +\fB timers basic [UPDATE-INTERVAL] [INVALID] [TIMEOUT] [GARBAGE-COLLECT] \fR +\fB no timers basic \fR + +\fB distribute-list [ACCESS-LIST] [in|out] [IFNAME] \fR +\fB no distribute-list [ACCESS-LIST] [in|out] [IFNAME] \fR + +\fB distribute-list prefix [PREFIX-LIST] [in|out] [IFNAME] \fR +\fB no distribute-list prefix [PREFIX-LIST] [in|out] [IFNAME] \fR + +\fB distance [DISTANCE] \fR +\fB no distance [DISTANCE] \fR + +\fB distance [DISTANCE] [A.B.C.D/M] \fR +\fB no distance [DISTANCE] [A.B.C.D/M] \fR + +\fB distance [DISTANCE] [A.B.C.D/M] [ACCESS-LIST]\fR +\fB no distance [DISTANCE] [A.B.C.D/M] [ACCESS-LIST]\fR + +\fB ip rip send version [VERSION] \fR +\fB no ip rip send version [VERSION] \fR +\fB ip rip receive version [VERSION] \fR +\fB no ip rip receive version [VERSION] \fR + +\fB ip rip authentication mode [md5|text]\fR +\fB no ip rip authentication mode [md5|text]\fR + +\fB ip rip authentication key-chain [KEY-CHAIN]\fR +\fB no ip rip authentication key-chain [KEY-CHAIN]\fR + +\fB ip rip authentication string [STRING]\fR +\fB no ip rip authentication string [STRING]\fR + +\fB ip spli-horizon\fR +\fB no ip spli-horizon\fR + +\fB show ip rip \fR +\fB show ip protocols \fR +\fB show debugging rip \fR + +\fB debug rip \fR +\fB debug rip events \fR +\fB debug rip packet \fR +\fB debug rip zebra \fR + +.SH FILES + +.TP +.BI /usr/local/sbin/ripd +The default location of the +.B ripd +binary. + +.TP +.BI /usr/local/etc/ripd.conf +The default location of the +.B ripd +config file. + +.TP +.BI $(PWD)/ripd.log +If the +.B ripd +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBripd\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line options, and for config file commands. The definitive document is the Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The ripd process may log to standard output, to a VTY, to a log file, or through syslog to the system logs. +.B ripd +supports many debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripngd(8), ospfd(8), ospf6d(8), bgpd(8), zebra(8) + + + +.SH BUGS +.B ripd +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. diff --git a/doc/ripd.texi b/doc/ripd.texi new file mode 100644 index 00000000..d598ca66 --- /dev/null +++ b/doc/ripd.texi @@ -0,0 +1,584 @@ +@c -*-texinfo-*- +@c This is part of the GNU Zebra Manual. +@c Copyright (C) 1999, 2000 Kunihiro Ishiguro +@c See file zebra.texi for copying conditions. +@node RIP +@comment node-name, next, previous, up +@chapter RIP + +RIP -- Routing Information Protocol is widely deployed interior gateway +protocol. RIP was developed in the 1970s at Xerox Labs as part of the +XNS routing protocol. RIP is a @dfn{distance-vector} protocol and is +based on the @dfn{Bellman-Ford} algorithms. As a distance-vector +protocol, RIP router send updates to its neighbors periodically, thus +allowing the convergence to a known topology. In each update, the +distance to any given network will be broadcasted to its neighboring +router. + +@command{ripd} supports RIP version 2 as described in RFC2453 and RIP +version 1 as described in RFC1058. + +@menu +* Starting and Stopping ripd:: +* RIP Configuration:: +* How to Announce RIP route:: +* Filtering RIP Routes:: +* RIP Metric Manipulation:: +* RIP distance:: +* RIP route-map:: +* RIP Authentication:: +* RIP Timers:: +* Show RIP Information:: +* RIP Debug Commands:: +@end menu + +@node Starting and Stopping ripd, RIP Configuration, RIP, RIP +@comment node-name, next, previous, up +@section Starting and Stopping ripd + +The default configuration file name of @command{ripd}'s is +@file{ripd.conf}. When invocation @command{ripd} searches directory +@value{INSTALL_PREFIX_ETC}. If @file{ripd.conf} is not there next +search current directory. + +RIP uses UDP port 521 to send and receive RIP packets. So the user must have +the capability to bind the port, generally this means that the user must +have superuser privileges. RIP protocol requires interface information +maintained by @command{zebra} daemon. So running @command{zebra} +is mandatory to run @command{ripd}. Thus minimum sequence for running +RIP is like below: + +@example +@group +# zebra -d +# ripd -d +@end group +@end example + +Please note that @command{zebra} must be invoked before @command{ripd}. + +To stop @command{ripd}. Please use @command{kill `cat +/var/run/ripd.pid`}. Certain signals have special meaningss to @command{ripd}. + +@table @samp +@item SIGHUP +Reload configuration file @file{ripd.conf}. All configurations are +reseted. All routes learned so far are cleared and removed from routing +table. +@item SIGUSR1 +Rotate @command{ripd} logfile. +@item SIGINT +@itemx SIGTERM +@command{ripd} sweeps all installed RIP routes then terminates properly. +@end table + +@command{ripd} invocation options. Common options that can be specified +(@pxref{Common Invocation Options}). + +@table @samp +@item -r +@itemx --retain +When the program terminates, retain routes added by @command{ripd}. +@end table + +@menu +* RIP netmask:: +@end menu + +@node RIP netmask, , Starting and Stopping ripd, Starting and Stopping ripd +@comment node-name, next, previous, up +@subsection RIP netmask + +The netmask features of @command{ripd} support both version 1 and version 2 of +RIP. Version 1 of RIP originally contained no netmask information. In +RIP version 1, network classes were originally used to determine the +size of the netmask. Class A networks use 8 bits of mask, Class B +networks use 16 bits of masks, while Class C networks use 24 bits of +mask. Today, the most widely used method of a network mask is assigned +to the packet on the basis of the interface that received the packet. +Version 2 of RIP supports a variable length subnet mask (VLSM). By +extending the subnet mask, the mask can be divided and reused. Each +subnet can be used for different purposes such as large to middle size +LANs and WAN links. Zebra @command{ripd} does not support the non-sequential +netmasks that are included in RIP Version 2. + +In a case of similar information with the same prefix and metric, the +old information will be suppressed. Ripd does not currently support +equal cost multipath routing. + + +@node RIP Configuration, How to Announce RIP route, Starting and Stopping ripd, RIP +@comment node-name, next, previous, up +@section RIP Configuration + +@deffn Command {router rip} {} +The @code{router rip} command is necessary to enable RIP. To disable +RIP, use the @code{no router rip} command. RIP must be enabled before +carrying out any of the RIP commands. +@end deffn + +@deffn Command {no rouer rip} {} +Disable RIP. +@end deffn + +RIP can be configured to process either Version 1 or Version 2 packets, +the default mode is Version 2. If no version is specified, then the RIP +daemon will default to Version 2. If RIP is set to Version +1, the setting "Version 1" will be displayed, but the setting "Version +2" will not be displayed whether or not Version 2 is set explicitly as +the version of RIP being used. + +@deffn {RIP Command} {network @var{network}} {} +@deffnx {RIP Command} {no network @var{network}} {} +Set the RIP enable interface by @var{network}. The interfaces which +have addresses matching with @var{network} are enabled. + +This group of commands either enables or disables RIP interfaces between +certain numbers of a specified network address. For example, if the +network for 10.0.0.0/24 is RIP enabled, this would result in all the +addresses from 10.0.0.0 to 10.0.0.255 being enabled for RIP. The @code{no +network} command will disable RIP for the specified network. +@end deffn + +@deffn {RIP Command} {network @var{ifname}} {} +@deffnx {RIP Command} {no network @var{ifname}} {} +Set a RIP enabled interface by @var{ifname}. Both the sending and +receiving of RIP packets will be enabled on the port specified in the +@code{network ifname} command. The @code{no network ifname} command will disable +RIP on the specified interface. +@end deffn + +@deffn {RIP Command} {neighbor @var{a.b.c.d}} {} +@deffnx {RIP Command} {no neighbor @var{a.b.c.d}} {} +Specify RIP neighbor. When a neighbor doesn't understand multicast, +this command is used to specify neighbors. In some cases, not all +routers will be able to understand multicasting, where packets are sent +to a network or a group of addresses. In a situation where a neighbor +cannot process multicast packets, it is necessary to establish a direct +link between routers. The neighbor command allows the network +administrator to specify a router as a RIP neighbor. The @code{no +neighbor a.b.c.d} command will disable the RIP neighbor. +@end deffn + +Below is very simple RIP configuration. Interface @code{eth0} and +interface which address match to @code{10.0.0.0/8} are RIP enabled. + +@example +@group +! +router rip + network 10.0.0.0/8 + network eth0 +! +@end group +@end example + +Passive interface + +@deffn {RIP command} {passive-interface @var{IFNAME}} {} +@deffnx {RIP command} {no passive-interface @var{IFNAME}} {} +This command sets the specified interface to passive mode. On passive mode +interface, all receiving packets are processed as normal and ripd does +not send either multicast or unicast RIP packets except to RIP neighbors +specified with @code{neighbor} command. +@end deffn + +RIP version handling + +@deffn {RIP Command} {version @var{version}} {} +Set RIP process's version. @var{version} can be ``1'' or ``2''. +@end deffn + +@deffn {Interface command} {ip rip send version @var{version}} {} +@var{version} can be `1', `2', `1 2'. This configuration command +overrides the router's rip version setting. The command will enable the +selected interface to send packets with RIP Version 1, RIP Version 2, or +both. In the case of '1 2', packets will be both broadcast and +multicast. +@end deffn + +@deffn {Interface command} {ip rip receive version @var{version}} {} +Version setting for incoming RIP packets. This command will enable the +selected interface to receive packets in RIP Version 1, RIP Version 2, +or both. +@end deffn + +RIP split-horizon + +@deffn {Interface command} {ip split-horizon} {} +@deffnx {Interface command} {no ip split-horizon} {} +Control split-horizon on the interface. Default is @code{ip +split-horizon}. If you don't perform split-horizon on the interface, +please specify @code{no ip split-horizon}. +@end deffn + +@node How to Announce RIP route, Filtering RIP Routes, RIP Configuration, RIP +@comment node-name, next, previous, up +@section How to Announce RIP route + +@deffn {RIP command} {redistribute kernel} {} +@deffnx {RIP command} {redistribute kernel metric <0-16>} {} +@deffnx {RIP command} {redistribute kernel route-map @var{route-map}} {} +@deffnx {RIP command} {no redistribute kernel} {} +@code{redistribute kernel} redistributes routing information from +kernel route entries into the RIP tables. @code{no redistribute kernel} +disables the routes. +@end deffn + +@deffn {RIP command} {redistribute static} {} +@deffnx {RIP command} {redistribute static metric <0-16>} {} +@deffnx {RIP command} {redistribute static route-map @var{route-map}} {} +@deffnx {RIP command} {no redistribute static} {} +@code{redistribute static} redistributes routing information from +static route entries into the RIP tables. @code{no redistribute static} +disables the routes. +@end deffn + +@deffn {RIP command} {redistribute connected} {} +@deffnx {RIP command} {redistribute connected metric <0-16>} {} +@deffnx {RIP command} {redistribute connected route-map @var{route-map}} {} +@deffnx {RIP command} {no redistribute connected} {} +Redistribute connected routes into the RIP tables. @code{no +redistribute connected} disables the connected routes in the RIP tables. +This command redistribute connected of the interface which RIP disabled. +The connected route on RIP enabled interface is announced by default. +@end deffn + +@deffn {RIP command} {redistribute ospf} {} +@deffnx {RIP command} {redistribute ospf metric <0-16>} {} +@deffnx {RIP command} {redistribute ospf route-map @var{route-map}} {} +@deffnx {RIP command} {no redistribute ospf} {} +@code{redistribute ospf} redistributes routing information from +ospf route entries into the RIP tables. @code{no redistribute ospf} +disables the routes. +@end deffn + +@deffn {RIP command} {redistribute bgp} {} +@deffnx {RIP command} {redistribute bgp metric <0-16>} {} +@deffnx {RIP command} {redistribute bgp route-map @var{route-map}} {} +@deffnx {RIP command} {no redistribute bgp} {} +@code{redistribute bgp} redistributes routing information from +bgp route entries into the RIP tables. @code{no redistribute bgp} +disables the routes. +@end deffn + +If you want to specify RIP only static routes: + +@deffn {RIP command} {default-information originate} {} +@end deffn + +@deffn {RIP command} {route @var{a.b.c.d/m}} {} +@deffnx {RIP command} {no route @var{a.b.c.d/m}} {} +This command is specific to Zebra. The @code{route} command makes a static +route only inside RIP. This command should be used only by advanced +users who are particularly knowledgeable about the RIP protocol. In +most cases, we recommend creating a static route in Zebra and +redistributing it in RIP using @code{redistribute static}. +@end deffn + + +@node Filtering RIP Routes, RIP Metric Manipulation, How to Announce RIP route, RIP +@comment node-name, next, previous, up +@section Filtering RIP Routes + +RIP routes can be filtered by a distribute-list. + +@deffn Command {distribute-list @var{access_list} @var{direct} @var{ifname}} {} +You can apply access lists to the interface with a @code{distribute-list} +command. @var{access_list} is the access list name. @var{direct} is +@samp{in} or @samp{out}. If @var{direct} is @samp{in} the access list +is applied to input packets. + +The @code{distribute-list} command can be used to filter the RIP path. +@code{distribute-list} can apply access-lists to a chosen interface. +First, one should specify the access-list. Next, the name of the +access-list is used in the distribute-list command. For example, in the +following configuration @samp{eth0} will permit only the paths that +match the route 10.0.0.0/8 + +@example +@group +! +router rip + distribute-list private in eth0 +! +access-list private permit 10 10.0.0.0/8 +access-list private deny any +! +@end group +@end example +@end deffn + +@code{distribute-list} can be applied to both incoming and outgoing data. + +@deffn Command {distribute-list prefix @var{prefix_list} (in|out) @var{ifname}} {} +You can apply prefix lists to the interface with a +@code{distribute-list} command. @var{prefix_list} is the prefix list +name. Next is the direction of @samp{in} or @samp{out}. If +@var{direct} is @samp{in} the access list is applied to input packets. +@end deffn + +@node RIP Metric Manipulation, RIP distance, Filtering RIP Routes, RIP +@comment node-name, next, previous, up +@section RIP Metric Manipulation + +RIP metric is a value for distance for the network. Usually +@command{ripd} increment the metric when the network information is +received. Redistributed routes' metric is set to 1. + +@deffn {RIP command} {default-metric <1-16>} {} +@deffnx {RIP command} {no default-metric <1-16>} {} +This command modifies the default metric value for redistributed routes. The +default value is 1. This command does not affect connected route +even if it is redistributed by @command{redistribute connected}. To modify +connected route's metric value, please use @command{redistribute +connected metric} or @command{route-map}. @command{offset-list} also +affects connected routes. +@end deffn + +@deffn {RIP command} {offset-list @var{access-list} (in|out)} {} +@deffnx {RIP command} {offset-list @var{access-list} (in|out) @var{ifname}} {} +@end deffn + +@node RIP distance, RIP route-map, RIP Metric Manipulation, RIP +@comment node-name, next, previous, up +@section RIP distance + +Distance value is used in zebra daemon. Default RIP distance is 120. + +@deffn {RIP command} {distance <1-255>} {} +@deffnx {RIP command} {no distance <1-255>} {} +Set default RIP distance to specified value. +@end deffn + +@deffn {RIP command} {distance <1-255> @var{A.B.C.D/M}} {} +@deffnx {RIP command} {no distance <1-255> @var{A.B.C.D/M}} {} +Set default RIP distance to specified value when the route's source IP +address matches the specified prefix. +@end deffn + +@deffn {RIP command} {distance <1-255> @var{A.B.C.D/M} @var{access-list}} {} +@deffnx {RIP command} {no distance <1-255> @var{A.B.C.D/M} @var{access-list}} {} +Set default RIP distance to specified value when the route's source IP +address matches the specified prefix and the specified access-list. +@end deffn + +@node RIP route-map, RIP Authentication, RIP distance, RIP +@comment node-name, next, previous, up +@section RIP route-map + +Usage of @command{ripd}'s route-map support. + +Optional argument route-map MAP_NAME can be added to each @code{redistribute} +statement. + +@example +redistribute static [route-map MAP_NAME] +redistribute connected [route-map MAP_NAME] +..... +@end example + +Cisco applies route-map _before_ routes will exported to rip route +table. In current Zebra's test implementation, @command{ripd} applies route-map +after routes are listed in the route table and before routes will be announced +to an interface (something like output filter). I think it is not so clear, +but it is draft and it may be changed at future. + +Route-map statement (@pxref{Route Map}) is needed to use route-map +functionality. + +@deffn {Route Map} {match interface @var{word}} {} +This command match to incoming interface. Notation of this match is +different from Cisco. Cisco uses a list of interfaces - NAME1 NAME2 +... NAMEN. Ripd allows only one name (maybe will change in the +future). Next - Cisco means interface which includes next-hop of +routes (it is somewhat similar to "ip next-hop" statement). Ripd +means interface where this route will be sent. This difference is +because "next-hop" of same routes which sends to different interfaces +must be different. Maybe it'd be better to made new matches - say +"match interface-out NAME" or something like that. +@end deffn + +@deffn {Route Map} {match ip address @var{word}} {} +@deffnx {Route Map} {match ip address prefix-list @var{word}} {} +Match if route destination is permitted by access-list. +@end deffn + +@deffn {Route Map} {match ip next-hop A.B.C.D} {} +Cisco uses here , @command{ripd} IPv4 address. Match if +route has this next-hop (meaning next-hop listed in the rip route +table - "show ip rip") +@end deffn + +@deffn {Route Map} {match metric <0-4294967295>} {} +This command match to the metric value of RIP updates. For other +protocol compatibility metric range is shown as <0-4294967295>. But +for RIP protocol only the value range <0-16> make sense. +@end deffn + +@deffn {Route Map} {set ip next-hop A.B.C.D} {} +This command set next hop value in RIPv2 protocol. This command does +not affect RIPv1 because there is no next hop field in the packet. +@end deffn + +@deffn {Route Map} {set metric <0-4294967295>} {} +Set a metric for matched route when sending announcement. The metric +value range is very large for compatibility with other protocols. For +RIP, valid metric values are from 1 to 16. +@end deffn + +@node RIP Authentication, RIP Timers, RIP route-map, RIP +@comment node-name, next, previous, up +@section RIP Authentication + +@deffn {Interface command} {ip rip authentication mode md5} {} +@deffnx {Interface command} {no ip rip authentication mode md5} {} +Set the interface with RIPv2 MD5 authentication. +@end deffn + +@deffn {Interface command} {ip rip authentication mode text} {} +@deffnx {Interface command} {no ip rip authentication mode text} {} +Set the interface with RIPv2 simple password authentication. +@end deffn + +@deffn {Interface command} {ip rip authentication string @var{string}} {} +@deffnx {Interface command} {no ip rip authentication string @var{string}} {} +RIP version 2 has simple text authentication. This command sets +authentication string. The string must be shorter than 16 characters. +@end deffn + +@deffn {Interface command} {ip rip authentication key-chain @var{key-chain}} {} +@deffnx {Interface command} {no ip rip authentication key-chain @var{key-chain}} {} +Specifiy Keyed MD5 chain. +@end deffn + +@example +! +key chain test + key 1 + key-string test +! +interface eth1 + ip rip authentication mode md5 + ip rip authentication key-chain test +! +@end example + +@node RIP Timers, Show RIP Information, RIP Authentication, RIP +@comment node-name, next, previous, up +@section RIP Timers + +@deffn {RIP command} {timers basic @var{update} @var{timeout} @var{garbage}} {} + +RIP protocol has several timers. User can configure those timers' values +by @code{timers basic} command. + +The default settings for the timers are as follows: + +@itemize @bullet +@item +The update timer is 30 seconds. Every update timer seconds, the RIP +process is awakened to send an unsolicited Response message containing +the complete routing table to all neighboring RIP routers. + +@item +The timeout timer is 180 seconds. Upon expiration of the timeout, the +route is no longer valid; however, it is retained in the routing table +for a short time so that neighbors can be notified that the route has +been dropped. + +@item +The garbage collect timer is 120 seconds. Upon expiration of the +garbage-collection timer, the route is finally removed from the routing +table. + +@end itemize + +The @code{timers basic} command allows the the default values of the timers +listed above to be changed. +@end deffn + +@deffn {RIP command} {no timers basic} {} +The @code{no timers basic} command will reset the timers to the default +settings listed above. +@end deffn + +@node Show RIP Information, RIP Debug Commands, RIP Timers, RIP +@comment node-name, next, previous, up +@section Show RIP Information + +To display RIP routes. + +@deffn Command {show ip rip} {} +Show RIP routes. +@end deffn + +The command displays all RIP routes. For routes that are received +through RIP, this command will display the time the packet was sent and +the tag information. This command will also display this information +for routes redistributed into RIP. + +@c Exmaple here. + +@deffn Command {show ip protocols} {} +The command displays current RIP status. It includes RIP timer, +filtering, version, RIP enabled interface and RIP peer inforation. +@end deffn + +@example +@group +ripd> @b{show ip protocols} +Routing Protocol is "rip" + Sending updates every 30 seconds with +/-50%, next due in 35 seconds + Timeout after 180 seconds, garbage collect after 120 seconds + Outgoing update filter list for all interface is not set + Incoming update filter list for all interface is not set + Default redistribution metric is 1 + Redistributing: kernel connected + Default version control: send version 2, receive version 2 + Interface Send Recv + Routing for Networks: + eth0 + eth1 + 1.1.1.1 + 203.181.89.241 + Routing Information Sources: + Gateway BadPackets BadRoutes Distance Last Update +@end group +@end example + +@node RIP Debug Commands, , Show RIP Information, RIP +@comment node-name, next, previous, up +@section RIP Debug Commands + +Debug for RIP protocol. + +@deffn Command {debug rip events} {} +Debug rip events. +@end deffn + +@code{debug rip} will show RIP events. Sending and receiving +packets, timers, and changes in interfaces are events shown with @command{ripd}. + +@deffn Command {debug rip packet} {} +Debug rip packet. +@end deffn + +@code{debug rip packet} will display detailed information about the RIP +packets. The origin and port number of the packet as well as a packet +dump is shown. + +@deffn Command {debug rip zebra} {} +Debug rip between zebra communication. +@end deffn + +This command will show the communication between @command{ripd} and @command{zebra}. The +main information will include addition and deletion of paths to the +kernel and the sending and receiving of interface information. + +@deffn Command {show debugging rip} {} +Display @command{ripd}'s debugging option. +@end deffn + +@code{show debugging rip} will show all information currently set for ripd +debug. diff --git a/doc/ripngd.8 b/doc/ripngd.8 new file mode 100644 index 00000000..cff8abe6 --- /dev/null +++ b/doc/ripngd.8 @@ -0,0 +1,143 @@ +.TH RIPNGD 8 "July 2000" "Zebra Beast - RIPNGD" "Version 0.88" + +.SH NAME +ripngd \- a RIP routing engine for use with Zebra and IPv6 + +.SH SYNOPSIS +.B ripngd +[ +.B \-dhlrv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-P port-number +] + +.SH DESCRIPTION +.B ripngd +is a routing component that works with the +.B zebra +routing engine. + + + +.SH OPTIONS + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this +option will likely default to \fB\fI/usr/local/etc/ripngd.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When ripngd starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart ripngd. The likely default is \fB\fI/var/run/ripngd.pid\fR. + +.TP +\fB\-l\fR, \fB\-\-log_mode\fR +Turn verbose logging on. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the ripngd VTY will listen on. This defaults to +2603, as specified in \fB\fI/etc/services\fR. + +.TP +\fB\-r\fR, \fB\-\-retain\fR +When the program terminates, retain routes added by \fBripd\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB router ripng \fR +\fB router zebra \fR -- (Move routes into kernel table) + +\fB network [NETWORK] \fR +\fB no network [NETWORK] \fR + +\fB network [IFNAME] \fR +\fB no network [IFNAME] \fR + +\fB route [NETWORK] \fR +\fB no route [NETWORK] \fR + +\fB flush_timer [FLUSH] \fR + +\fB distribute-list [ACCESS-LIST] [in|out] [IFNAME] \fR + +\fB show ip ripng \fR +\fB show debugging ripng \fR + +\fB debug ripng \fR +\fB debug ripng events \fR +\fB debug ripng packet \fR +\fB debug ripng zebra \fR + + + +.SH FILES + +.TP +.BI /usr/local/sbin/ripngd +The default location of the +.B ripngd +binary. + +.TP +.BI /usr/local/etc/ripngd.conf +The default location of the +.B ripngd +config file. + +.TP +.BI $(PWD)/ripngd.log +If the +.B ripngd +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBripngd\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line +options, and for config file commands. The definitive document is the +Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The ripngd process may log to standard output, to a VTY, to a log +file, or through syslog to the system logs. \fBripngd\fR supports many +debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripd(8), ospfd(8), ospf6d(8), bgpd(8), zebra(8), vtysh(1) + +.SH BUGS +.B ripngd +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/ripngd.texi b/doc/ripngd.texi new file mode 100644 index 00000000..b49f0bf3 --- /dev/null +++ b/doc/ripngd.texi @@ -0,0 +1,85 @@ +@node RIPng, OSPFv2, RIP, Top +@comment node-name, next, previous, up +@chapter RIPng + +@command{ripngd} supports the RIPng protocol as described in RFC2080. It's an +IPv6 reincarnation of the RIP protocol. + +@menu +* Invoking ripngd:: +* ripngd Configuration:: +* ripngd Terminal Mode Commands:: +* ripngd Filtering Commands:: +@end menu + +@node Invoking ripngd, ripngd Configuration, RIPng, RIPng +@comment node-name, next, previous, up +@section Invoking ripngd + +There are no @code{ripngd} specific invocation options. Common options +can be specified (@pxref{Common Invocation Options}). + +@node ripngd Configuration, ripngd Terminal Mode Commands, Invoking ripngd, RIPng +@comment node-name, next, previous, up +@section ripngd Configuration + +Currently ripngd supports the following commands: + +@deffn Command {router ripng} {} +Enable RIPng. +@end deffn + +@deffn {RIPng Command} {flush_timer @var{time}} {} +Set flush timer. +@end deffn + +@deffn {RIPng Command} {network @var{network}} {} +Set RIPng enabled interface by @var{network} +@end deffn + +@deffn {RIPng Command} {network @var{ifname}} {} +Set RIPng enabled interface by @var{ifname} +@end deffn + +@deffn {RIPng Command} {route @var{network}} {} +Set RIPng static routing announcement of @var{network}. +@end deffn + +@deffn Command {router zebra} {} +This command is the default and does not appear in the configuration. +With this statement, RIPng routes go to the @command{zebra} daemon. +@end deffn + +@node ripngd Terminal Mode Commands, ripngd Filtering Commands, ripngd Configuration, RIPng +@comment node-name, next, previous, up +@section ripngd Terminal Mode Commands + +@deffn Command {show ip ripng} {} +@end deffn + +@deffn Command {show debugging ripng} {} +@end deffn + +@deffn Command {debug ripng events} {} +@end deffn + +@deffn Command {debug ripng packet} {} +@end deffn + +@deffn Command {debug ripng zebra} {} +@end deffn + +@node ripngd Filtering Commands, , ripngd Terminal Mode Commands, RIPng +@comment node-name, next, previous, up +@section ripngd Filtering Commands + +@deffn Command {distribute-list @var{access_list} (in|out) @var{ifname}} {} +You can apply an access-list to the interface using the +@code{distribute-list} command. @var{access_list} is an access-list +name. @var{direct} is @samp{in} or @samp{out}. If @var{direct} is +@samp{in}, the access-list is applied only to incoming packets. + +@example +distribute-list local-only out sit1 +@end example +@end deffn diff --git a/doc/routemap.texi b/doc/routemap.texi new file mode 100644 index 00000000..478f4626 --- /dev/null +++ b/doc/routemap.texi @@ -0,0 +1,91 @@ +@node Route Map, IPv6 Support, Filtering, Top +@comment node-name, next, previous, up +@chapter Route Map + +Route map is a very useful function in zebra. There is a match and set +statement permitted in a route map. + +@example +@group +route-map test permit 10 + match ip address 10 + set local-preference 200 +@end group +@end example + +This means that if a route matches ip access-list number 10 it's +local-preference value is set to 200. + +@menu +* Route Map Command:: +* Route Map Match Command:: +* Route Map Set Command:: +@end menu + +@node Route Map Command, Route Map Match Command, Route Map, Route Map +@comment node-name, next, previous, up +@subsection Route Map Command + +@deffn {Command} {route-map @var{route-map-name} permit @var{priority}} {} +@end deffn + +@node Route Map Match Command, Route Map Set Command, Route Map Command, Route Map +@comment node-name, next, previous, up +@subsection Route Map Match Command + +@deffn {Route-map Command} {match ip address @var{access_list}} {} +Matches the specified @var{access_list} +@end deffn + +@deffn {Route-map Command} {match ip next-hop @var{ipv4_addr}} {} +Matches the specified @var{ipv4_addr}. +@end deffn + +@deffn {Route-map Command} {match aspath @var{as_path}} {} +Matches the specified @var{as_path}. +@end deffn + +@deffn {Route-map Command} {match metric @var{metric}} {} +Matches the specified @var{metric}. +@end deffn + +@deffn {Route-map Command} {match community @var{community_list}} {} +Matches the specified @var{community_list} +@end deffn + +@node Route Map Set Command, , Route Map Match Command, Route Map +@comment node-name, next, previous, up +@subsection Route Map Set Command + +@deffn {Route-map Command} {set ip next-hop @var{ipv4_address}} {} +Set the BGP nexthop address. +@end deffn + +@deffn {Route-map Command} {set local-preference @var{local_pref}} {} +Set the BGP local preference. +@end deffn + +@deffn {Route-map Command} {set weight @var{weight}} {} +Set the route's weight. +@end deffn + +@deffn {Route-map Command} {set metric @var{metric}} {} +Set the BGP attribute MED. +@end deffn + +@deffn {Route-map Command} {set as-path prepend @var{as_path}} {} +Set the BGP AS path to prepend. +@end deffn + +@deffn {Route-map Command} {set community @var{community}} {} +Set the BGP community attribute. +@end deffn + +@deffn {Route-map Command} {set ipv6 next-hop global @var{ipv6_address}} {} +Set the BGP-4+ global IPv6 nexthop address. +@end deffn + +@deffn {Route-map Command} {set ipv6 next-hop local @var{ipv6_address}} {} +Set the BGP-4+ link local IPv6 nexthop address. +@end deffn + diff --git a/doc/snmp.texi b/doc/snmp.texi new file mode 100644 index 00000000..315c91c9 --- /dev/null +++ b/doc/snmp.texi @@ -0,0 +1,68 @@ +@node SNMP Support, Zebra Protocol, Kernel Interface, Top +@comment node-name, next, previous, up +@chapter SNMP Support + +SNMP (Simple Network Managing Protocol) is widely implemented feature +for collecting network information from router and/or host. Zebra +itself does not support SNMP agent functionality. But conjuction with +SNMP agent, Zebra provides routing protocol MIBs. + +Zebra uses SMUX protocol (RFC1227) for making communication with SNMP +agent. There are several SNMP agent which support SMUX. We recommend +to use the latest @command{ucd-snmp} software. + +@menu +* How to get ucd-snmp:: +* SMUX configuration:: +@end menu + +@node How to get ucd-snmp, SMUX configuration, SNMP Support, SNMP Support +@comment node-name, next, previous, up +@section How to get ucd-snmp + +ucd-snmp is a free software which distributed so called "as is" software +license. Please check the license which comes with distribution of +@command{ucd-snmp}. The authors of ucd-snmp are the University of +California, the University of California at Davis, and the Electrical +Engineering department at the University of California at Davis. + +You can get ucd-snmp from @url{ftp://ucd-snmp.ucdavis.edu/}. As of this +writing we are testing with @command{ucd-snmp-4.1.pre1.tar.gz}. + +To enable SMUX protocol support, please configure @command{ucd-snmp} +like below. + +@example +% configure --with-mib-modules=smux +@end example + +After compile and install @command{ucd-snmp}, you will need to configure +smuxpeer. I'm now using configuration shown below. This means SMUX client +connects to MIB 1.3.6.1.6.3.1 with password test. + +@example +/usr/local/share/snmp/snmpd.conf +================================ +smuxpeer 1.3.6.1.6.3.1 test +@end example + +@node SMUX configuration, , How to get ucd-snmp, SNMP Support +@comment node-name, next, previous, up +@section SMUX configuration + +To enable SNMP support of Zebra, you have to configure Zebra with +@command{--enable-snmp} (@pxref{Configure the Software}). + +@deffn {Command} {smux peer @var{oid}} {} +@deffnx {Command} {no smux peer @var{oid}} {} +@end deffn + +@deffn {Command} {smux peer @var{oid} @var{password}} {} +@deffnx {Command} {no smux peer @var{oid} @var{password}} {} +@end deffn + +@example +! +smux peer .1.3.6.1.6.3.1 test +! +@end example diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 00000000..332e392f --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,5625 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{1999-02-14.16}% +% +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 +% Free Software Foundation, Inc. +% +% This texinfo.tex file is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License as +% published by the Free Software Foundation; either version 2, or (at +% your option) any later version. +% +% This texinfo.tex file is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the implied warranty +% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% ftp://ftp.gnu.org/pub/gnu/texinfo.tex +% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) +% ftp://tug.org/tex/texinfo.tex +% ftp://ctan.org/macros/texinfo/texinfo.tex +% (and all CTAN mirrors, finger ctan@ctan.org for a list). +% /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% The texinfo.tex in any given Texinfo distribution could well be out +% of date, so if that's what you're using, please check. +% There is a small home page for Texinfo at http://texinfo.org/. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever, to process the dvi file; this makes foo.ps. +% The extra runs of TeX get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages. You can get +% the existing language-specific files from ftp://ftp.gnu.org/gnu/texinfo/. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexi=\i +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexstar=\* +\let\ptext=\t + +% We never want plain's outer \+ definition in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefivar\undefined \gdef\putwordDefivar{Instance Variable}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset +\newdimen \normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\ifx\eTeXversion\undefined +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% +\else +\def\loggingall{\tracingcommands3 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \tracingscantokens1 \tracingassigns1 \tracingifs1 + \tracinggroups1 \tracingnesting2 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% +\fi + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \turnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment; press RETURN to continue} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Press RETURN to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce actual \{ & \} command in an index. + \catcode`\{ = 12 \catcode`\} = 12 + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\@ = 0 \catcode`\\ = 12 + @gdef@lbracecmd[\{]% + @gdef@rbracecmd[\}]% +@endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \leavevmode + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + + +% @page forces the start of a new page +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. + +\def\inmargin#1{% +\strut\vadjust{\nobreak\kern-\strutdepth + \vtop to \strutdepth{\baselineskip\strutdepth\vss + \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=12 + \catcode`~=12 + \catcode`^=12 + \catcode`_=12 + \catcode`|=12 + \catcode`<=12 + \catcode`>=12 + \catcode`+=12 + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% We cannot implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\def\paragraphindent{\parsearg\doparagraphindent} +\def\doparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{fonts,} +% Font-change commands. + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Use Computer Modern fonts at \magstephalf (11pt). +\newcount\mainmagstep +\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm\rmshape{12}{1000} +\setfont\texttt\ttshape{12}{1000} +\else +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples (9pt). +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\setfont\ninett\ttshape{9}{1000} +\setfont\ninettsl\ttslshape{10}{900} +\setfont\indrm\rmshape{9}{1000} +\setfont\indit\itshape{9}{1000} +\setfont\indsl\slshape{9}{1000} +\let\indtt=\ninett +\let\indttsl=\ninettsl +\let\indsf=\indrm +\let\indbf=\indrm +\setfont\indsc\scshape{10}{900} +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. +% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. +% \setfont\ssecsl\slshape{10}{\magstep1} +% \setfont\ssectt\ttshape{10}{\magstep1} +% \setfont\ssecsf\sfshape{10}{\magstep1} + +%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than +%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. +%\setfont\ssectt\ttshape{10}{1315} +%\setfont\ssecsf\sfshape{10}{1315} + +%\let\ssecbf=\ssecrm + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl + \resetmathfonts \setleading{12pt}} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\smallrm\rmshape{8}{1000} +\font\smallsy=cmsy9 +\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \codex + } + % + % If we end up with any active - characters when handling the index, + % just treat them as a normal -. + \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is kbdinputdistinct. (Too much of a hassle to call the macro, +% the catcodes are wrong for parsearg to work.) +\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl} + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @url, @env, @command quotes seem unnecessary, so use \code. +\let\url=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \unhbox0\ (\code{#1})% second arg given, show both it and url + \else + \code{#1}% only url given, so show it + \fi + \fi +} + +% rms does not like the angle brackets --karl, 17may97. +% So now @email is just like @uref. +%\def\email#1{\angleleft{\tt #1}\angleright} +\let\email=\uref + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi + % + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +% Contains a kludge to get @end[description] to work. +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +% @table, @ftable, @vtable. +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the part of the @columnfraction before the decimal point, which +% is presumably either 0 or the empty string (but we don't check, we +% just throw it away). #2 is the decimal part, which we use as the +% percent of \hsize for this column. +\def\pickupwholefraction#1.#2 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip }% Add a normal word space as a separator; + % typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% multitable syntax +\def\tab{&\hskip1sp\relax} % 2/2/96 + % tiny skip here makes sure this column space is + % maintained, even if it is never used. + +% @multitable ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item\crcr + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\else +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{conditionals,} +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% + \let\chapter=\relax + \let\unnumbered=\relax + \let\top=\relax + \let\unnumberedsec=\relax + \let\unnumberedsection=\relax + \let\unnumberedsubsec=\relax + \let\unnumberedsubsection=\relax + \let\unnumberedsubsubsec=\relax + \let\unnumberedsubsubsection=\relax + \let\section=\relax + \let\subsec=\relax + \let\subsubsec=\relax + \let\subsection=\relax + \let\subsubsection=\relax + \let\appendix=\relax + \let\appendixsec=\relax + \let\appendixsection=\relax + \let\appendixsubsec=\relax + \let\appendixsubsection=\relax + \let\appendixsubsubsec=\relax + \let\appendixsubsubsection=\relax + \let\contents=\relax + \let\smallbook=\relax + \let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\everyheading = \relax + \let\evenheading = \relax + \let\oddheading = \relax + \let\everyfooting = \relax + \let\evenfooting = \relax + \let\oddfooting = \relax + \let\headings = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifnottex{\doignore{ifnottex}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + \catcode`\c = 14 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{WARNING: for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}}% + % Do not execute macro definitions. + % `c' is a comment character, so the word `macro' will get cut off. + \def\macro{\doignore{ma}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +{ + \catcode`\_ = \active + % + % We might end up with active _ or - characters in the argument if + % we're called from @code, as @code{@value{foo-bar_}}. So \let any + % such active characters to their normal equivalents. + \gdef\value{\begingroup + \catcode`\-=12 \catcode`\_=12 + \indexbreaks \let_\normalunderscore + \valuexxx} +} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable, since the result +% winds up in the index file. This means that if the variable's value +% contains other Texinfo commands, it's almost certain it will fail +% (although perhaps we could fix that with sufficient work to do a +% one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text +% following, through the first @end iftex (etc.). Make `@end iftex' +% (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% The \closeout helps reduce unnecessary open files; the limit on the +% Acorn RISC OS is a mere 16 files. +\def\synindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\doindex{#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\docodeindex{#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +\def\ { }% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +% (Must be a way to avoid doing expansion at all, and thus not have to +% laboriously list every single command here.) +\def\@{@}% will be @@ when we switch to @ as escape char. +% Need these in case \tex is in effect and \{ is a \delimiter again. +% But can't use \lbracecmd and \rbracecmd because texindex assumes +% braces and backslashes are used only as delimiters. +\let\{ = \mylbrace +\let\} = \myrbrace +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +%\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\result{\realbackslash result}% +\def\equiv{\realbackslash equiv}% +\def\expansion{\realbackslash expansion}% +\def\print{\realbackslash print}% +\def\error{\realbackslash error}% +\def\point{\realbackslash point}% +\def\copyright{\realbackslash copyright}% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\uref##1{\realbackslash uref {##1}}% +\def\url##1{\realbackslash url {##1}}% +\def\env##1{\realbackslash env {##1}}% +\def\command##1{\realbackslash command {##1}}% +\def\option##1{\realbackslash option {##1}}% +\def\dotless##1{\realbackslash dotless {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\,##1{\realbackslash ,{##1}}% +\def\t##1{\realbackslash t {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\sc##1{\realbackslash sc {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +\def\acronym##1{\realbackslash acronym {##1}}% +% +% Handle some cases of @value -- where the variable name does not +% contain - or _, and the value does not contain any +% (non-fully-expandable) commands. +\let\value = \expandablevalue +% +\unsepspaces +% Turn off macro expansion +\turnoffmacros +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\,=\indexdummyfont +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +\let\dotless=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\url=\indexdummyfont +\let\uref=\indexdummyfont +\let\env=\indexdummyfont +\let\command=\indexdummyfont +\let\option=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +\def\@{@}% +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other + @gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + \def\thirdarg{#3}% + % + % If third arg is present, precede it with space in sort key. + \ifx\thirdarg\emptymacro + \let\subentry = \empty + \else + \def\subentry{ #3}% + \fi + % + % First process the index entry with all font commands turned + % off to get the string to sort by. + {\indexnofonts \xdef\indexsorttmp{#2\subentry}}% + % + % Now the real index entry with the fonts. + \toks0 = {#2}% + % + % If third (subentry) arg is present, add it to the index + % string. And include a space. + \ifx\thirdarg\emptymacro \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + % Set up the complete index entry, with both the sort key + % and the original text, including any font commands. We write + % three arguments to \entry to the .?? file, texindex reduces to + % two when writing the .??s sorted result. + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + % + % But don't do any of this if we're not in vertical mode. We + % don't want to do a \vskip and prematurely end a paragraph. + % + % Avoid page breaks due to these extra skips, too. + % + \iflinks + \ifvmode + \skip0 = \lastskip + \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi + \fi + % + \temp % do the write + % + % + \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \indexfonts \rm + \tolerance = 9500 + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + \vskip .33\baselineskip plus .1\baselineskip + % + % Do our best not to break after the initial. + \nobreak +}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry#1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing columns. + \vskip 0pt plus1pt + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \advance\vsize by -\ht\partialpage + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +\def\pagesofar{% + % Re-output the contents of the output page -- any previous material, + % followed by the two boxes we just split, in box0 and box2. + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +\def\balancecolumns{% + % Called at the end of the double column material. + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + +% @chapter, @appendix, @unnumbered. +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% + {\the\chapno}}}% +\temp +\donoderef +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 +\message{\putwordAppendix\space \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% + {\putwordAppendix{} \appendixletter}}}% +\temp +\appendixnoderef +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @top is like @unnumbered. +\outer\def\top{\parsearg\unnumberedyyy} + +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the to achieve this: TeX expands \the only once, +% simply yielding the contents of . (We also do this for +% the toc entries.) +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}% +\temp +\unnumbnoderef +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +} + +% Sections. +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% + {\the\chapno}{\the\secno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% + {\appendixletter}{\the\secno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{% +\plainsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% Subsections. +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% + {\the\chapno}{\the\secno}{\the\subsecno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% + {\appendixletter}{\the\secno}{\the\subsecno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{% +\plainsubsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry% + {\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% Subsubsections. +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{% +\plainsubsubsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry% + {\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak +} + + +\message{toc,} +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. We supply {\folio} at the end of the +% argument, which will end up as the last argument to the \...entry macro. +% +% We open the .toc file here instead of at @setfilename or any other +% given time so that @contents can be put in the document anywhere. +% +\newif\iftocfileopened +\def\writetocentry#1{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + \iflinks \write\tocfile{#1{\folio}}\fi +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Finish up the main text and prepare to read what we've written +% to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \pageno = \savepageno +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm \putwordAppendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, so characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie + \catcode `\%=14 + \catcode 43=12 % plus + \catcode`\"=12 + \catcode`\==12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% Define the \E... control sequence only if we are inside the particular +% environment, so the error checking in \end will work. +% +% To end an @example-like environment, we first end the paragraph (via +% \afterenvbreak's vertical glue), and then the group. That way we keep +% the zero \parskip that the environments set -- \parskip glue will be +% inserted at the beginning of the next paragraph in the document, after +% the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup} + +% @lisp: indented, narrowed, typewriter font. +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @example: Same as @lisp. +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} + +% @small... is usually equivalent to the non-small (@smallbook +% redefines). We must call \example (or whatever) last in the +% definition, since it reads the return following the @example (or +% whatever) command. +% +% This actually allows (for example) @end display inside an +% @smalldisplay. Too bad, but makeinfo will catch the error anyway. +% +\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display} +\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format} +\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts. +% Originally contributed by Pavel@xerox. +\def\smalllispx{\begingroup + \def\Esmalllisp{\nonfillfinish\endgroup}% + \def\Esmallexample{\nonfillfinish\endgroup}% + \indexfonts + \lisp +} + +% @display: same as @lisp except keep current font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% @smalldisplay (when @smallbook): @display plus smaller fonts. +% +\def\smalldisplayx{\begingroup + \def\Esmalldisplay{\nonfillfinish\endgroup}% + \indexfonts \rm + \display +} + +% @format: same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @smallformat (when @smallbook): @format plus smaller fonts. +% +\def\smallformatx{\begingroup + \def\Esmallformat{\nonfillfinish\endgroup}% + \indexfonts \rm + \format +} + +% @flushleft (same as @format). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\noindent +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 +\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +% @deftypemethod has an extra argument that nothing else does. Sigh. +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by the space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\nobreak\vskip -\parskip\nobreak +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\nobreak\vskip -\parskip\nobreak +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDeffunc}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypefun}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefmac}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefspec}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypefunx #1 {\errmessage{@deftypefunx in invalid context}} + +% @defmethod, and so on + +% @defop CATEGORY CLASS OPERATION ARG... + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{}\putwordon\ #1}% +\defunargs {#3}\endgroup % +} + +% @deftypemethod CLASS RETURN-TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype\ \putwordof\ #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index +\begingroup\defname {#2}{\putwordDefivar\ \putwordof\ #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefvar}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefopt}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypevar}% +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scanmacro#1{% + \begingroup \newlinechar`\^^M + % Undo catcode changes of \startcontents and \doprintindex + \catcode`\@=0 \catcode`\\=12 \escapechar=`\@ + % Append \endinput to make sure that TeX does not see the ending newline. + \toks0={#1\endinput}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \let\xeatspaces\eatspaces + \input \jobname.tmp + \endgroup +} +\else +\def\scanmacro#1{% +\begingroup \newlinechar`\^^M +% Undo catcode changes of \startcontents and \doprintindex +\catcode`\@=0 \catcode`\\=12 \escapechar=`\@ +\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? +\def\macrolist{} % List of all defined macros in the form + % \do\macro1\do\macro2... + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=12\catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\macrobodyctxt{% + \catcode`\~=12 + \catcode`\^=12 + \catcode`\_=12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \catcode`\+=12 + \catcode`\{=12 + \catcode`\}=12 + \catcode`\@=12 + \catcode`\^^M=12 + \usembodybackslash} + +\def\macroargctxt{% + \catcode`\~=12 + \catcode`\^=12 + \catcode`\_=12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \catcode`\+=12 + \catcode`\@=12 + \catcode`\\=12} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{The name \the\macname\space is reserved}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + % Add the macroname to \macrolist + \toks0 = \expandafter{\macrolist\do}% + \xdef\macrolist{\the\toks0 + \expandafter\noexpand\csname\the\macname\endcsname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\def\unmacro{\parsearg\unmacroxxx} +\def\unmacroxxx#1{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist + \begingroup + \edef\tempa{\expandafter\noexpand\csname#1\endcsname}% + \def\do##1{% + \def\tempb{##1}% + \ifx\tempa\tempb + % remove this + \else + \toks0 = \expandafter{\newmacrolist\do}% + \edef\newmacrolist{\the\toks0\expandafter\noexpand\tempa}% + \fi}% + \def\newmacrolist{}% + % Execute macro list to define \newmacrolist + \macrolist + \global\let\macrolist\newmacrolist + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + +% We mant to disable all macros during \shipout so that they are not +% expanded by \write. +\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% + \edef\next{\macrolist}\expandafter\endgroup\next} + + +% @alias. +\def\alias#1=#2{\gdef#1{#2}} + + +\message{cross references,} +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's job is to define \lastnode. +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \fi +} +\def\unnumbnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% + \global\let\lastnode=\relax + \fi +} +\def\appendixnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Yappendixletterandtype}% + \global\let\lastnode=\relax + \fi +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\def\anchor#1{\setref{#1}{Ynothing}} + + +% \setref{NAME}{SNT} defines a cross-reference point NAME, namely +% NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have +% to set \indexdummies so commands such as @code in a section title +% aren't expanded. It would be nicer not to expand the titles in the +% first place, but there's so many layers that that is hard to do. +% +\def\setref#1#2{{% + \indexdummies + \dosetq{#1-title}{Ytitle}% + \dosetq{#1-pg}{Ypagenumber}% + \dosetq{#1-snt}{#2}% +}} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\normalturnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % [mynode], + [\printednodename],\space + % page 3 + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \normalturnoffactive so that punctuation chars such as underscore +% and backslash work in node names. (\turnoffactive doesn't do \.) +\def\dosetq#1#2{% + {\let\folio=0 + \normalturnoffactive + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks + \next + \fi + }% +} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\begingroup + % Reenable \ as an escape while reading the second argument. + \catcode`\\ = 0 + \afterassignment\endgroup + \expandafter\gdef\csname X#1\endcsname +} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + \catcode`\@=\other + \catcode`\^=\other + % It was suggested to define this as 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % The aux file uses ' as the escape (for now). + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\%=\other + \catcode`\'=0 + \catcode`\\=\other + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\long\gdef\footnotezzz{\insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t + \else\let\next\f@t\fi \next} +\def\f@@t{\bgroup\aftergroup\@foot\let\next} +\def\f@t#1{#1\@foot} +\def\@foot{\strut\egroup} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with post-v2.7 epsf.tex (available in + % doc/epsf.tex until it shows up on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +% Only complain once about lack of epsf.tex. +\def\image#1{% + \ifx\pdfoutput\undefined + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,\finish + \fi + \else + \centerline{\pdfimage #1.pdf}% + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is just the usual extra ignored arg for parsing this stuff. +\def\imagexxx#1,#2,#3,#4\finish{% + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + % If the image is by itself, center it. + \ifvmode + \nobreak\medskip + \nobreak + \centerline{\epsfbox{#1.eps}}% + \bigbreak + \else + % In the middle of a paragraph, no extra space. + \epsfbox{#1.eps}% + \fi +} + + +\message{localization,} + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\def\documentlanguage{\parsearg\dodocumentlanguage} +\def\dodocumentlanguage#1{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \let\temp = \relax + \else + \def\temp{\input txi-#1.tex }% + \fi + \temp + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = \hsize + \divide\emergencystretch by 40 + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; +% 4) hoffset; 5) binding offset; 6) topskip. Then whoever calls us can +% set \parskip and call \setleading for \baselineskip. +% +\def\internalpagesizes#1#2#3#4#5#6{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \setleading{13.2pt}% + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \setleading{12pt}% + % + \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \deftypemargin = 0pt + \defbodyindent = .5cm + % + \let\smalldisplay = \smalldisplayx + \let\smallexample = \smalllispx + \let\smallformat = \smallformatx + \let\smalllisp = \smalllispx +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \setleading{12pt}% + \parskip = 3pt plus 2pt minus 1pt + % + \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}% + % + \tolerance = 700 + \hfuzz = 1pt +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex{{\globaldefs = 1 + \setleading{13.6pt}% + % + \afourpaper + \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}% + % + \globaldefs = 0 +}} + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{% + \afourpaper + \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}% + % + \globaldefs = 0 +} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\def\pagesizes{\parsearg\pagesizesxxx} +\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{13.2pt}% + % + \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}% +}} + +% Set default to letter. +% +\letterpaper + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active @catcode`@_=@active} + +% These look ok in all fonts, so just make them not special. The @rm below +% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%H" +@c time-stamp-end: "}" +@c End: diff --git a/doc/vtysh.1 b/doc/vtysh.1 new file mode 100644 index 00000000..302e0166 --- /dev/null +++ b/doc/vtysh.1 @@ -0,0 +1,68 @@ +.TH VTYSH 1 "July 2000" "Zebra Beast - VTY shell" "Version 0.88" + +.SH NAME +vtysh \- a integrated shell for Zebra routing software + +.SH SYNOPSIS +.B vtysh +[ +.B \-e command +] + +.SH DESCBGPTION +.B vtysh +is a integrated shell for +.B Zebra +routing engine. + + +.SH OPTIONS + +.TP +\fB\-e +Specify command to be executed under batch mode. + + +.SH COMMANDS + +\fB Almost Zebra commands. + +\fB ping +\fB traceroute +\fB telnnet + +\fB start-shell +\fB start-shell bash +\fB start-shell zsh + + +.SH FILES + +.TP +.BI /usr/local/etc/Zebra.conf +The default location of the +.B vtysh +config file. + + +.SH WARNING +This man page is intended as a quick reference for command line +options, and for config file commands. The definitive document is the +Info file \fBZebra\fR. + + +.SH "SEE ALSO" +References to other related man pages: + +bgpd(8), ripd(8), ripngd(8), ospfd(8), ospf6d(8), zebra(8) + + +.SH BUGS +.B vtysh +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/vtysh.texi b/doc/vtysh.texi new file mode 100644 index 00000000..72490dba --- /dev/null +++ b/doc/vtysh.texi @@ -0,0 +1,27 @@ +@node VTY shell +@comment node-name, next, previous, up +@chapter VTY shell + +@command{vtysh} is integrated shell of Zebra software. + +To use vtysh please specify ---enable-vtysh to configure script. To use +PAM for authentication use ---with-libpam option to configure script. + +vtysh only searches @value{INSTALL_PREFIX_ETC} path for vtysh.conf which +is the vtysh configuration file. Vtysh does not search current +directory for configuration file because the file includes user +authentication settings. + +Currently, vtysh.conf has only one command. + +@example +! +username foo nopassword +! +@end example + +With this set, user foo does not need password authentication for user vtysh. +With PAM vtysh uses PAM authentication mechanism. + +If vtysh is compiled without PAM authentication, every user can use vtysh +without authentication. diff --git a/doc/zebra.8 b/doc/zebra.8 new file mode 100644 index 00000000..190f4a62 --- /dev/null +++ b/doc/zebra.8 @@ -0,0 +1,146 @@ +.TH ZEBRA 8 "July 2000" "Zebra" "Version 0.88" + +.SH NAME +zebra \- a routing manager for use with associated components + +.SH SYNOPSIS +.B zebra +[ +.B \-bdhklrv +] +[ +.B \-f config-file +] +[ +.B \-i pid-file +] +[ +.B \-P port-number +] + +.SH DESCRIPTION +.B zebra +is a routing manager that implements the +.B zebra +route engine. +.B zebra +supports RIPv1, RIPv2, RIPng, OSPF, OSPF6, BGP4+, and BGP4-. + + +.SH OPTIONS + +.TP +\fB\-b\fR, \fB\-\-batch\fR +Runs in batch mode, \fBzebra\fR parses its config and exits. + +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Runs in daemon mode, forking and exiting from tty. + +.TP +\fB\-f\fR, \fB\-\-config-file \fR\fIconfig-file\fR +Specifies the config file to use for startup. If not specified this option will likely default to \fB\fI/usr/local/etc/zebra.conf\fR. + +.TP +\fB\-h\fR, \fB\-\-help\fR +A brief message. + +.TP +\fB\-i\fR, \fB\-\-pid_file \fR\fIpid-file\fR +When zebra starts its process idenifier is written to +\fB\fIpid-file\fR. The init system uses the recorded PID to stop or +restart zebra. The likely default is \fB\fI/var/run/zebra.pid\fR. + +.TP +\fB\-k\fR, \fB\-\-keep_kernel\fR +On startup, don't delete self inserted routes. + +.TP +\fB\-l\fR, \fB\-\-log_mode\fR +Turn verbose logging on. + +.TP +\fB\-P\fR, \fB\-\-vty_port \fR\fIport-number\fR +Specify the port that the zebra VTY will listen on. This defaults to +2602, as specified in \fB\fI/etc/services\fR. + +.TP +\fB\-r\fR, \fB\-\-retain\fR +When the program terminates, retain routes added by \fBzebra\fR. + +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the version and exit. + + +.SH COMMANDS + +\fB table [TABLENO] \fR -- for use with multi-table kernels + +\fB ip route [NETWORK] [GATEWAY] \fR +\fB ipv6 route [NETWORK] [GATEWAY] \fR + +\fB show ip route \fR +\fB show ipv6 route \fR +\fB show interface \fR +\fB show ipforward \fR +\fB show ipv6forward \fR + +.TP +\fB interface [IFNAME] \fR +\fB shutdown \fR +\fB no shutdown \fR +\fB ip address [IP-ADDRESS] \fR +\fB description [DESCRIPTION] \fR +\fB multicast \fR +\fB no multicast \fR + + +.SH FILES + +.TP +.BI /usr/local/sbin/zebra +The default location of the +.B zebra +binary. + +.TP +.BI /usr/local/etc/zebra.conf +The default location of the +.B zebra +config file. + +.TP +.BI $(PWD)/zebra.log +If the +.B zebra +process is config'd to output logs to a file, then you will find this +file in the directory where you started \fBzebra\fR. + + +.SH WARNING +This man page is intended as a quick reference for command line options, and for config file commands. The definitive document is the Info file \fBzebra\fR. + + +.SH DIAGNOSTICS +The zebra process may log to standard output, to a VTY, to a log file, or through syslog to the system logs. +.B zebra +supports many debugging options, see the Info file, or the source for details. + + +.SH "SEE ALSO" +References to other related man pages: + +ripngd(8), ospfd(8), ospf6d(8), bgpd(8), zebra(8), vtysh(1) + + + +.SH BUGS +.B zebra +eats bugs for breakfast. If you have food for the maintainers try +.BI + + +.SH AUTHOR[S] +See <\fBwww.zebra.org\fR>, or the Info file for an accurate list of authors. + diff --git a/doc/zebra.info b/doc/zebra.info new file mode 100644 index 00000000..ca805e12 --- /dev/null +++ b/doc/zebra.info @@ -0,0 +1,170 @@ +This is zebra.info, produced by makeinfo version 4.2 from zebra.texi. + +INFO-DIR-SECTION Routing Software: +START-INFO-DIR-ENTRY +* Zebra: (zebra). The GNU Zebra routing software +END-INFO-DIR-ENTRY + + This file documents the GNU Zebra software which manages common +TCP/IP routing protocols. + + This is Edition 0.1, last updated 12 September 2002 of `The GNU +Zebra Manual', for Zebra Version 0.93b. + + Copyright (C) 1999, 2000, 2001, 2002 Kunihiro Ishiguro + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by Kunihiro Ishiguro. + + +Indirect: +zebra.info-1: 1121 +zebra.info-2: 48818 +zebra.info-3: 95581 +zebra.info-4: 143934 + +Tag Table: +(Indirect) +Node: Top1121 +Node: Overview1646 +Node: About Zebra3063 +Node: System Architecture5332 +Node: Supported Platforms8330 +Node: Supported RFC9317 +Node: How to get Zebra11119 +Node: Mailing List11824 +Node: Bug Reports12491 +Node: Installation13336 +Node: Configure the Software13767 +Ref: Configure the Software-Footnote-116134 +Node: Build the Software17776 +Node: Install the Software18318 +Node: Basic commands19689 +Node: Config Commands20402 +Node: Basic Config Commands21284 +Node: Sample Config File23682 +Node: Common Invocation Options24442 +Node: Virtual Terminal Interfaces25564 +Node: VTY Overview26069 +Node: VTY Modes27353 +Node: VTY View Mode27793 +Node: VTY Enable Mode28047 +Node: VTY Other Modes28311 +Node: VTY CLI Commands28473 +Node: CLI Movement Commands28923 +Node: CLI Editing Commands29456 +Node: CLI Advanced Commands30029 +Node: Zebra30780 +Node: Invoking zebra31287 +Node: Interface Commands31873 +Node: Static Route Commands32703 +Node: zebra Terminal Mode Commands34790 +Node: RIP35751 +Node: Starting and Stopping ripd36686 +Node: RIP netmask38107 +Node: RIP Configuration39229 +Node: How to Announce RIP route43124 +Node: Filtering RIP Routes45653 +Node: RIP Metric Manipulation47112 +Node: RIP distance48015 +Node: RIP route-map48818 +Node: RIP Authentication51320 +Node: RIP Timers52410 +Node: Show RIP Information53685 +Node: RIP Debug Commands55048 +Node: RIPng56032 +Node: Invoking ripngd56350 +Node: ripngd Configuration56607 +Node: ripngd Terminal Mode Commands57346 +Node: ripngd Filtering Commands57696 +Node: OSPFv258195 +Node: Configuring ospfd58752 +Node: OSPF router59229 +Node: OSPF area60960 +Node: OSPF interface63174 +Node: Redistribute routes to OSPF65956 +Node: Showing OSPF information68072 +Node: Debugging OSPF69292 +Node: OSPFv370303 +Node: OSPF6 router70621 +Node: OSPF6 area70978 +Node: OSPF6 interface71150 +Node: Redistribute routes to OSPF672002 +Node: Showing OSPF6 information72306 +Node: BGP73111 +Node: Starting BGP73972 +Node: BGP router74557 +Node: BGP distance75793 +Node: BGP decision process76234 +Node: BGP network76490 +Node: BGP route76671 +Node: Route Aggregation77232 +Node: Redistribute to BGP77784 +Node: BGP Peer78293 +Node: Defining Peer78471 +Node: BGP Peer commands79087 +Node: Peer filtering81458 +Node: BGP Peer Group81949 +Node: BGP Address Family82251 +Node: Autonomous System82396 +Node: AS Path Regular Expression83227 +Node: Display BGP Routes by AS Path84490 +Node: AS Path Access List84919 +Node: Using AS Path in Route Map85373 +Node: Private AS Numbers85639 +Node: BGP Communities Attribute85784 +Node: BGP Community Lists88245 +Node: Numbered BGP Community Lists90926 +Node: BGP Community in Route Map92500 +Node: Display BGP Routes by Community94427 +Node: Using BGP Communities Attribute95581 +Node: BGP Extended Communities Attribute99139 +Node: BGP Extended Community Lists100905 +Node: BGP Extended Communities in Route Map102806 +Node: Displaying BGP routes103249 +Node: Show IP BGP103475 +Node: More Show IP BGP104197 +Node: Capability Negotiation105317 +Node: Route Reflector108605 +Node: Route Server108870 +Node: Multiple instance109928 +Node: BGP instance and view111741 +Node: Routing policy113107 +Node: Viewing the view113863 +Node: How to set up a 6-Bone connection114135 +Node: Dump BGP packets and table115507 +Node: VTY shell116037 +Node: Filtering116877 +Node: IP Access List117225 +Node: IP Prefix List117616 +Node: ip prefix-list description120785 +Node: ip prefix-list sequential number control121318 +Node: Showing ip prefix-list121843 +Node: Clear counter of ip prefix-list122926 +Node: Route Map123347 +Node: Route Map Command123848 +Node: Route Map Match Command124051 +Node: Route Map Set Command124659 +Node: IPv6 Support125517 +Node: Router Advertisement126082 +Node: Kernel Interface126413 +Node: SNMP Support128363 +Node: How to get ucd-snmp128992 +Node: SMUX configuration130040 +Node: Zebra Protocol130473 +Node: Packet Binary Dump Format132367 +Node: Command Index143934 +Node: VTY Key Index173652 + +End Tag Table diff --git a/doc/zebra.texi b/doc/zebra.texi new file mode 100644 index 00000000..d09ff4d6 --- /dev/null +++ b/doc/zebra.texi @@ -0,0 +1,150 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setchapternewpage odd +@settitle GNU Zebra +@setfilename zebra.info +@defcodeindex op +@synindex pg cp +@c %**end of header + +@c Set variables +@set EDITION 0.1 +@set VERSION 0.93b +@set UPDATED 12 September 2002 +@set UPDATED-MONTH September 2002 + +@c These may vary with installation environment. +@set INSTALL_PREFIX_ETC /usr/local/etc +@set INSTALL_PREFIX_SBIN /usr/local/sbin + +@c Info entry +@dircategory Routing Software: +@direntry +* Zebra: (zebra). The @sc{gnu} Zebra routing software +@end direntry + +@c @smallbook + +@ifinfo +This file documents the @sc{gnu} Zebra software which manages common +TCP/IP routing protocols. + +This is Edition @value{EDITION}, last updated @value{UPDATED} of +@cite{The GNU Zebra Manual}, for Zebra Version @value{VERSION}. + +Copyright (C) 1999, 2000, 2001, 2002 Kunihiro Ishiguro + +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries a copyright permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation +approved by Kunihiro Ishiguro. +@end ifinfo + +@titlepage +@title GNU Zebra +@subtitle A routing software package for TCP/IP networks +@subtitle Zebra version @value{VERSION} +@subtitle @value{UPDATED-MONTH} +@author Kunihiro Ishiguro + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1999, 2000, 2001, 2002 Kunihiro Ishiguro + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by Kunihiro Ishiguro. +@end titlepage +@page + +@ifnottex +@node Top, Overview, (dir), (dir) +@comment node-name, next, previous, up +@top Zebra + +Zebra is a advanced routing software package that provides TCP/IP +based routing protocols. This is the Zebra Manual for +zebra-@value{VERSION}. +@end ifnottex + +@menu +* Overview:: +* Installation:: +* Basic commands:: +* Zebra:: +* RIP:: +* RIPng:: +* OSPFv2:: +* OSPFv3:: +* BGP:: +* VTY shell:: +* Filtering:: +* Route Map:: +* IPv6 Support:: +* Kernel Interface:: +* SNMP Support:: +* Zebra Protocol:: +* Packet Binary Dump Format:: +* Command Index:: +* VTY Key Index:: +@end menu + +@include overview.texi +@include install.texi +@include basic.texi +@include main.texi +@include ripd.texi +@include ripngd.texi +@include ospfd.texi +@include ospf6d.texi +@include bgpd.texi +@include vtysh.texi +@include filter.texi +@include routemap.texi +@include ipv6.texi +@include kernel.texi +@include snmp.texi +@include protocol.texi +@include appendix.texi + +@node Command Index, VTY Key Index, Top, Top +@comment node-name, next, previous, up +@unnumbered Command Index + +@printindex fn + +@node VTY Key Index, , Command Index, Top +@comment node-name, next, previous, up +@unnumbered VTY Key Index + +@printindex ky + +@summarycontents +@contents +@bye -- cgit v1.2.1