removed some error lines printed to stderr. not used and they also have the potentia...
[OpenSRF.git] / src / utils / utils.c
1 /*
2 Copyright (C) 2005  Georgia Public Library Service 
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 */
14
15 #include "utils.h"
16 #include <errno.h>
17
18 inline void* safe_malloc( int size ) {
19         void* ptr = (void*) malloc( size );
20         if( ptr == NULL ) {
21                 perror("safe_malloc(): Out of Memory" );
22                 exit(99);
23         }
24         memset( ptr, 0, size );
25         return ptr;
26 }
27
28
29 char** __global_argv = NULL;
30 int __global_argv_size = 0;
31
32 int init_proc_title( int argc, char* argv[] ) {
33
34         __global_argv = argv;
35
36         int i = 0;
37         while( i < argc ) {
38                 int len = strlen( __global_argv[i]);
39                 bzero( __global_argv[i++], len );
40                 __global_argv_size += len;
41         }
42
43         __global_argv_size -= 2;
44         return 0;
45 }
46
47 int set_proc_title( char* format, ... ) {
48         VA_LIST_TO_STRING(format);
49         bzero( *(__global_argv), __global_argv_size );
50         return snprintf( *(__global_argv), __global_argv_size, VA_BUF );
51 }
52
53
54 /* utility method for profiling */
55 double get_timestamp_millis() {
56         struct timeval tv;
57         gettimeofday(&tv, NULL);
58         double time     = (int)tv.tv_sec        + ( ((double)tv.tv_usec / 1000000) );
59         return time;
60 }
61
62
63 /* setting/clearing file flags */
64 int set_fl( int fd, int flags ) {
65         
66         int val;
67
68         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) 
69                 return -1;
70
71         val |= flags;
72
73         if( fcntl( fd, F_SETFL, val ) < 0 ) 
74                 return -1;
75
76         return 0;
77 }
78         
79 int clr_fl( int fd, int flags ) {
80         
81         int val;
82
83         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) 
84                 return -1;
85
86         val &= ~flags;
87
88         if( fcntl( fd, F_SETFL, val ) < 0 ) 
89                 return -1;
90
91         return 0;
92 }
93
94 long va_list_size(const char* format, va_list args) {
95         int len = 0;
96         len = vsnprintf(NULL, 0, format, args);
97         va_end(args);
98         len += 2;
99         return len;
100 }
101
102
103 char* va_list_to_string(const char* format, ...) {
104
105         long len = 0;
106         va_list args;
107         va_list a_copy;
108
109         va_copy(a_copy, args);
110
111         va_start(args, format);
112         len = va_list_size(format, args);
113
114         char buf[len];
115         memset(buf, 0, len);
116
117         va_start(a_copy, format);
118         vsnprintf(buf, len - 1, format, a_copy);
119         va_end(a_copy);
120         return strdup(buf);
121 }
122
123 // ---------------------------------------------------------------------------------
124 // Flesh out a ubiqitous growing string buffer
125 // ---------------------------------------------------------------------------------
126
127 growing_buffer* buffer_init(int num_initial_bytes) {
128
129         if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
130
131         size_t len = sizeof(growing_buffer);
132
133         growing_buffer* gb;
134         OSRF_MALLOC(gb, len);
135
136         gb->n_used = 0;/* nothing stored so far */
137         gb->size = num_initial_bytes;
138         OSRF_MALLOC(gb->buf, gb->size + 1);
139
140         return gb;
141 }
142
143
144 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
145
146         if(!gb || !format) return 0; 
147
148         long len = 0;
149         va_list args;
150         va_list a_copy;
151
152         va_copy(a_copy, args);
153
154         va_start(args, format);
155         len = va_list_size(format, args);
156
157         char buf[len];
158         memset(buf, 0, len);
159
160         va_start(a_copy, format);
161         vsnprintf(buf, len - 1, format, a_copy);
162         va_end(a_copy);
163
164         return buffer_add(gb, buf);
165
166 }
167
168
169 int buffer_add(growing_buffer* gb, char* data) {
170         if(!(gb && data)) return 0;
171
172         int data_len = strlen( data );
173
174         if(data_len == 0) return 0;
175
176         int total_len = data_len + gb->n_used;
177
178         if( total_len >= gb->size ) {
179                 while( total_len >= gb->size ) {
180                         gb->size *= 2;
181                 }
182         
183                 if( gb->size > BUFFER_MAX_SIZE ) {
184                         fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
185                         buffer_free( gb );
186                         return 0;
187                 }
188         
189                 char* new_data;
190                 OSRF_MALLOC(new_data, gb->size );
191         
192                 strcpy( new_data, gb->buf );
193                 free( gb->buf );
194                 gb->buf = new_data;
195         }
196
197         strcat( gb->buf, data );
198         gb->n_used = total_len;
199         return total_len;
200 }
201
202
203 int buffer_reset( growing_buffer *gb){
204         if( gb == NULL ) { return 0; }
205         if( gb->buf == NULL ) { return 0; }
206         memset( gb->buf, 0, gb->size );
207         gb->n_used = 0;
208         return 1;
209 }
210
211 /* Return a pointer to the text within a growing_buffer, */
212 /* while destroying the growing_buffer itself.           */
213
214 char* buffer_release( growing_buffer* gb) {
215         char* s = gb->buf;
216         s[gb->n_used] = '\0';
217         free( gb );
218         return s;
219 }
220
221 /* Destroy a growing_buffer and the text it contains */
222
223 int buffer_free( growing_buffer* gb ) {
224         if( gb == NULL ) 
225                 return 0;
226         free( gb->buf );
227         free( gb );
228         return 1;
229 }
230
231 char* buffer_data( growing_buffer *gb) {
232         return strdup( gb->buf );
233 }
234
235
236 /*
237 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
238         do {\
239                 if(gb) {\
240                         if(gb->n_used < gb->size - 1)\
241                                 gb->buf[gb->n_used++] = c;\
242                         else\
243                                 buffer_add_char(gb, c);\
244                 }\
245         }while(0)
246         */
247
248 int buffer_add_char(growing_buffer* gb, char c) {
249         char buf[2];
250         buf[0] = c;
251         buf[1] = '\0';
252         buffer_add(gb, buf);
253         return 1;
254 }
255
256
257
258 char* uescape( const char* string, int size, int full_escape ) {
259
260         growing_buffer* buf = buffer_init(size + 64);
261         int clen = 0;
262         int idx = 0;
263         unsigned long int c = 0x0;
264
265         while (string[idx]) {
266
267                 c = 0x0;
268
269                 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
270
271                         if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
272
273                                 clen = 1;
274                                 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
275                                         clen = 3;
276                                         c = (unsigned char)string[idx] ^ 0xF0;
277
278                                 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
279                                         clen = 2;
280                                         c = (unsigned char)string[idx] ^ 0xE0;
281
282                                 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
283                                         clen = 1;
284                                         c = (unsigned char)string[idx] ^ 0xC0;
285                                 }
286
287                                 for (;clen;clen--) {
288
289                                         idx++; // look at the next byte
290                                         c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
291
292                                 }
293
294                                 buffer_fadd(buf, "\\u%04x", c);
295
296                         } else {
297                                 buffer_free(buf);
298                                 return NULL;
299                         }
300
301                 } else {
302                         c = string[idx];
303
304                         /* escape the usual suspects */
305                         if(full_escape) {
306                                 switch(c) {
307                                         case '"':
308                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
309                                                 OSRF_BUFFER_ADD_CHAR(buf, '"');
310                                                 break;
311         
312                                         case '\b':
313                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
314                                                 OSRF_BUFFER_ADD_CHAR(buf, 'b');
315                                                 break;
316         
317                                         case '\f':
318                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
319                                                 OSRF_BUFFER_ADD_CHAR(buf, 'f');
320                                                 break;
321         
322                                         case '\t':
323                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
324                                                 OSRF_BUFFER_ADD_CHAR(buf, 't');
325                                                 break;
326         
327                                         case '\n':
328                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
329                                                 OSRF_BUFFER_ADD_CHAR(buf, 'n');
330                                                 break;
331         
332                                         case '\r':
333                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
334                                                 OSRF_BUFFER_ADD_CHAR(buf, 'r');
335                                                 break;
336
337                                         case '\\':
338                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
339                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
340                                                 break;
341
342                                         default:
343                                                 if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
344                                                 else OSRF_BUFFER_ADD_CHAR(buf, c);
345                                 }
346
347                         } else {
348                                 OSRF_BUFFER_ADD_CHAR(buf, c);
349                         }
350                 }
351
352                 idx++;
353         }
354
355         char* d = buffer_data(buf);
356         buffer_free(buf);
357         return d;
358 }
359
360
361 // A function to turn a process into a daemon and set it's process name in ps/top
362 int daemonize() {
363         int f = fork();
364
365         if (f == -1) {
366                 perror("Failed to fork!");
367                 return -1;
368
369         } else if (f == 0) { // We're in the child now...
370                 setsid();
371                 return 0;
372
373         } else { // We're in the parent...
374                 exit(0);
375         }
376 }
377
378
379 /* Return 1 if the string represents an integer,  */
380 /* as recognized by strtol(); Otherwise return 0. */
381
382 int stringisnum(char* s) {
383         char* w;
384         strtol(s, &w, 10);
385         return *w ? 0 : 1;
386 }
387         
388
389
390 char* file_to_string(const char* filename) {
391
392         if(!filename) return NULL;
393
394         int len = 1024;
395         char buf[len];
396         bzero(buf, len);
397         growing_buffer* gb = buffer_init(len);
398
399         FILE* file = fopen(filename, "r");
400         if(!file) {
401                 int l = strlen(filename) + 64;
402                 char b[l];
403                 snprintf(b,l,"Unable to open file [%s] in file_to_string()", filename);
404                 perror(b);
405                 return NULL;
406         }
407
408         while(fgets(buf, len - 1, file)) {
409                 buffer_add(gb, buf);
410                 bzero(buf, len);
411         }
412
413         fclose(file);
414
415         char* data = buffer_data(gb);
416         buffer_free(gb);
417         return data;
418 }
419
420
421 char* md5sum( char* text, ... ) {
422
423         struct md5_ctx ctx;
424         unsigned char digest[16];
425
426         MD5_start (&ctx);
427
428         VA_LIST_TO_STRING(text);
429
430         int i;
431         for ( i=0 ; i != strlen(VA_BUF) ; i++ )
432                 MD5_feed (&ctx, VA_BUF[i]);
433
434         MD5_stop (&ctx, digest);
435
436         char buf[16];
437         memset(buf,0,16);
438
439         char final[256];
440         memset(final,0,256);
441
442         for ( i=0 ; i<16 ; i++ ) {
443                 sprintf(buf, "%02x", digest[i]);
444                 strcat( final, buf );
445         }
446
447         return strdup(final);
448
449 }
450
451 int osrfUtilsCheckFileDescriptor( int fd ) {
452
453         fd_set tmpset;
454         FD_ZERO(&tmpset);
455         FD_SET(fd, &tmpset);
456
457         struct timeval tv;
458         tv.tv_sec = 0;
459         tv.tv_usec = 0;
460
461         if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
462                 if( errno == EBADF ) return -1;
463         }
464
465         return 0;
466 }
467