LCOV - code coverage report
Current view: top level - src - util.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 203 491 41.3 %
Date: 2010-12-13 Functions: 29 62 46.8 %
Branches: 129 324 39.8 %

           Branch data     Line data    Source code
       1                 :            : // $Id: util.cc 6916 2009-09-24 20:48:36Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #ifdef TIME_WITH_SYS_TIME
       8                 :            : # include <sys/time.h>
       9                 :            : # include <time.h>
      10                 :            : #else
      11                 :            : # ifdef HAVE_SYS_TIME_H
      12                 :            : #  include <sys/time.h>
      13                 :            : # else
      14                 :            : #  include <time.h>
      15                 :            : # endif
      16                 :            : #endif
      17                 :            : 
      18                 :            : #include <ctype.h>
      19                 :            : #include <stdio.h>
      20                 :            : #include <stdlib.h>
      21                 :            : #include <unistd.h>
      22                 :            : #include <sys/types.h>
      23                 :            : #include <sys/stat.h>
      24                 :            : #include <sys/resource.h>
      25                 :            : #include <fcntl.h>
      26                 :            : #include <stdarg.h>
      27                 :            : #include <errno.h>
      28                 :            : #include <signal.h>
      29                 :            : 
      30                 :            : #ifdef HAVE_MALLINFO
      31                 :            : # include <malloc.h>
      32                 :            : #endif
      33                 :            : 
      34                 :            : #include "input.h"
      35                 :            : #include "util.h"
      36                 :            : #include "Obj.h"
      37                 :            : #include "md5.h"
      38                 :            : #include "Val.h"
      39                 :            : #include "NetVar.h"
      40                 :            : #include "Net.h"
      41                 :            : 
      42                 :      73119 : char* copy_string(const char* s)
      43                 :            :         {
      44                 :      73119 :         char* c = new char[strlen(s)+1];
      45                 :      73119 :         strcpy(c, s);
      46                 :      73119 :         return c;
      47                 :            :         }
      48                 :            : 
      49                 :     418531 : int streq(const char* s1, const char* s2)
      50                 :            :         {
      51                 :     418531 :         return ! strcmp(s1, s2);
      52                 :            :         }
      53                 :            : 
      54                 :       2470 : int expand_escape(const char*& s)
      55                 :            :         {
      56 [ -  -  +  +  + :       2470 :         switch ( *(s++) ) {
          -  -  +  +  + ]
      57                 :          0 :         case 'b': return '\b';
      58                 :          0 :         case 'f': return '\f';
      59                 :        640 :         case 'n': return '\n';
      60                 :          4 :         case 'r': return '\r';
      61                 :         22 :         case 't': return '\t';
      62                 :          0 :         case 'a': return '\a';
      63                 :          0 :         case 'v': return '\v';
      64                 :            : 
      65                 :            :         case '0': case '1': case '2': case '3': case '4':
      66                 :            :         case '5': case '6': case '7':
      67                 :            :                 { // \<octal>{1,3}
      68                 :          2 :                 --s;    // put back the first octal digit
      69                 :          2 :                 const char* start = s;
      70                 :            : 
      71                 :            :                 // Don't increment inside loop control
      72                 :            :                 // because if isdigit() is a macro it might
      73                 :            :                 // expand into multiple increments ...
      74                 :            : 
      75                 :            :                 // Here we define a maximum length for escape sequence
      76                 :            :                 // to allow easy handling of string like: "^H0" as
      77                 :            :                 // "\0100".
      78                 :            : 
      79 [ +  + ][ +  - ]:          8 :                 for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s);
                 [ +  - ]
      80                 :            :                       ++s, ++len)
      81                 :            :                         ;
      82                 :            : 
      83                 :            :                 int result;
      84         [ -  + ]:          2 :                 if ( sscanf(start, "%3o", &result) != 1 )
      85                 :            :                         {
      86                 :          0 :                         warn("bad octal escape: ", start);
      87                 :          0 :                         result = 0;
      88                 :            :                         }
      89                 :            : 
      90                 :          2 :                 return result;
      91                 :            :                 }
      92                 :            : 
      93                 :            :         case 'x':
      94                 :            :                 { /* \x<hex> */
      95                 :         13 :                 const char* start = s;
      96                 :            : 
      97                 :            :                 // Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
      98 [ +  + ][ +  - ]:         39 :                 for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s);
                 [ +  - ]
      99                 :            :                       ++s, ++len)
     100                 :            :                         ;
     101                 :            : 
     102                 :            :                 int result;
     103         [ -  + ]:         13 :                 if ( sscanf(start, "%2x", &result) != 1 )
     104                 :            :                         {
     105                 :          0 :                         warn("bad hexadecimal escape: ", start);
     106                 :          0 :                         result = 0;
     107                 :            :                         }
     108                 :            : 
     109                 :         13 :                 return result;
     110                 :            :                 }
     111                 :            : 
     112                 :            :         default:
     113                 :       2470 :                 return s[-1];
     114                 :            :         }
     115                 :            :         }
     116                 :            : 
     117                 :        436 : char* skip_whitespace(char* s)
     118                 :            :         {
     119 [ +  + ][ -  + ]:        872 :         while ( *s == ' ' || *s == '\t' )
     120                 :        436 :                 ++s;
     121                 :        436 :         return s;
     122                 :            :         }
     123                 :            : 
     124                 :        966 : const char* skip_whitespace(const char* s)
     125                 :            :         {
     126 [ +  + ][ -  + ]:        985 :         while ( *s == ' ' || *s == '\t' )
     127                 :         19 :                 ++s;
     128                 :        966 :         return s;
     129                 :            :         }
     130                 :            : 
     131                 :          0 : char* skip_whitespace(char* s, char* end_of_s)
     132                 :            :         {
     133 [ #  # ][ #  # ]:          0 :         while ( s < end_of_s && (*s == ' ' || *s == '\t') )
                 [ #  # ]
     134                 :          0 :                 ++s;
     135                 :          0 :         return s;
     136                 :            :         }
     137                 :            : 
     138                 :       2775 : const char* skip_whitespace(const char* s, const char* end_of_s)
     139                 :            :         {
     140 [ +  + ][ +  + ]:       4536 :         while ( s < end_of_s && (*s == ' ' || *s == '\t') )
                 [ -  + ]
     141                 :       1761 :                 ++s;
     142                 :       2775 :         return s;
     143                 :            :         }
     144                 :            : 
     145                 :          0 : char* skip_digits(char* s)
     146                 :            :         {
     147 [ #  # ][ #  # ]:          0 :         while ( *s && isdigit(*s) )
     148                 :          0 :                 ++s;
     149                 :          0 :         return s;
     150                 :            :         }
     151                 :            : 
     152                 :          0 : char* get_word(char*& s)
     153                 :            :         {
     154                 :          0 :         char* w = s;
     155 [ #  # ][ #  # ]:          0 :         while ( *s && ! isspace(*s) )
     156                 :          0 :                 ++s;
     157                 :            : 
     158         [ #  # ]:          0 :         if ( *s )
     159                 :            :                 {
     160                 :          0 :                 *s = '\0';      // terminate the word
     161                 :          0 :                 s = skip_whitespace(s+1);
     162                 :            :                 }
     163                 :            : 
     164                 :          0 :         return w;
     165                 :            :         }
     166                 :            : 
     167                 :          0 : void get_word(int length, const char* s, int& pwlen, const char*& pw)
     168                 :            :         {
     169                 :          0 :         pw = s;
     170                 :            : 
     171                 :          0 :         int len = 0;
     172 [ #  # ][ #  # ]:          0 :         while ( len < length && *s && ! isspace(*s) )
                 [ #  # ]
     173                 :            :                 {
     174                 :          0 :                 ++s;
     175                 :          0 :                 ++len;
     176                 :            :                 }
     177                 :            : 
     178                 :          0 :         pwlen = len;
     179                 :          0 :         }
     180                 :            : 
     181                 :          0 : void to_upper(char* s)
     182                 :            :         {
     183         [ #  # ]:          0 :         while ( *s )
     184                 :            :                 {
     185         [ #  # ]:          0 :                 if ( islower(*s) )
     186                 :          0 :                         *s = toupper(*s);
     187                 :          0 :                 ++s;
     188                 :            :                 }
     189                 :          0 :         }
     190                 :            : 
     191                 :          0 : const char* strchr_n(const char* s, const char* end_of_s, char ch)
     192                 :            :         {
     193         [ #  # ]:          0 :         for ( ; s < end_of_s; ++s )
     194         [ #  # ]:          0 :                 if ( *s == ch )
     195                 :          0 :                         return s;
     196                 :            : 
     197                 :          0 :         return 0;
     198                 :            :         }
     199                 :            : 
     200                 :          0 : const char* strrchr_n(const char* s, const char* end_of_s, char ch)
     201                 :            :         {
     202         [ #  # ]:          0 :         for ( --end_of_s; end_of_s >= s; --end_of_s )
     203         [ #  # ]:          0 :                 if ( *end_of_s == ch )
     204                 :          0 :                         return end_of_s;
     205                 :            : 
     206                 :          0 :         return 0;
     207                 :            :         }
     208                 :            : 
     209                 :       4408 : int decode_hex(char ch)
     210                 :            :         {
     211 [ +  - ][ +  + ]:       4408 :         if ( ch >= '0' && ch <= '9' )
     212                 :       2778 :                 return ch - '0';
     213                 :            : 
     214 [ +  - ][ +  + ]:       1630 :         if ( ch >= 'A' && ch <= 'F' )
     215                 :       1294 :                 return ch - 'A' + 10;
     216                 :            : 
     217 [ +  - ][ +  - ]:        336 :         if ( ch >= 'a' && ch <= 'f' )
     218                 :        336 :                 return ch - 'a' + 10;
     219                 :            : 
     220                 :       4408 :         return -1;
     221                 :            :         }
     222                 :            : 
     223                 :          0 : unsigned char encode_hex(int h)
     224                 :            :         {
     225                 :            :         static const char hex[16] = {
     226                 :            :                 '0', '1', '2', '3', '4', '5', '6', '7', '8',
     227                 :            :                 '9', 'A', 'B', 'C', 'D', 'E', 'F'
     228                 :            :         };
     229                 :            : 
     230 [ #  # ][ #  # ]:          0 :         if  ( h < 0 || h >= 16 )
     231                 :            :                 {
     232                 :          0 :                 internal_error("illegal value for encode_hex: %d", h);
     233                 :            :                 return 'X';
     234                 :            :                 }
     235                 :            : 
     236                 :          0 :         return hex[h];
     237                 :            :         }
     238                 :            : 
     239                 :            : // Same as strpbrk except that s is not NUL-terminated, but limited by
     240                 :            : // len. Note that '\0' is always implicitly contained in charset.
     241                 :          0 : const char* strpbrk_n(size_t len, const char* s, const char* charset)
     242                 :            :         {
     243         [ #  # ]:          0 :         for ( const char* p = s; p < s + len; ++p )
     244         [ #  # ]:          0 :                 if ( strchr(charset, *p) )
     245                 :          0 :                         return p;
     246                 :            : 
     247                 :          0 :         return 0;
     248                 :            :         }
     249                 :            : 
     250                 :      52656 : int strcasecmp_n(int b_len, const char* b, const char* t)
     251                 :            :         {
     252         [ -  + ]:      52656 :         if ( ! b )
     253                 :          0 :                 return -1;
     254                 :            : 
     255                 :            :         int i;
     256         [ +  + ]:     111733 :         for ( i = 0; i < b_len; ++i )
     257                 :            :                 {
     258         [ +  + ]:     109173 :                 char c1 = islower(b[i]) ? toupper(b[i]) : b[i];
     259         [ +  + ]:     109173 :                 char c2 = islower(t[i]) ? toupper(t[i]) : t[i];
     260                 :            : 
     261         [ +  + ]:     109173 :                 if ( c1 < c2 )
     262                 :      25047 :                         return -1;
     263                 :            : 
     264         [ +  + ]:      84126 :                 if ( c1 > c2 )
     265                 :      25049 :                         return 1;
     266                 :            :                 }
     267                 :            : 
     268                 :      52656 :         return t[i] != '\0';
     269                 :            :         }
     270                 :            : 
     271                 :            : #ifndef HAVE_STRCASESTR
     272                 :            : // This code is derived from software contributed to BSD by Chris Torek.
     273                 :            : char* strcasestr(const char* s, const char* find)
     274                 :            :         {
     275                 :            :         char c = *find++;
     276                 :            :         if ( c )
     277                 :            :                 {
     278                 :            :                 c = tolower((unsigned char) c);
     279                 :            : 
     280                 :            :                 size_t len = strlen(find);
     281                 :            : 
     282                 :            :                 do {
     283                 :            :                         char sc;
     284                 :            :                         do {
     285                 :            :                                 sc = *s++;
     286                 :            :                                 if ( sc == 0 )
     287                 :            :                                         return 0;
     288                 :            :                         } while ( char(tolower((unsigned char) sc)) != c );
     289                 :            :                 } while ( strcasecmp_n(len, s, find) != 0 );
     290                 :            : 
     291                 :            :                 --s;
     292                 :            :                 }
     293                 :            : 
     294                 :            :         return (char*) s;
     295                 :            :         }
     296                 :            : #endif
     297                 :            : 
     298                 :        494 : int atoi_n(int len, const char* s, const char** end, int base, int& result)
     299                 :            :         {
     300                 :        494 :         int n = 0;
     301                 :        494 :         int neg = 0;
     302                 :            : 
     303 [ +  - ][ -  + ]:        494 :         if ( len > 0 && *s == '-' )
     304                 :            :                 {
     305                 :          0 :                 neg = 1;
     306                 :          0 :                 --len; ++s;
     307                 :            :                 }
     308                 :            : 
     309                 :            :         int i;
     310         [ +  + ]:       2091 :         for ( i = 0; i < len; ++i )
     311                 :            :                 {
     312                 :            :                 unsigned int d;
     313                 :            : 
     314         [ +  + ]:       1610 :                 if ( isdigit(s[i]) )
     315                 :       1510 :                         d = s[i] - '0';
     316                 :            : 
     317 [ +  + ][ +  - ]:        100 :                 else if ( s[i] >= 'a' && s[i] < 'a' - 10 + base )
     318                 :         87 :                         d = s[i] - 'a' + 10;
     319                 :            : 
     320 [ -  + ][ #  # ]:         13 :                 else if ( s[i] >= 'A' && s[i] < 'A' - 10 + base )
     321                 :          0 :                         d = s[i] - 'A' + 10;
     322                 :            : 
     323         [ +  - ]:         13 :                 else if ( i > 0 )
     324                 :         13 :                         break;
     325                 :            : 
     326                 :            :                 else
     327                 :          0 :                         return 0;
     328                 :            : 
     329                 :       1597 :                 n = n * base + d;
     330                 :            :                 }
     331                 :            : 
     332         [ -  + ]:        494 :         if ( neg )
     333                 :          0 :                 result = -n;
     334                 :            :         else
     335                 :        494 :                 result = n;
     336                 :            : 
     337         [ -  + ]:        494 :         if ( end )
     338                 :          0 :                 *end = s + i;
     339                 :            : 
     340                 :        494 :         return 1;
     341                 :            :         }
     342                 :            : 
     343                 :            : int strstr_n(const int big_len, const u_char* big,
     344                 :      18039 :                 const int little_len, const u_char* little)
     345                 :            :         {
     346         [ -  + ]:      18039 :         if ( little_len > big_len )
     347                 :          0 :                 return -1;
     348                 :            : 
     349         [ +  + ]:     295442 :         for ( int i = 0; i <= big_len - little_len; ++i )
     350                 :            :                 {
     351         [ +  + ]:     278372 :                 if ( ! memcmp(big + i, little, little_len) )
     352                 :        969 :                         return i;
     353                 :            :                 }
     354                 :            : 
     355                 :      18039 :         return -1;
     356                 :            :         }
     357                 :            : 
     358                 :          0 : int fputs(int len, const char* s, FILE* fp)
     359                 :            :         {
     360         [ #  # ]:          0 :         for ( int i = 0; i < len; ++i )
     361         [ #  # ]:          0 :                 if ( fputc(s[i], fp) == EOF )
     362                 :          0 :                         return EOF;
     363                 :          0 :         return 0;
     364                 :            :         }
     365                 :            : 
     366                 :          0 : bool is_printable(const char* s, int len)
     367                 :            :         {
     368         [ #  # ]:          0 :         while ( --len >= 0 )
     369         [ #  # ]:          0 :                 if ( ! isprint(*s++) )
     370                 :          0 :                         return false;
     371                 :          0 :         return true;
     372                 :            :         }
     373                 :            : 
     374                 :      50345 : const char* fmt_bytes(const char* data, int len)
     375                 :            :         {
     376                 :            :         static char buf[1024];
     377                 :      50345 :         char* p = buf;
     378                 :            : 
     379 [ +  + ][ +  - ]:    1768854 :         for ( int i = 0; i < len && p - buf < int(sizeof(buf)); ++i )
     380                 :            :                 {
     381         [ +  + ]:    1718509 :                 if ( isprint(data[i]) )
     382                 :     903295 :                         *p++ = data[i];
     383                 :            :                 else
     384                 :            :                         p += snprintf(p, sizeof(buf) - (p - buf),
     385                 :     815214 :                                         "\\x%02x", (unsigned char) data[i]);
     386                 :            :                 }
     387                 :            : 
     388         [ +  - ]:      50345 :         if ( p - buf < int(sizeof(buf)) )
     389                 :      50345 :                 *p = '\0';
     390                 :            :         else
     391                 :          0 :                 buf[sizeof(buf) - 1] = '\0';
     392                 :            : 
     393                 :      50345 :         return buf;
     394                 :            :         }
     395                 :            : 
     396                 :      71980 : const char* fmt(const char* format, ...)
     397                 :            :         {
     398                 :            :         static char* buf = 0;
     399                 :            :         static unsigned int buf_len = 1024;
     400                 :            : 
     401         [ +  + ]:      71980 :         if ( ! buf )
     402                 :          3 :                 buf = (char*) malloc(buf_len);
     403                 :            : 
     404                 :            :         va_list al;
     405                 :      71980 :         va_start(al, format);
     406                 :      71980 :         int n = safe_vsnprintf(buf, buf_len, format, al);
     407                 :      71980 :         va_end(al);
     408                 :            : 
     409         [ -  + ]:      71980 :         if ( (unsigned int) n >= buf_len )
     410                 :            :                 { // Not enough room, grow the buffer.
     411                 :          0 :                 buf_len = n + 32;
     412                 :          0 :                 buf = (char*) realloc(buf, buf_len);
     413                 :            : 
     414                 :            :                 // Is it portable to restart?
     415                 :          0 :                 va_start(al, format);
     416                 :          0 :                 n = safe_vsnprintf(buf, buf_len, format, al);
     417                 :          0 :                 va_end(al);
     418                 :            : 
     419         [ #  # ]:          0 :                 if ( (unsigned int) n >= buf_len )
     420                 :          0 :                         internal_error("confusion reformatting in fmt()");
     421                 :            :                 }
     422                 :            : 
     423                 :      71980 :         return buf;
     424                 :            :         }
     425                 :            : 
     426                 :          0 : const char* fmt_access_time(double t)
     427                 :            :         {
     428                 :            :         static char buf[256];
     429                 :          0 :         time_t time = (time_t) t;
     430                 :          0 :         strftime(buf, sizeof(buf), "%d/%m-%H:%M", localtime(&time));
     431                 :          0 :         return buf;
     432                 :            :         }
     433                 :            : 
     434                 :          2 : bool ensure_dir(const char *dirname)
     435                 :            :         {
     436                 :            :         struct stat st;
     437         [ -  + ]:          2 :         if ( stat(dirname, &st) < 0 )
     438                 :            :                 {
     439         [ #  # ]:          0 :                 if ( errno != ENOENT )
     440                 :            :                         {
     441                 :            :                         warn(fmt("can't stat directory %s: %s",
     442                 :          0 :                                 dirname, strerror(errno)));
     443                 :          0 :                         return false;
     444                 :            :                         }
     445                 :            : 
     446         [ #  # ]:          0 :                 if ( mkdir(dirname, 0700) < 0 )
     447                 :            :                         {
     448                 :            :                         warn(fmt("can't create directory %s: %s",
     449                 :          0 :                                 dirname, strerror(errno)));
     450                 :          0 :                         return false;
     451                 :            :                         }
     452                 :            :                 }
     453                 :            : 
     454         [ -  + ]:          2 :         else if ( ! S_ISDIR(st.st_mode) )
     455                 :            :                 {
     456                 :          0 :                 warn(fmt("%s exists but is not a directory", dirname));
     457                 :          0 :                 return false;
     458                 :            :                 }
     459                 :            : 
     460                 :          2 :         return true;
     461                 :            :         }
     462                 :            : 
     463                 :        215 : bool is_dir(const char* path)
     464                 :            :         {
     465                 :            :         struct stat st;
     466         [ -  + ]:        215 :         if ( stat(path, &st) < 0 )
     467                 :            :                 {
     468         [ #  # ]:          0 :                 if ( errno != ENOENT )
     469                 :          0 :                         warn(fmt("can't stat %s: %s", path, strerror(errno)));
     470                 :            : 
     471                 :          0 :                 return false;
     472                 :            :                 }
     473                 :            : 
     474                 :        215 :         return S_ISDIR(st.st_mode);
     475                 :            :         }
     476                 :            : 
     477                 :      46089 : void hash_md5(size_t size, const unsigned char* bytes, unsigned char digest[16])
     478                 :            :         {
     479                 :            :         md5_state_s h;
     480                 :      46089 :         md5_init(&h);
     481                 :      46089 :         md5_append(&h, bytes, size);
     482                 :      46089 :         md5_finish(&h, digest);
     483                 :      46089 :         }
     484                 :            : 
     485                 :          0 : const char* md5_digest_print(const unsigned char digest[16])
     486                 :            :         {
     487                 :            :         static char digest_print[256];
     488                 :            : 
     489         [ #  # ]:          0 :         for ( int i = 0; i < 16; ++i )
     490                 :          0 :                 snprintf(digest_print + i * 2, 3, "%02x", digest[i]);
     491                 :            : 
     492                 :          0 :         return digest_print;
     493                 :            :         }
     494                 :            : 
     495                 :            : int hmac_key_set = 0;
     496                 :            : uint8 shared_hmac_md5_key[16];
     497                 :            : 
     498                 :      23043 : void hmac_md5(size_t size, const unsigned char* bytes, unsigned char digest[16])
     499                 :            :         {
     500         [ -  + ]:      23043 :         if ( ! hmac_key_set )
     501                 :          0 :                 internal_error("HMAC-MD5 invoked before the HMAC key is set");
     502                 :            : 
     503                 :      23043 :         hash_md5(size, bytes, digest);
     504                 :            : 
     505         [ +  + ]:     391731 :         for ( int i = 0; i < 16; ++i )
     506                 :     368688 :                 digest[i] ^= shared_hmac_md5_key[i];
     507                 :            : 
     508                 :      23043 :         hash_md5(16, digest, digest);
     509                 :      23043 :         }
     510                 :            : 
     511                 :            : static bool read_random_seeds(const char* read_file, uint32* seed,
     512                 :          0 :                                 uint32* buf, int bufsiz)
     513                 :            :         {
     514                 :            :         struct stat st;
     515                 :          0 :         FILE* f = 0;
     516                 :            : 
     517         [ #  # ]:          0 :         if ( stat(read_file, &st) < 0 )
     518                 :            :                 {
     519                 :            :                 warn(fmt("Seed file '%s' does not exist: %s",
     520                 :          0 :                                 read_file, strerror(errno)));
     521                 :          0 :                 return false;
     522                 :            :                 }
     523                 :            : 
     524         [ #  # ]:          0 :         if ( ! (f = fopen(read_file, "r")) )
     525                 :            :                 {
     526                 :            :                 warn(fmt("Could not open seed file '%s': %s",
     527                 :          0 :                                 read_file, strerror(errno)));
     528                 :          0 :                 return false;
     529                 :            :                 }
     530                 :            : 
     531                 :            :         // Read seed for srandom().
     532         [ #  # ]:          0 :         if ( fscanf(f, "%u", seed) != 1 )
     533                 :            :                 {
     534                 :          0 :                 fclose(f);
     535                 :          0 :                 return false;
     536                 :            :                 }
     537                 :            : 
     538                 :            :         // Read seeds for MD5.
     539         [ #  # ]:          0 :         for ( int i = 0; i < bufsiz; ++i )
     540                 :            :                 {
     541                 :            :                 int tmp;
     542         [ #  # ]:          0 :                 if ( fscanf(f, "%u", &tmp) != 1 )
     543                 :            :                         {
     544                 :          0 :                         fclose(f);
     545                 :          0 :                         return false;
     546                 :            :                         }
     547                 :            : 
     548                 :          0 :                 buf[i] = tmp;
     549                 :            :                 }
     550                 :            : 
     551                 :          0 :         fclose(f);
     552                 :          0 :         return true;
     553                 :            :         }
     554                 :            : 
     555                 :            : static bool write_random_seeds(const char* write_file, uint32 seed,
     556                 :          0 :                                 uint32* buf, int bufsiz)
     557                 :            :         {
     558                 :          0 :         FILE* f = 0;
     559                 :            : 
     560         [ #  # ]:          0 :         if ( ! (f = fopen(write_file, "w+")) )
     561                 :            :                 {
     562                 :            :                 warn(fmt("Could not create seed file '%s': %s",
     563                 :          0 :                                 write_file, strerror(errno)));
     564                 :          0 :                 return false;
     565                 :            :                 }
     566                 :            : 
     567                 :          0 :         fprintf(f, "%u\n", seed);
     568                 :            : 
     569         [ #  # ]:          0 :         for ( int i = 0; i < bufsiz; ++i )
     570                 :          0 :                 fprintf(f, "%u\n", buf[i]);
     571                 :            : 
     572                 :          0 :         fclose(f);
     573                 :          0 :         return true;
     574                 :            :         }
     575                 :            : 
     576                 :          3 : void init_random_seed(uint32 seed, const char* read_file, const char* write_file)
     577                 :            :         {
     578                 :            :         static const int bufsiz = 16;
     579                 :            :         uint32 buf[bufsiz];
     580                 :          3 :         int pos = 0;    // accumulates entropy
     581                 :          3 :         bool seeds_done = false;
     582                 :            : 
     583         [ -  + ]:          3 :         if ( read_file )
     584                 :            :                 {
     585         [ #  # ]:          0 :                 if ( ! read_random_seeds(read_file, &seed, buf, bufsiz) )
     586                 :            :                         fprintf(stderr, "Could not load seeds from file '%s'.\n",
     587                 :          0 :                                         read_file);
     588                 :            :                 else
     589                 :          0 :                         seeds_done = true;
     590                 :            :                 }
     591                 :            : 
     592         [ +  - ]:          3 :         if ( ! seeds_done )
     593                 :            :                 {
     594                 :            :                 // Gather up some entropy.
     595                 :          3 :                 gettimeofday((struct timeval *)(buf + pos), 0);
     596                 :          3 :                 pos += sizeof(struct timeval) / sizeof(uint32);
     597                 :            : 
     598                 :            : #if defined(O_NONBLOCK)
     599                 :          3 :                 int fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
     600                 :            : #elif defined(O_NDELAY)
     601                 :            :                 int fd = open("/dev/random", O_RDONLY | O_NDELAY);
     602                 :            : #else
     603                 :            :                 int fd = open("/dev/random", O_RDONLY);
     604                 :            : #endif
     605                 :            : 
     606         [ +  - ]:          3 :                 if ( fd >= 0 )
     607                 :            :                         {
     608                 :            :                         int amt = read(fd, buf + pos,
     609                 :          3 :                                         sizeof(uint32) * (bufsiz - pos));
     610                 :          3 :                         close(fd);
     611                 :            : 
     612         [ +  - ]:          3 :                         if ( amt > 0 )
     613                 :          3 :                                 pos += amt / sizeof(uint32);
     614                 :            :                         else
     615                 :            :                                 // Clear errno, which can be set on some
     616                 :            :                                 // systems due to a lack of entropy.
     617                 :          0 :                                 errno = 0;
     618                 :            :                         }
     619                 :            : 
     620         [ -  + ]:          3 :                 if ( pos < bufsiz )
     621                 :            :                         {
     622                 :          0 :                         buf[pos++] = getpid();
     623                 :            : 
     624         [ #  # ]:          0 :                         if ( pos < bufsiz )
     625                 :          0 :                                 buf[pos++] = getuid();
     626                 :            :                         }
     627                 :            : 
     628         [ +  - ]:          3 :                 if ( ! seed )
     629                 :            :                         {
     630         [ +  + ]:         51 :                         for ( int i = 0; i < pos; ++i )
     631                 :            :                                 {
     632                 :         48 :                                 seed ^= buf[i];
     633                 :         48 :                                 seed = (seed << 1) | (seed >> 31);
     634                 :            :                                 }
     635                 :            :                         }
     636                 :            :                 }
     637                 :            : 
     638                 :          3 :         srandom(seed);
     639                 :            : 
     640         [ +  - ]:          3 :         if ( ! hmac_key_set )
     641                 :            :                 {
     642                 :          3 :                 hash_md5(sizeof(buf), (u_char*) buf, shared_hmac_md5_key);
     643                 :          3 :                 hmac_key_set = 1;
     644                 :            :                 }
     645                 :            : 
     646 [ -  + ][ #  # ]:          3 :         if ( write_file && ! write_random_seeds(write_file, seed, buf, bufsiz) )
                 [ -  + ]
     647                 :            :                 fprintf(stderr, "Could not write seeds to file '%s'.\n",
     648                 :          0 :                                 write_file);
     649                 :          3 :         }
     650                 :            : 
     651                 :            : 
     652                 :            : // Returns a 64-bit random string.
     653                 :          0 : uint64 rand64bit()
     654                 :            :         {
     655                 :          0 :         uint64 base = 0;
     656                 :            :         int i;
     657                 :            : 
     658         [ #  # ]:          0 :         for ( i = 1; i <= 4; ++i )
     659                 :          0 :                 base = (base<<16) | random();
     660                 :          0 :         return base;
     661                 :            :         }
     662                 :            : 
     663                 :          0 : void message(const char* msg)
     664                 :            :         {
     665                 :          0 :         pinpoint();
     666                 :          0 :         fprintf(stderr, "%s\n", msg);
     667                 :          0 :         }
     668                 :            : 
     669                 :          0 : void warn(const char* msg)
     670                 :            :         {
     671                 :          0 :         pinpoint();
     672                 :          0 :         fprintf(stderr, "warning: %s\n", msg);
     673                 :          0 :         ++nwarn;
     674                 :          0 :         }
     675                 :            : 
     676                 :          0 : void warn(const char* msg, const char* addl)
     677                 :            :         {
     678                 :          0 :         pinpoint();
     679                 :          0 :         fprintf(stderr, "warning: %s %s\n", msg, addl);
     680                 :          0 :         ++nwarn;
     681                 :          0 :         }
     682                 :            : 
     683                 :          0 : void error(const char* msg)
     684                 :            :         {
     685                 :          0 :         pinpoint();
     686                 :          0 :         fprintf(stderr, "error: %s\n", msg);
     687                 :          0 :         ++nerr;
     688                 :          0 :         }
     689                 :            : 
     690                 :          2 : void error(const char* msg, const char* addl)
     691                 :            :         {
     692                 :          2 :         pinpoint();
     693                 :          2 :         fprintf(stderr, "error: %s %s\n", msg, addl);
     694                 :          2 :         ++nerr;
     695                 :          2 :         }
     696                 :            : 
     697                 :          0 : void error(const char* msg, uint32 addl)
     698                 :            :         {
     699                 :          0 :         pinpoint();
     700                 :          0 :         fprintf(stderr, "error: %s - %u\n", msg, addl);
     701                 :          0 :         ++nerr;
     702                 :          0 :         }
     703                 :            : 
     704                 :          0 : void run_time(const char* msg)
     705                 :            :         {
     706                 :          0 :         pinpoint();
     707                 :          0 :         fprintf(stderr, "run-time error: %s\n", msg);
     708                 :          0 :         ++nruntime;
     709                 :          0 :         }
     710                 :            : 
     711                 :          0 : void run_time(const char* fmt, BroObj* obj)
     712                 :            :         {
     713                 :          0 :         ODesc d;
     714                 :          0 :         obj->Describe(&d);
     715                 :          0 :         run_time(fmt, d.Description());
     716                 :          0 :         }
     717                 :            : 
     718                 :          0 : void run_time(const char* fmt, const char* arg)
     719                 :            :         {
     720                 :          0 :         pinpoint();
     721                 :          0 :         fprintf(stderr, "run-time error: ");
     722                 :          0 :         fprintf(stderr, fmt, arg);
     723                 :          0 :         fprintf(stderr, "\n");
     724                 :          0 :         ++nruntime;
     725                 :          0 :         }
     726                 :            : 
     727                 :          0 : void run_time(const char* fmt, const char* arg1, const char* arg2)
     728                 :            :         {
     729                 :          0 :         pinpoint();
     730                 :          0 :         fprintf(stderr, "run-time error: ");
     731                 :          0 :         fprintf(stderr, fmt, arg1, arg2);
     732                 :          0 :         fprintf(stderr, "\n");
     733                 :          0 :         ++nruntime;
     734                 :          0 :         }
     735                 :            : 
     736                 :          0 : void internal_error(const char* fmt, ...)
     737                 :            :         {
     738                 :            :         va_list al;
     739                 :            : 
     740                 :          0 :         pinpoint();
     741                 :          0 :         fprintf(stderr, "internal error: ");
     742                 :          0 :         va_start(al, fmt);
     743                 :          0 :         vfprintf(stderr, fmt, al);
     744                 :          0 :         va_end(al);
     745                 :          0 :         fprintf(stderr, "\n");
     746                 :          0 :         set_processing_status("TERMINATED", "internal_error");
     747                 :          0 :         abort();
     748                 :            :         }
     749                 :            : 
     750                 :          2 : void pinpoint()
     751                 :            :         {
     752         [ -  + ]:          2 :         if ( network_time > 0.0 )
     753                 :          0 :                 fprintf(stderr, "%.6f ", network_time);
     754                 :            :         else
     755                 :            :                 {
     756         [ -  + ]:          2 :                 if ( filename )
     757                 :          0 :                         fprintf(stderr, "%s, ", filename);
     758                 :          2 :                 fprintf(stderr, "line %d: ", line_number);
     759                 :            :                 }
     760                 :          2 :         }
     761                 :            : 
     762                 :      16792 : int int_list_cmp(const void* v1, const void* v2)
     763                 :            :         {
     764                 :      16792 :         ptr_compat_int i1 = *(ptr_compat_int*) v1;
     765                 :      16792 :         ptr_compat_int i2 = *(ptr_compat_int*) v2;
     766                 :            : 
     767         [ +  + ]:      16792 :         if ( i1 < i2 )
     768                 :       9226 :                 return -1;
     769         [ -  + ]:       7566 :         else if ( i1 == i2 )
     770                 :          0 :                 return 0;
     771                 :            :         else
     772                 :      16792 :                 return 1;
     773                 :            :         }
     774                 :            : 
     775                 :        350 : const char* bro_path()
     776                 :            :         {
     777                 :        350 :         const char* path = getenv("BROPATH");
     778         [ -  + ]:        350 :         if ( ! path )
     779                 :            :                 path = ".:"
     780                 :            :                         POLICYDEST ":"
     781                 :            :                         POLICYDEST "/sigs:" 
     782                 :            :                         POLICYDEST "/time-machine:"
     783                 :          0 :                         POLICYDEST "/site";
     784                 :            : 
     785                 :        350 :         return path;
     786                 :            :         }
     787                 :            : 
     788                 :          0 : const char* bro_prefixes()
     789                 :            :         {
     790                 :          0 :         int len = 1;    // room for \0
     791         [ #  # ]:          0 :         loop_over_list(prefixes, i)
     792                 :          0 :                 len += strlen(prefixes[i]) + 1;
     793                 :            : 
     794                 :          0 :         char* p = new char[len];
     795                 :            : 
     796         [ #  # ]:          0 :         loop_over_list(prefixes, j)
     797         [ #  # ]:          0 :                 if ( j == 0 )
     798                 :          0 :                         strcpy(p, prefixes[j]);
     799                 :            :                 else
     800                 :            :                         {
     801                 :          0 :                         strcat(p, ":");
     802                 :          0 :                         strcat(p, prefixes[j]);
     803                 :            :                         }
     804                 :            : 
     805                 :          0 :         return p;
     806                 :            :         }
     807                 :            : 
     808                 :        215 : FILE* open_file(const char* filename, const char** full_filename)
     809                 :            :         {
     810         [ +  + ]:        215 :         if ( full_filename )
     811                 :        214 :                 *full_filename = copy_string(filename);
     812                 :            : 
     813                 :        215 :         FILE* f = fopen(filename, "r");
     814                 :            : 
     815                 :        215 :         return f;
     816                 :            :         }
     817                 :            : 
     818                 :            : FILE* search_for_file(const char* filename, const char* ext,
     819                 :        350 :                         const char** full_filename)
     820                 :            :         {
     821 [ +  - ][ -  + ]:        350 :         if ( filename[0] == '/' || filename[0] == '.' )
     822                 :          0 :                 return open_file(filename, full_filename);
     823                 :            : 
     824                 :            :         char path[1024], full_filename_buf[1024];
     825                 :        350 :         safe_strncpy(path, bro_path(), sizeof(path));
     826                 :            : 
     827                 :        350 :         char* dir_beginning = path;
     828                 :        350 :         char* dir_ending = path;
     829                 :        350 :         int more = *dir_beginning != '\0';
     830                 :            : 
     831         [ +  + ]:       1692 :         while ( more )
     832                 :            :                 {
     833 [ +  + ][ +  + ]:      45741 :                 while ( *dir_ending && *dir_ending != ':' )
     834                 :      44184 :                         ++dir_ending;
     835                 :            : 
     836         [ +  + ]:       1557 :                 if ( *dir_ending == ':' )
     837                 :       1422 :                         *dir_ending = '\0';
     838                 :            :                 else
     839                 :        135 :                         more = 0;
     840                 :            : 
     841                 :            :                 safe_snprintf(full_filename_buf, sizeof(full_filename_buf),
     842                 :       1557 :                                 "%s/%s.%s", dir_beginning, filename, ext);
     843   [ +  +  +  - ]:       1557 :                 if ( access(full_filename_buf, R_OK) == 0 &&
                 [ +  + ]
     844                 :            :                      ! is_dir(full_filename_buf) )
     845                 :        174 :                         return open_file(full_filename_buf, full_filename);
     846                 :            : 
     847                 :            :                 safe_snprintf(full_filename_buf, sizeof(full_filename_buf),
     848                 :       1383 :                                 "%s/%s", dir_beginning, filename);
     849   [ +  +  +  - ]:       1383 :                 if ( access(full_filename_buf, R_OK) == 0 &&
                 [ +  + ]
     850                 :            :                       ! is_dir(full_filename_buf) )
     851                 :         41 :                         return open_file(full_filename_buf, full_filename);
     852                 :            : 
     853                 :       1342 :                 dir_beginning = ++dir_ending;
     854                 :            :                 }
     855                 :            : 
     856         [ +  + ]:        135 :         if ( full_filename )
     857                 :        134 :                 *full_filename = copy_string(filename);
     858                 :            : 
     859                 :        350 :         return 0;
     860                 :            :         }
     861                 :            : 
     862                 :          0 : FILE* rotate_file(const char* name, RecordVal* rotate_info)
     863                 :            :         {
     864                 :            :         // Build file names.
     865                 :          0 :         const int buflen = strlen(name) + 128;
     866                 :            : 
     867                 :          0 :         char tmpname[buflen], newname[buflen+4];
     868                 :            : 
     869                 :            :         safe_snprintf(newname, buflen, "%s.%d.%.06f.tmp",
     870                 :          0 :                         name, getpid(), network_time);
     871                 :          0 :         newname[buflen-1] = '\0';
     872                 :          0 :         strcpy(tmpname, newname);
     873                 :          0 :         strcat(tmpname, ".tmp");
     874                 :            : 
     875                 :            :         // First open the new file using a temporary name.
     876                 :          0 :         FILE* newf = fopen(tmpname, "w");
     877         [ #  # ]:          0 :         if ( ! newf )
     878                 :            :                 {
     879                 :          0 :                 run_time(fmt("rotate_file: can't open %s: %s", tmpname, strerror(errno)));
     880                 :          0 :                 return 0;
     881                 :            :                 }
     882                 :            : 
     883                 :            :         // Then move old file to "<name>.<pid>.<timestamp>" and make sure
     884                 :            :         // it really gets created.
     885                 :            :         struct stat dummy;
     886 [ #  # ][ #  # ]:          0 :         if ( link(name, newname) < 0 || stat(newname, &dummy) < 0 )
                 [ #  # ]
     887                 :            :                 {
     888                 :          0 :                 run_time(fmt("rotate_file: can't move %s to %s: %s", name, newname, strerror(errno)));
     889                 :          0 :                 fclose(newf);
     890                 :          0 :                 unlink(newname);
     891                 :          0 :                 unlink(tmpname);
     892                 :          0 :                 return 0;
     893                 :            :                 }
     894                 :            : 
     895                 :            :         // Close current file, and move the tmp to its place.
     896 [ #  # ][ #  # ]:          0 :         if ( unlink(name) < 0 || link(tmpname, name) < 0 || unlink(tmpname) < 0 )
         [ #  # ][ #  # ]
     897                 :            :                 {
     898                 :          0 :                 run_time(fmt("rotate_file: can't move %s to %s: %s", tmpname, name, strerror(errno)));
     899                 :          0 :                 exit(1);        // hard to fix, but shouldn't happen anyway...
     900                 :            :                 }
     901                 :            : 
     902                 :            :         // Init rotate_info.
     903         [ #  # ]:          0 :         if ( rotate_info )
     904                 :            :                 {
     905                 :          0 :                 rotate_info->Assign(0, new StringVal(name));
     906                 :          0 :                 rotate_info->Assign(1, new StringVal(newname));
     907                 :          0 :                 rotate_info->Assign(2, new Val(network_time, TYPE_TIME));
     908                 :          0 :                 rotate_info->Assign(3, new Val(network_time, TYPE_TIME));
     909                 :            :                 }
     910                 :            : 
     911                 :          0 :         return newf;
     912                 :            :         }
     913                 :            : 
     914                 :          3 : const char* log_file_name(const char* tag)
     915                 :            :         {
     916                 :          3 :         const char* env = getenv("BRO_LOG_SUFFIX");
     917         [ -  + ]:          3 :         return fmt("%s.%s", tag, (env ? env : "log"));
     918                 :            :         }
     919                 :            : 
     920                 :          0 : double calc_next_rotate(double interval, const char* rotate_base_time)
     921                 :            :         {
     922                 :          0 :         double current = network_time;
     923                 :            : 
     924                 :            :         // Calculate start of day.
     925                 :          0 :         time_t teatime = time_t(current);
     926                 :            : 
     927                 :            :         struct tm t;
     928                 :          0 :         t = *localtime(&teatime);
     929                 :          0 :         t.tm_hour = t.tm_min = t.tm_sec = 0;
     930                 :          0 :         double startofday = mktime(&t);
     931                 :            : 
     932                 :          0 :         double base = -1;
     933                 :            : 
     934   [ #  #  #  # ]:          0 :         if ( rotate_base_time && rotate_base_time[0] != '\0' )
     935                 :            :                 {
     936                 :            :                 struct tm t;
     937         [ #  # ]:          0 :                 if ( ! strptime(rotate_base_time, "%H:%M", &t) )
     938                 :          0 :                         run_time("calc_next_rotate(): can't parse rotation base time");
     939                 :            :                 else
     940                 :          0 :                         base = t.tm_min * 60 + t.tm_hour * 60 * 60;
     941                 :            :                 }
     942                 :            : 
     943         [ #  # ]:          0 :         if ( base < 0 )
     944                 :            :                 // No base time given. To get nice timestamps, we round
     945                 :            :                 // the time up to the next multiple of the rotation interval.
     946                 :            :                 return floor(current / interval) * interval
     947                 :          0 :                         + interval - current;
     948                 :            : 
     949                 :            :         // current < startofday + base + i * interval <= current + interval
     950                 :            :         return startofday + base +
     951                 :            :                 ceil((current - startofday - base) / interval) * interval -
     952                 :          0 :                         current;
     953                 :            :         }
     954                 :            : 
     955                 :            : 
     956                 :            : RETSIGTYPE sig_handler(int signo);
     957                 :            : 
     958                 :          0 : void terminate_processing()
     959                 :            :         {
     960         [ #  # ]:          0 :         if ( ! terminating )
     961                 :          0 :                 sig_handler(SIGTERM);
     962                 :          0 :         }
     963                 :            : 
     964                 :            : extern const char* proc_status_file;
     965                 :         11 : void _set_processing_status(const char* status)
     966                 :            :         {
     967         [ +  - ]:         11 :         if ( ! proc_status_file )
     968                 :         11 :                 return;
     969                 :            : 
     970                 :            :         // This function can be called from a signal context, so we have to
     971                 :            :         // make sure to only call reentrant functions and to restore errno
     972                 :            :         // afterwards.
     973                 :            : 
     974                 :          0 :         int old_errno = errno;
     975                 :            : 
     976                 :          0 :         int fd = open(proc_status_file, O_CREAT | O_WRONLY | O_TRUNC, 0700);
     977                 :            : 
     978                 :          0 :         int len = strlen(status);
     979         [ #  # ]:          0 :         while ( len )
     980                 :            :                 {
     981                 :          0 :                 int n = write(fd, status, len);
     982                 :            : 
     983   [ #  #  #  # ]:          0 :                 if ( n < 0 && errno != EINTR && errno != EAGAIN )
         [ #  # ][ #  # ]
     984                 :            :                         // Ignore errors, as they're too difficult to
     985                 :            :                         // safely report here.
     986                 :          0 :                         break;
     987                 :            : 
     988                 :          0 :                 status += n;
     989                 :          0 :                 len -= n;
     990                 :            :                 }
     991                 :            : 
     992                 :          0 :         close(fd);
     993                 :            : 
     994                 :         11 :         errno = old_errno;
     995                 :            :         }
     996                 :            : 
     997                 :      21464 : double current_time(bool real)
     998                 :            :         {
     999                 :            :         struct timeval tv;
    1000         [ -  + ]:      21464 :         if ( gettimeofday(&tv, 0) < 0 )
    1001                 :          0 :                 internal_error("gettimeofday failed in current_time()");
    1002                 :            : 
    1003                 :      21464 :         double t = double(tv.tv_sec) + double(tv.tv_usec) / 1e6;
    1004                 :            : 
    1005 [ -  + ][ #  # ]:      21464 :         if ( ! pseudo_realtime || real || pkt_srcs.length() == 0 )
         [ #  # ][ +  - ]
    1006                 :      21464 :                 return t;
    1007                 :            : 
    1008                 :            :         // This obviously only works for a single source ...
    1009                 :          0 :         PktSrc* src = pkt_srcs[0];
    1010                 :            : 
    1011         [ #  # ]:          0 :         if ( net_is_processing_suspended() )
    1012                 :          0 :                 return src->CurrentPacketTimestamp();
    1013                 :            : 
    1014                 :            :         // We don't scale with pseudo_realtime here as that would give us a
    1015                 :            :         // jumping real-time.
    1016                 :            :         return src->CurrentPacketTimestamp() +
    1017                 :      21464 :                 (t - src->CurrentPacketWallClock());
    1018                 :            :         }
    1019                 :            : 
    1020                 :          0 : struct timeval double_to_timeval(double t)
    1021                 :            :         {
    1022                 :            :         struct timeval tv;
    1023                 :            : 
    1024                 :          0 :         double t1 = floor(t);
    1025                 :          0 :         tv.tv_sec = int(t1);
    1026                 :          0 :         tv.tv_usec = int((t - t1) * 1e6 + 0.5);
    1027                 :            : 
    1028                 :          0 :         return tv;
    1029                 :            :         }
    1030                 :            : 
    1031                 :          0 : int time_compare(struct timeval* tv_a, struct timeval* tv_b)
    1032                 :            :         {
    1033         [ #  # ]:          0 :         if ( tv_a->tv_sec == tv_b->tv_sec )
    1034                 :          0 :                 return tv_a->tv_usec - tv_b->tv_usec;
    1035                 :            :         else
    1036                 :          0 :                 return tv_a->tv_sec - tv_b->tv_sec;
    1037                 :            :         }
    1038                 :            : 
    1039                 :          0 : void out_of_memory(const char* where)
    1040                 :            :         {
    1041                 :          0 :         fprintf( stderr, "bro: out of memory in %s.\n", where );
    1042                 :          0 :         abort();
    1043                 :            :         }
    1044                 :            : 
    1045                 :          2 : void get_memory_usage(unsigned int* total, unsigned int* malloced)
    1046                 :            :         {
    1047                 :            :         unsigned int ret_total;
    1048                 :            : 
    1049                 :            : #ifdef HAVE_MALLINFO
    1050                 :            :         // For memory, getrusage() gives bogus results on Linux. Grmpf.
    1051                 :            :         struct mallinfo mi = mallinfo();
    1052                 :            : 
    1053                 :            :         if ( malloced )
    1054                 :            :                 *malloced = mi.uordblks;
    1055                 :            : 
    1056                 :            :         ret_total = mi.arena;
    1057                 :            : 
    1058                 :            :         if ( total )
    1059                 :            :                 *total = ret_total;
    1060                 :            : #else
    1061                 :            :         struct rusage r;
    1062                 :          2 :         getrusage(RUSAGE_SELF, &r);
    1063                 :            : 
    1064         [ -  + ]:          2 :         if ( malloced )
    1065                 :          0 :                 *malloced = 0;
    1066                 :            : 
    1067                 :            :         // At least on FreeBSD it's in KB.
    1068                 :          2 :         ret_total = r.ru_maxrss * 1024;
    1069                 :            : 
    1070         [ +  - ]:          2 :         if ( total )
    1071                 :          2 :                 *total = ret_total;
    1072                 :            : #endif
    1073                 :            : 
    1074                 :            :         // return ret_total;
    1075 [ +  - ][ +  - ]:          8 :         }
    1076                 :          3 : 
    1077                 :            : #ifdef malloc
    1078                 :            : 
    1079                 :            : #undef malloc
    1080                 :            : #undef realloc
    1081                 :            : #undef free
    1082                 :            : 
    1083                 :            : extern "C" {
    1084                 :            : void* malloc(size_t);
    1085                 :            : void* realloc(void*, size_t);
    1086                 :            : void free(void*);
    1087                 :            : }
    1088                 :            : 
    1089                 :            : static int malloc_debug = 0;
    1090                 :            : 
    1091                 :            : void* debug_malloc(size_t t)
    1092                 :            :         {
    1093                 :            :         void* v = malloc(t);
    1094                 :            :         if ( malloc_debug )
    1095                 :            :                 printf("%.6f malloc %x %d\n", network_time, v, t);
    1096                 :            :         return v;
    1097                 :            :         }
    1098                 :            : 
    1099                 :            : void* debug_realloc(void* v, size_t t)
    1100                 :            :         {
    1101                 :            :         v = realloc(v, t);
    1102                 :            :         if ( malloc_debug )
    1103                 :            :                 printf("%.6f realloc %x %d\n", network_time, v, t);
    1104                 :            :         return v;
    1105                 :            :         }
    1106                 :            : 
    1107                 :            : void debug_free(void* v)
    1108                 :            :         {
    1109                 :            :         if ( malloc_debug )
    1110                 :            :                 printf("%.6f free %x\n", network_time, v);
    1111                 :            :         free(v);
    1112                 :            :         }
    1113                 :            : 
    1114                 :            : void* operator new(size_t t)
    1115                 :            :         {
    1116                 :            :         void* v = malloc(t);
    1117                 :            :         if ( malloc_debug )
    1118                 :            :                 printf("%.6f new %x %d\n", network_time, v, t);
    1119                 :            :         return v;
    1120                 :            :         }
    1121                 :            : 
    1122                 :            : void* operator new[](size_t t)
    1123                 :            :         {
    1124                 :            :         void* v = malloc(t);
    1125                 :            :         if ( malloc_debug )
    1126                 :            :                 printf("%.6f new[] %x %d\n", network_time, v, t);
    1127                 :            :         return v;
    1128                 :            :         }
    1129                 :            : 
    1130                 :            : void operator delete(void* v)
    1131                 :            :         {
    1132                 :            :         if ( malloc_debug )
    1133                 :            :                 printf("%.6f delete %x\n", network_time, v);
    1134                 :            :         free(v);
    1135                 :            :         }
    1136                 :            : 
    1137                 :            : void operator delete[](void* v)
    1138                 :            :         {
    1139                 :            :         if ( malloc_debug )
    1140                 :            :                 printf("%.6f delete %x\n", network_time, v);
    1141                 :            :         free(v);
    1142                 :            :         }
    1143                 :            : 
    1144                 :            : #endif

Generated by: LCOV version 1.8