xref: /original-bsd/usr.sbin/timed/timed/correct.c (revision faf3fd95)
1 /*
2  * Copyright (c) 1985 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)correct.c	2.6 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 #include "globals.h"
13 #include <protocols/timed.h>
14 
15 #ifdef MEASURE
16 extern FILE *fp;
17 #endif
18 
19 /*
20  * `correct' sends to the slaves the corrections for their clocks
21  */
22 
23 correct(avdelta)
24 long avdelta;
25 {
26 	int i;
27 	int corr;
28 	struct timeval adjlocal;
29 	struct tsp msgs;
30 	struct timeval mstotvround();
31 	struct tsp *answer, *acksend();
32 
33 #ifdef MEASURE
34 	for(i=0; i<slvcount; i++) {
35 		if (hp[i].delta == HOSTDOWN)
36 			fprintf(fp, "%s\t", "down");
37 		else {
38 			fprintf(fp, "%d\t", hp[i].delta);
39 		}
40 	}
41 	fprintf(fp, "\n");
42 #endif
43 	corr = avdelta - hp[0].delta;
44 	adjlocal = mstotvround(&corr);
45 	adjclock(&adjlocal);
46 #ifdef MEASURE
47 	fprintf(fp, "%d\t", corr);
48 #endif
49 
50 	for(i=1; i<slvcount; i++) {
51 		if (hp[i].delta != HOSTDOWN)  {
52 			corr = avdelta - hp[i].delta;
53 			msgs.tsp_time = mstotvround(&corr);
54 			msgs.tsp_type = (u_char)TSP_ADJTIME;
55 			(void)strcpy(msgs.tsp_name, hostname);
56 			answer = acksend(&msgs, &hp[i].addr, hp[i].name,
57 			    TSP_ACK, (struct netinfo *)NULL);
58 			if (answer == NULL) {
59 				hp[i].delta = HOSTDOWN;
60 #ifdef MEASURE
61 				fprintf(fp, "%s\t", "down");
62 			} else {
63 				fprintf(fp, "%d\t", corr);
64 #endif
65 			}
66 		} else {
67 #ifdef MEASURE
68 			fprintf(fp, "%s\t", "down");
69 #endif
70 		}
71 	}
72 #ifdef MEASURE
73 	fprintf(fp, "\n");
74 #endif
75 }
76 
77 /*
78  * `mstotvround' rounds up the value of the argument to the
79  * nearest multiple of five, and converts it into a timeval
80  */
81 
82 struct timeval mstotvround(x)
83 int *x;
84 {
85 	int temp;
86 	struct timeval adj;
87 
88 	temp = *x % 5;
89 	if (temp >= 3)
90 		*x = *x-temp+5;
91 	else {
92 		if (temp <= -3)
93 			*x = *x - temp -5;
94 		else
95 			*x = *x-temp;
96 	}
97 	adj.tv_sec = *x/1000;
98 	adj.tv_usec = (*x-adj.tv_sec*1000)*1000;
99 	if (adj.tv_usec < 0) {
100 		adj.tv_usec += 1000000;
101 		adj.tv_sec--;
102 	}
103 	return(adj);
104 }
105 
106 adjclock(corr)
107 struct timeval *corr;
108 {
109 	struct timeval now;
110 
111 	if (timerisset(corr)) {
112 		if (corr->tv_sec < MAXADJ && corr->tv_sec > - MAXADJ) {
113 			(void)adjtime(corr, (struct timeval *)0);
114 		} else {
115 			syslog(LOG_WARNING,
116 			    "clock correction too large to adjust (%d sec)",
117 			    corr->tv_sec);
118 			(void) gettimeofday(&now, (struct timezone *)0);
119 			timevaladd(&now, corr);
120 			if (settimeofday(&now, (struct timezone *)0) < 0)
121 				syslog(LOG_ERR, "can't set time");
122 		}
123 	}
124 }
125 
126 timevaladd(tv1, tv2)
127 	register struct timeval *tv1, *tv2;
128 {
129 
130 	tv1->tv_sec += tv2->tv_sec;
131 	tv1->tv_usec += tv2->tv_usec;
132 	if (tv1->tv_usec >= 1000000) {
133 		tv1->tv_sec++;
134 		tv1->tv_usec -= 1000000;
135 	}
136 	if (tv1->tv_usec < 0) {
137 		tv1->tv_sec--;
138 		tv1->tv_usec += 1000000;
139 	}
140 }
141