Coverage Report

Created: 2025-07-01 06:48

/src/libssh/src/log.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * log.c - logging and debugging functions
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2008-2013   by Aris Adamantiadis
7
 *
8
 * The SSH Library is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or (at your
11
 * option) any later version.
12
 *
13
 * The SSH Library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16
 * License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with the SSH Library; see the file COPYING.  If not, write to
20
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21
 * MA 02111-1307, USA.
22
 */
23
24
#include "config.h"
25
26
#include <stdio.h>
27
#include <stdarg.h>
28
#include <string.h>
29
#ifdef HAVE_SYS_TIME_H
30
#include <sys/time.h>
31
#endif /* HAVE_SYS_TIME_H */
32
#ifdef HAVE_SYS_UTIME_H
33
#include <sys/utime.h>
34
#endif /* HAVE_SYS_UTIME_H */
35
#include <time.h>
36
37
#include "libssh/priv.h"
38
#include "libssh/misc.h"
39
#include "libssh/session.h"
40
41
#ifndef LOG_SIZE
42
#define LOG_SIZE 1024
43
#endif
44
45
static LIBSSH_THREAD int ssh_log_level;
46
static LIBSSH_THREAD ssh_logging_callback ssh_log_cb;
47
static LIBSSH_THREAD void *ssh_log_userdata = NULL;
48
49
/**
50
 * @defgroup libssh_log The SSH logging functions
51
 * @ingroup libssh
52
 *
53
 * Logging functions for debugging and problem resolving.
54
 *
55
 * @{
56
 */
57
58
static int current_timestring(int hires, char *buf, size_t len)
59
0
{
60
0
    char tbuf[64];
61
0
    struct timeval tv;
62
0
    struct tm tm, *tm_ptr = NULL;
63
0
    time_t t;
64
65
0
    gettimeofday(&tv, NULL);
66
0
    t = (time_t) tv.tv_sec;
67
68
0
    tm_ptr = localtime_r(&t, &tm);
69
0
    if (tm_ptr == NULL) {
70
0
        return -1;
71
0
    }
72
73
0
    if (hires) {
74
0
        strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
75
0
        snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec);
76
0
    } else {
77
0
        strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
78
0
        snprintf(buf, len, "%s", tbuf);
79
0
    }
80
81
0
    return 0;
82
0
}
83
84
static void ssh_log_stderr(int verbosity,
85
                           const char *function,
86
                           const char *buffer)
87
0
{
88
0
    char date[128] = {0};
89
0
    int rc;
90
91
0
    rc = current_timestring(1, date, sizeof(date));
92
0
    if (rc == 0) {
93
0
        fprintf(stderr, "[%s, %d] %s:", date, verbosity, function);
94
0
    } else {
95
0
        fprintf(stderr, "[%d] %s", verbosity, function);
96
0
    }
97
98
0
    fprintf(stderr, "  %s\n", buffer);
99
0
}
100
101
static void ssh_log_custom(ssh_logging_callback log_fn,
102
                           int verbosity,
103
                           const char *function,
104
                           const char *buffer)
105
0
{
106
0
    char buf[LOG_SIZE + 64];
107
108
0
    snprintf(buf, sizeof(buf), "%s: %s", function, buffer);
109
0
    log_fn(verbosity, function, buf, ssh_get_log_userdata());
110
0
}
111
112
void ssh_log_function(int verbosity,
113
                      const char *function,
114
                      const char *buffer)
115
0
{
116
0
    ssh_logging_callback log_fn = ssh_get_log_callback();
117
118
0
    if (log_fn) {
119
0
        ssh_log_custom(log_fn, verbosity, function, buffer);
120
0
        return;
121
0
    }
122
123
0
    ssh_log_stderr(verbosity, function, buffer);
124
0
}
125
126
void ssh_vlog(int verbosity,
127
              const char *function,
128
              const char *format,
129
              va_list *va)
130
0
{
131
0
    char buffer[LOG_SIZE];
132
133
0
    vsnprintf(buffer, sizeof(buffer), format, *va);
134
0
    ssh_log_function(verbosity, function, buffer);
135
0
}
136
137
void _ssh_log(int verbosity,
138
              const char *function,
139
              const char *format, ...)
140
0
{
141
0
    va_list va;
142
143
0
    if (verbosity <= ssh_get_log_level()) {
144
0
        va_start(va, format);
145
0
        ssh_vlog(verbosity, function, format, &va);
146
0
        va_end(va);
147
0
    }
148
0
}
149
150
/* LEGACY */
151
152
void ssh_log(ssh_session session,
153
             int verbosity,
154
             const char *format, ...)
155
0
{
156
0
  va_list va;
157
158
0
  if (verbosity <= session->common.log_verbosity) {
159
0
    va_start(va, format);
160
0
    ssh_vlog(verbosity, "", format, &va);
161
0
    va_end(va);
162
0
  }
163
0
}
164
165
/** @internal
166
 * @brief log a SSH event with a common pointer
167
 * @param common       The SSH/bind session.
168
 * @param verbosity     The verbosity of the event.
169
 * @param format        The format string of the log entry.
170
 */
171
void ssh_log_common(struct ssh_common_struct *common,
172
                    int verbosity,
173
                    const char *function,
174
                    const char *format, ...)
175
0
{
176
0
    va_list va;
177
178
0
    if (verbosity <= common->log_verbosity) {
179
0
        va_start(va, format);
180
0
        ssh_vlog(verbosity, function, format, &va);
181
0
        va_end(va);
182
0
    }
183
0
}
184
185
186
/* PUBLIC */
187
188
/**
189
 * @brief Set the log level of the library.
190
 *
191
 * @param[in]  level    The level to set.
192
 *
193
 * @return              SSH_OK on success, SSH_ERROR on error.
194
 */
195
0
int ssh_set_log_level(int level) {
196
0
  if (level < 0) {
197
0
    return SSH_ERROR;
198
0
  }
199
200
0
  ssh_log_level = level;
201
202
0
  return SSH_OK;
203
0
}
204
205
/**
206
 * @brief Get the log level of the library.
207
 *
208
 * @return    The value of the log level.
209
 */
210
0
int ssh_get_log_level(void) {
211
0
  return ssh_log_level;
212
0
}
213
214
0
int ssh_set_log_callback(ssh_logging_callback cb) {
215
0
  if (cb == NULL) {
216
0
    return SSH_ERROR;
217
0
  }
218
219
0
  ssh_log_cb = cb;
220
221
0
  return SSH_OK;
222
0
}
223
224
void
225
_ssh_reset_log_cb(void)
226
0
{
227
0
    ssh_log_cb = NULL;
228
0
}
229
230
0
ssh_logging_callback ssh_get_log_callback(void) {
231
0
  return ssh_log_cb;
232
0
}
233
234
/**
235
 * @brief Get the userdata of the logging function.
236
 *
237
 * @return    The userdata if set or NULL.
238
 */
239
void *ssh_get_log_userdata(void)
240
0
{
241
0
    if (ssh_log_userdata == NULL) {
242
0
        return NULL;
243
0
    }
244
245
0
    return ssh_log_userdata;
246
0
}
247
248
/**
249
 * @brief Set the userdata for the logging function.
250
 *
251
 * @param[in]  data     The userdata to set.
252
 *
253
 * @return              SSH_OK on success.
254
 */
255
int ssh_set_log_userdata(void *data)
256
0
{
257
0
    ssh_log_userdata = data;
258
259
0
    return 0;
260
0
}
261
262
/** @} */