Blob


1 #!/usr/bin/env perl
3 use strict;
4 use warnings;
5 use v5.10;
7 use String::ShellQuote qw( shell_quote );
8 use Any::URI::Escape qw( uri_escape );
10 my $path = $ENV{'PATH_INFO'};
11 my $query = $ENV{'QUERY_STRING'};
12 my $script_path = $ENV{'SCRIPT_NAME'};
14 sub reply {
15 my ($code, $meta) = @_;
16 print "$code $meta\r\n";
17 if ($code != 20) {
18 exit(0);
19 }
20 }
22 sub banner {
23 say '# man';
24 say '';
25 }
27 sub do_search {
28 my ($query) = @_;
29 reply(20, 'text/gemini');
30 banner;
31 say "Search results for: $query";
33 my $some = 0;
34 open(my $h, "-|", ("apropos", "-w", $query));
35 foreach (<$h>) {
36 chomp;
37 s,^.*/,,;
38 my ($page, $section) = split /\./;
39 my $esc = uri_escape($page);
40 say "=> $script_path/$section/$esc $page($section)";
42 $some = 1;
43 }
44 close($h);
46 if (!$some) {
47 say "Nothing.";
48 }
49 }
51 sub man_cmd {
52 my ($a, $b) = @_;
53 if (!$b) {
54 return shell_quote($a);
55 }
56 return shell_quote($a) . " " . shell_quote($b);
57 }
59 sub view_man {
60 my $args = @_;
61 reply(20, 'text/plain');
62 say "% uname -psr";
63 say "OpenBSD 6.8 amd64";
64 say "% man ", join(' ', @_);
66 my $pid;
67 if (!defined($pid = fork())) {
68 die();
69 } elsif ($pid == 0) {
70 exec("man -Tutf8 -- " . man_cmd(@_) .
71 " | col -b | sed '\$d'");
72 }
73 waitpid($pid, 0);
74 }
76 my $home = !$path || $path eq '/';
78 if ($home && $query) {
79 do_search($query);
80 } elsif ($home) {
81 reply(20, 'text/gemini');
82 banner;
83 say "Welcome to the manual!";
84 say "";
85 say "This service allows you to lookup a manual page is several ways:";
86 say "* by name, appending /<name> to the current URL";
87 say "* by name and section, appending /<section>/<name> to the current URL";
88 say "* by searching it, appending ?<query> to the current URL";
89 say "";
90 say "=> $script_path/search Or just click here to search";
91 } elsif ($path =~ m[^/?search/?]) {
92 if (!$query) {
93 reply(10, 'manpage:');
94 }
95 do_search($query);
96 } elsif ($path =~ m{^/([1-9]p?)/([-\w:]+)/?$}) {
97 view_man($1, $2);
98 } elsif ($path =~ m[^/([\w:]+)/?$]) {
99 view_man($1);
100 } else {
101 reply(51, 'not found');