Here's a fairly minor patch against screen 4.0.3. Enjoy. The background: we use screen as part of automated stability tests at work, and we use the logging mechanism. We noticed that we could come back after a weekend run and find the disks filled with dozens of gigabytes of output, when some command went crazy and kept spewing output. So I wrote a quick workaround for screen which closed the log files after 1MB. Then I wrote (on my own time) this patch, which makes it configurable. Drawbacks/limitations: - I let logfwrite() return -1 when it passes the size limit. That closes the logfile nicely, but also displays a misleading "log file write failed" error message, with a misleading strerror(). I didn't want to mess around too much here. - Integer overflow on some architectures. off_t seems to be signed 32-bit on some systems which support larger files. But off_t was what the code already used, so I didn't try to change it. - I have only tested this a little bit, and only compiled with gcc on Linux x86 and AMD64. Jörgen Grahn address@hidden Index: logfile.c =================================================================== RCS file: /home/cvs/screen/logfile.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- logfile.c 12 Jun 2008 21:24:52 -0000 1.1.1.1 +++ logfile.c 23 Jun 2008 20:44:05 -0000 1.3 @@ -31,6 +31,8 @@ #include "extern.h" #include "logfile.h" +extern off_t log_max_size; + static void changed_logfile __P((struct logfile *)); static struct logfile *lookup_logfile __P((char *)); static int stolen_logfile __P((struct logfile *)); @@ -158,6 +160,15 @@ return 0; } +static int +long_logfile(l) +struct logfile *l; +{ + struct stat *s = l->st; + return log_max_size && s->st_size > log_max_size; +} + + static struct logfile * lookup_logfile(name) char *name; @@ -259,6 +270,8 @@ if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) return -1; + if (long_logfile(l)) + return -1; r = fwrite(buf, n, 1, l->fp); l->writecount += l->flushcount + 1; l->flushcount = 0; Index: process.c =================================================================== RCS file: /home/cvs/screen/process.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- process.c 12 Jun 2008 21:24:52 -0000 1.1.1.1 +++ process.c 23 Jun 2008 20:44:05 -0000 1.2 @@ -54,6 +54,7 @@ extern int captionalways; extern char *hardcopydir, *screenlogfile, *logtstamp_string; extern int log_flush, logtstamp_on, logtstamp_after; +extern off_t log_max_size; extern char *VisualBellString; extern int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern char SockPath[], *SockName; @@ -2392,6 +2393,47 @@ Msg(0, "log flush timeout set to %ds\n", log_flush); break; } + if (args[1] && !(strcmp(*args, "size"))) + { + char * end; + off_t tmp, tmp2; + int badnumber = 0; + tmp = strtoul(args[1], &end, 10); + /* XXX should validate input better, but + * we don't elsewhere (e.g. atoi doesn't). + */ + if (!*end) + { + tmp2 = tmp; + } + else if (*end=='k' || *end=='K') + tmp2 = tmp * 1024; + else if (*end=='M') + tmp2 = tmp * 1024 * 1024; + else if (*end=='G') + tmp2 = tmp * 1024 * 1024 * 1024; + else + badnumber = 1; + /* pathetic overflow check */ + if (badnumber || tmp2 < tmp) + { + if (msgok) + Msg(0, "usage: logfile size \n"); + } + else + { + log_max_size = tmp2; + if (msgok) + { + if (log_max_size) + Msg(0, "logfile max size set to %lu bytes\n", + (unsigned long)log_max_size); + else + Msg(0, "logfile size restriction removed\n"); + } + } + break; + } if (ParseSaveStr(act, &screenlogfile) || !msgok) break; } Index: screen.c =================================================================== RCS file: /home/cvs/screen/screen.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- screen.c 12 Jun 2008 21:24:52 -0000 1.1.1.1 +++ screen.c 23 Jun 2008 20:44:05 -0000 1.2 @@ -177,6 +177,7 @@ char *screenlogfile; /* filename layout */ int log_flush = 10; /* flush interval in seconds */ +off_t log_max_size = 0; /* logfile size restriction off */ int logtstamp_on = 0; /* tstamp disabled */ char *logtstamp_string; /* stamp layout */ int logtstamp_after = 120; /* first tstamp after 120s */ Index: doc/screen.1 =================================================================== RCS file: /home/cvs/screen/doc/screen.1,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- doc/screen.1 12 Jun 2008 21:24:52 -0000 1.1.1.1 +++ doc/screen.1 23 Jun 2008 21:40:16 -0000 1.3 @@ -1,5 +1,5 @@ .\" vi:set wm=5 -.TH SCREEN 1 "Aug 2003" +.TH SCREEN 1 "Jun 2008" .if n .ds Q \&" .if n .ds U \&" .if t .ds Q `` @@ -2110,12 +2110,26 @@ .BI "logfile " filename .br .BI "logfile flush " secs +.br +.BI "logfile size " bytes .PP Defines the name the logfiles will get. The default is -\*Qscreenlog.%n\*U. The second form changes the number of seconds +\*Qscreenlog.%n\*U. +The second form changes the number of seconds .I screen will wait before flushing the logfile buffer to the file-system. The default value is 10 seconds. +.PP +The third form sets a size limit on the log files, +if you are worried a command may fill the file system with its output. +The size may be given as a plain number of bytes, or with the suffix +.BR k , " M " or " G" . +For example, +.I "logfile size 100k" +limits log files to 100 kB. +.I "logfile size 0" +turns the limit off. +Default is off. .sp .ne 3 .BR "login " [ on | off ] Index: doc/screen.texinfo =================================================================== RCS file: /home/cvs/screen/doc/screen.texinfo,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- doc/screen.texinfo 12 Jun 2008 21:24:52 -0000 1.1.1.1 +++ doc/screen.texinfo 23 Jun 2008 21:45:07 -0000 1.4 @@ -7,7 +7,7 @@ @finalout @setchapternewpage odd @c %**end of header address@hidden version 4.0.2 address@hidden version 4.0.3 @direntry * Screen: (screen). Full-screen window manager. @@ -52,7 +52,7 @@ @title Screen @subtitle The virtual terminal manager @subtitle for Version @value{version} address@hidden Aug 2003 address@hidden Jun 2008 @page @vskip 0pt plus 1filll @@ -996,6 +996,12 @@ Log all output in the current window. @xref{Log}. @item logfile @var{filename} Place where to collect logfiles. @xref{Log}. address@hidden logfile flush @var{seconds} +Logfile flush interval. @xref{Log}. address@hidden logfile size @var{bytes} +Max logfile size. @xref{Log}. address@hidden logfile @var{filename} +Place where to collect logfiles. @xref{Log}. @item login address@hidden Log the window in @file{/etc/utmp}. @xref{Login}. @item logtstamp address@hidden @@ -2888,7 +2894,7 @@ users. If your terminal sends characters, that cause you to abort copy mode, then this command may help by binding these characters to do nothing. -The no-op character is `@' and is used like this: @code{markkeys @@=L=H} +The no-op character is `@@' and is used like this: @code{markkeys @@=L=H} if you do not want to use the `H' or `L' commands any longer. As shown in this example, multiple keys can be assigned to one function in a single statement. @@ -4246,11 +4252,22 @@ @deffn Command logfile filename @deffnx Command logfile flush secs address@hidden Command logfile size bytes (none)@* Defines the name the logfiles will get. The default is @samp{screenlog.%n}. The second form changes the number of seconds @code{screen} will wait before flushing the logfile buffer to the file-system. The default value is 10 seconds. + +The third form sets a size limit on the log files, +if you are worried a command may fill the file system with its output. +The size may be given as a plain number of bytes, or with the suffix address@hidden, @code{M} or @code{G}. +For example, address@hidden size 100k} +limits log files to address@hidden address@hidden size 0} turns the limit off. +Default is off. @end deffn @deffn Command logtstamp [state]