123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /* log.c -- Guile-SSH logging procedures
- *
- * Copyright (C) 2014, 2015, 2016, 2017 Artyom V. Poptsov <poptsov.artyom@gmail.com>
- *
- * This file is part of Guile-SSH
- *
- * Guile-SSH is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * Guile-SSH 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 GNU General Public License
- * along with Guile-SSH. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <config.h>
- #include <stdarg.h>
- #include <libguile.h>
- #include <libssh/libssh.h>
- #include <libssh/callbacks.h>
- #include <sys/time.h>
- #include <time.h>
- #include <stdio.h> /* DEBUG */
- #include <unistd.h> /* DEBUG */
- #include "error.h"
- #include "common.h"
- /* Log verbosity levels used by libssh sessions and servers. */
- struct symbol_mapping log_verbosity[] = {
- /* 0, No logging at all */
- { "nolog", SSH_LOG_NOLOG },
- /* 1, Only rare and noteworthy events */
- { "rare", SSH_LOG_RARE },
- /* 2, High level protocol information */
- { "protocol", SSH_LOG_PROTOCOL },
- /* 3, Lower level protocol infomations, packet level */
- { "packet", SSH_LOG_PACKET },
- /* 4, Every function path */
- { "functions", SSH_LOG_FUNCTIONS },
- { NULL, -1 }
- };
- /* Whether the default calback was set or not. */
- static int is_logging_callback_set = 0;
- /* A Scheme log printer. */
- static SCM logging_callback = SCM_BOOL_F;
- /* The libssh logging callback which calls Scheme callback procedure. */
- void
- libssh_logging_callback (int c_priority,
- const char *c_function_name,
- const char *c_message,
- void *c_userdata)
- {
- SCM priority = scm_from_int (c_priority);
- SCM function = scm_from_locale_string (c_function_name);
- SCM message = scm_from_locale_string (c_message);
- SCM userdata = (SCM) c_userdata;
- scm_call_4 (logging_callback, priority, function, message, userdata);
- }
- #define TBUF_SZ 64
- static int
- _get_current_timestring (char *buf, size_t len)
- {
- char tbuf[TBUF_SZ];
- struct timeval tv;
- struct tm *tm;
- time_t t;
- gettimeofday (&tv, NULL);
- t = (time_t) tv.tv_sec;
- tm = localtime (&t);
- if (tm == NULL)
- return -1;
- strftime (tbuf, sizeof (tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
- snprintf (buf, len, "%s.%06ld", tbuf, (long) tv.tv_usec);
- return 0;
- }
- SCM_DEFINE (guile_ssh_default_libssh_log_printer,
- "%default-libssh-log-printer", 4, 0, 0,
- (SCM priority, SCM function_name, SCM message, SCM user_data),
- "")
- {
- char date[TBUF_SZ] = {0};
- int rc = _get_current_timestring (date, sizeof(date));
- scm_puts ("[", scm_current_error_port ());
- if (rc == 0)
- {
- scm_puts (date, scm_current_error_port ());
- scm_puts (", ", scm_current_error_port ());
- }
- scm_display (priority, scm_current_error_port ());
- scm_puts ("] ", scm_current_error_port ());
- scm_display (message, scm_current_error_port ());
- scm_newline (scm_current_error_port ());
- return SCM_UNDEFINED;
- }
- SCM_DEFINE (guile_ssh_set_logging_callback_x,
- "set-logging-callback!", 1, 0, 0,
- (SCM procedure),
- "")
- #define FUNC_NAME s_guile_ssh_set_logging_callback_x
- {
- SCM_ASSERT (scm_procedure_p (procedure), procedure, SCM_ARG1, FUNC_NAME);
- if (! is_logging_callback_set)
- {
- int res = ssh_set_log_userdata (SCM_BOOL_F);
- if (res != SSH_OK)
- guile_ssh_error1 (FUNC_NAME, "Could not set userdata", procedure);
- res = ssh_set_log_callback (&libssh_logging_callback);
- if (res != SSH_OK)
- guile_ssh_error1 (FUNC_NAME, "Could not setup logging", procedure);
- is_logging_callback_set = 1;
- }
- logging_callback = procedure;
- return SCM_UNDEFINED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (guile_ssh_get_logging_callback,
- "current-logging-callback", 0, 0, 0,
- (void),
- "")
- {
- return logging_callback;
- }
- SCM_DEFINE (guile_ssh_set_log_useradata_x,
- "set-log-userdata!", 1, 0, 0,
- (SCM data),
- "")
- #define FUNC_NAME s_guile_ssh_set_log_useradata_x
- {
- int res = ssh_set_log_userdata (data);
- if (res != SSH_OK)
- guile_ssh_error1 (FUNC_NAME, "Could not set userdata", data);
- return SCM_UNDEFINED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (guile_ssh_get_log_userdata,
- "get-log-userdata", 0, 0, 0,
- (void),
- "")
- {
- void *data = (void *) ssh_get_log_userdata ();
- return data ? (SCM) data : SCM_BOOL_F;
- }
- SCM_DEFINE (guile_ssh_write_log,
- "%write-log", 3, 0, 0,
- (SCM priority, SCM function_name, SCM message),
- "\
- Write a MESSAGE to the libssh log with the given PRIORITY. Return value is \n\
- undefined. \
- ")
- #define FUNC_NAME s_guile_ssh_write_log
- {
- const struct symbol_mapping *c_priority;
- char *c_function_name;
- char *c_message;
- SCM_ASSERT (scm_symbol_p (priority), priority, SCM_ARG1, FUNC_NAME);
- SCM_ASSERT (scm_string_p (function_name), function_name, SCM_ARG2, FUNC_NAME);
- SCM_ASSERT (scm_string_p (message), message, SCM_ARG3, FUNC_NAME);
- c_priority = _scm_to_ssh_const (log_verbosity, priority);
- if (! c_priority)
- guile_ssh_error1 (FUNC_NAME, "Wrong priority level", priority);
- c_function_name = scm_to_locale_string (function_name);
- c_message = scm_to_locale_string (message);
- _ssh_log (c_priority->value, c_function_name, "%s", c_message);
- return SCM_UNDEFINED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (guile_ssh_set_log_verbosity_x,
- "set-log-verbosity!", 1, 0, 0,
- (SCM verbosity),
- "\
- Set the global log verbosity to a VERBOSITY. Throw `guile-ssh-error' on \
- error. Return value is undefined.\
- ")
- #define FUNC_NAME s_guile_ssh_set_log_verbosity_x
- {
- const struct symbol_mapping *opt = _scm_to_ssh_const (log_verbosity, verbosity);
- int res;
- if (! opt)
- guile_ssh_error1 (FUNC_NAME, "Wrong verbosity level", verbosity);
- res = ssh_set_log_level (opt->value);
- if (res == SSH_ERROR)
- guile_ssh_error1 (FUNC_NAME, "Could not set log verbosity", verbosity);
- return SCM_UNDEFINED;
- }
- #undef FUNC_NAME
- SCM_DEFINE (guile_ssh_get_log_verbosity,
- "get-log-verbosity", 0, 0, 0,
- (void),
- "\
- Get global log verbosity value.\
- ")
- {
- return _ssh_const_to_scm (log_verbosity, ssh_get_log_level ());
- }
- /* Write an error MESSAGE along with ARGS to the libssh log. */
- void
- _gssh_log_error (const char* function_name, const char* msg, SCM args)
- {
- char *c_str;
- scm_dynwind_begin (0);
- c_str = scm_to_locale_string (scm_object_to_string (args, SCM_UNDEFINED));
- scm_dynwind_free (c_str);
- _ssh_log (SSH_LOG_NOLOG, function_name, "[GSSH ERROR] %s: %s",
- msg, c_str);
- scm_dynwind_end ();
- }
- void
- _gssh_log_warning (const char* function_name, const char* msg, SCM args)
- {
- char *c_str;
- scm_dynwind_begin (0);
- c_str = scm_to_locale_string (scm_object_to_string (args, SCM_UNDEFINED));
- scm_dynwind_free (c_str);
- _ssh_log (SSH_LOG_WARNING, function_name, "[GSSH WARNING] %s: %s",
- msg, c_str);
- scm_dynwind_end ();
- }
- void
- _gssh_log_debug (const char* function_name, const char* msg, SCM args)
- {
- char *c_str;
- scm_dynwind_begin (0);
- c_str = scm_to_locale_string (scm_object_to_string (args, SCM_UNDEFINED));
- scm_dynwind_free (c_str);
- _ssh_log (SSH_LOG_FUNCTIONS, function_name, "[GSSH DEBUG] %s: %s",
- msg, c_str);
- scm_dynwind_end ();
- }
- void
- _gssh_log_debug1 (const char* function_name, const char* msg)
- {
- _ssh_log (SSH_LOG_FUNCTIONS, function_name, "[GSSH DEBUG] %s", msg);
- }
- #ifdef DEBUG
- void
- _gssh_log_debug_format(const char* function_name, SCM args, const char* fmt, ...)
- {
- va_list arg;
- enum { MSG_SZ = 100 };
- char msg[MSG_SZ];
- va_start (arg, fmt);
- vsnprintf (msg, MSG_SZ, fmt, arg);
- va_end (arg);
- _gssh_log_debug(function_name, msg, args);
- }
- #else
- #define _gssh_log_debug_format(function_name, args, fmt, ...)
- #endif /* ifdef DEBUG */
- /* Initialization */
- void
- init_log_func (void)
- {
- #include "log.x"
- }
- /* log.c ends here */
|