Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Aug 2006 22:53:00 -0700
From:      Julian Elischer <julian@elischer.org>
To:        Giorgos Keramidas <keramida@ceid.upatras.gr>
Cc:        current@freebsd.org
Subject:   Re: suggested addition to 'date'
Message-ID:  <44DD6CBC.9030309@elischer.org>
In-Reply-To: <20060812045622.GA84354@gothmog.pc>
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>

next in thread | previous in thread | raw e-mail | index | archive | help
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 <julian@elischer.org> wrote:
>  
>
>>Giorgos Keramidas wrote:
>>    
>>
>>>On 2006-08-11 20:54, Julian Elischer <julian@elischer.org> 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 <err.h>
 #include <locale.h>
 #include <libutil.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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, &lt);
-	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, &lt);
+				if (badv) {
+					fprintf(stderr, "%s: Cannot apply date adjustment\n",
+						badv->arg);
+					vary_destroy(v);
+					usage();
+				}
+				(void)strftime(buf, sizeof(buf), format, &lt);
+				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, &lt);
+		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, &lt);
+		(void)printf("%s\n", buf);
+		if (fflush(stdout))
+			err(1, "stdout");
 	}
-	vary_destroy(v);
-	(void)strftime(buf, sizeof(buf), format, &lt);
-	(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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?44DD6CBC.9030309>