summaryrefslogtreecommitdiffstats
path: root/term-utils/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'term-utils/script.c')
-rw-r--r--term-utils/script.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/term-utils/script.c b/term-utils/script.c
index d5ffa27f1..102f7ec32 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -71,6 +71,7 @@
#include "all-io.h"
#include "monotonic.h"
#include "timeutils.h"
+#include "strutils.h"
#include "debug.h"
@@ -104,6 +105,8 @@ struct script_control {
FILE *typescriptfp; /* output file pointer */
char *tname; /* timing file path */
FILE *timingfp; /* timing file pointer */
+ ssize_t outsz; /* current output file size */
+ ssize_t maxsz; /* maximum output file size */
struct timeval oldtime; /* previous write or command start time */
int master; /* pseudoterminal master file descriptor */
int slave; /* pseudoterminal slave file descriptor */
@@ -169,6 +172,7 @@ static void __attribute__((__noreturn__)) usage(void)
" -e, --return return exit code of the child process\n"
" -f, --flush run flush after each write\n"
" --force use output file even when it is a link\n"
+ " -o, --output-limit <size> terminate if output files exceed size\n"
" -q, --quiet be quiet\n"
" -t[<file>], --timing[=<file>] output timing data to stderr or to FILE\n"
), out);
@@ -266,6 +270,8 @@ static void wait_for_child(struct script_control *ctl, int wait)
static void write_output(struct script_control *ctl, char *obuf,
ssize_t bytes)
{
+ int timing_bytes = 0;
+
DBG(IO, ul_debug(" writing output"));
if (ctl->timing && ctl->timingfp) {
@@ -275,11 +281,13 @@ static void write_output(struct script_control *ctl, char *obuf,
gettime_monotonic(&now);
timersub(&now, &ctl->oldtime, &delta);
- fprintf(ctl->timingfp, "%ld.%06ld %zd\n",
+ timing_bytes = fprintf(ctl->timingfp, "%ld.%06ld %zd\n",
(long)delta.tv_sec, (long)delta.tv_usec, bytes);
if (ctl->flush)
fflush(ctl->timingfp);
ctl->oldtime = now;
+ if (timing_bytes < 0)
+ timing_bytes = 0;
}
DBG(IO, ul_debug(" writing to script file"));
@@ -299,6 +307,9 @@ static void write_output(struct script_control *ctl, char *obuf,
fail(ctl);
}
+ if (ctl->maxsz != 0)
+ ctl->outsz += bytes + timing_bytes;
+
DBG(IO, ul_debug(" writing output *done*"));
}
@@ -350,7 +361,6 @@ static void handle_io(struct script_control *ctl, int fd, int *eof)
{
char buf[BUFSIZ];
ssize_t bytes;
-
DBG(IO, ul_debug("%d FD active", fd));
*eof = 0;
@@ -379,10 +389,18 @@ static void handle_io(struct script_control *ctl, int fd, int *eof)
* shell output that looks like double echoing */
fdatasync(ctl->master);
- /* from command (master) to stdout */
+ /* from command (master) to stdout and log */
} else if (fd == ctl->master) {
DBG(IO, ul_debug(" master --> stdout %zd bytes", bytes));
write_output(ctl, buf, bytes);
+
+ /* check output limit */
+ if (ctl->maxsz != 0 && ctl->outsz >= ctl->maxsz) {
+ if (!ctl->quiet)
+ printf(_("Script terminated, max output file size %zd exceeded.\n"), ctl->maxsz);
+ DBG(IO, ul_debug("output size %zd, exceeded limit %zd", ctl->outsz, ctl->maxsz));
+ done(ctl);
+ }
}
}
@@ -688,8 +706,7 @@ int main(int argc, char **argv)
.line = "/dev/ptyXX",
#endif
.master = -1,
- .poll_timeout = -1,
- 0
+ .poll_timeout = -1
};
int ch;
@@ -701,6 +718,7 @@ int main(int argc, char **argv)
{"return", no_argument, NULL, 'e'},
{"flush", no_argument, NULL, 'f'},
{"force", no_argument, NULL, FORCE_OPTION,},
+ {"output-limit", required_argument, NULL, 'o'},
{"quiet", no_argument, NULL, 'q'},
{"timing", optional_argument, NULL, 't'},
{"version", no_argument, NULL, 'V'},
@@ -723,7 +741,7 @@ int main(int argc, char **argv)
script_init_debug();
- while ((ch = getopt_long(argc, argv, "ac:efqt::Vh", longopts, NULL)) != -1)
+ while ((ch = getopt_long(argc, argv, "ac:efo:qt::Vh", longopts, NULL)) != -1)
switch (ch) {
case 'a':
ctl.append = 1;
@@ -740,6 +758,9 @@ int main(int argc, char **argv)
case FORCE_OPTION:
ctl.force = 1;
break;
+ case 'o':
+ ctl.maxsz = strtosize_or_err(optarg, _("failed to parse output limit size"));
+ break;
case 'q':
ctl.quiet = 1;
break;