1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate /*
9*7c478bd9Sstevel@tonic-gate  * lib/kadm/str_conv.c
10*7c478bd9Sstevel@tonic-gate  *
11*7c478bd9Sstevel@tonic-gate  * Copyright 1995, 1999 by the Massachusetts Institute of Technology.
12*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
15*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
16*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
17*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
18*7c478bd9Sstevel@tonic-gate  *
19*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
21*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
22*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
23*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
24*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
25*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
26*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
27*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
28*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
29*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
30*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
31*7c478bd9Sstevel@tonic-gate  * or implied warranty.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate  * str_conv.c - Convert between strings and Kerberos internal data.
37*7c478bd9Sstevel@tonic-gate  */
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /*
40*7c478bd9Sstevel@tonic-gate  * Table of contents:
41*7c478bd9Sstevel@tonic-gate  *
42*7c478bd9Sstevel@tonic-gate  * String decoding:
43*7c478bd9Sstevel@tonic-gate  * ----------------
44*7c478bd9Sstevel@tonic-gate  * krb5_string_to_salttype()	- Convert string to salttype (krb5_int32)
45*7c478bd9Sstevel@tonic-gate  * krb5_string_to_timestamp()	- Convert string to krb5_timestamp.
46*7c478bd9Sstevel@tonic-gate  * krb5_string_to_deltat()	- Convert string to krb5_deltat.
47*7c478bd9Sstevel@tonic-gate  *
48*7c478bd9Sstevel@tonic-gate  * String encoding:
49*7c478bd9Sstevel@tonic-gate  * ----------------
50*7c478bd9Sstevel@tonic-gate  * krb5_salttype_to_string()	- Convert salttype (krb5_int32) to string.
51*7c478bd9Sstevel@tonic-gate  * krb5_timestamp_to_string()	- Convert krb5_timestamp to string.
52*7c478bd9Sstevel@tonic-gate  * krb5_timestamp_to_sfstring()	- Convert krb5_timestamp to short filled string
53*7c478bd9Sstevel@tonic-gate  * krb5_deltat_to_string()	- Convert krb5_deltat to string.
54*7c478bd9Sstevel@tonic-gate  */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #include <k5-int.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate /* Salt type conversions */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * Local data structures.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate struct salttype_lookup_entry {
64*7c478bd9Sstevel@tonic-gate     krb5_int32		stt_enctype;		/* Salt type		*/
65*7c478bd9Sstevel@tonic-gate     const char *	stt_specifier;		/* How to recognize it	*/
66*7c478bd9Sstevel@tonic-gate     const char *	stt_output;		/* How to spit it out	*/
67*7c478bd9Sstevel@tonic-gate };
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*
70*7c478bd9Sstevel@tonic-gate  * Lookup tables.
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate static const struct salttype_lookup_entry salttype_table[] = {
74*7c478bd9Sstevel@tonic-gate /* salt type			input specifier	output string  */
75*7c478bd9Sstevel@tonic-gate /*-----------------------------	--------------- ---------------*/
76*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_NORMAL,	"normal",	"Version 5"	  },
77*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_V4,		"v4",		"Version 4"	  },
78*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_NOREALM,	"norealm",	"Version 5 - No Realm" },
79*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_ONLYREALM,	"onlyrealm",	"Version 5 - Realm Only" },
80*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_SPECIAL,	"special",	"Special" },
81*7c478bd9Sstevel@tonic-gate { KRB5_KDB_SALTTYPE_AFS3,	"afs3",		"AFS version 3"    }
82*7c478bd9Sstevel@tonic-gate };
83*7c478bd9Sstevel@tonic-gate static const int salttype_table_nents = sizeof(salttype_table)/
84*7c478bd9Sstevel@tonic-gate 					sizeof(salttype_table[0]);
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
87*7c478bd9Sstevel@tonic-gate krb5_string_to_salttype(string, salttypep)
88*7c478bd9Sstevel@tonic-gate     char	FAR * string;
89*7c478bd9Sstevel@tonic-gate     krb5_int32	FAR * salttypep;
90*7c478bd9Sstevel@tonic-gate {
91*7c478bd9Sstevel@tonic-gate     int i;
92*7c478bd9Sstevel@tonic-gate     int found;
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate     found = 0;
95*7c478bd9Sstevel@tonic-gate     for (i=0; i<salttype_table_nents; i++) {
96*7c478bd9Sstevel@tonic-gate 	if (!strcasecmp(string, salttype_table[i].stt_specifier)) {
97*7c478bd9Sstevel@tonic-gate 	    found = 1;
98*7c478bd9Sstevel@tonic-gate 	    *salttypep = salttype_table[i].stt_enctype;
99*7c478bd9Sstevel@tonic-gate 	    break;
100*7c478bd9Sstevel@tonic-gate 	}
101*7c478bd9Sstevel@tonic-gate     }
102*7c478bd9Sstevel@tonic-gate     return((found) ? 0 : EINVAL);
103*7c478bd9Sstevel@tonic-gate }
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * Internal datatype to string routines.
107*7c478bd9Sstevel@tonic-gate  *
108*7c478bd9Sstevel@tonic-gate  * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
109*7c478bd9Sstevel@tonic-gate  * if the supplied buffer/length will not contain the output.
110*7c478bd9Sstevel@tonic-gate  */
111*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
112*7c478bd9Sstevel@tonic-gate krb5_salttype_to_string(salttype, buffer, buflen)
113*7c478bd9Sstevel@tonic-gate     krb5_int32	salttype;
114*7c478bd9Sstevel@tonic-gate     char	FAR * buffer;
115*7c478bd9Sstevel@tonic-gate     size_t	buflen;
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate     int i;
118*7c478bd9Sstevel@tonic-gate     const char *out;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate     out = (char *) NULL;
121*7c478bd9Sstevel@tonic-gate     for (i=0; i<salttype_table_nents; i++) {
122*7c478bd9Sstevel@tonic-gate 	if (salttype ==  salttype_table[i].stt_enctype) {
123*7c478bd9Sstevel@tonic-gate 	    out = salttype_table[i].stt_output;
124*7c478bd9Sstevel@tonic-gate 	    break;
125*7c478bd9Sstevel@tonic-gate 	}
126*7c478bd9Sstevel@tonic-gate     }
127*7c478bd9Sstevel@tonic-gate     if (out) {
128*7c478bd9Sstevel@tonic-gate 	if (buflen > strlen(out))
129*7c478bd9Sstevel@tonic-gate 	    strcpy(buffer, out);
130*7c478bd9Sstevel@tonic-gate 	else
131*7c478bd9Sstevel@tonic-gate 	    out = (char *) NULL;
132*7c478bd9Sstevel@tonic-gate 	return((out) ? 0 : ENOMEM);
133*7c478bd9Sstevel@tonic-gate     }
134*7c478bd9Sstevel@tonic-gate     else
135*7c478bd9Sstevel@tonic-gate 	return(EINVAL);
136*7c478bd9Sstevel@tonic-gate }
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate /* (absolute) time conversions */
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate #ifndef HAVE_STRFTIME
141*7c478bd9Sstevel@tonic-gate #undef strftime
142*7c478bd9Sstevel@tonic-gate #define strftime my_strftime
143*7c478bd9Sstevel@tonic-gate static size_t strftime (char *, size_t, const char *, const struct tm *);
144*7c478bd9Sstevel@tonic-gate #endif
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate #ifndef HAVE_STRPTIME
147*7c478bd9Sstevel@tonic-gate #undef strptime
148*7c478bd9Sstevel@tonic-gate #define strptime my_strptime
149*7c478bd9Sstevel@tonic-gate static char *strptime (const char *, const char *, struct tm *);
150*7c478bd9Sstevel@tonic-gate #endif
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
153*7c478bd9Sstevel@tonic-gate krb5_string_to_timestamp(string, timestampp)
154*7c478bd9Sstevel@tonic-gate     char		FAR * string;
155*7c478bd9Sstevel@tonic-gate     krb5_timestamp	FAR * timestampp;
156*7c478bd9Sstevel@tonic-gate {
157*7c478bd9Sstevel@tonic-gate     int i,found;
158*7c478bd9Sstevel@tonic-gate     struct tm timebuf, nowbuf;
159*7c478bd9Sstevel@tonic-gate     time_t now;
160*7c478bd9Sstevel@tonic-gate     char *s;
161*7c478bd9Sstevel@tonic-gate     static const char * const atime_format_table[] = {
162*7c478bd9Sstevel@tonic-gate 	"%Y" "%m%d%H" "%M" "%S",/* yyyymmddhhmmss		*/
163*7c478bd9Sstevel@tonic-gate 	"%Y.%m.%d.%H.%M.%S",	/* yyyy.mm.dd.hh.mm.ss		*/
164*7c478bd9Sstevel@tonic-gate 	"%y%m%d%H" "%M" "%S",	/* yymmddhhmmss			*/
165*7c478bd9Sstevel@tonic-gate 	"%y.%m.%d.%H.%M.%S",	/* yy.mm.dd.hh.mm.ss		*/
166*7c478bd9Sstevel@tonic-gate 	"%y%m%d%H" "%M",	/* yymmddhhmm			*/
167*7c478bd9Sstevel@tonic-gate 	"%H" "%M" "%S",		/* hhmmss			*/
168*7c478bd9Sstevel@tonic-gate 	"%H" "%M",		/* hhmm				*/
169*7c478bd9Sstevel@tonic-gate 	"%T",			/* hh:mm:ss			*/
170*7c478bd9Sstevel@tonic-gate 	"%R",			/* hh:mm			*/
171*7c478bd9Sstevel@tonic-gate 	/* The following not really supported unless native strptime present */
172*7c478bd9Sstevel@tonic-gate 	"%x:%X",		/* locale-dependent short format */
173*7c478bd9Sstevel@tonic-gate 	"%d-%b-%Y:%T",		/* dd-month-yyyy:hh:mm:ss	*/
174*7c478bd9Sstevel@tonic-gate 	"%d-%b-%Y:%R"		/* dd-month-yyyy:hh:mm		*/
175*7c478bd9Sstevel@tonic-gate     };
176*7c478bd9Sstevel@tonic-gate     static const int atime_format_table_nents =
177*7c478bd9Sstevel@tonic-gate 	sizeof(atime_format_table)/sizeof(atime_format_table[0]);
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate     found = 0;
180*7c478bd9Sstevel@tonic-gate     for (i=0; i<atime_format_table_nents; i++) {
181*7c478bd9Sstevel@tonic-gate 	s = strptime(string, atime_format_table[i], &timebuf);
182*7c478bd9Sstevel@tonic-gate 	/* make sure the entire string was parsed */
183*7c478bd9Sstevel@tonic-gate 	if (s && (*s == '\0')) {
184*7c478bd9Sstevel@tonic-gate 		/* If only time and no date was provided, assume today */
185*7c478bd9Sstevel@tonic-gate 		if ((timebuf.tm_mday == 0) && (timebuf.tm_mon == 0) &&
186*7c478bd9Sstevel@tonic-gate 			(timebuf.tm_year == 0)) {
187*7c478bd9Sstevel@tonic-gate 			now = time((time_t *) NULL);
188*7c478bd9Sstevel@tonic-gate 			(void) memcpy(&nowbuf, localtime(&now), sizeof(timebuf));
189*7c478bd9Sstevel@tonic-gate 			timebuf.tm_mday = nowbuf.tm_mday;
190*7c478bd9Sstevel@tonic-gate 			timebuf.tm_mon = nowbuf.tm_mon;
191*7c478bd9Sstevel@tonic-gate 			timebuf.tm_year = nowbuf.tm_year;
192*7c478bd9Sstevel@tonic-gate 		}
193*7c478bd9Sstevel@tonic-gate 		found = 1;
194*7c478bd9Sstevel@tonic-gate 		break;
195*7c478bd9Sstevel@tonic-gate 	}
196*7c478bd9Sstevel@tonic-gate     }
197*7c478bd9Sstevel@tonic-gate     if (found) {
198*7c478bd9Sstevel@tonic-gate 	if ((*timestampp = (krb5_timestamp) mktime(&timebuf)) != -1) {
199*7c478bd9Sstevel@tonic-gate 		if (timebuf.tm_isdst == 1) {
200*7c478bd9Sstevel@tonic-gate 			*timestampp -= (timezone - altzone);
201*7c478bd9Sstevel@tonic-gate 		}
202*7c478bd9Sstevel@tonic-gate 		return (0);
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate     }
205*7c478bd9Sstevel@tonic-gate     return(EINVAL);
206*7c478bd9Sstevel@tonic-gate }
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
209*7c478bd9Sstevel@tonic-gate krb5_timestamp_to_string(timestamp, buffer, buflen)
210*7c478bd9Sstevel@tonic-gate     krb5_timestamp	timestamp;
211*7c478bd9Sstevel@tonic-gate     char		FAR * buffer;
212*7c478bd9Sstevel@tonic-gate     size_t		buflen;
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate     int ret;
215*7c478bd9Sstevel@tonic-gate     time_t timestamp2 = timestamp;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate     ret = strftime(buffer, buflen, "%c", localtime(&timestamp2));
218*7c478bd9Sstevel@tonic-gate     if (ret == 0 || ret == buflen)
219*7c478bd9Sstevel@tonic-gate 	return(ENOMEM);
220*7c478bd9Sstevel@tonic-gate     return(0);
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
224*7c478bd9Sstevel@tonic-gate krb5_timestamp_to_sfstring(timestamp, buffer, buflen, pad)
225*7c478bd9Sstevel@tonic-gate     krb5_timestamp	timestamp;
226*7c478bd9Sstevel@tonic-gate     char		FAR * buffer;
227*7c478bd9Sstevel@tonic-gate     size_t		buflen;
228*7c478bd9Sstevel@tonic-gate     char		FAR * pad;
229*7c478bd9Sstevel@tonic-gate {
230*7c478bd9Sstevel@tonic-gate     struct tm	*tmp;
231*7c478bd9Sstevel@tonic-gate     size_t i;
232*7c478bd9Sstevel@tonic-gate     size_t	ndone;
233*7c478bd9Sstevel@tonic-gate     time_t timestamp2 = timestamp;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate     static const char * const sftime_format_table[] = {
236*7c478bd9Sstevel@tonic-gate 	"%c",			/* Default locale-dependent date and time */
237*7c478bd9Sstevel@tonic-gate 	"%d %b %Y %T",		/* dd mon yyyy hh:mm:ss			*/
238*7c478bd9Sstevel@tonic-gate 	"%x %X",		/* locale-dependent short format	*/
239*7c478bd9Sstevel@tonic-gate 	"%d/%m/%Y %R"		/* dd/mm/yyyy hh:mm			*/
240*7c478bd9Sstevel@tonic-gate     };
241*7c478bd9Sstevel@tonic-gate     static const int sftime_format_table_nents =
242*7c478bd9Sstevel@tonic-gate 	sizeof(sftime_format_table)/sizeof(sftime_format_table[0]);
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate     tmp = localtime(&timestamp2);
245*7c478bd9Sstevel@tonic-gate     ndone = 0;
246*7c478bd9Sstevel@tonic-gate     for (i=0; i<sftime_format_table_nents; i++) {
247*7c478bd9Sstevel@tonic-gate 	if ((ndone = strftime(buffer, buflen, sftime_format_table[i], tmp)))
248*7c478bd9Sstevel@tonic-gate 	    break;
249*7c478bd9Sstevel@tonic-gate     }
250*7c478bd9Sstevel@tonic-gate     if (!ndone) {
251*7c478bd9Sstevel@tonic-gate #define sftime_default_len	2+1+2+1+4+1+2+1+2+1
252*7c478bd9Sstevel@tonic-gate 	if (buflen >= sftime_default_len) {
253*7c478bd9Sstevel@tonic-gate 	    sprintf(buffer, "%02d/%02d/%4d %02d:%02d",
254*7c478bd9Sstevel@tonic-gate 		    tmp->tm_mday, tmp->tm_mon+1, 1900+tmp->tm_year,
255*7c478bd9Sstevel@tonic-gate 		    tmp->tm_hour, tmp->tm_min);
256*7c478bd9Sstevel@tonic-gate 	    ndone = strlen(buffer);
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate     }
259*7c478bd9Sstevel@tonic-gate     if (ndone && pad) {
260*7c478bd9Sstevel@tonic-gate 	for (i=ndone; i<buflen-1; i++)
261*7c478bd9Sstevel@tonic-gate 	    buffer[i] = *pad;
262*7c478bd9Sstevel@tonic-gate 	buffer[buflen-1] = '\0';
263*7c478bd9Sstevel@tonic-gate     }
264*7c478bd9Sstevel@tonic-gate     return((ndone) ? 0 : ENOMEM);
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate #ifdef SUNW_INC_DEAD_CODE
268*7c478bd9Sstevel@tonic-gate /* relative time (delta-t) conversions */
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate /* string->deltat is in deltat.y */
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
273*7c478bd9Sstevel@tonic-gate krb5_deltat_to_string(deltat, buffer, buflen)
274*7c478bd9Sstevel@tonic-gate     krb5_deltat	deltat;
275*7c478bd9Sstevel@tonic-gate     char	FAR * buffer;
276*7c478bd9Sstevel@tonic-gate     size_t	buflen;
277*7c478bd9Sstevel@tonic-gate {
278*7c478bd9Sstevel@tonic-gate     int			days, hours, minutes, seconds;
279*7c478bd9Sstevel@tonic-gate     krb5_deltat		dt;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate     /*
282*7c478bd9Sstevel@tonic-gate      * We want something like ceil(log10(2**(nbits-1))) + 1.  That log
283*7c478bd9Sstevel@tonic-gate      * value is log10(2)*(nbits-1) or log10(2**8)*(nbits-1)/8.  So,
284*7c478bd9Sstevel@tonic-gate      * 2.4... is log10(256), rounded up.  Add one to handle leading
285*7c478bd9Sstevel@tonic-gate      * minus, and one more to force int cast to round the value up.
286*7c478bd9Sstevel@tonic-gate      * This doesn't include room for a trailing nul.
287*7c478bd9Sstevel@tonic-gate      *
288*7c478bd9Sstevel@tonic-gate      * This will break if bytes are more than 8 bits.
289*7c478bd9Sstevel@tonic-gate      */
290*7c478bd9Sstevel@tonic-gate #define MAX_CHARS_FOR_INT_TYPE(TYPE)	((int) (2 + 2.408241 * sizeof (TYPE)))
291*7c478bd9Sstevel@tonic-gate     char tmpbuf[MAX_CHARS_FOR_INT_TYPE(int) * 4 + 8];
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate     days = (int) (deltat / (24*3600L));
294*7c478bd9Sstevel@tonic-gate     dt = deltat % (24*3600L);
295*7c478bd9Sstevel@tonic-gate     hours = (int) (dt / 3600);
296*7c478bd9Sstevel@tonic-gate     dt %= 3600;
297*7c478bd9Sstevel@tonic-gate     minutes = (int) (dt / 60);
298*7c478bd9Sstevel@tonic-gate     seconds = (int) (dt % 60);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate     memset (tmpbuf, 0, sizeof (tmpbuf));
301*7c478bd9Sstevel@tonic-gate     if (days == 0)
302*7c478bd9Sstevel@tonic-gate 	sprintf(buffer, "%d:%02d:%02d", hours, minutes, seconds);
303*7c478bd9Sstevel@tonic-gate     else if (hours || minutes || seconds)
304*7c478bd9Sstevel@tonic-gate 	sprintf(buffer, "%d %s %02d:%02d:%02d", days,
305*7c478bd9Sstevel@tonic-gate 		(days > 1) ? "days" : "day",
306*7c478bd9Sstevel@tonic-gate 		hours, minutes, seconds);
307*7c478bd9Sstevel@tonic-gate     else
308*7c478bd9Sstevel@tonic-gate 	sprintf(buffer, "%d %s", days,
309*7c478bd9Sstevel@tonic-gate 		(days > 1) ? "days" : "day");
310*7c478bd9Sstevel@tonic-gate     if (tmpbuf[sizeof(tmpbuf)-1] != 0)
311*7c478bd9Sstevel@tonic-gate 	/* Something must be very wrong with my math above, or the
312*7c478bd9Sstevel@tonic-gate 	   assumptions going into it...  */
313*7c478bd9Sstevel@tonic-gate 	abort ();
314*7c478bd9Sstevel@tonic-gate     if (strlen (tmpbuf) > buflen)
315*7c478bd9Sstevel@tonic-gate 	return ENOMEM;
316*7c478bd9Sstevel@tonic-gate     else
317*7c478bd9Sstevel@tonic-gate 	strncpy (buffer, tmpbuf, buflen);
318*7c478bd9Sstevel@tonic-gate     return 0;
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate #endif /* SUNW_INC_DEAD_CODE */
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate #undef __P
323*7c478bd9Sstevel@tonic-gate #define __P(X) X
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate #if !defined (HAVE_STRFTIME) || !defined (HAVE_STRPTIME)
326*7c478bd9Sstevel@tonic-gate #undef _CurrentTimeLocale
327*7c478bd9Sstevel@tonic-gate #define _CurrentTimeLocale (&dummy_locale_info)
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate struct dummy_locale_info_t {
330*7c478bd9Sstevel@tonic-gate     char d_t_fmt[15];
331*7c478bd9Sstevel@tonic-gate     char t_fmt_ampm[12];
332*7c478bd9Sstevel@tonic-gate     char t_fmt[9];
333*7c478bd9Sstevel@tonic-gate     char d_fmt[9];
334*7c478bd9Sstevel@tonic-gate     char day[7][10];
335*7c478bd9Sstevel@tonic-gate     char abday[7][4];
336*7c478bd9Sstevel@tonic-gate     char mon[12][10];
337*7c478bd9Sstevel@tonic-gate     char abmon[12][4];
338*7c478bd9Sstevel@tonic-gate     char am_pm[2][3];
339*7c478bd9Sstevel@tonic-gate };
340*7c478bd9Sstevel@tonic-gate static const struct dummy_locale_info_t dummy_locale_info = {
341*7c478bd9Sstevel@tonic-gate     "%a %b %d %X %Y",		/* %c */
342*7c478bd9Sstevel@tonic-gate     "%I:%M:%S %p",		/* %r */
343*7c478bd9Sstevel@tonic-gate     "%H:%M:%S",			/* %X */
344*7c478bd9Sstevel@tonic-gate     "%m/%d/%y",			/* %x */
345*7c478bd9Sstevel@tonic-gate     { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
346*7c478bd9Sstevel@tonic-gate       "Saturday" },
347*7c478bd9Sstevel@tonic-gate     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
348*7c478bd9Sstevel@tonic-gate     { "January", "February", "March", "April", "May", "June",
349*7c478bd9Sstevel@tonic-gate       "July", "August", "September", "October", "November", "December" },
350*7c478bd9Sstevel@tonic-gate     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
351*7c478bd9Sstevel@tonic-gate       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
352*7c478bd9Sstevel@tonic-gate     { "AM", "PM" },
353*7c478bd9Sstevel@tonic-gate };
354*7c478bd9Sstevel@tonic-gate #undef  TM_YEAR_BASE
355*7c478bd9Sstevel@tonic-gate #define TM_YEAR_BASE 1900
356*7c478bd9Sstevel@tonic-gate #endif
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate #ifndef HAVE_STRFTIME
359*7c478bd9Sstevel@tonic-gate #undef  DAYSPERLYEAR
360*7c478bd9Sstevel@tonic-gate #define DAYSPERLYEAR 366
361*7c478bd9Sstevel@tonic-gate #undef  DAYSPERNYEAR
362*7c478bd9Sstevel@tonic-gate #define DAYSPERNYEAR 365
363*7c478bd9Sstevel@tonic-gate #undef  DAYSPERWEEK
364*7c478bd9Sstevel@tonic-gate #define DAYSPERWEEK 7
365*7c478bd9Sstevel@tonic-gate #undef  isleap
366*7c478bd9Sstevel@tonic-gate #define isleap(N)	((N % 4) == 0 && (N % 100 != 0 || N % 400 == 0))
367*7c478bd9Sstevel@tonic-gate #undef  tzname
368*7c478bd9Sstevel@tonic-gate #define tzname my_tzname
369*7c478bd9Sstevel@tonic-gate static const char *const tzname[2] = { 0, 0 };
370*7c478bd9Sstevel@tonic-gate #undef  tzset
371*7c478bd9Sstevel@tonic-gate #define tzset()
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate #include "strftime.c"
374*7c478bd9Sstevel@tonic-gate #endif
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate #ifndef HAVE_STRPTIME
377*7c478bd9Sstevel@tonic-gate #include "strptime.c"
378*7c478bd9Sstevel@tonic-gate #endif
379