1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * date.c: support for the scadm date option (change/display service
29  * processor date)
30  */
31 
32 #include <libintl.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <locale.h>
36 #include <langinfo.h>
37 #include <time.h>  /* required by rsc.h */
38 
39 #include "librsc.h"
40 #include "adm.h"
41 
42 static void ADM_Get_Date();
43 static void ADM_Set_Date(int argc, char *argv[]);
44 static int ADM_Decode_Date(char *String, dp_set_date_time_t *Date);
45 static int ADM_twodigits(char *s);
46 static void usage();
47 
48 extern int cftime(char *, char *, const time_t *);
49 
50 void
ADM_Process_date(int argc,char * argv[])51 ADM_Process_date(int argc, char *argv[])
52 {
53 	static dp_set_date_time_t	DateTime;
54 	static char			date[40];
55 	time_t				currentTime;
56 	int				largc;
57 	char				*largv[3];
58 
59 	if ((argc != 2) && (argc != 3)) {
60 		usage();
61 		exit(-1);
62 	}
63 
64 	if (argc == 3) {
65 		if (strcasecmp(argv[2], "-s") != 0) {
66 			if (ADM_Decode_Date(argv[2], &DateTime) != 0) {
67 				usage();
68 				exit(-1);
69 			}
70 		}
71 	}
72 
73 	ADM_Start();
74 
75 	if (argc == 2) {
76 		ADM_Get_Date();
77 	} else if (argc == 3) {
78 		if (strcasecmp(argv[2], "-s") == 0) {
79 			currentTime = time(NULL);
80 			(void) cftime(date, "%m""%d""%H""%M""%Y", &currentTime);
81 			largc = 3;
82 			largv[0] = argv[0];
83 			largv[1] = argv[1];
84 			largv[2] = date;
85 			ADM_Set_Date(largc, largv);
86 		} else {
87 			ADM_Set_Date(argc, argv);
88 		}
89 	}
90 }
91 
92 
93 static void
ADM_Get_Date()94 ADM_Get_Date()
95 {
96 	rscp_msg_t		Message;
97 	struct timespec		Timeout;
98 	dp_get_date_time_r_t	*dateInfo;
99 	struct tm		*tp;
100 	char			buf[64];
101 
102 	Message.type = DP_GET_DATE_TIME;
103 	Message.len  = 0;
104 	Message.data = NULL;
105 
106 	ADM_Send(&Message);
107 
108 	Timeout.tv_nsec = 0;
109 	Timeout.tv_sec  = ADM_TIMEOUT;
110 	ADM_Recv(&Message, &Timeout,
111 	    DP_GET_DATE_TIME_R, sizeof (dp_get_date_time_r_t));
112 
113 	if (*(int *)Message.data != 0) {
114 		(void) fprintf(stderr, "\n%s\n\n",
115 		    gettext("scadm: could not read date from SC"));
116 		exit(-1);
117 	}
118 
119 	dateInfo = (dp_get_date_time_r_t *)Message.data;
120 
121 	/* Print the date */
122 	(void) setlocale(LC_ALL, "");
123 	tp = gmtime((time_t *)&dateInfo->current_datetime);
124 	(void) strftime(buf, 64, nl_langinfo(D_T_FMT), tp);
125 	(void) printf("%s\n", buf);
126 
127 	ADM_Free(&Message);
128 }
129 
130 
131 static void
ADM_Set_Date(int argc,char * argv[])132 ADM_Set_Date(int argc, char *argv[])
133 {
134 	static dp_set_date_time_t	specTime;
135 	rscp_msg_t			Message;
136 	struct timespec			Timeout;
137 
138 	if (argc < 3) {
139 		/* should have caught this earlier */
140 		(void) fprintf(stderr, "\n%s\n\n",
141 		    gettext("scadm: arguments error in set date"));
142 		exit(-1);
143 	}
144 
145 	if (ADM_Decode_Date(argv[2], &specTime) != 0) {
146 		/* should have caught this earlier */
147 		(void) fprintf(stderr, "\n%s\n\n",
148 		    gettext("scadm: INTERNAL ERROR in set date"));
149 		exit(-1);
150 	}
151 
152 	/* Correct month to be 0 - 11.  Why does firmware want this? */
153 	/* Correct year to be offset from 1900.  Why does firmware want this? */
154 	if (specTime.month != DP_SET_DATE_TIME_IGNORE_FIELD)
155 		specTime.month = specTime.month - 1;
156 	if (specTime.year != DP_SET_DATE_TIME_IGNORE_FIELD)
157 		specTime.year  = specTime.year  - 1900;
158 
159 	Message.type = DP_SET_DATE_TIME;
160 	Message.len  = sizeof (dp_set_date_time_t);
161 	Message.data = &specTime;
162 	ADM_Send(&Message);
163 
164 	Timeout.tv_nsec = 0;
165 	Timeout.tv_sec  = ADM_TIMEOUT;
166 	ADM_Recv(&Message, &Timeout,
167 	    DP_SET_DATE_TIME_R, sizeof (dp_set_date_time_r_t));
168 
169 	if (*(int *)Message.data != 0) {
170 		(void) fprintf(stderr, "\n%s\n\n",
171 		    gettext("scadm: could not set date on SC"));
172 		exit(-1);
173 	}
174 
175 	ADM_Free(&Message);
176 }
177 
178 
179 static int
ADM_twodigits(char * s)180 ADM_twodigits(char *s)
181 {
182 	int n;
183 
184 	n = ((s[0] - '0') * 10) + (s[1] - '0');
185 	return (n);
186 }
187 
188 
189 static int
ADM_Decode_Date(char * String,dp_set_date_time_t * Date)190 ADM_Decode_Date(char *String, dp_set_date_time_t *Date)
191 {
192 	int		localDate;
193 
194 
195 	if (strlen(String) == 4) {
196 
197 		/* HHMM */
198 		Date->month	= DP_SET_DATE_TIME_IGNORE_FIELD;
199 		Date->day	= DP_SET_DATE_TIME_IGNORE_FIELD;
200 		Date->hour	= ADM_twodigits(&String[0]);
201 		Date->minute	= ADM_twodigits(&String[2]);
202 		Date->second	= DP_SET_DATE_TIME_IGNORE_FIELD;
203 		Date->year	= DP_SET_DATE_TIME_IGNORE_FIELD;
204 		if (((int)Date->hour < 0) || (Date->hour > 23))
205 			return (-1);
206 		if (((int)Date->minute < 0) || (Date->minute > 59))
207 			return (-1);
208 
209 	} else if (strlen(String) == 7) {
210 
211 		/* HHMM.SS */
212 		Date->month	= DP_SET_DATE_TIME_IGNORE_FIELD;
213 		Date->day	= DP_SET_DATE_TIME_IGNORE_FIELD;
214 		Date->hour	= ADM_twodigits(&String[0]);
215 		Date->minute	= ADM_twodigits(&String[2]);
216 		Date->second	= ADM_twodigits(&String[5]);
217 		Date->year	= DP_SET_DATE_TIME_IGNORE_FIELD;
218 		if (((int)Date->hour < 0) || (Date->hour > 23))
219 			return (-1);
220 		if (((int)Date->minute < 0) || (Date->minute > 59))
221 			return (-1);
222 		if (((int)Date->second < 0) || (Date->second > 59))
223 			return (-1);
224 
225 	} else if (strlen(String) == 8) {
226 
227 		/* mmddHHMM */
228 		Date->month	= ADM_twodigits(&String[0]);
229 		Date->day	= ADM_twodigits(&String[2]);
230 		Date->hour	= ADM_twodigits(&String[4]);
231 		Date->minute	= ADM_twodigits(&String[6]);
232 		Date->second	= DP_SET_DATE_TIME_IGNORE_FIELD;
233 		Date->year	= DP_SET_DATE_TIME_IGNORE_FIELD;
234 		if ((Date->month < 1) || (Date->month > 12))
235 			return (-1);
236 		if ((Date->day < 1) || (Date->day > 31))
237 			return (-1);
238 		if (((int)Date->hour < 0) || (Date->hour > 23))
239 			return (-1);
240 		if (((int)Date->minute < 0) || (Date->minute > 59))
241 			return (-1);
242 
243 	} else if (strlen(String) == 11) {
244 
245 		/* mmddHHMM.SS */
246 		Date->month  = ADM_twodigits(&String[0]);
247 		Date->day    = ADM_twodigits(&String[2]);
248 		Date->hour   = ADM_twodigits(&String[4]);
249 		Date->minute = ADM_twodigits(&String[6]);
250 		Date->second = ADM_twodigits(&String[9]);
251 		Date->year   = DP_SET_DATE_TIME_IGNORE_FIELD;
252 		if ((Date->month < 1) || (Date->month > 12))
253 			return (-1);
254 		if ((Date->day < 1) || (Date->day > 31))
255 			return (-1);
256 		if (((int)Date->hour < 0) || (Date->hour > 23))
257 			return (-1);
258 		if (((int)Date->minute < 0) || (Date->minute > 59))
259 			return (-1);
260 		if (((int)Date->second < 0) || (Date->second > 59))
261 			return (-1);
262 
263 	} else if (strlen(String) == 10) {
264 
265 		/* mmddHHMMyy */
266 		Date->month	= ADM_twodigits(&String[0]);
267 		Date->day	= ADM_twodigits(&String[2]);
268 		Date->hour	= ADM_twodigits(&String[4]);
269 		Date->minute	= ADM_twodigits(&String[6]);
270 		Date->second	= DP_SET_DATE_TIME_IGNORE_FIELD;
271 		localDate	= ADM_twodigits(&String[8]);
272 		if (localDate > 70)
273 			Date->year = localDate + 1900;
274 		else
275 			Date->year = localDate + 2000;
276 
277 		if ((Date->month < 1) || (Date->month > 12))
278 			return (-1);
279 		if ((Date->day < 1) || (Date->day > 31))
280 			return (-1);
281 		if (((int)Date->hour < 0) || (Date->hour > 23))
282 			return (-1);
283 		if (((int)Date->minute < 0) || (Date->minute > 59))
284 			return (-1);
285 		if ((Date->year < 1970) || (Date->year > 2038))
286 			return (-1);
287 
288 	} else if (strlen(String) == 13) {
289 
290 		/* mmddHHMMyy.SS */
291 		Date->month	= ADM_twodigits(&String[0]);
292 		Date->day	= ADM_twodigits(&String[2]);
293 		Date->hour	= ADM_twodigits(&String[4]);
294 		Date->minute	= ADM_twodigits(&String[6]);
295 		Date->second	= ADM_twodigits(&String[11]);
296 		localDate	= ADM_twodigits(&String[8]);
297 		if (localDate > 70)
298 			Date->year = localDate + 1900;
299 		else
300 			Date->year = localDate + 2000;
301 
302 		if ((Date->month < 1) || (Date->month > 12))
303 			return (-1);
304 		if ((Date->day < 1) || (Date->day > 31))
305 			return (-1);
306 		if (((int)Date->hour < 0) || (Date->hour > 23))
307 			return (-1);
308 		if (((int)Date->minute < 0) || (Date->minute > 59))
309 			return (-1);
310 		if ((Date->year < 1970) || (Date->year > 2038))
311 			return (-1);
312 		if (((int)Date->second < 0) || (Date->second > 59))
313 			return (-1);
314 
315 	} else if (strlen(String) == 12) {
316 
317 		/* mmddHHMMccyy */
318 		Date->month	= ADM_twodigits(&String[0]);
319 		Date->day	= ADM_twodigits(&String[2]);
320 		Date->hour	= ADM_twodigits(&String[4]);
321 		Date->minute	= ADM_twodigits(&String[6]);
322 		Date->second	= DP_SET_DATE_TIME_IGNORE_FIELD;
323 		Date->year	= (ADM_twodigits(&String[8]) * 100) +
324 		    ADM_twodigits(&String[10]);
325 		if ((Date->month < 1) || (Date->month > 12))
326 			return (-1);
327 		if ((Date->day < 1) || (Date->day > 31))
328 			return (-1);
329 		if (((int)Date->hour < 0) || (Date->hour > 23))
330 			return (-1);
331 		if (((int)Date->minute < 0) || (Date->minute > 59))
332 			return (-1);
333 		if ((Date->year < 1970) || (Date->year > 2038))
334 			return (-1);
335 
336 	} else if (strlen(String) == 15) {
337 
338 		/* mmddHHMMccyy.SS */
339 		Date->month  = ADM_twodigits(&String[0]);
340 		Date->day    = ADM_twodigits(&String[2]);
341 		Date->hour   = ADM_twodigits(&String[4]);
342 		Date->minute = ADM_twodigits(&String[6]);
343 		Date->second = ADM_twodigits(&String[13]);
344 		Date->year   = (ADM_twodigits(&String[8]) * 100) +
345 		    ADM_twodigits(&String[10]);
346 		if ((Date->month < 1) || (Date->month > 12))
347 			return (-1);
348 		if ((Date->day < 1) || (Date->day > 31))
349 			return (-1);
350 		if (((int)Date->hour < 0) || (Date->hour > 23))
351 			return (-1);
352 		if (((int)Date->minute < 0) || (Date->minute > 59))
353 			return (-1);
354 		if ((Date->year < 1970) || (Date->year > 2038))
355 			return (-1);
356 		if (((int)Date->second < 0) || (Date->second > 59))
357 			return (-1);
358 
359 	} else {
360 		return (-1);
361 	}
362 
363 	return (0);
364 }
365 
366 
367 static void
usage()368 usage()
369 {
370 	(void) fprintf(stderr, "\n%s\n\n",
371 	    gettext("USAGE: scadm date [-s] "
372 	    "| [[mmdd]HHMM | mmddHHMM[cc]yy][.SS]\n"
373 	    "       1  <=  mm  <= 12\n"
374 	    "       1  <=  dd  <= 31\n"
375 	    "       1  <=  HH  <= 23\n"
376 	    "       0  <=  MM  <= 59\n"
377 	    "     1970 <= ccyy <= 2038\n"
378 	    "       0  <=  SS  <= 59"));
379 }
380