1 #define _XOPEN_SOURCE 500 /* For strdup(3) */
2 #define _POSIX_C_SOURCE 200112L /* For setenv() */
13 char *tz_orig
; /* Copy of original TZ variable */
15 /* Concatenate two strings into newly allocated buffer.
16 * You must free() them, when you don't need it anymore.
17 * Any of the arguments can be NULL meaning empty string.
18 * In case of error returns NULL.
19 * Empty string is always returned as allocated empty string. */
20 _hidden
char *astrcat(const char *first
, const char *second
) {
21 size_t first_len
, second_len
;
24 first_len
= (first
) ? strlen(first
) : 0;
25 second_len
= (second
) ? strlen(second
) : 0;
26 buf
= malloc(1 + first_len
+ second_len
);
29 if (first
) strcpy(buf
, first
);
30 if (second
) strcpy(buf
+ first_len
, second
);
36 /* Concatenate three strings into newly allocated buffer.
37 * You must free() them, when you don't need it anymore.
38 * Any of the arguments can be NULL meaning empty string.
39 * In case of error returns NULL.
40 * Empty string is always returned as allocated empty string. */
41 _hidden
char *astrcat3(const char *first
, const char *second
,
43 size_t first_len
, second_len
, third_len
;
46 first_len
= (first
) ? strlen(first
) : 0;
47 second_len
= (second
) ? strlen(second
) : 0;
48 third_len
= (third
) ? strlen(third
) : 0;
49 buf
= malloc(1 + first_len
+ second_len
+ third_len
);
69 /* Print formated string into automtically reallocated @uffer.
70 * @buffer automatically reallocated buffer. Must be &NULL or preallocated
72 * @format format string as for printf(3)
73 * @ap list of variadic arguments, after call will be in udefined state
74 * @Returns number of bytes printed. In case of errror, -1 and NULL @buffer*/
75 _hidden
int isds_vasprintf(char **buffer
, const char *format
, va_list ap
) {
77 int length
, new_length
;
80 if (!buffer
|| !format
) {
89 length
= vsnprintf(NULL
, 0, format
, aq
) + 1;
97 new_buffer
= realloc(*buffer
, length
);
103 *buffer
= new_buffer
;
105 new_length
= vsnprintf(*buffer
, length
, format
, ap
);
106 if (new_length
>= length
) {
116 /* Print formated string into automtically reallocated @uffer.
117 * @buffer automatically reallocated buffer. Must be &NULL or preallocated
119 * @format format string as for printf(3)
120 * @... variadic arguments
121 * @Returns number of bytes printed. In case of errror, -1 and NULL @buffer*/
122 _hidden
int isds_asprintf(char **buffer
, const char *format
, ...) {
125 va_start(ap
, format
);
126 ret
= isds_vasprintf(buffer
, format
, ap
);
132 /* Converts UTF8 string into locale encoded string.
133 * @utf string int UTF-8 terminated by zero byte
134 * @return allocated string encoded in locale specific encoding. You must free
135 * it. In case of error or NULL @utf returns NULL. */
136 _hidden
char *utf82locale(const char *utf
) {
139 char *buffer
= NULL
, *new_buffer
;
140 size_t buffer_length
= 0, buffer_used
= 0;
141 char *inbuf
, *outbuf
;
142 size_t inleft
, outleft
;
144 if (!utf
) return NULL
;
146 /* nl_langinfo() is not thread-safe */
147 state
= iconv_open(nl_langinfo(CODESET
), "UTF-8");
148 if (state
== (iconv_t
) -1) return NULL
;
150 /* Get the initial ouput buffer length */
151 utf_length
= strlen(utf
);
152 buffer_length
= utf_length
+ 1;
154 inbuf
= (char *) utf
;
155 inleft
= utf_length
+ 1;
159 new_buffer
= realloc(buffer
, buffer_length
);
168 outbuf
= buffer
+ buffer_used
;
169 outleft
= buffer_length
- buffer_used
;
171 /* Convert chunk of data */
172 if ((size_t) -1 == iconv(state
, &inbuf
, &inleft
, &outbuf
, &outleft
)) {
178 /* Update positions */
179 buffer_length
+= 1024;
180 buffer_used
= outbuf
- buffer
;
189 /* Encode given data into MIME Base64 encoded zero terminated string.
190 * @plain are input data (binary stream)
191 * @length is length of @plain data in bytes
192 * @return allocated string of base64 encoded plain data or NULL in case of
193 * error. You must free it. */
194 _hidden
char *b64encode(const void *plain
, const size_t length
) {
196 base64_encodestate state
;
198 char *buffer
, *new_buffer
;
200 if (!plain
) return NULL
;
202 base64_init_encodestate(&state
);
204 /* TODO: This function assumes sizeof(char) == 1 byte.
205 * To fix it, one must fix underlying functions too. */
206 if (sizeof(char) != 1) PANIC("sizeof(char) != 1 byte");
209 * (4 is padding, 1 is final new line, and 1 is string terminator) */
210 buffer
= malloc(length
* 2 + 4 + 1 + 1);
211 if (!buffer
) return NULL
;
213 /* Encode plain data */
214 code_length
= base64_encode_block(plain
, length
, buffer
, &state
);
215 code_length
+= base64_encode_blockend(buffer
+ code_length
, &state
);
217 /* Terminate string */
218 buffer
[code_length
++] = '\0';
220 /* Shrink the buffer */
221 new_buffer
= realloc(buffer
, code_length
);
222 if (new_buffer
) buffer
= new_buffer
;
228 /* Decode given data from MIME Base64 encoded zero terminated string to binary
230 * @encoded are input data (Base64 zero terminated string)
231 * @plain are automatically realocated output data (binary stream). You must
232 * free it. Will be freed in case of error.
233 * @return length of @plain data in bytes or (size_t) -1 in case of decoding
235 _hidden
size_t b64decode(const char *encoded
, void **plain
) {
237 base64_decodestate state
;
238 size_t encoded_length
;
242 if (!encoded
|| !plain
) {
243 if (plain
&& *plain
) zfree(*plain
);
244 return ((size_t) -1);
247 encoded_length
= strlen(encoded
);
248 base64_init_decodestate(&state
);
250 /* TODO: This function assumes sizeof(char) == 1 byte.
251 * To fix it, one must fix underlying functions too. */
252 if (sizeof(char) != 1) PANIC("sizeof(char) != 1 byte");
254 /* Allocate buffer */
255 buffer
= realloc(*plain
, encoded_length
);
258 return ((size_t) -1);
262 /* Decode encoded data */
263 plain_length
= base64_decode_block(encoded
, encoded_length
,
265 if (plain_length
< 0) {
270 /* Shrink the buffer */
271 buffer
= realloc(*plain
, plain_length
);
272 if (!buffer
) *plain
= buffer
;
278 /* Switches time zone to UTC.
279 * XXX: This is not reentrant and not thread-safe */
280 _hidden
void switch_tz_to_utc(void) {
285 tz_orig
= strdup(tz
);
287 PANIC("Can not back original time zone up");
292 if (setenv("TZ", "", 1))
293 PANIC("Can not change time zone to UTC temporarily");
299 /* Switches time zone to original value.
300 * XXX: This is not reentrant and not thread-safe */
301 _hidden
void switch_tz_to_native(void) {
303 if (setenv("TZ", tz_orig
, 1))
304 PANIC("Can not restore time zone by setting TZ variable");
309 PANIC("Can not restore time zone by unsetting TZ variable");