? cat-date.c Index: cat.1 =================================================================== RCS file: /home/ncvs/src/bin/cat/cat.1,v retrieving revision 1.25 diff -u -r1.25 cat.1 --- cat.1 16 Jan 2005 16:41:55 -0000 1.25 +++ cat.1 6 Sep 2006 20:34:17 -0000 @@ -32,7 +32,7 @@ .\" @(#)cat.1 8.3 (Berkeley) 5/2/95 .\" $FreeBSD: src/bin/cat/cat.1,v 1.25 2005/01/16 16:41:55 ru Exp $ .\" -.Dd March 21, 2004 +.Dd September 6, 2006 .Dt CAT 1 .Os .Sh NAME @@ -41,6 +41,7 @@ .Sh SYNOPSIS .Nm .Op Fl benstuv +.Op Fl D Ar date_format .Op Ar .Sh DESCRIPTION The @@ -73,6 +74,31 @@ .Bl -tag -width indent .It Fl b Number the non-blank output lines, starting at 1. +.It Fl D Ar date_format +Prefix each output line with a string that indicates the date and/or +time when that line was read by the +.Nm +utility. +The resolution used for that time will be to the nearest second. +The format of that prefix is specified by the value of +.Ar date_format . +The +.Ar date_format +argument may contain any of the conversion specifications described in the +.Xr strftime 3 +manual page, as well as any arbitrary text. +No separator will be inserted between the generated prefix and the +remainder of the output line, so if a separator is desired then +the value for +.Ar date_format +should end with a space or the conversion specifier of +.Dq Li %t . +The +.Fl t +and +.Fl v +options do not affect any characters generated by the +.Ar date_format . .It Fl e Display non-printing characters (see the .Fl v @@ -152,6 +178,24 @@ when it encountered the first .Ql \&- operand. +.Pp +The command: +.Pp +.Dl "command | cat -D '%F %T '" +.Pp +will prepend the current date/time in the form +.Dq Li YYYY-MM-DD HH:MM:SS , +followed by a space, to each line of the stdout from +.Nm command . +This is useful for timestamping output, especially if +.Nm command +will be running for a long period of time, and you want to know when +each output line was written. +Note that +.Nm command +must have unbuffered or line-buffered output for the +.Fl D +option to produce accurate timestamps. .Sh SEE ALSO .Xr head 1 , .Xr more 1 , @@ -160,7 +204,8 @@ .Xr tail 1 , .Xr vis 1 , .Xr zcat 1 , -.Xr setbuf 3 +.Xr setbuf 3 , +.Xr strftime 3 .Rs .%A Rob Pike .%T "UNIX Style, or cat -v Considered Harmful" @@ -175,7 +220,7 @@ specification. .Pp The flags -.Op Fl benstv +.Op Fl bDenstv are extensions to the specification. .Sh HISTORY A @@ -199,3 +244,9 @@ or .Fl v option is in effect. +.Pp +The +.Nm +utility does not correctly handle multibyte characters in the +argument to +.Fl D . Index: cat.c =================================================================== RCS file: /home/ncvs/src/bin/cat/cat.c,v retrieving revision 1.32 diff -u -r1.32 cat.c --- cat.c 10 Jan 2005 08:39:20 -0000 1.32 +++ cat.c 6 Sep 2006 20:34:17 -0000 @@ -64,13 +64,19 @@ #include #include +#define DATEPFX_MAXLEN 1024 + int bflag, eflag, nflag, sflag, tflag, vflag; int rval; +static time_t prev_time; +static const char *datefmt; +static char *datepfx; const char *filename; static void usage(void); static void scanfiles(char *argv[], int cooked); static void cook_cat(FILE *); +static void set_datepfx(void); static void raw_cat(int); #ifndef NO_UDOM_SUPPORT @@ -84,11 +90,14 @@ setlocale(LC_CTYPE, ""); - while ((ch = getopt(argc, argv, "benstuv")) != -1) + while ((ch = getopt(argc, argv, "bD:enstuv")) != -1) switch (ch) { case 'b': bflag = nflag = 1; /* -b implies -n */ break; + case 'D': + datefmt = optarg; + break; case 'e': eflag = vflag = 1; /* -e implies -v */ break; @@ -112,7 +121,17 @@ } argv += optind; - if (bflag || eflag || nflag || sflag || tflag || vflag) + /* + * If -D was specified, then make an initial call to set the prefix. + * This means that if the format is likely to generate an error, the + * user will see that error immediately instead of waiting until + * after the first line is read in. + */ + if (datefmt != NULL) + set_datepfx(); + + if (bflag || eflag || nflag || sflag || tflag || vflag || + datefmt != NULL) scanfiles(argv, 1); else scanfiles(argv, 0); @@ -125,7 +144,7 @@ static void usage(void) { - fprintf(stderr, "usage: cat [-benstuv] [file ...]\n"); + fprintf(stderr, "usage: cat [-benstuv] [-D datefmt] [file ...]\n"); exit(1); /* NOTREACHED */ } @@ -198,6 +217,12 @@ if (ferror(stdout)) break; } + if (datefmt != NULL) { + set_datepfx(); + (void)fputs(datepfx, stdout); + if (ferror(stdout)) + break; + } } if (ch == '\n') { if (eflag && putchar('$') == EOF) @@ -261,6 +286,30 @@ } } +static void +set_datepfx(void) +{ + int reslen; + time_t now; + + if (datepfx == NULL) + datepfx = malloc(DATEPFX_MAXLEN); + + /* + * Avoid the calls to localtime and strftime if the current second + * is the same as the second when the previous line was read in. + */ + now = time(NULL); + if (now == prev_time) + return; + prev_time = now; + + reslen = strftime(datepfx, DATEPFX_MAXLEN, datefmt, localtime(&now)); + if (reslen == 0) + errx(1, "Format specified by -D results in prefix > %d bytes.", + DATEPFX_MAXLEN); +} + #ifndef NO_UDOM_SUPPORT static int