]> git.cameronkatri.com Git - mandoc.git/blobdiff - cgi.c
If no man.cgi `whatis' results are found, offer a quick link to the apropos
[mandoc.git] / cgi.c
diff --git a/cgi.c b/cgi.c
index 7585e5896a1426508b625ba0065548de97767dd2..755318b94d83c6c95b0ccc1fed18e93b8fcd54cc 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/*     $Id: cgi.c,v 1.12 2011/12/07 13:00:40 kristaps Exp $ */
+/*     $Id: cgi.c,v 1.19 2011/12/08 22:47:09 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -67,6 +67,7 @@ struct        req {
 
 static int              atou(const char *, unsigned *);
 static void             catman(const char *);
+static int              cmp(const void *, const void *);
 static void             format(const char *);
 static void             html_print(const char *);
 static void             html_putchar(char);
@@ -295,8 +296,8 @@ resp_begin_html(int code, const char *msg)
             " \"http://www.w3.org/TR/html4/strict.dtd\">"      "\n"
             "<HTML>"                                           "\n"
             " <HEAD>"                                          "\n"
-            "   <META HTTP-EQUIV=\"Content-Type\" "            "\n"
-            "         CONTENT=\"text/html; charset=utf-8\">"   "\n"
+            "  <META HTTP-EQUIV=\"Content-Type\" "             "\n"
+            "        CONTENT=\"text/html; charset=utf-8\">"    "\n"
             "  <LINK REL=\"stylesheet\" HREF=\"/man.cgi.css\"" "\n"
             "        TYPE=\"text/css\" media=\"all\">"         "\n"
             "  <TITLE>System Manpage Reference</TITLE>"        "\n"
@@ -323,30 +324,37 @@ resp_searchform(const struct req *req)
        for (i = 0; i < (int)req->fieldsz; i++)
                if (0 == strcmp(req->fields[i].key, "expr"))
                        expr = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "query"))
+                       expr = req->fields[i].val;
                else if (0 == strcmp(req->fields[i].key, "sec"))
                        sec = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "sektion"))
+                       sec = req->fields[i].val;
                else if (0 == strcmp(req->fields[i].key, "arch"))
                        arch = req->fields[i].val;
 
+       if (NULL != sec && 0 == strcmp(sec, "0"))
+               sec = NULL;
+
        puts("<!-- Begin search form. //-->");
        printf("<FORM ACTION=\"");
        html_print(progname);
        printf("/search.html\" METHOD=\"get\">\n");
-       puts("<FIELDSET>\n"
-            "<INPUT TYPE=\"submit\" NAME=\"op\" "
-             "VALUE=\"Whatis\"> or \n"
-            "<INPUT TYPE=\"submit\" NAME=\"op\" "
-             "VALUE=\"apropos\"> for manuals satisfying \n"
-            "<INPUT TYPE=\"text\" SIZE=\"40\" "
-             "NAME=\"expr\" VALUE=\"");
+       printf("<FIELDSET>\n"
+              "<LEGEND>Search Parameters</LEGEND>\n"
+              "<INPUT TYPE=\"submit\" NAME=\"op\" "
+               "VALUE=\"Whatis\"> or \n"
+              "<INPUT TYPE=\"submit\" NAME=\"op\" "
+               "VALUE=\"apropos\"> for manuals satisfying \n"
+              "<INPUT TYPE=\"text\" NAME=\"expr\" VALUE=\"");
        html_print(expr);
-       puts("\">, section "
-            "<INPUT TYPE=\"text\" "
-             "SIZE=\"4\" NAME=\"sec\" VALUE=\"");
+       printf("\">, section "
+              "<INPUT TYPE=\"text\" "
+               "SIZE=\"4\" NAME=\"sec\" VALUE=\"");
        html_print(sec);
-       puts("\">, arch "
-            "<INPUT TYPE=\"text\" "
-             "SIZE=\"8\" NAME=\"arch\" VALUE=\"");
+       printf("\">, arch "
+              "<INPUT TYPE=\"text\" "
+               "SIZE=\"8\" NAME=\"arch\" VALUE=\"");
        html_print(arch);
        puts("\">.\n"
             "<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n"
@@ -416,7 +424,12 @@ resp_baddb(void)
 static void
 resp_search(struct res *r, size_t sz, void *arg)
 {
-       int              i;
+       int              i, whatis;
+       const char      *ep, *sec, *arch;
+       const struct req *req;
+
+       whatis = 1;
+       ep = sec = arch = NULL;
 
        if (1 == sz) {
                /*
@@ -431,14 +444,55 @@ resp_search(struct res *r, size_t sz, void *arg)
                return;
        }
 
+       req = (const struct req *)arg;
+
+       for (i = 0; i < (int)req->fieldsz; i++)
+               if (0 == strcmp(req->fields[i].key, "expr"))
+                       ep = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "query"))
+                       ep = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "sec"))
+                       sec = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "sektion"))
+                       sec = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "arch"))
+                       arch = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "apropos"))
+                       whatis = 0 == strcmp
+                               (req->fields[i].val, "0");
+               else if (0 == strcmp(req->fields[i].key, "op"))
+                       whatis = 0 == strcasecmp
+                               (req->fields[i].val, "whatis");
+
+       qsort(r, sz, sizeof(struct res), cmp);
+
        resp_begin_html(200, NULL);
-       resp_searchform((const struct req *)arg);
+       resp_searchform(req);
+
+       if (0 == sz) {
+               puts("<P>\n"
+                    "No results found.");
+               if (whatis) {
+                       printf("(Try <A HREF=\"");
+                       html_print(progname);
+                       printf("/search.html?op=apropos&amp;expr=");
+                       html_print(ep ? ep : "");
+                       printf("&amp;sec=");
+                       html_print(sec ? sec : "");
+                       printf("&amp;arch=");
+                       html_print(arch ? arch : "");
+                       puts("\">apropos</A>?)");
+               }
+               puts("</P>");
+               resp_end_html();
+               return;
+       }
 
-       if (0 == sz)
-               puts("<P>No results found.</P>");
+       puts("<P></P>\n"
+            "<TABLE>");
 
        for (i = 0; i < (int)sz; i++) {
-               printf("<P><A HREF=\"");
+               printf("<TR><TD CLASS=\"title\"><A HREF=\"");
                html_print(progname);
                printf("/show/%u/%u.html\">", r[i].volume, r[i].rec);
                html_print(r[i].title);
@@ -448,11 +502,13 @@ resp_search(struct res *r, size_t sz, void *arg)
                        putchar('/');
                        html_print(r[i].arch);
                }
-               printf(")</A> ");
+               printf(")</A></TD><TD CLASS=\"desc\">");
                html_print(r[i].desc);
-               puts("</P>");
+               puts("</TD></TR>");
        }
 
+       puts("</TABLE>");
+
        resp_end_html();
 }
 
@@ -712,7 +768,7 @@ pg_show(const struct manpaths *ps, const struct req *req, char *path)
        else if (NULL == memchr(fn, '\0', val.size - (fn - cp)))
                resp_baddb();
        else {
-               strlcpy(file, ps->paths[vol], MAXPATHLEN);
+               strlcpy(file, cache, MAXPATHLEN);
                strlcat(file, "/", MAXPATHLEN);
                strlcat(file, fn, MAXPATHLEN);
                if (0 == strcmp(cp, "cat"))
@@ -738,21 +794,31 @@ pg_search(const struct manpaths *ps, const struct req *req, char *path)
        cp = NULL;
        ep = NULL;
        sz = 0;
-       whatis = 0;
+       whatis = 1;
 
        memset(&opt, 0, sizeof(struct opts));
 
        for (sz = i = 0; i < (int)req->fieldsz; i++)
                if (0 == strcmp(req->fields[i].key, "expr"))
                        ep = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "query"))
+                       ep = req->fields[i].val;
                else if (0 == strcmp(req->fields[i].key, "sec"))
                        opt.cat = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "sektion"))
+                       opt.cat = req->fields[i].val;
                else if (0 == strcmp(req->fields[i].key, "arch"))
                        opt.arch = req->fields[i].val;
+               else if (0 == strcmp(req->fields[i].key, "apropos"))
+                       whatis = 0 == strcmp
+                               (req->fields[i].val, "0");
                else if (0 == strcmp(req->fields[i].key, "op"))
                        whatis = 0 == strcasecmp
                                (req->fields[i].val, "whatis");
 
+       if (NULL != opt.cat && 0 == strcmp(opt.cat, "0"))
+               opt.cat = NULL;
+
        /*
         * Poor man's tokenisation.
         * Just break apart by spaces.
@@ -893,3 +959,12 @@ main(void)
 
        return(EXIT_SUCCESS);
 }
+
+static int
+cmp(const void *p1, const void *p2)
+{
+
+       return(strcasecmp(((const struct res *)p1)->title,
+                               ((const struct res *)p2)->title));
+}
+