home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2995 / filename.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-06  |  6.1 KB  |  359 lines

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