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 bzero( global_argv[i++], len );
49 global_argv_size += len;
52 global_argv_size -= 2;
56 int set_proc_title( char* format, ... ) {
57 VA_LIST_TO_STRING(format);
58 bzero( *(global_argv), global_argv_size );
59 return snprintf( *(global_argv), global_argv_size, VA_BUF );
63 /* utility method for profiling */
64 double get_timestamp_millis() {
66 gettimeofday(&tv, NULL);
67 double time = (int)tv.tv_sec + ( ((double)tv.tv_usec / 1000000) );
72 /* setting/clearing file flags */
73 int set_fl( int fd, int flags ) {
77 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
82 if( fcntl( fd, F_SETFL, val ) < 0 )
88 int clr_fl( int fd, int flags ) {
92 if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
97 if( fcntl( fd, F_SETFL, val ) < 0 )
103 long va_list_size(const char* format, va_list args) {
105 len = vsnprintf(NULL, 0, format, args);
112 char* va_list_to_string(const char* format, ...) {
118 va_copy(a_copy, args);
120 va_start(args, format);
121 len = va_list_size(format, args);
126 va_start(a_copy, format);
127 vsnprintf(buf, len - 1, format, a_copy);
132 // ---------------------------------------------------------------------------------
133 // Flesh out a ubiqitous growing string buffer
134 // ---------------------------------------------------------------------------------
136 growing_buffer* buffer_init(int num_initial_bytes) {
138 if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
140 size_t len = sizeof(growing_buffer);
143 OSRF_MALLOC(gb, len);
145 gb->n_used = 0;/* nothing stored so far */
146 gb->size = num_initial_bytes;
147 OSRF_MALLOC(gb->buf, gb->size + 1);
153 int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
155 if(!gb || !format) return 0;
161 va_copy(a_copy, args);
163 va_start(args, format);
164 len = va_list_size(format, args);
169 va_start(a_copy, format);
170 vsnprintf(buf, len - 1, format, a_copy);
173 return buffer_add(gb, buf);
178 int buffer_add(growing_buffer* gb, char* data) {
179 if(!(gb && data)) return 0;
181 int data_len = strlen( data );
183 if(data_len == 0) return 0;
185 int total_len = data_len + gb->n_used;
187 if( total_len >= gb->size ) {
188 while( total_len >= gb->size ) {
192 if( gb->size > BUFFER_MAX_SIZE ) {
193 osrfLogError( OSRF_LOG_MARK, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
199 OSRF_MALLOC(new_data, gb->size );
201 strcpy( new_data, gb->buf );
206 strcat( gb->buf, data );
207 gb->n_used = total_len;
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 );
220 /* Return a pointer to the text within a growing_buffer, */
221 /* while destroying the growing_buffer itself. */
223 char* buffer_release( growing_buffer* gb) {
225 s[gb->n_used] = '\0';
230 /* Destroy a growing_buffer and the text it contains */
232 int buffer_free( growing_buffer* gb ) {
240 char* buffer_data( growing_buffer *gb) {
241 return strdup( gb->buf );
246 #define OSRF_BUFFER_ADD_CHAR(gb, c)\
249 if(gb->n_used < gb->size - 1)\
250 gb->buf[gb->n_used++] = c;\
252 buffer_add_char(gb, c);\
257 int buffer_add_char(growing_buffer* gb, char c) {
267 char* uescape( const char* string, int size, int full_escape ) {
269 growing_buffer* buf = buffer_init(size + 64);
272 unsigned long int c = 0x0;
274 while (string[idx]) {
278 if ((unsigned char)string[idx] >= 0x80) { // not ASCII
280 if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
283 if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
285 c = (unsigned char)string[idx] ^ 0xF0;
287 } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
289 c = (unsigned char)string[idx] ^ 0xE0;
291 } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
293 c = (unsigned char)string[idx] ^ 0xC0;
298 idx++; // look at the next byte
299 c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
303 buffer_fadd(buf, "\\u%04x", c);
313 /* escape the usual suspects */
317 OSRF_BUFFER_ADD_CHAR(buf, '\\');
318 OSRF_BUFFER_ADD_CHAR(buf, '"');
322 OSRF_BUFFER_ADD_CHAR(buf, '\\');
323 OSRF_BUFFER_ADD_CHAR(buf, 'b');
327 OSRF_BUFFER_ADD_CHAR(buf, '\\');
328 OSRF_BUFFER_ADD_CHAR(buf, 'f');
332 OSRF_BUFFER_ADD_CHAR(buf, '\\');
333 OSRF_BUFFER_ADD_CHAR(buf, 't');
337 OSRF_BUFFER_ADD_CHAR(buf, '\\');
338 OSRF_BUFFER_ADD_CHAR(buf, 'n');
342 OSRF_BUFFER_ADD_CHAR(buf, '\\');
343 OSRF_BUFFER_ADD_CHAR(buf, 'r');
347 OSRF_BUFFER_ADD_CHAR(buf, '\\');
348 OSRF_BUFFER_ADD_CHAR(buf, '\\');
352 if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
353 else OSRF_BUFFER_ADD_CHAR(buf, c);
357 OSRF_BUFFER_ADD_CHAR(buf, c);
364 char* d = buffer_data(buf);
370 // A function to turn a process into a daemon
375 osrfLogError( OSRF_LOG_MARK, "Failed to fork!" );
378 } else if (f == 0) { // We're in the child now...
380 // Change directories. Otherwise whatever directory
381 // we're in couldn't be deleted until the program
382 // terminated -- possibly causing some inconvenience.
385 /* create new session */
388 // Now that we're no longer attached to a terminal,
389 // we don't want any traffic on the standard streams
390 freopen( "/dev/null", "r", stdin );
391 freopen( "/dev/null", "w", stdout );
392 freopen( "/dev/null", "w", stderr );
396 } else { // We're in the parent...
402 /* Return 1 if the string represents an integer, */
403 /* as recognized by strtol(); Otherwise return 0. */
405 int stringisnum(char* s) {
413 char* file_to_string(const char* filename) {
415 if(!filename) return NULL;
420 growing_buffer* gb = buffer_init(len);
422 FILE* file = fopen(filename, "r");
424 osrfLogError( OSRF_LOG_MARK, "Unable to open file [%s]", filename );
428 while(fgets(buf, len - 1, file)) {
435 char* data = buffer_data(gb);
441 char* md5sum( char* text, ... ) {
444 unsigned char digest[16];
448 VA_LIST_TO_STRING(text);
451 for ( i=0 ; i != strlen(VA_BUF) ; i++ )
452 MD5_feed (&ctx, VA_BUF[i]);
454 MD5_stop (&ctx, digest);
462 for ( i=0 ; i<16 ; i++ ) {
463 sprintf(buf, "%02x", digest[i]);
464 strcat( final, buf );
467 return strdup(final);
471 int osrfUtilsCheckFileDescriptor( int fd ) {
481 if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
482 if( errno == EBADF ) return -1;