• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aremmell / libsir / 376

03 Sep 2023 10:18AM UTC coverage: 94.796% (-0.09%) from 94.888%
376

push

gitlab-ci

aremmell
update config.h to use %Y instead of %y (gcc warnings)

3060 of 3228 relevant lines covered (94.8%)

621037.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.32
/src/sirinternal.c
1
/*
2
 * sirinternal.c
3
 *
4
 * Author:    Ryan M. Lederman <lederman@gmail.com>
5
 * Copyright: Copyright (c) 2018-2023
6
 * Version:   2.2.3
7
 * License:   The MIT License (MIT)
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
 * this software and associated documentation files (the "Software"), to deal in
11
 * the Software without restriction, including without limitation the rights to
12
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
 * the Software, and to permit persons to whom the Software is furnished to do so,
14
 * subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
#include "sir/internal.h"
27
#include "sir/console.h"
28
#include "sir/defaults.h"
29
#include "sir/filecache.h"
30
#include "sir/plugins.h"
31
#include "sir/textstyle.h"
32
#include "sir/filesystem.h"
33
#include "sir/mutex.h"
34

35
#if defined(__WIN__)
36
# if defined(__EMBARCADEROC__) && defined(_WIN64)
37
#  pragma comment(lib, "ws2_32.a")
38
# else
39
#  pragma comment(lib, "ws2_32.lib")
40
# endif
41
#endif
42

43
static sirconfig _sir_cfg      = {0};
44
static sirfcache _sir_fc       = {0};
45
static sir_plugincache _sir_pc = {0};
46

47
static sir_mutex cfg_mutex = SIR_MUTEX_INIT;
48
static sir_once cfg_once   = SIR_ONCE_INIT;
49

50
static sir_mutex fc_mutex  = SIR_MUTEX_INIT;
51
static sir_once fc_once    = SIR_ONCE_INIT;
52

53
static sir_mutex pc_mutex  = SIR_MUTEX_INIT;
54
static sir_once pc_once    = SIR_ONCE_INIT;
55

56
static sir_mutex ts_mutex  = SIR_MUTEX_INIT;
57
static sir_once ts_once    = SIR_ONCE_INIT;
58

59
static sir_once magic_once = SIR_ONCE_INIT;
60

61
#if defined(__HAVE_ATOMIC_H__)
62
static atomic_uint_fast32_t _sir_magic;
63
#else
64
static volatile uint32_t _sir_magic;
65
#endif
66

67
static _sir_thread_local char _sir_tid[SIR_MAXPID] = {0};
68

69
bool _sir_makeinit(sirinit* si) {
55✔
70
    bool retval = _sir_validptr(si);
55✔
71

72
    if (retval) {
55✔
73
        memset(si, 0, sizeof(sirinit));
49✔
74

75
        si->d_stdout.opts   = SIRO_DEFAULT;
55✔
76
        si->d_stdout.levels = SIRL_DEFAULT;
55✔
77

78
        si->d_stderr.opts   = SIRO_DEFAULT;
55✔
79
        si->d_stderr.levels = SIRL_DEFAULT;
55✔
80

81
#if !defined(SIR_NO_SYSTEM_LOGGERS)
82
        si->d_syslog.opts   = SIRO_DEFAULT;
42✔
83
        si->d_syslog.levels = SIRL_DEFAULT;
42✔
84
#else
85
        si->d_syslog.opts   = SIRO_MSGONLY;
13✔
86
        si->d_syslog.levels = SIRL_NONE;
13✔
87
#endif
88
    }
89

90
    return retval;
55✔
91
}
92

93
bool _sir_init(sirinit* si) {
801✔
94
    (void)_sir_seterror(_SIR_E_NOERROR);
801✔
95
    _sir_once(&magic_once, _sir_initialize_once);
801✔
96

97
    if (!_sir_validptr(si))
801✔
98
        return false;
19✔
99

100
#if defined(__HAVE_ATOMIC_H__)
101
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
779✔
102
#else
103
    if (_SIR_MAGIC == _sir_magic)
104
#endif
105
        return _sir_seterror(_SIR_E_ALREADY);
23✔
106

107
    _sir_defaultlevels(&si->d_stdout.levels, sir_stdout_def_lvls);
756✔
108
    _sir_defaultopts(&si->d_stdout.opts, sir_stdout_def_opts);
756✔
109

110
    _sir_defaultlevels(&si->d_stderr.levels, sir_stderr_def_lvls);
756✔
111
    _sir_defaultopts(&si->d_stderr.opts, sir_stderr_def_opts);
756✔
112

113
#if !defined(SIR_NO_SYSTEM_LOGGERS)
114
    _sir_defaultlevels(&si->d_syslog.levels, sir_syslog_def_lvls);
570✔
115
    _sir_defaultopts(&si->d_syslog.opts, sir_syslog_def_opts);
570✔
116
#endif
117

118
    if (!_sir_init_sanity(si))
756✔
119
        return false;
19✔
120

121
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
734✔
122

123
#if !defined(__WIN__)
124
    tzset();
734✔
125
#endif
126

127
#if defined(__HAVE_ATOMIC_H__)
128
    atomic_store(&_sir_magic, _SIR_MAGIC);
734✔
129
#else
130
    _sir_magic = _SIR_MAGIC;
131
#endif
132

133
#if defined(__WIN__)
134
    _sir_initialize_stdio();
135
#endif
136

137
    _sir_setcolormode(SIRCM_16);
734✔
138

139
    if (!_sir_resettextstyles())
734✔
140
        _sir_selflog("error: failed to reset text styles!");
×
141

142
    memset(&_cfg->state, 0, sizeof(_cfg->state));
734✔
143
    memcpy(&_cfg->si, si, sizeof(sirinit));
734✔
144

145
    /* forcibly null-terminate the process name. */
146
    _cfg->si.name[SIR_MAXNAME - 1] = '\0';
734✔
147

148
    /* Store PID. */
149
    _cfg->state.pid = _sir_getpid();
734✔
150

151
    (void)snprintf(_cfg->state.pidbuf, SIR_MAXPID, SIR_PIDFORMAT,
734✔
152
        PID_CAST _cfg->state.pid);
153

154
#if !defined(SIR_NO_SYSTEM_LOGGERS)
155
    /* initialize system logger. */
156
    _sir_syslog_reset(&_cfg->si.d_syslog);
554✔
157

158
    if (_cfg->si.d_syslog.levels != SIRL_NONE) {
554✔
159
        if (!_sir_syslog_init(_cfg->si.name, &_cfg->si.d_syslog))
96✔
160
            _sir_selflog("failed to initialize system logger!");
×
161
    }
162
#endif
163

164
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
734✔
165

166
    return true;
734✔
167
}
168

169
bool _sir_cleanup(void) {
756✔
170
    if (!_sir_sanity())
756✔
171
        return false;
19✔
172

173
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
734✔
174
    bool cleanup   = true;
632✔
175
    bool destroyfc = _sir_fcache_destroy(sfc);
734✔
176
    SIR_ASSERT(destroyfc);
700✔
177

178
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
734✔
179
    cleanup &= destroyfc;
632✔
180

181
#if !defined(SIR_NO_PLUGINS)
182
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
692✔
183
    bool destroypc = _sir_plugin_cache_destroy(spc);
692✔
184
    SIR_ASSERT(destroypc);
658✔
185
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
692✔
186
    cleanup &= destroypc;
590✔
187
#endif
188

189
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
734✔
190

191
#if !defined(SIR_NO_SYSTEM_LOGGERS)
192
    if (!_sir_syslog_close(&_cfg->si.d_syslog)) {
554✔
193
        cleanup = false;
×
194
        _sir_selflog("error: failed to close system logger!");
×
195
    }
196

197
    _sir_syslog_reset(&_cfg->si.d_syslog);
554✔
198
#endif
199

200
    if (!_sir_resettextstyles()) {
734✔
201
        cleanup = false;
×
202
        _sir_selflog("error: failed to reset text styles!");
×
203
    }
204

205
#if defined(__HAVE_ATOMIC_H__)
206
    atomic_store(&_sir_magic, 0);
734✔
207
#else
208
    _sir_magic = 0U;
209
#endif
210

211
    memset(_cfg, 0, sizeof(sirconfig));
632✔
212
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
734✔
213

214
    _sir_selflog("cleanup: %s", (cleanup ? "successful" : "with errors"));
700✔
215

216
    SIR_ASSERT(cleanup);
700✔
217
    return cleanup;
666✔
218
}
219

220
bool _sir_sanity(void) {
2,498,640✔
221
#if defined(__HAVE_ATOMIC_H__)
222
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,498,640✔
223
        return true;
2,418,388✔
224
#else
225
    if (_SIR_MAGIC == _sir_magic)
226
        return true;
227
#endif
228
    return _sir_seterror(_SIR_E_NOTREADY);
34✔
229
}
230

231
bool _sir_init_sanity(const sirinit* si) {
756✔
232
    if (!_sir_validptr(si))
756✔
233
        return false;
×
234

235
    bool levelcheck = true;
651✔
236
    levelcheck &= _sir_validlevels(si->d_stdout.levels);
756✔
237
    levelcheck &= _sir_validlevels(si->d_stderr.levels);
756✔
238

239
#if !defined(SIR_NO_SYSTEM_LOGGERS)
240
    levelcheck &= _sir_validlevels(si->d_syslog.levels);
570✔
241
#endif
242

243
    bool optscheck = true;
651✔
244
    optscheck &= _sir_validopts(si->d_stdout.opts);
756✔
245
    optscheck &= _sir_validopts(si->d_stderr.opts);
756✔
246

247
#if !defined(SIR_NO_SYSTEM_LOGGERS)
248
    optscheck &= _sir_validopts(si->d_syslog.opts);
570✔
249
#endif
250

251
    return levelcheck && optscheck;
756✔
252
}
253

254
static
255
bool _sir_updatelevels(const char* name, sir_levels* old, sir_levels* new) {
861✔
256
    if (*old != *new) {
861✔
257
        _sir_selflog("updating %s levels from %04"PRIx16" to %04"PRIx16, name, *old, *new);
778✔
258
        *old = *new;
823✔
259
    } else {
260
        _sir_selflog("skipped superfluous update of %s levels: %04"PRIx16, name, *old);
36✔
261
    }
262
    return true;
861✔
263
}
264

265
static
266
bool _sir_updateopts(const char* name, sir_options* old, sir_options* new) {
72,817✔
267
    if (*old != *new) {
72,817✔
268
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
34,883✔
269
        *old = *new;
36,961✔
270
    } else {
271
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
33,889✔
272
    }
273
    return true;
72,817✔
274
}
275

276
bool _sir_stdoutlevels(sirinit* si, sir_update_config_data* data) {
424✔
277
    return _sir_updatelevels(SIR_DESTNAME_STDOUT, &si->d_stdout.levels, data->levels);
424✔
278
}
279

280
bool _sir_stdoutopts(sirinit* si, sir_update_config_data* data) {
72,380✔
281
    return _sir_updateopts(SIR_DESTNAME_STDOUT, &si->d_stdout.opts, data->opts);
72,380✔
282
}
283

284
bool _sir_stderrlevels(sirinit* si, sir_update_config_data* data) {
380✔
285
    return _sir_updatelevels(SIR_DESTNAME_STDERR, &si->d_stderr.levels, data->levels);
380✔
286
}
287

288
bool _sir_stderropts(sirinit* si, sir_update_config_data* data) {
380✔
289
    return _sir_updateopts(SIR_DESTNAME_STDERR, &si->d_stderr.opts, data->opts);
380✔
290
}
291

292
bool _sir_sysloglevels(sirinit* si, sir_update_config_data* data) {
57✔
293
    bool updated = _sir_updatelevels(SIR_DESTNAME_SYSLOG, &si->d_syslog.levels, data->levels);
57✔
294
    if (updated) {
57✔
295
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
57✔
296
        updated = _sir_syslog_updated(si, data);
57✔
297
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
57✔
298
    }
299
    return updated;
57✔
300
}
301

302
bool _sir_syslogopts(sirinit* si, sir_update_config_data* data) {
57✔
303
    bool updated = _sir_updateopts(SIR_DESTNAME_SYSLOG, &si->d_syslog.opts, data->opts);
57✔
304
    if (updated) {
57✔
305
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
57✔
306
        updated = _sir_syslog_updated(si, data);
57✔
307
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
57✔
308
    }
309
    return updated;
57✔
310
}
311

312
bool _sir_syslogid(sirinit* si, sir_update_config_data* data) {
118✔
313
    bool cur_valid = _sir_validstrnofail(si->d_syslog.identity);
118✔
314
    if (!cur_valid || 0 != strncmp(si->d_syslog.identity, data->sl_identity, SIR_MAX_SYSLOG_ID)) {
118✔
315
        _sir_selflog("updating %s identity from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
72✔
316
            si->d_syslog.identity, data->sl_identity);
317
        _sir_strncpy(si->d_syslog.identity, SIR_MAX_SYSLOG_ID, data->sl_identity,
72✔
318
            strnlen(data->sl_identity, SIR_MAX_SYSLOG_ID));
319
    } else {
320
        _sir_selflog("skipped superfluous update of %s identity: '%s'", SIR_DESTNAME_SYSLOG,
43✔
321
            si->d_syslog.identity);
322
        return true;
43✔
323
    }
324

325
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
72✔
326
    bool updated = _sir_syslog_updated(si, data);
72✔
327
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
72✔
328

329
    return updated;
72✔
330
}
331

332
bool _sir_syslogcat(sirinit* si, sir_update_config_data* data) {
94✔
333
    bool cur_valid = _sir_validstrnofail(si->d_syslog.category);
94✔
334
    if (!cur_valid || 0 != strncmp(si->d_syslog.category, data->sl_category, SIR_MAX_SYSLOG_CAT)) {
94✔
335
        _sir_selflog("updating %s category from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
47✔
336
            si->d_syslog.category, data->sl_category);
337
        _sir_strncpy(si->d_syslog.category, SIR_MAX_SYSLOG_CAT, data->sl_category,
47✔
338
            strnlen(data->sl_category, SIR_MAX_SYSLOG_CAT));
339
    } else {
340
        _sir_selflog("skipped superfluous update of %s category: '%s'", SIR_DESTNAME_SYSLOG,
44✔
341
            si->d_syslog.identity);
342
        return true;
44✔
343
    }
344

345
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
346
    bool updated = _sir_syslog_updated(si, data);
47✔
347
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
348

349
    return updated;
47✔
350
}
351

352
bool _sir_writeinit(sir_update_config_data* data, sirinit_update update) {
73,890✔
353
    (void)_sir_seterror(_SIR_E_NOERROR);
73,890✔
354

355
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
73,888✔
356
        return false;
×
357

358
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
73,885✔
359

360
    bool updated = update(&_cfg->si, data);
73,890✔
361
    if (!updated)
69,785✔
362
        _sir_selflog("error: update routine failed!");
×
363

364
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
73,890✔
365
    return updated;
73,889✔
366
}
367

368
void* _sir_locksection(sir_mutex_id mid) {
9,057,295✔
369
    sir_mutex* m = NULL;
9,057,295✔
370
    void* sec    = NULL;
9,057,295✔
371

372
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
9,057,295✔
373
    SIR_ASSERT(enter);
9,003,168✔
374

375
    return enter ? sec : NULL;
9,058,583✔
376
}
377

378
void _sir_unlocksection(sir_mutex_id mid) {
9,058,141✔
379
    sir_mutex* m = NULL;
9,058,141✔
380
    void* sec    = NULL;
9,058,141✔
381

382
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
9,058,141✔
383
    SIR_ASSERT_UNUSED(leave, leave);
9,004,348✔
384
}
9,059,971✔
385

386
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
18,109,528✔
387
    sir_mutex* tmpm;
388
    void* tmpsec;
389

390
    switch (mid) {
18,109,528✔
391
        case SIRMI_CONFIG:
8,777,865✔
392
            _sir_once(&cfg_once, _sir_initmutex_cfg_once);
8,777,865✔
393
            tmpm   = &cfg_mutex;
8,658,074✔
394
            tmpsec = &_sir_cfg;
8,658,074✔
395
            break;
8,777,885✔
396
        case SIRMI_FILECACHE:
4,472,221✔
397
            _sir_once(&fc_once, _sir_initmutex_fc_once);
4,472,221✔
398
            tmpm   = &fc_mutex;
4,396,815✔
399
            tmpsec = &_sir_fc;
4,396,815✔
400
            break;
4,472,382✔
401
        case SIRMI_PLUGINCACHE:
240,207✔
402
            _sir_once(&pc_once, _sir_initmutex_pc_once);
240,207✔
403
            tmpm   = &pc_mutex;
200,949✔
404
            tmpsec = &_sir_pc;
200,949✔
405
            break;
240,207✔
406
        case SIRMI_TEXTSTYLE:
4,629,007✔
407
            _sir_once(&ts_once, _sir_initmutex_ts_once);
4,629,007✔
408
            tmpm   = &ts_mutex;
4,529,815✔
409
            tmpsec = &sir_text_style_section;
4,529,815✔
410
            break;
4,629,017✔
411
        // GCOVR_EXCL_START
412
        default: /* this should never happen. */
413
            SIR_ASSERT(mid);
414
            tmpm   = NULL;
415
            tmpsec = NULL;
416
            break;
417
        // GCOVR_EXCL_STOP
418
    }
419

420
    *m = tmpm;
18,119,491✔
421

422
    if (section)
18,119,491✔
423
        *section = tmpsec;
18,110,196✔
424

425
    return *m != NULL && (!section || *section != NULL);
18,119,491✔
426
}
427

428
#if !defined(__WIN__)
429
void _sir_initialize_once(void) {
57✔
430
# if defined(__HAVE_ATOMIC_H__)
431
    atomic_init(&_sir_magic, 0);
57✔
432
# endif
433
}
57✔
434

435
void _sir_initmutex_cfg_once(void) {
57✔
436
    bool created = _sir_mutexcreate(&cfg_mutex);
57✔
437
    SIR_ASSERT_UNUSED(created, created);
55✔
438
}
57✔
439

440
void _sir_initmutex_fc_once(void) {
57✔
441
    bool created = _sir_mutexcreate(&fc_mutex);
57✔
442
    SIR_ASSERT_UNUSED(created, created);
55✔
443
}
57✔
444

445
void _sir_initmutex_pc_once(void) {
48✔
446
    bool created = _sir_mutexcreate(&pc_mutex);
48✔
447
    SIR_ASSERT_UNUSED(created, created);
46✔
448
}
48✔
449

450
void _sir_initmutex_ts_once(void) {
57✔
451
    bool created = _sir_mutexcreate(&ts_mutex);
57✔
452
    SIR_ASSERT_UNUSED(created, created);
55✔
453
}
57✔
454

455
#else /* __WIN__ */
456
BOOL CALLBACK _sir_initialize_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
457
    SIR_UNUSED(ponce);
458
    SIR_UNUSED(param);
459
    SIR_UNUSED(ctx);
460
    return TRUE;
461
}
462

463
BOOL CALLBACK _sir_initmutex_cfg_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
464
    SIR_UNUSED(ponce);
465
    SIR_UNUSED(param);
466
    SIR_UNUSED(ctx);
467

468
    if (!_sir_mutexcreate(&cfg_mutex)) {
469
        SIR_ASSERT(!"failed to create mutex!");
470
        return FALSE;
471
    }
472

473
    return TRUE;
474
}
475

476
BOOL CALLBACK _sir_initmutex_fc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
477
    SIR_UNUSED(ponce);
478
    SIR_UNUSED(param);
479
    SIR_UNUSED(ctx);
480

481
    if (!_sir_mutexcreate(&fc_mutex)) {
482
        SIR_ASSERT(!"failed to create mutex!");
483
        return FALSE;
484
    }
485

486
    return TRUE;
487
}
488

489
BOOL CALLBACK _sir_initmutex_pc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
490
    SIR_UNUSED(ponce);
491
    SIR_UNUSED(param);
492
    SIR_UNUSED(ctx);
493

494
    if (!_sir_mutexcreate(&pc_mutex)) {
495
        SIR_ASSERT(!"failed to create mutex!");
496
        return FALSE;
497
    }
498

499
    return TRUE;
500
}
501

502
BOOL CALLBACK _sir_initmutex_ts_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
503
    SIR_UNUSED(ponce);
504
    SIR_UNUSED(param);
505
    SIR_UNUSED(ctx);
506

507
    if (!_sir_mutexcreate(&ts_mutex)) {
508
        SIR_ASSERT(!"failed to create mutex!");
509
        return FALSE;
510
    }
511

512
    return TRUE;
513
}
514
#endif
515

516
bool _sir_once(sir_once* once, sir_once_fn func) {
18,108,929✔
517
#if !defined(__WIN__)
518
    int ret = pthread_once(once, func);
18,108,929✔
519
    return 0 == ret ? true : _sir_handleerr(ret);
18,110,128✔
520
#else /* __WIN__ */
521
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
522
        : _sir_handlewin32err(GetLastError());
523
#endif
524
}
525

526
PRINTF_FORMAT_ATTR(2, 0)
527
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,156,915✔
528
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,156,915✔
529
        return false;
44✔
530

531
    (void)_sir_seterror(_SIR_E_NOERROR);
2,156,872✔
532

533
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,156,872✔
534

535
    sirbuf buf = {0};
2,156,875✔
536

537
    /* from time to time, update the host name in the config, just in case. */
538
    time_t now_sec = -1;
2,156,875✔
539
    if (-1 != time(&now_sec) &&
2,156,875✔
540
        (now_sec - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,148,963✔
541
        _sir_selflog("updating hostname...");
8,299✔
542
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,321✔
543
            _sir_selflog("error: failed to get hostname!");
7,912✔
544
        } else {
545
            _cfg->state.last_hname_chk = now_sec;
409✔
546
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
387✔
547
        }
548
    }
549

550
    sir_time now;
551
    int64_t msec_since_chk = _sir_msec_since(&_cfg->state.last_misc_chk, &now);
2,156,875✔
552

553
    /* update milliseconds. */
554
    _sir_snprintf_trunc(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, now.msec);
2,156,875✔
555

556
    /* update hours/minutes/seconds. */
557
    bool fmt = _sir_formattime(now.sec, buf.timestamp, SIR_TIMEFORMAT);
2,156,875✔
558
    SIR_ASSERT_UNUSED(fmt, fmt);
2,148,963✔
559

560
    /* update the string form of the timestamp (h/m/s) and the thread identifier/name
561
     * if SIR_MISC_CHK_INTERVAL milliseconds have elapsed since the last update. */
562
    if (msec_since_chk > SIR_MISC_CHK_INTERVAL) {
2,156,875✔
563
/*         _cfg->state.last_misc_chk.sec  = now.sec;
564
        _cfg->state.last_misc_chk.msec = now.msec; */
565
        _cfg->state.last_misc_chk = now;
727✔
566

567
        /* update the thread identifier/name. decide how to identify this thread
568
         * based on the configuration, and whether or not its identifier is
569
         * identical to the process identifier. */
570
        pid_t tid         = _sir_gettid();
727✔
571
        bool resolved_tid = false;
636✔
572

573
        if (tid == _cfg->state.pid) {
727✔
574
#if SIR_DUPE_THREAD_ID_USE_NAME
575
            /* if a name is set, use it. */
576
            resolved_tid = _sir_getthreadname(_sir_tid);
596✔
577
#else
578
            /* don't use anything to identify the thread. */
579
            _sir_resetstr(_sir_tid);
580
            resolved_tid = true;
581
#endif
582
        }
583

584
#if !SIR_PREFER_THREAD_ID
585
        if (!resolved_tid)
705✔
586
            resolved_tid = _sir_getthreadname(_sir_tid);
265✔
587
#endif
588

589
        if (!resolved_tid)
682✔
590
            _sir_snprintf_trunc(_sir_tid, SIR_MAXPID, SIR_PIDFORMAT,
134✔
591
                PID_CAST tid);
592
    }
593

594
    sirconfig cfg;
595
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,133,139✔
596
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,875✔
597

598
    buf.hostname  = cfg.state.hostname;
2,156,875✔
599
    buf.pid       = cfg.state.pidbuf;
2,156,875✔
600
    buf.name      = cfg.si.name;
2,156,875✔
601

602
    const char* style_str = _sir_gettextstyle(level);
2,156,875✔
603

604
    SIR_ASSERT(NULL != style_str);
2,148,963✔
605
    if (NULL != style_str)
2,141,051✔
606
        (void)_sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,156,875✔
607
            strnlen(style_str, SIR_MAXSTYLE));
608

609
    buf.level = _sir_formattedlevelstr(level);
2,156,875✔
610

611
    (void)_sir_strncpy(buf.tid, SIR_MAXPID, _sir_tid, SIR_MAXPID);
2,156,875✔
612

613
    (void)vsnprintf(buf.message, SIR_MAXMESSAGE, format, args);
2,133,136✔
614

615
    if (!_sir_validstr(buf.message))
2,156,872✔
616
        return _sir_seterror(_SIR_E_INTERNAL);
22✔
617

618
    bool match             = false;
2,133,119✔
619
    bool exit_early        = false;
2,133,119✔
620
    bool update_last_props = true;
2,133,119✔
621
    uint64_t hash          = 0ULL;
2,133,119✔
622

623
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,156,852✔
624
        cfg.state.last.prefix[1] == buf.message[1]) {
2,102,572✔
625
        hash  = FNV64_1a(buf.message);
2,120,740✔
626
        match = cfg.state.last.hash == hash;
2,120,740✔
627
    }
628

629
    if (match) {
2,151,938✔
630
        cfg.state.last.counter++;
33,724✔
631

632
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
633
            cfg.state.last.counter); */
634

635
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
33,724✔
636
            size_t old_threshold = cfg.state.last.threshold;
916✔
637

638
            update_last_props = false;
916✔
639
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
1,060✔
640
            cfg.state.last.squelch = true;
1,060✔
641

642
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
1,012✔
643
                         " to %zu (factor: %d)",
644
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
645

646
            (void)snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold);
916✔
647
        } else if (cfg.state.last.squelch) {
32,664✔
648
            exit_early = true;
26,734✔
649
        }
650
    } else {
651
        cfg.state.last.squelch   = false;
2,123,128✔
652
        cfg.state.last.counter   = 0;
2,123,128✔
653
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,123,128✔
654
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
655
    }
656

657
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,156,852✔
658
    if (!_cfg)
2,156,853✔
659
        return _sir_seterror(_SIR_E_INTERNAL);
×
660

661
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,156,853✔
662

663
    if (update_last_props) {
2,156,853✔
664
        _cfg->state.last.hash      = hash;
2,155,793✔
665
        _cfg->state.last.prefix[0] = buf.message[0];
2,155,793✔
666
        _cfg->state.last.prefix[1] = buf.message[1];
2,155,793✔
667
    }
668

669
    _cfg->state.last.counter   = cfg.state.last.counter;
2,156,853✔
670
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,156,853✔
671

672
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,853✔
673

674
    if (exit_early)
2,156,849✔
675
        return false;
26,734✔
676

677
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,125,894✔
678
    return update_last_props ? dispatched : false;
2,125,898✔
679
}
680

681
bool _sir_dispatch(sirinit* si, sir_level level, sirbuf* buf) {
2,125,894✔
682
    bool retval       = true;
2,106,383✔
683
    size_t dispatched = 0;
2,106,383✔
684
    size_t wanted     = 0;
2,106,383✔
685

686
    if (_sir_bittest(si->d_stdout.levels, level)) {
2,125,894✔
687
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,122,266✔
688
        bool wrote        = _sir_validstrnofail(write) &&
2,244,535✔
689
            _sir_write_stdout(write, buf->output_len);
1,122,267✔
690
        retval &= wrote;
1,122,268✔
691

692
        if (wrote)
1,122,268✔
693
            dispatched++;
1,097,130✔
694
        wanted++;
1,103,347✔
695
    }
696

697
    if (_sir_bittest(si->d_stderr.levels, level)) {
2,125,896✔
698
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,099✔
699
        bool wrote        = _sir_validstrnofail(write) &&
2,198✔
700
            _sir_write_stderr(write, buf->output_len);
1,099✔
701
        retval &= wrote;
1,099✔
702

703
        if (wrote)
1,099✔
704
            dispatched++;
1,090✔
705
        wanted++;
1,099✔
706
    }
707

708
#if !defined(SIR_NO_SYSTEM_LOGGERS)
709
    if (_sir_bittest(si->d_syslog.levels, level)) {
2,091,512✔
710
        if (_sir_syslog_write(level, buf, &si->d_syslog))
594✔
711
            dispatched++;
594✔
712
        wanted++;
594✔
713
    }
714
#endif
715

716
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,125,894✔
717
    size_t fdispatched = 0;
2,125,898✔
718
    size_t fwanted     = 0;
2,125,898✔
719
    retval &= _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted);
2,125,898✔
720
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,125,898✔
721

722
    dispatched += fdispatched;
2,125,898✔
723
    wanted += fwanted;
2,125,898✔
724

725
#if !defined(SIR_NO_PLUGINS)
726
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
119,319✔
727
    size_t pdispatched = 0;
119,319✔
728
    size_t pwanted     = 0;
119,319✔
729
    retval &= _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted);
119,319✔
730
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
119,319✔
731

732
    dispatched += pdispatched;
119,319✔
733
    wanted += pwanted;
119,319✔
734
#endif
735

736
    if (0 == wanted) {
2,125,898✔
737
        _sir_selflog("error: no destinations registered for level %04"PRIx16, level);
897✔
738
        return _sir_seterror(_SIR_E_NODEST);
950✔
739
    }
740

741
    return retval && (dispatched == wanted);
2,124,948✔
742
}
743

744
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,271,176✔
745
    if (_sir_validptr(buf)) {
2,271,176✔
746
        bool first = true;
2,226,784✔
747

748
        _sir_resetstr(buf->output);
2,271,149✔
749

750
        if (styling)
2,271,195✔
751
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,123,364✔
752

753
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,271,181✔
754
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,107,788✔
755
            first = false;
2,089,201✔
756

757
#if defined(SIR_MSEC_TIMER)
758
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,107,791✔
759
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
71,463✔
760
#endif
761
        }
762

763
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,271,192✔
764
            if (!first)
1,033,521✔
765
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,538✔
766
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,033,521✔
767
            first = false;
1,027,246✔
768
        }
769

770
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,271,077✔
771
            if (!first)
2,158,224✔
772
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,107,937✔
773
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,158,215✔
774
            first = false;
2,132,687✔
775
        }
776

777
        bool name = false;
2,226,717✔
778
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,271,146✔
779
            if (!first)
1,101,432✔
780
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,097,464✔
781
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,101,423✔
782
            first = false;
1,082,952✔
783
            name  = true;
1,082,952✔
784
        }
785

786
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,271,218✔
787
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,271,486✔
788

789
        if (wantpid || wanttid) {
2,271,380✔
790
            if (name)
2,114,525✔
791
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,070,214✔
792
            else if (!first)
1,044,311✔
793
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,044,305✔
794

795
            if (wantpid)
2,114,534✔
796
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,076,407✔
797

798
            if (wanttid) {
2,114,528✔
799
                if (wantpid)
2,080,761✔
800
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
2,042,628✔
801
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
2,080,760✔
802
            }
803

804
            if (name)
2,114,526✔
805
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,070,232✔
806

807
            if (first)
2,094,656✔
808
                first = false;
6✔
809
        }
810

811
        if (!first)
2,251,511✔
812
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,193,924✔
813

814
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,271,367✔
815

816
        if (styling)
2,271,206✔
817
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,123,346✔
818

819
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,271,204✔
820

821
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,271,258✔
822

823
        return buf->output;
2,271,258✔
824
    }
825

826
    return NULL;
×
827
}
828

829
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
225✔
830
#if !defined(SIR_NO_SYSTEM_LOGGERS)
831
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
225✔
832
        return false;
×
833

834
    /* begin resolve identity. */
835
    if (!_sir_validstrnofail(ctx->identity)) {
225✔
836
        _sir_selflog("ctx->identity is no good; trying name");
47✔
837
        if (_sir_validstrnofail(name)) {
50✔
838
            _sir_selflog("using name");
28✔
839
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
30✔
840
        } else {
841
            _sir_selflog("name is no good; trying filename");
19✔
842
            char* appbasename = _sir_getappbasename();
20✔
843
            if (_sir_validstrnofail(appbasename)) {
20✔
844
                _sir_selflog("filename is good: %s", appbasename);
14✔
845
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
14✔
846
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
847
            } else {
848
                _sir_selflog("filename no good; using fallback");
6✔
849
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
6✔
850
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
851
            }
852
            _sir_safefree(&appbasename);
20✔
853
        }
854
    } else {
855
        _sir_selflog("already have identity");
165✔
856
    }
857

858
    /* category */
859
    if (!_sir_validstrnofail(ctx->category)) {
225✔
860
        _sir_selflog("category not set; using fallback");
71✔
861
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
75✔
862
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
863
    } else {
864
        _sir_selflog("already have category");
141✔
865
    }
866

867
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
225✔
868
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
212✔
869

870
    return _sir_syslog_open(ctx);
225✔
871
#else
872
    SIR_UNUSED(name);
873
    SIR_UNUSED(ctx);
874
    return false;
×
875
#endif
876
}
877

878
bool _sir_syslog_open(sir_syslog_dest* ctx) {
225✔
879
#if !defined(SIR_NO_SYSTEM_LOGGERS)
880
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
225✔
881
        _sir_selflog("not initialized; ignoring");
×
882
        return _sir_seterror(_SIR_E_INVALID);
×
883
    }
884

885
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
225✔
886
        _sir_selflog("log already open; ignoring");
97✔
887
        return true;
97✔
888
    }
889

890
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
122✔
891
        ctx->opts);
892

893
# if defined(SIR_OS_LOG_ENABLED)
894
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
895
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
896
# elif defined(SIR_SYSLOG_ENABLED)
897
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
122✔
898
    int facility = LOG_USER;
101✔
899

900
    openlog(ctx->identity, logopt, facility);
122✔
901
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
115✔
902
# endif
903

904
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
122✔
905
    return true;
122✔
906
#else
907
    SIR_UNUSED(ctx);
908
    return false;
×
909
#endif
910
}
911

912
bool _sir_syslog_write(sir_level level, const sirbuf* buf, sir_syslog_dest* ctx) {
594✔
913
#if !defined(SIR_NO_SYSTEM_LOGGERS)
914
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
594✔
915
        _sir_selflog("not initialized; ignoring");
×
916
        return _sir_seterror(_SIR_E_INVALID);
×
917
    }
918

919
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
594✔
920
        _sir_selflog("log not open; ignoring");
×
921
        return _sir_seterror(_SIR_E_INVALID);
×
922
    }
923

924
# if defined(SIR_OS_LOG_ENABLED)
925
    if (SIRL_DEBUG == level)
926
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
927
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
928
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
929
    else if (SIRL_WARN == level || SIRL_ERROR == level)
930
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
931
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
932
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
933

934
    return true;
935
# elif defined(SIR_SYSLOG_ENABLED)
936
    int syslog_level;
937
    switch (level) {
594✔
938
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
25✔
939
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
27✔
940
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
80✔
941
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
80✔
942
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
80✔
943
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
106✔
944
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
80✔
945
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
106✔
946
        // GCOVR_EXCL_START
947
        case SIRL_NONE: /* this should never happen. */
948
        default:
949
            SIR_ASSERT(level);
950
            syslog_level = LOG_DEBUG;
951
        // GCOVR_EXCL_STOP
952
    }
953

954
    syslog(syslog_level, "%s", buf->message);
594✔
955
    return true;
594✔
956
# endif
957
#else
958
    SIR_UNUSED(level);
959
    SIR_UNUSED(buf);
960
    SIR_UNUSED(ctx);
961
    return false;
×
962
#endif
963
}
964

965
bool _sir_syslog_updated(sirinit* si, sir_update_config_data* data) {
233✔
966
#if !defined(SIR_NO_SYSTEM_LOGGERS)
967
    if (!_sir_validptr(si) || !_sir_validptr(data))
233✔
968
        return false;
×
969

970
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
233✔
971
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
220✔
972
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
233✔
973
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
220✔
974
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
233✔
975
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
233✔
976
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
233✔
977

978
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
220✔
979
                     " identity: %u, is_init: %u, is_open: %u)",
980
                     levels, options, category, identity, is_init, is_open);
981

982
        bool must_init = false;
194✔
983

984
# if defined(SIR_OS_LOG_ENABLED)
985
        /*
986
         * for os_log, if initialized and open already, only need to reconfigure
987
         * if identity or category changed.
988
         */
989
        must_init = (!is_init || !is_open) || (identity || category);
990
# elif defined(SIR_SYSLOG_ENABLED)
991
        /*
992
         * for os_log, if initialized and open already, only need to reconfigure
993
         * if identity or options changed.
994
         */
995
        must_init = (!is_init || !is_open) || (identity || options);
233✔
996
# endif
997
        bool init = true;
194✔
998
        if (must_init) {
194✔
999
            _sir_selflog("re-init...");
122✔
1000
            init = _sir_syslog_init(si->name, &si->d_syslog);
129✔
1001
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
122✔
1002
        } else {
1003
            _sir_selflog("no re-init necessary");
98✔
1004
        }
1005

1006
        return init;
233✔
1007
    } else {
1008
        _sir_selflog("BUG: called without 'updated' flag set!");
×
1009
        return false;
×
1010
    }
1011
#else
1012
    SIR_UNUSED(si);
1013
    SIR_UNUSED(data);
1014
    return false;
×
1015
#endif
1016
}
1017

1018
bool _sir_syslog_close(sir_syslog_dest* ctx) {
554✔
1019
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1020
    if (!_sir_validptr(ctx))
554✔
1021
        return false;
×
1022

1023
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
554✔
1024
        _sir_selflog("log not open; ignoring");
405✔
1025
        return true;
405✔
1026
    }
1027

1028
# if defined(SIR_OS_LOG_ENABLED)
1029
    /* evidently, you don't need to close the handle returned from os_log_create(), and
1030
     * if you make that call again, you'll get the same cached value. so let's keep the
1031
     * value we've got in the global context. */
1032
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
1033
    _sir_selflog("log closure not necessary");
1034
    return true;
1035
# elif defined(SIR_SYSLOG_ENABLED)
1036
    closelog();
122✔
1037
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
122✔
1038
    _sir_selflog("closed log");
115✔
1039
    return true;
122✔
1040
# endif
1041
#else
1042
    SIR_UNUSED(ctx);
1043
    return false;
×
1044
#endif
1045
}
1046

1047
void _sir_syslog_reset(sir_syslog_dest* ctx) {
1,108✔
1048
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1049
    if (_sir_validptr(ctx)) {
1,108✔
1050
        uint32_t old       = ctx->_state.mask;
1,040✔
1051
        ctx->_state.mask   = 0U;
1,108✔
1052
        ctx->_state.logger = NULL;
1,108✔
1053
        _sir_selflog("state reset; mask was %08"PRIx32, old);
1,040✔
1054
    }
1055
#else
1056
    SIR_UNUSED(ctx);
1057
#endif
1058
}
1,108✔
1059

1060
const char* _sir_formattedlevelstr(sir_level level) {
2,156,875✔
1061
    static const size_t low  = 0;
1062
    static const size_t high = SIR_NUMLEVELS - 1;
1063

1064
    const char* retval = SIR_UNKNOWN;
2,133,139✔
1065

1066
    _SIR_DECLARE_BIN_SEARCH(low, high);
2,133,139✔
1067
    _SIR_BEGIN_BIN_SEARCH()
1068

1069
    if (sir_level_to_str_map[_mid].level == level) {
8,583,968✔
1070
        retval = sir_level_to_str_map[_mid].fmt;
2,156,875✔
1071
        break;
2,156,875✔
1072
    }
1073

1074
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1));
6,427,093✔
1075
    _SIR_END_BIN_SEARCH();
1076

1077
    return retval;
2,156,875✔
1078
}
1079

1080
bool _sir_clock_gettime(int64_t* tbuf, int64_t* msecbuf) {
2,156,875✔
1081
    if (tbuf) {
2,156,875✔
1082
        time_t ret = time((time_t*)tbuf);
2,156,875✔
1083
        if (-1 == ret) {
2,156,875✔
1084
            if (msecbuf)
7,912✔
1085
                *msecbuf = 0LL;
7,912✔
1086
            return _sir_handleerr(errno);
7,912✔
1087
        }
1088
#if defined(SIR_MSEC_POSIX)
1089
        struct timespec ts = {0};
2,148,963✔
1090
        int clock          = clock_gettime(SIR_MSECCLOCK, &ts);
2,148,963✔
1091
        SIR_ASSERT(0 == clock);
2,141,051✔
1092

1093
        if (0 == clock) {
2,133,139✔
1094
            if (msecbuf)
2,141,091✔
1095
                *msecbuf = (int64_t)(((double)ts.tv_nsec) / 1e6);
2,141,091✔
1096
        } else {
1097
            if (msecbuf)
7,872✔
1098
                *msecbuf = 0LL;
7,872✔
1099
            return _sir_handleerr(errno);
7,872✔
1100
        }
1101
#elif defined(SIR_MSEC_MACH)
1102
        kern_return_t retval = KERN_SUCCESS;
1103
        mach_timespec_t mts  = {0};
1104
        clock_serv_t clock;
1105

1106
        host_get_clock_service(mach_host_self(), SIR_MSECCLOCK, &clock);
1107
        retval = clock_get_time(clock, &mts);
1108
        mach_port_deallocate(mach_task_self(), clock);
1109

1110
        if (KERN_SUCCESS == retval) {
1111
            if (msecbuf)
1112
                *msecbuf = (int64_t)(((double)mts.tv_nsec) / 1e6);
1113
        } else {
1114
            if (msecbuf)
1115
                *msecbuf = 0LL;
1116
            return _sir_handleerr(retval);
1117
        }
1118
#elif defined(SIR_MSEC_WIN32)
1119
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9;
1120

1121
        FILETIME ftutc = {0};
1122
        GetSystemTimePreciseAsFileTime(&ftutc);
1123

1124
        ULARGE_INTEGER ftnow = {0};
1125
        ftnow.HighPart = ftutc.dwHighDateTime;
1126
        ftnow.LowPart  = ftutc.dwLowDateTime;
1127
        ftnow.QuadPart = (ULONGLONG)((double)(ftnow.QuadPart - uepoch) / 1e7);
1128

1129
        *tbuf = (int64_t)ftnow.QuadPart;
1130

1131
        SYSTEMTIME st = {0};
1132
        if (FileTimeToSystemTime(&ftutc, &st)) {
1133
            if (msecbuf)
1134
                *msecbuf = (int64_t)st.wMilliseconds;
1135
        } else {
1136
            if (msecbuf)
1137
                *msecbuf = 0LL;
1138
            return _sir_handlewin32err(GetLastError());
1139
        }
1140

1141
#else
1142
        time((time_t*)tbuf);
1143
        if (msecbuf)
1144
            *msecbuf = 0LL;
1145
#endif
1146
        return true;
2,141,091✔
1147
    }
1148
    return false;
×
1149
}
1150

1151
int64_t _sir_msec_since(sir_time* when, sir_time* out) {
2,156,875✔
1152
    if (!_sir_validptr(when) || !_sir_validptr(out))
2,156,875✔
1153
        return 0LL;
×
1154

1155
    out->sec  = 0LL;
2,156,875✔
1156
    out->msec = 0LL;
2,156,875✔
1157

1158
    bool gettime = _sir_clock_gettime(&out->sec, &out->msec);
2,156,875✔
1159
    SIR_ASSERT(gettime);
2,148,963✔
1160

1161
    if (!gettime)
2,141,051✔
1162
        return 0LL;
15,784✔
1163

1164
    return ((out->sec * 1000LL) + out->msec) - ((when->sec * 1000LL) + when->msec);
2,141,091✔
1165
}
1166

1167
pid_t _sir_getpid(void) {
750✔
1168
#if !defined(__WIN__)
1169
    return getpid();
750✔
1170
#else /* __WIN__ */
1171
    return (pid_t)GetCurrentProcessId();
1172
#endif
1173
}
1174

1175
pid_t _sir_gettid(void) {
823✔
1176
    pid_t tid = 0;
717✔
1177
#if defined(__MACOS__)
1178
    uint64_t tid64 = 0ULL;
1179
    int gettid     = pthread_threadid_np(NULL, &tid64);
1180
    if (0 != gettid)
1181
        (void)_sir_handleerr(gettid);
1182
    tid = (pid_t)tid64;
1183
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1184
      defined(__DragonFly_getthreadid__)
1185
    tid = (pid_t)pthread_getthreadid_np();
1186
#elif defined(__OpenBSD__)
1187
    tid = (pid_t)getthrid();
1188
#elif defined(__SOLARIS__) || defined(__NetBSD__) || defined(__HURD__) || \
1189
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1190
    tid = (pid_t)pthread_self();
1191
#elif defined(__HAIKU__)
1192
    tid = get_pthread_thread_id(pthread_self());
1193
#elif defined(__linux__) || defined(__serenity__)
1194
# if (defined(__GLIBC__) && GLIBC_VERSION >= 23000) || \
1195
      defined(__serenity__)
1196
    tid = gettid();
823✔
1197
# else
1198
    tid = syscall(SYS_gettid);
1199
# endif
1200
#elif defined(__WIN__)
1201
    tid = (pid_t)GetCurrentThreadId();
1202
#else
1203
# error "cannot determine how to get thread id; please contact the author"
1204
#endif
1205
    return tid;
823✔
1206
}
1207

1208
bool _sir_getthreadname(char name[SIR_MAXPID]) {
861✔
1209
    _sir_resetstr(name);
861✔
1210
#if defined(__MACOS__) || \
1211
   (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1212
   (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1213
    defined(USE_PTHREAD_GETNAME_NP)
1214
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
861✔
1215
    if (0 != ret)
861✔
1216
        return _sir_handleerr(ret);
×
1217
# if defined(__HAIKU__)
1218
    if ((strncmp(name, "pthread_func", SIR_MAXPID)) || _sir_validstrnofail(name))
1219
        (void)snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1220
# endif
1221
    return _sir_validstrnofail(name);
861✔
1222
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1223
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1224
    return _sir_validstrnofail(name);
1225
#else
1226
# if !defined(_AIX) && !defined(__HURD__) && !defined(SUNLINT)
1227
#  pragma message("unable to determine how to get a thread name")
1228
# endif
1229
    SIR_UNUSED(name);
1230
    return false;
1231
#endif
1232
}
1233

1234
bool _sir_setthreadname(const char* name) {
44✔
1235
    if (!_sir_validptr(name))
44✔
1236
        return false;
×
1237
#if defined (__MACOS__)
1238
    int ret = pthread_setname_np(name);
1239
    return (0 != ret) ? _sir_handleerr(ret) : true;
1240
#elif (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1241
      (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1242
       defined(USE_PTHREAD_GETNAME_NP)
1243
    int ret = pthread_setname_np(pthread_self(), name);
44✔
1244
    return (0 != ret) ? _sir_handleerr(ret) : true;
44✔
1245
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1246
    pthread_set_name_np(pthread_self(), name);
1247
    return true;
1248
#else
1249
# if !defined(SUNLINT)
1250
#  pragma message("unable to determine how to set a thread name")
1251
# endif
1252
    SIR_UNUSED(name);
1253
    return false;
1254
#endif
1255
}
1256

1257
bool _sir_gethostname(char name[SIR_MAXHOST]) {
8,321✔
1258
#if !defined(__WIN__)
1259
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,255✔
1260
    return 0 == ret ? true : _sir_handleerr(errno);
8,321✔
1261
#else
1262
    WSADATA wsad = {0};
1263
    int ret      = WSAStartup(MAKEWORD(2, 2), &wsad);
1264
    if (0 != ret)
1265
        return _sir_handlewin32err(ret);
1266

1267
    if (SOCKET_ERROR == gethostname(name, SIR_MAXHOST)) {
1268
        int err = WSAGetLastError();
1269
        WSACleanup();
1270
        return _sir_handlewin32err(err);
1271
    }
1272

1273
    WSACleanup();
1274
    return true;
1275
#endif /* !__WIN__ */
1276
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc