diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-08-16 11:33:07 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-08-16 11:33:07 +0300 |
commit | b40125990e923f743fa4a1b53c7af05feda422cc (patch) | |
tree | 1c56eed51640589503298846fcb1c6110dff09a7 | |
parent | 5b7e047dfdb34d0fdc3720e14dd08a7693948b2f (diff) | |
download | runcap-b40125990e923f743fa4a1b53c7af05feda422cc.tar.gz runcap-b40125990e923f743fa4a1b53c7af05feda422cc.tar.bz2 |
Run line monitor functions with stream capturing disabled
* runcap.3: Document changes.
* runcap.c (stream_capture_init): Change signature. Change to static.
(stream_capture_free): Change to static.
(stream_capture_get): Special handling for "no capture" streams with
line monitors.
* runcap.h (stream_capture): New member: sc_nocap.
(RCF_STDOUT_NOCAP)
(RCF_STDERR_NOCAP): New flags.
* t/Makefile.am: Add new tests.
* t/testsuite.at: Likewise.
* t/linemon02.at: Add copyright header.
* t/linemon03.at: New test.
* t/nocap.inc: New include file.
* t/nocap00.at: New test.
* t/nocap01.at: New test.
* t/rt.c: New option: -N
-rw-r--r-- | runcap.3 | 44 | ||||
-rw-r--r-- | runcap.c | 78 | ||||
-rw-r--r-- | runcap.h | 16 | ||||
-rw-r--r-- | t/Makefile.am | 4 | ||||
-rw-r--r-- | t/linemon02.at | 16 | ||||
-rw-r--r-- | t/linemon03.at | 85 | ||||
-rw-r--r-- | t/nocap.inc | 78 | ||||
-rw-r--r-- | t/nocap00.at | 22 | ||||
-rw-r--r-- | t/nocap01.at | 22 | ||||
-rw-r--r-- | t/rt.c | 13 | ||||
-rw-r--r-- | t/testsuite.at | 3 |
11 files changed, 339 insertions, 42 deletions
@@ -15,3 +15,3 @@ .\" along with runcap. If not, see <http://www.gnu.org/licenses/>. -.TH RUNCAP 2 "August 22, 2017" "RUNCAP" "User Commands" +.TH RUNCAP 2 "August 16, 2019" "RUNCAP" "User Commands" .SH NAME @@ -145,3 +145,6 @@ input data exceeds the buffer size, the data are saved in the disk file, therefore setting a larger buffer can improve performance. -Setting \fBsc_size\fR to 0 disables capturing. + +Setting \fBsc_size\fR to 0 disables capturing. Same effect is +achieved by setting the \fBRCF_STDOUT_NOCAP\fR or +\fBRCF_STDERR_NOCAP\fR flag. @@ -302,2 +305,39 @@ runcap_rewind(rc, stream) <=> runcap_seek(rc, stream, 0, SEEK_SET) .in +.SS Disabling capturing +Two ways are provided to disable capturing of a particular stream. +First, you can set the \fBsc_size\fR member of the corresponding +\fBrc_cap\fR element to 0 and indicate that by setting the +\fBRCF_STDOUT_SIZE\fR (for stdout) or \fBRCF_STDERR_SIZE\fR (for +stderr) bit. This was the method used in first releases of runcap. +.PP +The second method is to use the \fBRCF_STDOUT_NOCAP\fR and/or +\fBRCF_STDERR_NOCAP\fR flag in the call to \fBruncap\fR. +.PP +Both methods are equivalent. +.PP +If capturing is disabled for a particular stream, the corresponding +file descriptor of the program being invoked remains unchanged. This +means, e.g., that if you disable stderr capturing, error diagnostics +from the programs that \fBruncap\fR runs will appear at the stderr of +your program. Upon return from \fBruncap\fR both +.B sc_leng +and +.B sc_nlines +fields of the corresponding \fBrc_cap\fR structure will be zero. +.PP +This is changed if line monitor is installed on the stream with +disabled capturing. In that case, the output from the program will be +intercepted, passed to the line monitor function and discarded. Upon +return, both +.B sc_leng +and +.B sc_nlines +will reflect the actual length in bytes and number of lines in the +processed material. +.SS Last line handling +If the last line of the output is not terminated with a newline, it +will be passed to the line monitor function (if such is defined) +verbatim and will be counted in the +.B sc_nlines +field. .SH RETURN VALUE @@ -25,7 +25,8 @@ #include <signal.h> - +#include <string.h> #include "runcap.h" -int -stream_capture_init(struct stream_capture *cap, size_t size) +static int +stream_capture_init(struct stream_capture *cap, size_t size, int linemon, + int nocap) { @@ -36,2 +37,9 @@ stream_capture_init(struct stream_capture *cap, size_t size) + if (size == 0) { + if (linemon) + size = STRCAP_BUFSIZE; + nocap = 1; + } else if (nocap && !linemon) + size = 0; + if (size) { @@ -49,2 +57,9 @@ stream_capture_init(struct stream_capture *cap, size_t size) cap->sc_fd = -1; + + if (!linemon) { + cap->sc_linemon = NULL; + cap->sc_monarg = NULL; + } + cap->sc_nocap = nocap; + return 0; @@ -70,3 +85,3 @@ stream_capture_reset(struct stream_capture *cap) -void +static void stream_capture_free(struct stream_capture *cap) @@ -110,14 +125,16 @@ stream_capture_flush(struct stream_capture *cap) cap->sc_monarg); - if (cap->sc_storfd == -1) { - int fd; - char tmpl[] = "/tmp/rcXXXXXX"; - fd = mkstemp(tmpl); - if (fd == -1) + if (!cap->sc_nocap) { + if (cap->sc_storfd == -1) { + int fd; + char tmpl[] = "/tmp/rcXXXXXX"; + fd = mkstemp(tmpl); + if (fd == -1) + return -1; + unlink(tmpl); + cap->sc_storfd = fd; + } + res = full_write(cap->sc_storfd, cap->sc_base, cap->sc_level); + if (res) return -1; - unlink(tmpl); - cap->sc_storfd = fd; } - res = full_write(cap->sc_storfd, cap->sc_base, cap->sc_level); - if (res) - return -1; cap->sc_level = 0; @@ -138,3 +155,4 @@ stream_capture_get(struct stream_capture *cap, int *feof) - rc = read(cap->sc_fd, cap->sc_base + cap->sc_level, cap->sc_size - cap->sc_level); + rc = read(cap->sc_fd, cap->sc_base + cap->sc_level, + cap->sc_size - cap->sc_level); if (rc == -1) { @@ -172,3 +190,9 @@ stream_capture_get(struct stream_capture *cap, int *feof) } - + + if (cap->sc_nocap && cap->sc_linemon && cap->sc_level > cap->sc_cur) { + memmove(cap->sc_base, cap->sc_base + cap->sc_cur, + cap->sc_level - cap->sc_cur); + cap->sc_level -= cap->sc_cur; + cap->sc_cur = 0; + } @@ -453,5 +477,5 @@ runcap_init(struct runcap *rc, int flags) rc->rc_cap[RUNCAP_STDIN].sc_storfd = -1; - } else if (stream_capture_init(&rc->rc_cap[RUNCAP_STDIN], 0)) + } else if (stream_capture_init(&rc->rc_cap[RUNCAP_STDIN], 0, 0, 0)) return -1; - + res = stream_capture_init(&rc->rc_cap[RUNCAP_STDOUT], @@ -459,3 +483,5 @@ runcap_init(struct runcap *rc, int flags) ? rc->rc_cap[RUNCAP_STDOUT].sc_size - : STRCAP_BUFSIZE); + : STRCAP_BUFSIZE, + flags & RCF_STDOUT_LINEMON, + flags & RCF_STDOUT_NOCAP); if (res) @@ -463,7 +489,2 @@ runcap_init(struct runcap *rc, int flags) - if (!(flags & RCF_STDOUT_LINEMON)) { - rc->rc_cap[RUNCAP_STDOUT].sc_linemon = NULL; - rc->rc_cap[RUNCAP_STDOUT].sc_monarg = NULL; - } - res = stream_capture_init(&rc->rc_cap[RUNCAP_STDERR], @@ -471,3 +492,5 @@ runcap_init(struct runcap *rc, int flags) ? rc->rc_cap[RUNCAP_STDERR].sc_size - : STRCAP_BUFSIZE); + : STRCAP_BUFSIZE, + flags & RCF_STDERR_LINEMON, + flags & RCF_STDERR_NOCAP); if (res) @@ -475,7 +498,2 @@ runcap_init(struct runcap *rc, int flags) - if (!(flags & RCF_STDERR_LINEMON)) { - rc->rc_cap[RUNCAP_STDERR].sc_linemon = NULL; - rc->rc_cap[RUNCAP_STDERR].sc_monarg = NULL; - } - rc->rc_pid = (pid_t) -1; @@ -33,2 +33,3 @@ struct stream_capture void *sc_monarg; /* Line monitor argument */ + int sc_nocap; /* If 1, capturing is disabled */ }; @@ -59,9 +60,8 @@ struct runcap #define RCF_STDIN 0x0004 /* rc_cap[RUNCAP_STDIN] is set */ -#define RCF_STDOUT_SIZE 0x0008 -#define RCF_STDOUT_LINEMON 0x0010 -#define RCF_STDERR_SIZE 0x0020 -#define RCF_STDERR_LINEMON 0x0040 - -int stream_capture_init(struct stream_capture *fc, size_t size); -void stream_capture_free(struct stream_capture *fc); +#define RCF_STDOUT_SIZE 0x0008 /* rc_cap[RUNCAP_STDOUT].sc_size is set */ +#define RCF_STDOUT_LINEMON 0x0010 /* rc_cap[RUNCAP_STDOUT].sc_linemon is set */ +#define RCF_STDERR_SIZE 0x0020 /* rc_cap[RUNCAP_STDERR].sc_size is set */ +#define RCF_STDERR_LINEMON 0x0040 /* rc_cap[RUNCAP_STDERR].sc_linemon is set */ +#define RCF_STDOUT_NOCAP 0x0080 /* disable stdout capturing */ +#define RCF_STDERR_NOCAP 0x0100 /* disable stderr capturing */ @@ -82,3 +82,3 @@ runcap_get_capture(struct runcap *rc, int stream) - if (!fp->sc_base || fp->sc_size == 0) { + if (!fp->sc_base || fp->sc_size == 0 || fp->sc_nocap) { errno = EINVAL; diff --git a/t/Makefile.am b/t/Makefile.am index 22786c0..4e44f05 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -52,2 +52,6 @@ TESTSUITE_AT = \ linemon02.at\ + linemon03.at\ + nocap.inc\ + nocap00.at\ + nocap01.at\ seek00.at\ diff --git a/t/linemon02.at b/t/linemon02.at index 87ff0ea..73cf720 100644 --- a/t/linemon02.at +++ b/t/linemon02.at @@ -1 +1,17 @@ +# Testsuite for runcap - run program and capture its output -*- autotest -*- +# Copyright (C) 2017-2019 Sergey Poznyakoff +# +# Runcap is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# Runcap is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Runcap. If not, see <http://www.gnu.org/licenses/>. + AT_SETUP([line monitor, no trailing newline]) diff --git a/t/linemon03.at b/t/linemon03.at new file mode 100644 index 0000000..2ede768 --- /dev/null +++ b/t/linemon03.at @@ -0,0 +1,85 @@ +AT_SETUP([line monitor, disable capture]) +AT_KEYWORDS([linemon linemon03.at nocap]) +AT_CHECK([rt -S stdout -N -m -s 85 -r stdout:10 -- genout $INPUT], +[1], +[stdout: CHAPTER I. Down the Rabbit-Hole +stdout: +stdout: Alice was beginning to get very tired of sitting by her sister on the +stdout: bank, and of having nothing to do: once or twice she had peeped into the +stdout: book her sister was reading, but it had no pictures or conversations +stdout: in it, 'and what is the use of a book,' thought Alice 'without +stdout: pictures or conversations?' +stdout: +stdout: So she was considering in her own mind (as well as she could, for the +stdout: hot day made her feel very sleepy and stupid), whether the pleasure of +stdout: making a daisy-chain would be worth the trouble of getting up and picking +stdout: the daisies, when suddenly a White Rabbit with pink eyes ran close by her. +stdout: +stdout: There was nothing so very remarkable in that; nor did Alice think it +stdout: so very much out of the way to hear the Rabbit say to itself, 'Oh +stdout: dear! Oh dear! I shall be late!' (when she thought it over afterwards, +stdout: it occurred to her that she ought to have wondered at this, but at the +stdout: time it all seemed quite natural); but when the Rabbit actually took a +stdout: watch out of its waistcoat-pocket, and looked at it, and then hurried on, +stdout: Alice started to her feet, for it flashed across her mind that she had +stdout: never before seen a rabbit with either a waistcoat-pocket, or a watch +stdout: to take out of it, and burning with curiosity, she ran across the field +stdout: after it, and fortunately was just in time to see it pop down a large +stdout: rabbit-hole under the hedge. +stdout: +stdout: In another moment down went Alice after it, never once considering how +stdout: in the world she was to get out again. +stdout: +stdout: The rabbit-hole went straight on like a tunnel for some way, and then +stdout: dipped suddenly down, so suddenly that Alice had not a moment to think +stdout: about stopping herself before she found herself falling down a very +stdout: deep well. +stdout: +stdout: Either the well was very deep, or she fell very slowly, for she had plenty +stdout: of time as she went down to look about her and to wonder what was going +stdout: to happen next. First, she tried to look down and make out what she was +stdout: coming to, but it was too dark to see anything; then she looked at the +stdout: sides of the well, and noticed that they were filled with cupboards +stdout: and book-shelves; here and there she saw maps and pictures hung upon +stdout: pegs. She took down a jar from one of the shelves as she passed; it was +stdout: labelled 'ORANGE MARMALADE', but to her great disappointment it was +stdout: empty: she did not like to drop the jar for fear of killing somebody, +stdout: so managed to put it into one of the cupboards as she fell past it. +stdout: +stdout: 'Well!' thought Alice to herself, 'after such a fall as this, +stdout: I shall think nothing of tumbling down stairs! How brave they'll all +stdout: think me at home! Why, I wouldn't say anything about it, even if I +stdout: fell off the top of the house!' (Which was very likely true.) +stdout: +stdout: Down, down, down. Would the fall never come to an end! 'I wonder how +stdout: many miles I've fallen by this time?' she said aloud. 'I must be +stdout: getting somewhere near the centre of the earth. Let me see: that would be +stdout: four thousand miles down, I think--' (for, you see, Alice had learnt +stdout: several things of this sort in her lessons in the schoolroom, and though +stdout: this was not a very good opportunity for showing off her knowledge, +stdout: as there was no one to listen to her, still it was good practice to +stdout: say it over) '--yes, that's about the right distance--but then I +stdout: wonder what Latitude or Longitude I've got to?' (Alice had no idea +stdout: what Latitude was, or Longitude either, but thought they were nice grand +stdout: words to say.) +stdout: +stdout: Presently she began again. 'I wonder if I shall fall right through +stdout: the earth! How funny it'll seem to come out among the people that +stdout: walk with their heads downward! The Antipathies, I think--' (she was +stdout: rather glad there was no one listening, this time, as it didn't sound +stdout: at all the right word) '--but I shall have to ask them what the name +stdout: of the country is, you know. Please, Ma'am, is this New Zealand or +stdout: Australia?' (and she tried to curtsey as she spoke--fancy curtseying +stdout: as you're falling through the air! Do you think you could manage +stdout: it?) 'And what an ignorant little girl she'll think me for asking! No, +stdout: it'll never do to ask: perhaps I shall see it written up somewhere.' +res=0 +exit code: 0 +stdout: 71 lines, 4051 bytes +stderr: 0 lines, 0 bytes +READ 0: +], +[runcap_seek: Invalid argument +]) +AT_CLEANUP + diff --git a/t/nocap.inc b/t/nocap.inc new file mode 100644 index 0000000..fb1e20c --- /dev/null +++ b/t/nocap.inc @@ -0,0 +1,78 @@ +AT_DATA([expout], +[CHAPTER I. Down the Rabbit-Hole + +Alice was beginning to get very tired of sitting by her sister on the +bank, and of having nothing to do: once or twice she had peeped into the +book her sister was reading, but it had no pictures or conversations +in it, 'and what is the use of a book,' thought Alice 'without +pictures or conversations?' + +So she was considering in her own mind (as well as she could, for the +hot day made her feel very sleepy and stupid), whether the pleasure of +making a daisy-chain would be worth the trouble of getting up and picking +the daisies, when suddenly a White Rabbit with pink eyes ran close by her. + +There was nothing so very remarkable in that; nor did Alice think it +so very much out of the way to hear the Rabbit say to itself, 'Oh +dear! Oh dear! I shall be late!' (when she thought it over afterwards, +it occurred to her that she ought to have wondered at this, but at the +time it all seemed quite natural); but when the Rabbit actually took a +watch out of its waistcoat-pocket, and looked at it, and then hurried on, +Alice started to her feet, for it flashed across her mind that she had +never before seen a rabbit with either a waistcoat-pocket, or a watch +to take out of it, and burning with curiosity, she ran across the field +after it, and fortunately was just in time to see it pop down a large +rabbit-hole under the hedge. + +In another moment down went Alice after it, never once considering how +in the world she was to get out again. + +The rabbit-hole went straight on like a tunnel for some way, and then +dipped suddenly down, so suddenly that Alice had not a moment to think +about stopping herself before she found herself falling down a very +deep well. + +Either the well was very deep, or she fell very slowly, for she had plenty +of time as she went down to look about her and to wonder what was going +to happen next. First, she tried to look down and make out what she was +coming to, but it was too dark to see anything; then she looked at the +sides of the well, and noticed that they were filled with cupboards +and book-shelves; here and there she saw maps and pictures hung upon +pegs. She took down a jar from one of the shelves as she passed; it was +labelled 'ORANGE MARMALADE', but to her great disappointment it was +empty: she did not like to drop the jar for fear of killing somebody, +so managed to put it into one of the cupboards as she fell past it. + +'Well!' thought Alice to herself, 'after such a fall as this, +I shall think nothing of tumbling down stairs! How brave they'll all +think me at home! Why, I wouldn't say anything about it, even if I +fell off the top of the house!' (Which was very likely true.) + +Down, down, down. Would the fall never come to an end! 'I wonder how +many miles I've fallen by this time?' she said aloud. 'I must be +getting somewhere near the centre of the earth. Let me see: that would be +four thousand miles down, I think--' (for, you see, Alice had learnt +several things of this sort in her lessons in the schoolroom, and though +this was not a very good opportunity for showing off her knowledge, +as there was no one to listen to her, still it was good practice to +say it over) '--yes, that's about the right distance--but then I +wonder what Latitude or Longitude I've got to?' (Alice had no idea +what Latitude was, or Longitude either, but thought they were nice grand +words to say.) + +Presently she began again. 'I wonder if I shall fall right through +the earth! How funny it'll seem to come out among the people that +walk with their heads downward! The Antipathies, I think--' (she was +rather glad there was no one listening, this time, as it didn't sound +at all the right word) '--but I shall have to ask them what the name +of the country is, you know. Please, Ma'am, is this New Zealand or +Australia?' (and she tried to curtsey as she spoke--fancy curtseying +as you're falling through the air! Do you think you could manage +it?) 'And what an ignorant little girl she'll think me for asking! No, +it'll never do to ask: perhaps I shall see it written up somewhere.' +res=0 +exit code: 0 +stdout: 0 lines, 0 bytes +stderr: 0 lines, 0 bytes +]) + diff --git a/t/nocap00.at b/t/nocap00.at new file mode 100644 index 0000000..9323936 --- /dev/null +++ b/t/nocap00.at @@ -0,0 +1,22 @@ +# Testsuite for runcap - run program and capture its output -*- autotest -*- +# Copyright (C) 2017-2019 Sergey Poznyakoff +# +# Runcap is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# Runcap is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Runcap. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([disable capture: size 0]) +AT_KEYWORDS([nocap]) +m4_include([nocap.inc]) +AT_CHECK([rt -S stdout -s 0 -- genout $INPUT],[0],[expout]) +AT_CLEANUP + diff --git a/t/nocap01.at b/t/nocap01.at new file mode 100644 index 0000000..38f6b00 --- /dev/null +++ b/t/nocap01.at @@ -0,0 +1,22 @@ +# Testsuite for runcap - run program and capture its output -*- autotest -*- +# Copyright (C) 2017-2019 Sergey Poznyakoff +# +# Runcap is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# Runcap is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Runcap. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([disable capture: nocap flag]) +AT_KEYWORDS([nocap]) +m4_include([nocap.inc]) +AT_CHECK([rt -S stdout -N -- genout $INPUT],[0],[expout]) +AT_CLEANUP + @@ -49,5 +49,6 @@ usage(int code) fprintf(fp, "OPTIONS are:\n\n"); - fprintf(fp, " -S all|stderr|stdout selects capture for the next -m or -s option\n"); + fprintf(fp, " -S all|stderr|stdout selects capture for the next -m, -N, or -s option\n"); fprintf(fp, " -f FILE reads stdin from FILE\n"); fprintf(fp, " -i inline read (use before -f)\n"); + fprintf(fp, " -N disable capturing\n"); fprintf(fp, " -n all|stderr|stdout print lines from the requested capture\n"); @@ -245,3 +246,3 @@ main(int argc, char **argv) progname = argv[0]; - while ((c = getopt(argc, argv, "?f:in:mp:r:S:s:t:")) != EOF) { + while ((c = getopt(argc, argv, "?f:iNn:mp:r:S:s:t:")) != EOF) { switch (c) { @@ -300,2 +301,10 @@ main(int argc, char **argv) break; + case 'N': + if (what & WA_STDOUT) { + rcf |= RCF_STDOUT_NOCAP; + } + if (what & WA_STDERR) { + rcf |= RCF_STDERR_NOCAP; + } + break; case 'n': diff --git a/t/testsuite.at b/t/testsuite.at index 0c93340..4f4ba29 100644 --- a/t/testsuite.at +++ b/t/testsuite.at @@ -25,2 +25,4 @@ m4_include([stdin.at]) m4_include([pipe.at]) +m4_include([nocap00.at]) +m4_include([nocap01.at]) m4_include([linemon00.at]) @@ -28,2 +30,3 @@ m4_include([linemon01.at]) m4_include([linemon02.at]) +m4_include([linemon03.at]) m4_include([seek00.at]) |