home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- Purpose : Routines for setting KA9Q's time from the remote host.
- : Uses the protocol described in RFC 868.
- ***************************************************************************
- : Copyright Giles Todd 1992. All rights reserved.
- : The right of Giles Todd to be identified as the author
- : of this work has been asserted by him in accordance
- : with the Copyrights, Designs and Patents Act, 1988.
- : No restrictions on the use of this module with KA9Q.
- ***************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "Arc.h"
- #include "domain.h"
- #include "global.h"
- #include "mbuf.h"
- #include "misc.h"
- #include "cmdparse.h"
- #include "socket.h"
- #include "timer.h"
- #include "netuser.h"
- #include "udp.h"
-
- int done_set_time = 0; /* have we set the time since this open? */
-
- #define TIME_PORT 37
-
- extern int16 lport; /* local port placeholder */
- extern int32 wimp_ver;
-
- /***************************************************************************
- Static function declarations.
- ***************************************************************************/
-
- static int do_server (int argc, char **argv);
- static int do_maxcorrect (int argc, char **argv);
- static int do_mincorrect (int argc, char **argv);
- static int do_read (int argc, char **argv);
- static int do_set (int argc, char **argv);
-
- /***************************************************************************
- Static data.
- ***************************************************************************/
-
- static time_t correction = 0; /* difference in seconds */
- /* between remote and PC clock */
- static int32 server = 0L; /* time server address */
- static time_t max_correction = 0; /* !0 is max correction allowed */
- static time_t min_correction = 0; /* !0 is min correction allowed */
-
- static BOOL set_clock = FALSE;
-
- static struct timer net_time_t;
- static struct socket time_socket;
-
- static struct cmds time_cmds[] =
- {
- "maxcorrect", do_maxcorrect, 0, 0, NULLCHAR ,
- "mincorrect", do_mincorrect, 0, 0, NULLCHAR ,
- "read", do_read, 0, 0, NULLCHAR ,
- "server", do_server, 0, 0, NULLCHAR ,
- "set", do_set, 0, 0, NULLCHAR ,
- NULLCHAR ,
- };
-
- int dotime (int argc, char *argv[])
- {
- return(subcmd(time_cmds, argc, argv));
- }
-
- /* Display or set the timer server address. */
-
- static int do_server(int argc, char *argv[])
- {
- int32 n; /* temporary */
-
- if (argc < 2)
- {
- cwprintf(NULL, "%s\r\n", inet_ntoa(server));
- }
- else if (n = resolve(argv[1]), n == 0)
- {
- cwprintf(NULL, "Time - Bad host %s\r\n", argv[1]);
- return (1);
- }
- else
- {
- server = n;
- }
- return (0);
- }
-
- static void no_net_time(void *sk)
- {
- cwprintf(NULL, "Time - No response from %s\r\n", inet_ntoa(server));
- del_udp((struct socket *) sk);
- set_clock = FALSE;
- }
-
- time_t RiscTime(time_t *place)
- {
- BOOL carry = FALSE;
- char btime[] = "\x00\x00\x00\x00\x6A\x99\x6E\x33\x00";
- char rtime[8], ntime[8], tzname[10];
- int diff, loop, temp, tz;
-
- if (wimp_ver < 300)
- return(time(place));
-
- os_swi2r(0x43048, NULL, NULL, (int *) tzname, &tz);
- rtime[3] = 3;
- os_word(14, &rtime[3]);
- for (loop = 3; loop < 8; loop++)
- {
- temp = rtime[loop] - btime[loop] - carry;
- ntime[loop] = temp & 0xFF;
- carry = ((temp & 0x100) != 0);
- }
- diff = (*((int *) &ntime[4]));
- temp = ((diff / 100) * 256) + (((diff % 100) * 256) + ntime[3]) / 100 + tz / 100;
- if (place)
- *place = temp;
- return(temp);
- }
-
- static void time_rec(struct socket *lsock, int16 rcvcnt)
- {
- int loop;
- struct socket fsocket; /* socket address */
- struct mbuf *bp;
- time_t pctime; /* PC time */
- union
- {
- time_t time;
- char bytes[sizeof (time_t)];
- } result; /* data from remote */
-
- if (recv_udp(lsock, &fsocket, &bp) != 4)
- {
- cwprintf(NULL, "TIME: receive failed\r\n");
- stop_timer(&net_time_t);
- del_udp(lsock);
- done_set_time = FALSE;
- return;
- }
- /* Calculate the correction value. */
- loop = 0;
-
- while (pullone(&bp, &result.bytes[3 - loop]) == 1)
- loop++;
-
- result.time -= 2208988800U; /* adjust epoch */
-
- pctime = RiscTime(NULL);
- pctime = mktime(gmtime(&pctime));
- correction = result.time - pctime;
- cwprintf(NULL, "TIME: correction = %ld seconds\r\n", correction);
- cwprintf(NULL, "Net time (GMT): %s", asctime(localtime(&result.time)));
- cwprintf(NULL, "Local time (GMT): %s", asctime(localtime(&pctime)));
- stop_timer(&net_time_t);
- del_udp(lsock);
-
- if (set_clock)
- {
- char itime[8];
- int correction_abs;
-
- correction_abs = (int) labs(correction);
-
- if (max_correction && correction_abs > max_correction)
- {
- cwprintf(NULL, "TIME: required correction (%ld) greater than maximum (%ld)\r\n",
- correction, max_correction);
- correction = 0;
- return;
- }
-
- if (min_correction && correction_abs < min_correction)
- {
- cwprintf(NULL, "TIME: required correction (%ld) less than minimum (%ld)\r\n",
- correction, min_correction);
- correction = 0;
- return;
- }
- itime[0] = 3;
- os_word(14, itime);
- time_adj(itime, correction);
- os_swi1(0x43047 /* Territory_SetTime */, (int) itime);
-
- correction = 0; /* no need for a correction now */
- cwprintf(NULL, "TIME: Arc clock reset\r\n");
- }
- set_clock = FALSE;
- }
-
- /* Read the time from the remote and set the correction value. */
-
- static int do_read(int argc, char *argv[])
- {
- struct socket lsocket, fsocket; /* socket address */
-
- if (server == 0L)
- {
- cwprintf(NULL, "Time - Bad host %s\r\n", "0.0.0.0");
- return (1);
- }
- if (run_timer(&net_time_t))
- {
- cwprintf(NULL, "Time - Already asking\r\n");
- return (1);
- }
-
- /* Set up the connection. */
-
- fsocket.address = server;
- fsocket.port = TIME_PORT;
- lsocket.address = ip_addr; /* our ip address */
- lsocket.port = lport++; /* next unused port */
-
- open_udp(&lsocket, (void (*)())time_rec);
- send_udp(&lsocket, &fsocket, 0, 0, 0, 0, 0, 0);
-
- time_socket = lsocket;
- net_time_t.func = no_net_time; /* what to call on timeout */
- net_time_t.arg = (void *) &time_socket;
- set_timer(&net_time_t, 30000);
- start_timer(&net_time_t);
- return(0);
- }
-
-
- /* Set the Arc's clock from the time server. */
-
- static int do_set (int argc, char *argv[])
- {
- if (do_read (0, NULL) != 0)
- return (1);
-
- set_clock = TRUE;
-
- return (0);
- }
-
-
- static int do_maxcorrect(int argc, char *argv[])
- {
- if(argc < 2)
- {
- cwprintf(NULL, "TIME: maximum correction: %d\r\n", max_correction);
- return 0;
- }
- max_correction = atoi(argv[1]);
- return 0;
- }
-
- static int do_mincorrect(int argc, char *argv[])
- {
- if(argc < 2)
- {
- cwprintf(NULL, "TIME: minimum correction: %d\r\n", min_correction);
- return 0;
- }
- min_correction = atoi(argv[1]);
- return 0;
- }
-