From owner-freebsd-current@FreeBSD.ORG Sat Aug 12 05:53:01 2006 Return-Path: X-Original-To: current@freebsd.org Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E517716A4E7 for ; Sat, 12 Aug 2006 05:53:01 +0000 (UTC) (envelope-from prvs=julian=372565577@elischer.org) Received: from a50.ironport.com (a50.ironport.com [63.251.108.112]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7FB6543D45 for ; Sat, 12 Aug 2006 05:53:01 +0000 (GMT) (envelope-from prvs=julian=372565577@elischer.org) Received: from unknown (HELO [192.168.2.3]) ([10.251.60.35]) by a50.ironport.com with ESMTP; 11 Aug 2006 22:53:01 -0700 Message-ID: <44DD6CBC.9030309@elischer.org> Date: Fri, 11 Aug 2006 22:53:00 -0700 From: Julian Elischer User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.13) Gecko/20060414 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Giorgos Keramidas References: <44DD4510.5070002@elischer.org> <20060812033607.GB80768@gothmog.pc> <44DD50FF.5040406@elischer.org> <20060812041535.GA82669@gothmog.pc> <44DD5992.5080409@elischer.org> <20060812045622.GA84354@gothmog.pc> In-Reply-To: <20060812045622.GA84354@gothmog.pc> Content-Type: multipart/mixed; boundary="------------080909080706090606000305" Cc: current@freebsd.org Subject: Re: suggested addition to 'date' X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 12 Aug 2006 05:53:02 -0000 This is a multi-part message in MIME format. --------------080909080706090606000305 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Giorgos Keramidas wrote: >On 2006-08-11 21:31, Julian Elischer wrote: > > >>Giorgos Keramidas wrote: >> >> >>>On 2006-08-11 20:54, Julian Elischer wrote: >>> >>> >>>>Yes I said I hacked it in :-) >>>>In my app you will never have such long lines.. >>>>basically you need something that reads lines and tells you how much it >>>>read.. >>>>(I have no idea WHY fgets need sto return the START.. you already KNOW >>>>that!) >>>>it'd be nice if you didn't have to to a strlen() on each line. >>>> >>>> >>>Perhaps the solution Sam proposed is much better then? >>> >>>To read one >>>character at-a-time and only special-case the '\n' characters? >>> >>> >>I didn't see that being mentionned anywhere, but I guess compared to >>running date once for every line >>I could live with a strlen(). :-) >>it'd probably be more efficient than doing it one char at a time. >> >> >> >>>Maybe something like this? >>> >>> if (sflag) { >>> >>> >>> >>> >>> >>[...] >> >> >> >>> otval = tval; >>> } >>> (void)printf("%s", buf); >>> if (fflush(stdout)) >>> >>> >>> >>> >>wonder if it would want to be flushed less often if stdout was a file.. >>I think stdio would do the right thing in most cases so I guess teh >>fflush woudl only be needed at the end, after the last file, >>or maybe just on a signal handler so it flushes out the last buffer on ^C >> >> > >IIRC, stdio can buffer more than one line, so now that you mention it, >maybe it is a good idea to flush at every '\n' character to make output >appear every time there's a complete line ready. > > stdio will automatically flush pipe and terminal output at every \n. the problem is if you are writing to a file. If you get a signal it just calls _exit() which doesn't flush anything. if it does an exit() it flushes the output so that would be ok. signal handlers shouldn't call stdio as they are not async-safe, so making a signal handler that calls fflush is not possible. I tried making the signal handler just set a variable that makes the main loop quit, flush and exit, but believe it or not, fgets() doesn't return from a signal. so you hit ^C but it doesn't notice the flag that is set until you then hit CR. hmm maybe if the signal handler closed file descriptor 0....... heh, yep that makes it quit.. try this on for size :) >I'm too sleepy to run tests now, but if you still want something inside >date(1) -- which is probably the only logical place to put it (to let us >leverage the date/time formatting code date(1) already has) -- then I >can run a few tests during the weekend and see which approach works >better, for some definition of `better' :-) > > --------------080909080706090606000305 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="date.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="date.diff" ? date ? date.1.gz ? xx Index: date.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/bin/date/date.c,v retrieving revision 1.47 diff -u -r1.47 date.c --- date.c 10 Jan 2005 08:39:21 -0000 1.47 +++ date.c 12 Aug 2006 05:50:57 -0000 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -64,17 +65,19 @@ static time_t tval; int retval; +int cleanup; static void setthetime(const char *, const char *, int, int); static void badformat(void); static void usage(void); +static void sighandler(int); int main(int argc, char *argv[]) { struct timezone tz; int ch, rflag; - int jflag, nflag; + int jflag, nflag, sflag; const char *format; char buf[1024]; char *endptr, *fmt; @@ -89,9 +92,9 @@ (void) setlocale(LC_TIME, ""); tz.tz_dsttime = tz.tz_minuteswest = 0; rflag = 0; - jflag = nflag = 0; + sflag = jflag = nflag = 0; set_timezone = 0; - while ((ch = getopt(argc, argv, "d:f:jnr:t:uv:")) != -1) + while ((ch = getopt(argc, argv, "d:f:jnr:t:uv:s")) != -1) switch((char)ch) { case 'd': /* daylight savings time */ tz.tz_dsttime = strtol(optarg, &endptr, 10) ? 1 : 0; @@ -114,6 +117,9 @@ if (*tmp != 0) usage(); break; + case 's': /* don't set network */ + sflag = 1; /* stream mode */ + break; case 't': /* minutes west of UTC */ /* error check; don't allow "PST" */ tz.tz_minuteswest = strtol(optarg, &endptr, 10); @@ -160,22 +166,76 @@ if (*argv && **argv == '+') format = *argv + 1; - lt = *localtime(&tval); - badv = vary_apply(v, <); - if (badv) { - fprintf(stderr, "%s: Cannot apply date adjustment\n", - badv->arg); + if (sflag) { + char linebuf[2048]; + time_t otval = 0; + int len; + int complete = 1; + + cleanup = 0; + signal(SIGHUP, sighandler); + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); + signal(SIGXCPU, sighandler); + signal(SIGXFSZ, sighandler); + signal(SIGVTALRM, sighandler); + signal(SIGPROF, sighandler); + while (fgets(linebuf, 2048, stdin) && cleanup == 0) { + if (!rflag && time(&tval) == -1) + err(1, "time"); + + if (complete != 0 && tval != otval) { + lt = *localtime(&tval); + badv = vary_apply(v, <); + if (badv) { + fprintf(stderr, "%s: Cannot apply date adjustment\n", + badv->arg); + vary_destroy(v); + usage(); + } + (void)strftime(buf, sizeof(buf), format, <); + otval = tval; + } + if (complete != 0) { + if (printf("%s", buf) < 0) + break; + complete = 0; + } + if (fputs(linebuf, stdout) == EOF) + break; + len = strlen(linebuf); + if (linebuf[len - 1] == '\n') + complete = 1; + } + if (fflush(stdout)) { + err(1, "stdout"); + } + } else { + lt = *localtime(&tval); + badv = vary_apply(v, <); + if (badv) { + fprintf(stderr, "%s: Cannot apply date adjustment\n", + badv->arg); + vary_destroy(v); + usage(); + } vary_destroy(v); - usage(); + (void)strftime(buf, sizeof(buf), format, <); + (void)printf("%s\n", buf); + if (fflush(stdout)) + err(1, "stdout"); } - vary_destroy(v); - (void)strftime(buf, sizeof(buf), format, <); - (void)printf("%s\n", buf); - if (fflush(stdout)) - err(1, "stdout"); exit(retval); } +static void +sighandler(int arg) +{ + arg = 0; /* shut up gcc */ + close(0); + cleanup = 1; +} + #define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0')) static void @@ -299,7 +359,7 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", - "usage: date [-jnu] [-d dst] [-r seconds] [-t west] " + "usage: date [-jnus] [-d dst] [-r seconds] [-t west] " "[-v[+|-]val[ymwdHMS]] ... ", " " "[-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format]"); --------------080909080706090606000305--