DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦b0b80ca86⟧ TextFile

    Length: 8344 (0x2098)
    Types: TextFile
    Notes: UNIX file
    Names: »date.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦2d53db1df⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »frankh/src/date.c« 

TextFile

/*
 * Print and set the date.
 * modifications for OKI chip support - 07/31/85 fah
 */

#include <stdio.h>
#include <ctype.h>
#include <types.h>
#include <time.h>
#include <timeb.h>
#include <utmp.h>
#include <stat.h>

#define TFCFLAG	0		/* Truly French GMT is UTC */

#define PBDDR		0x57
#define PCDD		0x0D
#define PCDATA		0x1F
#define PBDATA		0x1D
#define MCCR		0x03
#define	MICR		0x01
#define PBCSR		0x13
#define SIOCRC		0x0F

int	gmtflag;		/* Do things in Greenwich Mean Time */
int	okiflag;

struct	tm	*gtime();

struct	timeb	tb;
struct	utmp	utmps[2];
char	utmpf[] = "/usr/adm/wtmp";
struct	stat	sbuf;
time_t	timep[2];
char	btimf[] = "/etc/boottime";
#define	MIN	(60L)
#define	HOUR	(60L*60L)
#define	DAY	(60L*60L*24L)
#define	APR	3
#define	OCT	9

/*
 * Table of days per month.
 * This will be adjusted for leap years.
 */
char	dpm[] = {
	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

main(argc, argv)
char *argv[];
{
	register char *s;
	register struct tm *tmp;
	long ltime;
	char *tzone;

	okiflag = 0;
	if (argc>1 && *argv[1]=='-') {
		if (argv[1][2] != '\0')
			usage();
		if (argv[1][1] == 'u')
			gmtflag = 1;
		else
			if (argv[1][1] == 'c') {
				if (getuid() != 0) {
					printf("no permission\n");
					exit(1);
				}
				okiflag = 1;
				okiset();  /* set coherent time to oki time  */
			}
			else
				usage();
		argc--;
		argv++;
	}
	if (argc > 2)
		usage();
	if (argc > 1)
		sdate(argv[1]);
	ftime(&tb);
	ltime = tb.time;
	s = asctime(tmp = gtime(&ltime));
	s[24] = '\0';
	if (!gmtflag)
		tzone = tzname[tmp->tm_isdst];
	else
		tzone = TFCFLAG ? "UTC" : "GMT";
	printf("%s %s\n", s, tzone);
}

/*
 * Set the date/time based on
 * string `s'.
 */
sdate(s)
char *s;
{
	register char *sp;
	int status;
	int ufd;
	long ltime;
	struct tm *tmp;

	ftime(&tb);
	ltime = tb.time;
	utmps[0].ut_time = ltime;
	tmp = gtime(&ltime);
	for (sp = s; *sp != '\0'; sp++)
		;
	if ((sp -= 2) < s)
		usage();
	if (sp>s && sp[-1]=='.') {
		tmp->tm_sec = convert(sp, 60, s);
		sp--;
	} else {
		sp += 2;
		tmp->tm_sec = 0;
	}
	tmp->tm_min = convert(sp-=2, 60, s);
	tmp->tm_hour = convert(sp-=2, 24, s);
	if ((sp-=2) >= s) {
		tmp->tm_mday = convert(sp, 31+1, s);
		if ((sp-=2) >= s) {
			tmp->tm_mon = convert(sp, 12+1, s) - 1;
			if ((sp-=2) >= s)
				tmp->tm_year = convert(sp, 100, s);
		}
	}
	if (tmp->tm_mday > dpm[tmp->tm_mon])
		usage();

	ctset(tmp);		/* convert to ltime & set coherent time */

}


ctset(tmp)
struct tm *tmp;
{

	register int year;
	register int month;
	int status;
	int ufd;
	long ltime;

	/*
	 * Convert using the year, month, day, hour, minute,
	 * and second values in the `tm' structure.
	 * When all is completed, take care of timezone.
	 */
	ltime = tmp->tm_sec + MIN*tmp->tm_min + HOUR*tmp->tm_hour;
	ltime += (tmp->tm_mday-1) * DAY;
	year = 1900 + tmp->tm_year;
	/*
	 * Adjust length of February in leap years.
	 */
	if (!isleap(year))
		dpm[1] = 28;
	month = tmp->tm_mon;
	while (--month >= 0)
		ltime += dpm[month] * DAY;
	while (--year >= 1970)
		ltime += (long)DAY * (isleap(year) ? 366 : 365);
	if (!gmtflag) {
		ltime += timezone;
		tmp = localtime(&ltime);
		if (tmp->tm_isdst)
			ltime -= HOUR;
	}
	status = stime(&ltime);
	if (status < 0) {
		error("No permission\n");
		return;
	}

	if (gmtflag == 1 & okiflag == 0)
		okit(ltime);		/* if setting GMT time, set oki time */

	/* Correct the modtime of /etc/boottime */
	stat(btimf, &sbuf);
	timep[0] = ltime - utmps[0].ut_time + sbuf.st_mtime;
	timep[1] = timep[0];
	utime(btimf, timep);

	/* Note the change of time in /usr/adm/wtmp */
	utmps[1].ut_time = ltime;
	utmps[0].ut_line[0] = '|';
	utmps[1].ut_line[0] = '}';
	if ((ufd = open(utmpf, 1)) >= 0) {
		lseek(ufd, 0L, 2);
		write(ufd, utmps, sizeof (utmps));
		close(ufd);
	}
}

/*
 * Return 1 on leap years.
 */
isleap(yr)
register yr;
{
	if (yr%4000 == 0)
		return (0);
	if (yr%400==0 || (yr%100!=0 && yr%4==0))
		return (1);
	return (0);
}

/*
 * Convert a piece of the time.
 * The pointer cp should never fall before
 * beg and the two digits parsed should be
 * less than max.
 */
convert(cp, max, beg)
register char *cp;
char *beg;
{
	register val;

	if (cp<beg || !isdigit(cp[0]) || !isdigit(cp[1]))
		usage();
	val = (cp[0]-'0')*10 + cp[1]-'0';
	if (val >= max)
		usage();
	return (val);
}

/*
 * Return either local time or Greenwich
 * Mean `tm' in a `tm' structure.
 */
struct tm *
gtime(tp)
register time_t *tp;
{
	return (gmtflag ? gmtime(tp) : localtime(tp));
}

usage()
{
	error("Usage: date [-uc] [yymmddhhmm[.ss]]\n");
}

error(x)
{
	printf("%r", &x);
	exit(1);
}

/* 
 * set time in OKI chip
 */

okit(ltime)
long ltime;

{
	struct tm *tmm;
	register int fd, i;
	int j, status;
	int stm[15];

	tmm = gtime(&ltime);	/* this sets proper day of the week in	*/
				/* the tmm structure.			*/
	initio();		/* load driver for I/O	*/
	fd = open("/dev/port", 2);

	setup(fd);		/* setup 8036 for oki chip.	*/

	stm[1] = tmm->tm_sec / 10;
	stm[0] = tmm->tm_sec - 10 * stm[1];
	stm[3] = tmm->tm_min / 10;
	stm[2] = tmm->tm_min - 10 * stm[3];
	stm[5] = tmm->tm_hour / 10;
	stm[4] = tmm->tm_hour - 10 * stm[5];
	stm[6] = tmm->tm_wday;
	stm[8] = tmm->tm_mday / 10;
	stm[7] = tmm->tm_mday - 10 * stm[8];
	stm[10] = (tmm->tm_mon + 1) / 10;
	stm[9] = (tmm->tm_mon + 1) - 10 * stm[10];
	stm[12] = tmm->tm_year / 10;
	stm[11] = tmm->tm_year - 10 * stm[12];

	stm[5] = stm[5] | 0x8;		/* set to 24 hr mode	*/

	seloki(fd);			/* select OKI chip	*/

	for( i = 0; i < 13; ++i)	/* do writes to clock chip	*/
		okiw( i, stm[i], fd);

	okiw( 0x0D, 0, fd);	/* clear post-stage counters	*/

	desoki(fd);

	cloio();	/* unload I/O driver	*/
	printf("Backup clock set.  ");

}

/*
 * set Coherent time from OKI clock chip.
 */
okiset()
{
	struct	tm *tmp;
	register int fd;
	int ufd, j, status;
	int stm[15];
	long ltime;

	gmtflag = 1;	/* time in OKI part is GMT! always!	*/

	ftime(&tb);
	ltime = tb.time;
	utmps[0].ut_time = ltime;
	tmp = gtime(&ltime);

	initio();	/* load driver for I/O	*/

	fd = open("/dev/port", 2);

	setup(fd);		/* set up 8036		*/

	seloki(fd);	/* select oki chip	*/

	tmp->tm_sec = okir(0, fd) + okir(1, fd) * 10;
	tmp->tm_min = okir(2, fd) + okir(3, fd) * 10;
	tmp->tm_hour = okir(4, fd) + (okir(5, fd) & 0x3) * 10;
	tmp->tm_mday = okir(7, fd) + (okir(8, fd) & 0x3) * 10;
	tmp->tm_mon = (okir(9, fd) + okir(0xA, fd) * 10) - 1;
	tmp->tm_year = okir(0xB, fd) + okir(0xC, fd) * 10;
	tmp->tm_wday = okir(6, fd);

	okiw( 0x0D, 0, fd);	/* clear post-stage counters	*/

	desoki(fd);		/* deselect oki chip	*/

	cloio();	/* unload I/O driver	*/

	ctset(tmp);	/* set coherent time from tmp structure	*/

	printf("Internal Coherent clock set.\n");
	exit(0);

}

okir(reg, fd)
int fd;
unsigned int reg;
{
	unsigned int tmp;

	setreg(reg, fd);		/* set register address		*/

/*
 * make PB0-3 input lines
 */
	outb(fd, PBDDR, (inb(fd, PBDDR) | 0x0F));

	outb(fd, PBDATA, (inb(fd, PBDATA) | 0x10)); 	/* set READ high */
	tmp = inb(fd, PBDATA) & 0x0F;			/* read D0-D3    */
	outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x10));	/* set READ low  */
/*
 * make PB0-3 output lines
 */
	outb(fd, PBDDR, (inb(fd, PBDDR) & 0xF0));

	return(tmp);
}

okiw(reg, data, fd)
int fd;
unsigned int reg;
unsigned int data;
{

	setreg(reg, fd);	/* set register address in OKI chip	*/

	outb(fd, PBDATA, ((inb(fd, PBDATA) & 0xF0) | data)); /* set D0-D3  */
	outb(fd, PBDATA, (inb(fd, PBDATA) | 0x20));	/* toggle WRITE	   */
	outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x20));

}

/*
 * set a register address in OKI chip
 */
setreg(reg, fd)
int fd, reg;
{

	outb(fd, PBDATA, (inb(fd, PBDATA) & 0xF0) | reg); /* write reg addr. */

	outb(fd, PBDATA, (inb(fd, PBDATA) | 0x40));	/* toggle ADWRITE */
	outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x40));
}

setup(fd)
int fd;
{

/*
 * do some setup of 8036 for oki chip.
 */

	outb( fd, PCDATA, inb(fd, PCDATA) & 0x0F); /* enable 0-3 write */
	outb( fd, PCDD, 0x05);		/* set up CS line	*/
	outb( fd, PCDATA, (inb(fd, PCDATA) & 0x0F) | 0x02); /* set select = 1 */
	outb( fd, PBDATA, 0);
}

/*
 * select & stop counting in oki chip.
 */

seloki(fd)
int fd;
{
	outb( fd, PCDATA, inb(fd, PCDATA) & 0x0D); 	/* set select = 0 */
	outb( fd, PBDATA, inb(fd, PBDATA) | 0x80); 	/* set stop = 1 */
}

/*
 * de-select & start count in oki chip.
 */

desoki(fd)
int fd;
{
	outb( fd, PBDATA, inb(fd, PBDATA) & ~0x80);	/* set stop = 0 */
	outb( fd, PCDATA, (inb(fd, PCDATA) & 0x0f) | 0x02); /* sel = 1 */
}