Print this page
9718 update mandoc to 1.14.4

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/mandocdb.c
          +++ new/usr/src/cmd/mandoc/mandocdb.c
   1      -/*      $Id: mandocdb.c,v 1.253 2017/07/28 14:48:25 schwarze Exp $ */
        1 +/*      $Id: mandocdb.c,v 1.258 2018/02/23 18:25:57 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
   4    4   * Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
   5    5   * Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
   6    6   *
   7    7   * Permission to use, copy, modify, and distribute this software for any
   8    8   * purpose with or without fee is hereby granted, provided that the above
   9    9   * copyright notice and this permission notice appear in all copies.
  10   10   *
  11   11   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
  12   12   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13   13   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
  14   14   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15   15   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16   16   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17   17   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18   18   */
  19   19  #include "config.h"
  20   20  
  21   21  #include <sys/types.h>
       22 +#include <sys/mman.h>
  22   23  #include <sys/stat.h>
  23      -#include <sys/wait.h>
  24   24  
  25   25  #include <assert.h>
  26   26  #include <ctype.h>
  27   27  #if HAVE_ERR
  28   28  #include <err.h>
  29   29  #endif
  30   30  #include <errno.h>
  31   31  #include <fcntl.h>
  32   32  #if HAVE_FTS
  33   33  #include <fts.h>
↓ open down ↓ 98 lines elided ↑ open up ↑
 132  132  static  void     mlinks_undupe(struct mpage *);
 133  133  static  void     mpages_free(void);
 134  134  static  void     mpages_merge(struct dba *, struct mparse *);
 135  135  static  void     parse_cat(struct mpage *, int);
 136  136  static  void     parse_man(struct mpage *, const struct roff_meta *,
 137  137                          const struct roff_node *);
 138  138  static  void     parse_mdoc(struct mpage *, const struct roff_meta *,
 139  139                          const struct roff_node *);
 140  140  static  int      parse_mdoc_head(struct mpage *, const struct roff_meta *,
 141  141                          const struct roff_node *);
      142 +static  int      parse_mdoc_Fa(struct mpage *, const struct roff_meta *,
      143 +                        const struct roff_node *);
 142  144  static  int      parse_mdoc_Fd(struct mpage *, const struct roff_meta *,
 143  145                          const struct roff_node *);
 144  146  static  void     parse_mdoc_fname(struct mpage *, const struct roff_node *);
 145  147  static  int      parse_mdoc_Fn(struct mpage *, const struct roff_meta *,
 146  148                          const struct roff_node *);
 147  149  static  int      parse_mdoc_Fo(struct mpage *, const struct roff_meta *,
 148  150                          const struct roff_node *);
 149  151  static  int      parse_mdoc_Nd(struct mpage *, const struct roff_meta *,
 150  152                          const struct roff_node *);
 151  153  static  int      parse_mdoc_Nm(struct mpage *, const struct roff_meta *,
↓ open down ↓ 48 lines elided ↑ open up ↑
 200  202          { NULL, 0, 0 },  /* Ad */
 201  203          { NULL, TYPE_An, 0 },  /* An */
 202  204          { NULL, 0, 0 },  /* Ap */
 203  205          { NULL, TYPE_Ar, 0 },  /* Ar */
 204  206          { NULL, TYPE_Cd, 0 },  /* Cd */
 205  207          { NULL, TYPE_Cm, 0 },  /* Cm */
 206  208          { NULL, TYPE_Dv, 0 },  /* Dv */
 207  209          { NULL, TYPE_Er, 0 },  /* Er */
 208  210          { NULL, TYPE_Ev, 0 },  /* Ev */
 209  211          { NULL, 0, 0 },  /* Ex */
 210      -        { NULL, TYPE_Fa, 0 },  /* Fa */
      212 +        { parse_mdoc_Fa, 0, 0 },  /* Fa */
 211  213          { parse_mdoc_Fd, 0, 0 },  /* Fd */
 212  214          { NULL, TYPE_Fl, 0 },  /* Fl */
 213  215          { parse_mdoc_Fn, 0, 0 },  /* Fn */
 214      -        { NULL, TYPE_Ft, 0 },  /* Ft */
      216 +        { NULL, TYPE_Ft | TYPE_Vt, 0 },  /* Ft */
 215  217          { NULL, TYPE_Ic, 0 },  /* Ic */
 216  218          { NULL, TYPE_In, 0 },  /* In */
 217  219          { NULL, TYPE_Li, 0 },  /* Li */
 218  220          { parse_mdoc_Nd, 0, 0 },  /* Nd */
 219  221          { parse_mdoc_Nm, 0, 0 },  /* Nm */
 220  222          { NULL, 0, 0 },  /* Op */
 221  223          { NULL, 0, 0 },  /* Ot */
 222  224          { NULL, TYPE_Pa, NODE_NOSRC },  /* Pa */
 223  225          { NULL, 0, 0 },  /* Rv */
 224  226          { NULL, TYPE_St, 0 },  /* St */
↓ open down ↓ 87 lines elided ↑ open up ↑
 312  314  mandocdb(int argc, char *argv[])
 313  315  {
 314  316          struct manconf    conf;
 315  317          struct mparse    *mp;
 316  318          struct dba       *dba;
 317  319          const char       *path_arg, *progname;
 318  320          size_t            j, sz;
 319  321          int               ch, i;
 320  322  
 321  323  #if HAVE_PLEDGE
 322      -        if (pledge("stdio rpath wpath cpath fattr flock proc exec", NULL) == -1) {
      324 +        if (pledge("stdio rpath wpath cpath", NULL) == -1) {
 323  325                  warn("pledge");
 324  326                  return (int)MANDOCLEVEL_SYSERR;
 325  327          }
 326  328  #endif
 327  329  
 328  330  #if HAVE_SANDBOX_INIT
 329  331          if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) {
 330  332                  warnx("sandbox_init");
 331  333                  return (int)MANDOCLEVEL_SYSERR;
 332  334          }
↓ open down ↓ 100 lines elided ↑ open up ↑
 433  435                   */
 434  436                  if (OP_TEST != op && 0 == set_basedir(path_arg, 1))
 435  437                          goto out;
 436  438  
 437  439                  dba = nodb ? dba_new(128) : dba_read(MANDOC_DB);
 438  440                  if (dba != NULL) {
 439  441                          /*
 440  442                           * The existing database is usable.  Process
 441  443                           * all files specified on the command-line.
 442  444                           */
 443      -#if HAVE_PLEDGE
 444      -                        if (!nodb) {
 445      -                                if (pledge("stdio rpath wpath cpath fattr flock", NULL) == -1) {
 446      -                                        warn("pledge");
 447      -                                        exitcode = (int)MANDOCLEVEL_SYSERR;
 448      -                                        goto out;
 449      -                                }
 450      -                        }
 451      -#endif
 452  445                          use_all = 1;
 453  446                          for (i = 0; i < argc; i++)
 454  447                                  filescan(argv[i]);
 455  448                          if (nodb == 0)
 456  449                                  dbprune(dba);
 457  450                  } else {
 458  451                          /* Database missing or corrupt. */
 459  452                          if (op != OP_UPDATE || errno != ENOENT)
 460  453                                  say(MANDOC_DB, "%s: Automatically recreating"
 461  454                                      " from scratch", strerror(errno));
↓ open down ↓ 913 lines elided ↑ open up ↑
1375 1368          while (NULL != (line = memchr(p, '\b', plen))) {
1376 1369                  len = line - p;
1377 1370                  if (0 == len) {
1378 1371                          memmove(line, line + 1, plen--);
1379 1372                          continue;
1380 1373                  }
1381 1374                  memmove(line - 1, line + 1, plen - len);
1382 1375                  plen -= 2;
1383 1376          }
1384 1377  
1385      -        mpage->desc = mandoc_strdup(p);
     1378 +        /*
     1379 +         * Cut off excessive one-line descriptions.
     1380 +         * Bad pages are not worth better heuristics.
     1381 +         */
     1382 +
     1383 +        mpage->desc = mandoc_strndup(p, 150);
1386 1384          fclose(stream);
1387 1385          free(title);
1388 1386  }
1389 1387  
1390 1388  /*
1391 1389   * Put a type/word pair into the word database for this particular file.
1392 1390   */
1393 1391  static void
1394 1392  putkey(const struct mpage *mpage, char *value, uint64_t type)
1395 1393  {
↓ open down ↓ 123 lines elided ↑ open up ↑
1519 1517                          else if (0 == strncmp(start, "\\-", 2))
1520 1518                                  start += 2;
1521 1519                          else if (0 == strncmp(start, "\\(en", 4))
1522 1520                                  start += 4;
1523 1521                          else if (0 == strncmp(start, "\\(em", 4))
1524 1522                                  start += 4;
1525 1523  
1526 1524                          while (' ' == *start)
1527 1525                                  start++;
1528 1526  
1529      -                        mpage->desc = mandoc_strdup(start);
     1527 +                        /*
     1528 +                         * Cut off excessive one-line descriptions.
     1529 +                         * Bad pages are not worth better heuristics.
     1530 +                         */
     1531 +
     1532 +                        mpage->desc = mandoc_strndup(start, 150);
1530 1533                          free(title);
1531 1534                          return;
1532 1535                  }
1533 1536          }
1534 1537  
1535 1538          for (n = n->child; n; n = n->next) {
1536 1539                  if (NULL != mpage->desc)
1537 1540                          break;
1538 1541                  parse_man(mpage, meta, n);
1539 1542          }
↓ open down ↓ 25 lines elided ↑ open up ↑
1565 1568                          break;
1566 1569                  default:
1567 1570                          continue;
1568 1571                  }
1569 1572                  if (NULL != n->child)
1570 1573                          parse_mdoc(mpage, meta, n);
1571 1574          }
1572 1575  }
1573 1576  
1574 1577  static int
     1578 +parse_mdoc_Fa(struct mpage *mpage, const struct roff_meta *meta,
     1579 +        const struct roff_node *n)
     1580 +{
     1581 +        uint64_t mask;
     1582 +
     1583 +        mask = TYPE_Fa;
     1584 +        if (n->sec == SEC_SYNOPSIS)
     1585 +                mask |= TYPE_Vt;
     1586 +
     1587 +        putmdockey(mpage, n->child, mask, 0);
     1588 +        return 0;
     1589 +}
     1590 +
     1591 +static int
1575 1592  parse_mdoc_Fd(struct mpage *mpage, const struct roff_meta *meta,
1576 1593          const struct roff_node *n)
1577 1594  {
1578 1595          char            *start, *end;
1579 1596          size_t           sz;
1580 1597  
1581 1598          if (SEC_SYNOPSIS != n->sec ||
1582 1599              NULL == (n = n->child) ||
1583 1600              n->type != ROFFT_TEXT)
1584 1601                  return 0;
↓ open down ↓ 48 lines elided ↑ open up ↑
1633 1650  
1634 1651          putkeys(mpage, cp, sz, TYPE_Fn);
1635 1652          if (n->sec == SEC_SYNOPSIS)
1636 1653                  putkeys(mpage, cp, sz, NAME_SYN);
1637 1654  }
1638 1655  
1639 1656  static int
1640 1657  parse_mdoc_Fn(struct mpage *mpage, const struct roff_meta *meta,
1641 1658          const struct roff_node *n)
1642 1659  {
     1660 +        uint64_t mask;
1643 1661  
1644 1662          if (n->child == NULL)
1645 1663                  return 0;
1646 1664  
1647 1665          parse_mdoc_fname(mpage, n->child);
1648 1666  
1649      -        for (n = n->child->next; n != NULL; n = n->next)
1650      -                if (n->type == ROFFT_TEXT)
1651      -                        putkey(mpage, n->string, TYPE_Fa);
     1667 +        n = n->child->next;
     1668 +        if (n != NULL && n->type == ROFFT_TEXT) {
     1669 +                mask = TYPE_Fa;
     1670 +                if (n->sec == SEC_SYNOPSIS)
     1671 +                        mask |= TYPE_Vt;
     1672 +                putmdockey(mpage, n, mask, 0);
     1673 +        }
1652 1674  
1653 1675          return 0;
1654 1676  }
1655 1677  
1656 1678  static int
1657 1679  parse_mdoc_Fo(struct mpage *mpage, const struct roff_meta *meta,
1658 1680          const struct roff_node *n)
1659 1681  {
1660 1682  
1661 1683          if (n->type != ROFFT_HEAD)
↓ open down ↓ 450 lines elided ↑ open up ↑
2112 2134                  }
2113 2135          }
2114 2136  }
2115 2137  
2116 2138  /*
2117 2139   * Write the database from memory to disk.
2118 2140   */
2119 2141  static void
2120 2142  dbwrite(struct dba *dba)
2121 2143  {
2122      -        char             tfn[32];
2123      -        int              status;
2124      -        pid_t            child;
     2144 +        struct stat      sb1, sb2;
     2145 +        char             tfn[33], *cp1, *cp2;
     2146 +        off_t            i;
     2147 +        int              fd1, fd2;
2125 2148  
2126 2149          /*
2127 2150           * Do not write empty databases, and delete existing ones
2128 2151           * when makewhatis -u causes them to become empty.
2129 2152           */
2130 2153  
2131 2154          dba_array_start(dba->pages);
2132 2155          if (dba_array_next(dba->pages) == NULL) {
2133 2156                  if (unlink(MANDOC_DB) == -1 && errno != ENOENT)
2134 2157                          say(MANDOC_DB, "&unlink");
↓ open down ↓ 18 lines elided ↑ open up ↑
2153 2176           * We lack write permission and cannot replace the database
2154 2177           * file, but let's at least check whether the data changed.
2155 2178           */
2156 2179  
2157 2180          (void)strlcpy(tfn, "/tmp/mandocdb.XXXXXXXX", sizeof(tfn));
2158 2181          if (mkdtemp(tfn) == NULL) {
2159 2182                  exitcode = (int)MANDOCLEVEL_SYSERR;
2160 2183                  say("", "&%s", tfn);
2161 2184                  return;
2162 2185          }
2163      -
     2186 +        cp1 = cp2 = MAP_FAILED;
     2187 +        fd1 = fd2 = -1;
2164 2188          (void)strlcat(tfn, "/" MANDOC_DB, sizeof(tfn));
2165 2189          if (dba_write(tfn, dba) == -1) {
2166      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2167 2190                  say(tfn, "&dba_write");
2168      -                goto out;
     2191 +                goto err;
2169 2192          }
2170      -
2171      -        switch (child = fork()) {
2172      -        case -1:
2173      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2174      -                say("", "&fork cmp");
2175      -                return;
2176      -        case 0:
2177      -                execlp("cmp", "cmp", "-s", tfn, MANDOC_DB, (char *)NULL);
2178      -                say("", "&exec cmp");
2179      -                exit(0);
2180      -        default:
2181      -                break;
     2193 +        if ((fd1 = open(MANDOC_DB, O_RDONLY, 0)) == -1) {
     2194 +                say(MANDOC_DB, "&open");
     2195 +                goto err;
2182 2196          }
2183      -        if (waitpid(child, &status, 0) == -1) {
2184      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2185      -                say("", "&wait cmp");
2186      -        } else if (WIFSIGNALED(status)) {
2187      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2188      -                say("", "cmp died from signal %d", WTERMSIG(status));
2189      -        } else if (WEXITSTATUS(status)) {
2190      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2191      -                say(MANDOC_DB,
2192      -                    "Data changed, but cannot replace database");
     2197 +        if ((fd2 = open(tfn, O_RDONLY, 0)) == -1) {
     2198 +                say(tfn, "&open");
     2199 +                goto err;
2193 2200          }
     2201 +        if (fstat(fd1, &sb1) == -1) {
     2202 +                say(MANDOC_DB, "&fstat");
     2203 +                goto err;
     2204 +        }
     2205 +        if (fstat(fd2, &sb2) == -1) {
     2206 +                say(tfn, "&fstat");
     2207 +                goto err;
     2208 +        }
     2209 +        if (sb1.st_size != sb2.st_size)
     2210 +                goto err;
     2211 +        if ((cp1 = mmap(NULL, sb1.st_size, PROT_READ, MAP_PRIVATE,
     2212 +            fd1, 0)) == MAP_FAILED) {
     2213 +                say(MANDOC_DB, "&mmap");
     2214 +                goto err;
     2215 +        }
     2216 +        if ((cp2 = mmap(NULL, sb2.st_size, PROT_READ, MAP_PRIVATE,
     2217 +            fd2, 0)) == MAP_FAILED) {
     2218 +                say(tfn, "&mmap");
     2219 +                goto err;
     2220 +        }
     2221 +        for (i = 0; i < sb1.st_size; i++)
     2222 +                if (cp1[i] != cp2[i])
     2223 +                        goto err;
     2224 +        goto out;
2194 2225  
     2226 +err:
     2227 +        exitcode = (int)MANDOCLEVEL_SYSERR;
     2228 +        say(MANDOC_DB, "Data changed, but cannot replace database");
     2229 +
2195 2230  out:
     2231 +        if (cp1 != MAP_FAILED)
     2232 +                munmap(cp1, sb1.st_size);
     2233 +        if (cp2 != MAP_FAILED)
     2234 +                munmap(cp2, sb2.st_size);
     2235 +        if (fd1 != -1)
     2236 +                close(fd1);
     2237 +        if (fd2 != -1)
     2238 +                close(fd2);
     2239 +        unlink(tfn);
2196 2240          *strrchr(tfn, '/') = '\0';
2197      -        switch (child = fork()) {
2198      -        case -1:
2199      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2200      -                say("", "&fork rm");
2201      -                return;
2202      -        case 0:
2203      -                execlp("rm", "rm", "-rf", tfn, (char *)NULL);
2204      -                say("", "&exec rm");
2205      -                exit((int)MANDOCLEVEL_SYSERR);
2206      -        default:
2207      -                break;
2208      -        }
2209      -        if (waitpid(child, &status, 0) == -1) {
2210      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2211      -                say("", "&wait rm");
2212      -        } else if (WIFSIGNALED(status) || WEXITSTATUS(status)) {
2213      -                exitcode = (int)MANDOCLEVEL_SYSERR;
2214      -                say("", "%s: Cannot remove temporary directory", tfn);
2215      -        }
     2241 +        rmdir(tfn);
2216 2242  }
2217 2243  
2218 2244  static int
2219 2245  set_basedir(const char *targetdir, int report_baddir)
2220 2246  {
2221 2247          static char      startdir[PATH_MAX];
2222 2248          static int       getcwd_status;  /* 1 = ok, 2 = failure */
2223 2249          static int       chdir_status;  /* 1 = changed directory */
2224 2250          char            *cp;
2225 2251  
↓ open down ↓ 113 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX