[BACK]Return to filename.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Diff for /src/usr.bin/less/filename.c between version 1.7 and 1.8

version 1.7, 2003/04/06 23:38:06 version 1.8, 2003/04/13 18:26:25
Line 1 
Line 1 
 /*      $OpenBSD$       */  
   
 /*  /*
  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman   * Copyright (C) 1984-2002  Mark Nudelman
  * All rights reserved.  
  *   *
  * Redistribution and use in source and binary forms, with or without   * You may distribute under the terms of either the GNU General Public
  * modification, are permitted provided that the following conditions   * License or the Less License, as specified in the README file.
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice in the documentation and/or other materials provided with  
  *    the distribution.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY   * For more information about less, or for information on how to
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   * contact the author, see the README file.
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE  
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */   */
   
   
Line 33 
Line 15 
  */   */
   
 #include "less.h"  #include "less.h"
 #if MSOFTC  #include "lglob.h"
   #if MSDOS_COMPILER
 #include <dos.h>  #include <dos.h>
   #if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER)
   #include <dir.h>
 #endif  #endif
   #if MSDOS_COMPILER==DJGPPC
   #include <glob.h>
   #include <dir.h>
   #define _MAX_PATH       PATH_MAX
   #endif
   #endif
   #ifdef _OSK
   #include <rbf.h>
   #ifndef _OSK_MWC32
   #include <modes.h>
   #endif
   #endif
   #if OS2
   #include <signal.h>
   #endif
   
   #if HAVE_STAT
   #include <sys/stat.h>
   #ifndef S_ISDIR
   #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
   #endif
   #ifndef S_ISREG
   #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
   #endif
   #endif
   
   
 extern int force_open;  extern int force_open;
   extern int secure;
   extern int use_lessopen;
 extern IFILE curr_ifile;  extern IFILE curr_ifile;
 extern IFILE old_ifile;  extern IFILE old_ifile;
   #if SPACES_IN_FILENAMES
   extern char openquote;
   extern char closequote;
   #endif
   
 /*  /*
    * Remove quotes around a filename.
    */
           public char *
   shell_unquote(str)
           char *str;
   {
           char *name;
           char *p;
   
           name = p = (char *) ecalloc(strlen(str)+1, sizeof(char));
           if (*str == openquote)
           {
                   str++;
                   while (*str != '\0')
                   {
                           if (*str == closequote)
                           {
                                   if (str[1] != closequote)
                                           break;
                                   str++;
                           }
                           *p++ = *str++;
                   }
           } else
           {
                   char *esc = get_meta_escape();
                   int esclen = strlen(esc);
                   while (*str != '\0')
                   {
                           if (esclen > 0 && strncmp(str, esc, esclen) == 0)
                                   str += esclen;
                           *p++ = *str++;
                   }
           }
           *p = '\0';
           return (name);
   }
   
   /*
    * Get the shell's escape character.
    */
           public char *
   get_meta_escape()
   {
           char *s;
   
           s = lgetenv("LESSMETAESCAPE");
           if (s == NULL)
                   s = DEF_METAESCAPE;
           return (s);
   }
   
   /*
    * Get the characters which the shell considers to be "metacharacters".
    */
           static char *
   metachars()
   {
           static char *mchars = NULL;
   
           if (mchars == NULL)
           {
                   mchars = lgetenv("LESSMETACHARS");
                   if (mchars == NULL)
                           mchars = DEF_METACHARS;
           }
           return (mchars);
   }
   
   /*
    * Is this a shell metacharacter?
    */
           static int
   metachar(c)
           char c;
   {
           return (strchr(metachars(), c) != NULL);
   }
   
   /*
    * Insert a backslash before each metacharacter in a string.
    */
           public char *
   shell_quote(s)
           char *s;
   {
           char *p;
           char *newstr;
           int len;
           char *esc = get_meta_escape();
           int esclen = strlen(esc);
           int use_quotes = 0;
           int have_quotes = 0;
   
           /*
            * Determine how big a string we need to allocate.
            */
           len = 1; /* Trailing null byte */
           for (p = s;  *p != '\0';  p++)
           {
                   len++;
                   if (*p == openquote || *p == closequote)
                           have_quotes = 1;
                   if (metachar(*p))
                   {
                           if (esclen == 0)
                           {
                                   /*
                                    * We've got a metachar, but this shell
                                    * doesn't support escape chars.  Use quotes.
                                    */
                                   use_quotes = 1;
                           } else
                           {
                                   /*
                                    * Allow space for the escape char.
                                    */
                                   len += esclen;
                           }
                   }
           }
           if (use_quotes)
           {
                   if (have_quotes)
                           /*
                            * We can't quote a string that contains quotes.
                            */
                           return (NULL);
                   len = strlen(s) + 3;
           }
           /*
            * Allocate and construct the new string.
            */
           newstr = p = (char *) ecalloc(len, sizeof(char));
           if (use_quotes)
           {
                   snprintf(newstr, len, "%c%s%c", openquote, s, closequote);
           } else
           {
                   while (*s != '\0')
                   {
                           if (metachar(*s))
                           {
                                   /*
                                    * Add the escape char.
                                    */
                                   strlcpy(p, esc, newstr + len - p);
                                   p += esclen;
                           }
                           *p++ = *s++;
                   }
                   *p = '\0';
           }
           return (newstr);
   }
   
   /*
  * Return a pathname that points to a specified file in a specified directory.   * Return a pathname that points to a specified file in a specified directory.
  * Return NULL if the file does not exist in the directory.   * Return NULL if the file does not exist in the directory.
  */   */
Line 51 
Line 225 
         char *filename;          char *filename;
 {  {
         char *pathname;          char *pathname;
         int f, len;          char *qpathname;
           int f;
           size_t len;
   
         if (dirname == NULL || *dirname == '\0')          if (dirname == NULL || *dirname == '\0')
                 return (NULL);                  return (NULL);
Line 62 
Line 238 
         pathname = (char *) calloc(len, sizeof(char));          pathname = (char *) calloc(len, sizeof(char));
         if (pathname == NULL)          if (pathname == NULL)
                 return (NULL);                  return (NULL);
 #if MSOFTC || OS2          snprintf(pathname, len, "%s%s%s", dirname, PATHNAME_SEP, filename);
         snprintf(pathname, len, "%s\\%s", dirname, filename);  
 #else  
         snprintf(pathname, len, "%s/%s", dirname, filename);  
 #endif  
         /*          /*
          * Make sure the file exists.           * Make sure the file exists.
          */           */
         f = open(pathname, OPEN_READ);          qpathname = shell_unquote(pathname);
           f = open(qpathname, OPEN_READ);
         if (f < 0)          if (f < 0)
         {          {
                 free(pathname);                  free(pathname);
                 pathname = NULL;                  pathname = NULL;
         } else          } else
         {          {
                 close (f);                  close(f);
         }          }
           free(qpathname);
         return (pathname);          return (pathname);
 }  }
   
Line 89 
Line 263 
 homefile(filename)  homefile(filename)
         char *filename;          char *filename;
 {  {
         char *pathname;          register char *pathname;
   
         /*          /*
          * Try $HOME/filename.           * Try $HOME/filename.
          */           */
         pathname = dirfile(getenv("HOME"), filename);          pathname = dirfile(lgetenv("HOME"), filename);
         if (pathname != NULL)          if (pathname != NULL)
                 return (pathname);                  return (pathname);
 #if OS2  #if OS2
         /*          /*
          * Try $INIT/filename.           * Try $INIT/filename.
          */           */
         pathname = dirfile(getenv("INIT"), filename);          pathname = dirfile(lgetenv("INIT"), filename);
         if (pathname != NULL)          if (pathname != NULL)
                 return (pathname);                  return (pathname);
 #endif  #endif
 #if MSOFTC || OS2  #if MSDOS_COMPILER || OS2
         /*          /*
          * Look for the file anywhere on search path.           * Look for the file anywhere on search path.
          */           */
         pathname = (char *) calloc(_MAX_PATH, sizeof(char));          pathname = (char *) calloc(_MAX_PATH, sizeof(char));
   #if MSDOS_COMPILER==DJGPPC
           {
                   char *res = searchpath(filename);
                   if (res == 0)
                           *pathname = '\0';
                   else
                           strlcpy(pathname, res, _MAX_PATH);
           }
   #else
         _searchenv(filename, "PATH", pathname);          _searchenv(filename, "PATH", pathname);
   #endif
         if (*pathname != '\0')          if (*pathname != '\0')
                 return (pathname);                  return (pathname);
         free(pathname);          free(pathname);
Line 119 
Line 303 
 }  }
   
 /*  /*
  * Find out where the help file is.  
  */  
         public char *  
 find_helpfile()  
 {  
         char *helpfile;  
   
         if ((helpfile = getenv("LESSHELP")) != NULL)  
                 return (save(helpfile));  
 #if MSOFTC || OS2  
         return (homefile(HELPFILE));  
 #else  
         return (save(HELPFILE));  
 #endif  
 }  
   
 /*  
  * Expand a string, substituting any "%" with the current filename,   * Expand a string, substituting any "%" with the current filename,
  * and any "#" with the previous filename.   * and any "#" with the previous filename.
    * But a string of N "%"s is just replaced with N-1 "%"s.
    * Likewise for a string of N "#"s.
  * {{ This is a lot of work just to support % and #. }}   * {{ This is a lot of work just to support % and #. }}
  */   */
         public char *          public char *
 fexpand(s)  fexpand(s)
         char *s;          char *s;
 {  {
         char *fr, *to;          register char *fr, *to;
         int n;          register int n;
         char *e;          register char *e;
           IFILE ifile;
   
   #define fchar_ifile(c) \
           ((c) == '%' ? curr_ifile : \
            (c) == '#' ? old_ifile : NULL_IFILE)
   
         /*          /*
          * Make one pass to see how big a buffer we           * Make one pass to see how big a buffer we
          * need to allocate for the expanded string.           * need to allocate for the expanded string.
Line 158 
Line 332 
                 switch (*fr)                  switch (*fr)
                 {                  {
                 case '%':                  case '%':
                         if (curr_ifile == NULL_IFILE)  
                         {  
                                 /* error("No current file", NULL_PARG); */  
                                 return (save(s));  
                         }  
                         n += strlen(get_filename(curr_ifile));  
                         break;  
                 case '#':                  case '#':
                         if (old_ifile == NULL_IFILE)                          if (fr > s && fr[-1] == *fr)
                         {                          {
                                 /* error("No previous file", NULL_PARG); */                                  /*
                                 return (save(s));                                   * Second (or later) char in a string
                                    * of identical chars.  Treat as normal.
                                    */
                                   n++;
                           } else if (fr[1] != *fr)
                           {
                                   /*
                                    * Single char (not repeated).  Treat specially.
                                    */
                                   ifile = fchar_ifile(*fr);
                                   if (ifile == NULL_IFILE)
                                           n++;
                                   else
                                           n += strlen(get_filename(ifile));
                         }                          }
                         n += strlen(get_filename(old_ifile));                          /*
                            * Else it is the first char in a string of
                            * identical chars.  Just discard it.
                            */
                         break;                          break;
                 default:                  default:
                         n++;                          n++;
Line 190 
Line 373 
                 switch (*fr)                  switch (*fr)
                 {                  {
                 case '%':                  case '%':
                         strlcpy(to, get_filename(curr_ifile), e + n + 1 - to);  
                         to += strlen(to);  
                         break;  
                 case '#':                  case '#':
                         strlcpy(to, get_filename(old_ifile), e + n + 1 - to);                          if (fr > s && fr[-1] == *fr)
                         to += strlen(to);                          {
                                   *to++ = *fr;
                           } else if (fr[1] != *fr)
                           {
                                   ifile = fchar_ifile(*fr);
                                   if (ifile == NULL_IFILE)
                                           *to++ = *fr;
                                   else
                                   {
                                           strlcpy(to, get_filename(ifile),
                                               e + n + 1 - to);
                                           to += strlen(to);
                                   }
                           }
                         break;                          break;
                 default:                  default:
                         *to++ = *fr;                          *to++ = *fr;
Line 217 
Line 410 
         char *s;          char *s;
 {  {
         char *fpat;          char *fpat;
         size_t l;          char *qs;
           size_t len;
   
           if (secure)
                   return (NULL);
         /*          /*
          * Complete the filename "s" by globbing "s*".           * Complete the filename "s" by globbing "s*".
          */           */
 #if MSOFTC  #if MSDOS_COMPILER && (MSDOS_COMPILER == MSOFTC || MSDOS_COMPILER == BORLANDC)
         /*          /*
          * But in DOS, we have to glob "s*.*".           * But in DOS, we have to glob "s*.*".
          * But if the final component of the filename already has           * But if the final component of the filename already has
Line 230 
Line 426 
          * (Thus, "FILE" is globbed as "FILE*.*",           * (Thus, "FILE" is globbed as "FILE*.*",
          *  but "FILE.A" is globbed as "FILE.A*").           *  but "FILE.A" is globbed as "FILE.A*").
          */           */
         char *slash;          {
         for (slash = s+strlen(s)-1;  slash > s;  slash--)                  char *slash;
                 if (*slash == '/' || *slash == '\\')                  for (slash = s+strlen(s)-1;  slash > s;  slash--)
                         break;                          if (*slash == *PATHNAME_SEP || *slash == '/')
         l = strlen(s)+4;                                  break;
         fpat = (char *) ecalloc(l, sizeof(char));                  len = strlen(s) + 4;
         if (strchr(slash, '.') == NULL)                  fpat = (char *) ecalloc(len, sizeof(char));
                 snprintf(fpat, l, "%s*.*", s);                  if (strchr(slash, '.') == NULL)
         else                          snprintf(fpat, len, "%s*.*", s);
                 snprintf(fpat, l, "%s*", s);                  else
                           snprintf(fpat, len, "%s*", s);
           }
 #else  #else
         l = strlen(s)+2;          len = strlen(s) + 2;
         fpat = (char *) ecalloc(l, sizeof(char));          fpat = (char *) ecalloc(len, sizeof(char));
         snprintf(fpat, l, "%s*", s);          snprintf(fpat, len, "%s*", s);
 #endif  #endif
         s = glob(fpat);          qs = lglob(fpat);
           s = shell_unquote(qs);
         if (strcmp(s,fpat) == 0)          if (strcmp(s,fpat) == 0)
         {          {
                 /*                  /*
                  * The filename didn't expand.                   * The filename didn't expand.
                  */                   */
                 free(s);                  free(qs);
                 s = NULL;                  qs = NULL;
         }          }
           free(s);
         free(fpat);          free(fpat);
         return (s);          return (qs);
 }  }
 #endif  #endif
   
Line 297 
Line 497 
         return ((POSITION) spos);          return ((POSITION) spos);
 }  }
   
 #if GLOB  
   
 FILE *popen();  
   
 /*  /*
  * Read a string from a file.   * Read a string from a file.
  * Return a pointer to the string in memory.   * Return a pointer to the string in memory.
Line 344 
Line 540 
         return (buf);          return (buf);
 }  }
   
   
   
   #if HAVE_POPEN
   
   FILE *popen();
   
 /*  /*
  * Execute a shell command.   * Execute a shell command.
  * Return a pointer to a pipe connected to the shell command's standard output.   * Return a pointer to a pipe connected to the shell command's standard output.
  */   */
         static FILE *          static FILE *
 shellcmd(cmd, s1, s2)  shellcmd(cmd)
         char *cmd;          char *cmd;
         char *s1;  
         char *s2;  
 {  {
         char *scmd;  
         char *scmd2;  
         char *shell;  
         FILE *fd;          FILE *fd;
         int len;          size_t len;
   
         len = strlen(cmd) +  
                 (s1 == NULL ? 0 : strlen(s1)) +  
                 (s2 == NULL ? 0 : strlen(s2)) + 1;  
         scmd = (char *) ecalloc(len, sizeof(char));  
         snprintf(scmd, len, cmd, s1, s2);  
 #if HAVE_SHELL  #if HAVE_SHELL
         shell = getenv("SHELL");          char *shell;
   
           shell = lgetenv("SHELL");
         if (shell != NULL && *shell != '\0')          if (shell != NULL && *shell != '\0')
         {          {
                   char *scmd;
                   char *esccmd;
   
                 /*                  /*
                  * Read the output of <$SHELL -c "cmd">.                   * Read the output of <$SHELL -c cmd>.
                    * Escape any metacharacters in the command.
                  */                   */
                 len = strlen(shell) + strlen(scmd) + 7;                  esccmd = shell_quote(cmd);
                 scmd2 = (char *) ecalloc(len, sizeof(char));                  if (esccmd == NULL)
                 snprintf(scmd2, len, "%s -c \"%s\"", shell, scmd);                  {
                 free(scmd);                          fd = popen(cmd, "r");
                 scmd = scmd2;                  } else
         }                  {
                           len = strlen(shell) + strlen(esccmd) + 5;
                           scmd = (char *) ecalloc(len, sizeof(char));
                           snprintf(scmd, len, "%s %s %s", shell, shell_coption(),
                               esccmd);
                           free(esccmd);
                           fd = popen(scmd, "r");
                           free(scmd);
                   }
           } else
 #endif  #endif
         fd = popen(scmd, "r");          {
         free(scmd);                  fd = popen(cmd, "r");
           }
           /*
            * Redirection in `popen' might have messed with the
            * standard devices.  Restore binary input mode.
            */
           SET_BINARY(0);
         return (fd);          return (fd);
 }  }
   
   #endif /* HAVE_POPEN */
   
   
 /*  /*
  * Expand a filename, doing any shell-level substitutions.   * Expand a filename, doing any system-specific metacharacter substitutions.
  */   */
         public char *          public char *
 glob(filename)  lglob(filename)
         char *filename;          char *filename;
 {  {
         char *gfilename;          char *gfilename;
           char *ofilename;
   
         filename = fexpand(filename);          ofilename = fexpand(filename);
 #if OS2          if (secure)
                   return (ofilename);
           filename = shell_unquote(ofilename);
   
   #ifdef DECL_GLOB_LIST
 {  {
         char **list;          /*
         int cnt;           * The globbing function returns a list of names.
            */
         int length;          int length;
           char *p;
           char *qfilename;
           DECL_GLOB_LIST(list)
   
         list = _fnexplode(filename);          GLOB_LIST(filename, list);
         if (list == NULL)          if (GLOB_LIST_FAILED(list))
                 return (filename);          {
         length = 0;                  free(filename);
         for (cnt = 0;  list[cnt] != NULL;  cnt++)                  return (ofilename);
                 length += strlen(list[cnt]) + 1;          }
           length = 1; /* Room for trailing null byte */
           for (SCAN_GLOB_LIST(list, p))
           {
                   INIT_GLOB_LIST(list, p);
                   qfilename = shell_quote(p);
                   if (qfilename != NULL)
                   {
                           length += strlen(qfilename) + 1;
                           free(qfilename);
                   }
           }
         gfilename = (char *) ecalloc(length, sizeof(char));          gfilename = (char *) ecalloc(length, sizeof(char));
         for (cnt = 0;  list[cnt] != NULL;  cnt++)          for (SCAN_GLOB_LIST(list, p))
         {          {
                 strlcat(gfilename, list[cnt], length);                  INIT_GLOB_LIST(list, p);
                 strlcat(gfilename, " ", length);                  qfilename = shell_quote(p);
                   if (qfilename != NULL)
                   {
                           snprintf(gfilename + strlen(gfilename),
                               length - strlen(gfilename), "%s ", qfilename);
                           free(qfilename);
                   }
         }          }
         _fnexplodefree(list);          /*
            * Overwrite the final trailing space with a null terminator.
            */
           *--p = '\0';
           GLOB_LIST_DONE(list);
 }  }
 #else  #else
   #ifdef DECL_GLOB_NAME
 {  {
         FILE *fd;          /*
            * The globbing function returns a single name, and
            * is called multiple times to walk thru all names.
            */
           register char *p;
           register int len;
           register int n;
           char *pathname;
           char *qpathname;
           DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle)
   
           GLOB_FIRST_NAME(filename, &fnd, handle);
           if (GLOB_FIRST_FAILED(handle))
           {
                   free(filename);
                   return (ofilename);
           }
   
           _splitpath(filename, drive, dir, fname, ext);
           len = 100;
           gfilename = (char *) ecalloc(len, sizeof(char));
           p = gfilename;
           do {
                   n = strlen(drive) + strlen(dir) + strlen(fnd.GLOB_NAME) + 1;
                   pathname = (char *) ecalloc(n, sizeof(char));
                   snprintf(pathname, n, "%s%s%s", drive, dir, fnd.GLOB_NAME);
                   qpathname = shell_quote(pathname);
                   free(pathname);
                   if (qpathname != NULL)
                   {
                           n = strlen(qpathname);
                           while (p - gfilename + n + 2 >= len)
                           {
                                   /*
                                    * No room in current buffer.
                                    * Allocate a bigger one.
                                    */
                                   len *= 2;
                                   *p = '\0';
                                   p = (char *) ecalloc(len, sizeof(char));
                                   strlcpy(p, gfilename, len);
                                   free(gfilename);
                                   gfilename = p;
                                   p = gfilename + strlen(gfilename);
                           }
                           strlcpy(p, qpathname, gfilename + len - p);
                           free(qpathname);
                           p += n;
                           *p++ = ' ';
                   }
           } while (GLOB_NEXT_NAME(handle, &fnd) == 0);
   
         /*          /*
          * We get the shell to expand the filename for us by passing           * Overwrite the final trailing space with a null terminator.
            */
           *--p = '\0';
           GLOB_NAME_DONE(handle);
   }
   #else
   #if HAVE_POPEN
   {
           /*
            * We get the shell to glob the filename for us by passing
          * an "echo" command to the shell and reading its output.           * an "echo" command to the shell and reading its output.
          */           */
         fd = shellcmd("echo %s", filename, (char*)NULL);          FILE *fd;
           char *s;
           char *lessecho;
           char *cmd;
           char *esc;
           size_t len;
   
           esc = get_meta_escape();
           if (strlen(esc) == 0)
                   esc = "-";
           esc = shell_quote(esc);
           if (esc == NULL)
           {
                   free(filename);
                   return (ofilename);
           }
           lessecho = lgetenv("LESSECHO");
           if (lessecho == NULL || *lessecho == '\0')
                   lessecho = "lessecho";
           /*
            * Invoke lessecho, and read its output (a globbed list of filenames).
            */
           len = strlen(lessecho) + strlen(ofilename) + (7*strlen(metachars())) + 24;
           cmd = (char *) ecalloc(len, sizeof(char));
           snprintf(cmd, len, "%s -p0x%x -d0x%x -e%s ", lessecho, openquote,
               closequote, esc);
           free(esc);
           for (s = metachars();  *s != '\0';  s++)
                   snprintf(cmd + strlen(cmd), len - strlen(cmd), "-n0x%x ", *s);
           snprintf(cmd + strlen(cmd), len - strlen(cmd), "-- %s", ofilename);
           fd = shellcmd(cmd);
           free(cmd);
         if (fd == NULL)          if (fd == NULL)
         {          {
                 /*                  /*
                  * Cannot create the pipe.                   * Cannot create the pipe.
                  * Just return the original (fexpanded) filename.                   * Just return the original (fexpanded) filename.
                  */                   */
                 return (filename);                  free(filename);
                   return (ofilename);
         }          }
         gfilename = readfd(fd);          gfilename = readfd(fd);
         pclose(fd);          pclose(fd);
         if (*gfilename == '\0')          if (*gfilename == '\0')
         {          {
                 free(gfilename);                  free(gfilename);
                 return (filename);                  free(filename);
                   return (ofilename);
         }          }
         free(filename);  
 }  }
   #else
           /*
            * No globbing functions at all.  Just use the fexpanded filename.
            */
           gfilename = save(filename);
 #endif  #endif
   #endif
   #endif
           free(filename);
           free(ofilename);
         return (gfilename);          return (gfilename);
 }  }
   
Line 454 
Line 801 
         int *pf;          int *pf;
         void **pfd;          void **pfd;
 {  {
   #if !HAVE_POPEN
           return (NULL);
   #else
         char *lessopen;          char *lessopen;
         char *gfilename;          char *cmd;
         int returnfd = 0;  
         FILE *fd;          FILE *fd;
           size_t len;
   #if HAVE_FILENO
           int returnfd = 0;
   #endif
   
           if (!use_lessopen || secure)
                   return (NULL);
         ch_ungetchar(-1);          ch_ungetchar(-1);
         if ((lessopen = getenv("LESSOPEN")) == NULL)          if ((lessopen = lgetenv("LESSOPEN")) == NULL)
                 return (NULL);                  return (NULL);
         if (strcmp(filename, "-") == 0)          if (strcmp(filename, "-") == 0)
                 return (NULL);                  return (NULL);
Line 470 
Line 825 
                  * If LESSOPEN starts with a |, it indicates                   * If LESSOPEN starts with a |, it indicates
                  * a "pipe preprocessor".                   * a "pipe preprocessor".
                  */                   */
   #if HAVE_FILENO
                 lessopen++;                  lessopen++;
                 returnfd = 1;                  returnfd = 1;
   #else
                   error("LESSOPEN pipe is not supported", NULL_PARG);
                   return (NULL);
   #endif
         }          }
         fd = shellcmd(lessopen, filename, (char*)NULL);  
           len = strlen(lessopen) + strlen(filename) + 2;
           cmd = (char *) ecalloc(len, sizeof(char));
           snprintf(cmd, len, lessopen, filename);
           fd = shellcmd(cmd);
           free(cmd);
         if (fd == NULL)          if (fd == NULL)
         {          {
                 /*                  /*
Line 481 
Line 846 
                  */                   */
                 return (NULL);                  return (NULL);
         }          }
   #if HAVE_FILENO
         if (returnfd)          if (returnfd)
         {          {
 #if HAVE_FILENO  
                 int f;                  int f;
                 char c;                  char c;
   
Line 492 
Line 857 
                  * If it does, push the char back on the pipe.                   * If it does, push the char back on the pipe.
                  */                   */
                 f = fileno(fd);                  f = fileno(fd);
                   SET_BINARY(f);
                 if (read(f, &c, 1) != 1)                  if (read(f, &c, 1) != 1)
                 {                  {
                         /*                          /*
Line 504 
Line 870 
                 *pfd = (void *) fd;                  *pfd = (void *) fd;
                 *pf = f;                  *pf = f;
                 return (save("-"));                  return (save("-"));
 #else  
                 error("LESSOPEN pipe is not supported", NULL_PARG);  
                 return (NULL);  
 #endif  
         }          }
         gfilename = readfd(fd);  #endif
           cmd = readfd(fd);
         pclose(fd);          pclose(fd);
         if (*gfilename == '\0')          if (*cmd == '\0')
                 /*                  /*
                  * Pipe is empty.  This means there is no alt file.                   * Pipe is empty.  This means there is no alt file.
                  */                   */
                 return (NULL);                  return (NULL);
         return (gfilename);          return (cmd);
   #endif /* HAVE_POPEN */
 }  }
   
 /*  /*
Line 528 
Line 892 
         char *filename;          char *filename;
         void *pipefd;          void *pipefd;
 {  {
   #if HAVE_POPEN
         char *lessclose;          char *lessclose;
         FILE *fd;          FILE *fd;
           char *cmd;
           size_t len;
   
           if (secure)
                   return;
         if (pipefd != NULL)          if (pipefd != NULL)
           {
   #if OS2
                   /*
                    * The pclose function of OS/2 emx sometimes fails.
                    * Send SIGINT to the piped process before closing it.
                    */
                   kill(((FILE*)pipefd)->_pid, SIGINT);
   #endif
                 pclose((FILE*) pipefd);                  pclose((FILE*) pipefd);
         if ((lessclose = getenv("LESSCLOSE")) == NULL)          }
           if ((lessclose = lgetenv("LESSCLOSE")) == NULL)
                 return;                  return;
         fd = shellcmd(lessclose, filename, altfilename);          len = strlen(lessclose) + strlen(filename) + strlen(altfilename) + 2;
         pclose(fd);          cmd = (char *) ecalloc(len, sizeof(char));
           snprintf(cmd, len, lessclose, filename, altfilename);
           fd = shellcmd(cmd);
           free(cmd);
           if (fd != NULL)
                   pclose(fd);
   #endif
 }  }
   
 #else  /*
 #if MSOFTC   * Is the specified file a directory?
    */
         public char *          public int
 glob(filename)  is_dir(filename)
         char *filename;          char *filename;
 {  {
         char *gfilename;          int isdir = 0;
         char *p;  
         int len;  
         int n;  
         struct find_t fnd;  
         char drive[_MAX_DRIVE];  
         char dir[_MAX_DIR];  
         char fname[_MAX_FNAME];  
         char ext[_MAX_EXT];  
   
         filename = fexpand(filename);  
         if (_dos_findfirst(filename, ~0, &fnd) != 0)  
                 return (filename);  
   
         _splitpath(filename, drive, dir, fname, ext);  
         len = 100;  
         gfilename = (char *) ecalloc(len, sizeof(char));  
         p = gfilename;  
         do {  
                 n = strlen(drive) + strlen(dir) + strlen(fnd.name);  
                 while (p - gfilename + n+2 >= len)  
                 {  
                         len *= 2;  
                         *p = '\0';  
                         p = (char *) ecalloc(len, sizeof(char));  
                         strlcpy(p, gfilename, len);  
                         free(gfilename);  
                         gfilename = p;  
                         p = gfilename + strlen(gfilename);  
                 }  
                 sprintf(p, "%s%s%s", drive, dir, fnd.name);  
                 p += n;  
                 *p++ = ' ';  
         } while (_dos_findnext(&fnd) == 0);  
   
         *--p = '\0';  
         return (gfilename);  
 }  
   
         public char *  
 open_altfile(filename)  
         char *filename;  
 {  
         return (NULL);  
 }  
   
         public void          filename = shell_unquote(filename);
 close_altfile(altfilename, filename)  #if HAVE_STAT
         char *altfilename;  
         char *filename;  
 {  {
           int r;
           struct stat statbuf;
   
           r = stat(filename, &statbuf);
           isdir = (r >= 0 && S_ISDIR(statbuf.st_mode));
 }  }
   
 #else  #else
   #ifdef _OSK
         public char *  
 glob(filename)  
         char *filename;  
 {  {
         return (fexpand(filename));          register int f;
 }  
   
           f = open(filename, S_IREAD | S_IFDIR);
         public char *          if (f >= 0)
 open_altfile(filename)                  close(f);
         char *filename;          isdir = (f >= 0);
 {  
         return (NULL);  
 }  }
   
         public void  
 close_altfile(altfilename, filename)  
         char *altfilename;  
         char *filename;  
 {  
 }  
   
 #endif  #endif
 #endif  #endif
           free(filename);
           return (isdir);
   }
   
   
 #if HAVE_STAT  
   
 #include <sys/stat.h>  
 #ifndef S_ISDIR  
 #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)  
 #endif  
 #ifndef S_ISREG  
 #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)  
 #endif  
   
 /*  /*
  * Returns NULL if the file can be opened and   * Returns NULL if the file can be opened and
  * is an ordinary file, otherwise an error message   * is an ordinary file, otherwise an error message
Line 646 
Line 966 
 bad_file(filename)  bad_file(filename)
         char *filename;          char *filename;
 {  {
         char *m;          register char *m = NULL;
         struct stat statbuf;          size_t len;
   
         if (stat(filename, &statbuf) < 0)          filename = shell_unquote(filename);
                 return (errno_message(filename));          if (is_dir(filename))
   
         if (force_open)  
                 return (NULL);  
   
         if (S_ISDIR(statbuf.st_mode))  
         {          {
                 static char is_dir[] = " is a directory";                  static char is_a_dir[] = " is a directory";
                 size_t len;  
   
                 len = strlen(filename) + sizeof(is_dir);                  len = strlen(filename) + sizeof(is_a_dir);
                 m = (char *) ecalloc(len, sizeof(char));                  m = (char *) ecalloc(len, sizeof(char));
                 strlcpy(m, filename, len);                  strlcpy(m, filename, len);
                 strlcat(m, is_dir, len);                  strlcat(m, is_a_dir, len);
                 return (m);          } else
         }  
         if (!S_ISREG(statbuf.st_mode))  
         {          {
                 static char not_reg[] = " is not a regular file";  #if HAVE_STAT
                 size_t len;                  int r;
                   struct stat statbuf;
   
                 len = strlen(filename) + sizeof(not_reg);                  r = stat(filename, &statbuf);
                 m = (char *) ecalloc(len, sizeof(char));                  if (r < 0)
                 strlcpy(m, filename, len);                  {
                 strlcat(m, not_reg, len);                          m = errno_message(filename);
                 return (m);                  } else if (force_open)
                   {
                           m = NULL;
                   } else if (!S_ISREG(statbuf.st_mode))
                   {
                           static char not_reg[] = " is not a regular file (use -f to see it)";
                           len = strlen(filename) + sizeof(not_reg);
                           m = (char *) ecalloc(len, sizeof(char));
                           strlcpy(m, filename, len);
                           strlcat(m, not_reg, len);
                   }
   #endif
         }          }
           free(filename);
         return (NULL);          return (m);
 }  }
   
 /*  /*
Line 689 
Line 1013 
 filesize(f)  filesize(f)
         int f;          int f;
 {  {
   #if HAVE_STAT
         struct stat statbuf;          struct stat statbuf;
   
         if (fstat(f, &statbuf) < 0)          if (fstat(f, &statbuf) >= 0)
                 /*                  return ((POSITION) statbuf.st_size);
                  * Can't stat; try seeking to the end.  #else
                  */  #ifdef _OSK
                 return (seek_filesize(f));          long size;
   
         return ((POSITION) statbuf.st_size);          if ((size = (long) _gs_size(f)) >= 0)
                   return ((POSITION) size);
   #endif
   #endif
           return (seek_filesize(f));
 }  }
   
 #else  
   
 /*  /*
  * If we have no way to find out, just say the file is good.   *
  */   */
         public char *          public char *
 bad_file(filename)  shell_coption()
         char *filename;  
 {  {
         return (NULL);          return ("-c");
 }  }
   
 /*  
  * We can find the file size by seeking.  
  */  
         public POSITION  
 filesize(f)  
         int f;  
 {  
         return (seek_filesize(f));  
 }  
   
 #endif  

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8