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