1 /*
2 * types.h
3 *
4 * Version: 2.2.6
5 *
6 * -----------------------------------------------------------------------------
7 *
8 * SPDX-License-Identifier: MIT
9 *
10 * Copyright (c) 2018-2024 Ryan M. Lederman <lederman@gmail.com>
11 * Copyright (c) 2018-2024 Jeffrey H. Johnson <trnsz@pobox.com>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy of
14 * this software and associated documentation files (the "Software"), to deal in
15 * the Software without restriction, including without limitation the rights to
16 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17 * the Software, and to permit persons to whom the Software is furnished to do so,
18 * subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in all
21 * copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
27 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 *
30 * -----------------------------------------------------------------------------
31 */
32
33 #ifndef _SIR_TYPES_H_INCLUDED
34 # define _SIR_TYPES_H_INCLUDED
35
36 # include "sir/platform.h"
37 # include "sir/config.h"
38 # include "sir/ansimacros.h"
39
40 /**
41 * @addtogroup public
42 * @{
43 *
44 * @defgroup publictypes Types
45 * @{
46 */
47
48 /** Log file identifier type. */
49 typedef uint32_t sirfileid;
50
51 /** Plugin module identifier type. */
52 typedef uint32_t sirpluginid;
53
54 /*
55 * The following define the available levels of logging output.
56 */
57
58 # define SIRL_NONE 0x0000U /**< No output. */
59 # define SIRL_EMERG 0x0001U /**< Nuclear war, Armageddon, etc. */
60 # define SIRL_ALERT 0x0002U /**< Action required ASAP. */
61 # define SIRL_CRIT 0x0004U /**< Critical errors. */
62 # define SIRL_ERROR 0x0008U /**< Errors. */
63 # define SIRL_WARN 0x0010U /**< Warnings that could likely be ignored. */
64 # define SIRL_NOTICE 0x0020U /**< Normal but significant. */
65 # define SIRL_INFO 0x0040U /**< Informational messages. */
66 # define SIRL_DEBUG 0x0080U /**< Debugging/diagnostic output. */
67 # define SIRL_ALL 0x00ffU /**< Include all logging levels. */
68 # define SIRL_DEFAULT 0x0100U /**< Default levels for this type of destination. */
69
70 /** The ::sir_level type. */
71 typedef uint16_t sir_level;
72
73 /** ::sir_level bitmask type. */
74 typedef uint16_t sir_levels;
75
76 /*
77 * Formatting options for a destination.
78 */
79
80 # define SIRO_ALL 0x00000000U /**< Include all formatting and functionality. */
81 # define SIRO_NOTIME 0x00000100U /**< Exclude time stamps (implies ::SIRO_NOMSEC). */
82 # define SIRO_NOMSEC 0x00000200U /**< Exclude millisecond-resolution in time stamps. */
83 # define SIRO_NOHOST 0x00000400U /**< Exclude local hostname. */
84 # define SIRO_NOLEVEL 0x00000800U /**< Exclude human-readable logging level. */
85 # define SIRO_NONAME 0x00001000U /**< Exclude process/app name. */
86 # define SIRO_NOPID 0x00002000U /**< Exclude process ID. */
87 # define SIRO_NOTID 0x00004000U /**< Exclude thread ID/name. */
88 # define SIRO_NOHDR 0x00010000U /**< Don't write header messages to log files. */
89 # define SIRO_MSGONLY 0x00007f00U /**< Sets all other options except ::SIRO_NOHDR. */
90 # define SIRO_DEFAULT 0x00100000U /**< Default options for this type of destination. */
91
92 /** The ::sir_option type. */
93 typedef uint32_t sir_option;
94
95 /** ::sir_option bitmask type. */
96 typedef uint32_t sir_options;
97
98 /** Color mode selection. */
99 typedef enum {
100 SIRCM_16 = 0, /**< 4-bit 16-color mode. */
101 SIRCM_256 = 1, /**< 8-bit 256-color mode. */
102 SIRCM_RGB = 2, /**< 24-bit RGB-color mode. */
103 SIRCM_INVALID = 3 /**< Represents the invalid color mode. */
104 } sir_colormode;
105
106 /** Attributes for stdio output. */
107 typedef enum {
108 SIRTA_NORMAL = 0, /**< Normal text. */
109 SIRTA_BOLD = 1, /**< Bold text. */
110 SIRTA_DIM = 2, /**< Dimmed text. */
111 SIRTA_EMPH = 3, /**< Italicized/emphasized text. */
112 SIRTA_ULINE = 4, /**< Underlined text. */
113 } sir_textattr;
114
115 /** Colors for stdio output (16-color mode). */
116 enum {
117 /* 4-bit (16-color). */
118 SIRTC_BLACK = 0, /**< Black. */
119 SIRTC_RED = 1, /**< Red. */
120 SIRTC_GREEN = 2, /**< Green. */
121 SIRTC_YELLOW = 3, /**< Yellow. */
122 SIRTC_BLUE = 4, /**< Blue. */
123 SIRTC_MAGENTA = 5, /**< Magenta. */
124 SIRTC_CYAN = 6, /**< Cyan. */
125 SIRTC_LGRAY = 7, /**< Light gray. */
126 SIRTC_DGRAY = 8, /**< Dark gray. */
127 SIRTC_BRED = 9, /**< Bright red. */
128 SIRTC_BGREEN = 10, /**< Bright green. */
129 SIRTC_BYELLOW = 11, /**< Bright yellow. */
130 SIRTC_BBLUE = 12, /**< Bright blue. */
131 SIRTC_BMAGENTA = 13, /**< Bright magenta. */
132 SIRTC_BCYAN = 14, /**< Bright cyan. */
133 SIRTC_WHITE = 15, /**< White. */
134 /* 8-bit (256-color) and 24-bit (RGB color) modes:
135 * use the numeric representation (16..255) instead of an enum.
136 * these colors do not have defined names like the above. */
137 SIRTC_DEFAULT = 256 /**< Represents the default color. */
138 };
139
140 /** stdio text color type. */
141 typedef uint32_t sir_textcolor;
142
143 /**
144 * @struct sir_errorinfo
145 * @brief Information about an error that occurred.
146 *
147 * Granular error information in order to provide the caller with flexibility in
148 * regards to error handling and formatting.
149 */
150 typedef struct {
151 const char* func; /**< Name of the function in which the error occurred. */
152 const char* file; /**< Name of the file in which the error occurred. */
153 uint32_t line; /**< Line number at which the error occurred. */
154 int os_code; /**< If an OS/libc error, the relevant code. */
155 char os_msg[SIR_MAXERROR]; /**< If an OS/libc error, the relevant message. */
156 uint16_t code; /**< Numeric error code (see ::sir_errorcode). */
157 char msg[SIR_MAXERROR]; /**< Error message associated with code. */
158 } sir_errorinfo;
159
160 /**
161 * @struct sir_textstyle
162 * @brief Container for all the information associated with the appearance of text
163 * in the context of stdio.
164 *
165 * For 4-bit (16-color) and 8-bit (256-color) modes, fg and bg are simply the
166 * associated SIRTC_* value. For 24-bit RGB color mode, fg and bg are packed as
167 * follows: 0x00rrggbb.
168 */
169 typedef struct {
170 sir_textattr attr; /**< Text attributes. */
171 sir_textcolor fg; /**< Foreground color. */
172 sir_textcolor bg; /**< Background color. */
173 } sir_textstyle;
174
175 /**
176 * @struct sir_stdio_dest
177 * @brief Configuration for stdio destinations (stdout and stderr).
178 *
179 * @see ::sir_syslog_dest
180 */
181 typedef struct {
182 /** ::sir_level bitmask defining output levels to register for. */
183 sir_levels levels;
184
185 /** ::sir_option bitmask defining the formatting of output. */
186 sir_options opts;
187 } sir_stdio_dest;
188
189 /**
190 * @struct sir_syslog_dest
191 * @brief Configuration for the system logger destination.
192 *
193 * @see ::sir_stdio_dest
194 */
195 typedef struct {
196 sir_levels levels; /**< ::sir_level bitmask defining levels to register for. */
197
198 /**
199 * ::sir_option bitmask defining the formatting of output.
200 *
201 * @remark Unlike the stdio and log file destinations, not all options are
202 * supported. This is due to the fact that system logging facilities typically
203 * already include the information represented by ::sir_option on their own.
204 *
205 * Furthermore, the supported options vary based on the system logging
206 * facility in use.
207 *
208 * @note If your system supports syslog, and libsir is compiled with the intent
209 * to use it (SIR_SYSLOG_ENABLED is defined), then at least SIRO_NOPID is
210 * supported.
211 */
212 sir_options opts;
213
214 /** Reserved for internal use; do not modify. */
215 struct {
216 uint32_t mask; /**< State bitmask. */
217 void* logger; /**< System logger handle/identifier. */
218 } _state;
219
220 /**
221 * The identity string to pass to the system logger.
222 * @see ::sir_syslogid
223 */
224 char identity[SIR_MAX_SYSLOG_ID];
225
226 /**
227 * The category string to pass to the system logger.
228 * @see ::sir_syslogcat
229 */
230 char category[SIR_MAX_SYSLOG_CAT];
231 } sir_syslog_dest;
232
233 /**
234 * @struct sirinit
235 * @brief libsir initialization and configuration data.
236 *
237 * @note Pass a pointer to an instance of this structure to ::sir_init
238 * to begin using libsir.
239 *
240 * @see ::sir_makeinit
241 * @see ::sir_stdio_dest
242 * @see ::sir_syslog_dest
243 */
244 typedef struct {
245 sir_stdio_dest d_stdout; /**< stdout configuration. */
246 sir_stdio_dest d_stderr; /**< stderr configuration. */
247 sir_syslog_dest d_syslog; /**< System logger configuration. */
248
249 /**
250 * The name to use in log messages (usually the process name). Set ::SIRO_NONAME
251 * in a destination's options bitmask to suppress it.
252 */
253 char name[SIR_MAXNAME];
254 } sirinit;
255
256 /**
257 * @}
258 * @}
259 */
260
261 /** Magic number used to determine if libsir has been initialized. */
262 # define _SIR_MAGIC 0x60906090U
263
264 /** System logger facility state flags. */
265 # define SIRSL_IS_OPEN 0x00000001U /**< Log is open. */
266 # define SIRSL_LEVELS 0x00000002U /**< Level registrations. */
267 # define SIRSL_OPTIONS 0x00000004U /**< Formatting options. */
268 # define SIRSL_CATEGORY 0x00000008U /**< Category. */
269 # define SIRSL_IDENTITY 0x00000010U /**< Identity. */
270 # define SIRSL_UPDATED 0x00000020U /**< Config has been updated. */
271 # define SIRSL_IS_INIT 0x00000040U /**< Subsystem is initialized. */
272
273 # if defined(__WIN__)
274 /** Invalid parameter handler used when passing possibly invalid values to
275 * certain Windows libc calls. Without it, the default behavior is to abort. */
276 typedef void (*invalparamfn)(const wchar_t*, const wchar_t*, const wchar_t*,
277 unsigned int, uintptr_t);
278 # endif
279
280 /** Internally-used time value type. */
281 typedef struct {
282 # if !defined(__WIN__)
283 time_t sec;
284 long msec;
285 # else /* __WIN__ */
286 LARGE_INTEGER counter;
287 # endif
288 } sir_time;
289
290 /** Internally-used global config container. */
291 typedef struct {
292 sirinit si;
293 struct {
294 char hostname[SIR_MAXHOST];
295 time_t last_hname_chk;
296 char pidbuf[SIR_MAXPID];
297 pid_t pid;
298 char timestamp[SIR_MAXTIME];
299
300 /** Spam squelch state data. */
301 struct {
302 bool squelch;
303 uint64_t hash;
304 char prefix[2];
305 sir_level level;
306 size_t counter;
307 size_t threshold;
308 } last;
309 } state;
310 } sirconfig;
311
312 /** Internally-used log file data. */
313 typedef struct {
314 const char* path;
315 sir_levels levels;
316 sir_options opts;
317 FILE* f;
318 sirfileid id;
319 int writes_since_size_chk;
320 } sirfile;
321
322 /** Log file cache. */
323 typedef struct {
324 sirfile* files[SIR_MAXFILES];
325 size_t count;
326 } sirfcache;
327
328 /** The libsir-to-plugin query data structure. */
329 typedef struct {
330 uint8_t iface_ver; /**< Plugin interface version. */
331 uint8_t maj_ver; /**< Major version number. */
332 uint8_t min_ver; /**< Minor version number. */
333 uint8_t bld_ver; /**< Build/patch version number. */
334 sir_levels levels; /**< Level registration bitmask. */
335 sir_options opts; /**< Formatting options bitmask. */
336 const char* author; /**< Plugin author information. */
337 const char* desc; /**< Plugin description. */
338 uint64_t caps; /**< Plugin capabilities bitmask. */
339 } sir_plugininfo;
340
341 /** Plugin versioning. */
342 # define SIR_PLUGIN_V1 1
343 # define SIR_PLUGIN_VCURRENT SIR_PLUGIN_V1
344
345 /** Plugin export names for v1. */
346 # define SIR_PLUGIN_EXPORT_QUERY "sir_plugin_query"
347 # define SIR_PLUGIN_EXPORT_INIT "sir_plugin_init"
348 # define SIR_PLUGIN_EXPORT_WRITE "sir_plugin_write"
349 # define SIR_PLUGIN_EXPORT_CLEANUP "sir_plugin_cleanup"
350
351 /** Plugin export typedefs for v1. */
352 typedef bool (*sir_plugin_queryfn)(sir_plugininfo*);
353 typedef bool (*sir_plugin_initfn)(void);
354 typedef bool (*sir_plugin_writefn)(sir_level, const char*);
355 typedef bool (*sir_plugin_cleanupfn)(void);
356
357 /** Plugin interface for v1. */
358 typedef struct {
359 sir_plugin_queryfn query; /**< Address of sir_plugin_query. */
360 sir_plugin_initfn init; /**< Address of sir_plugin_init. */
361 sir_plugin_writefn write; /**< Address of sir_plugin_write. */
362 sir_plugin_cleanupfn cleanup; /**< Address of sir_plugin_cleanup. */
363 } sir_pluginifacev1;
364
365 typedef sir_pluginifacev1 sir_pluginiface;
366
367 /** Internally-used plugin module data. */
368 typedef struct {
369 const char* path;
370 sir_pluginhandle handle;
371 sir_plugininfo info;
372 bool loaded;
373 bool valid;
374 sir_pluginiface iface;
375 sirpluginid id;
376 } sir_plugin;
377
378 /** Plugin module cache. */
379 typedef struct {
380 sir_plugin* plugins[SIR_MAXPLUGINS];
381 size_t count;
382 } sir_plugincache;
383
384 /** A node in a sir_queue. */
385 typedef struct _sir_queue_node {
386 struct _sir_queue_node* next;
387 void* data;
388 } sir_queue_node;
389
390 /** FIFO queue. */
391 typedef struct {
392 sir_queue_node* head; /**< The first node in the linked list. */
393 } sir_queue;
394
395 /** Job used by a job queue. */
396 typedef struct {
397 bool (*fn)(void*); /**< Callback to be executed as part of the job. */
398 void* data; /**< Data to pass to the callback. */
399 } sir_threadpool_job;
400
401 /** Thread pool/job queue data container. */
402 typedef struct {
403 sir_thread* threads; /**< A list of thread handles. */
404 size_t num_threads; /**< The number of threads in the pool. */
405 sir_queue* jobs; /**< A queue of jobs to run (FIFO). */
406 sir_condition cond; /**< A condition which indicates that a job is ready. */
407 sir_mutex mutex; /**< A mutex to be paired with the condition variable. */
408 bool cancel; /**< Causes threads in the pool to exit when true. */
409 } sir_threadpool;
410
411 /** Formatted output container. */
412 typedef struct {
413 char style[SIR_MAXSTYLE];
414 char* timestamp;
415 char msec[SIR_MAXMSEC];
416 const char* hostname;
417 const char* pid;
418 const char* level;
419 const char* name;
420 char tid[SIR_MAXPID];
421 char message[SIR_MAXMESSAGE];
422 char output[SIR_MAXOUTPUT];
423 size_t output_len;
424 } sirbuf;
425
426 /** ::sir_level <-> ::sir_textstyle mapping. */
427 typedef struct {
428 const sir_level level; /**< The level for which the style applies. */
429 sir_textstyle style; /**< The un-formatted representation. */
430 char str[SIR_MAXSTYLE]; /**< The formatted string representation. */
431 } sir_level_style_tuple;
432
433 /** Container for text style related data that is mutex protected. */
434 typedef struct {
435 sir_level_style_tuple* map;
436 sir_colormode* color_mode;
437 } sir_text_style_data;
438
439 /** ::sir_level <-> human-readable string form. */
440 typedef struct {
441 const sir_level level; /**< The level for which the string applies. */
442 const char* fmt; /**< The formatted string representation. */
443 } sir_level_str_pair;
444
445 /** Mutex <-> protected section mapping. */
446 typedef enum {
447 SIRMI_CONFIG = 0, /**< The ::sirconfig section. */
448 SIRMI_FILECACHE, /**< The ::sirfcache section. */
449 SIRMI_PLUGINCACHE, /**< The ::sir_plugincache section. */
450 # if !defined(SIR_NO_TEXT_STYLING)
451 SIRMI_TEXTSTYLE, /**< The ::sir_level_style_tuple section. */
452 # endif
453 } sir_mutex_id;
454
455 /** Per-thread error type. */
456 typedef struct {
457 uint32_t lasterror;
458 int os_code;
459 char os_msg[SIR_MAXERROR];
460
461 struct {
462 const char* func;
463 const char* file;
464 uint32_t line;
465 } loc;
466 } sir_thread_err;
467
468 /** Bitmask defining which values are to be updated in the global config. */
469 typedef uint32_t sir_config_data_field;
470
471 # define SIRU_LEVELS 0x00000001U /**< Update level registrations. */
472 # define SIRU_OPTIONS 0x00000002U /**< Update formatting options. */
473 # define SIRU_SYSLOG_ID 0x00000004U /**< Update system logger identity. */
474 # define SIRU_SYSLOG_CAT 0x00000008U /**< Update system logger category. */
475 # define SIRU_ALL 0x0000000fU /**< Update all available fields. */
476
477 /** Encapsulates dynamic updating of current configuration. */
478 typedef struct {
479 uint32_t fields; /**< ::sir_config_data_field bitmask. */
480 sir_levels* levels; /**< Level registrations. */
481 sir_options* opts; /**< Formatting options. */
482 const char* sl_identity; /**< System logger identity. */
483 const char* sl_category; /**< System logger category. */
484 } sir_update_config_data;
485
486 #endif /* !_SIR_TYPES_H_INCLUDED */