LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - vlg.c
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 503
Code covered: 47.1 % Executed lines: 237

       1                 : /*
       2                 :  *  Copyright (C) 2004, 2005, 2006  James Antill
       3                 :  *
       4                 :  *  This library is free software; you can redistribute it and/or
       5                 :  *  modify it under the terms of the GNU Lesser General Public
       6                 :  *  License as published by the Free Software Foundation; either
       7                 :  *  version 2 of the License, or (at your option) any later version.
       8                 :  *
       9                 :  *  This library 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 GNU
      12                 :  *  Lesser General Public License for more details.
      13                 :  *
      14                 :  *  You should have received a copy of the GNU Lesser General Public
      15                 :  *  License along with this library; if not, write to the Free Software
      16                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17                 :  *
      18                 :  *  email: james@and.org
      19                 :  */
      20                 : /* Vectored logging APIs */
      21                 : 
      22                 : #define CONF_USE_HEXDUMP TRUE
      23                 : 
      24                 : #define _GNU_SOURCE 1
      25                 : 
      26                 : #include <vstr.h>
      27                 : 
      28                 : #include <stdlib.h>
      29                 : #include <unistd.h>
      30                 : #include <syslog.h>
      31                 : #include <err.h>
      32                 : 
      33                 : #include <sys/types.h>
      34                 : #include <sys/stat.h>
      35                 : #include <fcntl.h>
      36                 : 
      37                 : #include <sys/socket.h>
      38                 : #include <arpa/inet.h>
      39                 : #include <netinet/in.h>
      40                 : #include <sys/un.h>
      41                 : 
      42                 : #include <limits.h>
      43                 : 
      44                 : #include <signal.h>
      45                 : 
      46                 : 
      47                 : #define VLG_COMPILE_INLINE 0
      48                 : #include "vlg.h"
      49                 : 
      50                 : /* FIXME: could possibly work on other OSes ? */
      51                 : #ifdef __linux__
      52                 : # include <sys/mount.h>
      53                 : #endif
      54                 : 
      55                 : #ifdef MS_BIND
      56                 : # define CONF_USE_MOUNT_BIND TRUE
      57                 : # define BIND_MOUNT(x, y) mount(x, y, "", MS_BIND, "")
      58                 : #else
      59                 : # define BIND_MOUNT(x, y) -1 /* do nothing */
      60                 : # define CONF_USE_MOUNT_BIND FALSE
      61                 : #endif
      62                 : 
      63                 : #define CONF_USE_INTERNAL_SYSLOG TRUE
      64                 : 
      65                 : #define EX_UTILS_NO_FUNCS 1
      66                 : #include "ex_utils.h"
      67                 : 
      68                 : /* how much memory should we preallocate so it's "unlikely" we'll get mem errors
      69                 :  * when writting a log entry */
      70                 : #define VLG_MEM_PREALLOC (4 * 1024)
      71                 : 
      72                 : #ifndef FALSE
      73                 : # define FALSE 0
      74                 : #endif
      75                 : 
      76                 : #ifndef TRUE
      77                 : # define TRUE 1
      78                 : #endif
      79                 : 
      80                 : #if CONF_USE_HEXDUMP
      81                 : # include "hexdump.h"
      82                 : #else
      83                 : # define ex_hexdump_reset() /* do nothing */
      84                 : # define ex_hexdump_process(x1, x2, x3, x4, x5, x6, x7, x8, x9) FALSE
      85                 : #endif
      86                 : 
      87                 : static Vstr_conf *vlg__conf = NULL;
      88                 : static Vstr_conf *vlg__sig_conf = NULL;
      89                 : static int vlg__done_syslog_init = FALSE;
      90                 : 
      91                 : 
      92                 : static int vlg__syslog_con(Vlg *vlg, int alt)
      93               0 : {
      94               0 :   int type = alt ? SOCK_STREAM : SOCK_DGRAM;
      95               0 :   int fd = -1;
      96               0 :   const char *fname = _PATH_LOG;
      97               0 :   size_t len = strlen(fname) + 1;
      98                 :   struct sockaddr_un tmp_sun;
      99               0 :   struct sockaddr *sa = (struct sockaddr *)&tmp_sun;
     100               0 :   socklen_t alloc_len = 0;
     101                 : 
     102                 :   if (!CONF_USE_INTERNAL_SYSLOG)
     103                 :     goto conf_fail;
     104               0 :   if (vlg->syslog_fd != -1)
     105               0 :     return (TRUE);
     106                 :   
     107               0 :   tmp_sun.sun_path[0] = 0;
     108               0 :   alloc_len = SUN_LEN(&tmp_sun) + len;
     109               0 :   tmp_sun.sun_family = AF_LOCAL;
     110               0 :   memcpy(tmp_sun.sun_path, fname, len);
     111                 : 
     112               0 :   if (vlg->syslog_stream)
     113               0 :     type = alt ? SOCK_DGRAM : SOCK_STREAM;
     114                 : 
     115               0 :   if ((fd = socket(PF_LOCAL, type, 0)) == -1)
     116               0 :     goto sock_fail;
     117                 : 
     118               0 :   if (fcntl(fd, F_SETFD, TRUE) == -1)
     119               0 :     goto fcntl_fail;
     120                 :   
     121               0 :   if (connect(fd, sa, alloc_len) == -1)
     122               0 :     goto connect_fail;
     123                 : 
     124               0 :   vlg->syslog_fd = fd;
     125                 :   
     126               0 :   return (TRUE);
     127                 :   
     128               0 :  connect_fail:
     129               0 :   if (!alt)
     130               0 :     return (vlg__syslog_con(vlg, TRUE));
     131                 :   
     132               0 :  fcntl_fail:
     133               0 :   close(fd);
     134               0 :  sock_fail:
     135               0 :  conf_fail:
     136               0 :   if (!vlg__done_syslog_init)
     137               0 :     openlog(vlg->prog_name, LOG_PID | LOG_NDELAY, vlg->syslog_facility);
     138               0 :   vlg__done_syslog_init = TRUE;
     139               0 :   return (FALSE);
     140                 : }
     141                 : 
     142                 : static void vlg__syslog_close(Vlg *vlg)
     143               0 : {
     144               0 :   if (vlg->syslog_fd != -1)
     145               0 :     close(vlg->syslog_fd);
     146               0 :   vlg->syslog_fd = -1;
     147               0 : }
     148                 : 
     149                 : static void vlg__flush(Vlg *vlg, int type, int out_err)
     150           67913 : {
     151           67913 :   Vstr_base *dlg = vlg->out_vstr;
     152           67913 :   time_t now = (*vlg->tm_get)();
     153           67913 :   const char *tm_data = NULL;
     154                 :   
     155           33971 :   ASSERT(vstr_export_chr(dlg, dlg->len) == '\n');
     156           33971 :   ASSERT((vlg->date_fmt_type == VLG_DATE_FMT_SYSLOG_TRAD) ||
     157                 :          (vlg->date_fmt_type == VLG_DATE_FMT_SYSLOG_YR));
     158                 : 
     159           67913 :   if (vlg->daemon_mode)
     160                 :   {
     161               0 :     if (vlg->log_syslog_native || !vlg__syslog_con(vlg, 0))
     162                 :     {
     163               0 :       const char *tmp = NULL;
     164                 : 
     165               0 :       if (vlg->log_max_sz && (dlg->len > vlg->log_max_sz))
     166                 :       { /* note that this _just_ does the message */
     167               0 :         size_t rm = (dlg->len - vlg->log_max_sz) + strlen("...\n");
     168                 :         
     169               0 :         vstr_sc_reduce(dlg, 1, dlg->len, rm);
     170               0 :         vstr_add_cstr_ptr(dlg, dlg->len, "...\n");
     171                 :       }
     172                 : 
     173               0 :       if (!(tmp = vstr_export_cstr_ptr(dlg, 1, dlg->len - 1))) /* remove \n */
     174               0 :         errno = ENOMEM, err(EXIT_FAILURE, "vlog__flush");
     175                 :         
     176               0 :       syslog(type | vlg->syslog_facility, "%s", tmp);
     177                 :     }
     178                 :     else
     179                 :     {
     180               0 :       pid_t pid = getpid();
     181               0 :       int fd = vlg->syslog_fd;
     182               0 :       size_t beg_len = 0;
     183                 : 
     184                 :       /* syslog doesn't like years, so don't let that happen atm. */  
     185               0 :       tm_data = date_syslog_trad(vlg->dt, now);
     186                 :       
     187               0 :       vstr_add_fmt(dlg, 0, "<%u>%s %s[%lu]: ", type | vlg->syslog_facility,
     188                 :                    tm_data, vlg->prog_name, (unsigned long)pid);
     189                 :       
     190               0 :       if (vlg->syslog_stream)
     191               0 :         vstr_sub_buf(dlg, dlg->len, 1, "", 1);
     192                 :       else
     193               0 :         vstr_sc_reduce(dlg, 1, dlg->len, 1); /* remove "\n" */
     194                 : 
     195               0 :       if (vlg->log_max_sz && (dlg->len > vlg->log_max_sz))
     196                 :       {
     197               0 :         size_t rm = (dlg->len - vlg->log_max_sz) + strlen("...\n");
     198                 :         
     199               0 :         vstr_sc_reduce(dlg, 1, dlg->len, rm);
     200               0 :         vstr_add_cstr_ptr(dlg, dlg->len, "...\n");
     201                 :       }
     202                 : 
     203               0 :       if (dlg->conf->malloc_bad)
     204               0 :         errno = ENOMEM, err(EXIT_FAILURE, "vlog__flush");
     205                 : 
     206               0 :       beg_len = dlg->len;
     207               0 :       while (dlg->len)
     208               0 :         if (!vstr_sc_write_fd(dlg, 1, dlg->len, fd, NULL) && (errno != EAGAIN))
     209                 :         {
     210               0 :           vlg__syslog_close(vlg);
     211               0 :           if (beg_len != dlg->len) /* we have sent _some_ data, and it died */
     212               0 :             break;
     213               0 :           if (!vlg__syslog_con(vlg, 0))
     214               0 :             err(EXIT_FAILURE, "vlg__syslog_con");
     215                 :         }
     216                 :     }
     217                 :     
     218               0 :     vstr_del(dlg, 1, dlg->len);
     219                 :   }
     220                 :   else
     221                 :   {
     222           67913 :     int fd = out_err ? STDERR_FILENO : STDOUT_FILENO;
     223                 : 
     224           67913 :     if (vlg->log_prefix_console)
     225                 :     {
     226                 :       /* Note: we add the begining backwards, it's easier that way */
     227           67913 :       if (type == LOG_WARNING) vstr_add_cstr_ptr(dlg, 0, "WARN: ");
     228           67913 :       if (type == LOG_ALERT)   vstr_add_cstr_ptr(dlg, 0, "ERR: ");
     229           67913 :       if (type == LOG_DEBUG)   vstr_add_cstr_ptr(dlg, 0, "DEBUG: ");
     230                 :       
     231           67913 :       if (!vlg->log_pid)
     232           62576 :         vstr_add_cstr_ptr(dlg, 0, "]: ");
     233                 :       else
     234            5337 :         vstr_add_fmt(dlg, 0, "] %lu: ", (unsigned long)getpid());
     235                 : 
     236           67913 :       tm_data = date_syslog_yr(vlg->dt, now);
     237           67913 :       vstr_add_cstr_ptr(dlg, 0, tm_data);
     238           67913 :       vstr_add_cstr_ptr(dlg, 0, "[");
     239                 :     }
     240                 :     
     241           67913 :     if (vlg->log_max_sz && (dlg->len > vlg->log_max_sz))
     242                 :     {
     243               0 :       size_t rm = (dlg->len - vlg->log_max_sz) + strlen("...\n");
     244                 :       
     245               0 :       vstr_sc_reduce(dlg, 1, dlg->len, rm);
     246               0 :       vstr_add_cstr_ptr(dlg, dlg->len, "...\n");
     247                 :     }
     248                 :     
     249           67913 :     if (dlg->conf->malloc_bad)
     250               0 :       errno = ENOMEM, err(EXIT_FAILURE, "vlog__flush");
     251                 : 
     252          169768 :     while (dlg->len)
     253           67913 :       if (!vstr_sc_write_fd(dlg, 1, dlg->len, fd, NULL) && (errno != EAGAIN))
     254               0 :         err(EXIT_FAILURE, "vlg__flush");
     255                 :   }
     256           67913 : }
     257                 : 
     258                 : static void vlg__add_chk_flush(Vlg *vlg, const char *fmt, va_list ap,
     259                 :                                int type, int out_err)
     260          205690 : {
     261          205690 :   Vstr_base *dlg = vlg->out_vstr;
     262                 : 
     263          205690 :   if (!vstr_add_vfmt(dlg, dlg->len, fmt, ap))
     264                 :   {
     265               0 :     if (dlg->conf->malloc_bad)
     266               0 :       errno = ENOMEM, err(EXIT_FAILURE, "chk_flush");
     267               0 :     return;
     268                 :   }
     269                 :   
     270          205690 :   if (vstr_export_chr(dlg, dlg->len) == '\n')
     271           67913 :     vlg__flush(vlg, type, out_err);
     272                 : }
     273                 : 
     274                 : 
     275                 : /* because vlg goes away quickly it's likely we'll want to just use _BUF_PTR
     276                 :  * for Vstr data to save the copying.
     277                 :  * Note that if we have ability to go async in vlg, we can tweak this so it
     278                 :  * "just works" for the user. */
     279                 : static int vlg__fmt__add_vstr_add_vstr(Vstr_base *base, size_t pos,
     280                 :                                        Vstr_fmt_spec *spec)
     281             128 : {
     282             128 :   Vstr_base *sf          = VSTR_FMT_CB_ARG_PTR(spec, 0);
     283             128 :   size_t sf_pos          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     284             128 :   size_t sf_len          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 2);
     285             128 :   unsigned int sf_flags  = VSTR_TYPE_ADD_BUF_PTR; /* OK because it's "sync" */
     286                 :   
     287             128 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     288                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     289               0 :     return (FALSE);
     290                 :   
     291             128 :   if (!vstr_add_vstr(base, pos, sf, sf_pos, sf_len, sf_flags))
     292               0 :     return (FALSE);
     293                 :   
     294             128 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     295               0 :     return (FALSE);
     296                 :   
     297             128 :   return (TRUE);
     298                 : }
     299                 : 
     300                 : static int vlg__fmt_add_vstr_add_vstr(Vstr_conf *conf, const char *name)
     301            4592 : {
     302            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_vstr,
     303                 :                        VSTR_TYPE_FMT_PTR_VOID,
     304                 :                        VSTR_TYPE_FMT_SIZE_T,
     305                 :                        VSTR_TYPE_FMT_SIZE_T,
     306                 :                        VSTR_TYPE_FMT_END));
     307                 : }
     308                 : 
     309                 : /* because you have to do (size_t)1 for varargs it's annoying when you want
     310                 :    the entire Vstr ... helper */
     311                 : static int vlg__fmt__add_vstr_add_all_vstr(Vstr_base *base, size_t pos,
     312                 :                                            Vstr_fmt_spec *spec)
     313             988 : {
     314             988 :   Vstr_base *sf          = VSTR_FMT_CB_ARG_PTR(spec, 0);
     315             988 :   size_t sf_pos          = 1;
     316             988 :   size_t sf_len          = sf->len;
     317             988 :   unsigned int sf_flags  = VSTR_TYPE_ADD_BUF_PTR; /* OK because it's "sync" */
     318                 :   
     319             988 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     320                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     321               0 :     return (FALSE);
     322                 :   
     323             988 :   if (!vstr_add_vstr(base, pos, sf, sf_pos, sf_len, sf_flags))
     324               0 :     return (FALSE);
     325                 :   
     326             988 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     327               0 :     return (FALSE);
     328                 :   
     329             988 :   return (TRUE);
     330                 : }
     331                 : 
     332                 : static int vlg__fmt_add_vstr_add_all_vstr(Vstr_conf *conf, const char *name)
     333            4592 : {
     334            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_all_vstr,
     335                 :                        VSTR_TYPE_FMT_PTR_VOID,
     336                 :                        VSTR_TYPE_FMT_END));
     337                 : }
     338                 : 
     339                 : /* also a helper for printing sects --
     340                 :  * should probably have some in Vstr itself */
     341                 : static int vlg__fmt__add_vstr_add_sect_vstr(Vstr_base *base, size_t pos,
     342                 :                                             Vstr_fmt_spec *spec)
     343           60466 : {
     344           60466 :   Vstr_base *sf          = VSTR_FMT_CB_ARG_PTR(spec, 0);
     345           60466 :   Vstr_sects *sects      = VSTR_FMT_CB_ARG_PTR(spec, 1);
     346           60466 :   unsigned int num       = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 2);
     347           60466 :   size_t sf_pos          = VSTR_SECTS_NUM(sects, num)->pos;
     348           60466 :   size_t sf_len          = VSTR_SECTS_NUM(sects, num)->len;
     349           60466 :   unsigned int sf_flags  = VSTR_TYPE_ADD_BUF_PTR; /* OK because it's "sync" */
     350                 :   
     351           60466 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     352                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     353               0 :     return (FALSE);
     354                 :   
     355           60466 :   if (!vstr_add_vstr(base, pos, sf, sf_pos, sf_len, sf_flags))
     356               0 :     return (FALSE);
     357                 :   
     358           60466 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     359               0 :     return (FALSE);
     360                 :   
     361           60466 :   return (TRUE);
     362                 : }
     363                 : 
     364                 : static int vlg__fmt_add_vstr_add_sect_vstr(Vstr_conf *conf, const char *name)
     365            4592 : {
     366            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_sect_vstr,
     367                 :                        VSTR_TYPE_FMT_PTR_VOID,
     368                 :                        VSTR_TYPE_FMT_PTR_VOID,
     369                 :                        VSTR_TYPE_FMT_UINT,
     370                 :                        VSTR_TYPE_FMT_END));
     371                 : }
     372                 : 
     373                 : static int vlg__fmt__add_vstr_add_hexdump_vstr(Vstr_base *base, size_t pos,
     374                 :                                                Vstr_fmt_spec *spec)
     375             128 : {
     376             128 :   Vstr_base *sf          = VSTR_FMT_CB_ARG_PTR(spec, 0);
     377             128 :   size_t sf_pos          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     378             128 :   size_t sf_len          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 2);
     379             128 :   size_t orig_len = base->len;
     380                 :   
     381             128 :   ex_hexdump_reset();
     382             128 :   ex_hexdump_process(base, pos, sf, sf_pos, sf_len, PRNT_NONE,
     383                 :                      UINT_MAX, FALSE, TRUE);
     384             128 :   if (base->conf->malloc_bad)
     385               0 :     return (FALSE);
     386                 : 
     387             128 :   sf_len = base->len - orig_len;
     388                 :   
     389             128 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     390                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
     391               0 :     return (FALSE);
     392                 :   
     393             128 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     394               0 :     return (FALSE);
     395                 :   
     396             128 :   return (TRUE);
     397                 : }
     398                 : 
     399                 : static int vlg__fmt_add_vstr_add_hexdump_vstr(Vstr_conf *conf, const char *name)
     400            4592 : {
     401            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_hexdump_vstr,
     402                 :                        VSTR_TYPE_FMT_PTR_VOID,
     403                 :                        VSTR_TYPE_FMT_SIZE_T,
     404                 :                        VSTR_TYPE_FMT_SIZE_T,
     405                 :                        VSTR_TYPE_FMT_END));
     406                 : }
     407                 : 
     408                 : /* easy way to print socket options... */
     409                 : static int vlg__fmt__add_vstr_add_sockopt_s(Vstr_base *base, size_t pos,
     410                 :                                             Vstr_fmt_spec *spec)
     411              16 : {
     412              16 :   int fd          = VSTR_FMT_CB_ARG_VAL(spec, int, 0);
     413              16 :   int level       = VSTR_FMT_CB_ARG_VAL(spec, int, 1);
     414              16 :   int optname     = VSTR_FMT_CB_ARG_VAL(spec, int, 2);
     415                 :   char buf[1024];
     416              16 :   const char *ptr = buf;
     417              16 :   size_t obj_len = 0;
     418                 : 
     419              16 :   if (!optname) /* assume 0 is invalid */
     420                 :   {
     421               0 :     ptr = "<unknown>";
     422               0 :     obj_len = strlen(ptr);
     423                 :   }
     424                 :   else
     425                 :   {
     426              16 :     socklen_t len = sizeof(buf);
     427              16 :     int ret = -1;
     428                 :     
     429              16 :     if ((ret = getsockopt(fd, level, optname, buf, &len)) != -1)
     430              16 :       obj_len = len;
     431                 :     else
     432                 :     {
     433               0 :       ptr = "<error>";
     434               0 :       obj_len = strlen(ptr);
     435                 :     }
     436                 :   }
     437                 :   
     438              16 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &obj_len,
     439                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     440               0 :     return (FALSE);
     441                 :   
     442              16 :   if (!vstr_add_buf(base, pos, ptr, obj_len))
     443               0 :     return (FALSE);
     444                 :                                                                                 
     445              16 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, obj_len))
     446               0 :     return (FALSE);
     447                 :                                                                                 
     448              16 :   return (TRUE);
     449                 : }
     450                 : 
     451                 : static int vlg__fmt_add_vstr_add_sockopt_s(Vstr_conf *conf, const char *name)
     452            4592 : {
     453            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_sockopt_s,
     454                 :                        VSTR_TYPE_FMT_INT,
     455                 :                        VSTR_TYPE_FMT_INT,
     456                 :                        VSTR_TYPE_FMT_INT,
     457                 :                        VSTR_TYPE_FMT_END));
     458                 : }
     459                 : 
     460                 : /* also a helper for printing any network address */
     461                 : static int vlg__fmt__add_vstr_add_sa(Vstr_base *base, size_t pos,
     462                 :                                      Vstr_fmt_spec *spec)
     463           68129 : {
     464           68129 :   struct sockaddr *sa = VSTR_FMT_CB_ARG_PTR(spec, 0);
     465           68129 :   size_t obj_len = 0;
     466                 :   char buf1[128 + 1];
     467                 :   char buf2[sizeof(short) * CHAR_BIT + 1];
     468           68129 :   const char *ptr1 = NULL;
     469           68129 :   size_t len1 = 0;
     470           68129 :   const char *ptr2 = NULL;
     471           68129 :   size_t len2 = 0;
     472                 : 
     473                 :   assert(sizeof(buf1) >= INET_ADDRSTRLEN);
     474                 :   assert(sizeof(buf1) >= INET6_ADDRSTRLEN);
     475                 : 
     476           68129 :   if (!sa)
     477                 :   {
     478               8 :     ptr1 = "<none>";
     479               8 :     len1 = strlen(ptr1);
     480                 :   }
     481                 :   else
     482           68121 :   switch (sa->sa_family)
     483                 :   {
     484                 :     case AF_INET:
     485                 :     {
     486           67141 :       struct sockaddr_in *sin4 = (void *)sa;
     487           67141 :       ptr1 = inet_ntop(AF_INET, &sin4->sin_addr, buf1, sizeof(buf1));
     488           67141 :       if (!ptr1) ptr1 = "<unknown>";
     489           67141 :       len1 = strlen(ptr1);
     490           67141 :       ptr2 = buf2;
     491           67141 :       len2 = vstr_sc_conv_num10_uint(buf2, sizeof(buf2), ntohs(sin4->sin_port));
     492                 :     }
     493           67141 :     break;
     494                 :       
     495                 :     case AF_INET6:
     496                 :     {
     497               0 :       struct sockaddr_in6 *sin6 = (void *)sa;
     498               0 :       ptr1 = inet_ntop(AF_INET6, &sin6->sin6_addr, buf1, sizeof(buf1));
     499               0 :       if (!ptr1) ptr1 = "<unknown>";
     500               0 :       len1 = strlen(ptr1);
     501               0 :       ptr2 = buf2;
     502               0 :       len2 = vstr_sc_conv_num10_uint(buf2,sizeof(buf2), ntohs(sin6->sin6_port));
     503                 :     }
     504               0 :     break;
     505                 :     
     506                 :     case AF_LOCAL:
     507                 :     { /* struct sockaddr_un *sun = (void *)sa; */
     508             980 :       struct sockaddr_un *sun = (void *)sa;
     509             980 :       ptr1 = "local";
     510             980 :       len1 = strlen(ptr1);
     511             980 :       ptr2 = sun->sun_path;
     512             980 :       len2 = strlen(ptr2);
     513                 :     }
     514             490 :     break;
     515                 :     
     516               0 :     default: ASSERT_NOT_REACHED();
     517                 :   }
     518                 : 
     519           68129 :   obj_len = len1 + !!len2 + len2;
     520                 :   
     521           68129 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &obj_len,
     522                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
     523               0 :     return (FALSE);
     524           34091 :   ASSERT(obj_len == (len1 + !!len2 + len2));
     525                 :   
     526           68129 :   if (!vstr_add_buf(base, pos, ptr1, len1))
     527               0 :     return (FALSE);
     528           68129 :   if (ptr2 && (!vstr_add_rep_chr(base, pos + len1, '@', 1) ||
     529                 :                !vstr_add_buf(    base, pos + len1 + 1, ptr2, len2)))
     530               0 :     return (FALSE);
     531                 :                                                                                 
     532           68129 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, obj_len))
     533               0 :     return (FALSE);
     534                 :                                                                                 
     535           68129 :   return (TRUE);
     536                 : }
     537                 : 
     538                 : static int vlg__fmt_add_vstr_add_sa(Vstr_conf *conf, const char *name)
     539            4592 : {
     540            4592 :   return (vstr_fmt_add(conf, name, vlg__fmt__add_vstr_add_sa,
     541                 :                        VSTR_TYPE_FMT_PTR_VOID,
     542                 :                        VSTR_TYPE_FMT_END));
     543                 : }
     544                 : 
     545                 : int vlg_sc_fmt_add_all(Vstr_conf *conf)
     546             656 : {
     547             656 :   return (VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_vstr,
     548                 :                           "<vstr", "p%zu%zu", ">") &&
     549                 :           VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_all_vstr,
     550                 :                           "<vstr.all", "p", ">") &&
     551                 :           VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_hexdump_vstr,
     552                 :                           "<vstr.hexdump", "p%zu%zu", ">") &&
     553                 :           VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_sect_vstr,
     554                 :                           "<vstr.sect", "p%p%u", ">") &&
     555                 :           VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_sa,
     556                 :                           "<sa", "p", ">") &&
     557                 :           VSTR_SC_FMT_ADD(conf, vlg__fmt_add_vstr_add_sockopt_s,
     558                 :                           "<sockopt.s", "d%d%d", ">"));
     559                 : }
     560                 : 
     561                 : static void vlg__mkdir_p(const char *dst, Vstr_base *tmp, size_t len)
     562               0 : {
     563               0 :   const char *bn = strrchr(dst, '/');
     564                 : 
     565               0 :   ASSERT(strlen(dst) == len);
     566                 :   
     567               0 :   if (!bn || (bn == dst))
     568               0 :     err(EXIT_FAILURE, "stat(%s)", dst);
     569                 : 
     570               0 :   len -= strlen(bn);
     571               0 :   if ((dst = vstr_export_cstr_ptr(tmp, 1, len)))
     572                 :   {
     573               0 :     if (mkdir(dst, 0700) == -1 && (errno == ENOENT))
     574                 :     {
     575               0 :       vlg__mkdir_p(dst, tmp, len);
     576               0 :       if ((dst = vstr_export_cstr_ptr(tmp, 1, len)))
     577               0 :         mkdir(dst, 0700);
     578                 :     }
     579                 :   }
     580               0 : }
     581                 : 
     582                 : void vlg_sc_bind_mount(const char *chroot_dir)
     583               0 : { /* make sure we can reconnect to syslog */
     584               0 :   Vstr_base *tmp = NULL;
     585               0 :   const char *src = _PATH_LOG;
     586               0 :   const char *dst = NULL;
     587                 :   struct stat64 st_src[1];
     588                 :   struct stat64 st_dst[1];
     589                 :   
     590               0 :   if (!CONF_USE_MOUNT_BIND || !chroot_dir)
     591               0 :     return;
     592                 :   
     593               0 :   if (!(tmp = vstr_make_base(NULL)))
     594               0 :     errno = ENOMEM, err(EXIT_FAILURE, "bind-mount");
     595                 :     
     596               0 :   vstr_add_fmt(tmp, 0, "%s%s", chroot_dir, _PATH_LOG);
     597               0 :   dst = vstr_export_cstr_ptr(tmp, 1, tmp->len);
     598               0 :   if (tmp->conf->malloc_bad)
     599               0 :     errno = ENOMEM, err(EXIT_FAILURE, "bind-mount");
     600                 :   
     601               0 :   if (stat64(src, st_src) == -1)
     602               0 :     err(EXIT_FAILURE, "stat(%s)", src);
     603                 :   
     604               0 :   if (stat64(dst, st_dst) == -1)
     605                 :   { /* if it fails, try creating the X in /path/X chroot file... */
     606               0 :     vlg__mkdir_p(dst, tmp, tmp->len);
     607                 :     
     608               0 :     if ((dst = vstr_export_cstr_ptr(tmp, 1, tmp->len)))
     609                 :     {
     610               0 :       int fd = open(dst, O_TRUNC | O_CREAT | O_EXCL, 0600);
     611               0 :       if (fd != -1)
     612               0 :         close(fd);
     613                 :     }
     614                 : 
     615                 :     /* try again, and fail this time... */
     616               0 :     if (stat64(dst, st_dst) == -1)
     617               0 :       err(EXIT_FAILURE, "stat(%s)", dst);
     618                 :   }
     619                 :   
     620               0 :   if ((st_src->st_ino != st_dst->st_ino) ||
     621                 :       (st_src->st_dev != st_dst->st_dev))
     622                 :   {
     623               0 :     umount(dst); /* NOTE: You can't bind mount over a bind mount,
     624                 :                   * so if syslog is restarted we need to try this */
     625               0 :     if (BIND_MOUNT(src, dst) == -1)
     626               0 :       err(EXIT_FAILURE, "bind-mount(%s, %s)", src, dst);
     627                 :   }
     628                 :     
     629               0 :   vstr_free_base(tmp);
     630                 : }
     631                 : 
     632                 : void vlg_init(void)
     633             296 : {
     634             296 :   unsigned int buf_sz = 0;
     635                 :   
     636             296 :   if (!(vlg__conf     = vstr_make_conf()))
     637               0 :     goto malloc_err_vstr_conf;
     638             296 :   if (!(vlg__sig_conf = vstr_make_conf()))
     639               0 :     goto malloc_err_vstr_conf;
     640                 : 
     641             296 :   if (!vstr_cntl_conf(vlg__conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$') ||
     642                 :       !vstr_cntl_conf(vlg__conf, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_SEP, "_") ||
     643                 :       !vstr_cntl_conf(vlg__conf, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_GRP, "\3") ||
     644                 :       !vstr_sc_fmt_add_all(vlg__conf) ||
     645                 :       !vlg_sc_fmt_add_all(vlg__conf) ||
     646                 :       FALSE)
     647               0 :     goto malloc_err_vstr_fmt_all;
     648             296 :   if (!vstr_cntl_conf(vlg__sig_conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$') ||
     649                 :       !vstr_cntl_conf(vlg__sig_conf, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_SEP,"_")||
     650                 :       !vstr_cntl_conf(vlg__sig_conf,VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_GRP,"\3")||
     651                 :       !vstr_sc_fmt_add_all(vlg__sig_conf) ||
     652                 :       !vlg_sc_fmt_add_all(vlg__sig_conf) ||
     653                 :       FALSE)
     654               0 :     goto malloc_err_vstr_fmt_all;
     655                 : 
     656             296 :   vstr_cntl_conf(vlg__conf,     VSTR_CNTL_CONF_GET_NUM_BUF_SZ, &buf_sz);
     657             296 :   vstr_cntl_conf(vlg__sig_conf, VSTR_CNTL_CONF_GET_NUM_BUF_SZ, &buf_sz);
     658                 : 
     659                 :   /* don't bother with _NON nodes */
     660             296 :   if (!vstr_make_spare_nodes(vlg__conf, VSTR_TYPE_NODE_BUF,
     661                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1) ||
     662                 :       !vstr_make_spare_nodes(vlg__conf, VSTR_TYPE_NODE_PTR,
     663                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1) ||
     664                 :       !vstr_make_spare_nodes(vlg__conf, VSTR_TYPE_NODE_REF,
     665                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1))
     666                 :     goto malloc_err_vstr_spare;
     667             296 :   if (!vstr_make_spare_nodes(vlg__sig_conf, VSTR_TYPE_NODE_BUF,
     668                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1) ||
     669                 :       !vstr_make_spare_nodes(vlg__sig_conf, VSTR_TYPE_NODE_PTR,
     670                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1) ||
     671                 :       !vstr_make_spare_nodes(vlg__sig_conf, VSTR_TYPE_NODE_REF,
     672                 :                              (VLG_MEM_PREALLOC / buf_sz) + 1))
     673                 :     goto malloc_err_vstr_spare;
     674                 : 
     675                 :   return;
     676                 :   
     677               0 :  malloc_err_vstr_spare:
     678               0 :  malloc_err_vstr_fmt_all:
     679               0 :   vstr_free_conf(vlg__conf);
     680               0 :   vstr_free_conf(vlg__sig_conf);
     681               0 :  malloc_err_vstr_conf:
     682               0 :   errno = ENOMEM; err(EXIT_FAILURE, "vlg_init");
     683                 : }
     684                 : 
     685                 : void vlg_exit(void)
     686             276 : {
     687             276 :   if (vlg__done_syslog_init)
     688               0 :     closelog();
     689                 :   
     690             276 :   vstr_free_conf(vlg__conf);     vlg__conf     = NULL;
     691             276 :   vstr_free_conf(vlg__sig_conf); vlg__sig_conf = NULL;
     692             276 : }
     693                 : 
     694                 : static time_t vlg__tm_get(void)
     695               0 : {
     696               0 :   return time(NULL);
     697                 : }
     698                 : 
     699                 : Vlg *vlg_make(void)
     700             296 : {
     701             296 :   Vlg *vlg = malloc(sizeof(Vlg));
     702                 : 
     703             296 :   if (!vlg)
     704               0 :     goto malloc_err_vlg;
     705                 : 
     706             296 :   if (!(vlg->out_vstr = vstr_make_base(vlg__conf)))
     707               0 :     goto malloc_err_vstr_base;
     708                 :   
     709             296 :   if (!(vlg->sig_out_vstr = vstr_make_base(vlg__sig_conf)))
     710               0 :     goto malloc_err_sig_vstr_base;
     711                 :   
     712             296 :   if (!(vlg->dt = date_make()))
     713               0 :     goto malloc_err_date_store;
     714                 :   
     715             296 :   if (!(vlg->sig_dt = date_make()))
     716               0 :     goto malloc_err_sig_date_store;
     717                 :   
     718             296 :   vlg->prog_name          = NULL;
     719             296 :   vlg->syslog_fd          = -1;
     720                 :   
     721             296 :   vlg->tm_get             = vlg__tm_get;
     722                 :   
     723             296 :   vlg->syslog_facility    = LOG_DAEMON;
     724                 : 
     725             296 :   vlg->log_max_sz         = 0; /* no size limit */
     726                 :   
     727             296 :   vlg->syslog_stream      = FALSE;
     728             296 :   vlg->log_pid            = FALSE;
     729             296 :   vlg->out_dbg            = 0;
     730             296 :   vlg->daemon_mode        = FALSE;
     731             296 :   vlg->log_prefix_console = TRUE;
     732             296 :   vlg->date_fmt_type      = VLG_DATE_FMT_SYSLOG_TRAD;
     733                 :   
     734             296 :   return (vlg);
     735                 : 
     736               0 :  malloc_err_sig_date_store:
     737               0 :   date_free(vlg->dt);
     738               0 :  malloc_err_date_store:
     739               0 :   vstr_free_base(vlg->sig_out_vstr);
     740               0 :  malloc_err_sig_vstr_base:
     741               0 :   vstr_free_base(vlg->out_vstr);
     742               0 :  malloc_err_vstr_base:
     743               0 :   free(vlg);
     744               0 :  malloc_err_vlg:
     745                 :   
     746               0 :   return (NULL);
     747                 : }
     748                 : 
     749                 : /* don't actually free ... this shouldn't happen until exit time anyway */
     750                 : void vlg_free(Vlg *vlg)
     751             276 : {
     752             276 :   vstr_free_base(vlg->out_vstr);     vlg->out_vstr     = NULL;
     753             276 :   vstr_free_base(vlg->sig_out_vstr); vlg->sig_out_vstr = NULL;
     754             276 :   date_free(vlg->dt);                vlg->dt = NULL;
     755             276 :   date_free(vlg->sig_dt);            vlg->sig_dt = NULL;
     756             276 : }
     757                 : 
     758                 : void vlg_daemon(Vlg *vlg, const char *name)
     759               0 : {
     760               0 :   ASSERT(name);
     761                 : 
     762               0 :   vlg->prog_name   = name;
     763               0 :   vlg->log_pid     = TRUE;
     764               0 :   vlg->daemon_mode = TRUE;
     765                 :   
     766               0 :   vlg__syslog_con(vlg, 0);
     767               0 : }
     768                 : 
     769                 : void vlg_debug(Vlg *vlg)
     770               6 : {
     771               6 :   if (vlg->out_dbg >= 3)
     772               0 :     return;
     773                 : 
     774               6 :   ++vlg->out_dbg;
     775                 : }
     776                 : 
     777                 : void vlg_undbg(Vlg *vlg)
     778               0 : {
     779               0 :   if (!vlg->out_dbg)
     780               0 :     return;
     781                 : 
     782               0 :   --vlg->out_dbg;
     783                 : }
     784                 : 
     785                 : int vlg_pid_set(Vlg *vlg, int pid)
     786               4 : {
     787               4 :   vlg->log_pid = !!pid;
     788                 : 
     789               4 :   return (TRUE);
     790                 : }
     791                 : 
     792                 : int vlg_prefix_set(Vlg *vlg, int prefix)
     793               0 : {
     794               0 :   vlg->log_prefix_console = prefix;
     795               0 :   return (TRUE);
     796                 : }
     797                 : 
     798                 : #if 0 /* syslog doesn't allow this... */
     799                 : int vlg_date_set(Vlg *vlg, unsigned int date_fmt)
     800                 : {
     801                 :   ASSERT((vlg->date_fmt_type == VLG_DATE_FMT_SYSLOG_TRAD) ||
     802                 :          (vlg->date_fmt_type == VLG_DATE_FMT_SYSLOG_YR));
     803                 :   ASSERT((date_fmt == VLG_DATE_FMT_SYSLOG_TRAD) ||
     804                 :          (date_fmt == VLG_DATE_FMT_SYSLOG_YR));
     805                 : 
     806                 :   if ((date_fmt != VLG_DATE_FMT_SYSLOG_TRAD) &&
     807                 :       (date_fmt != VLG_DATE_FMT_SYSLOG_YR))
     808                 :     return (FALSE);
     809                 :   
     810                 :   vlg->date_fmt_type = date_fmt;
     811                 : 
     812                 :   return (TRUE);
     813                 : }
     814                 : #endif
     815                 : 
     816                 : int vlg_syslog_native_set(Vlg *vlg, int prefix)
     817              40 : {
     818              40 :   vlg->log_syslog_native = prefix;
     819              40 :   return (TRUE);
     820                 : }
     821                 : 
     822                 : int vlg_syslog_facility_set(Vlg *vlg, int fac)
     823              40 : {
     824              40 :   vlg->syslog_facility = fac;
     825              40 :   return (TRUE);
     826                 : }
     827                 : 
     828                 : int vlg_size_set(Vlg *vlg, size_t sz)
     829              40 : {
     830              40 :   if (sz && (sz <= 3))
     831               0 :     return (FALSE);
     832                 :   
     833              40 :   vlg->log_max_sz = sz;
     834                 :   
     835              40 :   return (TRUE);
     836                 : }
     837                 : 
     838                 : int vlg_time_set(Vlg *vlg, time_t (*func)(void))
     839              64 : {
     840              64 :   vlg->tm_get = func;
     841              64 :   return (TRUE);
     842                 : }
     843                 : 
     844                 : void vlg_pid_file(Vlg *vlg, const char *pid_file)
     845              20 : {
     846              20 :   Vstr_base *out = vlg->out_vstr;
     847                 :   
     848              20 :   if (out->len)
     849               0 :     vlg_err(vlg, EXIT_FAILURE, "Data in vlg for pid_file\n");
     850                 :   
     851              20 :   if (!vstr_add_fmt(out, out->len, "%lu\n", (unsigned long)getpid()))
     852               0 :     vlg_err(vlg, EXIT_FAILURE, "vlg_pid_file: %m\n");
     853                 : 
     854              20 :   if (!vstr_sc_write_file(out, 1, out->len,
     855                 :                           pid_file, O_WRONLY | O_CREAT | O_TRUNC, 0644, 0,NULL))
     856                 :   {
     857               0 :     vstr_del(out, 1, out->len);
     858               0 :     vlg_err(vlg, EXIT_FAILURE, "vlg_pid_file(%s): %m\n", pid_file);
     859                 :   }
     860              20 : }
     861                 : 
     862                 : /* ================== actual logging functions ================== */
     863                 : 
     864                 : /* ---------- va_list ---------- */
     865                 : void vlg_vabort(Vlg *vlg, const char *fmt, va_list ap)
     866               0 : {
     867               0 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_ALERT, TRUE);
     868               0 :   abort();
     869                 : }
     870                 : 
     871                 : void vlg_verr(Vlg *vlg, int exit_code, const char *fmt, va_list ap)
     872               0 : {
     873               0 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_ALERT, TRUE);
     874               0 :   _exit(exit_code);
     875                 : }
     876                 : 
     877                 : void vlg_vwarn(Vlg *vlg, const char *fmt, va_list ap)
     878              28 : {
     879              28 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_WARNING, TRUE);
     880              28 : }
     881                 : 
     882                 : void vlg_vinfo(Vlg *vlg, const char *fmt, va_list ap)
     883          203008 : {
     884          203008 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_NOTICE, FALSE);
     885          203008 : }
     886                 : 
     887                 : void vlg_vdbg1(Vlg *vlg, const char *fmt, va_list ap)
     888           54551 : {
     889           54551 :   if (vlg->out_dbg < 1)
     890           54279 :     return;
     891                 : 
     892             272 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_DEBUG, TRUE);
     893                 : }
     894                 : 
     895                 : void vlg_vdbg2(Vlg *vlg, const char *fmt, va_list ap)
     896        53191828 : {
     897        53191828 :   if (vlg->out_dbg < 2)
     898        53191196 :     return;
     899                 : 
     900             632 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_DEBUG, TRUE);
     901                 : }
     902                 : 
     903                 : void vlg_vdbg3(Vlg *vlg, const char *fmt, va_list ap)
     904        29723878 : {
     905        29723878 :   if (vlg->out_dbg < 3)
     906        29722128 :     return;
     907                 : 
     908            1750 :   vlg__add_chk_flush(vlg, fmt, ap, LOG_DEBUG, TRUE);
     909                 : }
     910                 : 
     911                 : /* ---------- ... ---------- */
     912                 : void vlg_abort(Vlg *vlg, const char *fmt, ... )
     913               0 : {
     914                 :   va_list ap;
     915                 : 
     916               0 :   va_start(ap, fmt);
     917               0 :   vlg_vabort(vlg, fmt, ap);
     918               0 :   va_end(ap);
     919                 :   
     920               0 :   ASSERT_NOT_REACHED();
     921               0 : }
     922                 : 
     923                 : void vlg_err(Vlg *vlg, int exit_code, const char *fmt, ... )
     924               0 : {
     925                 :   va_list ap;
     926                 : 
     927               0 :   va_start(ap, fmt);
     928               0 :   vlg_verr(vlg, exit_code, fmt, ap);
     929               0 :   va_end(ap);
     930                 :   
     931               0 :   ASSERT_NOT_REACHED();
     932               0 : }
     933                 : 
     934                 : void vlg_warn(Vlg *vlg, const char *fmt, ... )
     935              28 : {
     936                 :   va_list ap;
     937                 : 
     938              28 :   va_start(ap, fmt);
     939              28 :   vlg_vwarn(vlg, fmt, ap);
     940              28 :   va_end(ap);
     941              28 : }
     942                 : 
     943                 : void vlg_info(Vlg *vlg, const char *fmt, ... )
     944          203008 : {
     945                 :   va_list ap;
     946                 : 
     947          203008 :   va_start(ap, fmt);
     948          203008 :   vlg_vinfo(vlg, fmt, ap);
     949          203008 :   va_end(ap);
     950          203008 : }
     951                 : 
     952                 : void vlg_dbg1(Vlg *vlg, const char *fmt, ... )
     953           54551 : {
     954                 :   va_list ap;
     955                 : 
     956           54551 :   va_start(ap, fmt);
     957           54551 :   vlg_vdbg1(vlg, fmt, ap);
     958           54551 :   va_end(ap);
     959           54551 : }
     960                 : 
     961                 : void vlg_dbg2(Vlg *vlg, const char *fmt, ... )
     962        53191828 : {
     963                 :   va_list ap;
     964                 : 
     965        53191828 :   va_start(ap, fmt);
     966        53191828 :   vlg_vdbg2(vlg, fmt, ap);
     967        53191828 :   va_end(ap);
     968        53191828 : }
     969                 : 
     970                 : void vlg_dbg3(Vlg *vlg, const char *fmt, ... )
     971        29723878 : {
     972                 :   va_list ap;
     973                 : 
     974        29723878 :   va_start(ap, fmt);
     975        29723878 :   vlg_vdbg3(vlg, fmt, ap);
     976        29723878 :   va_end(ap);
     977        29723878 : }
     978                 : 
     979                 : /* ---------- signal ... ---------- */
     980                 : 
     981                 : static volatile sig_atomic_t vlg__in_signal = FALSE;
     982                 : 
     983                 : /* due to multiple signals hitting while we are inside vlg_*() we have
     984                 :    signal safe varients, that:
     985                 :    
     986                 :    block all signals (apart from SEGV and ABRT)
     987                 :    do their thing
     988                 :    make sure they have flushed
     989                 :    restore signal mask
     990                 :    
     991                 :    ...note that this does mean if we've crashed inside vlg, we are screwed
     992                 :    and just abort().
     993                 : */
     994                 : 
     995                 : #define VLG__SIG_BLOCK_BEG() do {                                       \
     996                 :       sigset_t oset;                                                    \
     997                 :       sigset_t nset;                                                    \
     998                 :                                                                         \
     999                 :       if (sigfillset(&nset)                      == -1) abort();        \
    1000                 :       if (sigdelset(&nset, SIGSEGV)              == -1) abort();        \
    1001                 :       if (sigdelset(&nset, SIGABRT)              == -1) abort();        \
    1002                 :       if (sigprocmask(SIG_SETMASK, &nset, &oset) == -1) abort();        \
    1003                 :                                                                         \
    1004                 :       if (vlg__in_signal) abort();                                      \
    1005                 :       else {                                                            \
    1006                 :         Vstr_base  *tmp_out = NULL;                                     \
    1007                 :         Date_store *tmp_dt  = NULL;                                     \
    1008                 :                                                                         \
    1009                 :         vlg__in_signal = TRUE;                                          \
    1010                 :                                                                         \
    1011                 :         tmp_out           = vlg->out_vstr;                              \
    1012                 :         vlg->out_vstr     = vlg->sig_out_vstr;                          \
    1013                 :         vlg->sig_out_vstr = NULL;                                       \
    1014                 :                                                                         \
    1015                 :         tmp_dt            = vlg->dt;                                    \
    1016                 :         vlg->dt           = vlg->sig_dt;                                \
    1017                 :         vlg->sig_dt       = NULL;                                       \
    1018                 :                                                                         \
    1019                 :         if (vlg->out_vstr->len) abort()
    1020                 : 
    1021                 : #define VLG__SIG_BLOCK_END()                                            \
    1022                 :         if (vlg->out_vstr->len) abort();                                \
    1023                 :         vlg->sig_out_vstr = vlg->out_vstr;                              \
    1024                 :         vlg->out_vstr     = tmp_out;                                    \
    1025                 :                                                                         \
    1026                 :         vlg->sig_dt       = vlg->dt;                                    \
    1027                 :         vlg->dt           = tmp_dt;                                     \
    1028                 :                                                                         \
    1029                 :         vlg__in_signal = FALSE;                                         \
    1030                 :       }                                                                 \
    1031                 :                                                                         \
    1032                 :       if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) abort();         \
    1033                 :     } while (FALSE)
    1034                 : 
    1035                 : void vlg_sig_abort(Vlg *vlg, const char *fmt, ... )
    1036               0 : {
    1037                 :   va_list ap;
    1038                 : 
    1039               0 :   VLG__SIG_BLOCK_BEG();
    1040                 :   
    1041               0 :   va_start(ap, fmt);
    1042               0 :   vlg_vabort(vlg, fmt, ap);
    1043               0 :   va_end(ap);
    1044                 :   
    1045               0 :   VLG__SIG_BLOCK_END();
    1046                 :   
    1047               0 :   ASSERT_NOT_REACHED();
    1048               0 : }
    1049                 : 
    1050                 : void vlg_sig_err(Vlg *vlg, int exit_code, const char *fmt, ... )
    1051               0 : {
    1052                 :   va_list ap;
    1053                 : 
    1054               0 :   VLG__SIG_BLOCK_BEG();
    1055                 :   
    1056               0 :   va_start(ap, fmt);
    1057               0 :   vlg_verr(vlg, exit_code, fmt, ap);
    1058               0 :   va_end(ap);
    1059                 : 
    1060               0 :   VLG__SIG_BLOCK_END();
    1061                 :   
    1062               0 :   ASSERT_NOT_REACHED();
    1063               0 : }
    1064                 : 
    1065                 : void vlg_sig_warn(Vlg *vlg, const char *fmt, ... )
    1066               0 : {
    1067                 :   va_list ap;
    1068                 : 
    1069               0 :   VLG__SIG_BLOCK_BEG();
    1070                 :   
    1071               0 :   va_start(ap, fmt);
    1072               0 :   vlg_vwarn(vlg, fmt, ap);
    1073               0 :   va_end(ap);
    1074                 : 
    1075               0 :   VLG__SIG_BLOCK_END();
    1076               0 : }
    1077                 : 
    1078                 : void vlg_sig_info(Vlg *vlg, const char *fmt, ... )
    1079               0 : {
    1080                 :   va_list ap;
    1081                 : 
    1082               0 :   VLG__SIG_BLOCK_BEG();
    1083                 :   
    1084               0 :   va_start(ap, fmt);
    1085               0 :   vlg_vinfo(vlg, fmt, ap);
    1086               0 :   va_end(ap);
    1087                 : 
    1088               0 :   VLG__SIG_BLOCK_END();
    1089               0 : }
    1090                 : 
    1091                 : void vlg_sig_dbg1(Vlg *vlg, const char *fmt, ... )
    1092               0 : {
    1093                 :   va_list ap;
    1094                 : 
    1095               0 :   VLG__SIG_BLOCK_BEG();
    1096                 :   
    1097               0 :   va_start(ap, fmt);
    1098               0 :   vlg_vdbg1(vlg, fmt, ap);
    1099               0 :   va_end(ap);
    1100                 : 
    1101               0 :   VLG__SIG_BLOCK_END();
    1102               0 : }
    1103                 : 
    1104                 : void vlg_sig_dbg2(Vlg *vlg, const char *fmt, ... )
    1105               0 : {
    1106                 :   va_list ap;
    1107                 : 
    1108               0 :   VLG__SIG_BLOCK_BEG();
    1109                 :   
    1110               0 :   va_start(ap, fmt);
    1111               0 :   vlg_vdbg2(vlg, fmt, ap);
    1112               0 :   va_end(ap);
    1113                 : 
    1114               0 :   VLG__SIG_BLOCK_END();
    1115               0 : }
    1116                 : 
    1117                 : void vlg_sig_dbg3(Vlg *vlg, const char *fmt, ... )
    1118               0 : {
    1119                 :   va_list ap;
    1120                 : 
    1121               0 :   VLG__SIG_BLOCK_BEG();
    1122                 :   
    1123               0 :   va_start(ap, fmt);
    1124               0 :   vlg_vdbg3(vlg, fmt, ap);
    1125               0 :   va_end(ap);
    1126                 : 
    1127               0 :   VLG__SIG_BLOCK_END();
    1128               0 : }
    1129                 : 

Generated by: LTP GCOV extension version 1.4