NBS to system clock update

NBS to system clock update

Post by Sanford 'Sandy' Zelkovi » Mon, 02 Jul 1990 13:55:00



The following program was uploaded to my BBS system which permits your
system to call into the National Bureau of Standards and retrieve the exact
time. It then calls /etc/setclock and updates your system clock to the
exact time for your geographic location.

To the best of my knowledge, the code is only compatible with SCO Xenix.

The following is the cc command line that I used to compile the code.

             cc -Mm2e -O nbs_time.c -lx -o nbs_time

I have been using the code and it works perfectly!

Sanford ( Sandy ) Zelkovitz
XBBS - 714-898-8634

           ............!ihnp4!hermix!alphacm!sandy
           ............!uunet!ccicpg!turnkey!alphacm!sandy
           ............!trwrb!ucla-an!alphacm!sandy
           ............!ucbvax!ucivax!icnvax!alphacm!sandy

--------------------------- 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 */

------------------------------ end of nbs_time.c ----------------------------