diff options
author | Jakob Kaivo <jkk@ung.org> | 2020-07-14 17:00:49 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2020-07-14 17:00:49 -0400 |
commit | fe5a38fc526c373c5cabad4f963fbd99ffb712e9 (patch) | |
tree | 4e4d46aa2c985a5ea2064902bc433c30a3999255 /io.c | |
parent | 6b8dfa2858c16b3cba4cd1e560000c47db3e50e6 (diff) |
split i/o stuff out to io.c
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -0,0 +1,71 @@ +#define _XOPEN_SOURCE 700 +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +//#include <unistd.h> + +#include "more.h" + +ssize_t more_getline(struct more_file *mf, size_t lineno) +{ + if (mf->nlines <= lineno && mf->nlines != 0) { + fsetpos(mf->f, &(mf->lines[mf->nlines - 1])); + getline(&(mf->buf), &(mf->nbuf), mf->f); + } + + while (mf->nlines <= lineno) { + mf->nlines++; + mf->lines = realloc(mf->lines, mf->nlines * sizeof(*mf->lines)); + + fgetpos(mf->f, &(mf->lines[mf->nlines - 1])); + + getline(&(mf->buf), &(mf->nbuf), mf->f); + + if (mf->backing != mf->f) { + fgetpos(mf->backing, &(mf->lines[mf->nlines - 1])); + fputs(mf->buf, mf->backing); + } + } + + fsetpos(mf->backing, &(mf->lines[lineno])); + return getline(&(mf->buf), &(mf->nbuf), mf->backing); +} + +struct more_file more_open(const char *path) +{ + struct more_file mf = { + .f = stdin, + }; + + if (strcmp(path, "-")) { + mf.f = fopen(path, "r"); + if (!mf.f) { + fprintf(stderr, "more: %s: %s\n", path, strerror(errno)); + return mf; + } + } + + fpos_t pos; + if (fgetpos(mf.f, &pos) != 0) { + mf.backing = tmpfile(); + } else { + mf.backing = mf.f; + } + + return mf; +} + +void more_close(struct more_file *mf) +{ + if (mf->backing != mf->f) { + fclose(mf->backing); + } + + if (mf->f != stdin) { + fclose(mf->f); + } + + free(mf->lines); + free(mf->buf); +} |