1 #define _XOPEN_SOURCE 500 /* For strdup(3) */
2 #define _POSIX_C_SOURCE 200112L /* For setenv() */
14 char *tz_orig
; /* Copy of original TZ variable */
16 /* Concatenate two strings into newly allocated buffer.
17 * You must free() them, when you don't need it anymore.
18 * Any of the arguments can be NULL meaning empty string.
19 * In case of error returns NULL.
20 * Empty string is always returned as allocated empty string. */
21 _hidden
char *astrcat(const char *first
, const char *second
) {
22 size_t first_len
, second_len
;
25 first_len
= (first
) ? strlen(first
) : 0;
26 second_len
= (second
) ? strlen(second
) : 0;
27 buf
= malloc(1 + first_len
+ second_len
);
30 if (first
) strcpy(buf
, first
);
31 if (second
) strcpy(buf
+ first_len
, second
);
37 /* Concatenate three strings into newly allocated buffer.
38 * You must free() them, when you don't need it anymore.
39 * Any of the arguments can be NULL meaning empty string.
40 * In case of error returns NULL.
41 * Empty string is always returned as allocated empty string. */
42 _hidden
char *astrcat3(const char *first
, const char *second
,
44 size_t first_len
, second_len
, third_len
;
47 first_len
= (first
) ? strlen(first
) : 0;
48 second_len
= (second
) ? strlen(second
) : 0;
49 third_len
= (third
) ? strlen(third
) : 0;
50 buf
= malloc(1 + first_len
+ second_len
+ third_len
);
70 /* Print formated string into automtically reallocated @uffer.
71 * @buffer automatically reallocated buffer. Must be &NULL or preallocated
73 * @format format string as for printf(3)
74 * @ap list of variadic arguments, after call will be in udefined state
75 * @Returns number of bytes printed. In case of errror, -1 and NULL @buffer*/
76 _hidden
int isds_vasprintf(char **buffer
, const char *format
, va_list ap
) {
78 int length
, new_length
;
81 if (!buffer
|| !format
) {
90 length
= vsnprintf(NULL
, 0, format
, aq
) + 1;
98 new_buffer
= realloc(*buffer
, length
);
104 *buffer
= new_buffer
;
106 new_length
= vsnprintf(*buffer
, length
, format
, ap
);
107 if (new_length
>= length
) {
117 /* Print formated string into automtically reallocated @uffer.
118 * @buffer automatically reallocated buffer. Must be &NULL or preallocated
120 * @format format string as for printf(3)
121 * @... variadic arguments
122 * @Returns number of bytes printed. In case of errror, -1 and NULL @buffer*/
123 _hidden
int isds_asprintf(char **buffer
, const char *format
, ...) {
126 va_start(ap
, format
);
127 ret
= isds_vasprintf(buffer
, format
, ap
);
133 /* Converts UTF8 string into locale encoded string.
134 * @utf string int UTF-8 terminated by zero byte
135 * @return allocated string encoded in locale specific encoding. You must free
136 * it. In case of error or NULL @utf returns NULL. */
137 _hidden
char *utf82locale(const char *utf
) {
140 char *buffer
= NULL
, *new_buffer
;
141 size_t buffer_length
= 0, buffer_used
= 0;
142 char *inbuf
, *outbuf
;
143 size_t inleft
, outleft
;
145 if (!utf
) return NULL
;
147 /* nl_langinfo() is not thread-safe */
148 state
= iconv_open(nl_langinfo(CODESET
), "UTF-8");
149 if (state
== (iconv_t
) -1) return NULL
;
151 /* Get the initial ouput buffer length */
152 utf_length
= strlen(utf
);
153 buffer_length
= utf_length
+ 1;
155 inbuf
= (char *) utf
;
156 inleft
= utf_length
+ 1;
160 new_buffer
= realloc(buffer
, buffer_length
);
169 outbuf
= buffer
+ buffer_used
;
170 outleft
= buffer_length
- buffer_used
;
172 /* Convert chunk of data */
173 if ((size_t) -1 == iconv(state
, &inbuf
, &inleft
, &outbuf
, &outleft
) &&
180 /* Update positions */
181 buffer_length
+= 1024;
182 buffer_used
= outbuf
- buffer
;
191 /* Encode given data into MIME Base64 encoded zero terminated string.
192 * @plain are input data (binary stream)
193 * @length is length of @plain data in bytes
194 * @return allocated string of base64 encoded plain data or NULL in case of
195 * error. You must free it. */
196 _hidden
char *b64encode(const void *plain
, const size_t length
) {
198 base64_encodestate state
;
200 char *buffer
, *new_buffer
;
202 if (!plain
) return NULL
;
204 base64_init_encodestate(&state
);
206 /* TODO: This function assumes sizeof(char) == 1 byte.
207 * To fix it, one must fix underlying functions too. */
208 if (sizeof(char) != 1) PANIC("sizeof(char) != 1 byte");
211 * (4 is padding, 1 is final new line, and 1 is string terminator) */
212 buffer
= malloc(length
* 2 + 4 + 1 + 1);
213 if (!buffer
) return NULL
;
215 /* Encode plain data */
216 code_length
= base64_encode_block(plain
, length
, buffer
, &state
);
217 code_length
+= base64_encode_blockend(buffer
+ code_length
, &state
);
219 /* Terminate string */
220 buffer
[code_length
++] = '\0';
222 /* Shrink the buffer */
223 new_buffer
= realloc(buffer
, code_length
);
224 if (new_buffer
) buffer
= new_buffer
;
230 /* Decode given data from MIME Base64 encoded zero terminated string to binary
232 * @encoded are input data (Base64 zero terminated string)
233 * @plain are automatically realocated output data (binary stream). You must
234 * free it. Will be freed in case of error.
235 * @return length of @plain data in bytes or (size_t) -1 in case of decoding
237 _hidden
size_t b64decode(const char *encoded
, void **plain
) {
239 base64_decodestate state
;
240 size_t encoded_length
;
244 if (!encoded
|| !plain
) {
245 if (plain
&& *plain
) zfree(*plain
);
246 return ((size_t) -1);
249 encoded_length
= strlen(encoded
);
250 base64_init_decodestate(&state
);
252 /* TODO: This function assumes sizeof(char) == 1 byte.
253 * To fix it, one must fix underlying functions too. */
254 if (sizeof(char) != 1) PANIC("sizeof(char) != 1 byte");
256 /* Allocate buffer */
257 buffer
= realloc(*plain
, encoded_length
);
260 return ((size_t) -1);
264 /* Decode encoded data */
265 plain_length
= base64_decode_block(encoded
, encoded_length
,
267 if (plain_length
< 0) {
272 /* Shrink the buffer */
273 buffer
= realloc(*plain
, plain_length
);
274 if (!buffer
) *plain
= buffer
;
280 /* Switches time zone to UTC.
281 * XXX: This is not reentrant and not thread-safe */
282 _hidden
void switch_tz_to_utc(void) {
287 tz_orig
= strdup(tz
);
289 PANIC("Can not back original time zone up");
294 if (setenv("TZ", "", 1))
295 PANIC("Can not change time zone to UTC temporarily");
301 /* Switches time zone to original value.
302 * XXX: This is not reentrant and not thread-safe */
303 _hidden
void switch_tz_to_native(void) {
305 if (setenv("TZ", tz_orig
, 1))
306 PANIC("Can not restore time zone by setting TZ variable");
311 PANIC("Can not restore time zone by unsetting TZ variable");