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

Diff for /mandoc/mandocdb.c between version 1.120 and 1.124

version 1.120, 2014/03/23 12:11:18 version 1.124, 2014/03/26 21:39:38
Line 119  struct mlink {
Line 119  struct mlink {
         char            *fsec;    /* section from file name suffix */          char            *fsec;    /* section from file name suffix */
         struct mlink    *next;    /* singly linked list */          struct mlink    *next;    /* singly linked list */
         struct mpage    *mpage;   /* parent */          struct mpage    *mpage;   /* parent */
           int              gzip;    /* filename has a .gz suffix */
 };  };
   
 enum    stmt {  enum    stmt {
Line 151  static void  mlink_free(struct mlink *);
Line 152  static void  mlink_free(struct mlink *);
 static  void     mlinks_undupe(struct mpage *);  static  void     mlinks_undupe(struct mpage *);
 static  void     mpages_free(void);  static  void     mpages_free(void);
 static  void     mpages_merge(struct mchars *, struct mparse *);  static  void     mpages_merge(struct mchars *, struct mparse *);
 static  void     parse_cat(struct mpage *);  static  void     parse_cat(struct mpage *, int);
 static  void     parse_man(struct mpage *, const struct man_node *);  static  void     parse_man(struct mpage *, const struct man_node *);
 static  void     parse_mdoc(struct mpage *, const struct mdoc_node *);  static  void     parse_mdoc(struct mpage *, const struct mdoc_node *);
 static  int      parse_mdoc_body(struct mpage *, const struct mdoc_node *);  static  int      parse_mdoc_body(struct mpage *, const struct mdoc_node *);
Line 536  treescan(void)
Line 537  treescan(void)
         FTS             *f;          FTS             *f;
         FTSENT          *ff;          FTSENT          *ff;
         struct mlink    *mlink;          struct mlink    *mlink;
         int              dform;          int              dform, gzip;
         char            *dsec, *arch, *fsec, *cp;          char            *dsec, *arch, *fsec, *cp;
         const char      *path;          const char      *path;
         const char      *argv[2];          const char      *argv[2];
Line 551  treescan(void)
Line 552  treescan(void)
         f = fts_open((char * const *)argv, FTS_LOGICAL, NULL);          f = fts_open((char * const *)argv, FTS_LOGICAL, NULL);
         if (NULL == f) {          if (NULL == f) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("", NULL);                  say("", "&fts_open");
                 return(0);                  return(0);
         }          }
   
Line 571  treescan(void)
Line 572  treescan(void)
                                 if (warnings)                                  if (warnings)
                                         say(path, "Extraneous file");                                          say(path, "Extraneous file");
                                 continue;                                  continue;
                         } else if (NULL == (fsec =                          }
                                         strrchr(ff->fts_name, '.'))) {                          gzip = 0;
                           fsec = NULL;
                           while (NULL == fsec) {
                                   fsec = strrchr(ff->fts_name, '.');
                                   if (NULL == fsec || strcmp(fsec+1, "gz"))
                                           break;
                                   gzip = 1;
                                   *fsec = '\0';
                                   fsec = NULL;
                           }
                           if (NULL == fsec) {
                                 if ( ! use_all) {                                  if ( ! use_all) {
                                         if (warnings)                                          if (warnings)
                                                 say(path,                                                  say(path,
Line 583  treescan(void)
Line 594  treescan(void)
                                 if (warnings)                                  if (warnings)
                                         say(path, "Skip html");                                          say(path, "Skip html");
                                 continue;                                  continue;
                         } else if (0 == strcmp(fsec, "gz")) {  
                                 if (warnings)  
                                         say(path, "Skip gz");  
                                 continue;  
                         } else if (0 == strcmp(fsec, "ps")) {                          } else if (0 == strcmp(fsec, "ps")) {
                                 if (warnings)                                  if (warnings)
                                         say(path, "Skip ps");                                          say(path, "Skip ps");
Line 611  treescan(void)
Line 618  treescan(void)
                         mlink->arch = arch;                          mlink->arch = arch;
                         mlink->name = ff->fts_name;                          mlink->name = ff->fts_name;
                         mlink->fsec = fsec;                          mlink->fsec = fsec;
                           mlink->gzip = gzip;
                         mlink_add(mlink, ff->fts_statp);                          mlink_add(mlink, ff->fts_statp);
                         continue;                          continue;
                 } else if (FTS_D != ff->fts_info &&                  } else if (FTS_D != ff->fts_info &&
Line 705  filescan(const char *file)
Line 713  filescan(const char *file)
   
         if (NULL == realpath(file, buf)) {          if (NULL == realpath(file, buf)) {
                 exitcode = (int)MANDOCLEVEL_BADARG;                  exitcode = (int)MANDOCLEVEL_BADARG;
                 say(file, NULL);                  say(file, "&realpath");
                 return;                  return;
         }          }
   
Line 721  filescan(const char *file)
Line 729  filescan(const char *file)
   
         if (-1 == stat(buf, &st)) {          if (-1 == stat(buf, &st)) {
                 exitcode = (int)MANDOCLEVEL_BADARG;                  exitcode = (int)MANDOCLEVEL_BADARG;
                 say(file, NULL);                  say(file, "&stat");
                 return;                  return;
         } else if ( ! (S_IFREG & st.st_mode)) {          } else if ( ! (S_IFREG & st.st_mode)) {
                 exitcode = (int)MANDOCLEVEL_BADARG;                  exitcode = (int)MANDOCLEVEL_BADARG;
Line 964  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 972  mpages_merge(struct mchars *mc, struct mparse *mp)
 {  {
         char                     any[] = "any";          char                     any[] = "any";
         struct ohash_info        str_info;          struct ohash_info        str_info;
           int                      fd[2];
         struct mpage            *mpage, *mpage_dest;          struct mpage            *mpage, *mpage_dest;
         struct mlink            *mlink, *mlink_dest;          struct mlink            *mlink, *mlink_dest;
         struct mdoc             *mdoc;          struct mdoc             *mdoc;
         struct man              *man;          struct man              *man;
         char                    *sodest;          char                    *sodest;
         char                    *cp;          char                    *cp;
         int                      match;          pid_t                    child_pid;
           int                      match, status;
         unsigned int             pslot;          unsigned int             pslot;
         enum mandoclevel         lvl;          enum mandoclevel         lvl;
   
Line 994  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1004  mpages_merge(struct mchars *mc, struct mparse *mp)
                 mparse_reset(mp);                  mparse_reset(mp);
                 mdoc = NULL;                  mdoc = NULL;
                 man = NULL;                  man = NULL;
                   sodest = NULL;
                   child_pid = 0;
                   fd[0] = -1;
                   fd[1] = -1;
   
                   if (mpage->mlinks->gzip) {
                           if (-1 == pipe(fd)) {
                                   exitcode = (int)MANDOCLEVEL_SYSERR;
                                   say(mpage->mlinks->file, "&pipe gunzip");
                                   goto nextpage;
                           }
                           switch (child_pid = fork()) {
                           case (-1):
                                   exitcode = (int)MANDOCLEVEL_SYSERR;
                                   say(mpage->mlinks->file, "&fork gunzip");
                                   child_pid = 0;
                                   close(fd[1]);
                                   close(fd[0]);
                                   goto nextpage;
                           case (0):
                                   close(fd[0]);
                                   if (-1 == dup2(fd[1], STDOUT_FILENO)) {
                                           say(mpage->mlinks->file,
                                               "&dup gunzip");
                                           exit(1);
                                   }
                                   execlp("gunzip", "gunzip", "-c",
                                       mpage->mlinks->file, NULL);
                                   say(mpage->mlinks->file, "&exec gunzip");
                                   exit(1);
                           default:
                                   close(fd[1]);
                                   break;
                           }
                   }
   
                 /*                  /*
                  * Try interpreting the file as mdoc(7) or man(7)                   * Try interpreting the file as mdoc(7) or man(7)
                  * source code, unless it is already known to be                   * source code, unless it is already known to be
Line 1002  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1047  mpages_merge(struct mchars *mc, struct mparse *mp)
                  */                   */
                 if (FORM_CAT != mpage->mlinks->dform ||                  if (FORM_CAT != mpage->mlinks->dform ||
                     FORM_CAT != mpage->mlinks->fform) {                      FORM_CAT != mpage->mlinks->fform) {
                         lvl = mparse_readfd(mp, -1, mpage->mlinks->file);                          lvl = mparse_readfd(mp, fd[0], mpage->mlinks->file);
                         if (lvl < MANDOCLEVEL_FATAL)                          if (lvl < MANDOCLEVEL_FATAL)
                                 mparse_result(mp, &mdoc, &man, &sodest);                                  mparse_result(mp, &mdoc, &man, &sodest);
                 }                  }
Line 1042  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1087  mpages_merge(struct mchars *mc, struct mparse *mp)
                                 mlink_dest->next = mpage->mlinks;                                  mlink_dest->next = mpage->mlinks;
                                 mpage->mlinks = NULL;                                  mpage->mlinks = NULL;
                         }                          }
                         ohash_delete(&strings);                          goto nextpage;
                         mpage = ohash_next(&mpages, &pslot);  
                         continue;  
                 } else if (NULL != mdoc) {                  } else if (NULL != mdoc) {
                         mpage->form = FORM_SRC;                          mpage->form = FORM_SRC;
                         mpage->sec =                          mpage->sec =
Line 1104  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1147  mpages_merge(struct mchars *mc, struct mparse *mp)
                 } else if (NULL != man)                  } else if (NULL != man)
                         parse_man(mpage, man_node(man));                          parse_man(mpage, man_node(man));
                 else                  else
                         parse_cat(mpage);                          parse_cat(mpage, fd[0]);
   
                 dbadd(mpage, mc);                  dbadd(mpage, mc);
   
   nextpage:
                   if (child_pid) {
                           if (-1 == waitpid(child_pid, &status, 0)) {
                                   exitcode = (int)MANDOCLEVEL_SYSERR;
                                   say(mpage->mlinks->file, "&wait gunzip");
                           } else if (WIFSIGNALED(status)) {
                                   exitcode = (int)MANDOCLEVEL_SYSERR;
                                   say(mpage->mlinks->file,
                                       "gunzip died from signal %d",
                                       WTERMSIG(status));
                           } else if (WEXITSTATUS(status)) {
                                   exitcode = (int)MANDOCLEVEL_SYSERR;
                                   say(mpage->mlinks->file,
                                       "gunzip failed with code %d",
                                       WEXITSTATUS(status));
                           }
                   }
                 ohash_delete(&strings);                  ohash_delete(&strings);
                 mpage = ohash_next(&mpages, &pslot);                  mpage = ohash_next(&mpages, &pslot);
         }          }
Line 1116  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1177  mpages_merge(struct mchars *mc, struct mparse *mp)
 }  }
   
 static void  static void
 parse_cat(struct mpage *mpage)  parse_cat(struct mpage *mpage, int fd)
 {  {
         FILE            *stream;          FILE            *stream;
         char            *line, *p, *title;          char            *line, *p, *title;
         size_t           len, plen, titlesz;          size_t           len, plen, titlesz;
   
         if (NULL == (stream = fopen(mpage->mlinks->file, "r"))) {          stream = (-1 == fd) ?
               fopen(mpage->mlinks->file, "r") :
               fdopen(fd, "r");
           if (NULL == stream) {
                 if (warnings)                  if (warnings)
                         say(mpage->mlinks->file, NULL);                          say(mpage->mlinks->file, "&fopen");
                 return;                  return;
         }          }
   
Line 1263  static void
Line 1327  static void
 parse_man(struct mpage *mpage, const struct man_node *n)  parse_man(struct mpage *mpage, const struct man_node *n)
 {  {
         const struct man_node *head, *body;          const struct man_node *head, *body;
         char            *start, *sv, *title;          char            *start, *title;
         char             byte;          char             byte;
         size_t           sz, titlesz;          size_t           sz;
   
         if (NULL == n)          if (NULL == n)
                 return;                  return;
Line 1285  parse_man(struct mpage *mpage, const struct man_node *
Line 1349  parse_man(struct mpage *mpage, const struct man_node *
                                 NULL != (head = (head->child)) &&                                  NULL != (head = (head->child)) &&
                                 MAN_TEXT == head->type &&                                  MAN_TEXT == head->type &&
                                 0 == strcmp(head->string, "NAME") &&                                  0 == strcmp(head->string, "NAME") &&
                                 NULL != (body = body->child) &&                                  NULL != body->child) {
                                 MAN_TEXT == body->type) {  
   
                         title = NULL;  
                         titlesz = 0;  
   
                         /*                          /*
                          * Suck the entire NAME section into memory.                           * Suck the entire NAME section into memory.
                          * Yes, we might run away.                           * Yes, we might run away.
Line 1298  parse_man(struct mpage *mpage, const struct man_node *
Line 1358  parse_man(struct mpage *mpage, const struct man_node *
                          * NAME sections over many lines.                           * NAME sections over many lines.
                          */                           */
   
                         for ( ; NULL != body; body = body->next) {                          title = NULL;
                                 if (MAN_TEXT != body->type)                          man_deroff(&title, body);
                                         break;  
                                 if (0 == (sz = strlen(body->string)))  
                                         continue;  
                                 title = mandoc_realloc  
                                         (title, titlesz + sz + 1);  
                                 memcpy(title + titlesz, body->string, sz);  
                                 titlesz += sz + 1;  
                                 title[titlesz - 1] = ' ';  
                         }  
                         if (NULL == title)                          if (NULL == title)
                                 return;                                  return;
   
                         title = mandoc_realloc(title, titlesz + 1);  
                         title[titlesz] = '\0';  
   
                         /* Skip leading space.  */  
   
                         sv = title;  
                         while (isspace((unsigned char)*sv))  
                                 sv++;  
   
                         if (0 == (sz = strlen(sv))) {  
                                 free(title);  
                                 return;  
                         }  
   
                         /* Erase trailing space. */  
   
                         start = &sv[sz - 1];  
                         while (start > sv && isspace((unsigned char)*start))  
                                 *start-- = '\0';  
   
                         if (start == sv) {  
                                 free(title);  
                                 return;  
                         }  
   
                         start = sv;  
   
                         /*                          /*
                          * Go through a special heuristic dance here.                           * Go through a special heuristic dance here.
                          * Conventionally, one or more manual names are                           * Conventionally, one or more manual names are
Line 1347  parse_man(struct mpage *mpage, const struct man_node *
Line 1371  parse_man(struct mpage *mpage, const struct man_node *
                          * the name parts here.                           * the name parts here.
                          */                           */
   
                           start = title;
                         for ( ;; ) {                          for ( ;; ) {
                                 sz = strcspn(start, " ,");                                  sz = strcspn(start, " ,");
                                 if ('\0' == start[sz])                                  if ('\0' == start[sz])
Line 1377  parse_man(struct mpage *mpage, const struct man_node *
Line 1402  parse_man(struct mpage *mpage, const struct man_node *
                                         start++;                                          start++;
                         }                          }
   
                         if (sv == start) {                          if (start == title) {
                                 putkey(mpage, start, TYPE_Nm);                                  putkey(mpage, start, TYPE_Nm);
                                 free(title);                                  free(title);
                                 return;                                  return;
Line 1545  parse_mdoc_Xr(struct mpage *mpage, const struct mdoc_n
Line 1570  parse_mdoc_Xr(struct mpage *mpage, const struct mdoc_n
 static int  static int
 parse_mdoc_Nd(struct mpage *mpage, const struct mdoc_node *n)  parse_mdoc_Nd(struct mpage *mpage, const struct mdoc_node *n)
 {  {
         size_t           sz;  
   
         if (MDOC_BODY != n->type)          if (MDOC_BODY == n->type)
                 return(0);                  mdoc_deroff(&mpage->desc, n);
           return(0);
         /*  
          * Special-case the `Nd' because we need to put the description  
          * into the document table.  
          */  
   
         for (n = n->child; NULL != n; n = n->next) {  
                 if (MDOC_TEXT == n->type) {  
                         if (NULL != mpage->desc) {  
                                 sz = strlen(mpage->desc) +  
                                      strlen(n->string) + 2;  
                                 mpage->desc = mandoc_realloc(  
                                     mpage->desc, sz);  
                                 strlcat(mpage->desc, " ", sz);  
                                 strlcat(mpage->desc, n->string, sz);  
                         } else  
                                 mpage->desc = mandoc_strdup(n->string);  
                 }  
                 if (NULL != n->child)  
                         parse_mdoc_Nd(mpage, n);  
         }  
         return(1);  
 }  }
   
 static int  static int
Line 1942  dbclose(int real)
Line 1945  dbclose(int real)
         if ('\0' == *tempfilename) {          if ('\0' == *tempfilename) {
                 if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {                  if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {
                         exitcode = (int)MANDOCLEVEL_SYSERR;                          exitcode = (int)MANDOCLEVEL_SYSERR;
                         say(MANDOC_DB, "%s", strerror(errno));                          say(MANDOC_DB, "&rename");
                 }                  }
                 return;                  return;
         }          }
Line 1950  dbclose(int real)
Line 1953  dbclose(int real)
         switch (child = fork()) {          switch (child = fork()) {
         case (-1):          case (-1):
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("fork cmp", "%s", strerror(errno));                  say("", "&fork cmp");
                 return;                  return;
         case (0):          case (0):
                 execlp("cmp", "cmp", "-s",                  execlp("cmp", "cmp", "-s",
                     tempfilename, MANDOC_DB, NULL);                      tempfilename, MANDOC_DB, NULL);
                 say("exec cmp", "%s", strerror(errno));                  say("", "&exec cmp");
                 exit(0);                  exit(0);
         default:          default:
                 break;                  break;
         }          }
         if (-1 == waitpid(child, &status, 0)) {          if (-1 == waitpid(child, &status, 0)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("wait cmp", "%s", strerror(errno));                  say("", "&wait cmp");
         } else if (WIFSIGNALED(status)) {          } else if (WIFSIGNALED(status)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("cmp", "Died from a signal");                  say("", "cmp died from signal %d", WTERMSIG(status));
         } else if (WEXITSTATUS(status)) {          } else if (WEXITSTATUS(status)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(MANDOC_DB,                  say(MANDOC_DB,
Line 1976  dbclose(int real)
Line 1979  dbclose(int real)
         switch (child = fork()) {          switch (child = fork()) {
         case (-1):          case (-1):
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("fork rm", "%s", strerror(errno));                  say("", "&fork rm");
                 return;                  return;
         case (0):          case (0):
                 execlp("rm", "rm", "-rf", tempfilename, NULL);                  execlp("rm", "rm", "-rf", tempfilename, NULL);
                 say("exec rm", "%s", strerror(errno));                  say("", "&exec rm");
                 exit((int)MANDOCLEVEL_SYSERR);                  exit((int)MANDOCLEVEL_SYSERR);
         default:          default:
                 break;                  break;
         }          }
         if (-1 == waitpid(child, &status, 0)) {          if (-1 == waitpid(child, &status, 0)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("wait rm", "%s", strerror(errno));                  say("", "&wait rm");
         } else if (WIFSIGNALED(status) || WEXITSTATUS(status)) {          } else if (WIFSIGNALED(status) || WEXITSTATUS(status)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(tempfilename,                  say("", "%s: Cannot remove temporary directory",
                     "Cannot remove temporary directory");                      tempfilename);
         }          }
 }  }
   
Line 2040  dbopen(int real)
Line 2043  dbopen(int real)
         if (strlcpy(tempfilename, "/tmp/mandocdb.XXXXXX",          if (strlcpy(tempfilename, "/tmp/mandocdb.XXXXXX",
             sizeof(tempfilename)) >= sizeof(tempfilename)) {              sizeof(tempfilename)) >= sizeof(tempfilename)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say("/tmp/mandocdb.XXXXXX", "Filename too long");                  say("", "/tmp/mandocdb.XXXXXX: Filename too long");
                 return(0);                  return(0);
         }          }
         if (NULL == mkdtemp(tempfilename)) {          if (NULL == mkdtemp(tempfilename)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(tempfilename, "%s", strerror(errno));                  say("", "&%s", tempfilename);
                 return(0);                  return(0);
         }          }
         if (strlcat(tempfilename, "/" MANDOC_DB,          if (strlcat(tempfilename, "/" MANDOC_DB,
             sizeof(tempfilename)) >= sizeof(tempfilename)) {              sizeof(tempfilename)) >= sizeof(tempfilename)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(tempfilename, "Filename too long");                  say("", "%s/" MANDOC_DB ": Filename too long",
                       tempfilename);
                 return(0);                  return(0);
         }          }
         rc = sqlite3_open_v2(tempfilename, &db, ofl, NULL);          rc = sqlite3_open_v2(tempfilename, &db, ofl, NULL);
         if (SQLITE_OK != rc) {          if (SQLITE_OK != rc) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(tempfilename, "%s", sqlite3_errmsg(db));                  say("", "%s: %s", tempfilename, sqlite3_errmsg(db));
                 return(0);                  return(0);
         }          }
   
Line 2154  set_basedir(const char *targetdir)
Line 2158  set_basedir(const char *targetdir)
                 if (NULL == getcwd(startdir, PATH_MAX)) {                  if (NULL == getcwd(startdir, PATH_MAX)) {
                         exitcode = (int)MANDOCLEVEL_SYSERR;                          exitcode = (int)MANDOCLEVEL_SYSERR;
                         if (NULL != targetdir)                          if (NULL != targetdir)
                                 say(".", NULL);                                  say("", "&getcwd");
                         return(0);                          return(0);
                 }                  }
                 if (-1 == (fd = open(startdir, O_RDONLY, 0))) {                  if (-1 == (fd = open(startdir, O_RDONLY, 0))) {
                         exitcode = (int)MANDOCLEVEL_SYSERR;                          exitcode = (int)MANDOCLEVEL_SYSERR;
                         say(startdir, NULL);                          say("", "&open %s", startdir);
                         return(0);                          return(0);
                 }                  }
                 if (NULL == targetdir)                  if (NULL == targetdir)
Line 2171  set_basedir(const char *targetdir)
Line 2175  set_basedir(const char *targetdir)
                         close(fd);                          close(fd);
                         basedir[0] = '\0';                          basedir[0] = '\0';
                         exitcode = (int)MANDOCLEVEL_SYSERR;                          exitcode = (int)MANDOCLEVEL_SYSERR;
                         say(startdir, NULL);                          say("", "&chdir %s", startdir);
                         return(0);                          return(0);
                 }                  }
                 if (NULL == targetdir) {                  if (NULL == targetdir) {
Line 2182  set_basedir(const char *targetdir)
Line 2186  set_basedir(const char *targetdir)
         if (NULL == realpath(targetdir, basedir)) {          if (NULL == realpath(targetdir, basedir)) {
                 basedir[0] = '\0';                  basedir[0] = '\0';
                 exitcode = (int)MANDOCLEVEL_BADARG;                  exitcode = (int)MANDOCLEVEL_BADARG;
                 say(targetdir, NULL);                  say("", "&%s: realpath", targetdir);
                 return(0);                  return(0);
         } else if (-1 == chdir(basedir)) {          } else if (-1 == chdir(basedir)) {
                 exitcode = (int)MANDOCLEVEL_BADARG;                  exitcode = (int)MANDOCLEVEL_BADARG;
                 say("", NULL);                  say("", "&chdir");
                 return(0);                  return(0);
         }          }
         return(1);          return(1);
Line 2196  static void
Line 2200  static void
 say(const char *file, const char *format, ...)  say(const char *file, const char *format, ...)
 {  {
         va_list          ap;          va_list          ap;
           int              use_errno;
   
         if ('\0' != *basedir)          if ('\0' != *basedir)
                 fprintf(stderr, "%s", basedir);                  fprintf(stderr, "%s", basedir);
Line 2203  say(const char *file, const char *format, ...)
Line 2208  say(const char *file, const char *format, ...)
                 fputs("//", stderr);                  fputs("//", stderr);
         if ('\0' != *file)          if ('\0' != *file)
                 fprintf(stderr, "%s", file);                  fprintf(stderr, "%s", file);
         fputs(": ", stderr);  
   
         if (NULL == format) {          use_errno = 1;
                 perror(NULL);          if (NULL != format) {
                 return;                  switch (*format) {
                   case ('&'):
                           format++;
                           break;
                   case ('\0'):
                           format = NULL;
                           break;
                   default:
                           use_errno = 0;
                           break;
                   }
         }          }
           if (NULL != format) {
         va_start(ap, format);                  if ('\0' != *basedir || '\0' != *file)
         vfprintf(stderr, format, ap);                          fputs(": ", stderr);
         va_end(ap);                  va_start(ap, format);
                   vfprintf(stderr, format, ap);
         fputc('\n', stderr);                  va_end(ap);
           }
           if (use_errno) {
                   if ('\0' != *basedir || '\0' != *file || NULL != format)
                           fputs(": ", stderr);
                   perror(NULL);
           } else
                   fputc('\n', stderr);
 }  }

Legend:
Removed from v.1.120  
changed lines
  Added in v.1.124

CVSweb