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