Simple utilities sink - stuff that doesn't fit anywhere else / objects in plain C Snapshot
|
00001 /* Copyright (c) Michael Moser (2011) . 3-clause BSD License applies */ 00002 00003 #include <stdio.h> 00004 #include <stdarg.h> 00005 #include <unistd.h> 00006 #include <errno.h> 00007 #include <string.h> 00008 #include "errorp.h" 00009 #include <sys/types.h> 00010 #include <sys/stat.h> 00011 #include <fcntl.h> 00012 #ifdef __linux__ 00013 #include <execinfo.h> 00014 #endif 00015 00016 #define ERROR_TOKEN "ERROR: " 00017 00018 #define STACK_FRAMES 30 00019 00020 #define STACK_START "*** start stack ***\n" 00021 #define STACK_EOF "\n*** eof stack ***\n\n" 00022 00023 00024 static int FD_OUT = 2; 00025 static int FD_ASSIGNED = 0; 00026 00027 #ifdef __linux__ 00028 static void dump_modules(char *buff, size_t buff_size); 00029 #endif 00030 00031 int errorp_is_file_open() 00032 { 00033 return FD_ASSIGNED; 00034 } 00035 00036 int errorp_open_file(const char *file) 00037 { 00038 int fd; 00039 00040 fd = open( file , O_CREAT | O_APPEND | O_RDWR, S_IWUSR | S_IRUSR ); 00041 if (fd != -1) { 00042 FD_OUT = fd; 00043 FD_ASSIGNED = 1; 00044 } 00045 return fd; 00046 } 00047 00048 void errorp_close_file() 00049 { 00050 if (FD_ASSIGNED != 1) { 00051 close( FD_OUT ); 00052 FD_OUT = 2; 00053 FD_ASSIGNED = 0; 00054 } 00055 } 00056 00057 void errorp(int rval, const char *fmt, ... ) 00058 { 00059 char buff[ 512 ]; 00060 char *p, *eof; 00061 va_list ap; 00062 int len, n; 00063 #if __linux__ 00064 void *sframes[ STACK_FRAMES + 1 ]; 00065 int nframes, i; 00066 #endif 00067 00068 00069 p = buff; 00070 eof = p + sizeof( buff ); 00071 00072 strcpy( p, ERROR_TOKEN ); 00073 p += strlen( ERROR_TOKEN ); 00074 00075 va_start( ap, fmt ); 00076 len = vsnprintf( p, eof - p - 1, fmt, ap ); 00077 va_end( ap ); 00078 p += len; 00079 00080 n = snprintf(p, eof - p - 1, ". returns %d errno %d\n", rval, errno ); 00081 p += n; 00082 00083 #if __linux__ 00084 nframes = backtrace( sframes, STACK_FRAMES + 1); \ 00085 write( FD_OUT, STACK_START, strlen( STACK_START ) ); 00086 00087 nframes = backtrace( sframes, STACK_FRAMES ); 00088 for (i=0; i<nframes; i++) { 00089 snprintf( buff, sizeof(buff), "frame %d ip: %p\n", i, sframes[ i ]); 00090 write( FD_OUT , buff, strlen( buff ) ); 00091 } 00092 00093 dump_modules( buff, sizeof(buff) ); 00094 write( FD_OUT, STACK_EOF, strlen( STACK_EOF ) ); 00095 #endif 00096 } 00097 00098 void error_dump_string( const char *msg, char *buff, size_t buff_size) 00099 { 00100 #if __linux__ 00101 void *sframes[ STACK_FRAMES + 1 ]; 00102 int nframes, i; 00103 #endif 00104 00105 00106 write( FD_OUT , msg , strlen( msg ) ); 00107 00108 #if __linux__ 00109 nframes = backtrace( sframes, STACK_FRAMES + 1); \ 00110 write( FD_OUT, STACK_START, strlen( STACK_START ) ); 00111 00112 nframes = backtrace( sframes, STACK_FRAMES ); 00113 for (i=0; i<nframes; i++) { 00114 snprintf( buff, buff_size, "frame %d ip: %p\n", i, sframes[ i ]); 00115 write( FD_OUT , buff, strlen( buff ) ); 00116 } 00117 00118 dump_modules( buff, buff_size ); 00119 write( FD_OUT, STACK_EOF, strlen( STACK_EOF ) ); 00120 #endif 00121 } 00122 00123 #define TOKENS_COUNT 6 00124 #define TOKENS_ADDRESS 0 00125 #define TOKENS_PERMISSIONS 1 00126 #define TOKENS_FILEOFFSET 2 00127 #define TOKENS_PATH 5 00128 00129 #ifdef __linux__ 00130 static void dump_modules(char *buf, size_t buff_size) 00131 { 00132 int fd, n, i, buf_start; 00133 char line[30]; 00134 char *pos, *eof_line, *tokens[ TOKENS_COUNT ]; 00135 00136 sprintf(buf,"/proc/%d/maps", getpid() ); 00137 00138 00139 fd = open( buf, O_RDONLY ); 00140 if (fd == -1) { 00141 return; 00142 } 00143 00144 buf_start = 0; 00145 while(1) { 00146 n = read(fd, buf + buf_start, buff_size - buf_start ); 00147 if (n <= 0) { 00148 break; 00149 } 00150 00151 pos = buf; 00152 while(1) { 00153 00154 eof_line = memchr( pos, '\n', buf + buff_size - pos ); 00155 if (eof_line == 0) { 00156 break; 00157 } 00158 00159 *eof_line = '\0'; 00160 for(i=0; i< TOKENS_COUNT; i++) { 00161 tokens[ i ] = strtok( !i ? pos : 0," "); 00162 if (! tokens[ i ]) { 00163 break; 00164 } 00165 if (i == TOKENS_PERMISSIONS) { 00166 if (strchr( tokens[i], 'x') == 0) { 00167 break; 00168 } 00169 } 00170 } 00171 if (i == TOKENS_COUNT) { 00172 snprintf(line, sizeof(line) - 1, "\n%s %s ", tokens[ TOKENS_ADDRESS ] , tokens[ TOKENS_FILEOFFSET ]); 00173 write( FD_OUT, line, strlen(line) ); 00174 write( FD_OUT, tokens[ TOKENS_PATH ], strlen( tokens[ TOKENS_PATH ] ) ); 00175 00176 } 00177 00178 pos = eof_line + 1; 00179 } 00180 00181 buf_start = 0; 00182 if (pos < (buf + buff_size - 1)) { 00183 buf_start = buf + buff_size - pos; 00184 memmove( buf, pos, buf_start ); 00185 } 00186 } 00187 close(fd); 00188 00189 } 00190 #endif