]> git.sur5r.net Git - openldap/blob - libraries/liblutil/utils.c
Sync with HEAD
[openldap] / libraries / liblutil / utils.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #include <stdio.h>
19 #include <ac/stdlib.h>
20 #include <ac/string.h>
21 #include <ac/ctype.h>
22 #include <ac/unistd.h>
23 #include <ac/time.h>
24 #ifdef HAVE_IO_H
25 #include <io.h>
26 #endif
27 #ifdef HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30
31 #include <lutil.h>
32 #include <ldap_defaults.h>
33
34 #ifdef HAVE_EBCDIC
35 int _trans_argv = 1;
36 #endif
37
38 #ifdef _WIN32
39 /* Some Windows versions accept both forward and backslashes in
40  * directory paths, but we always use backslashes when generating
41  * and parsing...
42  */
43 void lutil_slashpath( char *path )
44 {
45         char *c, *p;
46
47         p = path;
48         while (( c=strchr( p, '/' ))) {
49                 *c++ = '\\';
50                 p = c;
51         }
52 }
53 #endif
54
55 char* lutil_progname( const char* name, int argc, char *argv[] )
56 {
57         char *progname;
58
59         if(argc == 0) {
60                 return (char *)name;
61         }
62
63 #ifdef HAVE_EBCDIC
64         if (_trans_argv) {
65                 int i;
66                 for (i=0; i<argc; i++) __etoa(argv[i]);
67                 _trans_argv = 0;
68         }
69 #endif
70         LUTIL_SLASHPATH( argv[0] );
71         progname = strrchr ( argv[0], *LDAP_DIRSEP );
72         progname = progname ? &progname[1] : argv[0];
73         return progname;
74 }
75
76 #if 0
77 size_t lutil_gentime( char *s, size_t smax, const struct tm *tm )
78 {
79         size_t ret;
80 #ifdef HAVE_EBCDIC
81 /* We've been compiling in ASCII so far, but we want EBCDIC now since
82  * strftime only understands EBCDIC input.
83  */
84 #pragma convlit(suspend)
85 #endif
86         ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm );
87 #ifdef HAVE_EBCDIC
88 #pragma convlit(resume)
89         __etoa( s );
90 #endif
91         return ret;
92 }
93 #endif
94
95 size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta )
96 {
97         size_t  ret;
98         char    *p;
99
100         if ( smax < 16 ) {      /* YYYYmmddHHMMSSZ */
101                 return 0;
102         }
103
104 #ifdef HAVE_EBCDIC
105 /* We've been compiling in ASCII so far, but we want EBCDIC now since
106  * strftime only understands EBCDIC input.
107  */
108 #pragma convlit(suspend)
109 #endif
110         ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm );
111 #ifdef HAVE_EBCDIC
112 #pragma convlit(resume)
113         __etoa( s );
114 #endif
115         if ( delta == 0 || ret == 0 ) {
116                 return ret;
117         }
118
119         if ( smax < 20 ) {      /* YYYYmmddHHMMSS+HHMM */
120                 return 0;
121         }
122
123         p = s + 14;
124
125         if ( delta < 0 ) {
126                 p[ 0 ] = '-';
127                 delta = -delta;
128         } else {
129                 p[ 0 ] = '+';
130         }
131         p++;
132
133         snprintf( p, smax - 15, "%02ld%02ld", delta / 3600,
134                         ( delta % 3600 ) / 60 );
135
136         return ret + 5;
137 }
138
139 int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
140 {
141         static int moffset[12] = {
142                 0, 31, 59, 90, 120,
143                 151, 181, 212, 243,
144                 273, 304, 334 }; 
145         int sec;
146
147         tt->tt_usec = tm->tm_usec;
148
149         /* special case 0000/01/01+00:00:00 is returned as zero */
150         if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 &&
151                 tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) {
152                 tt->tt_sec = 0;
153                 tt->tt_gsec = 0;
154                 return 0;
155         }
156
157         /* tm->tm_year is years since 1900 */
158         /* calculate days from years since 1970 (epoch) */ 
159         tt->tt_sec = tm->tm_year - 70; 
160         tt->tt_sec *= 365L; 
161
162         /* count leap days in preceding years */ 
163         tt->tt_sec += ((tm->tm_year -69) >> 2); 
164
165         /* calculate days from months */ 
166         tt->tt_sec += moffset[tm->tm_mon]; 
167
168         /* add in this year's leap day, if any */ 
169         if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) { 
170                 tt->tt_sec ++; 
171         } 
172
173         /* add in days in this month */ 
174         tt->tt_sec += (tm->tm_mday - 1); 
175
176         /* this function can handle a range of about 17408 years... */
177         /* 86400 seconds in a day, divided by 128 = 675 */
178         tt->tt_sec *= 675;
179
180         /* move high 7 bits into tt_gsec */
181         tt->tt_gsec = tt->tt_sec >> 25;
182         tt->tt_sec -= tt->tt_gsec << 25;
183
184         /* get hours */ 
185         sec = tm->tm_hour; 
186
187         /* convert to minutes */ 
188         sec *= 60L; 
189         sec += tm->tm_min; 
190
191         /* convert to seconds */ 
192         sec *= 60L; 
193         sec += tm->tm_sec; 
194         
195         /* add remaining seconds */
196         tt->tt_sec <<= 7;
197         tt->tt_sec += sec;
198
199         /* return success */
200         return 0; 
201 }
202
203 int lutil_parsetime( char *atm, struct lutil_tm *tm )
204 {
205         while (atm && tm) {
206                 char *ptr = atm;
207                 int i, fracs;
208
209                 /* Is the stamp reasonably long? */
210                 for (i=0; isdigit(atm[i]); i++);
211                 if (i < sizeof("00000101000000")-1)
212                         break;
213
214                 /*
215                  * parse the time into a struct tm
216                  */
217                 /* 4 digit year to year - 1900 */
218                 tm->tm_year = *ptr++ - '0';
219                 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
220                 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
221                 tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
222                 tm->tm_year -= 1900;
223                 /* month 01-12 to 0-11 */
224                 tm->tm_mon = *ptr++ - '0';
225                 tm->tm_mon *=10; tm->tm_mon += *ptr++ - '0';
226                 if (tm->tm_mon < 1 || tm->tm_mon > 12) break;
227                 tm->tm_mon--;
228
229                 /* day of month 01-31 */
230                 tm->tm_mday = *ptr++ - '0';
231                 tm->tm_mday *=10; tm->tm_mday += *ptr++ - '0';
232                 if (tm->tm_mday < 1 || tm->tm_mday > 31) break;
233
234                 /* Hour 00-23 */
235                 tm->tm_hour = *ptr++ - '0';
236                 tm->tm_hour *=10; tm->tm_hour += *ptr++ - '0';
237                 if (tm->tm_hour < 0 || tm->tm_hour > 23) break;
238
239                 /* Minute 00-59 */
240                 tm->tm_min = *ptr++ - '0';
241                 tm->tm_min *=10; tm->tm_min += *ptr++ - '0';
242                 if (tm->tm_min < 0 || tm->tm_min > 59) break;
243
244                 /* Second 00-61 */
245                 tm->tm_sec = *ptr++ - '0';
246                 tm->tm_sec *=10; tm->tm_sec += *ptr++ - '0';
247                 if (tm->tm_sec < 0 || tm->tm_sec > 61) break;
248
249                 /* Fractions of seconds */
250                 for (i = 0, fracs = 0;isdigit(*ptr);) {
251                         i*=10; i+= *ptr++ - '0';
252                         fracs++;
253                 }
254                 tm->tm_usec = i;
255                 if (i) {
256                         for (i = fracs; i<6; i++)
257                                 tm->tm_usec *= 10;
258                 }
259
260                 /* Must be UTC */
261                 if (*ptr != 'Z') break;
262
263                 return 0;
264         }
265         return -1;
266 }
267
268 /* strcopy is like strcpy except it returns a pointer to the trailing NUL of
269  * the result string. This allows fast construction of catenated strings
270  * without the overhead of strlen/strcat.
271  */
272 char *
273 lutil_strcopy(
274         char *a,
275         const char *b
276 )
277 {
278         if (!a || !b)
279                 return a;
280         
281         while ((*a++ = *b++)) ;
282         return a-1;
283 }
284
285 /* strncopy is like strcpy except it returns a pointer to the trailing NUL of
286  * the result string. This allows fast construction of catenated strings
287  * without the overhead of strlen/strcat.
288  */
289 char *
290 lutil_strncopy(
291         char *a,
292         const char *b,
293         size_t n
294 )
295 {
296         if (!a || !b || n == 0)
297                 return a;
298         
299         while ((*a++ = *b++) && n-- > 0) ;
300         return a-1;
301 }
302
303 #ifndef HAVE_MKSTEMP
304 int mkstemp( char * template )
305 {
306 #ifdef HAVE_MKTEMP
307         return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 );
308 #else
309         return -1;
310 #endif
311 }
312 #endif