Re: [Patch] script: Implement a --ts-output and --ts-script options. -v3

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 Hi Robin, 

On Wed, Jul 15, 2009 at 09:33:22AM -0500, Robin Holt wrote:
> This patch introduces two new options (actually three).

 I spent a moment with the patch, and I found few problems:

 - the applications that prepare output according to the terminal size
   (e.g. ps aux) will produce too long lines. It seems that workaround
   is to change size (-30 columns) of the slave terminal by TIOCSWINSZ.

 - interactive mode (without -c) does not work properly

Script started, file is typescript
    0.000008 (    0.000008)|
nb:~$ date                   
    2.602039 (    0.272087)| Mon Jul 20 14:55:44 CEST 2009
    2.605886 (    0.003847)|
nb:~$ exit                   
Script done, file is typescript

   I guess we expect the timestamps and prompt ("nb:~$") on the same line. 

 And finally, the code in the patch could be refactored (see my attempt
 below).

 Sorry, but from my point of view the patch still looks like a hack. Not
 sure if we really need it.

    Karel

diff --git a/misc-utils/script.1 b/misc-utils/script.1
index e017b63..eed5444 100644
--- a/misc-utils/script.1
+++ b/misc-utils/script.1
@@ -44,6 +44,8 @@
 .Op Fl f
 .Op Fl q
 .Op Fl t
+.Op Fl O
+.Op Fl S
 .Op Ar file
 .Sh DESCRIPTION
 .Nm Script
@@ -86,6 +88,13 @@ separated by a space. The first field indicates how much time elapsed since
 the previous output. The second field indicates how many characters were
 output this time. This information can be used to replay typescripts with
 realistic typing and output delays.
+.It Fl O
+Add a formatted timestamp to stdout for each new line of output.
+The timestamp is composed of two floating point values, the first is
+seconds since the script was started.  The second is seconds since the
+previous line of output.
+.It Fl S
+Puts the same values as above in the typescript file instead of stdout.
 .El
 .Pp
 The script ends when the forked shell exits (a
diff --git a/misc-utils/script.c b/misc-utils/script.c
index b877c31..cae312e 100644
--- a/misc-utils/script.c
+++ b/misc-utils/script.c
@@ -95,6 +95,8 @@ char	*cflg = NULL;
 int	fflg = 0;
 int	qflg = 0;
 int	tflg = 0;
+int	ts_output = 0;		/* put timestamp on stdout */
+int	ts_script = 0;		/* put timestamp in script output */
 
 static char *progname;
 
@@ -150,7 +152,7 @@ main(int argc, char **argv) {
 		}
 	}
 
-	while ((ch = getopt(argc, argv, "ac:fqt")) != -1)
+	while ((ch = getopt(argc, argv, "ac:fqtOS")) != -1)
 		switch((char)ch) {
 		case 'a':
 			aflg++;
@@ -167,10 +169,17 @@ main(int argc, char **argv) {
 		case 't':
 			tflg++;
 			break;
+		case 'O':
+			ts_output++;
+			break;
+		case 'S':
+			ts_script++;
+			break;
 		case '?':
 		default:
 			fprintf(stderr,
-				_("usage: script [-a] [-f] [-q] [-t] [file]\n"));
+				_("usage: script [-a] [-c <command>] [-f] [-q] "
+					"[-t] [-O] [-S] [file]\n"));
 			exit(1);
 		}
 	argc -= optind;
@@ -284,25 +293,34 @@ my_strftime(char *buf, size_t len, const char *fmt, const struct tm *tm) {
 	strftime(buf, len, fmt, tm);
 }
 
+#define tv2double(_tv)	((_tv)->tv_sec + (double) (_tv)->tv_usec / 1000000)
+
 void
 dooutput() {
-	register ssize_t cc;
+	register ssize_t cc, real_cc;
 	time_t tvec;
-	char obuf[BUFSIZ];
+	char obuf[BUFSIZ], *obuf_p;
 	struct timeval tv;
-	double oldtime=time(NULL), newtime;
+	double oldtime = 0, newtime = 0, starttime = 0;
 	int flgs = 0;
 	ssize_t wrt;
 	size_t fwrt;
+	int nl=1;
 
 	(void) close(0);
 #ifdef HAVE_LIBUTIL
 	(void) close(slave);
 #endif
+
 	tvec = time((time_t *)NULL);
 	my_strftime(obuf, sizeof obuf, "%c\n", localtime(&tvec));
 	fprintf(fscript, _("Script started on %s"), obuf);
 
+	if (tflg || ts_output || ts_script) {
+		gettimeofday(&tv, NULL);
+		newtime = starttime = tv2double(&tv);
+	}
+
 	if (die == 0 && child && kill(child, 0) == -1 && errno == ESRCH)
 		/*
 		 * the SIGCHLD handler could be executed when the "child"
@@ -323,11 +341,13 @@ dooutput() {
 			if (fcntl(master, F_SETFL, (flgs | O_NONBLOCK)) == -1)
 				break;
 		}
-		if (tflg)
+		if (tflg || ts_output || ts_script) {
 			gettimeofday(&tv, NULL);
-
+			oldtime = newtime;
+			newtime = tv2double(&tv);
+		}
 		errno = 0;
-		cc = read(master, obuf, sizeof (obuf));
+		real_cc = cc = read(master, obuf, sizeof (obuf));
 
 		if (die && errno == EINTR && cc <= 0)
 			/* read() has been interrupted by SIGCHLD, try it again
@@ -336,27 +356,67 @@ dooutput() {
 			continue;
 		if (cc <= 0)
 			break;
-		if (tflg) {
-			newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
-			fprintf(stderr, "%f %zd\n", newtime - oldtime, cc);
-			oldtime = newtime;
-		}
-		wrt = write(1, obuf, cc);
-		if (wrt < 0) {
-			int err = errno;
-			fprintf (stderr, _("%s: write error: %s\n"),
-				progname, strerror(err));
-			fail();
-		}
-		fwrt = fwrite(obuf, 1, cc, fscript);
-		if (fwrt < cc) {
-			int err = errno;
-			fprintf (stderr, _("%s: cannot write script file, error: %s\n"),
-				progname, strerror(err));
-			fail();
+		obuf_p = obuf;
+
+		while(cc) {
+			if (nl && (ts_output || ts_script)) {
+				char buf_ts[30];
+				sprintf(buf_ts, "%12.6f (%12.6f)| ",
+					newtime - starttime, newtime - oldtime);
+
+				if (ts_output) {
+					wrt = write(1, buf_ts, 29);
+					if (wrt != 29) {
+						int err = errno;
+						fprintf (stderr, _("%s: write error: %s\n"),
+							progname, strerror(err));
+						fail();
+					}
+				}
+				if (ts_script) {
+					fwrt = fwrite(buf_ts, 1, 29, fscript);
+					if (fwrt != 29) {
+						int err = errno;
+						fprintf (stderr, _("%s: cannot write script file, error: %s\n"),
+							progname, strerror(err));
+						fail();
+					}
+				}
+			}
+			if (ts_output || ts_script) {
+				int i;
+				for (i = 0; i < cc; i++) {
+					nl = (obuf_p[i] == '\n');
+					if (nl) {
+						cc = i + 1;
+						break;
+					}
+				}
+			}
+			if (tflg)
+				fprintf(stderr, "%f %zd\n", newtime - oldtime,
+					cc + (ts_script && nl ? 29 : 0));
+			wrt = write(1, obuf_p, cc);
+			if (wrt < 0) {
+				int err = errno;
+				fprintf (stderr, _("%s: write error: %s\n"),
+					progname, strerror(err));
+				fail();
+			}
+			fwrt = fwrite(obuf_p, 1, cc, fscript);
+			if (fwrt < cc) {
+				int err = errno;
+				fprintf (stderr, _("%s: cannot write script file, error: %s\n"),
+					progname, strerror(err));
+				fail();
+			}
+			if (real_cc != cc)
+				obuf_p = &obuf_p[cc];
+			real_cc -= cc;
+			cc = real_cc;
+			if (fflg)
+				fflush(fscript);
 		}
-		if (fflg)
-			(void) fflush(fscript);
 	} while(1);
 
 	if (flgs)
-- 
1.6.2.5

--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux