2 Copyright (C) 2005 Georgia Public Library Service
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.
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.
15 #include <opensrf/utils.h>
16 #include <opensrf/log.h>
19 inline void* safe_malloc( int size ) {
20 void* ptr = (void*) malloc( size );
22 osrfLogError( OSRF_LOG_MARK, "Out of Memory" );
25 memset( ptr, 0, size );
30 The following static variables, and the following two functions,
31 overwrite the argv array passed to main(). The purpose is to
32 change the program name as reported by ps and similar utilities.
34 Warning: this code makes the non-portable assumption that the
35 strings to which argv[] points are contiguous in memory. The
36 C Standard makes no such guarantee.
38 static char** global_argv = NULL;
39 static int global_argv_size = 0;
41 int init_proc_title( int argc, char* argv[] ) {
47 int len = strlen( global_argv[i]);
48 memset( global_argv[i], 0, len);
49 global_argv_size += len;
53 global_argv_size -= 2;
57 int set_proc_title( char* format, ... ) {
58 VA_LIST_TO_STRING(format);
59 memset( *(global_argv), 0, global_argv_size);
60 return snprintf( *(global_argv), global_argv_size, VA_BUF );
64 /* utility method for profiling */
65 double get_timestamp_millis() {
67 gettimeofday(&tv, NULL);
68 double time = (int)tv.tv_sec + ( ((double)tv.tv_usec / 1000000) );
73 /* setting/clearing file flags */
74 int set_fl( int fd, int flags ) {
78 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
83 if( fcntl( fd, F_SETFL, val ) < 0 )
89 int clr_fl( int fd, int flags ) {
93 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
98 if( fcntl( fd, F_SETFL, val ) < 0 )
104 long va_list_size(const char* format, va_list args) {
106 len = vsnprintf(NULL, 0, format, args);
113 char* va_list_to_string(const char* format, ...) {
119 va_copy(a_copy, args);
121 va_start(args, format);
122 len = va_list_size(format, args);
125 memset(buf, 0, sizeof(buf));
127 va_start(a_copy, format);
128 vsnprintf(buf, len - 1, format, a_copy);
133 // ---------------------------------------------------------------------------------
134 // Flesh out a ubiqitous growing string buffer
135 // ---------------------------------------------------------------------------------
137 growing_buffer* buffer_init(int num_initial_bytes) {
139 if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
141 size_t len = sizeof(growing_buffer);
144 OSRF_MALLOC(gb, len);
146 gb->n_used = 0;/* nothing stored so far */
147 gb->size = num_initial_bytes;
148 OSRF_MALLOC(gb->buf, gb->size + 1);
154 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
156 if(!gb || !format) return 0;
162 va_copy(a_copy, args);
164 va_start(args, format);
165 len = va_list_size(format, args);
168 memset(buf, 0, sizeof(buf));
170 va_start(a_copy, format);
171 vsnprintf(buf, len - 1, format, a_copy);
174 return buffer_add(gb, buf);
179 int buffer_add(growing_buffer* gb, char* data) {
180 if(!(gb && data)) return 0;
182 int data_len = strlen( data );
184 if(data_len == 0) return 0;
186 int total_len = data_len + gb->n_used;
188 if( total_len >= gb->size ) {
189 while( total_len >= gb->size ) {
193 if( gb->size > BUFFER_MAX_SIZE ) {
194 osrfLogError( OSRF_LOG_MARK, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
200 OSRF_MALLOC(new_data, gb->size );
202 strcpy( new_data, gb->buf );
207 strcat( gb->buf, data );
208 gb->n_used = total_len;
213 int buffer_reset( growing_buffer *gb){
214 if( gb == NULL ) { return 0; }
215 if( gb->buf == NULL ) { return 0; }
216 memset( gb->buf, 0, sizeof(gb->buf) );
221 /* Return a pointer to the text within a growing_buffer, */
222 /* while destroying the growing_buffer itself. */
224 char* buffer_release( growing_buffer* gb) {
226 s[gb->n_used] = '\0';
231 /* Destroy a growing_buffer and the text it contains */
233 int buffer_free( growing_buffer* gb ) {
241 char* buffer_data( growing_buffer *gb) {
242 return strdup( gb->buf );
247 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
250 if(gb->n_used < gb->size - 1)\
251 gb->buf[gb->n_used++] = c;\
253 buffer_add_char(gb, c);\
258 int buffer_add_char(growing_buffer* gb, char c) {
268 char* uescape( const char* string, int size, int full_escape ) {
270 growing_buffer* buf = buffer_init(size + 64);
273 unsigned long int c = 0x0;
275 while (string[idx]) {
279 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
281 if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
284 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
286 c = (unsigned char)string[idx] ^ 0xF0;
288 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
290 c = (unsigned char)string[idx] ^ 0xE0;
292 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
294 c = (unsigned char)string[idx] ^ 0xC0;
299 idx++; // look at the next byte
300 c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
304 buffer_fadd(buf, "\\u%04x", c);
314 /* escape the usual suspects */
318 OSRF_BUFFER_ADD_CHAR(buf, '\\');
319 OSRF_BUFFER_ADD_CHAR(buf, '"');
323 OSRF_BUFFER_ADD_CHAR(buf, '\\');
324 OSRF_BUFFER_ADD_CHAR(buf, 'b');
328 OSRF_BUFFER_ADD_CHAR(buf, '\\');
329 OSRF_BUFFER_ADD_CHAR(buf, 'f');
333 OSRF_BUFFER_ADD_CHAR(buf, '\\');
334 OSRF_BUFFER_ADD_CHAR(buf, 't');
338 OSRF_BUFFER_ADD_CHAR(buf, '\\');
339 OSRF_BUFFER_ADD_CHAR(buf, 'n');
343 OSRF_BUFFER_ADD_CHAR(buf, '\\');
344 OSRF_BUFFER_ADD_CHAR(buf, 'r');
348 OSRF_BUFFER_ADD_CHAR(buf, '\\');
349 OSRF_BUFFER_ADD_CHAR(buf, '\\');
353 if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
354 else OSRF_BUFFER_ADD_CHAR(buf, c);
358 OSRF_BUFFER_ADD_CHAR(buf, c);
365 char* d = buffer_data(buf);
371 // A function to turn a process into a daemon
376 osrfLogError( OSRF_LOG_MARK, "Failed to fork!" );
379 } else if (f == 0) { // We're in the child now...
381 // Change directories. Otherwise whatever directory
382 // we're in couldn't be deleted until the program
383 // terminated -- possibly causing some inconvenience.
386 /* create new session */
389 // Now that we're no longer attached to a terminal,
390 // we don't want any traffic on the standard streams
391 freopen( "/dev/null", "r", stdin );
392 freopen( "/dev/null", "w", stdout );
393 freopen( "/dev/null", "w", stderr );
397 } else { // We're in the parent...
403 /* Return 1 if the string represents an integer, */
404 /* as recognized by strtol(); Otherwise return 0. */
406 int stringisnum(char* s) {
414 char* file_to_string(const char* filename) {
416 if(!filename) return NULL;
420 memset(buf, 0, sizeof(buf));
421 growing_buffer* gb = buffer_init(len);
423 FILE* file = fopen(filename, "r");
425 osrfLogError( OSRF_LOG_MARK, "Unable to open file [%s]", filename );
429 while(fgets(buf, sizeof(buf), file)) {
431 memset(buf, 0, sizeof(buf));
436 char* data = buffer_data(gb);
442 char* md5sum( char* text, ... ) {
445 unsigned char digest[16];
449 VA_LIST_TO_STRING(text);
452 for ( i=0 ; i != strlen(VA_BUF) ; i++ )
453 MD5_feed (&ctx, VA_BUF[i]);
455 MD5_stop (&ctx, digest);
459 memset(final, 0, sizeof(final));
461 for ( i=0 ; i<16 ; i++ ) {
462 snprintf(buf, sizeof(buf), "%02x", digest[i]);
463 strcat( final, buf );
466 return strdup(final);
470 int osrfUtilsCheckFileDescriptor( int fd ) {
480 if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
481 if( errno == EBADF ) return -1;