summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2020-07-14 17:00:49 -0400
committerJakob Kaivo <jkk@ung.org>2020-07-14 17:00:49 -0400
commitfe5a38fc526c373c5cabad4f963fbd99ffb712e9 (patch)
tree4e4d46aa2c985a5ea2064902bc433c30a3999255 /io.c
parent6b8dfa2858c16b3cba4cd1e560000c47db3e50e6 (diff)
split i/o stuff out to io.c
Diffstat (limited to 'io.c')
-rw-r--r--io.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/io.c b/io.c
new file mode 100644
index 0000000..0aab2ff
--- /dev/null
+++ b/io.c
@@ -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);
+}