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