--- /dev/null
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
--- /dev/null
+#!/usr/bin/perl
+
+# Copyright (C) 2014 Steven McDonald <steven@steven-mcdonald.id.au>
+#
+# This program is free software. It comes without any warranty, to the
+# extent permitted by applicable law. You can redistribute it and/or
+# modify it under the terms of the Do What The Fuck You Want To Public
+# License, Version 2, as published by Sam Hocevar. See the COPYING file
+# or visit http://www.wtfpl.net/ for more details.
+
+use strict;
+use warnings;
+
+sub print_tree;
+
+my $tree = {};
+my %name_to_node = (root => $tree);
+my $show_detached = 0;
+
+for (@ARGV) {
+ $show_detached = 1 if /^(-d|--show-detached)$/;
+}
+
+while (<STDIN>) {
+ if (/^(\w+) at (\w+):?\s(.*?["(<])?([^"()<>\n]+)?/) {
+ my $node_prettyname;
+ if ($4) {
+ $node_prettyname = "$1 ($4)";
+ } else {
+ $node_prettyname = $1;
+ }
+
+ my $new_node = {};
+ $name_to_node{$2}{$node_prettyname} = $new_node;
+ $name_to_node{$1} = $new_node;
+ } elsif (/^(\w+) detached$/ and my $node = $name_to_node{$1}) {
+ $node->{_is_detached} = 1;
+ }
+}
+
+print "root\n";
+print_tree $tree;
+exit;
+
+sub print_tree {
+ my $tree = shift;
+ my $prev_indent = shift || "";
+ my $indent = $prev_indent . " |";
+ my $count = 0;
+ my @keys = keys $tree;
+
+ for (sort @keys) {
+ my $name = $_;
+ if (delete $tree->{$_}->{_is_detached}) {
+ next unless $show_detached;
+ $name = "$name [DETACHED]";
+ }
+
+ print $indent . "-$name\n";
+ $indent = $prev_indent . " " if $count eq $#keys;
+ print_tree $tree->{$_}, $indent;
+ $count++;
+ }
+}
--- /dev/null
+.\" Copyright (C) 2014 Steven McDonald <steven@steven-mcdonald.id.au>
+.\"
+.\" This work is free. You can redistribute it and/or modify it under
+.\" the terms of the Do What The Fuck You Want To Public License,
+.\" Version 2, as published by Sam Hocevar. See the COPYING file or
+.\" visit http://www.wtfpl.net/ for more details.
+.\"
+.Dd $Mdocdate$
+.Dt DEVTREE 1
+.Os
+.Sh NAME
+.Nm devtree
+.Nd display a tree representing system hardware
+.Sh SYNOPSIS
+.Nm devtree
+.Op Fl d
+.Sh DESCRIPTION
+The
+.Nm
+utility accepts output from
+.Xr dmesg 8
+on standard input, and produces a human-friendly ASCII tree
+representing the currently attached system devices on standard output.
+.Pp
+If the
+.Sy -d
+option is provided, it will also include devices which have
+been detached from the system, appending
+.Em [DETACHED]
+to any such entries. All other options are ignored.
+.Sh EXAMPLES
+Display a tree of all attached devices on the current system:
+.Pp
+.Dl $ dmesg | devtree
+.Sh SEE ALSO
+.Xr dmesg 8