date not built from here
This commit is contained in:
		
							parent
							
								
									b49ba611bd
								
							
						
					
					
						commit
						47c18edb26
					
				| @ -1,443 +0,0 @@ | ||||
| /* date - Display (or set) the date and time		Author: V. Archer */ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <ctype.h> | ||||
| #include <stddef.h> | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #define	MIN	60L		/* # seconds in a minute */ | ||||
| #define	HOUR	(60 * MIN)	/* # seconds in an hour */ | ||||
| #define	DAY	(24 * HOUR)	/* # seconds in a day */ | ||||
| #define	YEAR	(365 * DAY)	/* # seconds in a (non-leap) year */ | ||||
| 
 | ||||
| int qflag, uflag, sflag, Sflag; | ||||
| 
 | ||||
| /* Default output file descriptor.
 | ||||
|  */ | ||||
| int outfd = 1; | ||||
| 
 | ||||
| _PROTOTYPE(int main, (int argc, char **argv)); | ||||
| _PROTOTYPE(void putchar, (int c)); | ||||
| _PROTOTYPE(void pstring, (char *s, int len)); | ||||
| _PROTOTYPE(void pldecimal, (unsigned long d, int digits)); | ||||
| _PROTOTYPE(void pdecimal, (int d, int digits)); | ||||
| _PROTOTYPE(void fmtdate, (char *format, time_t t, struct tm *p)); | ||||
| _PROTOTYPE(time_t make_time, (char *t)); | ||||
| _PROTOTYPE(struct tm *september, (time_t *tp)); | ||||
| _PROTOTYPE(void usage, (void)); | ||||
| 
 | ||||
| /* Main module. Handles P1003.2 date and system administrator's date. The
 | ||||
|  * date entered should be given GMT, regardless of the system's TZ! | ||||
|  */ | ||||
| int main(argc, argv) | ||||
| int argc; | ||||
| char **argv; | ||||
| { | ||||
|   time_t t; | ||||
|   struct tm *tm; | ||||
|   char *format; | ||||
|   char time_buf[40]; | ||||
|   int n; | ||||
|   int i; | ||||
| 
 | ||||
|   time(&t); | ||||
| 
 | ||||
|   i = 1; | ||||
|   while (i < argc && argv[i][0] == '-') { | ||||
| 	char *opt = argv[i++] + 1, *end; | ||||
| 
 | ||||
| 	if (opt[0] == '-' && opt[1] == 0) break; | ||||
| 
 | ||||
| 	while (*opt != 0) switch (*opt++) { | ||||
| 	case 'q': | ||||
| 		qflag = 1; | ||||
| 		break; | ||||
| 	case 's': | ||||
| 		sflag = 1; | ||||
| 		break; | ||||
| 	case 'u': | ||||
| 		uflag = 1; | ||||
| 		break; | ||||
| 	case 'S': | ||||
| 		Sflag = 1; | ||||
| 		break; | ||||
| 	case 't': | ||||
| 		/* (obsolete, now -r) */ | ||||
| 	case 'r': | ||||
| 		if (*opt == 0) { | ||||
| 			if (i == argc) usage(); | ||||
| 			opt = argv[i++]; | ||||
| 		} | ||||
| 		t = strtoul(opt, &end, 10); | ||||
| 		if (*end != 0) usage(); | ||||
| 		opt = ""; | ||||
| 		break; | ||||
| 	default: | ||||
| 		usage(); | ||||
| 	} | ||||
|   } | ||||
| 
 | ||||
|   if (!qflag && i < argc && ('0' <= argv[i][0] && argv[i][0] <= '9')) { | ||||
| 	t = make_time(argv[i++]); | ||||
| 	sflag = 1; | ||||
|   } | ||||
| 
 | ||||
|   format = "%c"; | ||||
|   if (i < argc && argv[i][0] == '+') format = argv[i++] + 1; | ||||
| 
 | ||||
|   if (i != argc) usage(); | ||||
| 
 | ||||
|   if (qflag) { | ||||
| 	pstring("\nPlease enter date: MMDDYYhhmmss. Then hit the RETURN key.\n", -1); | ||||
| 	n = read(0, time_buf, sizeof(time_buf)); | ||||
| 	if (n > 0 && time_buf[n-1] == '\n') n--; | ||||
| 	if (n >= 0) time_buf[n] = 0; | ||||
| 	t = make_time(time_buf); | ||||
| 	sflag = 1; | ||||
|   } | ||||
| 
 | ||||
|   if (sflag && stime(&t) != 0) { | ||||
| 	outfd = 2; | ||||
| 	pstring("No permission to set time\n", -1); | ||||
| 	return(1); | ||||
|   } | ||||
| 
 | ||||
|   tm = Sflag ? september(&t) : uflag ? gmtime(&t) : localtime(&t); | ||||
| 
 | ||||
|   fmtdate(format, t, tm); | ||||
|   putchar('\n'); | ||||
|   return(0); | ||||
| } | ||||
| 
 | ||||
| /* Replacement for stdio putchar().
 | ||||
|  */ | ||||
| void putchar(c) | ||||
| int c; | ||||
| { | ||||
|   static char buf[1024]; | ||||
|   static char *bp = buf; | ||||
| 
 | ||||
|   if (c != 0) *bp++ = c; | ||||
|   if (c == 0 || c == '\n' || bp == buf + sizeof(buf)) { | ||||
| 	write(outfd, buf, bp - buf); | ||||
| 	bp = buf; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Internal function that prints a n-digits number. Replaces stdio in our
 | ||||
|  * specific case. | ||||
|  */ | ||||
| void pldecimal(d, digits) | ||||
| unsigned long d; | ||||
| int digits; | ||||
| { | ||||
|   digits--; | ||||
|   if (d > 9 || digits > 0) pldecimal(d / 10, digits); | ||||
|   putchar('0' + (d % 10)); | ||||
| } | ||||
| 
 | ||||
| void pdecimal(d, digits) | ||||
| int d, digits; | ||||
| { | ||||
|   pldecimal((unsigned long) d, digits); | ||||
| } | ||||
| 
 | ||||
| /* Internal function that prints a fixed-size string. Replaces stdio in our
 | ||||
|  * specific case. | ||||
|  */ | ||||
| void pstring(s, len) | ||||
| char *s; | ||||
| int len; | ||||
| { | ||||
|   while (*s) | ||||
| 	if (len--) | ||||
| 		putchar(*s++); | ||||
| 	else | ||||
| 		break; | ||||
| } | ||||
| 
 | ||||
| /* Format the date, using the given locale string. A special case is the
 | ||||
|  * TZ which might be a sign followed by four digits (New format time zone). | ||||
|  */ | ||||
| void fmtdate(format, t, p) | ||||
| char *format; | ||||
| time_t t; | ||||
| struct tm *p; | ||||
| { | ||||
|   int i; | ||||
|   char *s; | ||||
|   static char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday", | ||||
| 		       "Thursday", "Friday", "Saturday"}; | ||||
|   static char *month[] = {"January", "February", "March", "April", | ||||
| 			"May", "June", "July", "August", | ||||
| 		    "September", "October", "November", "December"}; | ||||
| 
 | ||||
|   while (*format) | ||||
| 	if (*format == '%') { | ||||
| 		switch (*++format) { | ||||
| 		    case 'A': | ||||
| 			pstring(wday[p->tm_wday], -1); | ||||
| 			break; | ||||
| 		    case 'B': | ||||
| 			pstring(month[p->tm_mon], -1); | ||||
| 			break; | ||||
| 		    case 'D': | ||||
| 			pdecimal(p->tm_mon + 1, 2); | ||||
| 			putchar('/'); | ||||
| 			pdecimal(p->tm_mday, 2); | ||||
| 			putchar('/'); | ||||
| 		    case 'y': | ||||
| 			pdecimal(p->tm_year % 100, 2); | ||||
| 			break; | ||||
| 		    case 'H': | ||||
| 			pdecimal(p->tm_hour, 2); | ||||
| 			break; | ||||
| 		    case 'I': | ||||
| 			i = p->tm_hour % 12; | ||||
| 			pdecimal(i ? i : 12, 2); | ||||
| 			break; | ||||
| 		    case 'M': | ||||
| 			pdecimal(p->tm_min, 2); | ||||
| 			break; | ||||
| 		    case 'X': | ||||
| 		    case 'T': | ||||
| 			pdecimal(p->tm_hour, 2); | ||||
| 			putchar(':'); | ||||
| 			pdecimal(p->tm_min, 2); | ||||
| 			putchar(':'); | ||||
| 		    case 'S': | ||||
| 			pdecimal(p->tm_sec, 2); | ||||
| 			break; | ||||
| 		    case 'U': | ||||
| 			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2); | ||||
| 			break; | ||||
| 		    case 'W': | ||||
| 			if (--(p->tm_wday) < 0) p->tm_wday = 6; | ||||
| 			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2); | ||||
| 			if (++(p->tm_wday) > 6) p->tm_wday = 0; | ||||
| 			break; | ||||
| 		    case 'Y': | ||||
| 			pdecimal(p->tm_year + 1900, 4); | ||||
| 			break; | ||||
| 		    case 'Z': | ||||
| 			if (uflag) { | ||||
| 				s = "GMT"; | ||||
| 			} else { | ||||
| 				s = (p->tm_isdst == 1) ? tzname[1] : tzname[0]; | ||||
| 			} | ||||
| 			pstring(s, strlen(s)); | ||||
| 			break; | ||||
| 		    case 'a': | ||||
| 			pstring(wday[p->tm_wday], 3); | ||||
| 			break; | ||||
| 		    case 'b': | ||||
| 		    case 'h': | ||||
| 			pstring(month[p->tm_mon], 3); | ||||
| 			break; | ||||
| 		    case 'c': | ||||
| 			if (!(s = getenv("LC_TIME"))) | ||||
| 				s = "%a %b %e %T %Z %Y"; | ||||
| 			fmtdate(s, t, p); | ||||
| 			break; | ||||
| 		    case 'd': | ||||
| 			pdecimal(p->tm_mday, 2); | ||||
| 			break; | ||||
| 		    case 'e': | ||||
| 			if (p->tm_mday < 10) putchar(' '); | ||||
| 			pdecimal(p->tm_mday, 1); | ||||
| 			break; | ||||
| 		    case 'j': | ||||
| 			pdecimal(p->tm_yday + 1, 3); | ||||
| 			break; | ||||
| 		    case 'm': | ||||
| 			pdecimal(p->tm_mon + 1, 2); | ||||
| 			break; | ||||
| 		    case 'n':	putchar('\n');	break; | ||||
| 		    case 'p': | ||||
| 			if (p->tm_hour < 12) | ||||
| 				putchar('A'); | ||||
| 			else | ||||
| 				putchar('P'); | ||||
| 			putchar('M'); | ||||
| 			break; | ||||
| 		    case 'r': | ||||
| 			fmtdate("%I:%M:%S %p", t, p); | ||||
| 			break; | ||||
| 		    case 's': | ||||
| 			pldecimal((unsigned long) t, 0); | ||||
| 			break; | ||||
| 		    case 't':	putchar('\t');	break; | ||||
| 		    case 'w': | ||||
| 			putchar('0' + p->tm_wday); | ||||
| 			break; | ||||
| 		    case 'x': | ||||
| 			fmtdate("%B %e %Y", t, p); | ||||
| 			break; | ||||
| 		    case '%':	putchar('%');	break; | ||||
| 		    case '\0':	format--; | ||||
| 		} | ||||
| 		format++; | ||||
| 	} else | ||||
| 		putchar(*format++); | ||||
| } | ||||
| 
 | ||||
| /* Convert a local date string into GMT time in seconds. */ | ||||
| time_t make_time(t) | ||||
| char *t; | ||||
| { | ||||
|   struct tm tm;				/* user specified time */ | ||||
|   time_t now;				/* current time */ | ||||
|   int leap;				/* current year is leap year */ | ||||
|   int i;				/* general index */ | ||||
|   int fld;				/* number of fields */ | ||||
|   int f[6];				/* time fields */ | ||||
|   static int days_per_month[2][12] = { | ||||
|   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, | ||||
|   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }}; | ||||
| 
 | ||||
| /* Get current time just in case */ | ||||
|   now = time((time_t *) 0); | ||||
|   tm  = *localtime(&now); | ||||
|   tm.tm_sec   = 0; | ||||
|   tm.tm_mon++; | ||||
|   tm.tm_year %= 100; | ||||
| 
 | ||||
| /* Parse the time */ | ||||
| #if '0'+1 != '1' || '1'+1 != '2' || '2'+1 != '3' || '3'+1 != '4' || \ | ||||
|     '4'+1 != '5' || '5'+1 != '6' || '6'+1 != '7' || '7'+1 != '8' || '8'+1 != '9' | ||||
|   << Code unsuitable for character collating sequence >> | ||||
| #endif | ||||
| 
 | ||||
|   for (fld = 0; fld < sizeof(f)/sizeof(f[0]); fld++) { | ||||
| 	if (*t == 0) break; | ||||
| 	f[fld] = 0; | ||||
| 	for (i = 0; i < 2; i++, t++) { | ||||
| 		if (*t < '0' || *t > '9') usage(); | ||||
| 		f[fld] = f[fld] * 10 + *t - '0'; | ||||
| 	} | ||||
|   } | ||||
| 
 | ||||
|   switch (fld) { | ||||
|   case 2: | ||||
| 	tm.tm_hour = f[0]; tm.tm_min  = f[1]; break; | ||||
| 
 | ||||
|   case 3: | ||||
| 	tm.tm_hour = f[0]; tm.tm_min  = f[1]; tm.tm_sec  = f[2]; | ||||
| 	break; | ||||
| 
 | ||||
|   case 5: | ||||
|   	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2]; | ||||
| 	tm.tm_hour = f[3]; tm.tm_min  = f[4]; | ||||
| 	break; | ||||
| 
 | ||||
|   case 6: | ||||
| 	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2]; | ||||
| 	tm.tm_hour = f[3]; tm.tm_min  = f[4]; tm.tm_sec  = f[5]; | ||||
| 	break; | ||||
| 
 | ||||
|   default: | ||||
| 	usage(); | ||||
|   } | ||||
| 
 | ||||
| /* Convert the time into seconds since 1 January 1970 */ | ||||
|   if (tm.tm_year < 70) | ||||
|     tm.tm_year += 100; | ||||
|   leap = (tm.tm_year % 4 == 0 && tm.tm_year % 400 != 0); | ||||
|   if (tm.tm_mon  < 1  || tm.tm_mon  > 12 || | ||||
|       tm.tm_mday < 1  || tm.tm_mday > days_per_month[leap][tm.tm_mon-1] || | ||||
|       tm.tm_hour > 23 || tm.tm_min  > 59) { | ||||
|     outfd = 2; | ||||
|     pstring("Illegal date format\n", -1); | ||||
|     exit(1); | ||||
|   } | ||||
| 
 | ||||
| /* Convert the time into Minix time - zone independent code */ | ||||
|   { | ||||
|     time_t utctime;			/* guess at unix time */ | ||||
|     time_t nextbit;			/* next bit to try */ | ||||
|     int rv;				/* result of try */ | ||||
|     struct tm *tmp;			/* local time conversion */ | ||||
| 
 | ||||
| #define COMPARE(a,b)	((a) != (b)) ? ((a) - (b)) : | ||||
| 
 | ||||
|     utctime = 1; | ||||
|     do { | ||||
|       nextbit = utctime; | ||||
|       utctime = nextbit << 1; | ||||
|     } while (utctime >= 1); | ||||
| 
 | ||||
|     for (utctime = 0; ; nextbit >>= 1) { | ||||
| 
 | ||||
|       utctime |= nextbit; | ||||
|       tmp = localtime(&utctime); | ||||
|       if (tmp == 0) continue; | ||||
| 
 | ||||
|       rv = COMPARE(tmp->tm_year,    tm.tm_year) | ||||
|            COMPARE(tmp->tm_mon + 1, tm.tm_mon) | ||||
| 	   COMPARE(tmp->tm_mday,    tm.tm_mday) | ||||
| 	   COMPARE(tmp->tm_hour,    tm.tm_hour) | ||||
| 	   COMPARE(tmp->tm_min,     tm.tm_min) | ||||
| 	   COMPARE(tmp->tm_sec,     tm.tm_sec) | ||||
| 	   0; | ||||
| 
 | ||||
|       if (rv > 0) | ||||
|         utctime &= ~nextbit; | ||||
|       else if (rv == 0) | ||||
|         break; | ||||
| 
 | ||||
|       if (nextbit == 0) { | ||||
| 	uflag = 1; | ||||
|         outfd = 2; | ||||
|         pstring("Inexact conversion to UTC from ", -1); | ||||
|         fmtdate("%c\n", utctime, localtime(&utctime) ); | ||||
| 	exit(1); | ||||
|       } | ||||
|     } | ||||
|     return utctime; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Correct the time to the reckoning of Eternal September. */ | ||||
| struct tm *september(tp) | ||||
| time_t *tp; | ||||
| { | ||||
|   time_t t; | ||||
|   int days; | ||||
|   struct tm *tm; | ||||
| 
 | ||||
|   tm = localtime(tp); | ||||
| 
 | ||||
|   t = *tp - (tm->tm_hour - 12) * 3600L;  /* No zone troubles around noon. */ | ||||
|   days = 0; | ||||
| 
 | ||||
|   while (tm->tm_year > 93 || (tm->tm_year == 93 && tm->tm_mon >= 8)) { | ||||
| 	/* Step back a year or a month. */ | ||||
| 	days += tm->tm_year > 93 ? tm->tm_yday+1 : tm->tm_mday; | ||||
| 	t = *tp - days * (24 * 3600L); | ||||
| 
 | ||||
| 	tm = localtime(&t); | ||||
|   } | ||||
| 
 | ||||
|   if (days > 0) { | ||||
| 	tm = localtime(tp); | ||||
| 	tm->tm_mday = days; | ||||
| 	tm->tm_year = 93; | ||||
| 	tm->tm_mon = 8; | ||||
| #if SANITY | ||||
| 	t = mktime(tm); | ||||
| 	tm = localtime(&t); | ||||
| #endif | ||||
|   } | ||||
|   return tm; | ||||
| } | ||||
| 
 | ||||
| /* (Extended) Posix prototype of date. */ | ||||
| void usage() | ||||
| { | ||||
|   outfd = 2; | ||||
|   pstring("Usage: date [-qsuS] [-r seconds] [[MMDDYY]hhmm[ss]] [+format]\n", -1); | ||||
|   exit(1); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ben Gras
						Ben Gras