Print this page
9718 update mandoc to 1.14.4

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/main.c
          +++ new/usr/src/cmd/mandoc/main.c
   1      -/*      $Id: main.c,v 1.301 2017/07/26 10:21:55 schwarze Exp $ */
        1 +/*      $Id: main.c,v 1.306 2018/05/14 14:10:23 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2010-2012, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
        4 + * Copyright (c) 2010-2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
   5    5   * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.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/ioctl.h>
  22   23  #include <sys/param.h>  /* MACHINE */
       24 +#include <sys/termios.h>
  23   25  #include <sys/wait.h>
  24   26  
  25   27  #include <assert.h>
  26   28  #include <ctype.h>
  27   29  #if HAVE_ERR
  28   30  #include <err.h>
  29   31  #endif
  30   32  #include <errno.h>
  31   33  #include <fcntl.h>
  32   34  #include <glob.h>
↓ open down ↓ 80 lines elided ↑ open up ↑
 113  115  static  enum mandoclevel  rc;
 114  116  static  FILE             *mmsg_stream;
 115  117  
 116  118  
 117  119  int
 118  120  main(int argc, char *argv[])
 119  121  {
 120  122          struct manconf   conf;
 121  123          struct mansearch search;
 122  124          struct curparse  curp;
      125 +        struct winsize   ws;
 123  126          struct tag_files *tag_files;
 124  127          struct manpage  *res, *resp;
 125  128          const char      *progname, *sec, *thisarg;
 126  129          char            *conf_file, *defpaths, *auxpaths;
 127  130          char            *oarg;
 128  131          unsigned char   *uc;
 129  132          size_t           i, sz;
 130  133          int              prio, best_prio;
 131  134          enum outmode     outmode;
 132      -        int              fd;
      135 +        int              fd, startdir;
 133  136          int              show_usage;
 134  137          int              options;
 135  138          int              use_pager;
 136  139          int              status, signum;
 137  140          int              c;
 138  141          pid_t            pager_pid, tc_pgid, man_pgid, pid;
 139  142  
 140  143  #if HAVE_PROGNAME
 141  144          progname = getprogname();
 142  145  #else
↓ open down ↓ 166 lines elided ↑ open up ↑
 309  312                                  return (int)MANDOCLEVEL_BADARG;
 310  313                          }
 311  314                  }
 312  315          }
 313  316  
 314  317          if (outmode == OUTMODE_FLN ||
 315  318              outmode == OUTMODE_LST ||
 316  319              !isatty(STDOUT_FILENO))
 317  320                  use_pager = 0;
 318  321  
      322 +        if (use_pager &&
      323 +            (conf.output.width == 0 || conf.output.indent == 0) &&
      324 +            ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 &&
      325 +            ws.ws_col > 1) {
      326 +                if (conf.output.width == 0 && ws.ws_col < 79)
      327 +                        conf.output.width = ws.ws_col - 1;
      328 +                if (conf.output.indent == 0 && ws.ws_col < 66)
      329 +                        conf.output.indent = 3;
      330 +        }
      331 +
 319  332  #if HAVE_PLEDGE
 320  333          if (!use_pager)
 321  334                  if (pledge("stdio rpath", NULL) == -1)
 322  335                          err((int)MANDOCLEVEL_SYSERR, "pledge");
 323  336  #endif
 324  337  
 325  338          /* Parse arguments. */
 326  339  
 327  340          if (argc > 0) {
 328  341                  argc -= optind;
↓ open down ↓ 38 lines elided ↑ open up ↑
 367  380                      outmode == OUTMODE_ONE)
 368  381                          search.firstmatch = 1;
 369  382  
 370  383                  /* Access the mandoc database. */
 371  384  
 372  385                  manconf_parse(&conf, conf_file, defpaths, auxpaths);
 373  386                  if ( ! mansearch(&search, &conf.manpath,
 374  387                      argc, argv, &res, &sz))
 375  388                          usage(search.argmode);
 376  389  
 377      -                if (sz == 0) {
 378      -                        if (search.argmode == ARG_NAME)
 379      -                                fs_search(&search, &conf.manpath,
 380      -                                    argc, argv, &res, &sz);
 381      -                        else
 382      -                                warnx("nothing appropriate");
      390 +                if (sz == 0 && search.argmode == ARG_NAME)
      391 +                        fs_search(&search, &conf.manpath,
      392 +                            argc, argv, &res, &sz);
      393 +
      394 +                if (search.argmode == ARG_NAME) {
      395 +                        for (c = 0; c < argc; c++) {
      396 +                                if (strchr(argv[c], '/') == NULL)
      397 +                                        continue;
      398 +                                if (access(argv[c], R_OK) == -1) {
      399 +                                        warn("%s", argv[c]);
      400 +                                        continue;
      401 +                                }
      402 +                                res = mandoc_reallocarray(res,
      403 +                                    sz + 1, sizeof(*res));
      404 +                                res[sz].file = mandoc_strdup(argv[c]);
      405 +                                res[sz].names = NULL;
      406 +                                res[sz].output = NULL;
      407 +                                res[sz].ipath = SIZE_MAX;
      408 +                                res[sz].bits = 0;
      409 +                                res[sz].sec = 10;
      410 +                                res[sz].form = FORM_SRC;
      411 +                                sz++;
      412 +                        }
 383  413                  }
 384  414  
 385  415                  if (sz == 0) {
      416 +                        if (search.argmode != ARG_NAME)
      417 +                                warnx("nothing appropriate");
 386  418                          rc = MANDOCLEVEL_BADARG;
 387  419                          goto out;
 388  420                  }
 389  421  
 390  422                  /*
 391  423                   * For standard man(1) and -a output mode,
 392  424                   * prepare for copying filename pointers
 393  425                   * into the program parameter array.
 394  426                   */
 395  427  
↓ open down ↓ 63 lines elided ↑ open up ↑
 459  491           */
 460  492          if (OUTT_MAN == curp.outtype)
 461  493                  mparse_keep(curp.mp);
 462  494  
 463  495          if (argc < 1) {
 464  496                  if (use_pager)
 465  497                          tag_files = tag_init();
 466  498                  parse(&curp, STDIN_FILENO, "<stdin>");
 467  499          }
 468  500  
      501 +        /*
      502 +         * Remember the original working directory, if possible.
      503 +         * This will be needed if some names on the command line
      504 +         * are page names and some are relative file names.
      505 +         * Do not error out if the current directory is not
      506 +         * readable: Maybe it won't be needed after all.
      507 +         */
      508 +        startdir = open(".", O_RDONLY | O_DIRECTORY);
      509 +
 469  510          while (argc > 0) {
      511 +
      512 +                /*
      513 +                 * Changing directories is not needed in ARG_FILE mode.
      514 +                 * Do it on a best-effort basis.  Even in case of
      515 +                 * failure, some functionality may still work.
      516 +                 */
      517 +                if (resp != NULL) {
      518 +                        if (resp->ipath != SIZE_MAX)
      519 +                                (void)chdir(conf.manpath.paths[resp->ipath]);
      520 +                        else if (startdir != -1)
      521 +                                (void)fchdir(startdir);
      522 +                }
      523 +
 470  524                  fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv);
 471  525                  if (fd != -1) {
 472  526                          if (use_pager) {
 473  527                                  tag_files = tag_init();
 474  528                                  use_pager = 0;
 475  529                          }
 476  530  
 477  531                          if (resp == NULL)
 478  532                                  parse(&curp, fd, *argv);
 479      -                        else if (resp->form == FORM_SRC) {
 480      -                                /* For .so only; ignore failure. */
 481      -                                (void)chdir(conf.manpath.paths[resp->ipath]);
      533 +                        else if (resp->form == FORM_SRC)
 482  534                                  parse(&curp, fd, resp->file);
 483      -                        } else
      535 +                        else
 484  536                                  passthrough(resp->file, fd,
 485  537                                      conf.output.synopsisonly);
 486  538  
      539 +                        if (ferror(stdout)) {
      540 +                                if (tag_files != NULL) {
      541 +                                        warn("%s", tag_files->ofn);
      542 +                                        tag_unlink();
      543 +                                        tag_files = NULL;
      544 +                                } else
      545 +                                        warn("stdout");
      546 +                                rc = MANDOCLEVEL_SYSERR;
      547 +                                break;
      548 +                        }
      549 +
 487  550                          if (argc > 1 && curp.outtype <= OUTT_UTF8) {
 488  551                                  if (curp.outdata == NULL)
 489  552                                          outdata_alloc(&curp);
 490  553                                  terminal_sepline(curp.outdata);
 491  554                          }
 492  555                  } else if (rc < MANDOCLEVEL_ERROR)
 493  556                          rc = MANDOCLEVEL_ERROR;
 494  557  
 495  558                  if (MANDOCLEVEL_OK != rc && curp.wstop)
 496  559                          break;
 497  560  
 498  561                  if (resp != NULL)
 499  562                          resp++;
 500  563                  else
 501  564                          argv++;
 502  565                  if (--argc)
 503  566                          mparse_reset(curp.mp);
 504  567          }
      568 +        if (startdir != -1) {
      569 +                (void)fchdir(startdir);
      570 +                close(startdir);
      571 +        }
 505  572  
 506  573          if (curp.outdata != NULL) {
 507  574                  switch (curp.outtype) {
 508  575                  case OUTT_HTML:
 509  576                          html_free(curp.outdata);
 510  577                          break;
 511  578                  case OUTT_UTF8:
 512  579                  case OUTT_LOCALE:
 513  580                  case OUTT_ASCII:
 514  581                          ascii_free(curp.outdata);
↓ open down ↓ 200 lines elided ↑ open up ↑
 715  782                                  if (fs_lookup(paths, ipath, cfg->sec,
 716  783                                      cfg->arch, *argv, res, ressz) &&
 717  784                                      cfg->firstmatch)
 718  785                                          return 1;
 719  786                          } else for (isec = 0; isec < nsec; isec++)
 720  787                                  if (fs_lookup(paths, ipath, sections[isec],
 721  788                                      cfg->arch, *argv, res, ressz) &&
 722  789                                      cfg->firstmatch)
 723  790                                          return 1;
 724  791                  }
 725      -                if (res != NULL && *ressz == lastsz)
      792 +                if (res != NULL && *ressz == lastsz &&
      793 +                    strchr(*argv, '/') == NULL)
 726  794                          warnx("No entry for %s in the manual.", *argv);
 727  795                  lastsz = *ressz;
 728  796                  argv++;
 729  797                  argc--;
 730  798          }
 731  799          return 0;
 732  800  }
 733  801  
 734  802  static void
 735  803  parse(struct curparse *curp, int fd, const char *file)
↓ open down ↓ 430 lines elided ↑ open up ↑
1166 1234  #endif
1167 1235                  tag_files->pager_pid = pager_pid;
1168 1236                  return pager_pid;
1169 1237          }
1170 1238  
1171 1239          /* The child process becomes the pager. */
1172 1240  
1173 1241          if (dup2(tag_files->ofd, STDOUT_FILENO) == -1)
1174 1242                  err((int)MANDOCLEVEL_SYSERR, "pager stdout");
1175 1243          close(tag_files->ofd);
1176      -        close(tag_files->tfd);
     1244 +        assert(tag_files->tfd == -1);
1177 1245  
1178 1246          /* Do not start the pager before controlling the terminal. */
1179 1247  
1180 1248          while (tcgetpgrp(STDOUT_FILENO) != getpid())
1181 1249                  nanosleep(&timeout, NULL);
1182 1250  
1183 1251          execvp(argv[0], argv);
1184 1252          err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
1185 1253  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX