/*
+-------------------------------------------------------------------------+
|                           loghorn vers. 0.1.01                          |
|    Copyright (c) Andrey V. Stolyarov  <croco at croco dot net>  2026    |
| ----------------------------------------------------------------------- |
| This is free software.  Permission is granted to everyone to use, copy  |
|    or modify this software under the terms and conditions of either     |
|             CROCO'S INDIVIDUALISTIC FREE SOFTWARE LICENSE               |
|                          or, at your option,                            |
|               GNU LESSER GENERAL PUBLIC LICENSE, v. 2.1                 |
|                                                                         |
| Please visit http://www.croco.net/software/loghorn  to get a fresh copy |
| ----------------------------------------------------------------------- |
|   This code is provided strictly and exclusively on the "AS IS" basis.  |
|        THERE IS NO WARRANTY OF ANY KIND, DON'T EVEN THINK ABOUT IT      |
+-------------------------------------------------------------------------+
*/




#ifndef SERVLOG_H_SENTRY
#define SERVLOG_H_SENTRY

#include <stdarg.h>

/*
    Three channels are supported, configured independently:

    1) logging to stderr
    2) logging to a given file, in append mode, fflush'ed after each msg
    3) logging through the system logger

    Each channel is configured separately.  The functions performing
    actual logging use all configured channels, so it is possible, e.g.,
    to send all the information to all the three channels at once.

    By default, only the stderr channel is enabled, with the normal
    verbosity level and private information logging allowed.  The other
    two channels are disabled.
 */

#ifdef __cplusplus
extern "C" {
#endif

enum servlog_levels {
    srvl_disable =  0,    /* setup funcs only: disable the channel */

    srvl_alert   =  1,    /* show even in the "quiet" mode         */
    srvl_normal  =  2,    /* normal messages                       */
    srvl_info    =  3,    /* show in the "verbose" mode only       */
    srvl_debug   =  4,    /* show only for -vv and higher          */
    srvl_debug2  =  5,    /* show only for -vvv and higher,
                                never send to syslog               */

    srvl_private = 256    /* contains privacy-sensitive info, only
                          log if sensitive info logging is allowed */
};

enum servlog_facilities {
    srvl_facil_default = 0,
    srvl_facil_user    = 0,
    srvl_facil_daemon  = 1,
    srvl_facil_local0  = 2,
    srvl_facil_local1  = 3,
    srvl_facil_local2  = 4,
    srvl_facil_local3  = 5,
    srvl_facil_local4  = 6,
    srvl_facil_local5  = 7,
    srvl_facil_local6  = 8,
    srvl_facil_local7  = 9
};

void servlog_message_vl(int level, const char *fmt, va_list args);
void servlog_message(int level, const char *fmt, ...);

    /* s1 (sic!) may be NULL or empty */
void servlog_perror(int level, const char *s1, const char *s2);

void setup_stderr_log(int mode);

    /* returns boolean */
int setup_file_log(int mode, const char *filename);

void setup_syslog(int mode, const char *ident, int facility);


    /* function should look like

          void func(void *userdata, const char *message) { ... }
     */

typedef void (*extra_log_callback)(void *, const char *);

    /* it is the user's duty to create the instance of the struct
       extra_log_item and fill the fields f, userdata and level;
       f must point to the appropriate callback function, level
       must be any valid combination of the srvl_* constants, and
       userdata may actually be anything you want: its only role
       is that it will be given to your callback function as its
       first argument; the structure remains owned by the user;
       the instance of the struct extra_log_item, once added with
       add_extra_log, MUST be removed by remove_extra_log before
       it goes unusable for any reason; on the other hand, the
       user is welcome to change the f, userdata and level fields
       at any moment, provided that their values remain valid and
       good for work; fields p1 and p2 must never be touched by
       the user, they are for internal use only.
     */

struct extra_log_item {
    extra_log_callback f;
    void *userdata;
    int level;

    struct extra_log_item *p1, *p2;     /* used internally, don't touch */
};

void add_extra_log(struct extra_log_item *item);
void remove_extra_log(struct extra_log_item *item);


#ifdef __cplusplus
};
#endif

#endif
