summaryrefslogtreecommitdiff
path: root/tree/src/vi/ex-070224/exrecover.c
diff options
context:
space:
mode:
authorThomas Ulmer <thomasmulmer02@gmail.com>2026-03-01 11:37:31 -0800
committerThomas Ulmer <thomasmulmer02@gmail.com>2026-03-01 11:37:31 -0800
commite01b84a6698f5060fd7dea789fc0ffa872f26b15 (patch)
treeda1d4369048833f0496ae51d400d118f30c499bd /tree/src/vi/ex-070224/exrecover.c
parent6d8430971dada74478a0cd2c9eca2272a105b744 (diff)
remove tree
Diffstat (limited to 'tree/src/vi/ex-070224/exrecover.c')
-rw-r--r--tree/src/vi/ex-070224/exrecover.c905
1 files changed, 0 insertions, 905 deletions
diff --git a/tree/src/vi/ex-070224/exrecover.c b/tree/src/vi/ex-070224/exrecover.c
deleted file mode 100644
index 17ba06f..0000000
--- a/tree/src/vi/ex-070224/exrecover.c
+++ /dev/null
@@ -1,905 +0,0 @@
-/*
- * This code contains changes by
- * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
- *
- * Conditions 1, 2, and 4 and the no-warranty notice below apply
- * to these changes.
- *
- *
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *
- * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * Redistributions of source code and documentation must retain the
- * above copyright notice, this list of conditions and the following
- * disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed or owned by Caldera
- * International, Inc.
- * Neither the name of Caldera International, Inc. nor the names of
- * other contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
- * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
- * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef __GNUC__
-#define UNUSED __attribute__ ((unused))
-#else
-#define UNUSED
-#endif
-
-#ifndef lint
-#ifdef DOSCCS
-char *copyright =
-"@(#) Copyright (c) 1980 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif
-static char sccsid[] UNUSED = "@(#)exrecover.c 1.23 (gritter) 12/25/06";
-#endif
-
-/* from exrecover.c 7.9.2 (2.11BSD) 1996/10/26 */
-
-#include <stdarg.h>
-#ifdef notdef /* GR */
-#include <stdio.h> /* mjm: BUFSIZ: stdio = 512, VMUNIX = 1024 */
-#undef BUFSIZ /* mjm: BUFSIZ different */
-#undef EOF /* mjm: EOF and NULL effectively the same */
-#undef NULL
-#else
-#define xstderr (int*)0
-typedef int xFILE;
-extern void perror(const char *);
-extern int vsprintf(char *, const char *, va_list);
-#endif
-
-#define var
-
-#include "ex.h"
-#include "ex_temp.h"
-#include "ex_tty.h"
-#include <dirent.h>
-#include <time.h>
-
-#ifndef MAXNAMLEN
-#ifdef FNSIZE
-#define MAXNAMLEN FNSIZE
-#else
-#ifdef NAME_MAX
-#define MAXNAMLEN NAME_MAX
-#else
-#define MAXNAMLEN 255
-#endif
-#endif
-#endif
-
-#define TMP "/var/tmp"
-
-#ifdef LANGMSG
-nl_catd catd;
-#endif
-
-char xstr[1]; /* make loader happy */
-int tfile = -1; /* ditto */
-
-/*
- *
- * This program searches through the specified directory and then
- * the directory /usr/preserve looking for an instance of the specified
- * file from a crashed editor or a crashed system.
- * If this file is found, it is unscrambled and written to
- * the standard output.
- *
- * If this program terminates without a "broken pipe" diagnostic
- * (i.e. the editor doesn't die right away) then the buffer we are
- * writing from is removed when we finish. This is potentially a mistake
- * as there is not enough handshaking to guarantee that the file has actually
- * been recovered, but should suffice for most cases.
- */
-
-/*
- * Here we save the information about files, when
- * you ask us what files we have saved for you.
- * We buffer file name, number of lines, and the time
- * at which the file was saved.
- */
-struct svfile {
- char sf_name[FNSIZE + 1];
- int sf_lines;
- char sf_entry[MAXNAMLEN + 1];
- time_t sf_time;
-};
-
-#define ignorl(a) a
-
-/*
- * This directory definition also appears (obviously) in expreserve.c.
- * Change both if you change either.
- */
-#ifdef notdef
-char mydir[] = "/usr/preserve";
-#else
-char mydir[] = "/var/lib/ex";
-#endif
-
-/*
- * Limit on the number of printed entries
- * when an, e.g. ``ex -r'' command is given.
- */
-#define NENTRY 50
-
-char nb[BUFSIZ];
-int vercnt; /* Count number of versions of file found */
-
-extern void error(char *, ...);
-extern void listfiles(char *);
-extern void enter(struct svfile *, char *, int);
-extern int qucmp(struct svfile *, struct svfile *);
-extern void findtmp(char *);
-extern void searchdir(char *);
-extern int yeah(char *);
-extern int preserve(void);
-extern void scrapbad(void);
-extern void putfile(int);
-extern void wrerror(void);
-extern void clrstats(void);
-extern void getline(line);
-extern char *getblock(line, int);
-extern void blkio(bloc, char *, ssize_t (*)(int, void *, size_t));
-extern void syserror(void);
-extern void xvfprintf(xFILE *, char *, va_list);
-extern void xfprintf(xFILE *, char *, ...);
-
-int
-main(int argc, char *argv[])
-{
- register char *cp;
- register int b, i;
-
- /*
- * Initialize the built-in memory allocator.
- */
-#ifdef VMUNIX
- poolsbrk(0);
-#endif
- linebuf = calloc(LBSIZE = BUFSIZ<4096?4096:BUFSIZ, sizeof *linebuf);
- genbuf = calloc(MAXBSIZE, sizeof *genbuf);
-#ifdef LANGMSG
- setlocale(LC_MESSAGES, "");
- catd = catopen(CATNAME, NL_CAT_LOCALE);
-#endif
-
- /*
- * Initialize as though the editor had just started.
- */
- fendcore = (line *) sbrk(0);
- dot = zero = dol = fendcore;
- one = zero + 1;
- endcore = fendcore - 2;
- iblock = oblock = -1;
-
- /*
- * If given only a -r argument, then list the saved files.
- */
- if (argc == 2 && strcmp(argv[1], "-r") == 0) {
- listfiles(mydir);
- listfiles(TMP);
- exit(0);
- }
- if (argc != 3)
- error(catgets(catd, 2, 1,
- " Wrong number of arguments to exrecover"), 0);
-
- strcpy(file, argv[2]);
-
- /*
- * Search for this file.
- */
- findtmp(argv[1]);
-
- /*
- * Got (one of the versions of) it, write it back to the editor.
- */
- cp = ctime(&H.Time);
- cp[19] = 0;
- xfprintf(xstderr, catgets(catd, 2, 2, " [Dated: %s"), cp);
- xfprintf(xstderr, vercnt > 1 ? catgets(catd, 2, 3,
- ", newest of %d saved]")
- : catgets(catd, 2, 4, "]"), vercnt);
- H.Flines++;
-
- /*
- * Allocate space for the line pointers from the temp file.
- */
- if ((char *) sbrk(H.Flines * sizeof (line)) == (char *) -1)
- /*
- * Good grief.
- */
- error(catgets(catd, 1, 5, " Not enough core for lines"), 0);
-#ifdef DEBUG
- xfprintf(xstderr, "%d lines\n", H.Flines);
-#endif
-
- /*
- * Now go get the blocks of seek pointers which are scattered
- * throughout the temp file, reconstructing the incore
- * line pointers at point of crash.
- */
- b = 0;
- while (H.Flines > 0) {
- ignorl(lseek(tfile, (off_t) ((blocks[b] & BLKMSK) * BUFSIZ),
- SEEK_SET));
- i = H.Flines < BUFSIZ / sizeof (line) ?
- H.Flines * sizeof (line) : BUFSIZ;
- if (read(tfile, (char *) dot, i) != i) {
- perror(nb);
- exit(1);
- }
- dot += i / sizeof (line);
- H.Flines -= i / sizeof (line);
- b++;
- }
- dot--; dol = dot;
-
- /*
- * Sigh... due to sandbagging some lines may really not be there.
- * Find and discard such. This shouldn't happen much.
- */
- scrapbad();
-
- /*
- * Now if there were any lines in the recovered file
- * write them to the standard output.
- */
- if (dol > zero) {
- addr1 = one; addr2 = dol; io = 1;
- putfile(0);
- }
-
- /*
- * Trash the saved buffer.
- * Hopefully the system won't crash before the editor
- * syncs the new recovered buffer; i.e. for an instant here
- * you may lose if the system crashes because this file
- * is gone, but the editor hasn't completed reading the recovered
- * file from the pipe from us to it.
- *
- * This doesn't work if we are coming from an non-absolute path
- * name since we may have chdir'ed but what the hay, noone really
- * ever edits with temporaries in "." anyways.
- */
- if (nb[0] == '/')
- ignore(unlink(nb));
-
- /*
- * Adieu.
- */
- exit(0);
-}
-
-/*
- * Print an error message (notably not in error
- * message file). If terminal is in RAW mode, then
- * we should be writing output for "vi", so don't print
- * a newline which would screw up the screen.
- */
-/*VARARGS2*/
-void
-error(char *str, ...)
-{
- va_list ap;
-
- va_start(ap, str);
- xvfprintf(xstderr, str, ap);
- va_end(ap);
- tcgetattr(2, &tty);
- if (tty.c_lflag & ICANON)
- xfprintf(xstderr, "\n");
- exit(1);
-}
-
-void
-listfiles(char *dirname)
-{
- register DIR *dir;
- struct dirent *dirent;
- int ecount;
- register int f;
- char *cp;
- struct svfile *fp, svbuf[NENTRY];
-
- /*
- * Open /usr/preserve, and go there to make things quick.
- */
- dir = opendir(dirname);
- if (dir == NULL) {
- perror(dirname);
- return;
- }
- if (chdir(dirname) < 0) {
- perror(dirname);
- return;
- }
- xfprintf(xstderr, "%s:\n", dirname);
-
- /*
- * Look at the candidate files in /usr/preserve.
- */
- fp = &svbuf[0];
- ecount = 0;
- while ((dirent = readdir(dir)) != NULL) {
- if (dirent->d_name[0] != 'E')
- continue;
-#ifdef DEBUG
- xfprintf(xstderr, "considering %s\n", dirent->d_name);
-#endif
- /*
- * Name begins with E; open it and
- * make sure the uid in the header is our uid.
- * If not, then don't bother with this file, it can't
- * be ours.
- */
- f = open(dirent->d_name, O_RDONLY);
- if (f < 0) {
-#ifdef DEBUG
- xfprintf(xstderr, "open failed\n");
-#endif
- continue;
- }
- if (read(f, (char *) &H, sizeof H) != sizeof H) {
-#ifdef DEBUG
- xfprintf(xstderr, "culdnt read hedr\n");
-#endif
- ignore(close(f));
- continue;
- }
- ignore(close(f));
- if (getuid() != H.Uid) {
-#ifdef DEBUG
- xfprintf(xstderr, "uid wrong\n");
-#endif
- continue;
- }
-
- /*
- * Saved the day!
- */
- enter(fp++, dirent->d_name, ecount);
- ecount++;
-#ifdef DEBUG
- xfprintf(xstderr, "entered file %s\n", dirent->d_name);
-#endif
- }
- ignore(closedir(dir));
-
- /*
- * If any files were saved, then sort them and print
- * them out.
- */
- if (ecount == 0) {
- xfprintf(xstderr, catgets(catd, 2, 6, "No files saved.\n"));
- return;
- }
- qsort(&svbuf[0], ecount, sizeof svbuf[0], (int(*)(const void *, const void *)) qucmp);
- for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) {
- cp = ctime(&fp->sf_time);
- cp[10] = 0;
- xfprintf(xstderr, catgets(catd, 2, 7, "On %s at "), cp);
- cp[16] = 0;
- xfprintf(xstderr, &cp[11]);
- xfprintf(xstderr, catgets(catd, 2, 8,
- " saved %d lines of file \"%s\"\n"),
- fp->sf_lines, fp->sf_name);
- }
-}
-
-/*
- * Enter a new file into the saved file information.
- */
-void
-enter(struct svfile *fp, char *fname, int count)
-{
- register char *cp, *cp2;
- register struct svfile *f, *fl;
- time_t curtime;
-
- f = 0;
- if (count >= NENTRY) {
- /*
- * My god, a huge number of saved files.
- * Would you work on a system that crashed this
- * often? Hope not. So lets trash the oldest
- * as the most useless.
- *
- * (I wonder if this code has ever run?)
- */
- fl = fp - count + NENTRY - 1;
- curtime = fl->sf_time;
- for (f = fl; --f > fp-count; )
- if (f->sf_time < curtime)
- curtime = f->sf_time;
- for (f = fl; --f > fp-count; )
- if (f->sf_time == curtime)
- break;
- fp = f;
- }
-
- /*
- * Gotcha.
- */
- fp->sf_time = H.Time;
- fp->sf_lines = H.Flines;
- cp2 = fp->sf_name, cp = savedfile;
- while (*cp2++ = *cp++);
- for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;)
- *cp2++ = *cp++;
- *cp2++ = 0;
-}
-
-/*
- * Do the qsort compare to sort the entries first by file name,
- * then by modify time.
- */
-int
-qucmp(struct svfile *p1, struct svfile *p2)
-{
- register int t;
-
- if (t = strcmp(p1->sf_name, p2->sf_name))
- return(t);
- if (p1->sf_time > p2->sf_time)
- return(-1);
- return(p1->sf_time < p2->sf_time);
-}
-
-/*
- * Scratch for search.
- */
-char bestnb[BUFSIZ]; /* Name of the best one */
-long besttime; /* Time at which the best file was saved */
-int bestfd; /* Keep best file open so it dont vanish */
-
-/*
- * Look for a file, both in the users directory option value
- * (i.e. usually /tmp) and in /usr/preserve.
- * Want to find the newest so we search on and on.
- */
-void
-findtmp(char *dir)
-{
-
- /*
- * No name or file so far.
- */
- bestnb[0] = 0;
- bestfd = -1;
-
- /*
- * Search /usr/preserve and, if we can get there, /tmp
- * (actually the users "directory" option).
- */
- searchdir(dir);
- if (chdir(mydir) == 0)
- searchdir(mydir);
- if (bestfd != -1) {
- /*
- * Gotcha.
- * Put the file (which is already open) in the file
- * used by the temp file routines, and save its
- * name for later unlinking.
- */
- tfile = bestfd;
- strcpy(nb, bestnb);
- ignorl(lseek(tfile, (off_t) 0, SEEK_SET));
-
- /*
- * Gotta be able to read the header or fall through
- * to lossage.
- */
- if (read(tfile, (char *) &H, sizeof H) == sizeof H)
- return;
- }
-
- /*
- * Extreme lossage...
- */
- error(catgets(catd, 2, 9, " File not found"), 0);
-}
-
-/*
- * Search for the file in directory dirname.
- *
- * Don't chdir here, because the users directory
- * may be ".", and we would move away before we searched it.
- * Note that we actually chdir elsewhere (because it is too slow
- * to look around in /usr/preserve without chdir'ing there) so we
- * can't win, because we don't know the name of '.' and if the path
- * name of the file we want to unlink is relative, rather than absolute
- * we won't be able to find it again.
- */
-void
-searchdir(char *dirname)
-{
- struct dirent *dirent;
- register DIR *dir;
- /* char dbuf[BUFSIZ]; */
-
- dir = opendir(dirname);
- if (dir == NULL)
- return;
- while ((dirent = readdir(dir)) != NULL) {
- if (dirent->d_name[0] != 'E')
- continue;
- /*
- * Got a file in the directory starting with E...
- * Save a consed up name for the file to unlink
- * later, and check that this is really a file
- * we are looking for.
- */
- ignore(strcat(strcat(strcpy(nb, dirname), "/"), dirent->d_name));
- if (yeah(nb)) {
- /*
- * Well, it is the file we are looking for.
- * Is it more recent than any version we found before?
- */
- if (H.Time > besttime) {
- /*
- * A winner.
- */
- ignore(close(bestfd));
- bestfd = dup(tfile);
- besttime = H.Time;
- strcpy(bestnb, nb);
- }
- /*
- * Count versions so user can be told there are
- * ``yet more pages to be turned''.
- */
- vercnt++;
- }
- ignore(close(tfile));
- }
- ignore(closedir(dir));
-}
-
-/*
- * Given a candidate file to be recovered, see
- * if its really an editor temporary and of this
- * user and the file specified.
- */
-int
-yeah(char *name)
-{
-
- tfile = open(name, O_RDWR);
- if (tfile < 0)
- return (0);
- if (read(tfile, (char *) &H, sizeof H) != sizeof H) {
-nope:
- ignore(close(tfile));
- return (0);
- }
- if (strcmp(savedfile, file))
- goto nope;
- if (getuid() != H.Uid)
- goto nope;
- /*
- * This is old and stupid code, which
- * puts a word LOST in the header block, so that lost lines
- * can be made to point at it.
- */
- ignorl(lseek(tfile, (off_t) (BUFSIZ*HBLKS-8), SEEK_SET));
- ignore(write(tfile, "LOST", 5));
- return (1);
-}
-
-int
-preserve(void)
-{
- return 0;
-}
-
-/*
- * Find the true end of the scratch file, and ``LOSE''
- * lines which point into thin air. This lossage occurs
- * due to the sandbagging of i/o which can cause blocks to
- * be written in a non-obvious order, different from the order
- * in which the editor tried to write them.
- *
- * Lines which are lost are replaced with the text LOST so
- * they are easy to find. We work hard at pretty formatting here
- * as lines tend to be lost in blocks.
- *
- * This only seems to happen on very heavily loaded systems, and
- * not very often.
- */
-void
-scrapbad(void)
-{
- register line *ip;
- struct stat stbuf;
- off_t size, maxt;
- bbloc bno, cnt = 0, bad, was;
- char bk[BUFSIZ];
-
- ignore(fstat(tfile, &stbuf));
- size = stbuf.st_size;
- maxt = (size >> SHFT) | (BNDRY-1);
- bno = (maxt >> OFFBTS) & BLKMSK;
-#ifdef DEBUG
- xfprintf(xstderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno);
-#endif
-
- /*
- * Look for a null separating two lines in the temp file;
- * if last line was split across blocks, then it is lost
- * if the last block is.
- */
- while (bno > 0) {
- ignorl(lseek(tfile, (off_t) (BUFSIZ * (bno & BLKMSK)),
- SEEK_SET));
- cnt = read(tfile, (char *) bk, BUFSIZ);
- while (cnt > 0)
- if (bk[--cnt] == 0)
- goto null;
- bno--;
- }
-null:
-
- /*
- * Magically calculate the largest valid pointer in the temp file,
- * consing it up from the block number and the count.
- */
- maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1;
-#ifdef DEBUG
- xfprintf(xstderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt);
-#endif
-
- /*
- * Now cycle through the line pointers,
- * trashing the Lusers.
- */
- was = bad = 0;
- for (ip = one; ip <= dol; ip++)
- if (*ip > maxt) {
-#ifdef DEBUG
- xfprintf(xstderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt);
-#endif
- if (was == 0)
- was = ip - zero;
- *ip = ((HBLKS*BUFSIZ)-8) >> SHFT;
- } else if (was) {
- if (bad == 0)
- xfprintf(xstderr, catgets(catd, 2, 10,
- " [Lost line(s):"));
- xfprintf(xstderr, catgets(catd, 2, 11,
- " %d"), was);
- if ((ip - 1) - zero > was)
- xfprintf(xstderr, catgets(catd, 2, 12, "-%d"),
- (int) ((ip - 1) - zero));
- bad++;
- was = 0;
- }
- if (was != 0) {
- if (bad == 0)
- xfprintf(xstderr, catgets(catd, 2, 13,
- " [Lost line(s):"));
- xfprintf(xstderr, catgets(catd, 2, 14, " %d"), was);
- if (dol - zero != was)
- xfprintf(xstderr, catgets(catd, 2, 15,
- "-%d"), (int) (dol - zero));
- bad++;
- }
- if (bad)
- xfprintf(xstderr, catgets(catd, 2, 16, "]"));
-}
-
-int cntch, cntln, cntodd, cntnull;
-
-/*
- * Following routines stolen mercilessly from ex.
- */
-void
-putfile(int unused)
-{
- line *a1;
- register char *fp, *lp;
- register int nib;
-
- a1 = addr1;
- clrstats();
- cntln = addr2 - a1 + 1;
- if (cntln == 0)
- return;
- nib = BUFSIZ;
- fp = genbuf;
- do {
- getline(*a1++);
- lp = linebuf;
- for (;;) {
- if (--nib < 0) {
- nib = fp - genbuf;
- if (write(io, genbuf, nib) != nib)
- wrerror();
- cntch += nib;
- nib = MAXBSIZE - 1 /* 511 */;
- fp = genbuf;
- }
- if ((*fp++ = *lp++) == 0) {
- fp[-1] = '\n';
- break;
- }
- }
- } while (a1 <= addr2);
- nib = fp - genbuf;
- if (write(io, genbuf, nib) != nib)
- wrerror();
- cntch += nib;
-}
-
-void
-wrerror(void)
-{
-
- syserror();
-}
-
-void
-clrstats(void)
-{
-
- ninbuf = 0;
- cntch = 0;
- cntln = 0;
- cntnull = 0;
- cntodd = 0;
-}
-
-#define READ 0
-#define WRITE 1
-
-void
-getline(line tl)
-{
- register char *bp, *lp;
- register int nl;
-
- lp = linebuf;
- bp = getblock(tl, READ);
- nl = nleft;
- tl &= ~OFFMSK;
- while (*lp++ = *bp++)
- if (--nl == 0) {
- bp = getblock(tl += INCRMT, READ);
- nl = nleft;
- }
-}
-
-char *
-getblock(line atl, int iof)
-{
- register bbloc bno, off;
-
- bno = (atl >> OFFBTS) & BLKMSK;
- off = (atl << SHFT) & LBTMSK;
- if (bno >= NMBLKS)
- error(catgets(catd, 2, 17, " Tmp file too large"));
- nleft = BUFSIZ - off;
- if (bno == iblock) {
- ichanged |= iof;
- return (ibuff + off);
- }
- if (bno == oblock)
- return (obuff + off);
- if (iof == READ) {
- if (ichanged)
- blkio(iblock, ibuff,
- (ssize_t(*)(int, void *, size_t))write);
- ichanged = 0;
- iblock = bno;
- blkio(bno, ibuff, (ssize_t(*)(int, void *, size_t))read);
- return (ibuff + off);
- }
- if (oblock >= 0)
- blkio(oblock, obuff, (ssize_t(*)(int, void *, size_t))write);
- oblock = bno;
- return (obuff + off);
-}
-
-void
-blkio(bloc b, char *buf, ssize_t (*iofcn)(int, void *, size_t))
-{
-
- lseek(tfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
- if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
- syserror();
-}
-
-void
-syserror(void)
-{
-
- dirtcnt = 0;
- write(2, " ", 1);
- error("%s", strerror(errno));
- exit(1);
-}
-
-/*
- * Must avoid stdio because expreserve uses sbrk to do memory
- * allocation and stdio uses malloc.
- */
-/*
- * I do not know whether vsprintf() uses malloc() or not.
- * So this may be fail, too.
- */
-void
-xvfprintf(xFILE *fp, char *fmt, va_list ap)
-{
- char buf[BUFSIZ];
-
- if (fp != xstderr)
- return;
- vsprintf(buf, fmt, ap);
- write(2, buf, strlen(buf));
-}
-
-void
-xfprintf(xFILE *fp, char *fmt, ...)
-{
- va_list ap;
-
- if (fp != xstderr)
- return;
- va_start(ap, fmt);
- xvfprintf(fp, fmt, ap);
- va_end(ap);
-}