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

Annotation of src/usr.bin/less/filename.c, Revision 1.1

1.1     ! etheisen    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(getenv("HOME"), filename);
        !            96:        if (pathname != NULL)
        !            97:                return (pathname);
        !            98: #if OS2
        !            99:        /*
        !           100:         * Try $INIT/filename.
        !           101:         */
        !           102:        pathname = dirfile(getenv("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 = getenv("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 "%" with the current filename,
        !           138:  * and any "#" with the previous filename.
        !           139:  * {{ This is a lot of work just to support % and #. }}
        !           140:  */
        !           141:        public char *
        !           142: fexpand(s)
        !           143:        char *s;
        !           144: {
        !           145:        register char *fr, *to;
        !           146:        register int n;
        !           147:        register char *e;
        !           148:
        !           149:        /*
        !           150:         * Make one pass to see how big a buffer we
        !           151:         * need to allocate for the expanded string.
        !           152:         */
        !           153:        n = 0;
        !           154:        for (fr = s;  *fr != '\0';  fr++)
        !           155:        {
        !           156:                switch (*fr)
        !           157:                {
        !           158:                case '%':
        !           159:                        if (curr_ifile == NULL_IFILE)
        !           160:                        {
        !           161:                                /* error("No current file", NULL_PARG); */
        !           162:                                return (save(s));
        !           163:                        }
        !           164:                        n += strlen(get_filename(curr_ifile));
        !           165:                        break;
        !           166:                case '#':
        !           167:                        if (old_ifile == NULL_IFILE)
        !           168:                        {
        !           169:                                /* error("No previous file", NULL_PARG); */
        !           170:                                return (save(s));
        !           171:                        }
        !           172:                        n += strlen(get_filename(old_ifile));
        !           173:                        break;
        !           174:                default:
        !           175:                        n++;
        !           176:                        break;
        !           177:                }
        !           178:        }
        !           179:
        !           180:        e = (char *) ecalloc(n+1, sizeof(char));
        !           181:
        !           182:        /*
        !           183:         * Now copy the string, expanding any "%" or "#".
        !           184:         */
        !           185:        to = e;
        !           186:        for (fr = s;  *fr != '\0';  fr++)
        !           187:        {
        !           188:                switch (*fr)
        !           189:                {
        !           190:                case '%':
        !           191:                        strcpy(to, get_filename(curr_ifile));
        !           192:                        to += strlen(to);
        !           193:                        break;
        !           194:                case '#':
        !           195:                        strcpy(to, get_filename(old_ifile));
        !           196:                        to += strlen(to);
        !           197:                        break;
        !           198:                default:
        !           199:                        *to++ = *fr;
        !           200:                        break;
        !           201:                }
        !           202:        }
        !           203:        *to = '\0';
        !           204:        return (e);
        !           205: }
        !           206:
        !           207: #if TAB_COMPLETE_FILENAME
        !           208:
        !           209: /*
        !           210:  * Return a blank-separated list of filenames which "complete"
        !           211:  * the given string.
        !           212:  */
        !           213:        public char *
        !           214: fcomplete(s)
        !           215:        char *s;
        !           216: {
        !           217:        char *fpat;
        !           218:        /*
        !           219:         * Complete the filename "s" by globbing "s*".
        !           220:         */
        !           221: #if MSOFTC
        !           222:        /*
        !           223:         * But in DOS, we have to glob "s*.*".
        !           224:         * But if the final component of the filename already has
        !           225:         * a dot in it, just do "s*".
        !           226:         * (Thus, "FILE" is globbed as "FILE*.*",
        !           227:         *  but "FILE.A" is globbed as "FILE.A*").
        !           228:         */
        !           229:        char *slash;
        !           230:        for (slash = s+strlen(s)-1;  slash > s;  slash--)
        !           231:                if (*slash == '/' || *slash == '\\')
        !           232:                        break;
        !           233:        fpat = (char *) ecalloc(strlen(s)+4, sizeof(char));
        !           234:        if (strchr(slash, '.') == NULL)
        !           235:                sprintf(fpat, "%s*.*", s);
        !           236:        else
        !           237:                sprintf(fpat, "%s*", s);
        !           238: #else
        !           239:        fpat = (char *) ecalloc(strlen(s)+2, sizeof(char));
        !           240:        sprintf(fpat, "%s*", s);
        !           241: #endif
        !           242:        s = glob(fpat);
        !           243:        if (strcmp(s,fpat) == 0)
        !           244:        {
        !           245:                /*
        !           246:                 * The filename didn't expand.
        !           247:                 */
        !           248:                free(s);
        !           249:                s = NULL;
        !           250:        }
        !           251:        free(fpat);
        !           252:        return (s);
        !           253: }
        !           254: #endif
        !           255:
        !           256: /*
        !           257:  * Try to determine if a file is "binary".
        !           258:  * This is just a guess, and we need not try too hard to make it accurate.
        !           259:  */
        !           260:        public int
        !           261: bin_file(f)
        !           262:        int f;
        !           263: {
        !           264:        int i;
        !           265:        int n;
        !           266:        unsigned char data[64];
        !           267:
        !           268:        if (!seekable(f))
        !           269:                return (0);
        !           270:        if (lseek(f, (off_t)0, 0) == BAD_LSEEK)
        !           271:                return (0);
        !           272:        n = read(f, data, sizeof(data));
        !           273:        for (i = 0;  i < n;  i++)
        !           274:                if (binary_char(data[i]))
        !           275:                        return (1);
        !           276:        return (0);
        !           277: }
        !           278:
        !           279: /*
        !           280:  * Try to determine the size of a file by seeking to the end.
        !           281:  */
        !           282:        static POSITION
        !           283: seek_filesize(f)
        !           284:        int f;
        !           285: {
        !           286:        off_t spos;
        !           287:
        !           288:        spos = lseek(f, (off_t)0, 2);
        !           289:        if (spos == BAD_LSEEK)
        !           290:                return (NULL_POSITION);
        !           291:        return ((POSITION) spos);
        !           292: }
        !           293:
        !           294: #if GLOB
        !           295:
        !           296: FILE *popen();
        !           297:
        !           298: /*
        !           299:  * Read a string from a file.
        !           300:  * Return a pointer to the string in memory.
        !           301:  */
        !           302:        static char *
        !           303: readfd(fd)
        !           304:        FILE *fd;
        !           305: {
        !           306:        int len;
        !           307:        int ch;
        !           308:        char *buf;
        !           309:        char *p;
        !           310:
        !           311:        /*
        !           312:         * Make a guess about how many chars in the string
        !           313:         * and allocate a buffer to hold it.
        !           314:         */
        !           315:        len = 100;
        !           316:        buf = (char *) ecalloc(len, sizeof(char));
        !           317:        for (p = buf;  ;  p++)
        !           318:        {
        !           319:                if ((ch = getc(fd)) == '\n' || ch == EOF)
        !           320:                        break;
        !           321:                if (p - buf >= len-1)
        !           322:                {
        !           323:                        /*
        !           324:                         * The string is too big to fit in the buffer we have.
        !           325:                         * Allocate a new buffer, twice as big.
        !           326:                         */
        !           327:                        len *= 2;
        !           328:                        *p = '\0';
        !           329:                        p = (char *) ecalloc(len, sizeof(char));
        !           330:                        strcpy(p, buf);
        !           331:                        free(buf);
        !           332:                        buf = p;
        !           333:                        p = buf + strlen(buf);
        !           334:                }
        !           335:                *p = ch;
        !           336:        }
        !           337:        *p = '\0';
        !           338:        return (buf);
        !           339: }
        !           340:
        !           341: /*
        !           342:  * Execute a shell command.
        !           343:  * Return a pointer to a pipe connected to the shell command's standard output.
        !           344:  */
        !           345:        static FILE *
        !           346: shellcmd(cmd, s1, s2)
        !           347:        char *cmd;
        !           348:        char *s1;
        !           349:        char *s2;
        !           350: {
        !           351:        char *scmd;
        !           352:        char *scmd2;
        !           353:        char *shell;
        !           354:        FILE *fd;
        !           355:        int len;
        !           356:
        !           357:        len = strlen(cmd) +
        !           358:                (s1 == NULL ? 0 : strlen(s1)) +
        !           359:                (s2 == NULL ? 0 : strlen(s2)) + 1;
        !           360:        scmd = (char *) ecalloc(len, sizeof(char));
        !           361:        sprintf(scmd, cmd, s1, s2);
        !           362: #if HAVE_SHELL
        !           363:        shell = getenv("SHELL");
        !           364:        if (shell != NULL && *shell != '\0')
        !           365:        {
        !           366:                /*
        !           367:                 * Read the output of <$SHELL -c "cmd">.
        !           368:                 */
        !           369:                scmd2 = (char *) ecalloc(strlen(shell) + strlen(scmd) + 7,
        !           370:                                        sizeof(char));
        !           371:                sprintf(scmd2, "%s -c \"%s\"", shell, scmd);
        !           372:                free(scmd);
        !           373:                scmd = scmd2;
        !           374:        }
        !           375: #endif
        !           376:        fd = popen(scmd, "r");
        !           377:        free(scmd);
        !           378:        return (fd);
        !           379: }
        !           380:
        !           381: /*
        !           382:  * Expand a filename, doing any shell-level substitutions.
        !           383:  */
        !           384:        public char *
        !           385: glob(filename)
        !           386:        char *filename;
        !           387: {
        !           388:        char *gfilename;
        !           389:
        !           390:        filename = fexpand(filename);
        !           391: #if OS2
        !           392: {
        !           393:        char **list;
        !           394:        int cnt;
        !           395:        int length;
        !           396:
        !           397:        list = _fnexplode(filename);
        !           398:        if (list == NULL)
        !           399:                return (filename);
        !           400:        length = 0;
        !           401:        for (cnt = 0;  list[cnt] != NULL;  cnt++)
        !           402:                length += strlen(list[cnt]) + 1;
        !           403:        gfilename = (char *) ecalloc(length, sizeof(char));
        !           404:        for (cnt = 0;  list[cnt] != NULL;  cnt++)
        !           405:        {
        !           406:                strcat(gfilename, list[cnt]);
        !           407:                strcat(gfilename, " ");
        !           408:        }
        !           409:        _fnexplodefree(list);
        !           410: }
        !           411: #else
        !           412: {
        !           413:        FILE *fd;
        !           414:
        !           415:        /*
        !           416:         * We get the shell to expand the filename for us by passing
        !           417:         * an "echo" command to the shell and reading its output.
        !           418:         */
        !           419:        fd = shellcmd("echo %s", filename, (char*)NULL);
        !           420:        if (fd == NULL)
        !           421:        {
        !           422:                /*
        !           423:                 * Cannot create the pipe.
        !           424:                 * Just return the original (fexpanded) filename.
        !           425:                 */
        !           426:                return (filename);
        !           427:        }
        !           428:        gfilename = readfd(fd);
        !           429:        pclose(fd);
        !           430:        if (*gfilename == '\0')
        !           431:        {
        !           432:                free(gfilename);
        !           433:                return (filename);
        !           434:        }
        !           435:        free(filename);
        !           436: }
        !           437: #endif
        !           438:        return (gfilename);
        !           439: }
        !           440:
        !           441: /*
        !           442:  * See if we should open a "replacement file"
        !           443:  * instead of the file we're about to open.
        !           444:  */
        !           445:        public char *
        !           446: open_altfile(filename, pf, pfd)
        !           447:        char *filename;
        !           448:        int *pf;
        !           449:        void **pfd;
        !           450: {
        !           451:        char *lessopen;
        !           452:        char *gfilename;
        !           453:        int returnfd = 0;
        !           454:        FILE *fd;
        !           455:
        !           456:        ch_ungetchar(-1);
        !           457:        if ((lessopen = getenv("LESSOPEN")) == NULL)
        !           458:                return (NULL);
        !           459:        if (strcmp(filename, "-") == 0)
        !           460:                return (NULL);
        !           461:        if (*lessopen == '|')
        !           462:        {
        !           463:                /*
        !           464:                 * If LESSOPEN starts with a |, it indicates
        !           465:                 * a "pipe preprocessor".
        !           466:                 */
        !           467:                lessopen++;
        !           468:                returnfd = 1;
        !           469:        }
        !           470:        fd = shellcmd(lessopen, filename, (char*)NULL);
        !           471:        if (fd == NULL)
        !           472:        {
        !           473:                /*
        !           474:                 * Cannot create the pipe.
        !           475:                 */
        !           476:                return (NULL);
        !           477:        }
        !           478:        if (returnfd)
        !           479:        {
        !           480: #if HAVE_FILENO
        !           481:                int f;
        !           482:                char c;
        !           483:
        !           484:                /*
        !           485:                 * Read one char to see if the pipe will produce any data.
        !           486:                 * If it does, push the char back on the pipe.
        !           487:                 */
        !           488:                f = fileno(fd);
        !           489:                if (read(f, &c, 1) != 1)
        !           490:                {
        !           491:                        /*
        !           492:                         * Pipe is empty.  This means there is no alt file.
        !           493:                         */
        !           494:                        pclose(fd);
        !           495:                        return (NULL);
        !           496:                }
        !           497:                ch_ungetchar(c);
        !           498:                *pfd = (void *) fd;
        !           499:                *pf = f;
        !           500:                return (save("-"));
        !           501: #else
        !           502:                error("LESSOPEN pipe is not supported", NULL_PARG);
        !           503:                return (NULL);
        !           504: #endif
        !           505:        }
        !           506:        gfilename = readfd(fd);
        !           507:        pclose(fd);
        !           508:        if (*gfilename == '\0')
        !           509:                /*
        !           510:                 * Pipe is empty.  This means there is no alt file.
        !           511:                 */
        !           512:                return (NULL);
        !           513:        return (gfilename);
        !           514: }
        !           515:
        !           516: /*
        !           517:  * Close a replacement file.
        !           518:  */
        !           519:        public void
        !           520: close_altfile(altfilename, filename, pipefd)
        !           521:        char *altfilename;
        !           522:        char *filename;
        !           523:        void *pipefd;
        !           524: {
        !           525:        char *lessclose;
        !           526:        FILE *fd;
        !           527:
        !           528:        if (pipefd != NULL)
        !           529:                pclose((FILE*) pipefd);
        !           530:        if ((lessclose = getenv("LESSCLOSE")) == NULL)
        !           531:                return;
        !           532:        fd = shellcmd(lessclose, filename, altfilename);
        !           533:        pclose(fd);
        !           534: }
        !           535:
        !           536: #else
        !           537: #if MSOFTC
        !           538:
        !           539:        public char *
        !           540: glob(filename)
        !           541:        char *filename;
        !           542: {
        !           543:        register char *gfilename;
        !           544:        register char *p;
        !           545:        register int len;
        !           546:        register int n;
        !           547:        struct find_t fnd;
        !           548:        char drive[_MAX_DRIVE];
        !           549:        char dir[_MAX_DIR];
        !           550:        char fname[_MAX_FNAME];
        !           551:        char ext[_MAX_EXT];
        !           552:
        !           553:        filename = fexpand(filename);
        !           554:        if (_dos_findfirst(filename, ~0, &fnd) != 0)
        !           555:                return (filename);
        !           556:
        !           557:        _splitpath(filename, drive, dir, fname, ext);
        !           558:        len = 100;
        !           559:        gfilename = (char *) ecalloc(len, sizeof(char));
        !           560:        p = gfilename;
        !           561:        do {
        !           562:                n = strlen(drive) + strlen(dir) + strlen(fnd.name);
        !           563:                while (p - gfilename + n+2 >= len)
        !           564:                {
        !           565:                        len *= 2;
        !           566:                        *p = '\0';
        !           567:                        p = (char *) ecalloc(len, sizeof(char));
        !           568:                        strcpy(p, gfilename);
        !           569:                        free(gfilename);
        !           570:                        gfilename = p;
        !           571:                        p = gfilename + strlen(gfilename);
        !           572:                }
        !           573:                sprintf(p, "%s%s%s", drive, dir, fnd.name);
        !           574:                p += n;
        !           575:                *p++ = ' ';
        !           576:        } while (_dos_findnext(&fnd) == 0);
        !           577:
        !           578:        *--p = '\0';
        !           579:        return (gfilename);
        !           580: }
        !           581:
        !           582:        public char *
        !           583: open_altfile(filename)
        !           584:        char *filename;
        !           585: {
        !           586:        return (NULL);
        !           587: }
        !           588:
        !           589:        public void
        !           590: close_altfile(altfilename, filename)
        !           591:        char *altfilename;
        !           592:        char *filename;
        !           593: {
        !           594: }
        !           595:
        !           596: #else
        !           597:
        !           598:        public char *
        !           599: glob(filename)
        !           600:        char *filename;
        !           601: {
        !           602:        return (fexpand(filename));
        !           603: }
        !           604:
        !           605:
        !           606:        public char *
        !           607: open_altfile(filename)
        !           608:        char *filename;
        !           609: {
        !           610:        return (NULL);
        !           611: }
        !           612:
        !           613:        public void
        !           614: close_altfile(altfilename, filename)
        !           615:        char *altfilename;
        !           616:        char *filename;
        !           617: {
        !           618: }
        !           619:
        !           620: #endif
        !           621: #endif
        !           622:
        !           623:
        !           624: #if HAVE_STAT
        !           625:
        !           626: #include <sys/stat.h>
        !           627: #ifndef S_ISDIR
        !           628: #define        S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
        !           629: #endif
        !           630: #ifndef S_ISREG
        !           631: #define        S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
        !           632: #endif
        !           633:
        !           634: /*
        !           635:  * Returns NULL if the file can be opened and
        !           636:  * is an ordinary file, otherwise an error message
        !           637:  * (if it cannot be opened or is a directory, etc.)
        !           638:  */
        !           639:        public char *
        !           640: bad_file(filename)
        !           641:        char *filename;
        !           642: {
        !           643:        register char *m;
        !           644:        struct stat statbuf;
        !           645:
        !           646:        if (stat(filename, &statbuf) < 0)
        !           647:                return (errno_message(filename));
        !           648:
        !           649:        if (force_open)
        !           650:                return (NULL);
        !           651:
        !           652:        if (S_ISDIR(statbuf.st_mode))
        !           653:        {
        !           654:                static char is_dir[] = " is a directory";
        !           655:                m = (char *) ecalloc(strlen(filename) + sizeof(is_dir),
        !           656:                        sizeof(char));
        !           657:                strcpy(m, filename);
        !           658:                strcat(m, is_dir);
        !           659:                return (m);
        !           660:        }
        !           661:        if (!S_ISREG(statbuf.st_mode))
        !           662:        {
        !           663:                static char not_reg[] = " is not a regular file";
        !           664:                m = (char *) ecalloc(strlen(filename) + sizeof(not_reg),
        !           665:                        sizeof(char));
        !           666:                strcpy(m, filename);
        !           667:                strcat(m, not_reg);
        !           668:                return (m);
        !           669:        }
        !           670:
        !           671:        return (NULL);
        !           672: }
        !           673:
        !           674: /*
        !           675:  * Return the size of a file, as cheaply as possible.
        !           676:  * In Unix, we can stat the file.
        !           677:  */
        !           678:        public POSITION
        !           679: filesize(f)
        !           680:        int f;
        !           681: {
        !           682:        struct stat statbuf;
        !           683:
        !           684:        if (fstat(f, &statbuf) < 0)
        !           685:                /*
        !           686:                 * Can't stat; try seeking to the end.
        !           687:                 */
        !           688:                return (seek_filesize(f));
        !           689:
        !           690:        return ((POSITION) statbuf.st_size);
        !           691: }
        !           692:
        !           693: #else
        !           694:
        !           695: /*
        !           696:  * If we have no way to find out, just say the file is good.
        !           697:  */
        !           698:        public char *
        !           699: bad_file(filename)
        !           700:        char *filename;
        !           701: {
        !           702:        return (NULL);
        !           703: }
        !           704:
        !           705: /*
        !           706:  * We can find the file size by seeking.
        !           707:  */
        !           708:        public POSITION
        !           709: filesize(f)
        !           710:        int f;
        !           711: {
        !           712:        return (seek_filesize(f));
        !           713: }
        !           714:
        !           715: #endif