1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.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->tlines[mf->nlines - 1]));
getline(&(mf->buf), &(mf->nbuf), mf->f);
}
while (mf->nlines <= lineno) {
mf->nlines++;
mf->tlines = realloc(mf->tlines, mf->nlines * sizeof(*mf->tlines));
mf->bytepos = realloc(mf->bytepos, mf->nlines * sizeof(*mf->bytepos));
fgetpos(mf->f, &(mf->tlines[mf->nlines - 1]));
if (getline(&(mf->buf), &(mf->nbuf), mf->f) == -1) {
return -1;
}
if (mf->nlines > 1) {
mf->bytepos[mf->nlines - 1] = mf->bytepos[mf->nlines - 2] + strlen(mf->buf);
} else {
mf->bytepos[0] = 0;
}
if (mf->backing != mf->f) {
fgetpos(mf->backing, &(mf->tlines[mf->nlines - 1]));
fputs(mf->buf, mf->backing);
}
}
fsetpos(mf->backing, &(mf->tlines[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\r\n", path, strerror(errno));
return mf;
}
}
fpos_t pos;
if (fgetpos(mf.f, &pos) != 0) {
mf.backing = tmpfile();
} else {
mf.backing = mf.f;
struct stat st;
fstat(fileno(mf.f), &st);
mf.nbytes = st.st_size;
}
mf.path = strdup(path);
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->tlines);
free(mf->buf);
free(mf->path);
}
|