aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-07-18 17:50:34 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-07-18 17:50:34 +0300
commit24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8 (patch)
treefbd53229d5f87f9a99cbd64a89ac4fb1d06bd7ad
parent3488a182f66e35b091f441b9201ad43ad6d0f1ac (diff)
downloadruncap-24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8.tar.gz
runcap-24b9e009c9c2eef1b6d1accb3ac7ccc53c44c0a8.tar.bz2
Add missing API calls, provide testsuite
-rw-r--r--.gitignore7
-rw-r--r--Makefile9
-rw-r--r--getc.c54
-rw-r--r--getl.c90
-rw-r--r--runcap.h49
-rw-r--r--seek.c73
-rw-r--r--t/.gitignore4
-rwxr-xr-xt/00simple.t30
-rwxr-xr-xt/01lines.t101
-rwxr-xr-xt/02two.t51
-rwxr-xr-xt/03longout.t101
-rwxr-xr-xt/04stdin.t50
-rwxr-xr-xt/05stdin.t50
-rw-r--r--t/INPUT71
-rw-r--r--t/Makefile28
-rw-r--r--t/genout.c80
-rw-r--r--t/rt.c39
-rwxr-xr-xt/testsuite137
-rw-r--r--tell.c41
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*~
4core
5.emacs.*
6.gdbinit
7tmp
diff --git a/Makefile b/Makefile
index b0cec8a..4eb3a1c 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ MKHIER = install -d
28# Compiler options 28# Compiler options
29O = -ggdb -Wall 29O = -ggdb -Wall
30 30
31SOURCES = runcap.c 31SOURCES = runcap.c getc.c getl.c seek.c tell.c
32OBJECTS = $(SOURCES:.c=.o) 32OBJECTS = $(SOURCES:.c=.o)
33HEADERS = runcap.h 33HEADERS = runcap.h
34 34
@@ -38,6 +38,8 @@ ARFLAGS = cru
38 38
39all: libruncap.a 39all: libruncap.a
40 40
41$(OBJECTS): $(HEADERS)
42
41libruncap.a: $(OBJECTS) 43libruncap.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
55install-man:; 57install-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
62check:
63 $(MAKE) -C t check
64
diff --git a/getc.c b/getc.c
new file mode 100644
index 0000000..3c203d9
--- /dev/null
+++ b/getc.c
@@ -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
23int
24runcap_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
diff --git a/getl.c b/getl.c
new file mode 100644
index 0000000..d989aa9
--- /dev/null
+++ b/getl.c
@@ -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
23ssize_t
24runcap_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
diff --git a/runcap.h b/runcap.h
index b677f05..517cd43 100644
--- a/runcap.h
+++ b/runcap.h
@@ -19,16 +19,17 @@
19 19
20struct filecapture 20struct 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);
66int runcap(struct runcap *rc, int flags); 67int runcap(struct runcap *rc, int flags);
67void runcap_free(struct runcap *rc); 68void runcap_free(struct runcap *rc);
68 69
70static inline struct filecapture *
71runcap_filecapture(struct runcap *rc, int stream)
72{