New Clock program for XENIX
tsui at silver.bacs.indiana.edu
tsui at silver.bacs.indiana.edu
Tue Aug 9 07:52:00 AEST 1988
/* Written 9:04 am Jul 31, 1988 by sandy at turnkey in silver:alt.sources */
/* ---------- "New Clock program for XENIX" ---------- */
Since I sent through the net, nbs_time, a NEW and MUCH improved version of
the program has been uploaded to my bbs by the author, Warren H. Tucker.
Not only did he improve the main program but he also included a few handy
additional programs as enhancements. Below, you will find all of the source
code, in SHAR format, as sent to me.
Sanford ( Sandy ) Zelkovitz
XBBS 714-898-8634
------------------------------ Cut / Snip / Ax Here ---------------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./CMOSstime.c`
then
echo "writing ./CMOSstime.c"
cat > ./CMOSstime.c << '\Rogue\Monster\'
/* CHK=0xC608 */
/*+-------------------------------------------------------------------------
CMOSstime.c -- read cmos clock then stime()
Defined functions:
date_to_epochsecs(year,month,day,hour,min,sec)
days_since_epoch(year,month,day)
leap_year(yr)
main(argc,argv,envp)
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
--------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-18:59-wht-release */
/*:07-22-1988-19:34-wht-creation */
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <time.h>
#include "dev_cmos.h"
int leap_year(int );
int days_since_epoch(int ,int ,int );
long date_to_epochsecs(int ,int ,int ,int ,int ,int );
char *ctime(long *);
int stime(long *);
long time(long *);
char *cmos = "/dev/cmos";
/*+-------------------------------------------------------------------------
leap_year(yr) -- returns 1 if leap year, 0 otherwise
--------------------------------------------------------------------------*/
int
leap_year(yr)
int yr;
{
return (yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0);
} /* end of leap_year */
/*+-------------------------------------------------------------------------
days_since_epoch(year,month,day)
Return the number of days between Jan 1, 1970 and year,month,day
year is full year (e.g., 1988)
month is 0-11
day is 0-30 (must be legal day in month)
--------------------------------------------------------------------------*/
int
days_since_epoch(year,month,day)
int year;
int month;
int day;
{
register int days = day + 1; /* adjust for day 0-n instead of 1-n */
register int m;
register int y;
register char *md = "\37\34\37\36\37\36\37\37\36\37\36\37";
for (y = 1970; y < year; ++y)
{
days += 365;
if (leap_year(y)) ++days;
}
for (m = 0; m < month; ++m)
days += md[m] + (m == 1 && leap_year(y));
return(days);
} /* end of days_since_epoch */
/*+-------------------------------------------------------------------------
date_to_epochsecs(year,month,day,hour,min,sec)
Convert arguments into long seconds since 1/1/1970
year is full year (e.g., 1988)
month is 0-11
day is 0-30 (must be legal day in month)
hour is 0-23, min and sec 0-59
--------------------------------------------------------------------------*/
long
date_to_epochsecs(year,month,day,hour,min,sec)
int year;
int month;
int day;
int hour;
int min;
int sec;
{
register int m1;
register int m2;
long t;
struct tm *tp;
struct tm *localtime();
t = (days_since_epoch(year,month,day) - 1) * 86400L
+ (hour * 3600L) + (min * 60L) + sec;
/* Now the hard part -- correct for the time zone */
tp = localtime(&t);
m1 = tp->tm_hour * 60 + tp->tm_min;
m2 = (hour * 60) + min;
t -= ((m1 - m2 + 720 + 1440) % 1440 - 720) * 60L;
return(t);
} /* end of date_to_epochsecs */
/*+-------------------------------------------------------------------------
main(argc,argv,envp)
--------------------------------------------------------------------------*/
main(argc,argv,envp)
int argc;
char **argv;
char **envp;
{
int year;
int month;
int day;
int hour;
int min;
int sec;
int fdcmos;
long now;
setbuf(stdout,NULL);
setbuf(stderr,NULL);
if((fdcmos = open(cmos,O_RDONLY)) < 0)
{
perror(cmos);
exit(1);
}
get_clock(fdcmos,&year,&month,&day,&hour,&min,&sec);
now = date_to_epochsecs(year,month,day,hour,min,sec);
if(stime(&now))
{
perror("stime");
exit(1);
}
time(&now);
fputs("System time after stime(): ",stdout);
fputs(ctime(&now), stdout);
exit(0);
} /* end of main */
\Rogue\Monster\
else
echo "will not over write ./CMOSstime.c"
fi
if `test ! -s ./NBSsetclk.c`
then
echo "writing ./NBSsetclk.c"
cat > ./NBSsetclk.c << '\Rogue\Monster\'
/* CHK=0x0BFA */
/*+-----------------------------------------------------------------------
SCO XENIX SYSTEM V.2 (Others too?)
NBSsetclk.c -- call NBS, get time, hangup quickly, set system time,
update cmos clock (/dev/cmos)
Defined functions:
create_lock_file(lock_file_name)
hangup(sig)
hayes_dial()
hayes_send_cmd(cmd)
lclose()
lgetc(char_rtnd)
lgetc_timeout(timeout_msec)
lgets_timeout(lrwt)
lkill_buf()
lock_tty()
lopen()
lputc(lchar)
lputs_paced(pace_msec,string)
lrdchk()
lset_baud_rate(ioctl_flag)
lset_parity(ioctl_flag)
main(argc,argv,envp)
make_lock_name(ttyname,lock_file_name)
other_lock_name(first_lock_name)
to_lower(ch)
to_upper(ch)
ulcmpb(str1,str2)
ulindex(str1,str2)
unlock_tty()
usage()
valid_baud_rate(baud)
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
Note: must be root to execute
Exit status codes for the program:
1-n signal values if program killed
200 illogical cmos device behavior (when reading clock)
249 stime() call failed
250 could not open communications line
251 /dev/cmos read&write access denied
252 user is not root
253 usage
254 couldn't get time from line (after 40 retries! BAD line conditions)
255 could not establish a connection
------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-19:03-wht-release */
/*:07-23-1988-13:11-wht-get good parsed time before hanging up w/max retries */
/*:07-23-1988-12:50-wht-do not use setclock ... messes up new system time */
/*:07-22-1988-20:17-wht-change output format */
/*:07-18-1988-22:07-wht-working! */
/*:07-18-1988-17:27-wht-creation */
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termio.h>
#include "dev_cmos.h"
#ifndef ushort
#define ushort unsigned short
#endif
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
void usage(void);
char to_upper(char );
char to_lower(char );
int ulcmpb(unsigned char *,unsigned char *);
int ulindex(char *,char *);
void hangup(int );
int make_lock_name(char *,char *);
int create_lock_file(char *);
char *other_lock_name(char *);
int lock_tty(void );
void unlock_tty(void );
int valid_baud_rate(unsigned int );
int lset_baud_rate(int );
void lset_parity(int );
void lgetc(char *);
int lrdchk(void );
void lputc(char );
void lputs_paced(int ,char *);
char *lgets_timeout(struct lrwt *);
int lgetc_timeout(unsigned long );
void lkill_buf(void );
int lopen(void );
void lclose(void );
int hayes_send_cmd(char *);
int hayes_dial(void );
ushort geteuid();
ushort getuid();
long nap(long);
long time(long *);
char *ctime(long *);
typedef struct lrwt /* param to lgets_timeout in eculine.c */
{
ulong to1; /* timeout for 1st character (granularity 20) */
ulong to2; /* timeout for each next char (granularity 20) */
int raw_flag; /* !=0, rtn full buffer, ==0, rtn filtered hayes result */
char *buffer; /* buffer to fill */
int bufsize; /* size of buffer */
int count; /* from proc, count rcvd */
} LRWT;
#define EPOCH 40587 /* UNIX starts JD 2440587, */
#define leap(y, m) ((y+m-1 - 70%m) / m) /* also known as 1/1/70 */
#define TONE '*'
/* #define TIME "\n%05ld %03d %02d%02d%02d UTC" */
#define TIME "%05ld %03d %02d%02d%02d UTC"
/* for better source line utilization, frequent use of 'fprintf' and 'stderr'
warrants the following */
#define pf printf
#define ff fprintf
#define se stderr
#define so stdout
/* lopen() and related routines error codes */
#define LOPEN_INVALID -1 /* for invalid tty name */
#define LOPEN_UNKPID -2 /* unknown pid using line */
#define LOPEN_LCKERR -3 /* lock file open error */
#define LOPEN_NODEV -4 /* device does not exist */
#define LOPEN_OPNFAIL -5 /* count not open line */
#define LOPEN_ALREADY -6 /* line already open */
extern char *revision; /* ecurev.c temp file from buildrev */
extern char *numeric_revision; /*ecunumrev.c */
char LLCKname[128]; /* lock file name */
char Ltelno[64]; /* telephone number for remote or null */
char Lline[64]; /* line name */
int Liofd; /* file descriptor for line */
int Lparity; /* 0==NONE, 'e' == even, 'o' == odd */
struct termio Llv; /* attributes for the line to remote */
uint Lbaud; /* baud rate */
ushort euid;
ushort uid;
char *cmos = "/dev/cmos";
/*+-------------------------------------------------------------------------
usage()
--------------------------------------------------------------------------*/
void
usage()
{
ff(se,"Usage: nbs_time [-][-e][-o][-n][-b#][-t#]\n");
ff(se,"Defaults 1200-N %s %s\n",Ltelno,Lline);
ff(se," - use defaults\n");
ff(se," -e even parity\n");
ff(se," -o odd parity\n");
ff(se," -n no parity\n");
ff(se," -b# baud rate\n");
ff(se," -t# telephone number\n");
ff(se," -l<name> line (/dev/tty??)\n");
exit(253);
} /* end of usage */
/*+-------------------------------------------------------------------------
to_upper() / to_lower()
one would think that these were relatively standard
types of thing, but MSC/Xenix specifies toupper() to convert to upper
case if not already and Unix says to adjust without testing,
so, two stupid little routines here
ASCII only -- no EBCDIC gradoo here please
--------------------------------------------------------------------------*/
char to_upper(ch)
register char ch;
{ return( ((ch >= 'a') && (ch <= 'z')) ? ch - 0x20 : ch);
} /* end of to_upper() */
char to_lower(ch)
register char ch;
{ return( ((ch >= 'A') && (ch <= 'Z')) ? ch + 0x20 : ch);
} /* end of to_lower() */
/*+----------------------------------------------------------------------------
ulcmpb(str1,str) -- Upper/Lower [case insensitive] Compare Bytes
Returns -1 if strings are equal, else failing character position
If the second strings terminates with a null and both strings have matched
character for character until that point, then -1 is returned.
NOTE: this is not a test for complete equality of two strings, but allows
discovery of a string as a substring in a larger containing string.
-----------------------------------------------------------------------------*/
int
ulcmpb(str1,str2)
register unsigned char *str1;
register unsigned char *str2;
{
register int istr;
for( istr=0 ; ; ++istr )
{
if(str2[istr] == '\0') /* if second string exhausts, match! */
return(-1);
if((str1[istr] == '\0' ) ||
( to_upper(str1[istr]) != to_upper(str2[istr]) ))
return(istr);
}
/*NOTREACHED*/
} /* end of ulcmpb */
/*+-------------------------------------------------------------------------
ulindex: Upper/Lower [case insensitive] Index functioni
Returns position of 'str2' in 'str1' if found
If 'str2' is null, then 0 is returned (null matches anything)
Returns -1 if not found
uses 'ulcmpb'
--------------------------------------------------------------------------*/
int ulindex(str1,str2)
register char *str1; /* the (target) string to search */
register char *str2; /* the (comparand) string to search for */
{
register int istr1 = 0; /* moving index into str1 */
register char *mstr = str1; /* moving string pointer */
if(str2[0] == '\0') /* null string matches anything */
return(0);
while(1)
{
if(*mstr == '\0') /* if we exhaust target string, flunk */
return(-1);
/* Can we find either case of first comparand char in target? */
if( to_upper(*mstr) == to_upper(str2[0]) )
{
/* we have a first char match... does rest of string match? */
if(ulcmpb(mstr,str2) == -1) /* if the rest matches, ... */
return(istr1); /* ... return match position */
}
/* we did not match this time... increment istr1, mstr and try again */
++istr1;
++mstr;
}
} /* end of ulindex */
/*+-----------------------------------------------------------------------
hangup(sig) -- terminate program (with comm line cleanup)
------------------------------------------------------------------------*/
void
hangup(sig)
int sig;
{
void lclose();
ff(se,"\n");
if(Liofd != -1)
lclose(); /* close line */
exit(sig);
} /* end of hangup */
/*+-------------------------------------------------------------------------
make_lock_name(ttyname,lock_file_name)
--------------------------------------------------------------------------*/
make_lock_name(ttyname,lock_file_name)
char *ttyname;
char *lock_file_name;
{
register int itmp;
register char *ttyptr;
if((itmp = ulindex(ttyname,"/dev/tty")) != 0)
return(LOPEN_INVALID);
itmp = ulindex(ttyname,"tty");
ttyptr = &ttyname[itmp];
strcpy(lock_file_name,"/usr/spool/uucp/LCK..");
strcat(lock_file_name,ttyptr);
return(0);
} /* end of make_lock_name */
/*+-----------------------------------------------------------------------
create_lock_file()
Returns 0 if lock file created,else error codes:
LOPEN_ if error
else pid of process currently busy on device
------------------------------------------------------------------------*/
create_lock_file(lock_file_name)
char *lock_file_name;
{
register int fd_lockf;
int pid;
int old_umask;
int erc = 0;
old_umask = umask(0);
if((fd_lockf = open(lock_file_name,O_CREAT | O_EXCL | O_RDWR,0666)) < 0)
{ /* file already exists */
if((fd_lockf = open(lock_file_name,O_RDWR,0666)) < 0)
{
erc = LOPEN_LCKERR;
goto RESTORE_UMASK;
}
else if(read(fd_lockf,(char *)&pid,sizeof(pid)))
{
if(kill(pid,0)) /* is owner pid already dead? */
{
if(errno == ESRCH) /* this error sez so */
{
pid = getpid(); /* so we will use it */
lseek(fd_lockf,0L,0);
write(fd_lockf,(char *)&pid,sizeof(pid));
close(fd_lockf);
erc = 0;
goto RESTORE_UMASK;
}
}
/* owner pid still active with lock */
close(fd_lockf);
erc = pid; /* port is busy */
goto RESTORE_UMASK;
}
else
{
close(fd_lockf);
erc = LOPEN_UNKPID;
goto RESTORE_UMASK;
}
}
pid = getpid();
write(fd_lockf,(char *)&pid,sizeof(pid));
close(fd_lockf);
chmod(lock_file_name,0666);
RESTORE_UMASK:
(void)umask(old_umask);
return(erc);
} /* end of create_lock_file */
/*+-------------------------------------------------------------------------
other_lock_name(first_lock_name)
--------------------------------------------------------------------------*/
char *
other_lock_name(first_lock_name)
char *first_lock_name;
{
register int itmp;
static char other_lock_name[64];
strcpy(other_lock_name,first_lock_name);
itmp = strlen(other_lock_name) - 1;
if(islower(other_lock_name[itmp]))
other_lock_name[itmp] = toupper(other_lock_name[itmp]);
else if(isupper(other_lock_name[itmp]))
other_lock_name[itmp] = tolower(other_lock_name[itmp]);
return(other_lock_name);
} /* end of other_lock_name */
/*+-------------------------------------------------------------------------
lock_tty()
--------------------------------------------------------------------------*/
lock_tty()
{
register int itmp;
struct stat ttystat;
if(itmp = make_lock_name(Lline,LLCKname))
return(itmp);
if(stat(Lline,&ttystat) < 0)
return(LOPEN_NODEV);
if(itmp = create_lock_file(LLCKname))
return(itmp);
if(itmp = create_lock_file(other_lock_name(LLCKname)))
{
unlink(LLCKname);
LLCKname[0] = 0;
return(itmp);
}
} /* end of lock_tty */
/*+-----------------------------------------------------------------------
void unlock_tty()
------------------------------------------------------------------------*/
void
unlock_tty()
{
if(LLCKname[0] == 0)
return;
unlink(LLCKname);
unlink(other_lock_name(LLCKname));
LLCKname[0] = 0;
} /* end of unlock_tty */
/*+-------------------------------------------------------------------------
valid_baud_rate(baud) -- returns (positive) baud rate selector
or -1 if invalid baud rate
--------------------------------------------------------------------------*/
valid_baud_rate(baud)
uint baud;
{
switch(baud)
{
case 110: return(B110);
case 300: return(B300);
case 600: return(B600);
case 1200: return(B1200);
case 2400: return(B2400);
case 4800: return(B4800);
case 9600: return(B9600);
case 19200: return(EXTA);
case 38400: return(EXTB);
default: return(-1);
}
} /* end of valid_baud_rate */
/*+-----------------------------------------------------------------------
lset_baud_rate(ioctl_flag)
If 'ioctl_flag' is set,then ioctl(Liofd,TCSETA,&Llv)
is executed after setting baud rate
------------------------------------------------------------------------*/
lset_baud_rate(ioctl_flag)
int ioctl_flag;
{
int baud_selector = valid_baud_rate(Lbaud);
if(baud_selector < 0)
{
ff(se,"invalid baud rate: %u\n",Lbaud);
ff(se,"valid rates: 110,300,600,1200,2400,4800,9600,19200\n");
return(1);
}
Llv.c_cflag &= ~CBAUD;
Llv.c_cflag |= baud_selector;
if(ioctl_flag)
ioctl(Liofd,(int)TCSETA,(char *)&Llv);
return(1);
} /* end of lset_baud_rate */
/*+-----------------------------------------------------------------------
lset_parity(ioctl_flag)
If 'ioctl_flag' is set,then ioctl(Liofd,TCSETA,&Llv)
is executed after setting parity
------------------------------------------------------------------------*/
void
lset_parity(ioctl_flag)
int ioctl_flag;
{
Llv.c_cflag &= ~(CS8 | PARENB | PARODD);
switch(to_lower(Lparity))
{
case 'e':
Llv.c_cflag |= CS7 | PARENB;
Llv.c_iflag |= ISTRIP;
break;
case 'o':
Llv.c_cflag |= PARODD | CS7 | PARENB;
Llv.c_iflag |= ISTRIP;
break;
default:
ff(se,"invalid parity: %c ... defaulting to no parity\n");
case 0:
case 'n':
Llv.c_cflag |= CS8;
Llv.c_iflag &= ~(ISTRIP);
Lparity = 0;
break;
}
if(ioctl_flag)
ioctl(Liofd,(int)TCSETA,(char *)&Llv);
} /* end of lset_parity */
/*+-------------------------------------------------------------------------
lgetc(char_rtnd)
--------------------------------------------------------------------------*/
void
lgetc(char_rtnd)
char *char_rtnd;
{
READ_AGAIN:
errno = 0;
if(read(Liofd,char_rtnd,1) < 1)
{
if(errno == EINTR) /* if signal interrupted, ... */
goto READ_AGAIN;
hangup(254);
}
} /* end of lgetc */
/*+-------------------------------------------------------------------------
lrdchk() -- rdchk(Liofd)
--------------------------------------------------------------------------*/
int
lrdchk()
{
return(rdchk(Liofd));
} /* end of lrdchk */
/*+-----------------------------------------------------------------------
lputc(lchar) -- write lchar to comm line
------------------------------------------------------------------------*/
void
lputc(lchar)
char lchar;
{
while(write(Liofd,&lchar,1) != 1)
{
if(errno == EINTR)
continue;
hangup(255);
}
} /* end of lputc */
/*+-----------------------------------------------------------------------
lputs_paced(pace_msec,string) -- write string to comm line
with time between each character
------------------------------------------------------------------------*/
void
lputs_paced(pace_msec,string)
register int pace_msec;
register char *string;
{
register long msec = (pace_msec) ? (long)pace_msec : (long)20;
while(*string)
{
lputc(*string++);
nap(msec);
}
} /* end of lputs_paced */
/*+-------------------------------------------------------------------------
char *lgets_timeout(LRWT *)
typedef struct lrwt
{
ulong to1;
ulong to2;
int raw_flag;
char *buffer;
int bufsize;
int count;
} LRWT;
to1 and to2 are unsigned long values in milliseconds (not
currently supported well under BSD4); to1 is the time to wait
for the first character, to2 the time to wait for subsequent
characters.
if raw_flag 0, non-printables are stripped from beginning
and end of received characters (i.e., modem
response reads); NULs discarded, parity stripped
if raw_flag 1, full raw read buffer returned
if raw_flag 2, full buffer, NULs discarded, parity stripped
buffer is address to read chars into
bufsize is buffer max size (allowing room for terminating null)
which should be at least 2 if raw_size includes 0x80 bit,
else at least 12 characters if 0x80 omitted.
count is a int which, at return, receives the actual count read
--------------------------------------------------------------------------*/
char *
lgets_timeout(lrwt)
LRWT *lrwt;
{
register int actual_count = 0;
register char *cptr = lrwt->buffer;
int max_count = lrwt->bufsize;
char *rtn_val;
int timeout_counter;
int qc1;
int qc2;
long quantum;
long ltmp;
/* minimum wait is 60 msec */
if(Lbaud < 300)
if(lrwt->to2 < 300L) lrwt->to2 = 300L;
if(Lbaud < 1200)
if(lrwt->to2 < 200L) lrwt->to2 = 200L;
else
if(lrwt->to2 < 60L) lrwt->to2 = 60L;
/* shortest interval */
ltmp = (lrwt->to1 < lrwt->to2) ? lrwt->to1 : lrwt->to2;
/* calculate wait quantum */
quantum = ltmp / 10L; /* try for ten ticks */
if(quantum < 20L)
quantum = 20L;
qc1 = lrwt->to1 / quantum;
if(!qc1) qc1 = 1L;
qc2 = lrwt->to2 / quantum;
if(!qc2) qc2 = 1L;
/* perform the lrtw function
input: qc1 is first nap count (for first charcters)
qc2 is 2nd nap count (for subsequent characters)
quantum is the nap period in milliseconds
cptr is char* to receive read string
max_count is max number of characters incl null
lrwt->raw_flag as described above
output: lrwt->count is actual count of return result
lrwt->buffer is return read buffer
*/
max_count--; /* leave room for null */
lrwt->raw_flag &= 0x0F; /* get rid of 0xF0 flags */
timeout_counter = qc1; /* first timeout */
*cptr = 0; /* init result string */
while(timeout_counter--)
{
nap(quantum);
while(lrdchk())
{
lgetc(cptr);
if(lrwt->raw_flag != 1)
{
*cptr &= 0x7F;
if(*cptr == 0)
continue;
}
*++cptr = 0;
actual_count++;
if(--max_count == 0)
goto READ_LINE_POST_PROCESS;
timeout_counter = qc2;
}
}
READ_LINE_POST_PROCESS:
if(lrwt->raw_flag)
{
lrwt->count = actual_count;
return(lrwt->buffer);
}
cptr = lrwt->buffer;
while(((*cptr >0) && (*cptr < 0x20)) || (*cptr >= 0x7F))
cptr++;
rtn_val = cptr;
actual_count = 0;
while(((*cptr &= 0x7F) >= 0x20) && (*cptr <= 0x7E))
{
cptr++;
actual_count++;
}
*cptr = 0;
strcpy(lrwt->buffer,rtn_val);
lrwt->count = actual_count;
return(lrwt->buffer);
} /* end of lgets_timeout */
/*+-------------------------------------------------------------------------
lgetc_timeout(timeout_msec)
reads one character from line unless timeout_msec passes with no receipt.
timeout_msec < 20 msec becomes 20 msec
return char (raw - parity bit preserved) if received, else -1 if timeout
--------------------------------------------------------------------------*/
int
lgetc_timeout(timeout_msec)
ulong timeout_msec;
{
LRWT lr;
char getc_buf[2]; /* room for one char + null */
lr.to1 = timeout_msec;
lr.to2 = timeout_msec;
lr.raw_flag = 1; /* full raw read */
lr.buffer = getc_buf;
lr.bufsize = sizeof(getc_buf);
lgets_timeout(&lr);
return( (lr.count == 1) ? (int)getc_buf[0] : -1 );
} /* end of lgetc_timeout */
/*+-------------------------------------------------------------------------
lkill_buf()
--------------------------------------------------------------------------*/
void
lkill_buf()
{
ioctl(Liofd,(int)TCFLSH,(char *)2); /* flush input and output */
} /* end of lkill_buf */
/*+----------------------------------------------------------------------
lopen()
returns negative LOPEN_ codes if failure else positive pid using line
else 0 if successful open
------------------------------------------------------------------------*/
int
lopen()
{
register int itmp;
if(Liofd >= 0)
return(LOPEN_ALREADY);
if(itmp = lock_tty()) /* get lock file */
return(itmp);
Liofd = open(Lline,O_RDWR,0777);
if(Liofd < 0)
return(LOPEN_OPNFAIL);
else
{
ioctl(Liofd,(int)TCGETA,(char *)&Llv);
Llv.c_iflag = (IGNPAR | IGNBRK | IXOFF );
Llv.c_cflag |= (CREAD | HUPCL);
Llv.c_lflag = 0;
Llv.c_cc[VMIN] = 1;
Llv.c_cc[VTIME] = 1;
lset_baud_rate(0); /* do not perform ioctl */
lset_parity(1); /* do perform ioctl */
}
return(0);
} /* end of lopen */
/*+-----------------------------------------------------------------------
lclose()
------------------------------------------------------------------------*/
void
lclose()
{
if(Liofd < 0)
return;
ioctl(Liofd,(int)TCGETA,(char *)&Llv); /* save initial state */
Llv.c_cflag |= HUPCL;
ioctl(Liofd,(int)TCSETA,(char *)&Llv);
close(Liofd);
Liofd = -1;
unlock_tty(); /* kill lock file */
} /* end of lclose */
/*+-------------------------------------------------------------------------
hayes_send_cmd(cmd)
0: success (cmd accepted)
-1: cannot talk to modem
--------------------------------------------------------------------------*/
hayes_send_cmd(cmd)
char *cmd;
{
register char *cptr;
int retry = 0;
cptr = cmd;
lkill_buf();
while(1)
{
lputc(0x07); /* something random */
if(lgetc_timeout(500L) < 0)
{
if(retry)
return(-1);
retry = 1;
lputs_paced(0,"ATQ0E1V1\r");
nap((long)1500);
lkill_buf();
continue;
}
break;
}
while(*cptr)
{
lputc(*cptr++);
if(lgetc_timeout(500L) < 0)
return(-1);
}
lputc('\r');
if(lgetc_timeout(500L) < 0)
return(-1);
return(0);
} /* end of hayes_send_cmd */
/*+-----------------------------------------------------------------------
hayes_dial()
returns 1 on success (CONNECT),
0 if failure to connect
-1 if cannot talk to modem
------------------------------------------------------------------------*/
int
hayes_dial()
{
register int itmp;
char s128[128];
int rtn_code = -1; /* assume fail, CONNECT will chg to zero */
int s7;
LRWT lr;
s7 = 30;
strcpy(s128,"ATV1E1S11=45DT" );
strcat(s128,Ltelno);
if(itmp = hayes_send_cmd(s128))
return(itmp);
/* some modems (ahem, the Hayes 2400) do not accurately honor S7 */
lr.to1 = s7 * 3 * 1000L;
lr.to2 = 100L;
lr.raw_flag = 0;
lr.buffer = s128;
lr.bufsize = sizeof(s128);
ff(se,"Dialing %s ... INT to abort ... ",Ltelno);
fflush(se);
lgets_timeout(&lr);
if(lr.count)
ff(se,"%s\n",s128);
if(strncmp(s128,"CONNECT",7) == 0)
return(1);
return(0);
} /* end of hayes_dial */
/*+-------------------------------------------------------------------------
main(argc,argv,envp)
main() program forks to create rcvr process; then main()
becomes the xmtr process
------------------------------------------------------------------------*/
main(argc,argv,envp)
int argc;
char **argv;
char **envp;
{
char *cptr;
int iargv;
int swchar;
int itmp;
LRWT lr;
char rd_buf[64];
long now;
long julian;
long time_at_connect;
int day_of_year;
int year;
int month;
int day;
int hour;
int min;
int sec;
int fdcmos;
int have_time = 0;
int max_tries;
struct tm *lt;
setbuf(stderr,NULL);
setbuf(stdout,NULL);
/* init line variables */
strcpy(Lline,"/dev/tty1a");
strcpy(Ltelno,"1(202)653-0351");
Liofd = -1;
Lbaud = 1200;
Lparity = 0;
if(argc < 2)
usage();
if((argc == 2) && (!strcmp(argv[1],"-")))
;
else
{
for(iargv = 1; iargv < argc; iargv++)
{
if(*argv[iargv] != '-')
continue;
switch(*(argv[iargv] + 1))
{
case 'e': Lparity = 'e'; break;
case 'o': Lparity = 'o'; break;
case 'n': Lparity = 0 ; break;
case 'b': Lbaud = atoi(argv[iargv] + 2); break;
case 't': strcpy(Ltelno,argv[iargv] + 2); break;
case 'l': strcpy(Lline,argv[iargv] + 2); break;
default: usage();
}
}
}
uid = getuid();
euid = geteuid();
if((euid == 0) || (uid == 0)) /* if root running or prog text ... */
nice(-40);
else
{
ff(se,"must be root\n");
exit(252);
}
if((fdcmos = open(cmos,O_RDWR,0)) < 0)
{
perror(cmos);
exit(251);
}
signal(SIGHUP,hangup);
signal(SIGQUIT,hangup);
signal(SIGINT,hangup);
signal(SIGTERM,hangup);
if(itmp = lopen())
{
switch(itmp)
{
case LOPEN_INVALID:
ff(se,"invalid line name\n"); break;
case LOPEN_UNKPID:
ff(se,"unknown pid is using line\n"); break;
case LOPEN_LCKERR:
ff(se,"lock file error\n"); break;
case LOPEN_NODEV:
ff(se,"line does not exist\n"); break;
case LOPEN_ALREADY:
ff(se,"line already open\n"); break;
case LOPEN_OPNFAIL:
ff(se,"line open error\n"); break;
default:
ff(se,"pid %d using line\n",itmp); break;
}
exit(250);
}
lr.to1 = 1100L;
lr.to2 = 100L;
lr.raw_flag = 0; /* full raw read */
lr.buffer = rd_buf;
lr.bufsize = sizeof(rd_buf);
/* spend money on long distance call ... only time freaks can understand */
if(!hayes_dial())
hangup(255);
time_at_connect = time((long *)0);
max_tries = 40; /* 40 sec max connect time (charged for 1 min anyway) */
while(!have_time)
{
for(itmp = 0; itmp < 30; itmp++) /* look for asterisk */
{
if(lgetc_timeout(500L) == TONE)
break;
}
lgets_timeout(&lr); /* get date/time string */
if(sscanf(lr.buffer,TIME,&julian,&day_of_year,&hour,&min,&sec) != 5)
{
ff(se,"garbled result: '%s' ",lr.buffer);
if(--max_tries)
{
puts("... retrying");
continue;
}
puts("... aborting");
break; /* too many retries ... BAAAAD line condx */
}
have_time = 1;
}
lclose();
/* no longer spending money */
fprintf(stdout,"Connect time %ld second(s)\n",
time((long *)0) - time_at_connect);
if(have_time)
{
now = (((julian - EPOCH) * 24 + hour) * 60 + min) * 60 + sec;
if(stime(&now) < 0)
{
perror("stime");
exit(249);
}
fputs("Time retrieved from standard: ",stdout);
fputs(ctime(&now), stdout);
time(&now);
lt = localtime(&now);
fputs("setting cmos clock ... ",stdout);
set_clock(fdcmos,lt->tm_year,lt->tm_mon,lt->tm_mday,
lt->tm_hour,lt->tm_min,lt->tm_sec);
fputs("result: ",stdout);
get_clock(fdcmos,&year,&month,&day,&hour,&min,&sec);
printf("%02d/%02d/%04d %02d:%02d:%02d\n",month,day,year,hour,min,sec);
exit(0);
}
else
{
puts("Did not get time ... sorry");
exit(254);
}
} /* end of main */
/* end of nbs_time.c */
\Rogue\Monster\
else
echo "will not over write ./NBSsetclk.c"
fi
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\Rogue\Monster\'
Abstract
--------------------------------------------------------------------
XENIX V supports the 286 cmos ram with two devices (/dev/cmos,
/dev/clock), programs /etc/setclock and /lib/cvtdate and a shell
script /etc/asktime.
However, there is no way to set the system time or the cmos clock
ACCURATELY using these tools since seconds are not part of the
paradigm of setclock or /dev/clock. One can, however, set the cmos
clock accurately by the direct manipulation of /dev/cmos. Then again,
by reading /dev/cmos, one can get the correct time and set the
system time with stime(S).
Overview of cmostime.tar.Z
--------------------------------------------------------------------
This collection of programs allow you to:
1) set the cmos clock and system time very accurately by calling
the Naval Observatory ((202)653-0351 in DC) using 'NBSsetclk'
2) set the system clock from the (somwhat drifty) cmos clock
by using 'CMOSstime'
3) display interesting things in the cmos ram by using 'cmos_disp'
The file is compressed to 12-bits (using compress16 thanks to
Sandy Zelkovitz's BBS at 1(714)898-8634). When tar is run on
the uncompressed file, a group of files consisting of the sources,
executables and Makefile is produced.
List of files:
CMOSstime CMOSstime.c Makefile NBSsetclk NBSsetclk.c README
at_cmos.h cmos_disp cmos_disp.c dev_cmos.c dev_cmos.h NBSsetclk
--------------------------------------------------------------------
'NBSsetclk' MUST be run by root. Why waste a long distance call
only to have stime() fail? Most user will use the default parameters
of this program by invoking it with 'NBSsetclk -'. Running the
program with no parameters gives you the options available.
NBSsetclk assumes a Hayes modem is connected to the line and
that command recognition is enabled. /dev/tty1a is used by default.
The program tries up to 40 times (40 seconds) to read the time,
making it likely that you will succeed. However, the program will
terminate before the minimum 1 minute connect charge has expired.
Exit status codes for the NBSsetclk:
1-n signal values if program killed
200 illogical cmos device behavior (when reading clock)
249 stime() call failed
250 could not open communications line
251 /dev/cmos read&write access denied
252 user is not root
253 usage
254 couldn't get time from line (after 40 retries! BAD line conditions)
255 couldn't establish a connection
CMOSstime
--------------------------------------------------------------------
'CMOSstime' must be run by root. Run it in your /etc/rc in place
of the rather klunky 'asktime'. It reads the cmos clock and sets
the system time to the second. The program returns exit status 0
if it succeeds, 1 for most failures (stime() failure or /dev/cmos
read access failure), or 200 for the rare cases where the cmos
device appears to be acting up.
cmos_disp
--------------------------------------------------------------------
This is an experimental program that displays information contained
in the cmos ram. It has some bugs in it (on my system, it reports
no floppy drives, when I in fact have one). The information used
to build the program came from the sketchy notes in the IBM AT
Technical Reference Manual. Look in header file 'at_cmos.h' and
source file 'cmos_disp.c' for notes I have made about empirical
"discoveries".
Acknowlegments
--------------------------------------------------------------------
The routines for converting mm/dd/yy hh:mm:ss to seconds since
the epoch were adapted from the 'tm_to_time.c' module in Emmet P.
Gray's conversion of arc to unix.
The concepts of parsing the Naval Observatory data stream came from
an anonymous author's nbs.c (which read the data stream from stdin).
The hayes modem handler came from my homebrew comm program I've
been hacking on the last couple of years.
And I'd like to say hello to Mom and everybody that's watching.
Enjoy.
NOT COPYRIGHTED BY or clutched to the chest of:
Warren H. Tucker
150 West Lake Drive
Mountain Park, GA. 30075
(404)587-5766
\Rogue\Monster\
else
echo "will not over write ./README"
fi
if `test ! -s ./at_cmos.h`
then
echo "writing ./at_cmos.h"
cat > ./at_cmos.h << '\Rogue\Monster\'
/* CHK=0x7AFA */
/*+-------------------------------------------------------------------------
at_cmos.h -- 286 cmos ram definitions
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
--------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-19:06-wht-release */
/*:07-23-1988-15:12-wht-break out from cmos_disp.c */
#ifndef uchar
#define uchar unsigned char
#endif
typedef struct at_cmos
{
uchar sec;
uchar sec_alarm;
uchar min;
uchar min_alarm;
uchar hour;
uchar hour_alarm;
uchar day; /* 0-6 */
uchar date; /* 1-31 */
uchar month;
uchar year;
uchar srA; /* status register A */
uchar srB; /* status register B */
uchar srC; /* status register C */
uchar srD; /* status register D */
uchar dsb; /* diagnostic status byte */
uchar ssb; /* shutdown status byte */
uchar ddtb; /* diskette drive type byte */
uchar rsvd11; /* byte at address 0x11 reserved */
uchar fdtb; /* fixed disk type byte */
uchar rsvd13; /* byte at address 0x13 reserved */
uchar equip; /* equipment byte */
/* base size of memory = (contents(byte 0x16) << 8) + contents(byte 0x15) */
uchar base_low; /* low base memory byte */
uchar base_high; /* hi base memory byte */
/* memory expansion size similar calculation (0x17 low order byte, 0x18 hi) */
uchar expand_low;
uchar expand_high;
/* reserved bytes */
uchar rsvd19_2D[ 0x2D - 0x19 + 1 ];
/* checksum (on bytes in addresses 0x10 - 0x20) */
uchar cksum_high; /* tech ref sez these bytes in other order */
uchar cksum_low;
/* > 1 mb expansion size (in cmos ram addresses 0x30-31) */
uchar exp2_low;
uchar exp2_high;
uchar century; /* date century byte */
uchar info_flag; /* see IF_ bits below */
uchar rsvd34_3F[ 0x3F - 0x34 + 1];
} AT_CMOS;
union cmos_union
{
uchar a[64];
AT_CMOS s;
};
/*+-----------------------------------------------------------------------
AT Real Time Clock Status Register bit assignments
------------------------------------------------------------------------*/
#define SRA_UIP 0x80 /* update in progress */
#define SRA_DV22 0x70 /* 3-bit time-base divider */
#define SRA_DVOUT 0x0F /* 4-bit time-base divider output freq */
#define SRB_SET 0x80 /* when 1, no tick advance (set mode) */
#define SRB_PIE 0x40 /* when 1, periodic interrupt */
#define SRB_AIE 0x20 /* when 1, alarm enabled */
#define SRB_UIE 0x10 /* enabled update-ended interrupt */
#define SRB_SQWE 0x08 /* square wave enabled */
#define SRB_DM 0x04 /* data mode 1==binary, 0==BCD */
#define SRB_24HR 0x02 /* 1==24 hour mode, 0==12 hour mode */
#define SRB_DSE 0x01 /* daylight savings time enabled */
#define SRC_IRQF 0x80
#define SRC_PF 0x40
#define SRC_AF 0x20
#define SRC_UF 0x10
/* remaining bits in status register C reserved */
#define SRD_VRB 0x80 /* valid ram (==0 when power has been lost)
* remaining bits in status register D reserved */
/*+-----------------------------------------------------------------------
Diagnostic Status Byte
------------------------------------------------------------------------*/
#define DSB_RTLOST 0x80 /* ==1 if real time clock chip lost power */
#define DSB_CSI 0x40 /* checksum status indicator == 1 if bad */
#define DSB_ICI 0x20 /* invalid configuration information (if ==1) */
#define DSB_MSM 0x10 /* memory size miscompare (==1 if different) */
#define DSB_HDBAD 0x08 /* fixed disk bad if == 1 */
#define DSB_TSI 0x04 /* time status indicator (==1 if time bad) */
#ifdef NEEDED /* not under XENIX! */
#define cmos_ctrl_dev 0x70 /* cmos address control port */
#define cmos_data_dev 0x71 /* cmos data i/o port */
#endif
\Rogue\Monster\
else
echo "will not over write ./at_cmos.h"
fi
if `test ! -s ./cmos_disp.c`
then
echo "writing ./cmos_disp.c"
cat > ./cmos_disp.c << '\Rogue\Monster\'
/* CHK=0xD818 */
/*+-------------------------------------------------------------------------
cmos_disp.c -- interprets /dev/cmos 286 CMOS ram
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
--------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-19:05-wht-release */
/*:07-23-1988-14:17-wht-BIG face life on old program */
#include <stdio.h>
#include <fcntl.h>
#include "at_cmos.h"
#include "dev_cmos.h"
union cmos_union cmos;
char *day_of_week[] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
char *cmosname = "/dev/cmos";
main(argc,argv)
int argc;
char **argv;
{
register int icmos;
register int itmp;
char *format;
int fdcmos;
int clock_bcd_mode; /* true if clock in bcd mode */
unsigned short calc_cksum; /* calculated checksum */
unsigned short cmos_cksum; /* checksum in cmos */
if((fdcmos = open(cmosname,O_RDONLY)) < 0)
{
perror(cmosname);
exit(1);
}
get_cmos(fdcmos,&cmos);
close(fdcmos);
for(icmos = 0; icmos < 64; icmos++)
{
if(icmos % 16 == 0)
printf("\n %02x: ",icmos);
printf("%02x ",cmos.a[icmos]);
if(icmos % 4 == 3)
printf(" ");
}
printf("\n\n");
clock_bcd_mode = (cmos.s.srB & SRB_DM) ? 0 : 1;
printf("Base memory: %6dk (%8lx bytes hex)\n",
itmp = cmos.s.base_high << 8 | cmos.s.base_low,
(long)itmp * (long)1024);
printf("Expansion memory: %6dk (%8lx bytes hex)\n",
itmp = cmos.s.expand_high << 8 | cmos.s.expand_low,
(long)itmp * (long)1024);
printf("Memory above 1MB: %6dk (%8lx bytes hex)\n",
itmp = cmos.s.exp2_high << 8 | cmos.s.exp2_low,
(long)itmp * (long)1024);
printf("\n");
printf("Diag status byte: %02x Shutdown status byte: %02x\n",
cmos.s.dsb,cmos.s.ssb);
if(cmos.s.dsb)
{
itmp = cmos.s.dsb;
printf(" Diagnostic Status Byte (DSB) says:\n");
if(itmp & 0x80)
printf(" Real-time clock has lost power.\n");
if(itmp & 0x40)
printf(" Bad configuration record checksum.\n");
if(itmp & 0x20)
printf(" Incorrect configuration information.\n");
if(itmp & 0x10)
printf(" Memory size miscompare.\n");
if(itmp & 0x08)
printf(" Fixed disk adapter failed init.\n");
if(itmp & 0x04)
printf(" Time is invalid.\n");
printf("\n");
}
printf("Clock: %d-hour mode, %s time, alarm %s, %s mode\n",
(cmos.s.srB & SRB_24HR) ? 24 : 12,
(cmos.s.srB & SRB_DSE) ? "daylight" : "standard",
(cmos.s.srB & SRB_AIE) ? "enabled" : "disabled",
(clock_bcd_mode) ? "bcd" : "hex");
if(clock_bcd_mode)
format = "Date: %02x-%02x-%02x%02x ";
else
format = "Date: %02d-%02d-%02d%02d ";
printf(format,cmos.s.month,cmos.s.date,cmos.s.century,cmos.s.year);
if(clock_bcd_mode)
format = "Time: %02x:%02x:%02x Alarm: %02x:%02x:%02x\n";
else
format = "Time: %02d:%02d:%02d Alarm: %02d:%02d:%02d\n";
printf(format,cmos.s.hour,cmos.s.min,cmos.s.sec,
cmos.s.hour_alarm,cmos.s.min_alarm,cmos.s.sec_alarm);
printf("Number of diskette drives: %d Math coprocessor %s\n",
(int)(cmos.s.equip & 0xC0) >> 6,
(cmos.s.equip & 0x02) ? "present" : "not present"
);
printf("Primary display: ");
switch( itmp = (cmos.s.equip & 0x30) >> 4)
{
case 1:
format = "Color/Graphics 40 column\n";
break;
case 2:
format = "Color/Graphics 80 column\n";
break;
case 3:
format = "Monochrome display\n";
break;
default:
format = "unknown type: %d\n";
break;
}
printf(format,itmp);
/* tech ref doesn't say: empirically determined checksum algorithm (correct?) */
calc_cksum = 0;
for(itmp = 0x10; itmp < 0x21; itmp++)
calc_cksum += cmos.a[itmp];
calc_cksum++;
cmos_cksum = (cmos.s.cksum_high << 8) | cmos.s.cksum_low;
printf("Checksum: in ram: %04x calculated: %04x\n",cmos_cksum,calc_cksum);
exit(0); /* for now */
} /* end of main() */
\Rogue\Monster\
else
echo "will not over write ./cmos_disp.c"
fi
if `test ! -s ./dev_cmos.c`
then
echo "writing ./dev_cmos.c"
cat > ./dev_cmos.c << '\Rogue\Monster\'
/* CHK=0x2A78 */
/*+-------------------------------------------------------------------------
dev_cmos.c -- XENIX /dev/cmos routines
Defined functions:
bcdch_to_uchar(bcdch)
get_clock(fdcmos,year,month,day,hour,min,sec)
get_cmos(fdcmos,cmosbuf)
set_clock(fdcmos,year,month,day,hour,min,sec)
uchar_to_bcdch(uch)
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
--------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-19:06-wht-release */
/*:07-23-1988-13:53-wht-creation */
#include "at_cmos.h"
#include "dev_cmos.h"
long seek(int,long,int);
int read(int,char *,int);
union cmos_union cu;
#define SEEKPOS(elem) ((long)((char *)&cu.s.elem - (char *)&cu))
/*+-------------------------------------------------------------------------
bcdch_to_uchar(bcdch) -- convert two-nibble bcd to binary
--------------------------------------------------------------------------*/
unsigned char
bcdch_to_uchar(bcdch)
unsigned char bcdch;
{
return((((bcdch & 0xF0) >> 4) * 10) + (bcdch & 0x0F));
} /* end of bcdch_to_uchar */
/*+-------------------------------------------------------------------------
uchar_to_bcdch(uch) -- convert binary to two-nibble bcd
--------------------------------------------------------------------------*/
unsigned char
uchar_to_bcdch(uch)
unsigned char uch;
{
return(((uch / 10) << 4) | (uch % 10));
} /* end of uchar_to_bcdch */
/*+-------------------------------------------------------------------------
get_cmos(fdcmos,cmosbuf)
--------------------------------------------------------------------------*/
void
get_cmos(fdcmos,cmosbuf)
int fdcmos;
union cmos_union *cmosbuf;
{
unsigned int wait_counter;
unsigned char stat_reg_A;
/* check for clock update in progress and wait til done */
wait_counter = 32768;
while(1)
{
if(--wait_counter == 0)
{
puts("/dev/cmos: clock update in progress for too long");
exit(200);
}
lseek(fdcmos,SEEKPOS(srA),0); /* position to status register A */
read(fdcmos,&stat_reg_A,1);
if(!(stat_reg_A & SRA_UIP)) /* check update bit */
break; /* and break out of loop if not */
}
/* read the cmos ram */
lseek(fdcmos,0L,0);
read(fdcmos,(char *)cmosbuf,sizeof(AT_CMOS));
} /* end of get_cmos */
/*+-------------------------------------------------------------------------
get_clock(fdcmos,year,month,day,hour,min,sec) -- read /dev/cmos clock
fdcmos open fd to /dev/cmos
return values:
year is full year (e.g., 1988)
month is 0-11
day is 0-30
hour is 0-23
min is 0-59
--------------------------------------------------------------------------*/
void
get_clock(fdcmos,year,month,day,hour,min,sec)
int fdcmos;
int *year;
int *month;
int *day;
int *hour;
int *min;
int *sec;
{
char clkstr[12];
get_cmos(fdcmos,&cu);
*year = (int)bcdch_to_uchar(cu.s.year) + 1900;
*month = (int)bcdch_to_uchar(cu.s.month) - 1;
*day = (int)bcdch_to_uchar(cu.s.date) - 1;
*hour = (int)bcdch_to_uchar(cu.s.hour);
*min = (int)bcdch_to_uchar(cu.s.min);
*sec = (int)bcdch_to_uchar(cu.s.sec);
} /* end of get_clock */
/*+-------------------------------------------------------------------------
set_clock(fdcmos,year,month,day,hour,min,sec) -- write /dev/cmos clock
fdcmos open fd to /dev/cmos
other values: as returned by localtime()
--------------------------------------------------------------------------*/
void
set_clock(fdcmos,year,month,day,hour,min,sec)
int fdcmos;
int year;
int month;
int day;
int hour;
int min;
{
unsigned char stat_reg_B;
unsigned char wchar;
month++; /* month to 1-n */
year %= 100; /* think ahead (ha) */
/* set no tick advance */
lseek(fdcmos,SEEKPOS(srB),0);
read(fdcmos,&stat_reg_B,1); /* get current value */
stat_reg_B |= SRB_SET;
lseek(fdcmos,SEEKPOS(srB),0);
write(fdcmos,&stat_reg_B,1); /* plug new value */
/* set clock */
wchar = uchar_to_bcdch((uchar)year);
lseek(fdcmos,SEEKPOS(year),0);
write(fdcmos,&wchar,1);
wchar = uchar_to_bcdch((uchar)month);
lseek(fdcmos,SEEKPOS(month),0);
write(fdcmos,&wchar,1);
wchar = uchar_to_bcdch((uchar)day);
lseek(fdcmos,SEEKPOS(date),0);
write(fdcmos,&wchar,1);
wchar = uchar_to_bcdch((uchar)hour);
lseek(fdcmos,SEEKPOS(hour),0);
write(fdcmos,&wchar,1);
wchar = uchar_to_bcdch((uchar)min);
lseek(fdcmos,SEEKPOS(min),0);
write(fdcmos,&wchar,1);
wchar = uchar_to_bcdch((uchar)sec);
lseek(fdcmos,SEEKPOS(sec),0);
write(fdcmos,&wchar,1);
/* set no tick advance */
lseek(fdcmos,SEEKPOS(srB),0);
stat_reg_B &= ~SRB_SET;
write(fdcmos,&stat_reg_B,1); /* plug new value */
} /* end of set_clock */
\Rogue\Monster\
else
echo "will not over write ./dev_cmos.c"
fi
if `test ! -s ./dev_cmos.h`
then
echo "writing ./dev_cmos.h"
cat > ./dev_cmos.h << '\Rogue\Monster\'
/* CHK=0x843A */
/*+-------------------------------------------------------------------------
dev_clock.h -- prototypes for dev_clock.c functions
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
--------------------------------------------------------------------------*/
/*+:EDITS:*/
/*:07-23-1988-19:07-wht-release */
/*:07-23-1988-13:55-wht-creattion */
unsigned char bcdch_to_uchar(unsigned char );
unsigned char uchar_to_bcdch(unsigned char );
void get_cmos(int ,union cmos_union *);
void get_clock(int ,int *,int *,int *,int *,int *,int *);
void set_clock(int ,int ,int ,int ,int ,int ,int );
\Rogue\Monster\
else
echo "will not over write ./dev_cmos.h"
fi
if `test ! -s ./tags`
then
echo "writing ./tags"
cat > ./tags << '\Rogue\Monster\'
bcdch_to_uchar dev_cmos.c ?^bcdch_to_uchar(bcdch)$?
create_lock_file NBSsetclk.c ?^create_lock_file(lock_file_name)$?
date_to_epochsecs CMOSstime.c ?^date_to_epochsecs(year,month,day,hour,min,sec)$?
days_since_epoch CMOSstime.c ?^days_since_epoch(year,month,day)$?
get_clock dev_cmos.c ?^get_clock(fdcmos,year,month,day,hour,min,sec)$?
get_cmos dev_cmos.c ?^get_cmos(fdcmos,cmosbuf)$?
hangup NBSsetclk.c ?^hangup(sig)$?
hayes_dial NBSsetclk.c ?^hayes_dial()$?
hayes_send_cmd NBSsetclk.c ?^hayes_send_cmd(cmd)$?
lclose NBSsetclk.c ?^lclose()$?
leap_year CMOSstime.c ?^leap_year(yr)$?
lgetc NBSsetclk.c ?^lgetc(char_rtnd)$?
lgetc_timeout NBSsetclk.c ?^lgetc_timeout(timeout_msec)$?
lgets_timeout NBSsetclk.c ?^lgets_timeout(lrwt)$?
lkill_buf NBSsetclk.c ?^lkill_buf()$?
lock_tty NBSsetclk.c ?^lock_tty()$?
lopen NBSsetclk.c ?^lopen()$?
lputc NBSsetclk.c ?^lputc(lchar)$?
lputs_paced NBSsetclk.c ?^lputs_paced(pace_msec,string)$?
lrdchk NBSsetclk.c ?^lrdchk()$?
lset_baud_rate NBSsetclk.c ?^lset_baud_rate(ioctl_flag)$?
lset_parity NBSsetclk.c ?^lset_parity(ioctl_flag)$?
main CMOSstime.c ?^main(argc,argv,envp)$?
main NBSsetclk.c ?^main(argc,argv,envp)$?
main cmos_disp.c ?^main(argc,argv)$?
make_lock_name NBSsetclk.c ?^make_lock_name(ttyname,lock_file_name)$?
other_lock_name NBSsetclk.c ?^other_lock_name(first_lock_name)$?
set_clock dev_cmos.c ?^set_clock(fdcmos,year,month,day,hour,min,sec)$?
to_lower NBSsetclk.c ?^char to_lower(ch)$?
to_upper NBSsetclk.c ?^char to_upper(ch)$?
uchar_to_bcdch dev_cmos.c ?^uchar_to_bcdch(uch)$?
ulcmpb NBSsetclk.c ?^ulcmpb(str1,str2)$?
ulindex NBSsetclk.c ?^int ulindex(str1,str2)$?
unlock_tty NBSsetclk.c ?^unlock_tty()$?
usage NBSsetclk.c ?^usage()$?
valid_baud_rate NBSsetclk.c ?^valid_baud_rate(baud)$?
\Rogue\Monster\
else
echo "will not over write ./tags"
fi
echo "Finished archive 1 of 1"
exit
/* End of text from silver:alt.sources */
More information about the Alt.sources
mailing list