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 ); // remove this after safe_calloc transition
29 inline void* safe_calloc( int size ) {
30 void* ptr = (void*) malloc( size );
32 osrfLogError( OSRF_LOG_MARK, "Out of Memory" );
35 memset( ptr, 0, size );
40 The following static variables, and the following two functions,
41 overwrite the argv array passed to main(). The purpose is to
42 change the program name as reported by ps and similar utilities.
44 Warning: this code makes the non-portable assumption that the
45 strings to which argv[] points are contiguous in memory. The
46 C Standard makes no such guarantee.
48 static char** global_argv = NULL;
49 static int global_argv_size = 0;
51 int init_proc_title( int argc, char* argv[] ) {
57 int len = strlen( global_argv[i]);
58 osrf_clearbuf( global_argv[i], len );
59 global_argv_size += len;
63 global_argv_size -= 2;
67 int set_proc_title( const char* format, ... ) {
68 VA_LIST_TO_STRING(format);
69 osrf_clearbuf( *(global_argv), global_argv_size);
70 return snprintf( *(global_argv), global_argv_size, VA_BUF );
74 /* utility method for profiling */
75 double get_timestamp_millis( void ) {
77 gettimeofday(&tv, NULL);
78 double time = (int)tv.tv_sec + ( ((double)tv.tv_usec / 1000000) );
83 /* setting/clearing file flags */
84 int set_fl( int fd, int flags ) {
88 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
93 if( fcntl( fd, F_SETFL, val ) < 0 )
99 int clr_fl( int fd, int flags ) {
103 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
108 if( fcntl( fd, F_SETFL, val ) < 0 )
114 long va_list_size(const char* format, va_list args) {
116 len = vsnprintf(NULL, 0, format, args);
123 char* va_list_to_string(const char* format, ...) {
129 va_copy(a_copy, args);
131 va_start(args, format);
132 len = va_list_size(format, args);
135 osrf_clearbuf(buf, sizeof(buf));
137 va_start(a_copy, format);
138 vsnprintf(buf, len - 1, format, a_copy);
143 // ---------------------------------------------------------------------------------
144 // Flesh out a ubiqitous growing string buffer
145 // ---------------------------------------------------------------------------------
147 growing_buffer* buffer_init(int num_initial_bytes) {
149 if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
151 size_t len = sizeof(growing_buffer);
154 OSRF_MALLOC(gb, len);
156 gb->n_used = 0;/* nothing stored so far */
157 gb->size = num_initial_bytes;
158 OSRF_MALLOC(gb->buf, gb->size + 1);
164 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
166 if(!gb || !format) return 0;
172 va_copy(a_copy, args);
174 va_start(args, format);
175 len = va_list_size(format, args);
178 osrf_clearbuf(buf, sizeof(buf));
180 va_start(a_copy, format);
181 vsnprintf(buf, len - 1, format, a_copy);
184 return buffer_add(gb, buf);
189 int buffer_add(growing_buffer* gb, const char* data) {
190 if(!(gb && data)) return 0;
192 int data_len = strlen( data );
194 if(data_len == 0) return 0;
196 int total_len = data_len + gb->n_used;
198 if( total_len >= gb->size ) {
199 while( total_len >= gb->size ) {
203 if( gb->size > BUFFER_MAX_SIZE ) {
204 osrfLogError( OSRF_LOG_MARK, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
210 OSRF_MALLOC(new_data, gb->size );
212 strcpy( new_data, gb->buf );
217 strcat( gb->buf, data );
218 gb->n_used = total_len;
223 int buffer_reset( growing_buffer *gb){
224 if( gb == NULL ) { return 0; }
225 if( gb->buf == NULL ) { return 0; }
226 osrf_clearbuf( gb->buf, sizeof(gb->buf) );
231 /* Return a pointer to the text within a growing_buffer, */
232 /* while destroying the growing_buffer itself. */
234 char* buffer_release( growing_buffer* gb) {
236 s[gb->n_used] = '\0';
241 /* Destroy a growing_buffer and the text it contains */
243 int buffer_free( growing_buffer* gb ) {
251 char* buffer_data( const growing_buffer *gb) {
252 return strdup( gb->buf );
257 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
260 if(gb->n_used < gb->size - 1)\
261 gb->buf[gb->n_used++] = c;\
263 buffer_add_char(gb, c);\
268 int buffer_add_char(growing_buffer* gb, char c) {
278 char* uescape( const char* string, int size, int full_escape ) {
280 growing_buffer* buf = buffer_init(size + 64);
283 unsigned long int c = 0x0;
285 while (string[idx]) {
289 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
291 if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
294 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
296 c = (unsigned char)string[idx] ^ 0xF0;
298 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
300 c = (unsigned char)string[idx] ^ 0xE0;
302 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
304 c = (unsigned char)string[idx] ^ 0xC0;
309 idx++; // look at the next byte
310 c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
314 buffer_fadd(buf, "\\u%04x", c);
324 /* escape the usual suspects */
328 OSRF_BUFFER_ADD_CHAR(buf, '\\');
329 OSRF_BUFFER_ADD_CHAR(buf, '"');
333 OSRF_BUFFER_ADD_CHAR(buf, '\\');
334 OSRF_BUFFER_ADD_CHAR(buf, 'b');
338 OSRF_BUFFER_ADD_CHAR(buf, '\\');
339 OSRF_BUFFER_ADD_CHAR(buf, 'f');
343 OSRF_BUFFER_ADD_CHAR(buf, '\\');
344 OSRF_BUFFER_ADD_CHAR(buf, 't');
348 OSRF_BUFFER_ADD_CHAR(buf, '\\');
349 OSRF_BUFFER_ADD_CHAR(buf, 'n');
353 OSRF_BUFFER_ADD_CHAR(buf, '\\');
354 OSRF_BUFFER_ADD_CHAR(buf, 'r');
358 OSRF_BUFFER_ADD_CHAR(buf, '\\');
359 OSRF_BUFFER_ADD_CHAR(buf, '\\');
363 if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
364 else OSRF_BUFFER_ADD_CHAR(buf, c);
368 OSRF_BUFFER_ADD_CHAR(buf, c);
375 char* d = buffer_data(buf);
381 // A function to turn a process into a daemon
382 int daemonize( void ) {
386 osrfLogError( OSRF_LOG_MARK, "Failed to fork!" );
389 } else if (f == 0) { // We're in the child now...
391 // Change directories. Otherwise whatever directory
392 // we're in couldn't be deleted until the program
393 // terminated -- possibly causing some inconvenience.
396 /* create new session */
399 // Now that we're no longer attached to a terminal,
400 // we don't want any traffic on the standard streams
401 freopen( "/dev/null", "r", stdin );
402 freopen( "/dev/null", "w", stdout );
403 freopen( "/dev/null", "w", stderr );
407 } else { // We're in the parent...
413 /* Return 1 if the string represents an integer, */
414 /* as recognized by strtol(); Otherwise return 0. */
416 int stringisnum(const char* s) {
424 char* file_to_string(const char* filename) {
426 if(!filename) return NULL;
430 osrf_clearbuf(buf, sizeof(buf));
431 growing_buffer* gb = buffer_init(len);
433 FILE* file = fopen(filename, "r");
435 osrfLogError( OSRF_LOG_MARK, "Unable to open file [%s]", filename );
439 while(fgets(buf, sizeof(buf), file)) {
441 osrf_clearbuf(buf, sizeof(buf));
446 char* data = buffer_data(gb);
452 char* md5sum( const char* text, ... ) {
455 unsigned char digest[16];
459 VA_LIST_TO_STRING(text);
462 for ( i=0 ; i != strlen(VA_BUF) ; i++ )
463 MD5_feed (&ctx, VA_BUF[i]);
465 MD5_stop (&ctx, digest);
469 osrf_clearbuf(final, sizeof(final));
471 for ( i=0 ; i<16 ; i++ ) {
472 snprintf(buf, sizeof(buf), "%02x", digest[i]);
473 strcat( final, buf );
476 return strdup(final);
480 int osrfUtilsCheckFileDescriptor( int fd ) {
490 if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
491 if( errno == EBADF ) return -1;