home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less2912.zip / filename.c < prev    next >
C/C++ Source or Header  |  1995-11-09  |  16KB  |  784 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Routines to mess around with filenames (and files).
  30.  * Much of this is very OS dependent.
  31.  */
  32.  
  33. #include "less.h"
  34. #if MSOFTC
  35. #include <dos.h>
  36. #endif
  37.  
  38. extern int force_open;
  39. extern IFILE curr_ifile;
  40. extern IFILE old_ifile;
  41.  
  42. /*
  43.  * Return a pathname that points to a specified file in a specified directory.
  44.  * Return NULL if the file does not exist in the directory.
  45.  */
  46.     static char *
  47. dirfile(dirname, filename)
  48.     char *dirname;
  49.     char *filename;
  50. {
  51.     char *pathname;
  52.     int f;
  53.  
  54.     if (dirname == NULL || *dirname == '\0')
  55.         return (NULL);
  56.     /*
  57.      * Construct the full pathname.
  58.      */
  59.     pathname = (char *) calloc(strlen(dirname) + strlen(filename) + 2, 
  60.                     sizeof(char));
  61.     if (pathname == NULL)
  62.         return (NULL);
  63. #if MSOFTC || OS2
  64.     sprintf(pathname, "%s\\%s", dirname, filename);
  65. #else
  66.     sprintf(pathname, "%s/%s", dirname, filename);
  67. #endif
  68.     /*
  69.      * Make sure the file exists.
  70.      */
  71.     f = open(pathname, OPEN_READ);
  72.     if (f < 0)
  73.     {
  74.         free(pathname);
  75.         pathname = NULL;
  76.     } else
  77.     {
  78.         close (f);
  79.     }
  80.     return (pathname);
  81. }
  82.  
  83. /*
  84.  * Return the full pathname of the given file in the "home directory".
  85.  */
  86.     public char *
  87. homefile(filename)
  88.     char *filename;
  89. {
  90.     register char *pathname;
  91.  
  92.     /*
  93.      * Try $HOME/filename.
  94.      */
  95.     pathname = dirfile(lgetenv("HOME"), filename);
  96.     if (pathname != NULL)
  97.         return (pathname);
  98. #if OS2
  99.     /*
  100.      * Try $INIT/filename.
  101.      */
  102.     pathname = dirfile(lgetenv("INIT"), filename);
  103.     if (pathname != NULL)
  104.         return (pathname);
  105. #endif
  106. #if MSOFTC || OS2
  107.     /*
  108.      * Look for the file anywhere on search path.
  109.      */
  110.     pathname = (char *) calloc(_MAX_PATH, sizeof(char));
  111.     _searchenv(filename, "PATH", pathname);
  112.     if (*pathname != '\0')
  113.         return (pathname);
  114.     free(pathname);
  115. #endif
  116.     return (NULL);
  117. }
  118.  
  119. /*
  120.  * Find out where the help file is.
  121.  */
  122.     public char *
  123. find_helpfile()
  124. {
  125.     register char *helpfile;
  126.     
  127.     if ((helpfile = lgetenv("LESSHELP")) != NULL)
  128.         return (save(helpfile));
  129. #if MSOFTC || OS2
  130.     return (homefile(HELPFILE));
  131. #else
  132.     return (save(HELPFILE));
  133. #endif
  134. }
  135.  
  136. /*
  137.  * Expand a string, substituting any single "%" with the current filename,
  138.  * and any single "#" with the previous filename.
  139.  * "#" and "%" are self quoting.  Any sequence of 2 or more of them
  140.  * inserts the sequence - 1 of "%" or "#" chars into the command line.
  141.  * {{ This is a lot of work just to support % and #. }}
  142.  */
  143.     public char *
  144. fexpand(s)
  145.     char *s;
  146. {
  147.     register char *fr, *to;
  148.     register int n;
  149.     register char *e;
  150.     int percent_quote = FALSE;  /* Set initial state of machine to */      
  151.     int hash_quote = FALSE;     /* no sequence in progress. */
  152.  
  153.     /*
  154.      * Make one pass to see how big a buffer we 
  155.      * need to allocate for the expanded string.
  156.      */
  157.     /*
  158.      * The self quoting system is a state machine.  We look ahead
  159.      * one character to put ourselves into one or the other self
  160.      * quote states, and when we get a different character, we
  161.      * turn the previous quote state off.  We count and later
  162.      * insert, 1 less than the actual sequence of special
  163.      * characters into the output buffer, if there is a sequence.
  164.      * If there is a file error condition, we no longer bug out,
  165.      * we just do not count the unexpanded character or place it
  166.      * in the output buffer and we continue to check the rest of
  167.      * the string for single "%" or "#"s to expand or sequences to
  168.      * insert.  
  169.      */
  170.     n = 0;
  171.     for (fr = s;  *fr != '\0';  fr++)
  172.     {
  173.         switch (*fr)
  174.         {
  175.         case '%':
  176.                 if (hash_quote)
  177.                     hash_quote = FALSE;
  178.                 if (*(fr+1) == '%' || percent_quote)
  179.             {
  180.                     if (!percent_quote)
  181.                         percent_quote = TRUE;
  182.                 else
  183.                         n++;
  184.             }
  185.             else if (curr_ifile != NULL_IFILE)
  186.             n += strlen(get_filename(curr_ifile));
  187.             break;
  188.         case '#':
  189.             if (percent_quote)
  190.                     percent_quote = FALSE;
  191.                 if (*(fr+1) == '#' || hash_quote)
  192.             {
  193.                     if (!hash_quote)
  194.                         hash_quote = TRUE;
  195.                 else
  196.                         n++;
  197.             }
  198.             else if (old_ifile != NULL_IFILE)
  199.             n += strlen(get_filename(old_ifile));
  200.             break;
  201.         default:
  202.             n++;
  203.             if (percent_quote || hash_quote)
  204.             {
  205.                      percent_quote = FALSE;
  206.                      hash_quote = FALSE;
  207.             }
  208.             break;
  209.         }
  210.     }
  211.  
  212.     e = (char *) ecalloc(n+1, sizeof(char));
  213.  
  214.     /*
  215.      * Now copy the string, expanding any "%" or "#".
  216.      */
  217.     to = e;
  218.     /*
  219.      * Reset the state machine in case we ended on a sequence 
  220.      * of "%" or "#" characters.
  221.      */
  222.     percent_quote = FALSE;
  223.     hash_quote = FALSE;
  224.     for (fr = s;  *fr != '\0';  fr++)
  225.     {
  226.         switch (*fr)
  227.         {
  228.         case '%':
  229.             if (hash_quote)
  230.                     hash_quote = FALSE;
  231.                 if (*(fr+1) == '%' || percent_quote)
  232.             {
  233.                     if (!percent_quote)
  234.                         percent_quote = TRUE;
  235.                 else
  236.                         *to++ = *fr;
  237.             }                       
  238.             else if (curr_ifile != NULL_IFILE)
  239.                 {
  240.             strcpy(to, get_filename(curr_ifile));
  241.             to += strlen(to);
  242.             }
  243.             break;
  244.         case '#':
  245.             if (percent_quote)
  246.                     percent_quote = FALSE;
  247.                 if (*(fr+1) == '#' || hash_quote)
  248.             {
  249.                     if (!hash_quote)
  250.                         hash_quote = TRUE;
  251.                 else
  252.                         *to++ = *fr;
  253.             }                       
  254.             else if (old_ifile != NULL_IFILE)
  255.             {
  256.             strcpy(to, get_filename(old_ifile));
  257.             to += strlen(to);
  258.             }
  259.             break;
  260.         default:
  261.             *to++ = *fr;
  262.             if (percent_quote || hash_quote)
  263.             {
  264.                      percent_quote = FALSE;
  265.                      hash_quote = FALSE;
  266.             }
  267.             break;
  268.         }
  269.     }
  270.     *to = '\0';
  271.     return (e);
  272. }
  273.  
  274. #if TAB_COMPLETE_FILENAME
  275.  
  276. /*
  277.  * Return a blank-separated list of filenames which "complete"
  278.  * the given string.
  279.  */
  280.     public char *
  281. fcomplete(s)
  282.     char *s;
  283. {
  284.     char *fpat;
  285.     /*
  286.      * Complete the filename "s" by globbing "s*".
  287.      */
  288. #if MSOFTC
  289.     /*
  290.      * But in DOS, we have to glob "s*.*".
  291.      * But if the final component of the filename already has
  292.      * a dot in it, just do "s*".  
  293.      * (Thus, "FILE" is globbed as "FILE*.*", 
  294.      *  but "FILE.A" is globbed as "FILE.A*").
  295.      */
  296.     char *slash;
  297.     for (slash = s+strlen(s)-1;  slash > s;  slash--)
  298.         if (*slash == '/' || *slash == '\\')
  299.             break;
  300.     fpat = (char *) ecalloc(strlen(s)+4, sizeof(char));
  301.     if (strchr(slash, '.') == NULL)
  302.         sprintf(fpat, "%s*.*", s);
  303.     else
  304.         sprintf(fpat, "%s*", s);
  305. #else
  306.     fpat = (char *) ecalloc(strlen(s)+2, sizeof(char));
  307.     sprintf(fpat, "%s*", s);
  308. #endif
  309.     s = glob(fpat);
  310.     if (strcmp(s,fpat) == 0)
  311.     {
  312.         /*
  313.          * The filename didn't expand.
  314.          */
  315.         free(s);
  316.         s = NULL;
  317.     }
  318.     free(fpat);
  319.     return (s);
  320. }
  321. #endif
  322.  
  323. /*
  324.  * Try to determine if a file is "binary".
  325.  * This is just a guess, and we need not try too hard to make it accurate.
  326.  */
  327.     public int
  328. bin_file(f)
  329.     int f;
  330. {
  331.     int i;
  332.     int n;
  333.     unsigned char data[64];
  334.  
  335.     if (!seekable(f))
  336.         return (0);
  337.     if (lseek(f, (off_t)0, 0) == BAD_LSEEK)
  338.         return (0);
  339.     n = read(f, data, sizeof(data));
  340.     for (i = 0;  i < n;  i++)
  341.         if (binary_char(data[i]))
  342.             return (1);
  343.     return (0);
  344. }
  345.  
  346. /*
  347.  * Try to determine the size of a file by seeking to the end.
  348.  */
  349.     static POSITION
  350. seek_filesize(f)
  351.     int f;
  352. {
  353.     off_t spos;
  354.  
  355.     spos = lseek(f, (off_t)0, 2);
  356.     if (spos == BAD_LSEEK)
  357.         return (NULL_POSITION);
  358.     return ((POSITION) spos);
  359. }
  360.  
  361. #if GLOB
  362.  
  363. FILE *popen();
  364.  
  365. /*
  366.  * Read a string from a file.
  367.  * Return a pointer to the string in memory.
  368.  */
  369.     static char *
  370. readfd(fd)
  371.     FILE *fd;
  372. {
  373.     int len;
  374.     int ch;
  375.     char *buf;
  376.     char *p;
  377.     
  378.     /* 
  379.      * Make a guess about how many chars in the string
  380.      * and allocate a buffer to hold it.
  381.      */
  382.     len = 100;
  383.     buf = (char *) ecalloc(len, sizeof(char));
  384.     for (p = buf;  ;  p++)
  385.     {
  386.         if ((ch = getc(fd)) == '\n' || ch == EOF)
  387.             break;
  388.         if (p - buf >= len-1)
  389.         {
  390.             /*
  391.              * The string is too big to fit in the buffer we have.
  392.              * Allocate a new buffer, twice as big.
  393.              */
  394.             len *= 2;
  395.             *p = '\0';
  396.             p = (char *) ecalloc(len, sizeof(char));
  397.             strcpy(p, buf);
  398.             free(buf);
  399.             buf = p;
  400.             p = buf + strlen(buf);
  401.         }
  402.         *p = ch;
  403.     }
  404.     *p = '\0';
  405.     return (buf);
  406. }
  407.  
  408. /*
  409.  * Execute a shell command.
  410.  * Return a pointer to a pipe connected to the shell command's standard output.
  411.  */
  412.     static FILE *
  413. shellcmd(cmd, s1, s2)
  414.     char *cmd;
  415.     char *s1;
  416.     char *s2;
  417. {
  418.     char *scmd;
  419.     char *scmd2;
  420.     char *shell;
  421.     FILE *fd;
  422.     int len;
  423.     
  424.     len = strlen(cmd) + 
  425.         (s1 == NULL ? 0 : strlen(s1)) + 
  426.         (s2 == NULL ? 0 : strlen(s2)) + 1;
  427.     scmd = (char *) ecalloc(len, sizeof(char));
  428.     sprintf(scmd, cmd, s1, s2);
  429. #if HAVE_SHELL
  430.     shell = lgetenv("SHELL");
  431.     if (shell != NULL && *shell != '\0')
  432.     {
  433.         /*
  434.          * Read the output of <$SHELL -c "cmd">.
  435.          */
  436.         scmd2 = (char *) ecalloc(strlen(shell) + strlen(scmd) + 7,
  437.                     sizeof(char));
  438.         sprintf(scmd2, "%s -c \"%s\"", shell, scmd);
  439.         free(scmd);
  440.         scmd = scmd2;
  441.     }
  442. #endif
  443.     fd = popen(scmd, "r");
  444.     free(scmd);
  445.     return (fd);
  446. }
  447.  
  448. /*
  449.  * Expand a filename, doing any shell-level substitutions.
  450.  */
  451.     public char *
  452. glob(filename)
  453.     char *filename;
  454. {
  455.     char *gfilename;
  456.  
  457.     filename = fexpand(filename);
  458. #if OS2
  459. {
  460.     char **list;
  461.     int cnt;
  462.     int length;
  463.  
  464.     list = _fnexplode(filename);
  465.     if (list == NULL)
  466.         return (filename);
  467.     length = 0;
  468.     for (cnt = 0;  list[cnt] != NULL;  cnt++)
  469.           length += strlen(list[cnt]) + 1;
  470.     gfilename = (char *) ecalloc(length, sizeof(char));
  471.     for (cnt = 0;  list[cnt] != NULL;  cnt++)
  472.     {
  473.         strcat(gfilename, list[cnt]);
  474.         if (list[cnt+1] != NULL)
  475.           strcat(gfilename, " ");
  476.     }
  477.     _fnexplodefree(list);
  478. }
  479. #else
  480. {
  481.     FILE *fd;
  482.  
  483.     /*
  484.      * We get the shell to expand the filename for us by passing
  485.      * an "echo" command to the shell and reading its output.
  486.      */
  487.     fd = shellcmd("echo %s", filename, (char*)NULL);
  488.     if (fd == NULL)
  489.     {
  490.         /*
  491.          * Cannot create the pipe.
  492.          * Just return the original (fexpanded) filename.
  493.          */
  494.         return (filename);
  495.     }
  496.     gfilename = readfd(fd);
  497.     pclose(fd);
  498.     if (*gfilename == '\0')
  499.     {
  500.         free(gfilename);
  501.         return (filename);
  502.     }
  503.     free(filename);
  504. }
  505. #endif
  506.     return (gfilename);
  507. }
  508.  
  509. /*
  510.  * See if we should open a "replacement file" 
  511.  * instead of the file we're about to open.
  512.  */
  513.     public char *
  514. open_altfile(filename, pf, pfd)
  515.     char *filename;
  516.     int *pf;
  517.     void **pfd;
  518. {
  519.     char *lessopen;
  520.     char *gfilename;
  521.     int returnfd = 0;
  522.     FILE *fd;
  523.     
  524.     ch_ungetchar(-1);
  525.     if ((lessopen = lgetenv("LESSOPEN")) == NULL)
  526.         return (NULL);
  527.     if (strcmp(filename, "-") == 0)
  528.         return (NULL);
  529.     if (*lessopen == '|')
  530.     {
  531.         /*
  532.          * If LESSOPEN starts with a |, it indicates 
  533.          * a "pipe preprocessor".
  534.          */
  535.         lessopen++;
  536.         returnfd = 1;
  537.     }
  538.     fd = shellcmd(lessopen, filename, (char*)NULL);
  539.     if (fd == NULL)
  540.     {
  541.         /*
  542.          * Cannot create the pipe.
  543.          */
  544.         return (NULL);
  545.     }
  546.     if (returnfd)
  547.     {
  548. #if HAVE_FILENO
  549.         int f;
  550.         char c;
  551.  
  552.         /*
  553.          * Read one char to see if the pipe will produce any data.
  554.          * If it does, push the char back on the pipe.
  555.          */
  556.         f = fileno(fd);
  557.         if (read(f, &c, 1) != 1)
  558.         {
  559.             /*
  560.              * Pipe is empty.  This means there is no alt file.
  561.              */
  562.             pclose(fd);
  563.             return (NULL);
  564.         }
  565.         ch_ungetchar(c);
  566.         *pfd = (void *) fd;
  567.         *pf = f;
  568.         return (save("-"));
  569. #else
  570.         error("LESSOPEN pipe is not supported", NULL_PARG);
  571.         return (NULL);
  572. #endif
  573.     }
  574.     gfilename = readfd(fd);
  575.     pclose(fd);
  576.     if (*gfilename == '\0')
  577.         /*
  578.          * Pipe is empty.  This means there is no alt file.
  579.          */
  580.         return (NULL);
  581.     return (gfilename);
  582. }
  583.  
  584. /*
  585.  * Close a replacement file.
  586.  */
  587.     public void
  588. close_altfile(altfilename, filename, pipefd)
  589.     char *altfilename;
  590.     char *filename;
  591.     void *pipefd;
  592. {
  593.     char *lessclose;
  594.     FILE *fd;
  595.     
  596.     if (pipefd != NULL)
  597.         pclose((FILE*) pipefd);
  598.     if ((lessclose = lgetenv("LESSCLOSE")) == NULL)
  599.              return;
  600.     fd = shellcmd(lessclose, filename, altfilename);
  601.     pclose(fd);
  602. }
  603.         
  604. #else
  605. #if MSOFTC
  606.  
  607.     public char *
  608. glob(filename)
  609.     char *filename;
  610. {
  611.     register char *gfilename;
  612.     register char *p;
  613.     register int len;
  614.     register int n;
  615.     struct find_t fnd;
  616.     char drive[_MAX_DRIVE];
  617.     char dir[_MAX_DIR];
  618.     char fname[_MAX_FNAME];
  619.     char ext[_MAX_EXT];
  620.     
  621.     filename = fexpand(filename);
  622.     if (_dos_findfirst(filename, ~0, &fnd) != 0)
  623.         return (filename);
  624.         
  625.     _splitpath(filename, drive, dir, fname, ext);
  626.     len = 100;
  627.     gfilename = (char *) ecalloc(len, sizeof(char));
  628.     p = gfilename;
  629.     do {
  630.         n = strlen(drive) + strlen(dir) + strlen(fnd.name);
  631.         while (p - gfilename + n+2 >= len)
  632.         {
  633.             len *= 2;
  634.             *p = '\0';
  635.             p = (char *) ecalloc(len, sizeof(char));
  636.             strcpy(p, gfilename);
  637.             free(gfilename);
  638.             gfilename = p;
  639.             p = gfilename + strlen(gfilename);
  640.         }
  641.         sprintf(p, "%s%s%s", drive, dir, fnd.name);
  642.         p += n;
  643.         *p++ = ' ';
  644.     } while (_dos_findnext(&fnd) == 0);
  645.     
  646.     *--p = '\0';
  647.     return (gfilename);
  648. }
  649.     
  650.     public char *
  651. open_altfile(filename)
  652.     char *filename;
  653. {
  654.     return (NULL);
  655. }
  656.  
  657.     public void
  658. close_altfile(altfilename, filename)
  659.     char *altfilename;
  660.     char *filename;
  661. {
  662. }
  663.         
  664. #else
  665.  
  666.     public char *
  667. glob(filename)
  668.     char *filename;
  669. {
  670.     return (fexpand(filename));
  671. }
  672.  
  673.     
  674.     public char *
  675. open_altfile(filename)
  676.     char *filename;
  677. {
  678.          return (NULL);
  679. }
  680.  
  681.     public void
  682. close_altfile(altfilename, filename)
  683.     char *altfilename;
  684.     char *filename;
  685. {
  686. }
  687.         
  688. #endif
  689. #endif
  690.  
  691.  
  692. #if HAVE_STAT
  693.  
  694. #include <sys/stat.h>
  695. #ifndef S_ISDIR
  696. #define    S_ISDIR(m)    (((m) & S_IFMT) == S_IFDIR)
  697. #endif
  698. #ifndef S_ISREG
  699. #define    S_ISREG(m)    (((m) & S_IFMT) == S_IFREG)
  700. #endif
  701.  
  702. /*
  703.  * Returns NULL if the file can be opened and
  704.  * is an ordinary file, otherwise an error message
  705.  * (if it cannot be opened or is a directory, etc.)
  706.  */
  707.     public char *
  708. bad_file(filename)
  709.     char *filename;
  710. {
  711.     register char *m;
  712.     struct stat statbuf;
  713.  
  714.     if (stat(filename, &statbuf) < 0)
  715.         return (errno_message(filename));
  716.  
  717.     if (force_open)
  718.         return (NULL);
  719.  
  720.     if (S_ISDIR(statbuf.st_mode))
  721.     {
  722.         static char is_dir[] = " is a directory";
  723.         m = (char *) ecalloc(strlen(filename) + sizeof(is_dir), 
  724.             sizeof(char));
  725.         strcpy(m, filename);
  726.         strcat(m, is_dir);
  727.         return (m);
  728.     }
  729.     if (!S_ISREG(statbuf.st_mode))
  730.     {
  731.         static char not_reg[] = " is not a regular file";
  732.         m = (char *) ecalloc(strlen(filename) + sizeof(not_reg), 
  733.             sizeof(char));
  734.         strcpy(m, filename);
  735.         strcat(m, not_reg);
  736.         return (m);
  737.     }
  738.  
  739.     return (NULL);
  740. }
  741.  
  742. /*
  743.  * Return the size of a file, as cheaply as possible.
  744.  * In Unix, we can stat the file.
  745.  */
  746.     public POSITION
  747. filesize(f)
  748.     int f;
  749. {
  750.     struct stat statbuf;
  751.  
  752.     if (fstat(f, &statbuf) < 0)
  753.         /*
  754.          * Can't stat; try seeking to the end.
  755.          */
  756.         return (seek_filesize(f));
  757.  
  758.     return ((POSITION) statbuf.st_size);
  759. }
  760.  
  761. #else
  762.  
  763. /*
  764.  * If we have no way to find out, just say the file is good.
  765.  */
  766.     public char *
  767. bad_file(filename)
  768.     char *filename;
  769. {
  770.     return (NULL);
  771. }
  772.  
  773. /*
  774.  * We can find the file size by seeking.
  775.  */
  776.     public POSITION
  777. filesize(f)
  778.     int f;
  779. {
  780.     return (seek_filesize(f));
  781. }
  782.  
  783. #endif
  784.