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