Re: suggested addition to 'date'

From: Julian Elischer <julian_at_elischer.org>
Date: Fri, 11 Aug 2006 22:53:00 -0700
Giorgos Keramidas wrote:

>On 2006-08-11 21:31, Julian Elischer <julian_at_elischer.org> wrote:
>  
>
>>Giorgos Keramidas wrote:
>>    
>>
>>>On 2006-08-11 20:54, Julian Elischer <julian_at_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' :-)
>  
>


? 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
_at__at_ -49,6 +49,7 _at__at_
 #include <err.h>
 #include <locale.h>
 #include <libutil.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
_at__at_ -64,17 +65,19 _at__at_
 
 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;
_at__at_ -89,9 +92,9 _at__at_
 	(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;
_at__at_ -114,6 +117,9 _at__at_
 			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);
_at__at_ -160,22 +166,76 _at__at_
 	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
_at__at_ -299,7 +359,7 _at__at_
 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]");
Received on Sat Aug 12 2006 - 03:53:01 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:58 UTC