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

aremmell / libsir / 1047

23 Jul 2023 07:35AM UTC coverage: 92.193% (-0.03%) from 92.219%
1047

push

travis-ci

aremmell
skip joining 0 thread handles

1 of 1 new or added line in 1 file covered. (100.0%)

2964 of 3215 relevant lines covered (92.19%)

1626468.71 hits per line

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

88.05
/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.1
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
# pragma comment(lib, "ws2_32.lib")
37
#endif
38

39
static sirconfig _sir_cfg      = {0};
40
static sirfcache _sir_fc       = {0};
41
static sir_plugincache _sir_pc = {0};
42

43
static sir_mutex cfg_mutex = SIR_MUTEX_INIT;
44
static sir_once cfg_once   = SIR_ONCE_INIT;
45

46
static sir_mutex fc_mutex  = SIR_MUTEX_INIT;
47
static sir_once fc_once    = SIR_ONCE_INIT;
48

49
static sir_mutex pc_mutex  = SIR_MUTEX_INIT;
50
static sir_once pc_once    = SIR_ONCE_INIT;
51

52
static sir_mutex ts_mutex  = SIR_MUTEX_INIT;
53
static sir_once ts_once    = SIR_ONCE_INIT;
54

55
static sir_once magic_once = SIR_ONCE_INIT;
56

57
#if defined(__HAVE_ATOMIC_H__)
58
static atomic_uint_fast32_t _sir_magic;
59
#else
60
static volatile uint32_t _sir_magic;
61
#endif
62

63
bool _sir_makeinit(sirinit* si) {
50✔
64
    if (!_sir_validptr(si))
50✔
65
        return false;
×
66

67
    memset(si, 0, sizeof(sirinit));
44✔
68

69
    si->d_stdout.opts   = SIRO_DEFAULT;
50✔
70
    si->d_stdout.levels = SIRL_DEFAULT;
50✔
71

72
    si->d_stderr.opts   = SIRO_DEFAULT;
50✔
73
    si->d_stderr.levels = SIRL_DEFAULT;
50✔
74

75
#if !defined(SIR_NO_SYSTEM_LOGGERS)
76
    si->d_syslog.opts   = SIRO_DEFAULT;
37✔
77
    si->d_syslog.levels = SIRL_DEFAULT;
37✔
78
#else
79
    si->d_syslog.opts   = SIRO_MSGONLY;
13✔
80
    si->d_syslog.levels = SIRL_NONE;
13✔
81
#endif
82

83
    return true;
50✔
84
}
85

86
bool _sir_init(sirinit* si) {
685✔
87
    (void)_sir_seterror(_SIR_E_NOERROR);
685✔
88
    _sir_once(&magic_once, _sir_initialize_once);
685✔
89

90
    if (!_sir_validptr(si))
685✔
91
        return false;
×
92

93
#if defined(__HAVE_ATOMIC_H__)
94
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
685✔
95
#else
96
    if (_SIR_MAGIC == _sir_magic)
97
#endif
98
        return _sir_seterror(_SIR_E_ALREADY);
21✔
99

100
    _sir_defaultlevels(&si->d_stdout.levels, sir_stdout_def_lvls);
664✔
101
    _sir_defaultopts(&si->d_stdout.opts, sir_stdout_def_opts);
664✔
102

103
    _sir_defaultlevels(&si->d_stderr.levels, sir_stderr_def_lvls);
664✔
104
    _sir_defaultopts(&si->d_stderr.opts, sir_stderr_def_opts);
664✔
105

106
#if !defined(SIR_NO_SYSTEM_LOGGERS)
107
    _sir_defaultlevels(&si->d_syslog.levels, sir_syslog_def_lvls);
484✔
108
    _sir_defaultopts(&si->d_syslog.opts, sir_syslog_def_opts);
484✔
109
#endif
110

111
    if (!_sir_init_sanity(si))
664✔
112
        return false;
17✔
113

114
#if defined(__WIN__)
115
    if (!_sir_initialize_stdio()) {
116
        _sir_selflog("error: failed to initialize stdio!");
117
        return false;
118
    }
119
#endif
120

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

123
#if defined(__HAVE_ATOMIC_H__)
124
    atomic_store(&_sir_magic, _SIR_MAGIC);
644✔
125
#else
126
    _sir_magic = _SIR_MAGIC;
127
#endif
128

129
    _sir_setcolormode(SIRCM_16);
644✔
130

131
    if (!_sir_resettextstyles())
644✔
132
        _sir_selflog("error: failed to reset text styles!");
×
133

134
    memset(&_cfg->state, 0, sizeof(_cfg->state));
644✔
135
    memcpy(&_cfg->si, si, sizeof(sirinit));
644✔
136

137
    /* forcibly null-terminate the process name. */
138
    _cfg->si.name[SIR_MAXNAME - 1] = '\0';
644✔
139

140
    /* Store PID. */
141
    _cfg->state.pid = _sir_getpid();
644✔
142

143
    if (0 > snprintf(_cfg->state.pidbuf, SIR_MAXPID, SIR_PIDFORMAT,
644✔
144
                     PID_CAST _cfg->state.pid))
145
        (void)_sir_handleerr(errno);
×
146

147
#if !defined(SIR_NO_SYSTEM_LOGGERS)
148
    /* initialize system logger. */
149
    _sir_syslog_reset(&_cfg->si.d_syslog);
470✔
150

151
    if (_cfg->si.d_syslog.levels != SIRL_NONE) {
470✔
152
        if (!_sir_syslog_init(_cfg->si.name, &_cfg->si.d_syslog))
84✔
153
            _sir_selflog("failed to initialize system logger!");
×
154
    }
155
#endif
156

157
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
644✔
158

159
    return true;
644✔
160
}
161

162
bool _sir_cleanup(void) {
644✔
163
    if (!_sir_sanity())
644✔
164
        return false;
×
165

166
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
644✔
167
    bool cleanup   = true;
545✔
168
    bool destroyfc = _sir_fcache_destroy(sfc);
644✔
169
    SIR_ASSERT(destroyfc);
611✔
170

171
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
644✔
172
    cleanup &= destroyfc;
545✔
173

174
#if !defined(SIR_NO_PLUGINS)
175
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
603✔
176
    bool destroypc = _sir_plugin_cache_destroy(spc);
603✔
177
    SIR_ASSERT(destroypc);
570✔
178
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
603✔
179
    cleanup &= destroypc;
504✔
180
#endif
181

182
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
644✔
183

184
#if !defined(SIR_NO_SYSTEM_LOGGERS)
185
    if (!_sir_syslog_close(&_cfg->si.d_syslog)) {
470✔
186
        cleanup = false;
×
187
        _sir_selflog("error: failed to close system logger!");
×
188
    }
189

190
    _sir_syslog_reset(&_cfg->si.d_syslog);
470✔
191
#endif
192

193
    if (!_sir_resettextstyles()) {
644✔
194
        cleanup = false;
×
195
        _sir_selflog("error: failed to reset text styles!");
×
196
    }
197

198
#if defined(__HAVE_ATOMIC_H__)
199
    atomic_store(&_sir_magic, 0);
644✔
200
#else
201
    _sir_magic = 0;
202
#endif
203

204
    memset(_cfg, 0, sizeof(sirconfig));
545✔
205
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
644✔
206

207
    _sir_selflog("cleanup: %s", (cleanup ? "successful" : "with errors"));
611✔
208

209
    SIR_ASSERT(cleanup);
611✔
210
    return cleanup;
578✔
211
}
212

213
bool _sir_sanity(void) {
2,445,253✔
214
#if defined(__HAVE_ATOMIC_H__)
215
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,445,253✔
216
        return true;
2,365,052✔
217
#else
218
    if (_SIR_MAGIC == _sir_magic)
219
        return true;
220
#endif
221
    return _sir_seterror(_SIR_E_NOTREADY);
40✔
222
}
223

224
bool _sir_init_sanity(const sirinit* si) {
664✔
225
    if (!_sir_validptr(si))
664✔
226
        return false;
×
227

228
    bool levelcheck = true;
562✔
229
    levelcheck &= _sir_validlevels(si->d_stdout.levels);
664✔
230
    levelcheck &= _sir_validlevels(si->d_stderr.levels);
664✔
231

232
#if !defined(SIR_NO_SYSTEM_LOGGERS)
233
    levelcheck &= _sir_validlevels(si->d_syslog.levels);
484✔
234
#endif
235

236
    bool optscheck = true;
562✔
237
    optscheck &= _sir_validopts(si->d_stdout.opts);
664✔
238
    optscheck &= _sir_validopts(si->d_stderr.opts);
664✔
239

240
#if !defined(SIR_NO_SYSTEM_LOGGERS)
241
    optscheck &= _sir_validopts(si->d_syslog.opts);
484✔
242
#endif
243

244
    return levelcheck && optscheck;
664✔
245
}
246

247
static
248
bool _sir_updatelevels(const char* name, sir_levels* old, sir_levels* new) {
808✔
249
    if (*old != *new) {
808✔
250
        _sir_selflog("updating %s levels from %04"PRIx16" to %04"PRIx16, name, *old, *new);
726✔
251
        *old = *new;
772✔
252
    } else {
253
        _sir_selflog("skipped superfluous update of %s levels: %04"PRIx16, name, *old);
34✔
254
    }
255
    return true;
808✔
256
}
257

258
static
259
bool _sir_updateopts(const char* name, sir_options* old, sir_options* new) {
64,774✔
260
    if (*old != *new) {
64,774✔
261
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
30,671✔
262
        *old = *new;
32,748✔
263
    } else {
264
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
30,057✔
265
    }
266
    return true;
64,774✔
267
}
268

269
bool _sir_stdoutlevels(sirinit* si, sir_update_config_data* data) {
399✔
270
    return _sir_updatelevels(SIR_DESTNAME_STDOUT, &si->d_stdout.levels, data->levels);
399✔
271
}
272

273
bool _sir_stdoutopts(sirinit* si, sir_update_config_data* data) {
64,365✔
274
    return _sir_updateopts(SIR_DESTNAME_STDOUT, &si->d_stdout.opts, data->opts);
64,365✔
275
}
276

277
bool _sir_stderrlevels(sirinit* si, sir_update_config_data* data) {
359✔
278
    return _sir_updatelevels(SIR_DESTNAME_STDERR, &si->d_stderr.levels, data->levels);
359✔
279
}
280

281
bool _sir_stderropts(sirinit* si, sir_update_config_data* data) {
359✔
282
    return _sir_updateopts(SIR_DESTNAME_STDERR, &si->d_stderr.opts, data->opts);
359✔
283
}
284

285
bool _sir_sysloglevels(sirinit* si, sir_update_config_data* data) {
50✔
286
    bool updated = _sir_updatelevels(SIR_DESTNAME_SYSLOG, &si->d_syslog.levels, data->levels);
50✔
287
    if (updated) {
50✔
288
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
50✔
289
        updated = _sir_syslog_updated(si, data);
50✔
290
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
50✔
291
    }
292
    return updated;
50✔
293
}
294

295
bool _sir_syslogopts(sirinit* si, sir_update_config_data* data) {
50✔
296
    bool updated = _sir_updateopts(SIR_DESTNAME_SYSLOG, &si->d_syslog.opts, data->opts);
50✔
297
    if (updated) {
50✔
298
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
50✔
299
        updated = _sir_syslog_updated(si, data);
50✔
300
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
50✔
301
    }
302
    return updated;
50✔
303
}
304

305
bool _sir_syslogid(sirinit* si, sir_update_config_data* data) {
23✔
306
    bool cur_valid = _sir_validstrnofail(si->d_syslog.identity);
23✔
307
    if (!cur_valid || 0 != strncmp(si->d_syslog.identity, data->sl_identity, SIR_MAX_SYSLOG_ID)) {
23✔
308
        _sir_selflog("updating %s identity from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
23✔
309
            si->d_syslog.identity, data->sl_identity);
310
        _sir_strncpy(si->d_syslog.identity, SIR_MAX_SYSLOG_ID, data->sl_identity,
23✔
311
            strnlen(data->sl_identity, SIR_MAX_SYSLOG_ID));
312
    } else {
313
        _sir_selflog("skipped superfluous update of %s identity: '%s'", SIR_DESTNAME_SYSLOG,
×
314
            si->d_syslog.identity);
315
        return true;
×
316
    }
317

318
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
23✔
319
    bool updated = _sir_syslog_updated(si, data);
23✔
320
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
23✔
321

322
    return updated;
23✔
323
}
324

325
bool _sir_syslogcat(sirinit* si, sir_update_config_data* data) {
×
326
    bool cur_valid = _sir_validstrnofail(si->d_syslog.category);
×
327
    if (!cur_valid || 0 != strncmp(si->d_syslog.category, data->sl_category, SIR_MAX_SYSLOG_CAT)) {
×
328
        _sir_selflog("updating %s category from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
×
329
            si->d_syslog.category, data->sl_category);
330
        _sir_strncpy(si->d_syslog.category, SIR_MAX_SYSLOG_CAT, data->sl_category,
×
331
            strnlen(data->sl_category, SIR_MAX_SYSLOG_CAT));
332
    } else {
333
        _sir_selflog("skipped superfluous update of %s category: '%s'", SIR_DESTNAME_SYSLOG,
×
334
            si->d_syslog.identity);
335
        return true;
×
336
    }
337

338
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
×
339
    bool updated = _sir_syslog_updated(si, data);
×
340
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
×
341

342
    return updated;
×
343
}
344

345
bool _sir_writeinit(sir_update_config_data* data, sirinit_update update) {
65,605✔
346
    (void)_sir_seterror(_SIR_E_NOERROR);
65,605✔
347

348
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
65,605✔
349
        return false;
×
350

351
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
65,605✔
352

353
    bool updated = update(&_cfg->si, data);
65,605✔
354
    if (!updated)
61,510✔
355
        _sir_selflog("error: update routine failed!");
×
356

357
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
65,605✔
358
    return updated;
65,605✔
359
}
360

361
void* _sir_locksection(sir_mutex_id mid) {
8,949,528✔
362
    sir_mutex* m = NULL;
8,949,528✔
363
    void* sec    = NULL;
8,949,528✔
364

365
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
8,949,528✔
366
    SIR_ASSERT(enter);
8,893,918✔
367

368
    if (!enter)
8,893,918✔
369
        _sir_selflog("error: failed to lock mutex!");
×
370

371
    return enter ? sec : NULL;
8,949,584✔
372
}
373

374
void _sir_unlocksection(sir_mutex_id mid) {
8,949,558✔
375
    sir_mutex* m = NULL;
8,949,558✔
376
    void* sec    = NULL;
8,949,558✔
377

378
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
8,949,558✔
379
    SIR_ASSERT(leave);
8,893,928✔
380

381
    if (!leave)
8,893,928✔
382
        _sir_selflog("error: failed to unlock mutex!");
×
383
}
8,949,596✔
384

385
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
17,898,960✔
386
    sir_mutex* tmpm;
387
    void* tmpsec;
388

389
    switch (mid) {
17,898,960✔
390
        case SIRMI_CONFIG:
8,698,490✔
391
            _sir_once(&cfg_once, _sir_initmutex_cfg_once);
8,698,490✔
392
            tmpm   = &cfg_mutex;
8,578,638✔
393
            tmpsec = &_sir_cfg;
8,578,638✔
394
            break;
8,698,490✔
395
        case SIRMI_FILECACHE:
4,422,837✔
396
            _sir_once(&fc_once, _sir_initmutex_fc_once);
4,422,837✔
397
            tmpm   = &fc_mutex;
4,347,127✔
398
            tmpsec = &_sir_fc;
4,347,127✔
399
            break;
4,422,834✔
400
        case SIRMI_PLUGINCACHE:
214,242✔
401
            _sir_once(&pc_once, _sir_initmutex_pc_once);
214,242✔
402
            tmpm   = &pc_mutex;
175,014✔
403
            tmpsec = &_sir_pc;
175,014✔
404
            break;
214,242✔
405
        case SIRMI_TEXTSTYLE:
4,563,619✔
406
            _sir_once(&ts_once, _sir_initmutex_ts_once);
4,563,619✔
407
            tmpm   = &ts_mutex;
4,464,371✔
408
            tmpsec = &sir_text_style_section;
4,464,371✔
409
            break;
4,563,623✔
410
        // GCOVR_EXCL_START
411
        default: /* this should never happen. */
412
            SIR_ASSERT("!invalid mutex id");
413
            tmpm   = NULL;
414
            tmpsec = NULL;
415
            break;
416
        // GCOVR_EXCL_STOP
417
    }
418

419
    *m = tmpm;
17,898,961✔
420

421
    if (section)
17,898,961✔
422
        *section = tmpsec;
17,899,164✔
423

424
    return *m != NULL && (!section || *section != NULL);
17,898,961✔
425
}
426

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

434
void _sir_initmutex_cfg_once(void) {
51✔
435
    if (!_sir_mutexcreate(&cfg_mutex))
51✔
436
        _sir_selflog("error: failed to create mutex!");
×
437
}
51✔
438

439
void _sir_initmutex_fc_once(void) {
51✔
440
    if (!_sir_mutexcreate(&fc_mutex))
51✔
441
        _sir_selflog("error: failed to create mutex!");
×
442
}
51✔
443

444
void _sir_initmutex_pc_once(void) {
42✔
445
    if (!_sir_mutexcreate(&pc_mutex))
42✔
446
        _sir_selflog("error: failed to create mutex!");
×
447
}
42✔
448

449
void _sir_initmutex_ts_once(void) {
51✔
450
    if (!_sir_mutexcreate(&ts_mutex))
51✔
451
        _sir_selflog("error: failed to create mutex!");
×
452
}
51✔
453
#else /* __WIN__ */
454
BOOL CALLBACK _sir_initialize_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
455
    SIR_UNUSED(ponce);
456
    SIR_UNUSED(param);
457
    SIR_UNUSED(ctx);
458
    return TRUE;
459
}
460

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

466
    if (!_sir_mutexcreate(&cfg_mutex)) {
467
        _sir_selflog("error: failed to create mutex!");
468
        return FALSE;
469
    }
470

471
    return TRUE;
472
}
473

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

479
    if (!_sir_mutexcreate(&fc_mutex)) {
480
        _sir_selflog("error: failed to create mutex!");
481
        return FALSE;
482
    }
483

484
    return TRUE;
485
}
486

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

492
    if (!_sir_mutexcreate(&pc_mutex)) {
493
        _sir_selflog("error: failed to create mutex!");
494
        return FALSE;
495
    }
496

497
    return TRUE;
498
}
499

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

505
    if (!_sir_mutexcreate(&ts_mutex)) {
506
        _sir_selflog("error: failed to create mutex!");
507
        return FALSE;
508
    }
509

510
    return TRUE;
511
}
512
#endif
513

514
bool _sir_once(sir_once* once, sir_once_fn func) {
17,899,730✔
515
#if !defined(__WIN__)
516
    int ret = pthread_once(once, func);
17,899,730✔
517
    return 0 == ret ? true : _sir_handleerr(ret);
17,899,744✔
518
#else /* __WIN__ */
519
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
520
        : _sir_handlewin32err(GetLastError());
521
#endif
522
}
523

524
PRINTF_FORMAT_ATTR(2, 0)
525
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,141,228✔
526
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,141,228✔
527
        return false;
40✔
528

529
    (void)_sir_seterror(_SIR_E_NOERROR);
2,141,188✔
530

531
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,141,187✔
532

533
    /* from time to time, update the host name in the config, just in case. */
534
    time_t now = -1;
2,141,188✔
535
    if (-1 != time(&now) &&
2,141,188✔
536
        (now - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,141,188✔
537
        _sir_selflog("updating hostname...");
8,258✔
538
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,279✔
539
            _sir_selflog("error: failed to get hostname!");
7,910✔
540
        } else {
541
            _cfg->state.last_hname_chk = now;
369✔
542
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
348✔
543
        }
544
    }
545

546
    sirconfig cfg;
547
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,117,461✔
548
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,141,188✔
549

550
    sirbuf buf = {
2,141,188✔
551
        {0},
552
        {0},
553
        {0},
554
        cfg.state.hostname,
555
        cfg.state.pidbuf,
556
        NULL,
557
        cfg.si.name,
558
        {0},
559
        {0},
560
        {0},
561
         0
562
    };
563

564
    bool fmt              = false;
2,117,461✔
565
    const char* style_str = _sir_gettextstyle(level);
2,141,188✔
566

567
    SIR_ASSERT(NULL != style_str);
2,133,279✔
568
    if (NULL != style_str)
2,141,188✔
569
        fmt = (0 == _sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,141,188✔
570
            strnlen(style_str, SIR_MAXSTYLE)));
571
    SIR_UNUSED(fmt);
572
    SIR_ASSERT(fmt);
2,133,279✔
573

574
    now          = -1;
2,141,188✔
575
    long nowmsec = 0;
2,141,188✔
576
    bool gettime = _sir_clock_gettime(&now, &nowmsec);
2,141,188✔
577
    SIR_ASSERT(gettime);
2,133,279✔
578

579
    if (gettime) {
2,141,188✔
580
        fmt = _sir_formattime(now, buf.timestamp, SIR_TIMEFORMAT);
2,133,317✔
581
        SIR_ASSERT(fmt);
2,125,409✔
582
        SIR_UNUSED(fmt);
583

584
        if (0 > snprintf(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, nowmsec))
2,133,318✔
585
            (void)_sir_handleerr(errno);
×
586
    }
587

588
    buf.level = _sir_formattedlevelstr(level);
2,141,189✔
589

590
    pid_t tid = _sir_gettid();
2,141,187✔
591
    if (tid != cfg.state.pid) {
2,141,187✔
592
        if (!_sir_getthreadname(buf.tid)) {
64,146✔
593
            if (0 > snprintf(buf.tid, SIR_MAXPID, SIR_PIDFORMAT, PID_CAST tid))
×
594
                (void)_sir_handleerr(errno);
×
595
        }
596
    }
597

598
    if (0 > vsnprintf(buf.message, SIR_MAXMESSAGE, format, args)) {
2,141,187✔
599
        (void)_sir_handleerr(errno);
×
600
        SIR_ASSERT(false);
×
601
    }
602

603
    if (!_sir_validstr(buf.message))
2,141,187✔
604
        return false;
17✔
605

606
    bool match             = false;
2,117,442✔
607
    bool exit_early        = false;
2,117,442✔
608
    bool update_last_props = true;
2,117,442✔
609
    uint64_t hash          = 0;
2,117,442✔
610

611
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,141,166✔
612
        cfg.state.last.prefix[1] == buf.message[1]) {
2,090,185✔
613
        hash  = FNV64_1a(buf.message);
2,108,572✔
614
        match = cfg.state.last.hash == hash;
2,108,572✔
615
    }
616

617
    if (match) {
2,136,263✔
618
        cfg.state.last.counter++;
29,688✔
619

620
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
621
            cfg.state.last.counter); */
622

623
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
29,688✔
624
            size_t old_threshold = cfg.state.last.threshold;
816✔
625

626
            update_last_props = false;
816✔
627
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
960✔
628
            cfg.state.last.squelch = true;
960✔
629

630
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
912✔
631
                         " to %zu (factor: %d)",
632
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
633

634
            if (0 > snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold))
960✔
635
                (void)_sir_handleerr(errno);
×
636
        } else if (cfg.state.last.squelch) {
28,728✔
637
            exit_early = true;
23,919✔
638
        }
639
    } else {
640
        cfg.state.last.squelch   = false;
2,111,478✔
641
        cfg.state.last.counter   = 0;
2,111,478✔
642
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,111,478✔
643
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
644
    }
645

646
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,141,166✔
647
    if (!_cfg)
2,141,168✔
648
        return _sir_seterror(_SIR_E_INTERNAL);
×
649

650
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,141,168✔
651

652
    if (update_last_props) {
2,141,168✔
653
        _cfg->state.last.hash      = hash;
2,140,208✔
654
        _cfg->state.last.prefix[0] = buf.message[0];
2,140,208✔
655
        _cfg->state.last.prefix[1] = buf.message[1];
2,140,208✔
656
    }
657

658
    _cfg->state.last.counter   = cfg.state.last.counter;
2,141,168✔
659
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,141,168✔
660

661
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,141,168✔
662

663
    if (exit_early)
2,141,167✔
664
        return false;
23,919✔
665

666
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,113,027✔
667
    return update_last_props ? dispatched : false;
2,113,028✔
668
}
669

670
bool _sir_dispatch(sirinit* si, sir_level level, sirbuf* buf) {
2,113,027✔
671
    bool retval       = true;
2,093,524✔
672
    size_t dispatched = 0;
2,093,524✔
673
    size_t wanted     = 0;
2,093,524✔
674

675
    if (_sir_bittest(si->d_stdout.levels, level)) {
2,113,027✔
676
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,109,681✔
677
        bool wrote        = _sir_validstrnofail(write) &&
2,219,359✔
678
            _sir_write_stdout(write, buf->output_len);
1,109,679✔
679
        retval &= wrote;
1,109,682✔
680

681
        if (wrote)
1,109,682✔
682
            dispatched++;
1,084,553✔
683
        wanted++;
1,090,769✔
684
    }
685

686
    if (_sir_bittest(si->d_stderr.levels, level)) {
2,113,028✔
687
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,042✔
688
        bool wrote        = _sir_validstrnofail(write) &&
2,084✔
689
            _sir_write_stderr(write, buf->output_len);
1,042✔
690
        retval &= wrote;
1,042✔
691

692
        if (wrote)
1,042✔
693
            dispatched++;
1,033✔
694
        wanted++;
1,042✔
695
    }
696

697
#if !defined(SIR_NO_SYSTEM_LOGGERS)
698
    if (_sir_bittest(si->d_syslog.levels, level)) {
2,078,656✔
699
        if (_sir_syslog_write(level, buf, &si->d_syslog))
520✔
700
            dispatched++;
520✔
701
        wanted++;
520✔
702
    }
703
#endif
704

705
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,113,029✔
706
    size_t fdispatched = 0;
2,113,028✔
707
    size_t fwanted     = 0;
2,113,028✔
708
    retval &= _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted);
2,113,028✔
709
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,113,028✔
710

711
    dispatched += fdispatched;
2,113,028✔
712
    wanted += fwanted;
2,113,028✔
713

714
#if !defined(SIR_NO_PLUGINS)
715
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
106,451✔
716
    size_t pdispatched = 0;
106,451✔
717
    size_t pwanted     = 0;
106,451✔
718
    retval &= _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted);
106,451✔
719
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
106,451✔
720

721
    dispatched += pdispatched;
106,451✔
722
    wanted += pwanted;
106,451✔
723
#endif
724

725
    if (0 == wanted) {
2,113,028✔
726
        _sir_selflog("error: no destinations registered for level %04"PRIx32, level);
823✔
727
        return _sir_seterror(_SIR_E_NODEST);
876✔
728
    }
729

730
    return retval && (dispatched == wanted);
2,112,152✔
731
}
732

733
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,252,263✔
734
    if (_sir_validptr(buf)) {
2,252,263✔
735
        bool first = true;
2,208,369✔
736

737
        _sir_resetstr(buf->output);
2,252,274✔
738

739
        if (styling)
2,252,276✔
740
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,110,720✔
741

742
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,252,277✔
743
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,110,375✔
744
            first = false;
2,090,586✔
745

746
#if defined(SIR_MSEC_TIMER)
747
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,110,375✔
748
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
78,055✔
749
#endif
750
        }
751

752
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,252,277✔
753
            if (!first)
1,031,527✔
754
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,539✔
755
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,031,527✔
756
            first = false;
1,025,224✔
757
        }
758

759
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,252,277✔
760
            if (!first)
2,156,344✔
761
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,110,561✔
762
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,156,345✔
763
            first = false;
2,129,620✔
764
        }
765

766
        bool name = false;
2,208,372✔
767
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,252,277✔
768
            if (!first)
1,109,832✔
769
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,107,793✔
770
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,109,831✔
771
            first = false;
1,090,092✔
772
            name  = true;
1,090,092✔
773
        }
774

775
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,252,278✔
776
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,252,277✔
777

778
        if (wantpid || wanttid) {
2,252,278✔
779
            if (name)
2,143,281✔
780
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,108,144✔
781
            else if (!first)
1,035,137✔
782
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,035,136✔
783

784
            if (wantpid)
2,143,284✔
785
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,068,042✔
786

787
            if (wanttid) {
2,143,287✔
788
                if (wantpid)
139,342✔
789
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
64,101✔
790
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
139,342✔
791
            }
792

793
            if (name)
2,143,286✔
794
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,108,145✔
795

796
            if (first)
2,143,285✔
797
                first = false;
3✔
798
        }
799

800
        if (!first)
2,252,284✔
801
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,188,195✔
802

803
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,252,285✔
804

805
        if (styling)
2,252,282✔
806
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,110,723✔
807

808
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,252,282✔
809

810
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,252,275✔
811

812
        return buf->output;
2,252,275✔
813
    }
814

815
    return NULL;
×
816
}
817

818
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
157✔
819
#if !defined(SIR_NO_SYSTEM_LOGGERS)
820
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
157✔
821
        return false;
×
822

823
    /* begin resolve identity. */
824
    if (!_sir_validstrnofail(ctx->identity)) {
157✔
825
        _sir_selflog("ctx->identity is no good; trying name");
48✔
826
        if (_sir_validstrnofail(name)) {
52✔
827
            _sir_selflog("using name");
27✔
828
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
29✔
829
        } else {
830
            _sir_selflog("name is no good; trying filename");
21✔
831
            char* appbasename = _sir_getappbasename();
23✔
832
            if (_sir_validstrnofail(appbasename)) {
23✔
833
                _sir_selflog("filename is good: %s", appbasename);
20✔
834
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
20✔
835
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
836
            } else {
837
                _sir_selflog("filename no good; using fallback");
3✔
838
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
3✔
839
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
840
            }
841
            _sir_safefree(&appbasename);
23✔
842
        }
843
    } else {
844
        _sir_selflog("already have identity");
98✔
845
    }
846

847
    /* category */
848
    if (!_sir_validstrnofail(ctx->category)) {
157✔
849
        _sir_selflog("category not set; using fallback");
64✔
850
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
67✔
851
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
852
    } else {
853
        _sir_selflog("already have category");
82✔
854
    }
855

856
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
157✔
857
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
146✔
858

859
    return _sir_syslog_open(ctx);
157✔
860
#else
861
    SIR_UNUSED(name);
862
    SIR_UNUSED(ctx);
863
    return false;
×
864
#endif
865
}
866

867
bool _sir_syslog_open(sir_syslog_dest* ctx) {
157✔
868
#if !defined(SIR_NO_SYSTEM_LOGGERS)
869
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
157✔
870
        _sir_selflog("not initialized; ignoring");
×
871
        return _sir_seterror(_SIR_E_INVALID);
×
872
    }
873

874
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
157✔
875
        _sir_selflog("log already open; ignoring");
46✔
876
        return true;
46✔
877
    }
878

879
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
107✔
880
        ctx->opts);
881

882
# if defined(SIR_OS_LOG_ENABLED)
883
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
884
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
885
# elif defined(SIR_SYSLOG_ENABLED)
886
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
107✔
887
    int facility = LOG_USER;
86✔
888

889
    openlog(ctx->identity, logopt, facility);
107✔
890
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
100✔
891
# endif
892

893
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
107✔
894
    return true;
107✔
895
#else
896
    SIR_UNUSED(ctx);
897
    return false;
×
898
#endif
899
}
900

901
bool _sir_syslog_write(sir_level level, const sirbuf* buf, sir_syslog_dest* ctx) {
520✔
902
#if !defined(SIR_NO_SYSTEM_LOGGERS)
903
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
520✔
904
        _sir_selflog("not initialized; ignoring");
×
905
        return _sir_seterror(_SIR_E_INVALID);
×
906
    }
907

908
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
520✔
909
        _sir_selflog("log not open; ignoring");
×
910
        return _sir_seterror(_SIR_E_INVALID);
×
911
    }
912

913
# if defined(SIR_OS_LOG_ENABLED)
914
    if (SIRL_DEBUG == level)
915
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
916
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
917
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
918
    else if (SIRL_WARN == level || SIRL_ERROR == level)
919
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
920
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
921
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
922

923
    return true;
924
# elif defined(SIR_SYSLOG_ENABLED)
925
    int syslog_level;
926
    switch (level) {
520✔
927
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
21✔
928
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
27✔
929
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
70✔
930
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
70✔
931
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
70✔
932
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
93✔
933
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
70✔
934
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
93✔
935
        // GCOVR_EXCL_START
936
        default: /* this should never happen. */
937
            SIR_ASSERT(!"invalid sir_level");
938
            syslog_level = LOG_DEBUG;
939
        // GCOVR_EXCL_STOP
940
    }
941

942
    syslog(syslog_level, "%s", buf->message);
520✔
943
    return true;
520✔
944
# endif
945
#else
946
    SIR_UNUSED(level);
947
    SIR_UNUSED(buf);
948
    SIR_UNUSED(ctx);
949
    return false;
×
950
#endif
951
}
952

953
bool _sir_syslog_updated(sirinit* si, sir_update_config_data* data) {
123✔
954
#if !defined(SIR_NO_SYSTEM_LOGGERS)
955
    if (!_sir_validptr(si) || !_sir_validptr(data))
123✔
956
        return false;
×
957

958
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
123✔
959
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
114✔
960
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
123✔
961
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
114✔
962
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
123✔
963
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
123✔
964
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
123✔
965

966
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
114✔
967
                     " identity: %u, is_init: %u, is_open: %u)",
968
                     levels, options, category, identity, is_init, is_open);
969

970
        bool must_init = false;
102✔
971

972
# if defined(SIR_OS_LOG_ENABLED)
973
        /*
974
         * for os_log, if initialized and open already, only need to reconfigure
975
         * if identity or category changed.
976
         */
977
        must_init = (!is_init || !is_open) || (identity || category);
978
# elif defined(SIR_SYSLOG_ENABLED)
979
        /*
980
         * for os_log, if initialized and open already, only need to reconfigure
981
         * if identity or options changed.
982
         */
983
        must_init = (!is_init || !is_open) || (identity || options);
123✔
984
# endif
985
        bool init = true;
102✔
986
        if (must_init) {
123✔
987
            _sir_selflog("re-init...");
68✔
988
            init = _sir_syslog_init(si->name, &si->d_syslog);
73✔
989
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
68✔
990
        } else {
991
            _sir_selflog("no re-init necessary");
46✔
992
        }
993

994
        return init;
123✔
995
    } else {
996
        _sir_selflog("BUG: called without 'updated' flag set!");
×
997
        return false;
×
998
    }
999
#else
1000
    SIR_UNUSED(si);
1001
    SIR_UNUSED(data);
1002
    return false;
×
1003
#endif
1004
}
1005

1006
bool _sir_syslog_close(sir_syslog_dest* ctx) {
470✔
1007
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1008
    if (!_sir_validptr(ctx))
470✔
1009
        return false;
×
1010

1011
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
470✔
1012
        _sir_selflog("log not open; ignoring");
337✔
1013
        return true;
337✔
1014
    }
1015

1016
# if defined(SIR_OS_LOG_ENABLED)
1017
    /* evidently, you don't need to close the handle returned from os_log_create(), and
1018
     * if you make that call again, you'll get the same cached value. so let's keep the
1019
     * value we've got in the global context. */
1020
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
1021
    _sir_selflog("log closure not necessary");
1022
    return true;
1023
# elif defined(SIR_SYSLOG_ENABLED)
1024
    closelog();
107✔
1025
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
107✔
1026
    _sir_selflog("closed log");
100✔
1027
    return true;
107✔
1028
# endif
1029
#else
1030
    SIR_UNUSED(ctx);
1031
    return false;
×
1032
#endif
1033
}
1034

1035
void _sir_syslog_reset(sir_syslog_dest* ctx) {
940✔
1036
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1037
    if (_sir_validptr(ctx)) {
940✔
1038
        uint32_t old       = ctx->_state.mask;
874✔
1039
        ctx->_state.mask   = 0;
940✔
1040
        ctx->_state.logger = NULL;
940✔
1041
        _sir_selflog("state reset; mask was %08"PRIx32, old);
874✔
1042
    }
1043
#else
1044
    SIR_UNUSED(ctx);
1045
#endif
1046
}
940✔
1047

1048
const char* _sir_formattedlevelstr(sir_level level) {
2,141,186✔
1049
    static const size_t low  = 0;
1050
    static const size_t high = SIR_NUMLEVELS - 1;
1051

1052
    _SIR_DECLARE_BIN_SEARCH(low, high)
2,117,460✔
1053
    _SIR_BEGIN_BIN_SEARCH()
1054

1055
    if (sir_level_to_str_map[_mid].level == level)
8,525,773✔
1056
        return sir_level_to_str_map[_mid].fmt;
2,141,187✔
1057

1058
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1))
6,384,586✔
1059
    _SIR_END_BIN_SEARCH()
1060

1061
    SIR_ASSERT(false);
×
1062
    return SIR_UNKNOWN;
×
1063
}
1064

1065
#if defined(__GNUC__)
1066
__attribute__ ((format (strftime, 3, 0)))
1067
#endif
1068
bool _sir_formattime(time_t now, char* buffer, const char* format) {
2,166,092✔
1069
    if (0 == now || -1 == now)
2,166,092✔
1070
        return _sir_seterror(_SIR_E_INVALID);
×
1071

1072
    struct tm timebuf = {0};
2,166,093✔
1073
    size_t fmttime    = strftime(buffer, SIR_MAXTIME, format,
2,166,094✔
1074
        _sir_localtime(&now, &timebuf));
2,166,093✔
1075

1076
    SIR_ASSERT(0 != fmttime);
2,156,162✔
1077
    if (0 == fmttime)
2,156,162✔
1078
        _sir_selflog("error: strftime failed; format string: '%s'", format);
×
1079

1080
    return 0 != fmttime;
2,166,094✔
1081
}
1082

1083
bool _sir_clock_gettime(time_t* tbuf, long* msecbuf) {
2,141,187✔
1084
    if (tbuf) {
2,141,187✔
1085
        time_t ret = time(tbuf);
2,141,187✔
1086
        if ((time_t)-1 == ret) {
2,141,187✔
1087
            if (msecbuf)
×
1088
                *msecbuf = 0;
×
1089
            return _sir_handleerr(errno);
×
1090
        }
1091
#if defined(SIR_MSEC_POSIX)
1092
        struct timespec ts = {0};
2,141,187✔
1093
        int clock          = clock_gettime(SIR_MSECCLOCK, &ts);
2,141,187✔
1094
        SIR_ASSERT(0 == clock);
2,133,279✔
1095

1096
        if (0 == clock) {
2,141,188✔
1097
            if (msecbuf)
2,133,318✔
1098
                *msecbuf = (long)(ts.tv_nsec / (long)1e6);
2,133,318✔
1099
        } else {
1100
            if (msecbuf)
7,870✔
1101
                *msecbuf = 0;
7,870✔
1102
            return _sir_handleerr(errno);
7,870✔
1103
        }
1104
#elif defined(SIR_MSEC_MACH)
1105
        kern_return_t retval = KERN_SUCCESS;
1106
        mach_timespec_t mts  = {0};
1107
        clock_serv_t clock;
1108

1109
        host_get_clock_service(mach_host_self(), SIR_MSECCLOCK, &clock);
1110
        retval = clock_get_time(clock, &mts);
1111
        mach_port_deallocate(mach_task_self(), clock);
1112

1113
        if (KERN_SUCCESS == retval) {
1114
            if (msecbuf)
1115
                *msecbuf = (mts.tv_nsec / 1e6);
1116
        } else {
1117
            if (msecbuf)
1118
                *msecbuf = 0;
1119
            return _sir_handleerr(retval);
1120
        }
1121
#elif defined(SIR_MSEC__WIN__)
1122
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9;
1123

1124
        FILETIME ftutc = {0};
1125
        GetSystemTimePreciseAsFileTime(&ftutc);
1126

1127
        ULARGE_INTEGER ftnow = {0};
1128
        ftnow.HighPart = ftutc.dwHighDateTime;
1129
        ftnow.LowPart  = ftutc.dwLowDateTime;
1130
        ftnow.QuadPart = (ULONGLONG)((ftnow.QuadPart - uepoch) / 1e7);
1131

1132
        *tbuf = (time_t)ftnow.QuadPart;
1133

1134
        SYSTEMTIME st = {0};
1135
        if (FileTimeToSystemTime(&ftutc, &st)) {
1136
            if (msecbuf)
1137
                *msecbuf = st.wMilliseconds;
1138
        } else {
1139
            if (msecbuf)
1140
                *msecbuf = 0;
1141
            return _sir_handlewin32err(GetLastError());
1142
        }
1143

1144
#else
1145
        time(tbuf);
1146
        if (msecbuf)
1147
            *msecbuf = 0;
1148
#endif
1149
        return true;
2,133,318✔
1150
    }
1151
    return false;
×
1152
}
1153

1154
pid_t _sir_getpid(void) {
644✔
1155
#if !defined(__WIN__)
1156
    return getpid();
644✔
1157
#else /* __WIN__ */
1158
    return (pid_t)GetCurrentProcessId();
1159
#endif
1160
}
1161

1162
pid_t _sir_gettid(void) {
2,141,259✔
1163
    pid_t tid = 0;
2,117,521✔
1164
#if defined(__MACOS__)
1165
    uint64_t tid64 = 0;
1166
    int gettid     = pthread_threadid_np(NULL, &tid64);
1167
    if (0 != gettid)
1168
        (void)_sir_handleerr(gettid);
1169
    tid = (pid_t)tid64;
1170
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1171
      defined(__DragonFly_getthreadid__)
1172
    tid = (pid_t)pthread_getthreadid_np();
1173
#elif defined(__OpenBSD__)
1174
    tid = (pid_t)getthrid();
1175
#elif defined(__SOLARIS__) || defined(__NetBSD__) || \
1176
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1177
    tid = (pid_t)pthread_self();
1178
#elif defined(__HAIKU__)
1179
    tid = get_pthread_thread_id(pthread_self());
1180
#elif defined(__linux__) || defined(__serenity__)
1181
# if (defined(__GLIBC__) && (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 30)) || \
1182
     defined(__serenity__)
1183
    tid = gettid();
2,141,259✔
1184
# else
1185
    tid = syscall(SYS_gettid);
1186
# endif
1187
#elif defined(__WIN__)
1188
    tid = (pid_t)GetCurrentThreadId();
1189
#else
1190
# error "cannot determine how to get thread id; please contact the author"
1191
#endif
1192
    return tid;
2,141,259✔
1193
}
1194

1195
bool _sir_getthreadname(char name[SIR_MAXPID]) {
64,145✔
1196
#if (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1197
     (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \
1198
      defined(USE_PTHREAD_GETNAME_NP) || defined(__MACOS__)
1199
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
64,145✔
1200
    if (0 != ret)
64,147✔
1201
        return _sir_handleerr(ret);
×
1202

1203
# if defined(__HAIKU__)
1204
    if ((strncmp(name, "pthread_func", SIR_MAXPID)) || _sir_validstrnofail(name))
1205
        snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1206
# endif
1207
    return _sir_validstrnofail(name);
64,147✔
1208
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1209
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1210
    return _sir_validstrnofail(name);
1211
#else
1212
# if !defined(_AIX)
1213
#  pragma message("unable to determine how to get a thread name")
1214
# endif
1215
    SIR_UNUSED(name);
1216
    return false;
1217
#endif
1218
}
1219

1220
bool _sir_gethostname(char name[SIR_MAXHOST]) {
8,279✔
1221
#if !defined(__WIN__)
1222
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,216✔
1223
    return 0 == ret ? true : _sir_handleerr(errno);
8,279✔
1224
#else
1225
    WSADATA wsad = {0};
1226
    int ret      = WSAStartup(MAKEWORD(2, 2), &wsad);
1227
    if (0 != ret)
1228
        return _sir_handlewin32err(ret);
1229

1230
    if (SOCKET_ERROR == gethostname(name, SIR_MAXHOST)) {
1231
        int err = WSAGetLastError();
1232
        WSACleanup();
1233
        return _sir_handlewin32err(err);
1234
    }
1235

1236
    WSACleanup();
1237
    return true;
1238
#endif /* !__WIN__ */
1239
}
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