#define _XOPEN_SOURCE 700 #include #include #include #include #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); }