usb_moded-log.c 7.45 KB
Newer Older
1
/**
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 * @file usb_moded-log.c
 *
 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
 * Copyright (C) 2016-2018 Jolla Ltd.
 *
 * @author: Philippe De Swert <philippe.de-swert@nokia.com>
 * @author: Simo Piiroinen <simo.piiroinen@nokia.com>
 * @author: Philippe De Swert <phdeswer@lumi.maa>
 * @author: Philippe De Swert <philippedeswert@gmail.com>
 * @author: Simo Piiroinen <simo.piiroinen@jollamobile.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Lesser GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the Lesser GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */
27

28 29
#include "usb_moded-log.h"

30 31
#include <sys/time.h>

32 33
#include <stdio.h>
#include <errno.h>
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/* ========================================================================= *
 * Prototypes
 * ========================================================================= */

/* -- log -- */

static char *log_strip       (char *str);
static void  log_gettime     (struct timeval *tv);
void         log_emit_va     (const char *file, const char *func, int line, int lev, const char *fmt, va_list va);
void         log_emit_real   (const char *file, const char *func, int line, int lev, const char *fmt, ...);
void         log_debugf      (const char *fmt, ...);
int          log_get_level   (void);
void         log_set_level   (int lev);
bool         log_p           (int lev);
int          log_get_type    (void);
void         log_set_type    (int type);
const char  *log_get_name    (void);
void         log_set_name    (const char *name);
void         log_set_lineinfo(bool lineinfo);
bool         log_get_lineinfo(void);
void         log_init        (void);

/* ========================================================================= *
 * Data
 * ========================================================================= */

61 62 63 64
static const char *log_name = "<unset>";
static int log_level = LOG_WARNING;
static int log_type  = LOG_TO_STDERR;
static bool log_lineinfo = false;
65
static struct timeval log_begtime = { 0, 0 };
66

67 68 69
/* ========================================================================= *
 * Functions
 * ========================================================================= */
phdeswer's avatar
phdeswer committed
70

71 72 73 74
static char *log_strip(char *str)
{
    unsigned char *src = (unsigned char *)str;
    unsigned char *dst = (unsigned char *)str;
phdeswer's avatar
phdeswer committed
75 76 77

    while( *src > 0 && *src <= 32 ) ++src;

78 79 80 81 82 83 84 85 86 87
    for( ;; )
    {
        while( *src > 32 ) *dst++ = *src++;
        while( *src > 0 && *src <= 32 ) ++src;
        if( *src == 0 ) break;
        *dst++ = ' ';
    }
    *dst = 0;
    return str;
}
88 89 90

static void log_gettime(struct timeval *tv)
{
91 92
    gettimeofday(tv, 0);
    timersub(tv, &log_begtime, tv);
93 94
}

95
/** Print the logged messages to the selected output
96
 *
97 98 99 100 101 102
 * @param file  Source file name
 * @param func  Function name
 * @param line  Line in source file
 * @param lev   The wanted log level
 * @param fmt   The message format string
 * @param va    Arguments for the format string
103
 */
104
void log_emit_va(const char *file, const char *func, int line, int lev, const char *fmt, va_list va)
105
{
106 107 108 109
    int saved = errno;
    if( log_p(lev) )
    {
        switch( log_type )
110
        {
111
        case LOG_TO_SYSLOG:
112

113 114
            vsyslog(lev, fmt, va);
            break;
115

116
        case LOG_TO_STDERR:
117

118 119 120 121 122 123 124 125 126
            if( log_get_lineinfo() ) {
                /* Use gcc error like prefix for logging so
                 * that logs can be analyzed with jump to
                 * line parsing  available in editors. */
                fprintf(stderr, "%s:%d: %s(): ", file, line, func);
            }
            else {
                fprintf(stderr, "%s: ", log_get_name());
            }
127 128

#if LOG_ENABLE_TIMESTAMPS
129 130 131 132 133 134 135
            {
                struct timeval tv;
                log_gettime(&tv);
                fprintf(stderr, "%3ld.%03ld ",
                        (long)tv.tv_sec,
                        (long)tv.tv_usec/1000);
            }
136 137 138
#endif

#if LOG_ENABLE_LEVELTAGS
139 140 141 142 143 144 145 146 147 148
            {
                static const char *tag = "U:";
                switch( lev )
                {
                case LOG_CRIT:    tag = "C:"; break;
                case LOG_ERR:     tag = "E:"; break;
                case LOG_WARNING: tag = "W:"; break;
                case LOG_NOTICE:  tag = "N:"; break;
                case LOG_INFO:    tag = "I:"; break;
                case LOG_DEBUG:   tag = "D:"; break;
149
                }
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
                fprintf(stderr, "%s ", tag);
            }
#endif
            {
                // squeeze whitespace like syslog does
                char buf[1024];
                errno = saved;
                vsnprintf(buf, sizeof buf - 1, fmt, va);
                fprintf(stderr, "%s\n", log_strip(buf));
            }
            break;

        default:
            // no logging
            break;
165
        }
166 167
    }
    errno = saved;
168 169
}

170 171 172 173 174 175 176 177 178
/** Print the logged messages to the selected output
 *
 * @param file  Source file name
 * @param func  Function name
 * @param line  Line in source file
 * @param lev   The wanted log level
 * @param fmt   The message format string
 * @param ...   Arguments for the format string
 */
179
void log_emit_real(const char *file, const char *func, int line, int lev, const char *fmt, ...)
180
{
181 182 183 184
    va_list va;
    va_start(va, fmt);
    log_emit_va(file, func, line, lev, fmt, va);
    va_end(va);
185 186 187 188
}

void log_debugf(const char *fmt, ...)
{
189 190 191 192 193 194 195 196
    /* This goes always to stderr */
    if( log_type == LOG_TO_STDERR && log_p(LOG_DEBUG) )
    {
        va_list va;
        va_start(va, fmt);
        vfprintf(stderr, fmt, va);
        va_end(va);
    }
197
}
198 199

/** Get the currently set logging level
200
 *
201
 * @return The current logging level
202
 */
203
int log_get_level(void)
204
{
205
    return log_level;
206 207
}

208
/** Set the logging level
209
 *
210
 * @param lev  The wanted logging level
211
 */
212
void log_set_level(int lev)
213
{
214
    log_level = lev;
215 216
}

217 218 219 220 221 222 223 224
/** Test if logging should be done at given level
 *
 * @param lev  The logging level to query
 *
 * @return true if logging in the given level is allowed, false otherwise
 */
bool log_p(int lev)
{
225
    return lev <= log_level;
226 227 228 229 230 231 232 233
}

/** Get the currently set logging type
 *
 * @return The current logging type
 */
int log_get_type(void)
{
234
    return log_type;
235 236 237 238 239 240 241 242
}

/* Set the logging type
 *
 * @param type  The wanted logging type
 */
void log_set_type(int type)
{
243
    log_type = type;
244 245 246 247 248 249 250 251
}

/** Get the currently set logging name
 *
 * @return The current logging name
 */
const char *log_get_name(void)
{
252
    return log_name;
253 254 255 256 257 258 259 260
}

/** Set the logging name
 *
 * @param name  The wanted logging name
 */
void log_set_name(const char *name)
{
261
    log_name = name;
262 263 264 265 266 267 268 269
}

/** Enable/disable the logging line info
 *
 * @param lineinfo  true to enable line info, false to disable
 */
void log_set_lineinfo(bool lineinfo)
{
270
    log_lineinfo = lineinfo;
271 272 273 274 275 276 277 278
}

/** Test if line info should be included in logging
 *
 * @return true when line info should be emitted, false otherwise
 */
bool log_get_lineinfo(void)
{
279
    return log_lineinfo;
280 281
}

282 283 284
/** Initialize logging */
void log_init(void)
{
285 286 287
    /* Get reference time used for verbose logging */
    if( !timerisset(&log_begtime) )
        gettimeofday(&log_begtime, 0);
288
}