N.B.S. clock update program
Sanford 'Sandy' Zelkovitz
sandy at turnkey.TCC.COM
Thu Jul 21 22:37:53 AEST 1988
The following is a program which was uploaded to my BBS which causes your
computer to call the National Bureau of Standards and retrieve the exact
time. It then calls /etc/setclock and updates your system clock. Please
note that this program, to the best of my knowledge, only runs under
SCO Xenix.
Sanford ( Sandy ) Zelkovitz
XBBS - 714-898-8634
P.S. The way that I compiled the code, under Xenix286, is as follows:
cc -Mm2e -O nbs_time.c -lx -o nbs_time
----------------------- cut here for nbs_time.c ----------------------------
/* CHK=0x0603 */
/*+-----------------------------------------------------------------------
SCO XENIX SYSTEM V.2 (Others too?)
nbs_time.c -- call NBS, get time, hangup quickly, set system time,
wait for top of minute, execute /etc/setclock to update cmos clock
Warren H. Tucker, 150 West Lake Drive, Mountain Park, GA 30075
(404)587-5766
Note: must be root to execute
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)
Sample execution:
% nbs -
nbs_time
Dialing 1(202)653-0351 ... INT to abort ... CONNECT 1200
'47361 201 020050 UTC'
Connect time 1 second(s)
Time retrieved from standard: Mon Jul 18 22:00:50 1988
Waiting for top of minute: Mon Jul 18 22:00:51 1988
Waiting for top of minute: Mon Jul 18 22:00:52 1988
Waiting for top of minute: Mon Jul 18 22:00:53 1988
Waiting for top of minute: Mon Jul 18 22:00:54 1988
Waiting for top of minute: Mon Jul 18 22:00:55 1988
Waiting for top of minute: Mon Jul 18 22:00:56 1988
Waiting for top of minute: Mon Jul 18 22:00:57 1988
Waiting for top of minute: Mon Jul 18 22:00:58 1988
/etc/setclock setting ... result: 0618220188
------------------------------------------------------------------------*/
/*+:EDITS:*/
/*: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>
#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
char *lgets_timeout(struct lrwt *);
char *other_lock_name(char *);
char to_lower(char );
char to_upper(char );
int create_lock_file(char *);
int hayes_dial(void);
int hayes_send_cmd(char *);
int lgetc_timeout(unsigned long );
int lock_tty(void);
int lopen(void);
int lrdchk(void);
int lset_baud_rate(int );
int main(int ,char * *,char * *);
int make_lock_name(char *,char *);
int ulcmpb(unsigned char *,unsigned char *);
int ulindex(char *,char *);
int valid_baud_rate(unsigned int );
void hangup(int );
void lclose(void);
void lgetc(char *);
void lkill_buf(void);
void lputc(char );
void lputs_paced(int ,char *);
void lset_parity(int );
void unlock_tty(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;
/*+-------------------------------------------------------------------------
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 */
/*+-------------------------------------------------------------------------
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 */
/*+-------------------------------------------------------------------------
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 connect_time;
int day_of_year;
int hour;
int min;
int sec;
struct tm *lt;
setbuf(stderr,NULL);
setbuf(stdout,NULL);
ff(se,"nbs_time\n");
/* 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);
}
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);
}
if(!hayes_dial())
hangup(1);
connect_time = time((long *)0);
for(itmp = 0; itmp < 30; itmp++)
{
if(lgetc_timeout(500L) == TONE)
break;
}
lr.to1 = 1100L;
lr.to2 = 100L;
lr.raw_flag = 0; /* full raw read */
lr.buffer = rd_buf;
lr.bufsize = sizeof(rd_buf);
lgets_timeout(&lr);
fputs("'",stdout);
fwrite(lr.buffer,1,lr.count,stdout);
fputs("'\n",stdout);
lclose();
fprintf(stdout,"Connect time %ld second(s)\n",
time((long *)0) - connect_time);
if(sscanf(lr.buffer,TIME, &julian, &day_of_year, &hour, &min, &sec) != 5)
{
ff(se,"garbled result: '%s'\n",lr.buffer);
exit(240);
}
else
{
now = (((julian - EPOCH) * 24 + hour) * 60 + min) * 60 + sec;
if(stime(&now) < 0)
perror("stime");
fputs("Time retrieved from standard: ",stdout);
fputs(ctime(&now), stdout);
lt = localtime(&now);
while(lt->tm_sec != 58)
{
nap(960L);
now = time((long *)0);
fputs("Waiting for top of minute: ",stdout);
fputs(ctime(&now), stdout);
lt = localtime(&now);
}
now += 60L; /* get top of next minute */
lt = localtime(&now);
/* mmddhhmmyy */
/* 0718213488 */
sprintf(rd_buf,"/etc/setclock %02d%02d%02d%02d%02d",
lt->tm_mon,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_year);
fputs("/etc/setclock setting ... ",stdout);
system(rd_buf);
fputs("result: ",stdout);
system("/etc/setclock");
}
exit(0);
} /* end of main */
/* end of nbs_time.c */
More information about the Alt.sources
mailing list