]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/utils/utils.c
bdeaa9678d993292118872a42bedb5367c2882b9
[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                 fprintf(stderr, "fcntl F_GETFL error");
70                 return -1;
71         }
72
73         val |= flags;
74
75         if( fcntl( fd, F_SETFL, val ) < 0 ) {
76                 fprintf(stderr, "fcntl F_SETFL error");
77                 return -1;
78         }
79         return 0;
80 }
81         
82 int clr_fl( int fd, int flags ) {
83         
84         int val;
85
86         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
87                 fprintf(stderr, "fcntl F_GETFL error" );
88                 return -1;
89         }
90
91         val &= ~flags;
92
93         if( fcntl( fd, F_SETFL, val ) < 0 ) {
94                 fprintf( stderr, "fcntl F_SETFL error" );
95                 return -1;
96         }
97         return 0;
98 }
99
100 long va_list_size(const char* format, va_list args) {
101         int len = 0;
102         len = vsnprintf(NULL, 0, format, args);
103         va_end(args);
104         len += 2;
105         return len;
106 }
107
108
109 char* va_list_to_string(const char* format, ...) {
110
111         long len = 0;
112         va_list args;
113         va_list a_copy;
114
115         va_copy(a_copy, args);
116
117         va_start(args, format);
118         len = va_list_size(format, args);
119
120         char buf[len];
121         memset(buf, 0, len);
122
123         va_start(a_copy, format);
124         vsnprintf(buf, len - 1, format, a_copy);
125         va_end(a_copy);
126         return strdup(buf);
127 }
128
129 // ---------------------------------------------------------------------------------
130 // Flesh out a ubiqitous growing string buffer
131 // ---------------------------------------------------------------------------------
132
133 growing_buffer* buffer_init(int num_initial_bytes) {
134
135         if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
136
137         size_t len = sizeof(growing_buffer);
138
139         growing_buffer* gb;
140         OSRF_MALLOC(gb, len);
141
142         gb->n_used = 0;/* nothing stored so far */
143         gb->size = num_initial_bytes;
144         OSRF_MALLOC(gb->buf, gb->size + 1);
145
146         return gb;
147 }
148
149
150 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
151
152         if(!gb || !format) return 0; 
153
154         long len = 0;
155         va_list args;
156         va_list a_copy;
157
158         va_copy(a_copy, args);
159
160         va_start(args, format);
161         len = va_list_size(format, args);
162
163         char buf[len];
164         memset(buf, 0, len);
165
166         va_start(a_copy, format);
167         vsnprintf(buf, len - 1, format, a_copy);
168         va_end(a_copy);
169
170         return buffer_add(gb, buf);
171
172 }
173
174
175 int buffer_add(growing_buffer* gb, char* data) {
176         if(!(gb && data)) return 0;
177
178         int data_len = strlen( data );
179
180         if(data_len == 0) return 0;
181
182         int total_len = data_len + gb->n_used;
183
184         if( total_len >= gb->size ) {
185                 while( total_len >= gb->size ) {
186                         gb->size *= 2;
187                 }
188         
189                 if( gb->size > BUFFER_MAX_SIZE ) {
190                         fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
191                         buffer_free( gb );
192                         return 0;
193                 }
194         
195                 char* new_data;
196                 OSRF_MALLOC(new_data, gb->size );
197         
198                 strcpy( new_data, gb->buf );
199                 free( gb->buf );
200                 gb->buf = new_data;
201         }
202
203         strcat( gb->buf, data );
204         gb->n_used = total_len;
205         return total_len;
206 }
207
208
209 int buffer_reset( growing_buffer *gb){
210         if( gb == NULL ) { return 0; }
211         if( gb->buf == NULL ) { return 0; }
212         memset( gb->buf, 0, gb->size );
213         gb->n_used = 0;
214         return 1;
215 }
216
217 int buffer_free( growing_buffer* gb ) {
218         if( gb == NULL ) 
219                 return 0;
220         free( gb->buf );
221         free( gb );
222         return 1;
223 }
224
225 char* buffer_data( growing_buffer *gb) {
226         return strdup( gb->buf );
227 }
228
229
230 /*
231 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
232         do {\
233                 if(gb) {\
234                         if(gb->n_used < gb->size - 1)\
235                                 gb->buf[gb->n_used++] = c;\
236                         else\
237                                 buffer_add_char(gb, c);\
238                 }\
239         }while(0)
240         */
241
242 int buffer_add_char(growing_buffer* gb, char c) {
243         char buf[2];
244         buf[0] = c;
245         buf[1] = '\0';
246         buffer_add(gb, buf);
247         return 1;
248 }
249
250
251
252 char* uescape( const char* string, int size, int full_escape ) {
253
254         growing_buffer* buf = buffer_init(size + 64);
255         int clen = 0;
256         int idx = 0;
257         unsigned long int c = 0x0;
258
259         while (string[idx]) {
260
261                 c = 0x0;
262
263                 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
264
265                         if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
266
267                                 clen = 1;
268                                 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
269                                         clen = 3;
270                                         c = (unsigned char)string[idx] ^ 0xF0;
271
272                                 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
273                                         clen = 2;
274                                         c = (unsigned char)string[idx] ^ 0xE0;
275
276                                 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
277                                         clen = 1;
278                                         c = (unsigned char)string[idx] ^ 0xC0;
279                                 }
280
281                                 for (;clen;clen--) {
282
283                                         idx++; // look at the next byte
284                                         c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
285
286                                 }
287
288                                 buffer_fadd(buf, "\\u%04x", c);
289
290                         } else {
291                                 buffer_free(buf);
292                                 return NULL;
293                         }
294
295                 } else {
296                         c = string[idx];
297
298                         /* escape the usual suspects */
299                         if(full_escape) {
300                                 switch(c) {
301                                         case '"':
302                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
303                                                 OSRF_BUFFER_ADD_CHAR(buf, '"');
304                                                 break;
305         
306                                         case '\b':
307                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
308                                                 OSRF_BUFFER_ADD_CHAR(buf, 'b');
309                                                 break;
310         
311                                         case '\f':
312                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
313                                                 OSRF_BUFFER_ADD_CHAR(buf, 'f');
314                                                 break;
315         
316                                         case '\t':
317                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
318                                                 OSRF_BUFFER_ADD_CHAR(buf, 't');
319                                                 break;
320         
321                                         case '\n':
322                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
323                                                 OSRF_BUFFER_ADD_CHAR(buf, 'n');
324                                                 break;
325         
326                                         case '\r':
327                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
328                                                 OSRF_BUFFER_ADD_CHAR(buf, 'r');
329                                                 break;
330
331                                         case '\\':
332                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
333                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
334                                                 break;
335
336                                         default:
337                                                 if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
338                                                 else OSRF_BUFFER_ADD_CHAR(buf, c);
339                                 }
340
341                         } else {
342                                 OSRF_BUFFER_ADD_CHAR(buf, c);
343                         }
344                 }
345
346                 idx++;
347         }
348
349         char* d = buffer_data(buf);
350         buffer_free(buf);
351         return d;
352 }
353
354
355 // A function to turn a process into a daemon and set it's process name in ps/top
356 int daemonize() {
357         int f = fork();
358
359         if (f == -1) {
360                 perror("Failed to fork!");
361                 return -1;
362
363         } else if (f == 0) { // We're in the child now...
364                 setsid();
365                 return 0;
366
367         } else { // We're in the parent...
368                 exit(0);
369         }
370 }
371
372
373 /* Return 1 if the string represents an integer,  */
374 /* as recognized by strtol(); Otherwise return 0. */
375
376 int stringisnum(char* s) {
377         char* w;
378         strtol(s, &w, 10);
379         return *w ? 0 : 1;
380 }
381         
382
383
384 char* file_to_string(const char* filename) {
385
386         if(!filename) return NULL;
387
388         int len = 1024;
389         char buf[len];
390         bzero(buf, len);
391         growing_buffer* gb = buffer_init(len);
392
393         FILE* file = fopen(filename, "r");
394         if(!file) {
395                 int l = strlen(filename) + 64;
396                 char b[l];
397                 snprintf(b,l,"Unable to open file [%s] in file_to_string()", filename);
398                 perror(b);
399                 return NULL;
400         }
401
402         while(fgets(buf, len - 1, file)) {
403                 buffer_add(gb, buf);
404                 bzero(buf, len);
405         }
406
407         fclose(file);
408
409         char* data = buffer_data(gb);
410         buffer_free(gb);
411         return data;
412 }
413
414
415 char* md5sum( char* text, ... ) {
416
417         struct md5_ctx ctx;
418         unsigned char digest[16];
419
420         MD5_start (&ctx);
421
422         VA_LIST_TO_STRING(text);
423
424         int i;
425         for ( i=0 ; i != strlen(VA_BUF) ; i++ )
426                 MD5_feed (&ctx, VA_BUF[i]);
427
428         MD5_stop (&ctx, digest);
429
430         char buf[16];
431         memset(buf,0,16);
432
433         char final[256];
434         memset(final,0,256);
435
436         for ( i=0 ; i<16 ; i++ ) {
437                 sprintf(buf, "%02x", digest[i]);
438                 strcat( final, buf );
439         }
440
441         return strdup(final);
442
443 }
444
445 int osrfUtilsCheckFileDescriptor( int fd ) {
446
447         fd_set tmpset;
448         FD_ZERO(&tmpset);
449         FD_SET(fd, &tmpset);
450
451         struct timeval tv;
452         tv.tv_sec = 0;
453         tv.tv_usec = 0;
454
455         if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
456                 if( errno == EBADF ) return -1;
457         }
458
459         return 0;
460 }
461