static char *sccsid = "@(#)date.c	4.1 (Berkeley) 10/1/80";
#include <stdio.h>
/*
 * date : print date
 * date YYMMDDHHMM[.SS] : set date, if allowed
 * date -u ... : date in GMT
 */
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <utmp.h>
long	timbuf;
char	*ap, *ep, *sp;
int	uflag;
int	nflag;

char	*timezone();
static	int	dmsize[12] =
{
	31,
	28,
	31,
	30,
	31,
	30,
	31,
	31,
	30,
	31,
	30,
	31
};

struct utmp wtmp[2] = { {"|", "", 0}, {"{", "", 0}};

char	*ctime();
char	*asctime();
struct	tm *localtime();
struct	tm *gmtime();

usage()
{
	printf("Usage: date [-u] [-n] YYMMDDHHMM[.SS]\n");
}

main(argc, argv)
char *argv[];
{
	register char *tzn;
	struct timeb info;
	int wf, rc;
	extern char _sobuf[];
	extern long atol();

	setbuf(stdout, _sobuf);
	rc = 0;
	ftime(&info);
	while((argc>1) && (argv[1][0]=='-'))
		switch(argv[1][1])
		{
		case 'u':	uflag++; argc--; argv++; break;
		case 'n':	nflag++; argc--; argv++; break;
		default:	usage(); exit(1);
		}
	if(argc > 1) {
		ap = argv[1];
		if(nflag)
			timbuf = atol(ap);
		else {
			if (gtime()) {
				printf("date: bad conversion\n");
				exit(1);
			}
		}
		/* convert to GMT assuming local time */
		if (uflag==0) {
			timbuf += (long)info.timezone*60;
			/* now fix up local daylight time */
			if(localtime(&timbuf)->tm_isdst)
				timbuf -= 60*60;
		}
		time(&wtmp[0].ut_time);
		if(stime(&timbuf) < 0) {
			rc++;
			printf("date: no permission\n");
		} else if ((wf = open("/usr/adm/wtmp", 1)) >= 0) {
			time(&wtmp[1].ut_time);
			lseek(wf, 0L, 2);
			write(wf, (char *)wtmp, sizeof(wtmp));
			close(wf);
		}
	}
	if (rc==0)
		time(&timbuf);
	if(uflag) {
		ap = asctime(gmtime(&timbuf));
		tzn = "GMT";
	} else {
		struct tm *tp;
		tp = localtime(&timbuf);
		ap = asctime(tp);
		tzn = timezone(info.timezone, tp->tm_isdst);
	}
	if(nflag) {
		/* fix up daylight saving and timezone */
		if(uflag == 0) {
			timbuf -= (long)info.timezone*60;
			if(localtime(&timbuf)->tm_isdst)
				timbuf += 60*60;
		}
		printf("%ld\n", timbuf);
	} else {
		printf("%.20s", ap);
		if (tzn)
			printf("%s", tzn);
		printf("%s", ap+19);
	}
	exit(rc);
}

gtime()
{
	register int i, year, month;
	int day, hour, mins, secs;
	struct tm *L;
	char x;

	ep=ap;
	while(*ep) ep++;
	sp=ap;
	while(sp<ep) {
		x = *sp;
		*sp++ = *--ep;
		*ep = x;
	}
	sp=ap;
	time(&timbuf);
	L=localtime(&timbuf);
	secs = gp(-1);
	if(*sp!='.') {
		mins=secs;
		secs=0;
	} else {sp++;
		mins = gp(-1);
	}
	hour = gp(-1);
	day = gp(L->tm_mday);
	month = gp(L->tm_mon+1);
	year = gp(L->tm_year);
	if(*sp)
		return(1);
	if( month<1 || month>12 ||
	    day<1 || day>31 ||
	    mins<0 || mins>59 ||
	    secs<0 || secs>59)
		return(1);
	if (hour==24) {
		hour=0; day++;
	}
	if (hour<0 || hour>23)
		return(1);
	timbuf = 0;
	year += 1900;
	for(i=1970; i<year; i++)
		timbuf += dysize(i);
	/* Leap year */
	if (dysize(year)==366 && month >= 3)
		timbuf++;
	while(--month)
		timbuf += dmsize[month-1];
	timbuf += day-1;
	timbuf = 24*timbuf + hour;
	timbuf = 60*timbuf + mins;
	timbuf = 60*timbuf + secs;
	return(0);

}

gp(dfault)
{
	register int c, d;

	if(*sp==0)
		return(dfault);
	c = (*sp++)-'0';
	d = (*sp ? (*sp++)-'0' : 0);
	if(c<0 || c>9 || d<0 || d>9)
		return(-1);
	return(c+10*d);
}
