home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / fileio.c < prev    next >
C/C++ Source or Header  |  1992-12-14  |  11KB  |  539 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.  * $Log: fileio.c,v $
  6.  * Revision 1.30  1992/08/20  23:40:48  foxharp
  7.  * typo fixes -- thanks, eric
  8.  *
  9.  * Revision 1.29  1992/07/28  21:42:36  foxharp
  10.  * linux switched to GNU stdio... okay, so maybe isready_c() _wasn't_
  11.  * such a good idea...
  12.  *
  13.  * Revision 1.28  1992/07/24  18:21:17  foxharp
  14.  * cleanup and better comments re: isready_c, and linux support
  15.  *
  16.  * Revision 1.27  1992/06/25  23:00:50  foxharp
  17.  * changes for dos/ibmpc
  18.  *
  19.  * Revision 1.26  1992/05/19  08:55:44  foxharp
  20.  * more prototype and shadowed decl fixups
  21.  *
  22.  * Revision 1.25  1992/05/16  14:02:55  pgf
  23.  * header/typedef fixups
  24.  *
  25.  * Revision 1.24  1992/05/16  12:00:31  pgf
  26.  * prototypes/ansi/void-int stuff/microsoftC
  27.  *
  28.  * Revision 1.23  1992/04/14  08:51:44  pgf
  29.  * ifdef fixups for pjr and DOS
  30.  *
  31.  * Revision 1.22  1992/03/25  19:13:17  pgf
  32.  * BSD portability changes
  33.  *
  34.  * Revision 1.21  1992/03/19  23:21:12  pgf
  35.  * moved includes to top
  36.  *
  37.  * Revision 1.20  1992/01/05  00:06:13  pgf
  38.  * split mlwrite into mlwrite/mlprompt/mlforce to make errors visible more
  39.  * often.  also normalized message appearance somewhat.
  40.  *
  41.  * Revision 1.19  1992/01/01  16:17:46  pgf
  42.  * improve behavior of long line reads (from Eric Krohn)
  43.  *
  44.  * Revision 1.18  1991/11/27  10:09:09  pgf
  45.  * move some ifdef, so as not to leave empty if body
  46.  *
  47.  * Revision 1.17  1991/11/16  18:31:39  pgf
  48.  * ifdef with FIONREAD instead of BSD in typahead()
  49.  *
  50.  * Revision 1.16  1991/11/08  13:22:56  pgf
  51.  * moved dosfiles processing out to file.c, and
  52.  * made aborts of file reads report FIOABRT, and
  53.  * hopefully, editing binary files should work better (don't
  54.  * use strncpy on lines)
  55.  *
  56.  * Revision 1.15  1991/11/07  02:00:32  pgf
  57.  * lint cleanup
  58.  *
  59.  * Revision 1.14  1991/11/03  17:38:38  pgf
  60.  * fixed some slop in the cr/nl checking
  61.  *
  62.  * Revision 1.13  1991/11/01  14:38:00  pgf
  63.  * saber cleanup
  64.  *
  65.  * Revision 1.12  1991/10/23  12:05:37  pgf
  66.  * changed filio.h to ioctl.h as the source of FIONREAD
  67.  *
  68.  * Revision 1.11  1991/10/22  14:08:23  pgf
  69.  * took out old ifdef BEFORE code
  70.  *
  71.  * Revision 1.10  1991/10/10  12:31:53  pgf
  72.  * added more "ff" utilities:  ffread, ffseek, ffrewind, ffsize
  73.  *
  74.  * Revision 1.9  1991/09/25  00:24:27  pgf
  75.  * ffhasdata now works most of the time for system V, by simply checking
  76.  * the stdio buffer -- no system call necessary
  77.  *
  78.  * Revision 1.8  1991/08/08  13:20:23  pgf
  79.  * set "dosfile" global after reading each line
  80.  *
  81.  * Revision 1.7  1991/08/07  12:35:07  pgf
  82.  * added RCS log messages
  83.  *
  84.  * revision 1.6
  85.  * date: 1991/06/18 20:08:09;
  86.  * added decl for FILE *npopen()
  87.  * 
  88.  * revision 1.5
  89.  * date: 1991/04/22 09:02:03;
  90.  * portability
  91.  * 
  92.  * revision 1.4
  93.  * date: 1991/04/08 15:49:44;
  94.  * added ffhasdata routine
  95.  * 
  96.  * revision 1.3
  97.  * date: 1991/04/04 09:37:25;
  98.  * minor fixes
  99.  * 
  100.  * revision 1.2
  101.  * date: 1990/10/12 19:30:46;
  102.  * added beeps on non-writeable
  103.  * 
  104.  * revision 1.1
  105.  * date: 1990/09/21 10:25:18;
  106.  * initial vile RCS revision
  107.  */
  108.  
  109. #include        <stdio.h>
  110. #include    "estruct.h"
  111. #include        "edef.h"
  112. #if UNIX
  113. #include    <sys/stat.h>
  114. #include        <errno.h>
  115. #endif
  116. #include        <fcntl.h>
  117. #if    BERK
  118. #include "sys/ioctl.h"
  119. #endif
  120. #if MSDOS
  121. #include    <sys/stat.h>
  122. #endif
  123.  
  124. FILE    *ffp;        /* File pointer, all functions. */
  125. int fileispipe;
  126. int eofflag;        /* end-of-file flag */
  127.  
  128. /*
  129.  * Open a file for reading.
  130.  */
  131. int
  132. ffropen(fn)
  133. char    *fn;
  134. {
  135. #if UNIX
  136.     FILE *npopen();
  137. #endif
  138.  
  139.  
  140. #if UNIX
  141.     
  142.     if (*fn == '!') {
  143.             if ((ffp=npopen(fn+1, "r")) == NULL)
  144.                     return (FIOERR);
  145.         fileispipe = TRUE;
  146.     } else {
  147.             if ((ffp=fopen(fn, "r")) == NULL) {
  148.             extern int errno;
  149.             if (errno == ENOENT)
  150.                         return (FIOFNF);
  151.                     return (FIOERR);
  152.         }
  153.         fileispipe = FALSE;
  154.     }
  155. #else
  156.         if ((ffp=fopen(fn, "r")) == NULL)
  157.                 return (FIOFNF);
  158. #endif
  159.     eofflag = FALSE;
  160.         return (FIOSUC);
  161. }
  162.  
  163. /*
  164.  * Open a file for writing. Return TRUE if all is well, and FALSE on error
  165.  * (cannot create).
  166.  */
  167. int
  168. ffwopen(fn)
  169. char    *fn;
  170. {
  171. #if UNIX
  172.     FILE *npopen();
  173.     if (*fn == '!') {
  174.             if ((ffp=npopen(fn+1, "w")) == NULL) {
  175.                     mlforce("[Cannot open pipe for writing]");
  176.             TTbeep();
  177.                     return (FIOERR);
  178.         }
  179.         fileispipe = TRUE;
  180.     } else {
  181.             if ((ffp=fopen(fn, "w")) == NULL) {
  182.                     mlforce("[Cannot open file for writing]");
  183.             TTbeep();
  184.                     return (FIOERR);
  185.         }
  186.         fileispipe = FALSE;
  187.     }
  188. #else
  189. #if     VMS
  190.         register int    fd;
  191.  
  192.         if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
  193.         || (ffp=fdopen(fd, "w")) == NULL) {
  194.                 mlforce("[Cannot open file for writing]");
  195.                 return (FIOERR);
  196.         }
  197. #else
  198.         if ((ffp=fopen(fn, "w")) == NULL) {
  199.                 mlforce("[Cannot open file for writing]");
  200.                 return (FIOERR);
  201.         }
  202. #endif
  203. #endif
  204.         return (FIOSUC);
  205. }
  206.  
  207. /* is the file read-only?  true or false */
  208. /* #if UNIX  / * don't know how to do it for other systems */
  209. int
  210. ffronly(fn)
  211. char    *fn;
  212. {
  213.     int fd;
  214.  
  215.     if (*fn == '!') {
  216.         return TRUE;
  217.     } else {
  218.             if ((fd=open(fn, O_WRONLY)) < 0) {
  219.                     return TRUE;
  220.         }
  221.         close(fd);
  222.         return FALSE;
  223.     }
  224. }
  225. /* #endif */
  226.  
  227. #if UNIX
  228. long
  229. ffsize()
  230. {
  231.     struct stat statbuf;
  232.     if (fstat(fileno(ffp), &statbuf) == 0) {
  233.         return (long)statbuf.st_size;
  234.     }
  235.         mlforce("[File sizing error]");
  236.         return -1;
  237. }
  238. #endif
  239.  
  240. #if MSDOS
  241. long
  242. ffsize(void)
  243. {
  244.     int fd = fileno(ffp);
  245.     return  filelength(fd);
  246. }
  247. #endif
  248.  
  249. int
  250. ffread(buf,len)
  251. char *buf;
  252. long len;
  253. {
  254.     return read(fileno(ffp), buf, (int)len);
  255. }
  256.  
  257. void
  258. ffseek(n)
  259. long n;
  260. {
  261.     fseek (ffp,n,0);
  262. }
  263.  
  264. void
  265. ffrewind()
  266. {
  267.     fseek (ffp,0L,0);
  268. }
  269.  
  270. /*
  271.  * Close a file. Should look at the status in all systems.
  272.  */
  273. int
  274. ffclose()
  275. {
  276.     int s = TRUE;
  277.  
  278.     /* free this since we do not need it anymore */
  279.     if (fline) {
  280.         free(fline);
  281.         fline = NULL;
  282.         flen = 0;
  283.     }
  284.  
  285. #if UNIX | (MSDOS & (LATTICE | MSC | TURBO | ZTC))
  286. #if UNIX
  287.     
  288.     if (fileispipe)
  289.         npclose(ffp);
  290.     else
  291. #endif
  292.         s = fclose(ffp);
  293.         if (s != 0) {
  294.                 mlforce("[Error on close]");
  295.                 return(FIOERR);
  296.         }
  297.         return(FIOSUC);
  298. #else
  299.         fclose(ffp);
  300.         return (FIOSUC);
  301. #endif
  302. }
  303.  
  304. /*
  305.  * Write a line to the already opened file. The "buf" points to the buffer,
  306.  * and the "nbuf" is its length, less the free newline. Return the status.
  307.  * Check only at the newline.
  308.  */
  309. int
  310. ffputline(buf, nbuf, do_cr)
  311. char    buf[];
  312. int    nbuf;
  313. int    do_cr;
  314. {
  315.         register int    i;
  316. #if    CRYPT
  317.     char c;        /* character to translate */
  318.  
  319.     if (cryptflag) {
  320.             for (i = 0; i < nbuf; ++i) {
  321.             c = buf[i] & 0xff;
  322.             crypt(&c, 1);
  323.             fputc(c, ffp);
  324.         }
  325.     } else
  326.             for (i = 0; i < nbuf; ++i)
  327.                     fputc(buf[i]&0xFF, ffp);
  328. #else
  329.         for (i = 0; i < nbuf; ++i)
  330.                 fputc(buf[i]&0xFF, ffp);
  331. #endif
  332.  
  333. #if    ST520
  334.         fputc('\r', ffp);
  335. #endif        
  336. #if DOSFILES
  337.     if (do_cr) { /* put out CR, unless we just did */
  338.         if (i == 0 || buf[i-1] != '\r')
  339.                 fputc('\r', ffp);
  340.     }
  341. #endif
  342.         fputc('\n', ffp);
  343.  
  344.         if (ferror(ffp)) {
  345.                 mlforce("[Write I/O error]");
  346.                 return (FIOERR);
  347.         }
  348.  
  349.         return (FIOSUC);
  350. }
  351. /*
  352.  * Write a charto the already opened file.
  353.  * Return the status.
  354.  */
  355. int
  356. ffputc(c)
  357. int c;
  358. {
  359.     c &= 0xff;
  360.  
  361. #if    CRYPT
  362.     if (cryptflag)
  363.         crypt(&c, 1);
  364. #endif
  365.         fputc(c, ffp);
  366.  
  367.         if (ferror(ffp)) {
  368.                 mlforce("[Write I/O error]");
  369.                 return (FIOERR);
  370.         }
  371.  
  372.         return (FIOSUC);
  373. }
  374.  
  375. /*
  376.  * Read a line from a file, and store the bytes in an allocated buffer.
  377.  * "flen" is the length of the buffer. Reallocate and copy as necessary.
  378.  * Check for I/O errors. Return status.
  379.  */
  380. int
  381. ffgetline(lenp)
  382. int *lenp;    /* to return the final length */
  383. {
  384.         register int c;        /* current character read */
  385.         register int i;        /* current index into fline */
  386.     register char *tmpline;    /* temp storage for expanding line */
  387.  
  388.     /* if we are at the end...return it */
  389.     if (eofflag)
  390.         return(FIOEOF);
  391.  
  392.     /* if we don't have an fline, allocate one */
  393.     if (fline == NULL)
  394.         if ((fline = malloc(flen = NSTRING)) == NULL)
  395.             return(FIOMEM);
  396.  
  397.     /* read the line in */
  398.         i = 0;
  399.         while ((c = fgetc(ffp)) != EOF && c != '\n') {
  400.         if (interrupted) {
  401.             free(fline);
  402.             fline = NULL;
  403.             *lenp = 0;
  404.             return FIOABRT;
  405.         }
  406.                 fline[i++] = c;
  407.         /* if it's longer, get more room */
  408.                 if (i >= flen) {
  409.             /* "Small" exponential growth - EJK */
  410.             long growth = (flen >> 3) + NSTRING;
  411.             if ((tmpline = malloc(flen+growth)) == NULL)
  412.                         return(FIOMEM);
  413.                     memcpy(tmpline, fline, flen);
  414.                     flen += growth;
  415.                     free(fline);
  416.                     fline = tmpline;
  417.                 }
  418.         }
  419.  
  420. #if !DOSFILES
  421. # if    ST520
  422.     if(c == '\n') {
  423.         if(i > 0 && fline[i-1] == '\r') {
  424.             i--;
  425.         }
  426.     }
  427. # endif
  428. #endif
  429.  
  430.     *lenp = i;    /* return the length, not including final null */
  431.         fline[i] = 0;
  432.  
  433.     /* test for any errors that may have occurred */
  434.         if (c == EOF) {
  435.                 if (ferror(ffp)) {
  436.                         mlforce("[File read error]");
  437.                         return(FIOERR);
  438.                 }
  439.  
  440.                 if (i != 0)
  441.             eofflag = TRUE;
  442.         else
  443.             return(FIOEOF);
  444.         }
  445.  
  446. #if    CRYPT
  447.     /* decrypt the line */
  448.     if (cryptflag)
  449.         crypt(fline, i);
  450. #endif
  451.         return(FIOSUC);
  452. }
  453.  
  454. /* 
  455.  * isready_c()
  456.  *
  457.  * This fairly non-portable addition to the stdio set of macros is used to
  458.  * see if stdio has data for us, without actually reading it and possibly
  459.  * blocking.  If you have trouble building this, just define no_isready_c
  460.  * below, so that ffhasdata() always returns FALSE.  If you want to make it
  461.  * work, figure out how your getc in stdio.h knows whether or not to call
  462.  * _filbuf() (or the equivalent), and write isready_c so that it returns
  463.  * true if the buffer has chars available now.  The big win in getting it
  464.  * to work is that reading the output of a pipe (e.g.  ":e !co -p file.c")
  465.  * is _much_much_ faster, and I don't have to futz with non-blocking
  466.  * reads...
  467.  */
  468.  
  469. /* #define no_isready_c 1 */
  470.  
  471. #ifndef no_isready_c
  472. # ifdef __sgetc
  473.    /* 386bsd */
  474. #  define    isready_c(p)    ( (p)->_r > 0)
  475. # else
  476. #  ifdef _STDIO_UCHAR_
  477.     /* C E Chew's package */
  478. #   define     isready_c(p)    ( (p)->__rptr < (p)->__rend)
  479. #  else
  480. #   ifdef _G_FOPEN_MAX
  481.     /* GNU iostream/stdio library */
  482. #    define     isready_c(p)    ( (p)->_gptr < (p)->_egptr)
  483. #   else
  484.     /* most other stdio's (?) */
  485. #    define    isready_c(p)    ( (p)->_cnt > 0)
  486. #   endif
  487. #  endif
  488. # endif
  489. #endif
  490.  
  491.  
  492. int
  493. ffhasdata()
  494. {
  495. #ifdef isready_c
  496.     if (isready_c(ffp))
  497.         return TRUE;
  498. #endif
  499. #ifdef    FIONREAD
  500.     {
  501.     long x;
  502.     return(((ioctl(fileno(ffp),FIONREAD,&x) < 0) || x == 0) ? FALSE : TRUE);
  503.     }
  504. #else
  505.     return FALSE;
  506. #endif
  507. }
  508.  
  509. #if    AZTEC & MSDOS
  510. #undef    fgetc
  511. /*    a1getc:        Get an ascii char from the file input stream
  512.             but DO NOT strip the high bit
  513. */
  514.  
  515. int a1getc(fp)
  516.  
  517. FILE *fp;
  518.  
  519. {
  520.     int c;        /* translated character */
  521.  
  522.     c = getc(fp);    /* get the character */
  523.  
  524.     /* if its a <LF> char, throw it out  */
  525.     while (c == '\n')
  526.         c = getc(fp);
  527.  
  528.     /* if its a <RETURN> char, change it to a LF */
  529.     if (c == '\r')
  530.         c = '\n';
  531.  
  532.     /* if its a ^Z, its an EOF */
  533.     if (c == 26)
  534.         c = EOF;
  535.  
  536.     return(c);
  537. }
  538. #endif
  539.