/* * l z i o . c * * I/O buffer management. All input/output I/O is done through these * routines (and the macros in lz.h). The rules of the game are: * * input via GET and GETBUF. * GET returns an 8-bit byte, or -1 on eof/error. * GETBUF returns the number of things gotten, or -1 on eof/error. * * output via PUT and PUTBUF * No return on error. * flush output by LZ_FLUSH before closing files -- or you'll lose data. */ #include "lz.h" #ifndef OS_DEBUG_IO LZ lz_buffer = { NULL, NULL, /* ip, iend */ lz_buffer.obuf, /* op */ &lz_buffer.obuf[MAXIO], /* oend */ }; /* * Low-level I/O routines. */ int lz_fill() { register int i; extern char *infilename; #ifdef unix i = read(fileno(stdin), (char *) LZ_IO.ibuf, MAXIO); #else i = fread((char *) LZ_IO.ibuf, 1, MAXIO, stdin); if (ferror(stdin)) { perror(infilename); exit(IO_ERROR); } #endif if (i <= 0) return (EOF); else { LZ_IO.ip = LZ_IO.ibuf; LZ_IO.iend = &LZ_IO.ibuf[i]; #if UCHAR return (*LZ_IO.ip++); #else return (*LZ_IO.ip++ & 0xFF); #endif } } lz_flush() { register int count; extern char *outfilename; count = LZ_IO.op - &LZ_IO.obuf[0]; #ifdef unix if (write(fileno(stdout), (char *) LZ_IO.obuf, count) != count) { perror(outfilename); fprintf(stderr, "Can't write to \"%s\"\n", outfilename); exit(IO_ERROR); } #else if (fwrite((char *) LZ_IO.obuf, 1, count, stdout) != count || ferror(stdout)) { perror(outfilename); exit(IO_ERROR); } #endif LZ_IO.op = LZ_IO.obuf; } int lz_getbuf(buffer, count) char_type *buffer; int count; /* * Read a block of data -- be clever. Return number gotten, or -1 * on eof. */ { register char_type *bp; /* -> buffer */ register char_type *ip; /* -> I/O buffer */ register char_type *ep; /* End of segment */ register int remaining; /* Size of segment */ int datum; if (count == 0) /* Shouldn't happen */ return (0); bp = buffer; while (--count >= 0) { if ((datum = GET()) == EOF) /* Maybe fill LZ buff */ break; *bp++ = datum; remaining = LZ_IO.iend - (ip = LZ_IO.ip); if (remaining > count) remaining = count; ep = &ip[remaining]; while (ip < ep) *bp++ = *ip++; count -= remaining; LZ_IO.ip = ip; /* Refresh buffer */ } return ((bp == buffer) ? -1 : bp - buffer); } int lz_putbuf(bp, count) register char_type *bp; int count; /* * Write a block of data -- be clever. */ { register char_type *op; /* -> I/O buffer */ register char_type *ep; /* End of segment */ register int remaining; /* Size of segment */ while (--count >= 0) { PUT(*bp++); /* Forces a buffer */ remaining = LZ_IO.oend - (op = LZ_IO.op); if (remaining > count) remaining = count; ep = &op[remaining]; while (op < ep) *op++ = *bp++; count -= remaining; LZ_IO.op = op; /* Refresh buffer */ } } #endif /* * getredirection() is intended to aid in porting C programs * to VMS (Vax-11 C) which does not support '>' and '<' * I/O redirection. With suitable modification, it may * useful for other portability problems as well. */ #ifdef vms int getredirection(argc, argv) int argc; char **argv; /* * Process vms redirection arg's. Exit if any error is seen. * If getredirection() processes an argument, it is erased * from the vector. getredirection() returns a new argc value. * * Warning: do not try to simplify the code for vms. The code * presupposes that getredirection() is called before any data is * read from stdin or written to stdout. * * Normal usage is as follows: * * main(argc, argv) * int argc; * char *argv[]; * { * argc = getredirection(argc, argv); * } */ { register char *ap; /* Argument pointer */ int i; /* argv[] index */ int j; /* Output index */ int file; /* File_descriptor */ for (j = i = 1; i < argc; i++) { /* Do all arguments */ switch (*(ap = argv[i])) { case '<': /* ': /* >file or >>file */ if (*++ap == '>') { /* >>file */ /* * If the file exists, and is writable by us, * call freopen to append to the file (using the * file's current attributes). Otherwise, create * a new file with "vanilla" attributes as if * the argument was given as ">filename". * access(name, 2) is TRUE if we can write on * the specified file. */ if (access(++ap, 2) == 0) { if (freopen(ap, "a", stdout) != NULL) break; /* Exit case statement */ perror(ap); /* Error, can't append */ exit(IO_ERROR); /* After access test */ } /* If file accessable */ } /* * On vms, we want to create the file using "standard" * record attributes. create(...) creates the file * using the caller's default protection mask and * "variable length, implied carriage return" * attributes. dup2() associates the file with stdout. */ if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1 || dup2(file, fileno(stdout)) == -1) { perror(ap); /* Can't create file */ exit(IO_ERROR); /* is a fatal error */ } /* If '>' creation */ break; /* Exit case test */ default: argv[j++] = ap; /* Not a redirector */ break; /* Exit case test */ } } /* For all arguments */ argv[j] = NULL; /* Terminate argv[] */ return (j); /* Return new argc */ } #endif