]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/utils/utils.c
any unhandled char below ascii 32 will now be encoded as utf8 (\uXXXX)
[OpenSRF.git] / 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 inline void* safe_malloc( int size ) {
21         void* ptr = (void*) malloc( size );
22         if( ptr == NULL ) {
23                 perror("safe_malloc(): Out of Memory" );
24                 exit(99);
25         }
26         memset( ptr, 0, size );
27         return ptr;
28 }
29
30
31 char** __global_argv = NULL;
32 int __global_argv_size = 0;
33
34 int init_proc_title( int argc, char* argv[] ) {
35
36         __global_argv = argv;
37
38         int i = 0;
39         while( i < argc ) {
40                 int len = strlen( __global_argv[i]);
41                 bzero( __global_argv[i++], len );
42                 __global_argv_size += len;
43         }
44
45         __global_argv_size -= 2;
46         return 0;
47 }
48
49 int set_proc_title( char* format, ... ) {
50         VA_LIST_TO_STRING(format);
51         bzero( *(__global_argv), __global_argv_size );
52         return snprintf( *(__global_argv), __global_argv_size, VA_BUF );
53 }
54
55
56 /* utility method for profiling */
57 double get_timestamp_millis() {
58         struct timeval tv;
59         gettimeofday(&tv, NULL);
60         double time     = (int)tv.tv_sec        + ( ((double)tv.tv_usec / 1000000) );
61         return time;
62 }
63
64
65 /* setting/clearing file flags */
66 int set_fl( int fd, int flags ) {
67         
68         int val;
69
70         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
71                 fprintf(stderr, "fcntl F_GETFL error");
72                 return -1;
73         }
74
75         val |= flags;
76
77         if( fcntl( fd, F_SETFL, val ) < 0 ) {
78                 fprintf(stderr, "fcntl F_SETFL error");
79                 return -1;
80         }
81         return 0;
82 }
83         
84 int clr_fl( int fd, int flags ) {
85         
86         int val;
87
88         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
89                 fprintf(stderr, "fcntl F_GETFL error" );
90                 return -1;
91         }
92
93         val &= ~flags;
94
95         if( fcntl( fd, F_SETFL, val ) < 0 ) {
96                 fprintf( stderr, "fcntl F_SETFL error" );
97                 return -1;
98         }
99         return 0;
100 }
101
102 long va_list_size(const char* format, va_list args) {
103         int len = 0;
104         len = vsnprintf(NULL, 0, format, args);
105         va_end(args);
106         len += 2;
107         return len;
108 }
109
110
111 char* va_list_to_string(const char* format, ...) {
112
113         long len = 0;
114         va_list args;
115         va_list a_copy;
116
117         va_copy(a_copy, args);
118
119         va_start(args, format);
120         len = va_list_size(format, args);
121
122         char buf[len];
123         memset(buf, 0, len);
124
125         va_start(a_copy, format);
126         vsnprintf(buf, len - 1, format, a_copy);
127         va_end(a_copy);
128         return strdup(buf);
129 }
130
131 // ---------------------------------------------------------------------------------
132 // Flesh out a ubiqitous growing string buffer
133 // ---------------------------------------------------------------------------------
134
135 growing_buffer* buffer_init(int num_initial_bytes) {
136
137         if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
138
139         size_t len = sizeof(growing_buffer);
140
141         growing_buffer* gb;
142         OSRF_MALLOC(gb, len);
143
144         gb->n_used = 0;/* nothing stored so far */
145         gb->size = num_initial_bytes;
146         OSRF_MALLOC(gb->buf, gb->size + 1);
147
148         return gb;
149 }
150
151
152 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
153
154         if(!gb || !format) return 0; 
155
156         long len = 0;
157         va_list args;
158         va_list a_copy;
159
160         va_copy(a_copy, args);
161
162         va_start(args, format);
163         len = va_list_size(format, args);
164
165         char buf[len];
166         memset(buf, 0, len);
167
168         va_start(a_copy, format);
169         vsnprintf(buf, len - 1, format, a_copy);
170         va_end(a_copy);
171
172         return buffer_add(gb, buf);
173
174 }
175
176
177 int buffer_add(growing_buffer* gb, char* data) {
178         if(!(gb && data)) return 0;
179
180         int data_len = strlen( data );
181
182         if(data_len == 0) return 0;
183
184         int total_len = data_len + gb->n_used;
185
186         if( total_len >= gb->size ) {
187                 while( total_len >= gb->size ) {
188                         gb->size *= 2;
189                 }
190         
191                 if( gb->size > BUFFER_MAX_SIZE ) {
192                         fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
193                         buffer_free( gb );
194                         return 0;
195                 }
196         
197                 char* new_data;
198                 OSRF_MALLOC(new_data, gb->size );
199         
200                 strcpy( new_data, gb->buf );
201                 free( gb->buf );
202                 gb->buf = new_data;
203         }
204
205         strcat( gb->buf, data );
206         gb->n_used = total_len;
207         return total_len;
208 }
209
210
211 int buffer_reset( growing_buffer *gb){
212         if( gb == NULL ) { return 0; }
213         if( gb->buf == NULL ) { return 0; }
214         memset( gb->buf, 0, gb->size );
215         gb->n_used = 0;
216         return 1;
217 }
218
219 int buffer_free( growing_buffer* gb ) {
220         if( gb == NULL ) 
221                 return 0;
222         free( gb->buf );
223         free( gb );
224         return 1;
225 }
226
227 char* buffer_data( growing_buffer *gb) {
228         return strdup( gb->buf );
229 }
230
231
232 /*
233 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
234         do {\
235                 if(gb) {\
236                         if(gb->n_used < gb->size - 1)\
237                                 gb->buf[gb->n_used++] = c;\
238                         else\
239                                 buffer_add_char(gb, c);\
240                 }\
241         }while(0)
242         */
243
244 int buffer_add_char(growing_buffer* gb, char c) {
245         char buf[2];
246         buf[0] = c;
247         buf[1] = '\0';
248         buffer_add(gb, buf);
249         return 1;
250 }
251
252
253
254 char* uescape( const char* string, int size, int full_escape ) {
255
256         growing_buffer* buf = buffer_init(size + 64);
257         int clen = 0;
258         int idx = 0;
259         unsigned long int c = 0x0;
260
261         while (string[idx]) {
262
263                 c = 0x0;
264
265                 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
266
267                         if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
268
269                                 clen = 1;
270                                 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
271                                         clen = 3;
272                                         c = (unsigned char)string[idx] ^ 0xF0;
273
274                                 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
275                                         clen = 2;
276                                         c = (unsigned char)string[idx] ^ 0xE0;
277
278                                 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
279                                         clen = 1;
280                                         c = (unsigned char)string[idx] ^ 0xC0;
281                                 }
282
283                                 for (;clen;clen--) {
284
285                                         idx++; // look at the next byte
286                                         c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
287
288                                 }
289
290                                 buffer_fadd(buf, "\\u%04x", c);
291
292                         } else {
293                                 return NULL;
294                         }
295
296                 } else {
297                         c = string[idx];
298
299                         /* escape the usual suspects */
300                         if(full_escape) {
301                                 switch(c) {
302                                         case '"':
303                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
304                                                 OSRF_BUFFER_ADD_CHAR(buf, '"');
305                                                 break;
306         
307                                         case '\b':
308                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
309                                                 OSRF_BUFFER_ADD_CHAR(buf, 'b');
310                                                 break;
311         
312                                         case '\f':
313                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
314                                                 OSRF_BUFFER_ADD_CHAR(buf, 'f');
315                                                 break;
316         
317                                         case '\t':
318                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
319                                                 OSRF_BUFFER_ADD_CHAR(buf, 't');
320                                                 break;
321         
322                                         case '\n':
323                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
324                                                 OSRF_BUFFER_ADD_CHAR(buf, 'n');
325                                                 break;
326         
327                                         case '\r':
328                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
329                                                 OSRF_BUFFER_ADD_CHAR(buf, 'r');
330                                                 break;
331
332                                         case '\\':
333                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
334                                                 OSRF_BUFFER_ADD_CHAR(buf, '\\');
335                                                 break;
336
337                                         default:
338                   if( c < 32 ) buffer_fadd(buf, "\\u%0.4x", c);
339                   else OSRF_BUFFER_ADD_CHAR(buf, c);
340                                 }
341
342                         } else {
343                                 OSRF_BUFFER_ADD_CHAR(buf, c);
344                         }
345                 }
346
347                 idx++;
348         }
349
350         char* d = buffer_data(buf);
351         buffer_free(buf);
352         return d;
353 }
354
355
356 // A function to turn a process into a daemon and set it's process name in ps/top
357 int daemonize() {
358         int f = fork();
359
360         if (f == -1) {
361                 perror("Failed to fork!");
362                 return -1;
363
364         } else if (f == 0) { // We're in the child now...
365                 setsid();
366                 return 0;
367
368         } else { // We're in the parent...
369                 exit(0);
370         }
371 }
372
373 int stringisnum(char* s) {
374         char* w = (char*) malloc(strlen(s) * sizeof(char*));
375         bzero(w, strlen(s));
376         strtol(s, &w, 10);
377         if(strlen(w) > 0)  
378                 return 0;
379         return 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