fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / msg.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections 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 <syslog.h>
11 #include <fcntl.h>
12 #include <stdarg.h>
13 #include <unistd.h>
14
15 #include "xlog.h"
16 #include "str.h"
17 #include "msg.h"
18 #include "defs.h"
19 #include "options.h"
20 #include "xconfig.h"
21 #include "util.h"
22 #include "nvlists.h"
23 #include "main.h"
24 #include "parse.h"
25
26 static const struct name_value priorities[] =
27    {
28       { "WARNING",   LOG_WARNING  },
29       { "ERROR",     LOG_ERR      },
30       { "CRITICAL",  LOG_CRIT     },
31       { "NOTICE",    LOG_NOTICE   },
32       { "DEBUG",     LOG_DEBUG    },
33       { "INFO",      LOG_INFO     },
34       { NULL,        1            },
35       { "UNKNOWN",   0            }
36    } ;
37
38 #define BUFSIZE                     2048
39
40 #define DEFAULT_SYSLOG_LEVEL         LOG_INFO
41
42 const char *msg_init(void)
43 {
44    xlog_h      xh ;
45    int         fd ;
46    xlog_e      type_of_xlog ;
47    bool_int    facility_error = FALSE ;
48    const char *func            = "msg_init" ;
49
50    if ( debug.on )
51    {
52       type_of_xlog = XLOG_FILELOG ;
53       xh = xlog_create( type_of_xlog, program_name, XLOG_NOFLAGS,
54                                  "/dev/tty", O_APPEND + O_WRONLY, 0 ) ;
55       debug.fd = -1 ;
56    }
57    else
58    {
59       if ( filelog_option )
60       {
61          type_of_xlog = XLOG_FILELOG ;
62          xh = xlog_create( type_of_xlog, program_name,
63                   XLOG_PRINT_ID + XLOG_PRINT_PID,
64                      filelog_option_arg, LOG_OPEN_FLAGS, LOG_FILE_MODE ) ;
65       }
66       else
67       {
68          int facility = DEFAULT_SYSLOG_FACILITY ;
69          
70          if ( syslog_option )
71          {
72             const struct name_value *nvp ;
73
74             nvp = nv_find_value( syslog_facilities, syslog_option_arg ) ;
75             if ( nvp != NULL )
76                facility = nvp->value ;
77             else
78                facility_error = TRUE ;
79          }
80
81          type_of_xlog = XLOG_SYSLOG ;
82          xh = xlog_create( type_of_xlog, program_name, XLOG_NOFLAGS,
83                                        facility, DEFAULT_SYSLOG_LEVEL ) ;
84       }
85    }
86
87    if ( xh == NULL )
88    {
89       /*
90        * This simply returns the most likely reason for failure.
91        * We can't do any better since xlog_create does not return an
92        * error code.
93        */
94       if ( type_of_xlog == XLOG_SYSLOG )
95          return( "can't connect to syslog" ) ;
96       else if ( type_of_xlog == XLOG_FILELOG )
97          return( "can't open log file" ) ;
98       else
99          return( "unknown reason" ) ;
100    }
101    
102    /*
103     * XXX:   we shouldn't have to check the xlog type.
104     *         xlog_control should not succeed if the undelying logging
105     *         object does not support the XLOG_GETFD operation.
106     */
107    if ( type_of_xlog == XLOG_FILELOG &&
108             xlog_control( xh, XLOG_GETFD, &fd ) == XLOG_ENOERROR )
109    {
110       if ( fcntl( fd, F_SETFD, FD_CLOEXEC ) == -1 )
111       {
112          xlog_destroy( xh ) ;
113          return( "can't set close-on-exec flag of log file" ) ;
114       }
115       if ( debug.on )
116          debug.fd = fd ;
117    }
118    
119    ps.rws.program_log = xh ;
120
121    if ( facility_error )
122       msg( LOG_ERR, func, "Bad syslog facility: %s", syslog_option_arg ) ;
123    return( CHAR_NULL ) ;
124 }
125
126
127 void msg_suspend(void)
128 {
129    (void) xlog_control( ps.rws.program_log, XLOG_PREEXEC ) ;
130 }
131
132
133 void msg_resume(void)
134 {
135    (void) xlog_control( ps.rws.program_log, XLOG_POSTEXEC ) ;
136 }
137
138
139 /*
140  * The size argument is a value-result argument
141  */
142 static int
143 #ifdef __GNUC__
144 __attribute__ ((format (printf, 5, 0)))
145 #endif
146 prepare_buffer( int level, 
147                 const char *func, 
148                 char *buf, 
149                 unsigned size, 
150                 const char *fmt, 
151                 va_list ap )
152 {
153    int         cc ;
154    char        *bufstart   = buf ;
155    unsigned    bytes_left  = size ;
156
157    /*
158     * Check if we need to print the level name
159     */
160    if ( debug.on || filelog_option )
161    {
162       cc = strx_nprint( bufstart, bytes_left,
163                                  "%s: ", nv_get_name( priorities, level ) ) ;
164       bufstart += cc ;
165       bytes_left -= cc ;
166    }
167
168    /*
169     * Check if we need to print the function name
170     */
171    if ( debug.on || level == LOG_CRIT )
172    {
173       cc = strx_nprint( bufstart, bytes_left, "%d {%s} ", getpid(), func ) ;
174       bufstart += cc ;
175       bytes_left -= cc ;
176    }
177
178    cc = strx_nprintv( bufstart, bytes_left, fmt, ap ) ;
179
180    bytes_left -= cc ;
181
182    return( size - bytes_left ) ;
183 }
184
185
186 /* VARARGS3 */
187 void msg( int level, const char *func, const char *fmt, ...)
188 {
189    va_list   ap ;
190    char      buf[ BUFSIZE ] ;
191    int      len ;
192
193    va_start( ap, fmt ) ;
194    len = prepare_buffer( level, func, buf, sizeof( buf ), fmt, ap ) ;
195    va_end( ap ) ;
196
197    xlog_write( ps.rws.program_log, buf, len, XLOG_SET_LEVEL, level ) ;
198 }
199
200
201 /*
202  * Parser message.
203  * There are 2 differences from msg():
204  *      1) parsemsg() prints the line #
205  *      2) parsemsg() does not interpret %m
206  */
207 /* VARARGS3 */
208 void parsemsg( int msg_level, const char *func, const char *fmt, ...)
209 {
210    va_list   ap ;
211    char      buf[ BUFSIZE ] ;
212    int       cc ;
213    int       len ;
214
215    va_start( ap, fmt ) ;
216    len = prepare_buffer( msg_level, func, buf, sizeof( buf ), fmt, ap ) ;
217    va_end( ap ) ;
218
219    cc = strx_nprint( &buf[ len ], sizeof(buf)-len, 
220                      " [file=%s] [line=%d]", current_file, line_count ) ;
221    len += cc ;
222
223    xlog_write( ps.rws.program_log, buf, len, 
224          XLOG_NO_ERRNO + XLOG_SET_LEVEL, msg_level ) ;
225 }
226