home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / fileio.c < prev    next >
C/C++ Source or Header  |  1998-09-28  |  16KB  |  768 lines

  1. /*
  2.  * The routines in this file read and write ASCII files from the disk. All of
  3.  * the knowledge about files are here.
  4.  *
  5.  * $Header: /usr/build/vile/vile/RCS/fileio.c,v 1.128 1998/09/29 02:22:02 tom Exp $
  6.  *
  7.  */
  8.  
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. #if SYS_VMS
  13. #include    <file.h>
  14. #endif
  15.  
  16. #if HAVE_SYS_IOCTL_H
  17. #include    <sys/ioctl.h>
  18. #endif
  19.  
  20. #if CC_NEWDOSCC
  21. #include    <io.h>
  22. #endif
  23.  
  24.  
  25. #ifndef EISDIR
  26. #define EISDIR EACCES
  27. #endif
  28.  
  29. /*--------------------------------------------------------------------------*/
  30.  
  31. static    int    count_fline;    /* # of lines read with 'ffgetline()' */
  32.  
  33. /*--------------------------------------------------------------------------*/
  34. static void
  35. free_fline(void)
  36. {
  37.     FreeAndNull(fline);
  38.     flen = 0;
  39. }
  40.  
  41. #if OPT_FILEBACK
  42. /*
  43.  * Copy file when making a backup
  44.  */
  45. static int
  46. copy_file (const char *src, const char *dst)
  47. {
  48.     FILE    *ifp;
  49.     FILE    *ofp;
  50.     int    chr;
  51.     int    ok = FALSE;
  52.  
  53.     if ((ifp = fopen(src, FOPEN_READ)) != 0) {
  54.         if ((ofp = fopen(dst, FOPEN_WRITE)) != 0) {
  55.             ok = TRUE;
  56.             for_ever {
  57.                 chr = fgetc(ifp);
  58.                 if (feof(ifp))
  59.                     break;
  60.                 fputc(chr, ofp);
  61.                 if (ferror(ifp) || ferror(ofp)) {
  62.                     ok = FALSE;
  63.                     break;
  64.                 }
  65.             }
  66.             (void)fclose(ofp);
  67.         }
  68.         (void)fclose(ifp);
  69.     }
  70.     return ok;
  71. }
  72.  
  73. /*
  74.  * Before overwriting a file, rename any existing version as a backup.
  75.  * Copy-back to retain the modification-date of the original file.
  76.  *
  77.  * Note: for UNIX, the direction of file-copy should be reversed, if the
  78.  *       original file happens to be a symbolic link.
  79.  */
  80.  
  81. #if SYS_UNIX
  82. # if ! HAVE_LONG_FILE_NAMES
  83. #  define MAX_FN_LEN 14
  84. # else
  85. #  define MAX_FN_LEN 255
  86. # endif
  87. #endif
  88.  
  89. static int
  90. write_backup_file(const char *orig, char *backup)
  91. {
  92.     int s;
  93.  
  94.     struct stat ostat, bstat;
  95.  
  96.     if (stat(SL_TO_BSL(orig), &ostat) != 0)
  97.         return FALSE;
  98.  
  99.     if (stat(SL_TO_BSL(backup), &bstat) == 0) {  /* the backup file exists */
  100.  
  101. #if SYS_UNIX
  102.         /* same file, somehow? */
  103.         if (bstat.st_dev == ostat.st_dev &&
  104.             bstat.st_ino == ostat.st_ino) {
  105.             return FALSE;
  106.         }
  107. #endif
  108.  
  109.         /* remove it */
  110.         if (unlink(backup) != 0)
  111.             return FALSE;
  112.     }
  113.  
  114.     /* there are many reasons for copying, rather than renaming
  115.        and writing a new file -- the file may have links, which
  116.        will follow the rename, rather than stay with the real-name.
  117.        additionally, if the write fails, we need to re-rename back to
  118.        the original name, otherwise two successive failed writes will
  119.        destroy the file.
  120.     */
  121.  
  122.     s = copy_file(orig, backup);
  123.     if (s != TRUE)
  124.         return s;
  125.  
  126.     /* change date and permissions to match original */
  127. #if HAVE_UTIMES
  128.     /* we favor utimes over utime, since not all implementations (i.e.
  129.         older ones) declare the utimbuf argument.  NeXT, for example,
  130.         declares it as an array of two timevals instead.  we think
  131.         utimes will be more standard, where it exists.  what we
  132.         really think is that it's probably BSD systems that got
  133.         utime wrong, and those will have utimes to cover for it.  :-) */
  134.     {
  135.         struct timeval buf[2];
  136.         buf[0].tv_sec = ostat.st_atime;
  137.         buf[0].tv_usec = 0;
  138.         buf[1].tv_sec = ostat.st_mtime;
  139.         buf[1].tv_usec = 0;
  140.         s = utimes(backup, buf);
  141.         if (s != 0) {
  142.             (void)unlink(backup);
  143.             return FALSE;
  144.         }
  145.     }
  146. #else
  147. # if HAVE_UTIME
  148.     {
  149.         struct utimbuf buf;
  150.         buf.actime = ostat.st_atime;
  151.         buf.modtime = ostat.st_mtime;
  152.         s = utime(backup, &buf);
  153.         if (s != 0) {
  154.             (void)unlink(backup);
  155.             return FALSE;
  156.         }
  157.     }
  158. #endif
  159. #endif
  160.  
  161. #if SYS_OS2 && CC_CSETPP
  162.     s = chmod(backup, ostat.st_mode & (S_IREAD | S_IWRITE));
  163. #else
  164.     s = chmod(backup, ostat.st_mode & 0777);
  165. #endif
  166.     if (s != 0) {
  167.         (void)unlink(backup);
  168.         return FALSE;
  169.     }
  170.  
  171.     return TRUE;
  172. }
  173.  
  174. static int
  175. make_backup (char *fname)
  176. {
  177.     int    ok    = TRUE;
  178.  
  179.     if (ffexists(fname)) { /* if the file exists, attempt a backup */
  180.         char    tname[NFILEN];
  181.         char    *s = pathleaf(strcpy(tname, fname)),
  182.             *t = strrchr(s, '.');
  183.         char *gvalfileback = global_g_val_ptr(GVAL_BACKUPSTYLE);
  184.  
  185.         if (strcmp(gvalfileback,".bak") == 0) {
  186.             if (t == 0    /* i.e. no '.' at all */
  187. #if SYS_UNIX
  188.                 || t == s    /* i.e. leading char is '.' */
  189. #endif
  190.             )
  191.                 t = skip_string(s); /* then just append */
  192.             (void)strcpy(t, ".bak");
  193. #if SYS_UNIX
  194.         } else if (strcmp(gvalfileback, "tilde") == 0) {
  195.             t = skip_string(s);
  196. #if ! HAVE_LONG_FILENAMES
  197.             if (t - s >= MAX_FN_LEN) {
  198.                 if (t - s == MAX_FN_LEN &&
  199.                     s[MAX_FN_LEN-2] == '.')
  200.                     s[MAX_FN_LEN-2] = s[MAX_FN_LEN-1];
  201.                 t = &s[MAX_FN_LEN-1];
  202.             }
  203. #endif
  204.             (void)strcpy(t, "~");
  205. #if SOMEDAY
  206.         } else if (strcmp(gvalfileback, "tilde_N_existing") {
  207.             /* numbered backups if one exists, else simple */
  208.         } else if (strcmp(gvalfileback, "tilde_N") {
  209.             /* numbered backups of all files*/
  210. #endif
  211. #endif /* SYS_UNIX */
  212.         } else {
  213.             mlwrite("BUG: bad fileback value");
  214.             return FALSE;
  215.         }
  216.  
  217.         ok = write_backup_file(fname, tname);
  218.  
  219.     }
  220.     return ok;
  221. }
  222. #endif /* OPT_FILEBACK */
  223.  
  224. /*
  225.  * Open a file for reading.
  226.  */
  227. int
  228. ffropen(char *fn)
  229. {
  230.     fileispipe = FALSE;
  231.     eofflag = FALSE;
  232.  
  233. #if OPT_SHELL
  234.     if (isShellOrPipe(fn)) {
  235.         ffp = 0;
  236. #if SYS_UNIX || SYS_MSDOS || SYS_OS2 || SYS_WINNT
  237.             ffp = npopen(fn+1, FOPEN_READ);
  238. #endif
  239. #if SYS_VMS
  240.             ffp = vms_rpipe(fn+1, 0, (char *)0);
  241.         /* really a temp-file, but we cannot fstat it to get size */
  242. #endif
  243.         if (ffp == 0) {
  244.             mlerror("opening pipe for read");
  245.             return (FIOERR);
  246.         }
  247.  
  248.         fileispipe = TRUE;
  249.         count_fline = 0;
  250.  
  251.     } else
  252. #endif
  253.     if (is_directory(fn)) {
  254.         set_errno(EISDIR);
  255.         mlerror("opening directory");
  256.         return (FIOERR);
  257.  
  258.     } else if ((ffp=fopen(fn, FOPEN_READ)) == NULL) {
  259.         if (errno != ENOENT
  260. #if SYS_OS2 && CC_CSETPP
  261.                  && errno != ENOTEXIST
  262.                  && errno != EBADNAME
  263. #endif
  264.          && errno != EINVAL) {    /* a problem with Linux to DOS-files */
  265.             mlerror("opening for read");
  266.             return (FIOERR);
  267.         }
  268.         return (FIOFNF);
  269.     }
  270.  
  271.         return (FIOSUC);
  272. }
  273.  
  274. /*
  275.  * Open a file for writing. Return TRUE if all is well, and FALSE on error
  276.  * (cannot create).
  277.  */
  278. int
  279. ffwopen(char *fn, int forced)
  280. {
  281. #if SYS_UNIX || SYS_MSDOS || SYS_OS2 || SYS_WINNT
  282.     char    *name;
  283.     char    *mode = FOPEN_WRITE;
  284.  
  285. #if OPT_SHELL
  286.     if (isShellOrPipe(fn)) {
  287.         if ((ffp=npopen(fn+1, mode)) == NULL) {
  288.                     mlerror("opening pipe for write");
  289.                     return (FIOERR);
  290.         }
  291.         fileispipe = TRUE;
  292.     } else
  293. #endif
  294.     {
  295.         if ((name = is_appendname(fn)) != NULL) {
  296.             fn = name;
  297.             mode = FOPEN_APPEND;
  298.         }
  299.         if (is_directory(fn)) {
  300.             set_errno(EISDIR);
  301.             mlerror("opening directory");
  302.             return (FIOERR);
  303.         }
  304.  
  305. #if OPT_FILEBACK
  306.         /* will we be able to write? (before attempting backup) */
  307.         if (ffexists(fn) && ffronly(fn)) {
  308.             mlerror("accessing for write");
  309.             return (FIOERR);
  310.         }
  311.  
  312.         if (*global_g_val_ptr(GVAL_BACKUPSTYLE) != 'o') { /* "off" ? */
  313.             if (!make_backup(fn)) {
  314.                 if (!forced) {
  315.                     mlerror("making backup file");
  316.                     return (FIOERR);
  317.                 }
  318.             }
  319.         }
  320. #endif
  321.         if ((ffp = fopen(fn, mode)) == NULL) {
  322.             mlerror("opening for write");
  323.             return (FIOERR);
  324.         }
  325.         fileispipe = FALSE;
  326.     }
  327. #else
  328. #if     SYS_VMS
  329.     /*
  330.      * Note:  using a '0' protection on VMS C 'open()' tells it to use an
  331.      * existing file's protection, or (if the file doesn't exist) the
  332.      * user's default protection.
  333.      */
  334.     char    temp[NFILEN];
  335.     register int    fd;
  336.     strip_version(fn = strcpy(temp, fn));
  337.  
  338.     if (is_appendname(fn)
  339.     ||  is_directory(fn)
  340.     || (fd=creat(temp, 0, "rfm=var", "rat=cr")) < 0
  341.     || (ffp=fdopen(fd, FOPEN_WRITE)) == NULL) {
  342.         mlforce("[Cannot open file for writing]");
  343.         return (FIOERR);
  344.     }
  345. #else
  346.         if ((ffp=fopen(fn, FOPEN_WRITE)) == NULL) {
  347.                 mlerror("opening for write");
  348.                 return (FIOERR);
  349.         }
  350. #endif
  351. #endif
  352.         return (FIOSUC);
  353. }
  354.  
  355. /* wrapper for 'access()' */
  356. int
  357. ffaccess(char *fn, int mode)
  358. {
  359. #if HAVE_ACCESS
  360.     return (!isInternalName(fn)
  361.        &&   access(SL_TO_BSL(fn), mode) == 0);
  362. #else
  363.     int    fd;
  364.     switch (mode) {
  365.     case FL_EXECABLE:
  366.         /* FALL-THRU */
  367.     case FL_READABLE:
  368.         if (ffropen(fn) == FIOSUC) {
  369.             ffclose();
  370.             return TRUE;
  371.         }
  372.             return FALSE;
  373.     case FL_WRITEABLE:
  374.             if ((fd=open(SL_TO_BSL(fn), O_WRONLY|O_APPEND)) < 0) {
  375.                     return FALSE;
  376.         }
  377.         (void)close(fd);
  378.         return TRUE;
  379.     default:
  380.         return ffexists(fn);
  381.     }
  382. #endif
  383. }
  384.  
  385. /* is the file read-only?  true or false */
  386. int
  387. ffronly(char *fn)
  388. {
  389.     if (isShellOrPipe(fn)) {
  390.         return TRUE;
  391.     } else {
  392.         return !ffaccess(fn, FL_WRITEABLE);
  393.     }
  394. }
  395.  
  396. #if SYS_WINNT
  397.  
  398. off_t
  399. ffsize(void)
  400. {
  401.     int flen, prev;
  402.     prev = ftell(ffp);
  403.     if (fseek(ffp, 0, 2) < 0)
  404.         return -1L;
  405.     flen = ftell(ffp);
  406.     fseek(ffp, prev, 0);
  407.     return flen;
  408. }
  409.  
  410. #else
  411. #if SYS_UNIX || SYS_VMS || SYS_OS2
  412. off_t
  413. ffsize(void)
  414. {
  415.     struct stat statbuf;
  416.     if (fstat(fileno(ffp), &statbuf) == 0) {
  417.         return (long)statbuf.st_size;
  418.     }
  419.         return -1L;
  420. }
  421. #endif
  422. #endif
  423.  
  424. #if SYS_MSDOS
  425. #if CC_DJGPP
  426.  
  427. off_t
  428. ffsize(void)
  429. {
  430.     int flen, prev;
  431.     prev = ftell(ffp);
  432.     if (fseek(ffp, 0, 2) < 0)
  433.         return -1L;
  434.     flen = ftell(ffp);
  435.     fseek(ffp, prev, 0);
  436.     return flen;
  437. }
  438.  
  439. #else
  440.  
  441. off_t
  442. ffsize(void)
  443. {
  444.     int fd = fileno(ffp);
  445.     if (fd < 0)
  446.         return -1L;
  447.     return  filelength(fd);
  448. }
  449.  
  450. #endif
  451. #endif
  452.  
  453. #if SYS_UNIX || SYS_VMS || SYS_OS2 || SYS_WINNT
  454.  
  455. int
  456. ffexists(char *p)
  457. {
  458.     struct stat statbuf;
  459.     if (!isInternalName(p)
  460.      && stat(SL_TO_BSL(p), &statbuf) == 0) {
  461.         return TRUE;
  462.     }
  463.         return FALSE;
  464. }
  465.  
  466. #endif
  467.  
  468. #if SYS_MSDOS || SYS_WIN31
  469.  
  470. int
  471. ffexists(char *p)
  472. {
  473.     if (!isInternalName(p)
  474.      && ffropen(SL_TO_BSL(p)) == FIOSUC) {
  475.         ffclose();
  476.         return TRUE;
  477.     }
  478.         return FALSE;
  479. }
  480.  
  481. #endif
  482.  
  483. #if !SYS_MSDOS
  484. int
  485. ffread(char *buf, long len)
  486. {
  487. #if SYS_VMS
  488.     /*
  489.      * If the input file is record-formatted (as opposed to stream-lf, a
  490.      * single read won't get the whole file.
  491.      */
  492.     int    total = 0;
  493.  
  494.     while (len > 0) {
  495.         int    this = read(fileno(ffp), buf+total, len-total);
  496.         if (this <= 0)
  497.             break;
  498.         total += this;
  499.     }
  500.     fseek (ffp, len, 1);    /* resynchronize stdio */
  501.     return total;
  502. #else
  503. # if CC_CSETPP
  504.     int got = fread(buf, len, 1, ffp);
  505.     return got == 1 ? len : -1;
  506. # else
  507.     int got = read(fileno(ffp), buf, (SIZE_T)len);
  508.     if (got >= 0)
  509.         fseek (ffp, len, 1);    /* resynchronize stdio */
  510.     return got;
  511. # endif
  512. #endif
  513. }
  514.  
  515. void
  516. ffseek(long n)
  517. {
  518. #if SYS_VMS
  519.     ffrewind();    /* see below */
  520. #endif
  521.     fseek (ffp,n,0);
  522. }
  523.  
  524. void
  525. ffrewind(void)
  526. {
  527. #if SYS_VMS
  528.     /* VAX/VMS V5.4-2, VAX-C 3.2 'rewind()' does not work properly, because
  529.      * no end-of-file condition is returned after rewinding.  Reopening the
  530.      * file seems to work.  We can get away with this because we only
  531.      * reposition in "permanent" files that we are reading.
  532.      */
  533.     char    temp[NFILEN];
  534.     fgetname(ffp, temp);
  535.     (void)fclose(ffp);
  536.     ffp = fopen(temp, FOPEN_READ);
  537. #else
  538.     fseek (ffp,0L,0);
  539. #endif
  540. }
  541. #endif
  542.  
  543. /*
  544.  * Close a file. Should look at the status in all systems.
  545.  */
  546. int
  547. ffclose(void)
  548. {
  549.     int s = 0;
  550.  
  551.     free_fline();    /* free this since we do not need it anymore */
  552.  
  553. #if SYS_UNIX || SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT
  554. #if OPT_SHELL
  555.     if (fileispipe) {
  556.         npclose(ffp);
  557.         mlforce("[Read %d lines%s]",
  558.             count_fline,
  559.             interrupted() ? "- Interrupted" : "");
  560. #ifdef    MDCHK_MODTIME
  561.         (void)check_visible_modtimes();
  562. #endif
  563.     } else
  564. #endif
  565.     {
  566.         s = fclose(ffp);
  567.     }
  568.         if (s != 0) {
  569.         mlerror("closing");
  570.                 return(FIOERR);
  571.         }
  572. #else
  573.         (void)fclose(ffp);
  574. #endif
  575.         return (FIOSUC);
  576. }
  577.  
  578. /*
  579.  * Write a line to the already opened file. The "buf" points to the buffer,
  580.  * and the "nbuf" is its length, less the free newline. Return the status.
  581.  */
  582. int
  583. ffputline(const char *buf, int nbuf, const char *ending)
  584. {
  585.         register int    i;
  586.     for (i = 0; i < nbuf; ++i)
  587.         if (ffputc(char2int(buf[i])) == FIOERR)
  588.             return FIOERR;
  589.  
  590.     while (*ending != EOS) {
  591.         if (*ending != '\r' || i == 0 || buf[i-1] != '\r')
  592.             fputc(*ending, ffp);
  593.         ending++;
  594.     }
  595.  
  596.         if (ferror(ffp)) {
  597.                 mlerror("writing");
  598.                 return (FIOERR);
  599.         }
  600.  
  601.         return (FIOSUC);
  602. }
  603.  
  604. /*
  605.  * Write a char to the already opened file.
  606.  * Return the status.
  607.  */
  608. int
  609. ffputc(int c)
  610. {
  611.     char    d = (char)c;
  612.  
  613. #if    OPT_ENCRYPT
  614.     if (cryptflag)
  615.         ue_crypt(&d, 1);
  616. #endif
  617.     fputc(d, ffp);
  618.  
  619.         if (ferror(ffp)) {
  620.                 mlerror("writing");
  621.                 return (FIOERR);
  622.         }
  623.  
  624.         return (FIOSUC);
  625. }
  626.  
  627. /*
  628.  * Read a line from a file, and store the bytes in an allocated buffer.
  629.  * "flen" is the length of the buffer. Reallocate and copy as necessary.
  630.  * Check for I/O errors. Return status.
  631.  */
  632.  
  633. int
  634. ffgetline(
  635. int *lenp)    /* to return the final length */
  636. {
  637.         register int c;        /* current character read */
  638.         register ALLOC_T i;    /* current index into fline */
  639.     register char *tmpline;    /* temp storage for expanding line */
  640.  
  641.     /* if we are at the end...return it */
  642.     if (eofflag)
  643.         return(FIOEOF);
  644.  
  645.     /* if we don't have an fline, allocate one */
  646.     if (fline == NULL)
  647.         if ((fline = castalloc(char,flen = NSTRING)) == NULL)
  648.             return(FIOMEM);
  649.  
  650.     /* read the line in */
  651.     i = 0;
  652.     for_ever {
  653. #if NEVER && OPT_WORKING && ! HAVE_RESTARTABLE_PIPEREAD
  654. /* i think some older kernels may lose data if a signal is
  655. received after some data has been tranferred to the user's buffer, so
  656. i don't think this code is safe... */
  657.         for_ever {
  658.             /* clear our signal memory.  this should
  659.               become a bitmap if we need to notice more than
  660.               just alarm signals */
  661.             signal_was = 0;
  662.             errno = 0;
  663.             c = fgetc(ffp);
  664.             if (!ferror(ffp) || errno != EINTR ||
  665.                     signal_was != SIGALRM)
  666.                 break;
  667.             clearerr(ffp);
  668.         }
  669. #else
  670.         c = fgetc(ffp);
  671. #endif
  672.         if ((c == '\n') || feof(ffp) || ferror(ffp))
  673.             break;
  674.         if (interrupted()) {
  675.             free_fline();
  676.             *lenp = 0;
  677.             return FIOABRT;
  678.         }
  679.                 fline[i++] = (char)c;
  680.         /* if it's longer, get more room */
  681.                 if (i >= flen) {
  682.             /* "Small" exponential growth - EJK */
  683.             ALLOC_T growth = (flen >> 3) + NSTRING;
  684.             if ((tmpline = castalloc(char,flen+growth)) == NULL)
  685.                         return(FIOMEM);
  686.                     (void)memcpy(tmpline, fline, (SIZE_T)flen);
  687.                     flen += growth;
  688.             free(fline);
  689.                     fline = tmpline;
  690.                 }
  691. #if OPT_WORKING
  692.         cur_working++;
  693. #endif
  694.         }
  695.  
  696.  
  697.     *lenp = i;    /* return the length, not including final null */
  698.         fline[i] = EOS;
  699.  
  700.     /* test for any errors that may have occurred */
  701.         if (c == EOF) {
  702.         if (!feof(ffp) && ferror(ffp)) {
  703.             mlerror("reading");
  704.             return(FIOERR);
  705.                 }
  706.  
  707.                 if (i != 0)
  708.             eofflag = TRUE;
  709.         else
  710.             return(FIOEOF);
  711.         }
  712.  
  713. #if    OPT_ENCRYPT
  714.     /* decrypt the line */
  715.     if (cryptflag)
  716.         ue_crypt(fline, i);
  717. #endif
  718.     count_fline++;
  719.         return (eofflag ? FIOFUN : FIOSUC);
  720. }
  721.  
  722. /*
  723.  * isready_c()
  724.  *
  725.  * This fairly non-portable addition to the stdio set of macros is used to
  726.  * see if stdio has data for us, without actually reading it and possibly
  727.  * blocking.  If you have trouble building this, just define no_isready_c
  728.  * below, so that ffhasdata() always returns FALSE.  If you want to make it
  729.  * work, figure out how your getc in stdio.h knows whether or not to call
  730.  * _filbuf() (or the equivalent), and write isready_c so that it returns
  731.  * true if the buffer has chars available now.  The big win in getting it
  732.  * to work is that reading the output of a pipe (e.g.  ":e !co -p file.c")
  733.  * is _much_much_ faster, and I don't have to futz with non-blocking
  734.  * reads...
  735.  */
  736.  
  737. #ifndef isready_c
  738. #  if CC_TURBO
  739. #    define    isready_c(p)    ( (p)->bsize > ((p)->curp - (p)->buffer) )
  740. #  endif
  741. #  if SYS_OS2_EMX
  742. #    define    isready_c(p)    ( (p)->_rcount > 0)
  743. #  endif
  744. #  if SYS_VMS
  745. #    define    isready_c(p)    ( (*p)->_cnt > 0)
  746. #  endif
  747. #  if SYS_WINNT && !defined( __BORLANDC__ )
  748. #    define    isready_c(p)    ( (p)->_cnt > 0)
  749. #  endif
  750. #endif
  751.  
  752. int
  753. ffhasdata(void)
  754. {
  755. #ifdef isready_c
  756.     if (isready_c(ffp))
  757.         return TRUE;
  758. #endif
  759. #if defined(FIONREAD) && !SYS_WINNT
  760.     {
  761.     long x;
  762.     return(((ioctl(fileno(ffp),FIONREAD,(caddr_t)&x) < 0) || x == 0) ? FALSE : TRUE);
  763.     }
  764. #else
  765.     return FALSE;
  766. #endif
  767. }
  768.