diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-18 17:50:34 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-07-18 17:50:34 +0300 |
commit | 24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8 (patch) | |
tree | fbd53229d5f87f9a99cbd64a89ac4fb1d06bd7ad | |
parent | 3488a182f66e35b091f441b9201ad43ad6d0f1ac (diff) | |
download | runcap-24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8.tar.gz runcap-24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8.tar.bz2 |
Add missing API calls, provide testsuite
-rw-r--r-- | .gitignore | 7 | ||||
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | getc.c | 54 | ||||
-rw-r--r-- | getl.c | 90 | ||||
-rw-r--r-- | runcap.h | 49 | ||||
-rw-r--r-- | seek.c | 73 | ||||
-rw-r--r-- | t/.gitignore | 4 | ||||
-rwxr-xr-x | t/00simple.t | 30 | ||||
-rwxr-xr-x | t/01lines.t | 101 | ||||
-rwxr-xr-x | t/02two.t | 51 | ||||
-rwxr-xr-x | t/03longout.t | 101 | ||||
-rwxr-xr-x | t/04stdin.t | 50 | ||||
-rwxr-xr-x | t/05stdin.t | 50 | ||||
-rw-r--r-- | t/INPUT | 71 | ||||
-rw-r--r-- | t/Makefile | 28 | ||||
-rw-r--r-- | t/genout.c | 80 | ||||
-rw-r--r-- | t/rt.c | 39 | ||||
-rwxr-xr-x | t/testsuite | 137 | ||||
-rw-r--r-- | tell.c | 41 |
19 files changed, 1053 insertions, 12 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6aee58 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,7 @@ | |||
1 | *.o | ||
2 | *.a | ||
3 | *~ | ||
4 | core | ||
5 | .emacs.* | ||
6 | .gdbinit | ||
7 | tmp | ||
@@ -28,7 +28,7 @@ MKHIER = install -d | |||
28 | # Compiler options | 28 | # Compiler options |
29 | O = -ggdb -Wall | 29 | O = -ggdb -Wall |
30 | 30 | ||
31 | SOURCES = runcap.c | 31 | SOURCES = runcap.c getc.c getl.c seek.c tell.c |
32 | OBJECTS = $(SOURCES:.c=.o) | 32 | OBJECTS = $(SOURCES:.c=.o) |
33 | HEADERS = runcap.h | 33 | HEADERS = runcap.h |
34 | 34 | ||
@@ -38,6 +38,8 @@ ARFLAGS = cru | |||
38 | 38 | ||
39 | all: libruncap.a | 39 | all: libruncap.a |
40 | 40 | ||
41 | $(OBJECTS): $(HEADERS) | ||
42 | |||
41 | libruncap.a: $(OBJECTS) | 43 | libruncap.a: $(OBJECTS) |
42 | ar $(ARFLAGS) libruncap.a $(OBJECTS) | 44 | ar $(ARFLAGS) libruncap.a $(OBJECTS) |
43 | ranlib libruncap.a | 45 | ranlib libruncap.a |
@@ -55,3 +57,8 @@ install-headers: runcap.h | |||
55 | install-man:; | 57 | install-man:; |
56 | # $(MKHIER) $(DESTDIR)$(MAN2DIR) | 58 | # $(MKHIER) $(DESTDIR)$(MAN2DIR) |
57 | # $(INSTALL) runcap.2 $(DESTDIR)$(MAN2DIR) | 59 | # $(INSTALL) runcap.2 $(DESTDIR)$(MAN2DIR) |
60 | |||
61 | .PHONY: check | ||
62 | check: | ||
63 | $(MAKE) -C t check | ||
64 | |||
@@ -0,0 +1,54 @@ | |||
1 | /* runcap - run program and capture its output | ||
2 | Copyright (C) 2017 Sergey Poznyakoff | ||
3 | |||
4 | Runcap is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License as published by the | ||
6 | Free Software Foundation; either version 3 of the License, or (at your | ||
7 | option) any later version. | ||
8 | |||
9 | Runcap is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with Runcap. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #include <stdlib.h> | ||
18 | #include <unistd.h> | ||
19 | #include <errno.h> | ||
20 | |||
21 | #include "runcap.h" | ||
22 | |||
23 | int | ||
24 | runcap_getc(struct runcap *rc, int stream, char *cp) | ||
25 | { | ||
26 | struct filecapture *fp; | ||
27 | |||
28 | if (!cp) { | ||
29 | errno = EINVAL; | ||
30 | return -1; | ||
31 | } | ||
32 | |||
33 | fp = runcap_filecapture(rc, stream); | ||
34 | if (!fp) | ||
35 | return -1; | ||
36 | |||
37 | if (fp->fc_level == fp->fc_linestart) { | ||
38 | if (fp->fc_tmpfd != -1) { | ||
39 | ssize_t r = read(fp->fc_tmpfd, fp->fc_base, | ||
40 | fp->fc_size); | ||
41 | if (r < 0) | ||
42 | return -1; | ||
43 | else if (r == 0) | ||
44 | return 0; | ||
45 | fp->fc_level = r; | ||
46 | fp->fc_linestart = 0; | ||
47 | } else { | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | *cp = fp->fc_base[fp->fc_linestart++]; | ||
52 | return 1; | ||
53 | } | ||
54 | |||
@@ -0,0 +1,90 @@ | |||
1 | /* runcap - run program and capture its output | ||
2 | Copyright (C) 2017 Sergey Poznyakoff | ||
3 | |||
4 | Runcap is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License as published by the | ||
6 | Free Software Foundation; either version 3 of the License, or (at your | ||
7 | option) any later version. | ||
8 | |||
9 | Runcap is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with Runcap. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #include <stdlib.h> | ||
18 | #include <unistd.h> | ||
19 | #include <errno.h> | ||
20 | |||
21 | #include "runcap.h" | ||
22 | |||
23 | ssize_t | ||
24 | runcap_getline(struct runcap *rc, int stream, char **pstr, size_t *psize) | ||
25 | { | ||
26 | struct filecapture *fp; | ||
27 | char *str; | ||
28 | size_t size; | ||
29 | size_t n; | ||
30 | char c; | ||
31 | int res; | ||
32 | |||
33 | if (!pstr || !psize) { | ||
34 | errno = EINVAL; | ||
35 | return -1; | ||
36 | } | ||
37 | |||
38 | str = *pstr; | ||
39 | size = *psize; | ||
40 | |||
41 | fp = runcap_filecapture(rc, stream); | ||
42 | if (!fp) | ||
43 | return -1; | ||
44 | |||
45 | if (!str || size == 0) { | ||
46 | /* Initial allocation */ | ||
47 | size = 16; | ||
48 | str = malloc(size); | ||
49 | if (!str) | ||
50 | return -1; | ||
51 | *pstr = str; | ||
52 | *psize = size; | ||
53 | } | ||
54 | |||
55 | n = 0; | ||
56 | while ((res = runcap_getc(rc, stream, &c)) == 1) { | ||
57 | if (n == size) { | ||
58 | char *p; | ||
59 | size_t sz; | ||
60 | |||
61 | if (size >= (size_t) -1 / 3 * 2) { | ||
62 | errno = ENOMEM; | ||
63 | return -1; | ||
64 | } | ||
65 | sz = size + (size + 1) / 2; | ||
66 | p = realloc(str, sz); | ||
67 | if (!p) | ||
68 | return -1; | ||
69 | *pstr = str = p; | ||
70 | *psize = size = sz; | ||
71 | } | ||
72 | str[n++] = c; | ||
73 | if (c == '\n') | ||
74 | break; | ||
75 | } | ||
76 | |||
77 | if (res == -1) | ||
78 | return -1; | ||
79 | |||
80 | if (n == size) { | ||
81 | char *p = realloc(str, size + 1); | ||
82 | if (!p) | ||
83 | return -1; | ||
84 | *pstr = str = p; | ||
85 | *psize = ++size; | ||
86 | } | ||
87 | str[n] = 0; | ||
88 | return n; | ||
89 | } | ||
90 | |||
@@ -19,16 +19,17 @@ | |||
19 | 19 | ||
20 | struct filecapture | 20 | struct filecapture |
21 | { | 21 | { |
22 | size_t fc_size; | 22 | size_t fc_size; /* size of the buffer */ |
23 | size_t fc_leng; | 23 | off_t fc_leng; /* total length of captured data */ |
24 | size_t fc_nlines; | 24 | size_t fc_nlines; /* number of captured lines */ |
25 | size_t fc_linestart; | 25 | size_t fc_linestart; /* current offset in buffer */ |
26 | char * fc_base; | 26 | char * fc_base; /* buffer space */ |
27 | size_t fc_level; | 27 | size_t fc_level; /* number of characters currently in buffer */ |
28 | void (*fc_linemon) (const char *, size_t, void *); | 28 | void (*fc_linemon) (const char *, size_t, void *); |
29 | void *fc_monarg; | 29 | /* Line monitor function */ |
30 | int fc_tmpfd; | 30 | void *fc_monarg; /* Line monitor argument */ |
31 | int fc_fd; | 31 | int fc_tmpfd; /* Storage file descriptor */ |
32 | int fc_fd; /* Input descriptor */ | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | #define FC_BUFSIZE 4096 | 35 | #define FC_BUFSIZE 4096 |
@@ -66,4 +67,34 @@ void filecapture_free(struct filecapture *fc); | |||
66 | int runcap(struct runcap *rc, int flags); | 67 | int runcap(struct runcap *rc, int flags); |
67 | void runcap_free(struct runcap *rc); | 68 | void runcap_free(struct runcap *rc); |
68 | 69 | ||
70 | static inline struct filecapture * | ||
71 | runcap_filecapture(struct runcap *rc, int stream) | ||
72 | { | ||