aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2019-08-16 14:32:23 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2019-08-16 14:36:33 +0300
commit86d62d746d8e2586e1b3a2995f7119d0562145b8 (patch)
tree592ee9b7e7ea2e2dc4dfd2320f895a3097168e43
parentb40125990e923f743fa4a1b53c7af05feda422cc (diff)
downloadruncap-86d62d746d8e2586e1b3a2995f7119d0562145b8.tar.gz
runcap-86d62d746d8e2586e1b3a2995f7119d0562145b8.tar.bz2
Explicitly indicate EOF when sc_linemon is initialized.
* runcap.3: Document changes. * runcap.c (stream_capture_get): Indicate EOF explicitly by calling sc_linemon function with 0 as line length. * t/rt.c (linemon): Update to handle this case.
-rw-r--r--runcap.393
-rw-r--r--runcap.c15
-rw-r--r--t/rt.c19
3 files changed, 82 insertions, 45 deletions
diff --git a/runcap.3 b/runcap.3
index b990eac..ace9da1 100644
--- a/runcap.3
+++ b/runcap.3
@@ -102,7 +102,7 @@ the
.B rc_cap
array. Its elements correspond to the standard input, output and
error streams. Upon successful return, the captured
-data from stdin and stdout can be retrieved using the \fBruncap_getc\fR, and
+data from stdout and stderr can be retrieved using the \fBruncap_getc\fR, and
\fBruncap_getline\fR functions (see below). For convenience, the
following constants are defined in \fBruncap.h\fR to refer to the
corresponding streams:
@@ -110,8 +110,8 @@ corresponding streams:
.BR RUNCAP_STDOUT ,
.BR RUNCAP_STDERR .
.PP
-The following fields are warranted to be present in \fBstruct
-stream_capture\fR:
+The \fBstream_capture\fR structure contains the following members
+accessible to the caller:
.PP
.in +4n
.nf
@@ -125,9 +125,9 @@ struct stream_capture
off_t sc_leng; /* [\fIOUT\fR] total length of captured data */
size_t sc_nlines; /* [\fIOUT\fR] number of captured lines */
- /* The following two are available only in \fBrc_cap[RUNCAP_STDIN]\fR,
- see the subsection \fBSupplying standard input\fR below, for
- details). */
+ /* The following two are available only in \fBrc_cap[RUNCAP_STDIN]\fR
+ For details. see the subsection \fBSupplying standard input\fR.
+ */
size_t sc_fd; /* Input file descriptor */
char *sc_base; /* Input data */
};
@@ -156,7 +156,7 @@ A pointer to the line monitor function. If set, the
\fBRCF_STDERR_LINEMON\fR (for \fBRUNCAP_STDERR\fR) bit must be set in
\fIflags\fR.
.sp
-The line monitor function allows the caller to monitor the arrival of
+Line monitor function allows the caller to monitor the arrival of
the new data in the corresponding stream. It is declared as follows:
.sp
.BI "void linemon(const char *" line ", size_t " size ", void *" data )
@@ -165,19 +165,49 @@ where \fIline\fR is the line that has been read, \fIsize\fR is its
length, and \fIdata\fR is an opaque pointer to application-specific
data, supplied in the \fBsc_monarg\fR member.
.sp
-The line monitor function is invoked each time a newline character is
-encountered in the stream, or when the stream buffer becomes full (and,
-therefore is about to be flushed into the storage file) and some
-characters remain unreported. This means that, if the
-\fBsc_linemon\fR function is designed to log each input line, it
-should keep the state of processing (e.g. in the \fIdata\fR argument),
-and concatenate the \fIline\fR parameters until
-\fBline[size-1] == '\\n'\fR.
+The line monitor function is invoked to notify the caller about
+arrival of new data on the stream. There are 4 cases:
+.RS +8
+.nr step 1 1
+.IP \n[step].
+A newline newline character is encountered in the stream.
+.sp
+The \fIline\fR argument points to the beginning of the captured
+line. The \fIsize\fR argument contains number of characters in the
+line, including the newline character.
+.IP \n+[step].
+The stream buffer is full (and therefore is about to be flushed into
+the storage file) and contains unfinished line.
+.sp
+The \fIline\fR
+argument points to the beginning of the captured line fragment. The
+\fIsize\fR argument contains number of characters in the
+fragment.
+.IP \n+[step].
+No more characters are available in the stream and the
+stream buffer contains unreported characters.
+.sp
+Argument assignment is the same as in previous case.
+.IP \n+[step].
+The stream reached EOF.
+.sp
+The \fIsize\fR argument is 0. The
+\fIline\fR argument is not meaningful, although it does point to a
+valid memory location.
+.PP
+Consequently, if the \fBsc_linemon\fR function needs to process full
+lines. it has to keep the state of processing (e.g. in the \fBdata\fR
+argument), and concatenate the line parameters until the following
+condition is met:
+.sp
+.EX
+ size == 0 || line[size-1] == '\\n'
+.EE
+.RE
.TP
.B sc_monarg
The value of the \fIdata\fR parameter for the \fBsc_linemon\fR
-function. It can be initialized only if \fBsc_linemon\fR is
-initialized as well.
+function.
.SS Supplying standard input
The
.B rc_cap[RUNCAP_STDIN]
@@ -226,11 +256,15 @@ Total length of captured stderr.
.B rc_cap[RUNCAP_STDERR].sc_nlines
Number of lines in the captured stderr.
.PP
-The actual data can be retrieved using the \fBruncap_getc\fR, and
+The last captured line can be partial, i.e. not terminated with a
+newline character. It will be counted in the stream's \fBsc_nlines\fR
+anyways.
+.PP
+Captured data can be retrieved using the \fBruncap_getc\fR, and
\fBruncap_getline\fR functions, described below.
.SH Examining output
Upon return from \fBruncap\fR the following functions can be used to
-retrieve the captured data from the \fBstruct runcap\fR object pointed
+retrieve captured data from the \fBstruct runcap\fR object pointed
to by its \fIrc\fR argument. The stream to retrieve data from is
identified by the \fIstream\fR argument, whose valid values are
\fBRUNCAP_STDOUT\fR (or \fB1\fR) or \fBRUNCAP_STDERR\fR (or \fB2\fR).
@@ -308,18 +342,19 @@ 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.
+stderr) flag. This was the method used in first releases of runcap.
.PP
-The second method is to use the \fBRCF_STDOUT_NOCAP\fR and/or
+Another way 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
+When capturing of a particular stream is disabled, the corresponding
+file descriptor of the program being invoked is inherited from the
+calling program. 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
@@ -334,10 +369,6 @@ 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
@@ -420,7 +451,7 @@ archive(void)
.SH AUTHORS
Sergey Poznyakoff
.SH COPYRIGHT
-Copyright \(co 2017 Sergey Poznyakoff
+Copyright \(co 2017--2019 Sergey Poznyakoff
.br
.na
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
diff --git a/runcap.c b/runcap.c
index d9b0539..bccdd99 100644
--- a/runcap.c
+++ b/runcap.c
@@ -161,12 +161,15 @@ stream_capture_get(struct stream_capture *cap, int *feof)
return -1;
}
if (rc == 0) {
- if (cap->sc_linemon && cap->sc_level > cap->sc_cur) {
- cap->sc_linemon(cap->sc_base + cap->sc_cur,
- cap->sc_level - cap->sc_cur,
- cap->sc_monarg);
- cap->sc_cur = cap->sc_level;
- cap->sc_nlines++;
+ if (cap->sc_linemon) {
+ if (cap->sc_level > cap->sc_cur) {
+ cap->sc_linemon(cap->sc_base + cap->sc_cur,
+ cap->sc_level - cap->sc_cur,
+ cap->sc_monarg);
+ cap->sc_cur = cap->sc_level;
+ cap->sc_nlines++;
+ }
+ cap->sc_linemon(cap->sc_base, 0, cap->sc_monarg);
}
*feof = 1;
return 0;
diff --git a/t/rt.c b/t/rt.c
index 05eb036..2c404e2 100644
--- a/t/rt.c
+++ b/t/rt.c
@@ -92,14 +92,17 @@ static void
linemon(const char *ptr, size_t len, void *data)
{
struct linemon_closure *clos = data;
-
- if (!clos->cont) {
- printf("%s:", clos->prefix);
- if (!(len == 1 && ptr[0] == '\n'))
- putchar(' ');
- }
- fwrite(ptr, len, 1, stdout);
- clos->cont = ptr[len-1] != '\n';
+
+ if (len) {
+ if (!clos->cont) {
+ printf("%s:", clos->prefix);
+ if (!(len == 1 && ptr[0] == '\n'))
+ putchar(' ');
+ }
+ fwrite(ptr, len, 1, stdout);
+ } else
+ fflush(stdout);
+ clos->cont = !(len == 0 || ptr[len-1] == '\n');
}
static void

Return to:

Send suggestions and report system problems to the System administrator.