afdf7194aa246f27ee7493569eb3a4dd38da8924
[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 <stdio.h>
18
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <sys/timeb.h>
25 #include "utils.h"
26
27 inline void* safe_malloc( int size ) {
28         void* ptr = (void*) malloc( size );
29         if( ptr == NULL ) {
30                 perror("safe_malloc(): Out of Memory" );
31                 exit(99);
32         }
33         memset( ptr, 0, size );
34         return ptr;
35 }
36
37 /* utility method for profiling */
38 double get_timestamp_millis() {
39         struct timeb t;
40         struct timeval tv;
41         gettimeofday(&tv, NULL);
42         ftime(&t);
43         double time     = (int)t.time   + ( ((double)t.millitm) / 1000 )  + ( ((double)tv.tv_usec / 1000000) );
44         return time;
45 }
46
47
48 /* setting/clearing file flags */
49 int set_fl( int fd, int flags ) {
50         
51         int val;
52
53         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
54                 fprintf(stderr, "fcntl F_GETFL error");
55                 return -1;
56         }
57
58         val |= flags;
59
60         if( fcntl( fd, F_SETFL, val ) < 0 ) {
61                 fprintf(stderr, "fcntl F_SETFL error");
62                 return -1;
63         }
64         return 0;
65 }
66         
67 int clr_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 // ---------------------------------------------------------------------------------
86 // Flesh out a ubiqitous growing string buffer
87 // ---------------------------------------------------------------------------------
88
89 growing_buffer* buffer_init(int num_initial_bytes) {
90
91         if( num_initial_bytes > BUFFER_MAX_SIZE ) {
92                 return NULL;
93         }
94
95
96         size_t len = sizeof(growing_buffer);
97
98         growing_buffer* gb = (growing_buffer*) safe_malloc(len);
99
100         gb->n_used = 0;/* nothing stored so far */
101         gb->size = num_initial_bytes;
102         gb->buf = (char *) safe_malloc(gb->size + 1);
103
104         return gb;
105 }
106
107 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
108
109         if(!gb || !format) return 0; 
110
111         int len = 0;
112         va_list args;
113         va_list a_copy;
114
115         //char* f_copy = strdup(format);
116
117         va_copy(a_copy, args);
118
119         va_start(args, format);
120         len = vsnprintf(NULL, 0, format, a_copy);
121         va_end(args);
122
123         len += 2;
124
125         char buf[len];
126         memset(buf, 0, len);
127
128         va_start(a_copy, format);
129         vsnprintf(buf, len - 1, format, args);
130         va_end(a_copy);
131
132         //free(f_copy);
133
134         return buffer_add(gb, buf);
135
136 }
137
138 int buffer_add(growing_buffer* gb, char* data) {
139
140
141         if( ! gb || ! data  ) { return 0; }
142         int data_len = strlen( data );
143
144         if( data_len == 0 ) { return 0; }
145         int total_len = data_len + gb->n_used;
146
147         while( total_len >= gb->size ) {
148                 gb->size *= 2;
149         }
150
151         if( gb->size > BUFFER_MAX_SIZE ) {
152                 fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
153                 buffer_free( gb );
154                 return 0;
155         }
156
157         char* new_data = (char*) safe_malloc( gb->size );
158
159         strcpy( new_data, gb->buf );
160         free( gb->buf );
161         gb->buf = new_data;
162
163         strcat( gb->buf, data );
164         gb->n_used = total_len;
165         return total_len;
166 }
167
168
169 int buffer_reset( growing_buffer *gb){
170         if( gb == NULL ) { return 0; }
171         if( gb->buf == NULL ) { return 0; }
172         memset( gb->buf, 0, gb->size );
173         gb->n_used = 0;
174         return 1;
175 }
176
177 int buffer_free( growing_buffer* gb ) {
178         if( gb == NULL ) 
179                 return 0;
180         free( gb->buf );
181         free( gb );
182         return 1;
183 }
184
185 char* buffer_data( growing_buffer *gb) {
186         return strdup( gb->buf );
187 }
188
189
190 int buffer_add_char(growing_buffer* gb, char c) {
191         char buf[2];
192         buf[0] = c;
193         buf[1] = '\0';
194         buffer_add(gb, buf);
195         return 1;
196 }
197
198
199
200 char* uescape( const char* string, int size, int full_escape ) {
201
202         growing_buffer* buf = buffer_init(size + 64);
203         int idx = 0;
204         long unsigned int c = 0;
205
206         while (string[idx]) {
207         
208                 c ^= c;
209                 
210                 if ((string[idx] & 0xF0) == 0xF0) {
211                         c = string[idx]<<18;
212
213                         if( size - idx < 4 ) return NULL;
214                         
215                         idx++;
216                         c |= (string[idx] & 0x3F)<<12;
217                         
218                         idx++;
219                         c |= (string[idx] & 0x3F)<<6;
220                         
221                         idx++;
222                         c |= (string[idx] & 0x3F);
223                         
224                         c ^= 0xFF000000;
225                         
226                         buffer_fadd(buf, "\\u%0.4x", c);
227
228                 } else if ((string[idx] & 0xE0) == 0xE0) {
229                         c = string[idx]<<12;
230                         if( size - idx < 3 ) return NULL;
231                         
232                         idx++;
233                         c |= (string[idx] & 0x3F)<<6;
234                         
235                         idx++;
236                         c |= (string[idx] & 0x3F);
237                         
238                         c ^= 0xFFF80000;
239                         
240                         buffer_fadd(buf, "\\u%0.4x", c);
241
242                 } else if ((string[idx] & 0xC0) == 0xC0) {
243                         // Two byte char
244                         c = string[idx]<<6;
245                         if( size - idx < 2 ) return NULL;
246                         
247                         idx++;
248                         c |= (string[idx] & 0x3F);
249                         
250                         c ^= 0xFFFFF000;
251                         
252                         buffer_fadd(buf, "\\u%0.4x", c);
253
254                 } else {
255                         c = string[idx];
256
257                         /* escape the usual suspects */
258                         if(full_escape) {
259                                 switch(c) {
260                                         case '"':
261                                                 buffer_add_char(buf, '\\');
262                                                 buffer_add_char(buf, '"');
263                                                 break;
264         
265                                         case '\b':
266                                                 buffer_add_char(buf, '\\');
267                                                 buffer_add_char(buf, 'b');
268                                                 break;
269         
270                                         case '\f':
271                                                 buffer_add_char(buf, '\\');
272                                                 buffer_add_char(buf, 'f');
273                                                 break;
274         
275                                         case '\t':
276                                                 buffer_add_char(buf, '\\');
277                                                 buffer_add_char(buf, 't');
278                                                 break;
279         
280                                         case '\n':
281                                                 buffer_add_char(buf, '\\');
282                                                 buffer_add_char(buf, 'n');
283                                                 break;
284         
285                                         case '\r':
286                                                 buffer_add_char(buf, '\\');
287                                                 buffer_add_char(buf, 'r');
288                                                 break;
289
290                                         default:
291                                                 buffer_add_char(buf, c);
292                                 }
293
294                         } else {
295                                 buffer_add_char(buf, c);
296                         }
297                 }
298
299                 idx++;
300         }
301
302         char* d = buffer_data(buf);
303         buffer_free(buf);
304         return d;
305 }
306
307
308 // A function to turn a process into a daemon and set it's process name in ps/top
309 int daemonize() {
310         int f = fork();
311         if (f == -1) {
312                 perror("Failed to fork!");
313                 return -1;
314         } else if (f == 0) {
315                 // We're in the child now...
316                 setsid();
317                 return 0;
318         } else {
319                 // We're in the parent...
320                 exit(0);
321         }
322 }
323
324 int stringisnum(char* s) {
325         char* w = (char*) malloc(strlen(s) * sizeof(char*));
326         bzero(w, strlen(s));
327         strtol(s, &w, 10);
328         if(strlen(w) > 0)  
329                 return 0;
330         return 1;
331 }
332         
333