home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / filename.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  8KB  |  408 lines

  1. /*
  2.  * Routines to mess around with filenames (and files).
  3.  * Much of this is very OS dependent.
  4.  */
  5. #include <stdio.h>
  6. #include "less.h"
  7.  
  8. extern char *getenv();
  9. #if OS2
  10. #include <stdlib.h>
  11. #include <sys/param.h>
  12. #endif
  13.  
  14. extern int force_open;
  15. extern IFILE curr_ifile;
  16. extern IFILE old_ifile;
  17.  
  18. /*
  19.  * Return the full pathname of the given file in the "home directory".
  20.  */
  21.     public char *
  22. homefile(filename)
  23.     char *filename;
  24. {
  25.     register char *pathname;
  26.     register char *homedir;
  27.  
  28. #if OS2
  29.     static char *path[MAXPATHLEN + 1];
  30. #endif
  31.  
  32.     homedir = getenv("HOME");
  33. #if __MSDOS__
  34.     /*
  35.      * Most MSDOS users do not have $HOME defined,
  36.      * so if no $HOME then look for "_less" anywhere 
  37.      * on search path (always begins at current directory).
  38.      */
  39.     if (homedir == NULL)
  40.     {
  41.         extern char *searchpath();
  42.         pathname = searchpath(filename);
  43.         if (pathname == NULL)
  44.             return (NULL);
  45.         pathname = save(pathname);
  46.     } else
  47.     {
  48.         pathname = (char *) calloc(strlen(homedir)+strlen(filename)+2, 
  49.                     sizeof(char));
  50.         if (pathname == NULL)
  51.             return (NULL);
  52.         sprintf(pathname, "%s\\%s", homedir, filename);
  53.     }
  54. #else
  55. #if OS2
  56.     if (homedir == NULL)
  57.     {
  58.                 _searchenv(filename, "DPATH", (char *)path);
  59.             if (path != NULL)
  60.                     return (save(path));
  61.         else
  62.             return (NULL);
  63.     } else
  64.     {
  65.         pathname = (char *) calloc(strlen(homedir)+strlen(filename)+2, 
  66.                     sizeof(char));
  67.         if (pathname == NULL)
  68.             return (NULL);
  69.         sprintf(pathname, "%s\\%s", homedir, filename);
  70.     }
  71. #else
  72.     if (homedir == NULL)
  73.         return (NULL);
  74.     pathname = (char *) calloc(strlen(homedir)+strlen(filename)+2,
  75.                 sizeof(char));
  76.     if (pathname == NULL)
  77.         return (NULL);
  78.     sprintf(pathname, "%s/%s", homedir, filename);
  79. #endif
  80. #endif
  81.     return (pathname);
  82. }
  83.  
  84. /*
  85.  * Find out where the help file is.
  86.  */
  87.     public char *
  88. find_helpfile()
  89. {
  90.     register char *helpfile;
  91. #if OS2
  92.     static char *path[MAXPATHLEN + 1];
  93. #endif
  94. #if __MSDOS__
  95.     extern char *searchpath();
  96.  
  97.     /*
  98.      * Look in current directory.
  99.      */
  100.     if (access(HELPFILE,0) == 0)
  101.         return (HELPFILE);
  102.     /*
  103.      * Find the basename of HELPFILE,
  104.      * and look for it in each directory in the search path.
  105.      */
  106.     if ((helpfile = strrchr(HELPFILE, '\\')) == NULL)
  107.         helpfile = HELPFILE;
  108.     else
  109.         helpfile++;
  110.     return (save(searchpath(helpfile)));
  111. #else
  112.     if ((helpfile = getenv("LESSHELP")) != NULL)
  113.         return (save(helpfile));
  114. #if OS2
  115.         _searchenv(HELPFILE, "DPATH", (char *)path);
  116.     if (path != NULL)
  117.             return (save(path));
  118. #endif
  119.     return (save(HELPFILE));
  120. #endif
  121. }
  122.  
  123. /*
  124.  * Expand a string, substituting any "%" with the current filename,
  125.  * and any "#" with the previous filename.
  126.  */
  127.     public char *
  128. fexpand(s)
  129.     char *s;
  130. {
  131.     register char *fr, *to;
  132.     register int n;
  133.     register char *e;
  134.  
  135.     /*
  136.      * Make one pass to see how big a buffer we 
  137.      * need to allocate for the expanded string.
  138.      */
  139.     n = 0;
  140.     for (fr = s;  *fr != '\0';  fr++)
  141.     {
  142.         switch (*fr)
  143.         {
  144.         case '%':
  145.             n += strlen(get_filename(curr_ifile));
  146.             break;
  147.         case '#':
  148.             if (old_ifile == NULL_IFILE)
  149.             {
  150.                 error("No previous file", NULL_PARG);
  151.                 return (NULL);
  152.             }
  153.             n += strlen(get_filename(old_ifile));
  154.             break;
  155.         default:
  156.             n++;
  157.             break;
  158.         }
  159.     }
  160.  
  161.     e = (char *) ecalloc(n+1, sizeof(char));
  162.  
  163.     /*
  164.      * Now copy the string, expanding any "%" or "#".
  165.      */
  166.     to = e;
  167.     for (fr = s;  *fr != '\0';  fr++)
  168.     {
  169.         switch (*fr)
  170.         {
  171.         case '%':
  172.             strcpy(to, get_filename(curr_ifile));
  173.             to += strlen(to);
  174.             break;
  175.         case '#':
  176.             strcpy(to, get_filename(old_ifile));
  177.             to += strlen(to);
  178.             break;
  179.         default:
  180.             *to++ = *fr;
  181.             break;
  182.         }
  183.     }
  184.     *to = '\0';
  185.     return (e);
  186. }
  187.  
  188. /*
  189.  * Try to determine if a file is "binary".
  190.  * This is just a guess, and we need not try too hard to make it accurate.
  191.  */
  192.     int
  193. bin_file(f)
  194.     int f;
  195. {
  196.     int i;
  197.     int n;
  198.     char data[64];
  199.  
  200.     n = read(f, data, sizeof(data));
  201.     for (i = 0;  i < n;  i++)
  202.         if (binary_char(data[i]))
  203.             return (1);
  204.     return (0);
  205. }
  206.  
  207. /*
  208.  * Try to determine the size of a file by seeking to the end.
  209.  */
  210.     static POSITION
  211. seek_filesize(f)
  212.     int f;
  213. {
  214.     offset_t spos;
  215.  
  216.     spos = lseek(f, (offset_t)0, 2);
  217.     if (spos == BAD_LSEEK)
  218.         return (NULL_POSITION);
  219.     return ((POSITION) spos);
  220. }
  221.  
  222. /*
  223.  * Expand a filename, substituting any environment variables, etc.
  224.  */
  225. #if GLOB
  226.  
  227. FILE *popen();
  228.  
  229.     public char *
  230. glob(filename)
  231.     char *filename;
  232. {
  233.     FILE *f;
  234.     char *p;
  235.     int ch;
  236.     int len;
  237.     char *cmd;
  238.     char *gfilename;
  239.  
  240.     filename = fexpand(filename);
  241.     if (filename == NULL)
  242.         return (NULL);
  243.  
  244.     /*
  245.      * We get the shell to expand the filename for us by passing
  246.      * an "echo" command to the shell and reading its output.
  247.      */
  248. #if OS2
  249.         p = getenv("COMSPEC");
  250. #else
  251.     p = getenv("SHELL");
  252. #endif
  253.     if (p == NULL || *p == '\0')
  254.     {
  255.         /*
  256.          * Read the output of <echo filename>.
  257.          */
  258.         cmd = (char *) ecalloc(strlen(filename)+6, sizeof(char));
  259.         sprintf(cmd, "echo %s", filename);
  260.     } else
  261.     {
  262.         /*
  263.          * Read the output of <$SHELL -c "echo filename">.
  264.          */
  265. #if OS2
  266.         cmd = (char *) ecalloc(strlen(filename)+12, sizeof(char));
  267.         sprintf(cmd, "\"vecho %s\"", filename);
  268. #else
  269.         cmd = (char *) ecalloc(strlen(p)+strlen(filename)+12, sizeof(char));
  270.         sprintf(cmd, "%s -c \"echo %s\"", p, filename);
  271. #endif
  272.     }
  273.  
  274. #if OS2
  275.     f = popen(cmd, "rb");
  276. #else
  277.     f = popen(cmd, "r");
  278. #endif
  279.     free(cmd);
  280.     if (f == NULL)
  281.         return (filename);
  282.     free(filename);
  283.  
  284.     len = 100;
  285.     gfilename = (char *) ecalloc(len, sizeof(char));
  286.     for (p = gfilename;  ;  p++)
  287.     {
  288.         if ((ch = getc(f)) == '\n' || ch == EOF)
  289.             break;
  290.         if (p - gfilename >= len-1)
  291.         {
  292.             len *= 2;
  293.             *p = '\0';
  294.             p = (char *) ecalloc(len, sizeof(char));
  295.             strcpy(p, gfilename);
  296.             free(gfilename);
  297.             gfilename = p;
  298.             p = gfilename + strlen(gfilename);
  299.         }
  300.         *p = ch;
  301.     }
  302.     *p = '\0';
  303.     pclose(f);
  304.     if (*gfilename == '\0')
  305.         return (NULL);
  306.     return (gfilename);
  307. }
  308.  
  309. #else
  310.  
  311.     public char *
  312. glob(filename)
  313.     char *filename;
  314. {
  315.     return (fexpand(filename));
  316. }
  317.  
  318. #endif
  319.  
  320.  
  321. #if STAT
  322.  
  323. #include <sys/types.h>
  324. #include <sys/stat.h>
  325.  
  326. /*
  327.  * Returns NULL if the file can be opened and
  328.  * is an ordinary file, otherwise an error message
  329.  * (if it cannot be opened or is a directory, etc.)
  330.  */
  331.     public char *
  332. bad_file(filename)
  333.     char *filename;
  334. {
  335.     register char *m;
  336.     struct stat statbuf;
  337.  
  338.     if (stat(filename, &statbuf) < 0)
  339.         return (errno_message(filename));
  340.  
  341.     if (force_open)
  342.         return (NULL);
  343.  
  344.     if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  345.     {
  346.         static char is_dir[] = " is a directory";
  347.         m = (char *) ecalloc(strlen(filename) + sizeof(is_dir), 
  348.             sizeof(char));
  349.         strcpy(m, filename);
  350.         strcat(m, is_dir);
  351.         return (m);
  352.     }
  353.     if ((statbuf.st_mode & S_IFMT) != S_IFREG)
  354.     {
  355.         static char not_reg[] = " is not a regular file";
  356.         m = (char *) ecalloc(strlen(filename) + sizeof(not_reg), 
  357.             sizeof(char));
  358.         strcpy(m, filename);
  359.         strcat(m, not_reg);
  360.         return (m);
  361.     }
  362.  
  363.     return (NULL);
  364. }
  365.  
  366. /*
  367.  * Return the size of a file, as cheaply as possible.
  368.  * In Unix, we can stat the file.
  369.  */
  370.     public POSITION
  371. filesize(f)
  372.     int f;
  373. {
  374.     struct stat statbuf;
  375.  
  376.     if (fstat(f, &statbuf) < 0)
  377.         /*
  378.          * Can't stat; try seeking to the end.
  379.          */
  380.         return (seek_filesize(f));
  381.  
  382.     return ((POSITION) statbuf.st_size);
  383. }
  384.  
  385. #else
  386.  
  387. /*
  388.  * If we have no way to find out, just say the file is good.
  389.  */
  390.     public char *
  391. bad_file(filename)
  392.     char *filename;
  393. {
  394.     return (NULL);
  395. }
  396.  
  397. /*
  398.  * We can find the file size by seeking.
  399.  */
  400.     public POSITION
  401. filesize(f)
  402.     int f;
  403. {
  404.     return (seek_filesize(f));
  405. }
  406.  
  407. #endif
  408.