[BACK]Return to main.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/main.c between version 1.338 and 1.345

version 1.338, 2019/07/28 18:23:17 version 1.345, 2020/03/13 15:32:28
Line 1 
Line 1 
 /*      $Id$ */  /* $Id$ */
 /*  /*
    * Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org>  
  * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>   * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 15 
Line 15 
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    *
    * Main program for mandoc(1), man(1), apropos(1), whatis(1), and help(1).
  */   */
 #include "config.h"  #include "config.h"
   
Line 32 
Line 34 
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <glob.h>  #include <glob.h>
   #include <limits.h>
 #if HAVE_SANDBOX_INIT  #if HAVE_SANDBOX_INIT
 #include <sandbox.h>  #include <sandbox.h>
 #endif  #endif
Line 51 
Line 54 
 #include "mdoc.h"  #include "mdoc.h"
 #include "man.h"  #include "man.h"
 #include "mandoc_parse.h"  #include "mandoc_parse.h"
 #include "tag.h"  #include "term_tag.h"
 #include "main.h"  #include "main.h"
 #include "manconf.h"  #include "manconf.h"
 #include "mansearch.h"  #include "mansearch.h"
Line 95  static int    fs_lookup(const struct manpaths *,
Line 98  static int    fs_lookup(const struct manpaths *,
                                 const char *, const char *,                                  const char *, const char *,
                                 struct manpage **, size_t *);                                  struct manpage **, size_t *);
 static  int               fs_search(const struct mansearch *,  static  int               fs_search(const struct mansearch *,
                                 const struct manpaths *, int, char**,                                  const struct manpaths *, const char *,
                                 struct manpage **, size_t *);                                  struct manpage **, size_t *);
   static  void              glob_esc(char **, const char *, const char *);
 static  void              outdata_alloc(struct outstate *, struct manoutput *);  static  void              outdata_alloc(struct outstate *, struct manoutput *);
 static  void              parse(struct mparse *, int, const char *,  static  void              parse(struct mparse *, int, const char *,
                                 struct outstate *, struct manoutput *);                                  struct outstate *, struct manoutput *);
Line 325  main(int argc, char *argv[])
Line 329  main(int argc, char *argv[])
   
         /* Postprocess options. */          /* Postprocess options. */
   
         if (outmode == OUTMODE_DEF) {          switch (outmode) {
           case OUTMODE_DEF:
                 switch (search.argmode) {                  switch (search.argmode) {
                 case ARG_FILE:                  case ARG_FILE:
                         outmode = OUTMODE_ALL;                          outmode = OUTMODE_ALL;
Line 338  main(int argc, char *argv[])
Line 343  main(int argc, char *argv[])
                         outmode = OUTMODE_LST;                          outmode = OUTMODE_LST;
                         break;                          break;
                 }                  }
                   break;
           case OUTMODE_FLN:
                   if (search.argmode == ARG_FILE)
                           outmode = OUTMODE_ALL;
                   break;
           case OUTMODE_ALL:
                   break;
           case OUTMODE_LST:
           case OUTMODE_ONE:
                   abort();
         }          }
   
         if (oarg != NULL) {          if (oarg != NULL) {
Line 436  main(int argc, char *argv[])
Line 451  main(int argc, char *argv[])
         /* man(1): Resolve each name individually. */          /* man(1): Resolve each name individually. */
   
         if (search.argmode == ARG_NAME) {          if (search.argmode == ARG_NAME) {
                 if (argc < 1)                  if (argc < 1) {
                         usage(ARG_NAME);                          if (outmode != OUTMODE_FLN)
                                   usage(ARG_NAME);
                           if (conf.manpath.sz == 0) {
                                   warnx("The manpath is empty.");
                                   mandoc_msg_setrc(MANDOCLEVEL_BADARG);
                           } else {
                                   for (i = 0; i + 1 < conf.manpath.sz; i++)
                                           printf("%s:", conf.manpath.paths[i]);
                                   printf("%s\n", conf.manpath.paths[i]);
                           }
                           manconf_free(&conf);
                           return (int)mandoc_msg_getrc();
                   }
                 for (res = NULL, ressz = 0; argc > 0; argc--, argv++) {                  for (res = NULL, ressz = 0; argc > 0; argc--, argv++) {
                         (void)mansearch(&search, &conf.manpath,                          (void)mansearch(&search, &conf.manpath,
                             1, argv, &resn, &resnsz);                              1, argv, &resn, &resnsz);
                         if (resnsz == 0)                          if (resnsz == 0)
                                 (void)fs_search(&search, &conf.manpath,                                  (void)fs_search(&search, &conf.manpath,
                                     1, argv, &resn, &resnsz);                                      *argv, &resn, &resnsz);
                           if (resnsz == 0 && strchr(*argv, '/') == NULL) {
                                   if (search.arch != NULL &&
                                       arch_valid(search.arch, OSENUM) == 0)
                                           warnx("Unknown architecture \"%s\".",
                                               search.arch);
                                   else if (search.sec != NULL)
                                           warnx("No entry for %s in "
                                               "section %s of the manual.",
                                               *argv, search.sec);
                                   else
                                           warnx("No entry for %s in "
                                               "the manual.", *argv);
                                   mandoc_msg_setrc(MANDOCLEVEL_BADARG);
                                   continue;
                           }
                         if (resnsz == 0) {                          if (resnsz == 0) {
                                 if (strchr(*argv, '/') == NULL) {  
                                         mandoc_msg_setrc(MANDOCLEVEL_BADARG);  
                                         continue;  
                                 }  
                                 if (access(*argv, R_OK) == -1) {                                  if (access(*argv, R_OK) == -1) {
                                         mandoc_msg_setinfilename(*argv);                                          mandoc_msg_setinfilename(*argv);
                                         mandoc_msg(MANDOCERR_BADARG_BAD,                                          mandoc_msg(MANDOCERR_BADARG_BAD,
Line 544  main(int argc, char *argv[])
Line 582  main(int argc, char *argv[])
                 break;                  break;
         }          }
   
 #if HAVE_PLEDGE  
         if (outst.use_pager) {  
                 if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {  
                         mandoc_msg(MANDOCERR_PLEDGE, 0, 0,  
                             "%s", strerror(errno));  
                         return mandoc_msg_getrc();  
                 }  
         } else {  
                 if (pledge("stdio rpath", NULL) == -1) {  
                         mandoc_msg(MANDOCERR_PLEDGE, 0, 0,  
                             "%s", strerror(errno));  
                         return mandoc_msg_getrc();  
                 }  
         }  
 #endif  
   
         if (search.argmode == ARG_FILE && auxpaths != NULL) {          if (search.argmode == ARG_FILE && auxpaths != NULL) {
                 if (strcmp(auxpaths, "doc") == 0)                  if (strcmp(auxpaths, "doc") == 0)
                         options |= MPARSE_MDOC;                          options |= MPARSE_MDOC;
Line 578  main(int argc, char *argv[])
Line 600  main(int argc, char *argv[])
          * readable: Maybe it won't be needed after all.           * readable: Maybe it won't be needed after all.
          */           */
         startdir = open(".", O_RDONLY | O_DIRECTORY);          startdir = open(".", O_RDONLY | O_DIRECTORY);
   
         for (i = 0; i < ressz; i++) {          for (i = 0; i < ressz; i++) {
                 process_onefile(mp, res + i, startdir, &outst, &conf);                  process_onefile(mp, res + i, startdir, &outst, &conf);
                 if (outst.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)                  if (outst.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
Line 588  main(int argc, char *argv[])
Line 609  main(int argc, char *argv[])
                 (void)fchdir(startdir);                  (void)fchdir(startdir);
                 close(startdir);                  close(startdir);
         }          }
   
         if (outst.outdata != NULL) {          if (outst.outdata != NULL) {
                 switch (outst.outtype) {                  switch (outst.outtype) {
                 case OUTT_HTML:                  case OUTT_HTML:
Line 597  main(int argc, char *argv[])
Line 617  main(int argc, char *argv[])
                 case OUTT_UTF8:                  case OUTT_UTF8:
                 case OUTT_LOCALE:                  case OUTT_LOCALE:
                 case OUTT_ASCII:                  case OUTT_ASCII:
                           term_tag_finish();
                         ascii_free(outst.outdata);                          ascii_free(outst.outdata);
                         break;                          break;
                 case OUTT_PDF:                  case OUTT_PDF:
Line 618  out:
Line 639  out:
   
         if (outst.tag_files != NULL) {          if (outst.tag_files != NULL) {
                 fclose(stdout);                  fclose(stdout);
                 tag_write();  
                 run_pager(outst.tag_files);                  run_pager(outst.tag_files);
                 tag_unlink();                  term_tag_unlink();
         } else if (outst.had_output && outst.outtype != OUTT_LINT)          } else if (outst.had_output && outst.outtype != OUTT_LINT)
                 mandoc_msg_summary();                  mandoc_msg_summary();
   
Line 655  usage(enum argmode argmode)
Line 675  usage(enum argmode argmode)
         exit((int)MANDOCLEVEL_BADARG);          exit((int)MANDOCLEVEL_BADARG);
 }  }
   
   static void
   glob_esc(char **dst, const char *src, const char *suffix)
   {
           while (*src != '\0') {
                   if (strchr("*?[", *src) != NULL)
                           *(*dst)++ = '\\';
                   *(*dst)++ = *src++;
           }
           while (*suffix != '\0')
                   *(*dst)++ = *suffix++;
   }
   
 static int  static int
 fs_lookup(const struct manpaths *paths, size_t ipath,  fs_lookup(const struct manpaths *paths, size_t ipath,
         const char *sec, const char *arch, const char *name,          const char *sec, const char *arch, const char *name,
Line 663  fs_lookup(const struct manpaths *paths, size_t ipath,
Line 695  fs_lookup(const struct manpaths *paths, size_t ipath,
         struct stat      sb;          struct stat      sb;
         glob_t           globinfo;          glob_t           globinfo;
         struct manpage  *page;          struct manpage  *page;
         char            *file;          char            *file, *cp;
         int              globres;          int              globres;
         enum form        form;          enum form        form;
   
           const char *const slman = "/man";
           const char *const slash = "/";
           const char *const sglob = ".[01-9]*";
   
         form = FORM_SRC;          form = FORM_SRC;
         mandoc_asprintf(&file, "%s/man%s/%s.%s",          mandoc_asprintf(&file, "%s/man%s/%s.%s",
             paths->paths[ipath], sec, name, sec);              paths->paths[ipath], sec, name, sec);
Line 690  fs_lookup(const struct manpaths *paths, size_t ipath,
Line 726  fs_lookup(const struct manpaths *paths, size_t ipath,
                 free(file);                  free(file);
         }          }
   
         mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*",          cp = file = mandoc_malloc(strlen(paths->paths[ipath]) * 2 +
             paths->paths[ipath], sec, name);              strlen(slman) + strlen(sec) * 2 + strlen(slash) +
               strlen(name) * 2 + strlen(sglob) + 1);
           glob_esc(&cp, paths->paths[ipath], slman);
           glob_esc(&cp, sec, slash);
           glob_esc(&cp, name, sglob);
           *cp = '\0';
         globres = glob(file, 0, NULL, &globinfo);          globres = glob(file, 0, NULL, &globinfo);
         if (globres != 0 && globres != GLOB_NOMATCH)          if (globres != 0 && globres != GLOB_NOMATCH)
                 mandoc_msg(MANDOCERR_GLOB, 0, 0,                  mandoc_msg(MANDOCERR_GLOB, 0, 0,
Line 734  found:
Line 775  found:
   
 static int  static int
 fs_search(const struct mansearch *cfg, const struct manpaths *paths,  fs_search(const struct mansearch *cfg, const struct manpaths *paths,
         int argc, char **argv, struct manpage **res, size_t *ressz)          const char *name, struct manpage **res, size_t *ressz)
 {  {
         const char *const sections[] =          const char *const sections[] =
             {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"};              {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"};
         const size_t nsec = sizeof(sections)/sizeof(sections[0]);          const size_t nsec = sizeof(sections)/sizeof(sections[0]);
   
         size_t           ipath, isec, lastsz;          size_t           ipath, isec;
   
         assert(cfg->argmode == ARG_NAME);          assert(cfg->argmode == ARG_NAME);
   
         if (res != NULL)          if (res != NULL)
                 *res = NULL;                  *res = NULL;
         *ressz = lastsz = 0;          *ressz = 0;
         while (argc) {          for (ipath = 0; ipath < paths->sz; ipath++) {
                 for (ipath = 0; ipath < paths->sz; ipath++) {                  if (cfg->sec != NULL) {
                         if (cfg->sec != NULL) {                          if (fs_lookup(paths, ipath, cfg->sec, cfg->arch,
                                 if (fs_lookup(paths, ipath, cfg->sec,                              name, res, ressz) != -1 && cfg->firstmatch)
                                     cfg->arch, *argv, res, ressz) != -1 &&                                  return 0;
                                     cfg->firstmatch)                  } else {
                                         return 0;                          for (isec = 0; isec < nsec; isec++)
                         } else for (isec = 0; isec < nsec; isec++)  
                                 if (fs_lookup(paths, ipath, sections[isec],                                  if (fs_lookup(paths, ipath, sections[isec],
                                     cfg->arch, *argv, res, ressz) != -1 &&                                      cfg->arch, name, res, ressz) != -1 &&
                                     cfg->firstmatch)                                      cfg->firstmatch)
                                         return 0;                                          return 0;
                 }                  }
                 if (res != NULL && *ressz == lastsz &&  
                     strchr(*argv, '/') == NULL) {  
                         if (cfg->arch != NULL &&  
                             arch_valid(cfg->arch, OSENUM) == 0)  
                                 warnx("Unknown architecture \"%s\".",  
                                     cfg->arch);  
                         else if (cfg->sec == NULL)  
                                 warnx("No entry for %s in the manual.",  
                                     *argv);  
                         else  
                                 warnx("No entry for %s in section %s "  
                                     "of the manual.", *argv, cfg->sec);  
                 }  
                 lastsz = *ressz;  
                 argv++;  
                 argc--;  
         }          }
         return -1;          return -1;
 }  }
Line 808  process_onefile(struct mparse *mp, struct manpage *res
Line 831  process_onefile(struct mparse *mp, struct manpage *res
         } else          } else
                 fd = STDIN_FILENO;                  fd = STDIN_FILENO;
   
         if (outst->use_pager) {          if (outst->outtype <= OUTT_UTF8) {
                 outst->use_pager = 0;                  if (outst->use_pager) {
                 outst->tag_files = tag_init(conf->output.tag);                          outst->use_pager = 0;
                           outst->tag_files = term_tag_init(conf->output.tag);
                   }
                   if (outst->had_output) {
                           if (outst->outdata == NULL)
                                   outdata_alloc(outst, &conf->output);
                           terminal_sepline(outst->outdata);
                   }
         }          }
   
         if (outst->had_output && outst->outtype <= OUTT_UTF8) {  
                 if (outst->outdata == NULL)  
                         outdata_alloc(outst, &conf->output);  
                 terminal_sepline(outst->outdata);  
         }  
   
         if (resp->form == FORM_SRC)          if (resp->form == FORM_SRC)
                 parse(mp, fd, resp->file, outst, &conf->output);                  parse(mp, fd, resp->file, outst, &conf->output);
         else {          else {
Line 830  process_onefile(struct mparse *mp, struct manpage *res
Line 854  process_onefile(struct mparse *mp, struct manpage *res
                 if (outst->tag_files != NULL) {                  if (outst->tag_files != NULL) {
                         mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s: %s",                          mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s: %s",
                             outst->tag_files->ofn, strerror(errno));                              outst->tag_files->ofn, strerror(errno));
                         tag_unlink();                          term_tag_unlink();
                         outst->tag_files = NULL;                          outst->tag_files = NULL;
                 } else                  } else
                         mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s",                          mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s",
Line 950  check_xr(void)
Line 974  check_xr(void)
                 search.firstmatch = 1;                  search.firstmatch = 1;
                 if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz))                  if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz))
                         continue;                          continue;
                 if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz) != -1)                  if (fs_search(&search, &paths, xr->name, NULL, &sz) != -1)
                         continue;                          continue;
                 if (xr->count == 1)                  if (xr->count == 1)
                         mandoc_msg(MANDOCERR_XR_BAD, xr->line,                          mandoc_msg(MANDOCERR_XR_BAD, xr->line,
Line 1255  spawn_pager(struct tag_files *tag_files)
Line 1279  spawn_pager(struct tag_files *tag_files)
                 _exit(mandoc_msg_getrc());                  _exit(mandoc_msg_getrc());
         }          }
         close(tag_files->ofd);          close(tag_files->ofd);
         assert(tag_files->tfd == -1);          assert(tag_files->tfs == NULL);
   
         /* Do not start the pager before controlling the terminal. */          /* Do not start the pager before controlling the terminal. */
   

Legend:
Removed from v.1.338  
changed lines
  Added in v.1.345

CVSweb