fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / logctl.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Copyright 1998-2001 by Rob Braun
4  * All rights reserved.  The file named COPYRIGHT specifies the terms 
5  * and conditions for redistribution.
6  */
7
8
9 #include "config.h"
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <syslog.h>
13 #include <fcntl.h>
14
15 #include "logctl.h"
16 #include "msg.h"
17 #include "xconfig.h"
18 #include "main.h"
19 #include "sconf.h"
20
21
22 static xlog_h start_filelog( const char *id, struct filelog *flp )
23 {
24    xlog_h   xh ;
25    int      fd ;
26    int      log_file_mode = ( debug.on ) ? 0644 : LOG_FILE_MODE ;
27    const char *func = "start_filelog" ;
28
29    xh = xlog_create( XLOG_FILELOG, id, XLOG_NOFLAGS,
30                      flp->fl_filename, LOG_OPEN_FLAGS, log_file_mode ) ;
31    if ( xh == NULL )
32    {
33       msg( LOG_ERR, func, "creation of %s log failed", id ) ;
34       return( NULL ) ;
35    }
36
37    if ( xlog_control( xh, XLOG_GETFD, &fd ) != XLOG_ENOERROR ||
38         fcntl( fd,  F_SETFD, FD_CLOEXEC ) == -1 )
39    {
40       msg( LOG_ERR, func, "Failed to set close-on-exec flag for log file" ) ;
41       xlog_destroy( xh ) ;
42       return( NULL ) ;
43    }
44
45    ps.rws.descriptors_free-- ;
46
47    if ( FILELOG_SIZE_CONTROL( flp ) )
48       (void) xlog_control( xh,
49                      XLOG_LIMITS, flp->fl_soft_limit, flp->fl_hard_limit ) ;
50
51    return( xh ) ;
52 }
53
54
55 /*
56  * This function is invoked when a xlog detects an error (for example,
57  * exceeding the file size limit).
58  * The function just enters a log message.
59  * 
60  * NOTE: We could destroy the xlog at this point but we choose not to.
61  */
62 static void log_in_error( xlog_h xh, int error_code, void *arg )
63 {
64    struct service     *sp       = SP( arg ) ;
65    const char         *log_id   = ( sp == NULL ) ? "common" : SVC_ID( sp ) ;
66    const char         *func     = "log_in_error" ;
67
68 #ifdef lint
69    xh = xh ;
70 #endif
71    if ( error_code == XLOG_ESIZE )
72       msg( LOG_ERR, func, "Size of %s log exceeded hard limit", log_id ) ;
73    else
74       msg( LOG_ERR, func, "Error in %s log: %d", log_id, error_code ) ;
75 }
76
77 /*
78  * Start logging for the specified service.
79  * The current configuration is used to determine the common log file.
80  */
81 status_e log_start( struct service *sp, xlog_h *xhp )
82 {
83    xlog_h        xh ;
84    const char   *sid   = SVC_ID( sp ) ;
85    struct log   *lp    = SC_LOG( SVC_CONF( sp ) ) ;
86    const char   *func  = "log_start" ;
87
88    switch ( lp->l_type )
89    {
90       case L_NONE:
91          xh = NULL ;
92          break ;
93
94       case L_SYSLOG:
95          xh = xlog_create( XLOG_SYSLOG, sid, XLOG_NOFLAGS, 
96                   LOG_GET_SYSLOG( lp )->sl_facility,
97                   LOG_GET_SYSLOG( lp )->sl_level ) ;
98          if ( xh == NULL )
99          {
100             msg( LOG_ERR, func, "failed to create a log for service %s", sid ) ;
101             return( FAILED ) ;
102          }
103          xlog_control( xh, XLOG_CALLBACK, log_in_error, (void *)sp ) ;
104          break ;
105       
106       case L_FILE:
107          /*
108           * NOTE: if the same file is specified for more than one service,
109           *         it will be opened as many times.
110           *         Furthermore, size control will not be accurate.
111           */
112          xh = start_filelog( sid, LOG_GET_FILELOG( lp ) ) ;
113          if ( xh == NULL )
114             return( FAILED ) ;
115          (void) xlog_control( xh, XLOG_CALLBACK, log_in_error, (void *)sp ) ;
116          break ;
117       
118       case L_COMMON_FILE:
119          if ( DEFAULT_LOG( ps ) == NULL )
120             if ( DEFAULT_LOG_ERROR( ps ) )
121                return( FAILED ) ;
122             else
123             {
124                xh = start_filelog( "default", 
125                               LOG_GET_FILELOG( SC_LOG( DEFAULTS( ps ) ) ) ) ;
126                if ( xh == NULL )
127                {
128                   DEFAULT_LOG_ERROR( ps ) = TRUE ;
129                   return( FAILED ) ;
130                }
131                DEFAULT_LOG( ps ) = xh ;
132                (void) xlog_control( xh,
133                            XLOG_CALLBACK, log_in_error, VOID_NULL ) ;
134             }
135          else
136             xh = DEFAULT_LOG( ps ) ;
137          break ;
138
139       default:         /* SHOULDN'T HAPPEN */
140          msg( LOG_ERR, func, "bad log type (%d) for service %s",
141             (int) LOG_GET_TYPE( lp ), sid ) ;
142          return( FAILED ) ;
143    }
144    *xhp = xh ;
145    return( OK ) ;
146 }
147
148
149 void log_end( struct log *lp, xlog_h xh )
150 {
151    const char *func = "log_end" ;
152
153    if ( xh == NULL )      /* shouldn't be NULL but just in case */
154    {
155       msg( LOG_NOTICE, func, "called with NULL handle" ) ;
156       return ;
157    }
158
159    switch ( LOG_GET_TYPE( lp ) )
160    {
161       case L_FILE:
162          ps.rws.descriptors_free++ ;
163          /* FALL THROUGH */
164       
165       case L_SYSLOG:
166          xlog_destroy( xh ) ;
167       case L_NONE:
168       case L_COMMON_FILE:
169          ;
170    }
171 }
172