.\" .\" Copyright (c) 2015 Ingo Schwarze .\" .\" Permission to use, copy, modify, and distribute this presentation for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE PRESENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL .\" WARRANTIES WITH REGARD TO THIS PRESENTATION INCLUDING ALL IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE .\" AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL .\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA .\" OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER .\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS PRESENTATION. .\" .\" -------------------------------------------------------------------- .\" .\" These slides use the mm and gpresent groff macros. .\" For example, on OpenBSD, install these ports: .\" groff, gpresent, ghostscript. .\" Build instructions: .\" groff -mm -mpresent bsdcan15-mandoc.roff > talk.pps .\" presentps -l talk.pps > talk.ps .\" ps2pdf talk.ps .\" .\" -------------------------------------------------------------------- .\" .\" --- global mm configuration settings ------------------------------- .nr Pi 3 .\" --- global gpresent configuration settings ------------------------- .DEFCOLOR Kea1 0 0.8 0.48 .DEFCOLOR Kea2 0 0.5 0.3 .TITLECOLOR Kea1 .SUBTITLEFORMAT C .SUBTITLECOLOR Kea2 .FOOTERSIZE 2 .\" We don't want a header line for the title page, .\" so we have to start it before setting up headers. .TITLE "mandoc: becoming the main BSD manual toolbox" .\" === gpresent header setup ========================================== .\" --- define gpresent extension registers ---------------------------- .nr gpe_page_tot 1 .nr gpe_page_sec 0 .af gpe_page_sec I .nr gpe_time_tsec 16*60+17*60 .nr gpe_time_hour 16 .nr gpe_time_min 17 .af gpe_time_min 02 .nr gpe_time_sec 0 .af gpe_time_sec 02 . .\" --- macro to start a new section ----------------------------------- .de GPE_SECTION .ds gpe_title_sec \\$1 .nr gpe_page_sec 0 .. .\" --- macro to prepare a new page ------------------------------------ .de GPE_NEXT .ds gpe_next \\$1 .SK .. .\" --- gpresent page header callback ---------------------------------- .de HEADER .nr gpe_page_tot +1 .nr gpe_page_sec +1 .sp 0.5v .ds gpe_middle page \\n[gpe_page_tot]: \\*[gpe_title_sec] \\n[gpe_page_sec] .tl 'Ingo Schwarze: mandoc'\\*[gpe_middle]'BSDCan 2015, June 13, Ottawa' .sp -0.5v .\" horizontal line below the page header \l'\\n(.lu'\h'-\\n(.lu' .br .. .\" --- initialize the first section before completing the title page -- .GPE_SECTION INTRO .\" === define some gpresent extension macros ========================== .\" --- two-column mode (for images) ----------------------------------- .\" 1st arg: width of first column .\" 2nd arg: move second column up by this amout (default 0.5v) .\" switch column with normal .MULN, end with normal .MULE .de GPE_MULB .nr gpe_colwr \\n(.l-\\$1-1n .ie \\n[.$]>1 .ds gpe_vsp \\$2 .el .ds gpe_vsp 0.5v .sp -\\*[gpe_vsp] .MULB \\$1 1n \\n[gpe_colwr]u .sp \\*[gpe_vsp] .. .\" --- emphasis ------------------------------------------------------- .\" arg: text .de GPE_EM .COLOR red \\$1 .COLOR P .. .\" --- small text ----------------------------------------------------- .\" arg: text .de GPE_SM .S -4 .ce \\$1 .S P .. .\" --- title page ----------------------------------------------------- .\" The main title line has already been printed. .SUBTITLE "BSDCan 2015, June 13, Ottawa" .SUBTITLE "Ingo Schwarze " .PSPIC Images/CynthiaLivingstonBe2013.eps 14cm .GPE_SM "Cynthia Livingston's OTTB \(lqBedifferent\(rq \ (c) 2013 C. Livingston (with permission)" .\" === gpresent footer setup ========================================== .\" We dont want a footer line for the title page, .\" so we have to set it up after completing the title page. .SK .\" --- macros to start a new page ------------------------------------- .\" arg: time for this page in seconds .de GPE_TIME .nr gpe_time_tsec +\\$1 .nr gpe_time_hour \\n[gpe_time_tsec]/3600 .nr gpe_time_min \\n[gpe_time_tsec]%3600/60 .nr gpe_time_sec \\n[gpe_time_tsec]%60 .ds gpe_source \\$2 .. .\" --- gpresent page footer callback ---------------------------------- .de FOOTER .ps 18 .vs 20 .sp -2v \l'\\n(.lu'\h'-\\n(.lu' .br .tl '\s-6\\n[gpe_time_hour]:\\n[gpe_time_min]:\s-2\\n[gpe_time_sec]\ \\*[gpe_source]\s+8''\\m[Kea2]\\*[gpe_next]\ \ \(->\\m[]' .ps .vs .. .\" The INTRO section was already started in header.roff. .TITLE "Brief history of UNIX documentation" .BL .LI The key point: All documentation in one place and one format. .br Easy to find, uniform and easy to read and write. Be correct, complete, concise. .LI 1964: RUNOFF/roff markup syntax by Jerome H. Saltzer, MIT. .br Unobtrusive, diff(1)-friendly, easy to hand-edit, simple tools, high quality output. .LI 1971: Basic manual structure by Ken Thompson and Dennis Ritchie .br for the AT&T Version 1 UNIX manuals, Bell Labs. .LI 1979: man(7) physical markup language for AT&T Version 7 UNIX. .LE .sp .GPE_MULB 16.5c .BL .LI 1989: .GPE_EM "mdoc(7) semantic markup by Cynthia Livingston" .br for 4.3BSD-Reno. Powerful, self-contained, portable. .LI 1989: GNU troff by James Clarke. .LI 2001: mdoc(7) rewrite by Werner Lemberg .br and Ruslan Ermilov for groff-1.17. .LI 2008: mandoc(1) started by Kristaps Dzonsons. .LI 2010: mandoc(1) is the only documentation formatter .br in the OpenBSD base system. .LE .MULN .PSPIC Images/BSDBeastie.eps .MULE .BL .LI 2014: mandoc(1) used by default in OpenBSD, FreeBSD, NetBSD, illumos. .LE .GPE_TIME 150 .GPE_NEXT "What is the mandoc toolbox?" .TITLE "What is the mandoc toolbox?" .SUBTITLE "User perspective: man(1), the manual viewer" One comprehensive tool! .br Normal operation always proceeds in three steps: .AL .LI .B Find one or more manuals in the file system or using a database .br by manual name \(em .B man(1) \(em .br or by search query \(em .B apropos(1) = man -k .br The result of this step can be printed out with man -w. .LI .B Format the manual page. .br This step can be accessed individually with .B mandoc(1) = man -l. .LI .B Display the formatted text. .br On a terminal device, use a pager unless -c is given. .LE .SUBTITLE "Progress since last year" .BL .LI In 2014, man(1) was still out of scope; now we have a unified user interface. .LI Much simplified man.conf(5) configuration file. .LE .GPE_TIME 90 .GPE_NEXT "What else is in the toolbox?" .TITLE "Auxiliary components in the toolbox" .BL .LI makewhatis(8) database generation and maintenance .LI mandoc(1) -Tlint syntax checker .LI mandoc(1) -Thtml polyglot HTML5 generator .LI mandoc(1) -Tpdf and -Tps formatters .LI mandoc(1) -Tman format converter .LI mandoc(1) -Ttree parse tree debugger .LI soelim(1) file inclusion resolver .LI \&... .LE .PSPIC Images/MacArmstrongKingEstate.eps 8c .GPE_SM "Moorside Cottage, Mackenzie King Estate, Gatineau Park\ \(co 2009 Mac Armstrong @flickr (CC)" .GPE_TIME 30 .GPE_NEXT "Topics of this talk" .TITLE "Which are the topics of this talk?" .AL .LI Unified user interface: man(1) and man.conf(5). .LI More powerful search on the web: man.cgi(8). .LI Better formatting of equations: eqn(7). .LI No more options required for UTF-8 support. .LI Eradicating bugs with afl(1), the American Fuzzy Lop. .LI Detect use of unsupported features: -Wunsupp. .LI Help LibreSSL documentation with pod2mdoc(1). .LI Status in various operating systems and future directions. .LE .PSPIC Images/LezumbalaberenjenaBlackLake.eps .GPE_SM "Black Lake near King Mountain, Gatineau Park, Quebec\ \(co 2012 Lezumbalaberenjena@flickr (CC)" .GPE_TIME 120 .\" .\" What needed to be done to replace man(1) in OpenBSD, .\" what the advantages are, and what the price is. .\" .GPE_SECTION MAN(1) .GPE_NEXT "What happened to man(1)?" .TITLE "Replacing the manual viewer" .BL .LI OpenBSD no longer uses the traditional BSD man(1) manual viewer, .br but an implementation of man(1) integrated in mandoc. .LI Traditional setup: .br man(1) finds the files in the file system and forks and executes .br the formatter (groff, mandoc) and the pager (more, less). .LI New setup: .br man(1) integrated in mandoc finds the files in the database or the file system .br and runs the formatter without forking, then forks and executes the pager. .LE .GPE_MULB 11c .sp 2v .BL .LI First portable release 1.13.2 .br on December 13, 2014 .LI Switched on in OpenBSD .br on December 14, 2014 .LE .MULN .PSPIC Images/LezumbalaberenjenaMasham.eps .GPE_SM "Paroisse Sainte C\('ecile de Masham, Quebec" .GPE_SM "\(co 2013 Lezumbalaberenjena@flickr (CC)" .MULE .GPE_TIME 50 .GPE_NEXT "Which steps were needed?" .TITLE "Steps to replace the manual viewer" .sp -1v .SUBTITLE "Preliminaries (Kristaps Dzonsons)" .BL .LI Concept of a manual page search database (April 2, 2011) .LI Create it: Implementation of makewhatis(8) (release 1.11.2, May 12, 2011) .LI Use it: Implementation of apropos(1) (release 1.12.0, October 8, 2011) .LI Port to SQLite3 (June 8, 2012) .LE .SUBTITLE "Main steps (Ingo Schwarze)" .BL .LI Polishing the SQLite3 implementation (t2k13 hackathon, June 2013) .LI Support compressed manuals (makewhatis(8): March 26, man(1): September 3, .so: November 26, 2014) .LI Switch makewhatis(8)/apropos(1) to mandoc in OpenBSD (April 18, 2014) .LI First portable release with SQLite3 (1.13.1, August 10, 2014) .LI Unified user interface and main program (August 16-26, 2014) .LI Options man(1) -l and -h (August 30, September 3, 2014) .LI File system lookup (January 13, 2015) .LI portable: man(1) even without database support (February 3, 2015) .LE .GPE_TIME 50 .GPE_NEXT "Why was man(1) replaced?" .TITLE "A better manual viewer" .GPE_MULB 15c .SUBTITLE "Current advantages" .BL .LI Unified interfaces: .br man can use: -W -T -O -I from mandoc(1) .br apropos can use: -w -h -a from man(1) .ig man -Tlint crypt_checkpass # check an installed manual man -Thtml lynx | lynx -stdin # pager overkill man -Tps gv | gv - # even more pager overkill .. .LI Allow much simpler man.conf(5) format \(-> next slides .LI database priority now overrides section priority .LI Use additional names from .Dt/.TH and NAME .Nm (250 new entries in OpenBSD, compared to 10200 existing ones) .LI One less userland program to maintain .br (that had rather old code) .LE .MULN .PSPIC Images/DougKerrEganville.eps .GPE_SM "Bonnechere Museum, Eganville" .GPE_SM "\(co 2011 Doug Kerr @flickr (CC)" .MULE .SUBTITLE "Possible future advantages" .BL .LI Possibility to get rid of multiple ln(1) links to the same manual .LI Possibility to implement an interactive chooser (-i) .LE .GPE_TIME 120 .GPE_NEXT "What is the price?" .TITLE "A better manual viewer (2)" .SUBTITLE "Prices to pay" .GPE_MULB 9c Database lookup is slightly slower .br than file system lookup: .br Ten milliseconds additional delay .br for displaying a manual .br on my notebook. .sp After installing new manuals, .br makewhatis(8) is required .br for full database support. .br However, pkg_add(1) .br does that automatically .br and man(1) works even without it. .MULN .PSPIC Images/OpeongoRoad.eps .GPE_SM "Opeongo Road, historic colonization road" .GPE_SM "\(co 2008 P199@wikimedia (CC)" .MULE .SUBTITLE "Very little downsides, if any!" .GPE_TIME 60 .GPE_NEXT "What was wrong with man.conf(5)?" .TITLE "Undesirable features of the old man.conf(5) format" .BL .LI Shell globbing for directory tree names .LI Different directory trees for man(1) and apropos(1) .LI Different directory tree search order for man(1) and apropos(1) .LI Custom file names for mandoc.db(5) files in individual directory trees .LI Custom subdirectory names not of the form man+section or cat+section .LI Default search: Additional directories outside all sections .LI Default search: Exclusion of certain sections in certain directory trees .LI Section-specific search: Additional directories outside any configured trees .LI Section-specific search: Exclusion of some directories configured by default .LI Different search order for different sections .LI Different decompression filters for different sections .LI Custom file name suffixes not of the form *.section, with globbing .LI Custom file name suffix for preformatted pages instead of .0, with globbing .LI Configuration file versioning .LE .SUBTITLE "So complicated that everybody hated it and almost nobody used it" .GPE_TIME 50 .GPE_NEXT "What about the new man.conf(5)?" .TITLE "Current features of the new man.conf(5) format" .BL .LI .B manpath .I directory \(em configure a tree .br automatically consistent across man(1), apropos(1), makewhatis(8) .LI .B output .I options \(em for example: .BL .LI for the terminal: output width 104 .LI for HTML: output style /man.css .LI for ps/pdf: output paper a4 .LE .LE .SUBTITLE "Very easy to use, needs almost no learning" .PSPIC Images/WilnoOntario.eps 12c .GPE_SM "Wilno, Renfrew County, Ontario \(co 2009 P199@wikimedia (CC)" .GPE_TIME 30 .GPE_NEXT "Is more needed?" .TITLE "man.conf(5) features to be implemented on demand" .BL .LI .B alias .I "aliasname dirname" \(em make a tree accessible with -s .LI .B sections .I "name name name" \&... \(em section names and search order .LI .B filter .I "suffix command" \(em custom filters, in particular for decompression .LI .B pager .I command \(em configure a default pager .LI .B input .I "option value" \(em for example input os name .LE .SUBTITLE "So far, there is no noticeable demand -> KISS." .PSPIC Images/WhitneyMadawaskaRiver.eps 10c .GPE_SM "Madawaska River at Whitney \(co 2006 P199@wikimedia (PD)" .GPE_TIME 40 .\" .\" What needed to be done to replace man.cgi(8) in OpenBSD, .\" what the advantages are, and what the price is. .\" .GPE_SECTION MAN.CGI(8) .GPE_NEXT "What happened on the web?" .TITLE "The new man.cgi(8) for manual pages on the web" .BL .LI OpenBSD no longer uses the traditional man.cgi Perl script .br by Wolfram Schneider (wosch@FreeBSD) .br but a man.cgi(8) implementation included in the mandoc toolkit. .LI Traditional setup: The man.cgi Perl script forks and executes the system's man(1) or apropos(1) commands, parses the output, and converts it to HTML. .LI Traditionally, the spawned man(1) in turn forked and executed groff, .br then later \(em about since 2012 \(em mandoc, but not in HTML mode. .LI New setup: man.cgi(8) is a C program linked against the mandoc parsers, .br the mandoc.db(5) database client code, and the mandoc HTML formatter. .LE .PSPIC Images/GaryWegeCommonLoons.eps 10c .GPE_SM "Common Loons \(co 2009 Gary J. Wege @USFWS (CC)" .GPE_TIME 60 .GPE_NEXT "Which steps were needed?" .TITLE "Steps to replace the web manual viewer" .sp -1v .GPE_MULB 12c .SUBTITLE Preliminaries .BL .LI Everything needed for man(1) .LI Berkeley-db based man.cgi(8) by Kristaps Dzonsons (developed since Nov 9, 2011; first release 1.12.1, March 23, 2012) .LI New makewhatis(8)/apropos(1) based on SQLite3 in OpenBSD since April 18, 2014 .LE .SUBTITLE "Main steps" .MULN .PSPIC Images/PtrbnsnAlgonquinCacheLake.eps .GPE_SM "Cache Lake, Algonquin Park" .GPE_SM "\(co 2005 Ptrbnsn@wikimedia (CC)" .MULE .BL .LI OpenBSD g2k14 general hackathon in Ljubljana, July 8-14 .LI Convert to SQLite3, polish, then switch over on July 12 .LI A some additional functional fixes on July 13-25 .LI Security audit by Sebastien Marie on July 18-23 .LI First portable release: 1.13.1 on August 10 .LI Release with HTML5 output: 1.13.2 on December 13 .LI All by Ingo Schwarze, 2014 .LE .GPE_TIME 30 .GPE_NEXT "What was polished?" .TITLE "Polishing the web manual viewer" Even though all underlying functionality was already quite mature when i started, there were surprisingly many things to polish in many distinct components: .BL .LI Configuration: Let manpath.conf be a plain text list of the directories to use. .br Do almost all other configuration at compile time, avoid run-time configuration .br to reduce the attack surface. .LI HTTP parser: make HTTP decode linear in time (tedu@) .LE .GPE_MULB 10c .BL .LI Query parser: .br Various backward-compatibility features to not break existing links in static pages around the web. Support backslash-escaping of white space in the query expression (reported: Marcus Merighi, Sep 14) .LI Page selection: .br Distinguish between man(1) and apropos(1) mode. Even when there are multiple pages, show one of them. .LE .MULN .PSPIC Images/TomThomsonAprilInAlgonquin.eps 10c .GPE_SM "April in Algonquin Park \(co 1917 Tom Thomson (PD)" .GPE_SM "Memorial Art Gallery, Owen Sound, Georgian Triangle" .MULE .GPE_TIME 50 .GPE_NEXT "What else was polished?" .sp -0.5v .TITLE "Polishing the web manual viewer (2)" .BL .LI Start page: section and architecture dropdowns, the latter with a default of "All Architectures", and some additional polishing. .LI HTTP output: HTTP headers must end lines with CRLF (tedu@) .LI Query printer: include manpath=, omit empty parameters, preserve manpath and arch in .Xr links .LI HTML output: use manroot as the default for .Os .br and start moving towards polyglot HTML5 (completed Sep 27) .LI Error handling: make it clear, the code readable, and avoid information leakage .LI Documentation: full rewrite of the man.cgi(8) manual .LI Internals: namespace cleanups, in particular of global variables .LE .P Various features were developed for man.cgi(8) that can be useful elsewehere, too: .BL .LI The mandoc -Ios option to handle multiple OS versions in parallel by a single installation (already on May 24, 2012) .LI The MANSEARCH_MAN internal mode in mansearch.c, reused for man(1) .LI Sort result pages first by section number, then by name; that's also nice for command-line apropos(1). .LI Unify console and CGI section titles (August 26) .LE .GPE_TIME 30 .GPE_NEXT "What about security?" .TITLE "Security issues of the web manual viewer" .BL .LI Basic problem: turning untrusted input into harmful processing or output .LI Sources of untrusted input: PATH_INFO, QUERY_STRING, manual page content .LI Harmful processing or output: Information leakage, resource exhaustion, misleading or dangerous HTTP headers or HTML content .LI Relevant modules: CGI steering program (cgi.c) and HTML formatter (html.c) .LE .SUBTITLE "Auditing approaches" .BL .LI Start with all untrusted input, trace forward, and check how it is used. .LI Locate all output statements (printf, puts, putchar...), trace backward, and check where the data comes from. .LI Locate all interfaces between the steering program and the HTML formatter, identify the data passed through the interface, and trace backward and forward to see where it comes from and what is done with it. .LE .P Almost all security issues were initially reported by Sebastien Marie, but i did the full audit described above to make sure nothing was missed. I also started an infrastructure for regression tests of HTML output (October 27). .GPE_TIME 130 .GPE_NEXT "Which vulnerabilities were found?" .TITLE "Security issues found in the web manual viewer" .sp -1v .nr Lsp_save \n[Lsp] .nr Lsp 0.1v .BL .LI Invalid configuration \(-> segfault: .br Fix: When there is no MAN_DIR or manpath.conf, log and exit. .LI Unvalidated PATH_INFO \(-> access to unrelated files, information disclosure: .br Fix: Reject absolute paths and ascenscion to the parent directory. .LI Unvalidated QUERY_STRING manpath \(-> info disclosure in error message: .br Fix: Validate the manpath up front using a whitelist. .LI Invalid characters in QUERY_STRING \(-> XSS: .br Fix: Restrict the character set of strings passed into html_alloc(). .LI Roff escape sequences and quotes in manuals \(-> XSS: .br Fix: HTML-encode quotes and rendered escape sequences. .LI Choosing the right encoding is a tricky business... .br Some output needs HTML encoding, some URI encoding, some both. .\" July 25 .LI Crafted expensive regular expressions \(-> REDoS attacks: .br No full fix possible. Mitigate by limiting CGI process execution time. .\" August 21 .LE .nr Lsp \n[Lsp_save] .GPE_MULB 18c .in 1c .PSPIC Images/RyanTirMaggieLake.eps 17c .MULN .sp 2v .S -4 .DS Maggie Lake Algonquin Park .sp \(co 2011 Ryan Tir @flickr (CC) .DE .S P .MULE .GPE_TIME 150 .\" .\" How the new eqn(7) MathML output works .\" and in which respects the newly improved eqn(7) terminal output .\" is now better than in groff(1). .\" .GPE_SECTION EQN(7) .GPE_NEXT "What about equations?" .TITLE "Equations in manual pages" .BVL 1c .LI "Relevance of the eqn(7) language:" Used less than mdoc(7), man(7), and tbl(7); but: X.org! .LI "Problem was: parsing works well, formatting was ugly..." Representing mathematical formula on the terminal is hard. .LI "Kristaps mostly completed the parser in 2011." (started Feb 6, released 1.10.10 Mar 20, mostly complete in 1.11.5 on July 24). .LE .SUBTITLE "The parser is quite straightforward, just over 1000 lines." .GPE_MULB 8.5c .sp Main loop: .BL .LI Parse a token. .LI Generate a syntax tree node. .LI If the token is binary, .br relink the preceding subtree. .LE .MULN .PSPIC Images/SeanMarshallMidland.eps .GPE_SM "Archer Daniels Midland \(co 2013 Sean Marshall @flickr (CC)" .MULE .GPE_TIME 60 .GPE_NEXT "What was improved?" .TITLE "Better formatting of equations" .BL .LI .B "HTML output:" rewrite to generate MathML (Kristaps Dzonsons, Oct 10) .br straightforward, 1:1 translation of the syntax tree, less than 200 lines of code .br quite beautiful in a graphical browser .LI .B "Terminal output:" .BL .LI GNU eqn: moves elements up and down to the previous or next line and draws bars out of ASCII characters \(em results are unintelligible .LI mandoc output rewrite (Ingo Schwarze, Oct 12): .br linear textual representation, showing fractions like (a + b)/(c + d), .br matrices like ((a_11 a_12)(b_21 b_22)), and roots like sqrt(x) .LI certainly not pretty, but at least you can figure out what the formulas mean .LI merely 125 lines of very straightforward code .LE .LI I added support for in-line equations (Oct 16). That helps a lot to not lose mathematical symbols embedded in the middle of the text, in various manuals. .LI mandoc eqn now much better than GNU eqn for both terminal and HTML .br PostScript/PDF is still the domain of GNU eqn: mandoc just does the same as on the terminal. .LE .P All that was first released together with HTML5 output in 1.13.2 on Dec 13, 2014. .GPE_TIME 90 .\" .\" How the new transparent UTF-8 input and output works .\" without requiring the user to specify any options. .\" .GPE_SECTION UTF .GPE_NEXT "What about UTF-8?" .TITLE "Multibyte character support" .sp -0.5v .BVL 1c .LI "Non-english manuals:" rare \(em hard to maintain \(em worse than nothing when outdated... .LI "But the tools must not hinder reading them!" That would only aggravate the problem. .LI "Hence, early basic UTF-8 support (Kristaps Dzonsons, May 20-26, 2011):" Like groff, use a preconv(1) preprocessor: UTF-8 \(-> roff escape sequences .br and -Tutf8 and -Tlocale terminal output modes. .LE .SUBTITLE "Improvements in 2014" .\" 2013 Oct 5 release 1.12.2: fix -Tutf8 and more (Ingo Schwarze) .GPE_MULB 9cm .BL .LI integrate preconv(1): .br direct UTF-8 input (Oct 25) .LI default to -Tlocale (Dec 2) .br (formerly -Tascii) .LI No more options needed! .LI released with 1.13.2 (Dec 13) .LI rewrite UTF-8 parser (Dec 19) .LI all by Ingo Schwarze .LE .MULN .PSPIC Images/JoeMabelWasaga.eps 10.5c .GPE_SM "Wasaga Beach, L. Huron \(co 2013 Joe Mabel @wikimedia (CC)" .MULE .GPE_TIME 110 .\" .\" Which types of errors were found by Jonathan Gray .\" with the American Fuzzy Lop (afl), .\" and what lessons are to be learned from that exercise. .\" .GPE_SECTION AFL .GPE_NEXT "What's teh fuzz all about?" .TITLE "American Fuzzy Lop inspecting mandoc" .SUBTITLE "Fuzzer: Try to crash or hang a program by feeding it varying input." .P .GPE_MULB 8c http://lcamtuf.coredump.cx/afl/ .P "Compile-time instrumentation and genetic algorithms to automatically discover clean, interesting test cases that trigger new internal states." .P Goal: Full functional coverage. .P For mandoc, afl can be seeded with the extensive test suite. .P For mandoc, full functional coverage requires running afl continuously for several days on modern PC hardware. .MULN .PSPIC Images/LithoniusAmericanFuzzyLop.eps .GPE_SM "American Fuzzy Lop \(co 2008 Lithonius@wikimedia (PD)" .MULE .SUBTITLE "Run by Jonathan Gray (jsg@) repeatedly since November 21, 2014." .ce 45 issues grand total \(-> Quantitative (but not statistical) analysis. .GPE_TIME 90 .GPE_NEXT "What caused bugs?" .TITLE "Root causes of bugs found with afl" .BL .LI 15/45 logic errors arising from complexity .br 9/15 excessive complexity in language design (badly nested blocks) .br 6/15 excessive complexity in the implementation of macro rewinding .LE .GPE_MULB 12c .BL .LI 14/45 exceptions from invariants .br 6/14 from supposedly generic invariants .br 8/14 from macro-specific invariants .sp .LI 6/45 missing elementary input validation .br (too large; too small; zero; negative; .br invalid byte in binary data) .LI 5/45 buffer overflows: .br string parser passes terminating \e0 .sp .LI 3/45 use after free of an allocated pointer .LI 1/45 abuse of assert() for input validation .LI 1/45 excessive power of roff(7) language: .br user input requests infinite recursion .LE .MULN .PSPIC Images/TudorCostacheBarrieSpiritcatcher.eps 7c .GPE_SM "Spiritcatcher by Ron Baird (1986) in Barrie" .GPE_SM "\(co 2009 Tudor Costache @wikimedia (CC)" .MULE .GPE_TIME 150 .GPE_NEXT "How severe were these bugs?" .TITLE "Severity of bugs found with afl" .sp -1v .BL .LI 2 write buffer overruns (both advancing a pointer past \e0 and returning it) .LI 3 read buffer overruns (all advancing a pointer past \e0 without returning it) .LI 2 use after free (both free a pointer, keep a copy, and use it) .LI 2 unsigned integer underflows (by unchecked subtraction and unvalidated input) .LI 2 cases of effectively infinite output (by not checking input for large numbers) .LI 2 infinite loops (one by user input, one by complicated internal logic) .LI 1 division by zero (by unvalidated user input) .LI 11 NULL pointer accessess .LI 20 assertion failures .LE .SUBTITLE "Here: The easier to avoid, the more dangerous the failure." .sp -0.5v .GPE_SM "Not guaranteed for other projects,\ but still, the following are likely to pay off:" .AL .LI Be particularly careful when passing around parse pointers. .LI Make sure you don't parse beyond \e0. .LI Watch out for use after free. .LI Don't forget to validate any input. .LI Be careful with arithmetic operations (/, *, -, +, etc.) .LE .GPE_TIME 120 .GPE_NEXT "What are the conclusions?" .TITLE "Conclusions from bug-hunting with afl" .sp -0.5v .BL .LI Largest numbers of bugs in most complex code \(-> avoid complexity. .LI Distribution across modules consistent with flat distribution \(-> keep code small. .LI Even mature open source projects have bugs. .br Not unusual: about 0.5 to 3 serious bugs per 1000 lines of C code. .LI Aggravating factors in this case: No formal language definitions, languages not designed according to any strict paradigm, languages evolved historically, parser requirements and design goals discovered piece-meal, again and again breaking existing logic and existing invariants. .LI If you can afford to spend the effort, explicitly specify the invariants you intend to guarantee, audit all your code changing data structures to make sure these are actually maintained, and audit all your code using data structures to make sure no other assumptions are made. That may catch a substantial fraction of severe bugs even without fuzzing, about one third in the case of mandoc. .LE .PSPIC Images/JliuBarrieWaterfront.eps .GPE_SM "Barrie across Kempenfelt Bay, Lake Simcoe, Ontario\ \(co 2010 Jliu@wikimedia (CC)" .GPE_TIME 120 .\" .\" How the new -Wunsupp option is going to simplify porting of software .\" and improve manual page formatting quality in FreeBSD ports. .\" .GPE_SECTION UNSUPP .GPE_NEXT "What about error handling?" .TITLE "Three message levels" .AL .LI Warnings: Tell manual authors that the quality of the code can be improved. .LI Errors: Tell manual authors that the intent of the code is unclear. .br \(-> Likely information loss or seriously bad formatting. .LI Unsupported: Tell porters that a manual page uses features not (yet) supported by mandoc and groff should better be used instead of mandoc. .LI The former fatal level no longer exists: .br It meant that mandoc(1) was unable to produce any output at all. .br That can no longer happen (since January 15, 2015). .LE .GPE_MULB 9c .sp 2v Several major cleanups .br of messages and levels in mandoc: .DS July 2009, May 2010, August 2010, October 2010, January 2011, March 2011, July 2014, January 2015, ... .DE .MULN .PSPIC Images/PaulBicaTorontoSunset.eps 10c .GPE_SM "Toronto \(co 2008 Paul Bica @flickr (CC)" .MULE .GPE_TIME 70 .GPE_NEXT "How do we handle manual pages in ports?" .TITLE "Manual pages in ports" .ce By now, 95% of ports manuals just work with mandoc. .SUBTITLE "The OpenBSD way" .BL .LI Mark those that don't work individually with USE_GROFF (about 200 remain). .LI Preformat these manuals at port build time with groff, .br package the preformatted versions of the manuals. .LE .GPE_MULB 9c .sp 2v Advantage: .br Perfect manuals for every port. .sp 2v Inconveniences: .br Needs support in the .br ports infrastructure .br (written by Marc Espie@), .sp 0.5v and manual maintenance .br of the USE_GROFF variable. .MULN .PSPIC Images/PaulBicaHumberBridge.eps 12c .GPE_SM "Humber Bay Bridge, Toronto \(co 2010 Paul Bica @flickr (CC)" .MULE .GPE_TIME 60 .GPE_NEXT "How does FreeBSD do it?" .TITLE "Manual pages in ports (2)" .BL .LI The FreeBSD way: .BL .LI Inside man(1), try mandoc -Tlint -Wunsupp and let mandoc itself decide whether it accepts the job. If so, use mandoc, otherwise groff. .LI Advantage: No manual checking of ports required. .LI Inconveniences: Double parsing at man(1) call time. .br False negatives: mandoc doesn't realize it's unfit for the job .br \(-> user gets incomplete or misformatted manual .br False positives: mandoc feels shy even though its output is fine .br \(-> time wasted for running groff .LE .LE .GPE_MULB 10c 1.5v .BL .LI The NetBSD way: .BL .LI Just ignore the whole problem (if i understand correctly). .LI Seems to be good enough for them, i don't hear any complaints regarding those about 5% broken ports manuals in NetBSD. .LE .LE .MULN .PSPIC Images/PaulBicaBloorViaduct.eps 9.5c .GPE_SM "Bloor Viaduct, Don Valley, Toronto" .GPE_SM "\(co 2013 Paul Bica @flickr (CC)" .MULE .GPE_TIME 70 .GPE_NEXT "Where to go from here?" .TITLE "Possible future directions for ports manuals" .BL .LI For the OpenBSD way: Improve low-level roff(7) support in mandoc(1) reducing the number of USE_GROFFs required. .BL .LI Chances aren't bad, there are some big classes of problems it might be possible to solve, so we can certainly get below 200. .LI But, at some point, there will be diminishing returns... .LI naddy@ eventually wants to get rid of USE_GROFF altogether. .LI Not yet quite sure how it will be done. .LE .LI For the FreeBSD way: Improve -Wunsupp logic. .BL .LI Detection can certainly be improved in some typical situations. .LI But we will run into diminishing returns, too; .br the number of ways to abuse low-level roff in manuals is boundless. .LI Not yet sure how good it can become. .LE .LE .GPE_MULB 16c .in 2 .PSPIC Images/KirilStraxTorontoThompsonPark.eps 14c .MULN .S -4 .sp 1.5v .DS Tommy Thompson Park Toronto, Ontario .sp 0.5v \(co 2008 Kiril Strax @flickr (CC) .DE .S P .MULE .GPE_TIME 60 .\" .\" What Anthony Bentley did with pod2mdoc(1) on LibreSSL documentation, .\" and which future possibilities exist in the vicinity. .\" .GPE_SECTION POD2MDOC(1) .GPE_NEXT "What about LibreSSL?" .TITLE "Getting started with pod2mdoc(1)" .BL .LI perlpod(1): maybe the third most important documentation format after mdoc(7) and man(7); used by Perl and many other projects, for example OpenSSL .LI usually converted to man(7) with pod2man(1) written in Perl .LI downsides: no semantic searching, LibreSSL developers have to cope with a second (and less useful) documentation language, consumes time during the build, pod2man(1) man(7) output contains ugly low-level roff(7) and keeps getting worse, the pod2man(1) utility itself is hackish and ugly .LI Hence we are working on pod2mdoc(1), a conversion tool from perlpod(1) to mdoc(7) format. .LI During g2k14 in Ljubljana (July 2014), Anthony Bentley started to convert the LibreSSL libssl manuals from perlpod(1) to mdoc(7) with pod2mdoc(1), mostly based on the version Kristaps developed in March/April 2014, containing only minor fixes on my part (versions 0.0.12 on July 11 and 0.0.13 on July 19). .LI With those versions of pod2mdoc(1), considerable manual postprocessing was still required. .LI The completed work was finally committed on October 12. .LI One important benefit: An extensive list of bug reports and feature requests. .LE .GPE_TIME 120 .GPE_NEXT "What was improved?" .TITLE "Improvements of pod2mdoc(1)" In February 2015, i started work on LibreSSL libcrypto, improving pod2mdoc(1) in parallel, using Anthony's list and my own observations. .GPE_MULB 11c .BL .LI whitespace improvements .BL .LI preserve blank lines inside .br literal displays (Feb 19) .LI re-wrap text lines (Feb 23) .LI new sentence, new line (Feb 14) .LI print whitespace before words, .br never after (Feb 13) .LI horizontal spacing fixes (Feb 20) .LE .LI handle all closing punctuation (Feb 19) .LI escape literal double quotes at the start of macro arguments (Feb 19) .LE .MULN .PSPIC Images/CanteausKingstonTheologicalHall.eps .GPE_SM "Theological Hall, Queen's University, Kingston" .GPE_SM "\(co 2011 Canteaus@wikimedia (CC)" .MULE .SUBTITLE "Such polishing may seem minor but is actually important:" .br The goal is to commit the converted manuals. .br So the generated code must be clean and maintainable. .br Cleaning it up by hand is very tedious. .GPE_TIME 60 .GPE_NEXT "Which new concepts?" .TITLE "New concepts in pod2mdoc(1)" .BL .LI SYNOPSIS rendering for library manuals: .BL .LI function prototypes -> .Ft/.Fo/.Fa/.Fc (Oct 22, version 0.1) .LI render preprocessor lines with .Fd (Feb 13) .LE .LE .GPE_MULB 9c .BL .LI ohash-driven markup .BL .LI function names with .Fn .br (Feb 13) .LI function args with .Fa .br (Feb 13 and 23) .LI type names with .Vt .br (Feb 13) .LI #defined names: .Dv or .Fn .br (Feb 19) .LE .LI foreign function names: .Xr .br (Feb 14) .LE .MULN .PSPIC Images/MkooimanKingstonCityHall.eps 10c .GPE_SM "Kingston City Hall \(co 2013 Mkooiman@wikimedia (CC)" .MULE .P .ce All released with pod2mdoc-0.2 on May 19, 2015. .SUBTITLE "Similar logic is needed for legacy man(7) manuals." .GPE_TIME 120 .\" .\" Which operating systems now use mandoc, .\" what the recommended next steps are for these systems, .\" and in which directions i'm planning to continue mandoc development. .\" .\" Since my talk at BSDCan 2014, FreeBSD and illumos (formerly OpenSolaris) .\" have switched to use mandoc as the default manual page formatter. .\" .GPE_SECTION STATUS .GPE_NEXT "What is the status in various systems?" .TITLE "Status in OpenBSD" .SUBTITLE "Status last year, at BSDCan 2014" .GPE_MULB 17.5c 4v .BL 3n 1 .LI Kristaps@ developed mandoc(1) since November 22, 2008. .LI Schwarze@ maintaining it since June 14, 2009. .LI Base system manuals built with mandoc(1) since April 3, 2010. .LE .MULN .PSPIC Images/OpenBSD.eps .MULE .BL 3n 1 .LI Releases fully rely on mandoc(1) since OpenBSD 4.8, November 1, 2010. .LI Groff disconnected from base build since October 18, 2010: .br .GPE_EM "mandoc(1) is the only documentation formatter in base\ for almost five years." .LI No stable releases contain groff since OpenBSD 4.9, May 1, 2011. .LI Install manual sources, not preformatted manuals since June 23, 2011. .LI SQLite-based code in the source tree since December 30, 2013. .LI .GPE_EM "makewhatis(8)/apropos(1) using mandoc" since April 18, 2014 (rel. with 5.6). .LE .SUBTITLE "New since last year" .BL .LI New man.cgi(8) online on www.openbsd.org since July 12, 2014. .LI Unified interface for mandoc(1) and apropos(1) since August 26, 2014. .LI .GPE_EM "man(1) switched to the mandoc implementation" on December 14, 2014. .LI All released with OpenBSD 5.7 on May 1, 2015. .LE .GPE_TIME 20 .GPE_NEXT "What got done in FreeBSD?" .TITLE "Status in FreeBSD" .SUBTITLE "Status last year, at BSDCan 2014" .GPE_MULB 17.5c 5v .BL .LI An mdocml port by Ulrich Sp\(:orlein exists since March 9, 2009. .LE .MULN .PSPIC Images/FreeBSD.eps .MULE .BL .LI Source code in the base repo and installed by default since October 19, 2012. .LI .GPE_EM "First released with FreeBSD 10.0 on January 20, 2014." .LE .SUBTITLE "New since last year" .BL .LI All work done by Baptiste Daroussin (bapt@). .LI .GPE_EM "mandoc(1) is the default formatter" since November 23, 2014. .LI Using -Wunsupp since March 2, 2015. .LI .GPE_EM "apropos(1)/makewhatis(8) default to the mandoc versions" since May 30, 2015 .LI Code is up to date using the portable stable release mandoc-1.13.3. .LI To be released with FreeBSD 11 in the future. .LI Still using the man(1) implementation written as a sh(1) script. .LE .GPE_TIME 60 .GPE_NEXT "Any progress in DragonFly and NetBSD?" .TITLE "Status in NetBSD" .BL .LI pkgsrc version well maintained by Thomas Klausner (wiz@) and up to date. .LE .GPE_MULB 17.5c .BL .LI Apart from that, no progress since last year. mandoc(1) version is outdated (1.12.3, released 2013, no reaction to the three newer versions of mandoc released after that). .LI Installing source manuals. .LE .MULN .PSPIC Images/NetBSD.eps .MULE .BL .LI Using mandoc(1) as the run-time manual formatter since February 7, 2012. .LI NetBSD-only apropos(1)/makemandb(8) featuring full-text search but no semantic search. .LE .TITLE "Status in DragonFly BSD" .GPE_MULB 17.5c .BL .LI No progress since last year. mandoc version in base is outdated (1.13.1, released in August 2014, no reaction to the two versions of mandoc released after that). .LI mandoc(1) is installed, but not used. .LI Semantic searching is not yet supported, not even as an option. .LE .MULN .PSPIC Images/DragonFly.eps .MULE .GPE_TIME 20 .GPE_NEXT illumos .TITLE "What happened in illumos?" .BL .LI Mandoc is contained in the base system .br .GPE_EM "and used by default for formatting manuals" .br since July 21, 2014 (Garrett D'Amore). .LI The first non-BSD system to accomplish this, and the third system grand total. .LI Have decided to gradually upgrade their man(7) pages to mdoc(7) format. .LI Using the same old version as NetBSD (1.12.3, released in 2013). .LI Still using their own apropos(1)/catman(8), no support for semantic searching. .LE .PSPIC Images/illumos.eps 4c .GPE_TIME 60 .GPE_NEXT "How many Linuxes use mandoc?" .TITLE "Status in Linux" .BL .LI Two Linux distributions have mandoc fully enabled by default: .LI Alpine Linux: mandoc(1) since June 12, 2011; .br man(1), apropos(1), makewhatis(8) since December 29, 2014 .LI Void Linux: mandoc(1) since September 23, 2014; .br man(1), apropos(1), makewhatis(8) since March 14, 2015 .LI Both using the latest stable portable mandoc (1.13.3) .LI Alpine Linux was the first non-BSD system ever to use the mandoc-based man(1), apropos(1), and makewhatis(8). .LI Apart from OpenBSD, i know of no other operating systems that rely more heavily on mandoc right now than these two. .LE .GPE_MULB 14c .BL .LI Definitely, these prove that fully switching a Linux distribution to use the complete mandoc suite is feasible. .LI Arch Linux has an official port, Slackware and Crux unofficial ones, no major Linuxes have followed so far, even though mandoc is known to work on Debian and Ubuntu, Fedora and RHEL and CentOs, OpenSuSE and SLES. .LE .MULN .PSPIC Images/FlagstaffBluePenguin.eps .GPE_SM "Little Blue Penguin \(co 2009 .GPE_SM "Flagstaffotos @wikimedia (CC)" .MULE .GPE_TIME 50 .GPE_NEXT "Any other systems?" .TITLE "Status in other operating systems" .BVL 1c .LI "Minix 3" Source code in the base repo since June 26, 2010 (Ben Gras). .br Completely apathetic, still using a version that is more than five years old. .LE .GPE_MULB 16c .nr Lsp_save \n[Lsp] .nr Lsp 1v .BVL 1c .LI "Mac OS X" 1.13.2 available on Homebrew .br 1.13.1 available on MacPorts .LI "Microsoft Windows" 1.13.1 package available built with MinGW .br 1.12.2 only an outdated package for Cygwin .LI "IBM AIX" Outdated unofficial 1.12.0 port .LE .nr Lsp \n[Lsp_save] .MULN .PSPIC Images/MacOSX.eps .MULE .SUBTITLE "Periodically updated information:" .ce http://mdocml.bsd.lv/ports.html .GPE_TIME 50 .GPE_NEXT "Let's summarize the status..." .TITLE "Status summary" .sp -1.5v .BVL 1c .LI "Fully integrated (mandoc, man, apropos, makewhatis)" OpenBSD, Alpine Linux, Void Linux .LI "Almost fully integrated (including apropos but without man)" FreeBSD-current .LI "Default formatter (but less powerful implementations of man and apropos)" NetBSD, illumos .LI "In the base system (but not used by default)" FreeBSD 10, DragonFly BSD, Minix 3 .LI "Official packages exist" FreeBSD 9, Arch Linux, pkgsrc .LI "Unofficial packages of useful versions exist" Slackware, Crux Linux, Mac OS X, MinGW .LI "Outdated packages only, probably easy to update" Debian, SUSE, Redhat and derivatives; IBM AIX, Cygwin .LE .sp -0.5v .PSPIC Images/GBaranskiOttawaPanorama.eps .GPE_SM "Ottawa (Ontario) seen from Gatineau (Quebec)\ \(co 2009 G. Baranski @wikimedia (CC)" .GPE_TIME 70 .GPE_NEXT "Which goals were reached?" .TITLE "Which goals were reached?" .SUBTITLE "Goals presented during BSDCan 2011" .BL .LI Install manual sources, not preformatted manuals. .COLOR darkred DONE June 23, 2011 .COLOR P .LI Implement -mdoc -Tman. .COLOR darkred DONE November 19, 2012 .COLOR P .LI Rewrite apropos(1) and makewhatis(8) to use mandoc. .COLOR darkred DONE April 14, 2014 .COLOR P .LE .GPE_MULB 13c .BL .LI Replace man.cgi on the OpenBSD website. .br .GPE_EM "DONE July 12, 2014" .LE .SUBTITLE "Goals presented in 2014" .BL .LI Integrate preconv(1) into mandoc(1) .br for better UTF-8 handling. .br .GPE_EM "DONE October 30, 2014" .LI Switch the default output mode .br from \-Tascii to \-Tlocale . .br .GPE_EM "DONE December 2, 2014" .LI Replace man(1) in OpenBSD. .br .GPE_EM "DONE December 14, 2014" .LE .MULN .PSPIC Images/WladyslawOttawaLibraryOfParliament.eps .GPE_SM "Library of Parliament, Ottawa" .GPE_SM "\(co 2009 Wladyslaw@wikimedia (CC)" .MULE .GPE_TIME 30 .GPE_NEXT "What shall we do in the future?" .TITLE "Possible future directions" .sp -1.5v .SUBTITLE "Work in progress" .BL .LI Improve pod2mdoc(1) and use it for LibreSSL (first mentioned: BSDCan 2011) .LI Unify parsers aiming for better roff(7) support (first mentioned: BSDCan 2014) .LI Automatically detect unsupported source code (-Wunsupp) (NEW) .LI Delete most ln(1) links to manual pages (NEW) .LI texi2mdoc(1) to convert texinfo(1) documentation to mdoc(7) (NEW) .LI Help with man(7) to mdoc(7) conversions (first mentioned: BSDCan 2011); docbook2mdoc(1) (first mentioned: BSDCan 2014) .LE .GPE_MULB 12c .SUBTITLE "Not yet started" .BL .LI Support automatic semantic enrichment .br of Perl manuals with pod2mdoc(1). .br (first mentioned: EuroBSDCon 2014) .LI Use less(1) tag functionality .br for repositioning text on the screen. .br (NEW idea by Kristaps Dzonsons) .LE .MULN .PSPIC Images/WladyslawGatineauMuseumOfHistory.eps .GPE_SM "Canadian Museum of History, Gatineau" .GPE_SM "\(co 2009 Wladyslaw@wikimedia (CC)" .MULE .GPE_TIME 80 .GPE_SECTION THANKS .GPE_NEXT "Who made this happen?" .TITLE Thanks! .sp -1v This list only mentions contributions since BSDCan 2014. .br For earlier contributions, see last year's talk. .BVL 1c .LI "Kristaps Dzonsons (bsd.lv)" for rewriting the eqn(7) parser, implementing HTML5 and MathML output, and various other code contributions .LI "Jonathan Gray (OpenBSD)" for extensive testing with afl resulting in many bug reports .LI "Baptiste Daroussin (FreeBSD)" for extensive FreeBSD system integration work and for source code patches, bug reports, and useful discussions .LI "Christian Weisgerber (OpenBSD)" for removing USE_GROFF from many ports, analyzing the remaining ones, many bug reports and useful discussions .LI "Thomas Klausner (NetBSD)" for excellent pkgsrc maintenance, reliable release testing, and several bug reports and useful discussions .LI "Natanael Copa (Alpine Linux)" for Alpine Linux integration and maintenance .LI "Paul Onyschuk (Alpine Linux)" for suggesting to include an implementation of man(1) into the mandoc toolkit .LE .GPE_TIME 40 .GPE_NEXT "Who contributed?" .SUBTITLE "Thanks for source code patches" Anthony Bentley, Daniel Dickman, Doug Hogan, Jason McIntyre, Ted Unangst, Theo de Raadt (OpenBSD), Martin Natano .GPE_MULB 12c 1v .P Thanks for bug reports, release testing, .br and/or useful suggestions and discussions: .P Antoine Jacoutot, Giovanni Becchis, J\('er\('emie Courr\(`eges-Anglas, Juan Francisco Cantero Hurtado, Marc Espie, Matthew Dempsky, Pascal Stumpf, Stuart Henderson, Todd Miller (OpenBSD), .br Abhinav Upadhyay, Havard Eidnes, Joerg Sonnenberger, Matthias Scheler (NetBSD), Pedro Giffuni, Ulrich Sp\(:orlein (FreeBSD), Garrett D'Amore (illumos), Jonathan Perkin (SmartOS), Daniel Levai (Slackware), Svyatoslav Mishyn (Crux Linux), Carsten Kunze (Heirloom troff), Alexis Hildebrandt (Homebrew), Alessandro de Laurenzis, Andreas V\(:ogele, Jan Stary, Justin Haynes, Marcus Merighi, Patrick Keshishian, S\('ebastien Marie, Steffen Nurpmeso, Theo B\(:uhler .MULN .PSPIC Images/CatherineBulinskiOttawaPeaceTower.eps .GPE_SM "Tulip Festival, Peace Tower, Ottawa" .GPE_SM "\(co 2007 Catherine Bulinski @flickr (CC)" .MULE .GPE_TIME 10 .GPE_NEXT "Where did the images come from?" .SUBTITLE "Thanks for sharing your pictures!" .S -9 .DS Cynthia Livingston's off-track thoroughbred "Bedifferent"\ (private communication, used with permission) https://www.flickr.com/photos/reiver/3821502286/\ Mac Armstrong: Moorside cottage, Mackenzie King Estate,\ Gatineau Park, Quebec (by-sa) https://www.flickr.com/photos/14020964@N02/7373733864/\ Lezumbalaberenjena: Black Lake, Gatineau Park, Quebec (by-nc-nd) https://www.flickr.com/photos/14020964@N02/14719822932/\ Lezumbalaberenjena: Paroisse Sainte C\('ecile de Masham, Quebec (by-nc-nd) https://www.flickr.com/photos/dougtone/5806473660/\ Doug Kerr: Bonnechere Museum, Eganville, Renfrew County, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Opeongo_Road_farm.jpg\ P199: Opeongo Road, Renfrew County, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Wilno_Ontario.JPG\ P199: Wilno, Renfrew County, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Madawaska_River_Whitney.JPG\ P199: Madawaska River at Whitney, Ontario (pd) https://www.flickr.com/photos/usfwsmidwest/4514433523/\ Gary J. Wege: Common Loons (by) http://commons.wikimedia.org/wiki/File:Algonquin_Cache_Lake_Lookout.JPG\ Ptrbnsn: Cache Lake, Algonquin Park, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Tom_Thomson,1917,_April_in_Algonquin_Park,21_x_26,5_cm,_Tom_Thomson_Memorial_Art_Gallery.jpg Tom Thomson: April in Algonquin Park (copyright expired) https://www.flickr.com/photos/ryan_tir/6232749531/\ Ryan Tir: Maggie Lake, Algonquin Park, Ontario (by) https://www.flickr.com/photos/7119320@N05/9439437967/\ Sean Marshall: Archer Daniels Midland, Simcoe County, Ontario (by-nc) http://commons.wikimedia.org/wiki/File:Aerial_-_Wasaga_Beach,_Ontario_from_SW_01_-_white_balanced_%289656223451%29.jpg\ Joe Mabel: Wasaga Beach (by-sa) http://commons.wikimedia.org/wiki/File:Rabbit_american_fuzzy_lop_buck_white.jpg Lithonius: American Fuzzy Lop rabbit (pd) http://commons.wikimedia.org/wiki/File:Spiritcatcher_barrie_wide.jpg\ Tudor Costache: Spiritcatcher by Ron Baird, Barrie, Ontario (by) http://commons.wikimedia.org/wiki/File:Barrie_Waterfront.jpg\ Jliu: Barrie Waterfront, Lake Simcoe, Ontario (by-sa) https://www.flickr.com/photos/dexxus/2497070861/\ Paul Bica: Toronto Sunset (by) https://www.flickr.com/photos/dexxus/5003010775/\ Paul Bica: Humber Bridge, Toronto, Ontario (by) https://www.flickr.com/photos/dexxus/2967568397/\ Paul Bica: Bloor Viaduct, Don Valley, Toronto, Ontario (by) https://www.flickr.com/photos/thru_the_night/3659236370/\ Kiril Strax: Tommy Thompson Park, Toronto, Ontario (by-nc-sa) http://commons.wikimedia.org/wiki/File:Kingstonhall.JPG\ Canteaus: Theological Hall, Kingston, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Kingston_on_city_hall.jpg\ Mkooiman: Kingston City Hall, Ontario (by-sa) http://commons.wikimedia.org/wiki/File:Little_Penguin_Feb09.jpg\ Fir0002/Flagstaffotos: Little Penguin (by-nc) http://commons.wikimedia.org/wiki/File:Canada_Ottawa_Panorama.jpg\ G. Baranski: Ottawa Panorama (by-sa) http://commons.wikimedia.org/wiki/File:Ottawa_-_ON_-_Library_of_Parliament.jpg\ Wladyslaw: Library of Parliament, Ottawa (by-sa) http://commons.wikimedia.org/wiki/File:Gatineau_-_QC_-_Museum_of_Civilisation.jpg\ Wladyslaw: Canadian Museum of History, Gatineau (by-sa) https://www.flickr.com/photos/kasiaflickr/489246505/\ Catherine Bulinski: Tulip Festival, Peace Tower, Ottawa (by-nd) http://commons.wikimedia.org/wiki/File:Algonquin_Sunset_Panorama.jpg\ Raul Heinrich: North Tea Lake, Algonquin Park, Ontario (by-sa) .DE .S P .PSPIC Images/RaulHeinrichAlgonquinTeaLake.eps .GPE_SM "North Tea Lake, Algonquin Provincial Park\ \(co 2008 Raul Heinrich @wikimedia (CC)" .GPE_TIME 10 .ds gpe_next What would you like to ask?