xref: /plan9-contrib/sys/src/9/boot/settime.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include "../boot/boot.h"
6 
7 static long lusertime(char*);
8 
9 char *timeserver = "#s/boot";
10 
11 void
12 settime(int islocal)
13 {
14 	int n, f;
15 	int timeset;
16 	Dir dir;
17 	char dirbuf[DIRLEN];
18 
19 	print("time...");
20 	timeset = 0;
21 	if(islocal){
22 		/*
23 		 *  set the time from the real time clock
24 		 */
25 		f = open("#r/rtc", ORDWR);
26 		if(f >= 0){
27 			if((n = read(f, dirbuf, sizeof(dirbuf)-1)) > 0){
28 				dirbuf[n] = 0;
29 				timeset = 1;
30 			}
31 			close(f);
32 		}else do{
33 			strcpy(dirbuf, "yymmddhhmm[ss]");
34 			outin(cpuflag, "\ndate/time ", dirbuf, sizeof(dirbuf));
35 		}while((timeset=lusertime(dirbuf)) <= 0);
36 	}
37 	if(timeset == 0){
38 		/*
39 		 *  set the time from the access time of the root
40 		 */
41 		f = open(timeserver, ORDWR);
42 		if(f < 0)
43 			return;
44 		if(mount(f, "/n/boot", MREPL, "") < 0){
45 warning("settime mount");
46 			close(f);
47 			return;
48 		}
49 		close(f);
50 		if(stat("/n/boot", dirbuf) < 0)
51 			fatal("stat");
52 		convM2D(dirbuf, &dir);
53 		sprint(dirbuf, "%ld", dir.atime);
54 		unmount(0, "/n/boot");
55 		/*
56 		 *  set real time clock if there is one
57 		 */
58 		f = open("#r/rtc", ORDWR);
59 		if(f > 0){
60 			write(f, dirbuf, strlen(dirbuf));
61 			close(f);
62 		}
63 	}
64 
65 	f = open("#c/time", OWRITE);
66 	if(write(f, dirbuf, strlen(dirbuf)) < 0)
67 		warning("can't set #c/time");
68 	close(f);
69 }
70 
71 #define SEC2MIN 60L
72 #define SEC2HOUR (60L*SEC2MIN)
73 #define SEC2DAY (24L*SEC2HOUR)
74 
75 int
76 g2(char **pp)
77 {
78 	int v;
79 
80 	v = 10*((*pp)[0]-'0') + (*pp)[1]-'0';
81 	*pp += 2;
82 	return v;
83 }
84 
85 /*
86  *  days per month plus days/year
87  */
88 static	int	dmsize[] =
89 {
90 	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
91 };
92 static	int	ldmsize[] =
93 {
94 	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
95 };
96 
97 /*
98  *  return the days/month for the given year
99  */
100 static int *
101 yrsize(int yr)
102 {
103 	if((yr % 4) == 0)
104 		return ldmsize;
105 	else
106 		return dmsize;
107 }
108 
109 /*
110  *  compute seconds since Jan 1 1970
111  */
112 static long
113 lusertime(char *argbuf)
114 {
115 	char *buf;
116 	ulong secs;
117 	int i, y, m;
118 	int *d2m;
119 
120 	buf = argbuf;
121 	i = strlen(buf);
122 	if(i != 10 && i != 12)
123 		return -1;
124 	secs = 0;
125 	y = g2(&buf);
126 	m = g2(&buf);
127 	if(y < 70)
128 		y += 2000;
129 	else
130 		y += 1900;
131 
132 	/*
133 	 *  seconds per year
134 	 */
135 	for(i = 1970; i < y; i++){
136 		d2m = yrsize(i);
137 		secs += d2m[0] * SEC2DAY;
138 	}
139 
140 	/*
141 	 *  seconds per month
142 	 */
143 	d2m = yrsize(y);
144 	for(i = 1; i < m; i++)
145 		secs += d2m[i] * SEC2DAY;
146 
147 	secs += (g2(&buf)-1) * SEC2DAY;
148 	secs += g2(&buf) * SEC2HOUR;
149 	secs += g2(&buf) * SEC2MIN;
150 	if(*buf)
151 		secs += g2(&buf);
152 
153 	sprint(argbuf, "%ld", secs);
154 	return secs;
155 }
156