Blame


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