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

aremmell / libsir / 428

04 Sep 2023 10:15PM UTC coverage: 94.486% (-0.4%) from 94.865%
428

Pull #257

gitlab-ci

aremmell
don't need check for OrangeC-test is disabled
Pull Request #257: WIP

238 of 238 new or added lines in 12 files covered. (100.0%)

3016 of 3192 relevant lines covered (94.49%)

629655.05 hits per line

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

93.47
/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_mutex fc_mutex   = SIR_MUTEX_INIT;
49
static sir_mutex pc_mutex   = SIR_MUTEX_INIT;
50
static sir_mutex ts_mutex   = SIR_MUTEX_INIT;
51
static sir_once static_once = SIR_ONCE_INIT;
52

53
#if defined(__WIN__)
54
static LARGE_INTEGER _sir_perfcntr_freq = {0};
55
#endif
56

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

63
static _sir_thread_local char _sir_tid[SIR_MAXPID]   = {0};
64
static _sir_thread_local sir_time _sir_last_thrd_chk = {0};
65

66
bool _sir_makeinit(sirinit* si) {
55✔
67
    bool retval = _sir_validptr(si);
55✔
68

69
    if (retval) {
55✔
70
        memset(si, 0, sizeof(sirinit));
49✔
71

72
        si->d_stdout.opts   = SIRO_DEFAULT;
55✔
73
        si->d_stdout.levels = SIRL_DEFAULT;
55✔
74

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

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

87
    return retval;
55✔
88
}
89

90
bool _sir_init(sirinit* si) {
779✔
91
    (void)_sir_seterror(_SIR_E_NOERROR);
779✔
92

93
    if (!_sir_once(&static_once, _sir_init_static_once)) {
779✔
94
        _sir_selflog("error: static data initialization routine failed!");
×
95
        return false;
×
96
    }
97

98
    if (!_sir_validptr(si))
779✔
99
        return false;
19✔
100

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

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

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

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

119
    if (!_sir_init_sanity(si))
734✔
120
        return false;
19✔
121

122
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
712✔
123

124
#if !defined(__WIN__)
125
    tzset();
712✔
126
#endif
127

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

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

138
    _sir_setcolormode(SIRCM_16);
712✔
139

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

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

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

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

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

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

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

165
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
712✔
166

167
    return true;
712✔
168
}
169

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

174
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
712✔
175
    bool cleanup   = true;
613✔
176
    bool destroyfc = _sir_fcache_destroy(sfc);
712✔
177
    SIR_ASSERT(destroyfc);
679✔
178

179
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
712✔
180
    cleanup &= destroyfc;
613✔
181

182
#if !defined(SIR_NO_PLUGINS)
183
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
671✔
184
    bool destroypc = _sir_plugin_cache_destroy(spc);
671✔
185
    SIR_ASSERT(destroypc);
638✔
186
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
671✔
187
    cleanup &= destroypc;
572✔
188
#endif
189

190
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
712✔
191

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

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

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

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

212
    memset(_cfg, 0, sizeof(sirconfig));
613✔
213
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
712✔
214

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

217
    SIR_ASSERT(cleanup);
679✔
218
    return cleanup;
646✔
219
}
220

221
bool _sir_sanity(void) {
2,487,595✔
222
#if defined(__HAVE_ATOMIC_H__)
223
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,487,595✔
224
        return true;
2,407,271✔
225
#else
226
    if (_SIR_MAGIC == _sir_magic)
227
        return true;
228
#endif
229
    return _sir_seterror(_SIR_E_NOTREADY);
51✔
230
}
231

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

236
    bool levelcheck = true;
632✔
237
    levelcheck &= _sir_validlevels(si->d_stdout.levels);
734✔
238
    levelcheck &= _sir_validlevels(si->d_stderr.levels);
734✔
239

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

244
    bool optscheck = true;
632✔
245
    optscheck &= _sir_validopts(si->d_stdout.opts);
734✔
246
    optscheck &= _sir_validopts(si->d_stderr.opts);
734✔
247

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

252
    return levelcheck && optscheck;
734✔
253
}
254

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

266
static
267
bool _sir_updateopts(const char* name, sir_options* old, sir_options* new) {
70,817✔
268
    if (*old != *new) {
70,817✔
269
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
36,414✔
270
        *old = *new;
38,470✔
271
    } else {
272
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
30,358✔
273
    }
274
    return true;
70,817✔
275
}
276

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

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

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

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

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

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

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

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

330
    return updated;
70✔
331
}
332

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

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

350
    return updated;
45✔
351
}
352

353
bool _sir_writeinit(sir_update_config_data* data, sirinit_update update) {
71,882✔
354
    (void)_sir_seterror(_SIR_E_NOERROR);
71,882✔
355

356
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
71,882✔
357
        return false;
×
358

359
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
71,881✔
360

361
    bool updated = update(&_cfg->si, data);
71,882✔
362
    if (!updated)
67,777✔
363
        _sir_selflog("error: update routine failed!");
×
364

365
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
71,882✔
366
    return updated;
71,881✔
367
}
368

369
void* _sir_locksection(sir_mutex_id mid) {
9,038,615✔
370
    sir_mutex* m = NULL;
9,038,615✔
371
    void* sec    = NULL;
9,038,615✔
372

373
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
9,038,615✔
374
    SIR_ASSERT(enter);
8,983,393✔
375

376
    return enter ? sec : NULL;
9,038,922✔
377
}
378

379
void _sir_unlocksection(sir_mutex_id mid) {
9,039,133✔
380
    sir_mutex* m = NULL;
9,039,133✔
381
    void* sec    = NULL;
9,039,133✔
382

383
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
9,039,133✔
384
    SIR_ASSERT_UNUSED(leave, leave);
8,984,988✔
385
}
9,040,622✔
386

387
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
18,073,434✔
388
    sir_mutex* tmpm;
389
    void* tmpsec;
390

391
    switch (mid) {
18,073,434✔
392
        case SIRMI_CONFIG:
8,645,870✔
393
            tmpm   = &cfg_mutex;
8,645,870✔
394
            tmpsec = &_sir_cfg;
8,645,870✔
395
            break;
8,645,870✔
396
        case SIRMI_FILECACHE:
4,461,821✔
397
            tmpm   = &fc_mutex;
4,386,175✔
398
            tmpsec = &_sir_fc;
4,386,175✔
399
            break;
4,461,821✔
400
        case SIRMI_PLUGINCACHE:
236,040✔
401
            tmpm   = &pc_mutex;
196,806✔
402
            tmpsec = &_sir_pc;
196,806✔
403
            break;
236,040✔
404
        case SIRMI_TEXTSTYLE:
4,616,954✔
405
            tmpm   = &ts_mutex;
4,517,811✔
406
            tmpsec = &sir_text_style_section;
4,517,811✔
407
            break;
4,616,954✔
408
        // GCOVR_EXCL_START
409
        default: /* this should never happen. */
410
            SIR_ASSERT(mid);
411
            tmpm   = NULL;
412
            tmpsec = NULL;
413
            break;
414
        // GCOVR_EXCL_STOP
415
    }
416

417
    *m = tmpm;
18,080,450✔
418

419
    if (section)
18,080,450✔
420
        *section = tmpsec;
18,074,053✔
421

422
    return *m != NULL && (!section || *section != NULL);
18,080,450✔
423
}
424

425
#if !defined(__WIN__)
426
void _sir_init_static_once(void) {
57✔
427
    (void)_sir_init_common_static();
57✔
428
}
57✔
429
#else /* __WIN__ */
430
BOOL CALLBACK _sir_init_static_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
431
    SIR_UNUSED(ponce);
432
    SIR_UNUSED(param);
433
    SIR_UNUSED(ctx);
434
    return _sir_init_common_static() ? TRUE : FALSE;
435
}
436
#endif
437

438
bool _sir_init_common_static(void) {
57✔
439
#if defined(__HAVE_ATOMIC_H__)
440
    atomic_init(&_sir_magic, 0);
57✔
441
#endif
442

443
#if defined(__WIN__)
444
    (void)QueryPerformanceFrequency(&_sir_perfcntr_freq);
445
#endif
446

447
    bool created = _sir_mutexcreate(&cfg_mutex);
57✔
448
    SIR_ASSERT_UNUSED(created, created);
55✔
449

450
    created &= _sir_mutexcreate(&fc_mutex);
57✔
451
    SIR_ASSERT_UNUSED(created, created);
55✔
452

453
    created &= _sir_mutexcreate(&pc_mutex);
57✔
454
    SIR_ASSERT_UNUSED(created, created);
55✔
455

456
    created &= _sir_mutexcreate(&ts_mutex);
57✔
457
    SIR_ASSERT_UNUSED(created, created);
55✔
458

459
    return created;
57✔
460
}
461

462
bool _sir_once(sir_once* once, sir_once_fn func) {
779✔
463
#if !defined(__WIN__)
464
    int ret = pthread_once(once, func);
779✔
465
    return 0 == ret ? true : _sir_handleerr(ret);
779✔
466
#else /* __WIN__ */
467
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
468
        : _sir_handlewin32err(GetLastError());
469
#endif
470
}
471

472
PRINTF_FORMAT_ATTR(2, 0)
473
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,154,856✔
474
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,154,856✔
475
        return false;
44✔
476

477
    (void)_sir_seterror(_SIR_E_NOERROR);
2,154,812✔
478

479
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,154,812✔
480

481
    sirbuf buf = {0};
2,154,812✔
482

483
    /* from time to time, update the host name in the config, just in case. */
484
    time_t now_sec = -1;
2,154,812✔
485
    if (-1 != time(&now_sec) &&
2,154,812✔
486
        (now_sec - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,146,903✔
487
        _sir_selflog("updating hostname...");
8,277✔
488
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,298✔
489
            _sir_selflog("error: failed to get hostname!");
7,909✔
490
        } else {
491
            _cfg->state.last_hname_chk = now_sec;
389✔
492
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
368✔
493
        }
494
    }
495

496
    /* format timestamp. */
497
    long now_msec = 0L;
2,154,812✔
498
    bool gettime = _sir_clock_gettime(SIR_WALLCLOCK, &now_sec, &now_msec);
2,154,812✔
499
    SIR_ASSERT_UNUSED(gettime, gettime);
2,146,903✔
500

501
    /* milliseconds. */
502
    _sir_snprintf_trunc(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, now_msec);
2,154,812✔
503

504
    /* hours/minutes/seconds. */
505
    bool fmt = _sir_formattime(now_sec, _cfg->state.timestamp, SIR_TIMEFORMAT);
2,154,812✔
506
    SIR_ASSERT_UNUSED(fmt, fmt);
2,146,903✔
507

508
    /* check elapsed time since updating thread identifier/name. */
509
    sir_time thrd_chk;
510
    double msec_since_thrd_chk = _sir_msec_since(&_sir_last_thrd_chk, &thrd_chk);
2,154,812✔
511

512
    /* update the thread identifier/name if enough time has elapsed. */
513
    if (msec_since_thrd_chk > SIR_THRD_CHK_INTERVAL) {
2,154,812✔
514
        _sir_last_thrd_chk = thrd_chk;
342✔
515

516
        pid_t tid         = _sir_gettid();
342✔
517
        bool resolved_tid = false;
294✔
518

519
        /* prefer thread names. */
520
        resolved_tid = _sir_getthreadname(_sir_tid);
342✔
521

522
        /* if tid is identical to pid... */
523
        if (!resolved_tid && tid == _cfg->state.pid) {
342✔
524
            /* don't use anything to identify the thread. */
525
            _sir_resetstr(_sir_tid);
×
526
            resolved_tid = true;
×
527
        }
528

529
        /* fall back on tid. */
530
        if (!resolved_tid)
294✔
531
            _sir_snprintf_trunc(_sir_tid, SIR_MAXPID, SIR_PIDFORMAT,
×
532
                PID_CAST tid);
533
    }
534

535
    sirconfig cfg;
536
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,131,085✔
537
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,154,812✔
538

539
    buf.timestamp = cfg.state.timestamp;
2,154,812✔
540
    buf.hostname  = cfg.state.hostname;
2,154,812✔
541
    buf.pid       = cfg.state.pidbuf;
2,154,812✔
542
    buf.name      = cfg.si.name;
2,154,812✔
543

544
    const char* style_str = _sir_gettextstyle(level);
2,154,812✔
545

546
    SIR_ASSERT(NULL != style_str);
2,146,903✔
547
    if (NULL != style_str)
2,138,994✔
548
        (void)_sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,154,812✔
549
            strnlen(style_str, SIR_MAXSTYLE));
550

551
    buf.level = _sir_formattedlevelstr(level);
2,154,812✔
552

553
    (void)_sir_strncpy(buf.tid, SIR_MAXPID, _sir_tid, SIR_MAXPID);
2,154,812✔
554

555
    (void)vsnprintf(buf.message, SIR_MAXMESSAGE, format, args);
2,131,085✔
556

557
    if (!_sir_validstr(buf.message))
2,154,812✔
558
        return _sir_seterror(_SIR_E_INTERNAL);
22✔
559

560
    bool match             = false;
2,131,066✔
561
    bool exit_early        = false;
2,131,066✔
562
    bool update_last_props = true;
2,131,066✔
563
    uint64_t hash          = 0ULL;
2,131,066✔
564

565
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,154,790✔
566
        cfg.state.last.prefix[1] == buf.message[1]) {
2,100,540✔
567
        hash  = FNV64_1a(buf.message);
2,118,704✔
568
        match = cfg.state.last.hash == hash;
2,118,704✔
569
    }
570

571
    if (match) {
2,149,879✔
572
        cfg.state.last.counter++;
34,344✔
573

574
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
575
            cfg.state.last.counter); */
576

577
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
34,344✔
578
            size_t old_threshold = cfg.state.last.threshold;
916✔
579

580
            update_last_props = false;
916✔
581
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
1,062✔
582
            cfg.state.last.squelch = true;
1,062✔
583

584
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
1,014✔
585
                         " to %zu (factor: %d)",
586
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
587

588
            (void)snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold);
916✔
589
        } else if (cfg.state.last.squelch) {
33,282✔
590
            exit_early = true;
26,737✔
591
        }
592
    } else {
593
        cfg.state.last.squelch   = false;
2,120,446✔
594
        cfg.state.last.counter   = 0;
2,120,446✔
595
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,120,446✔
596
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
597
    }
598

599
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,154,790✔
600
    if (!_cfg)
2,154,790✔
601
        return _sir_seterror(_SIR_E_INTERNAL);
×
602

603
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,154,790✔
604

605
    if (update_last_props) {
2,154,790✔
606
        _cfg->state.last.hash      = hash;
2,153,728✔
607
        _cfg->state.last.prefix[0] = buf.message[0];
2,153,728✔
608
        _cfg->state.last.prefix[1] = buf.message[1];
2,153,728✔
609
    }
610

611
    _cfg->state.last.counter   = cfg.state.last.counter;
2,154,790✔
612
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,154,790✔
613

614
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,154,790✔
615

616
    if (exit_early)
2,154,790✔
617
        return false;
26,737✔
618

619
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,123,832✔
620
    return update_last_props ? dispatched : false;
2,123,832✔
621
}
622

623
bool _sir_dispatch(sirinit* si, sir_level level, sirbuf* buf) {
2,123,832✔
624
    bool retval       = true;
2,104,329✔
625
    size_t dispatched = 0;
2,104,329✔
626
    size_t wanted     = 0;
2,104,329✔
627

628
    if (_sir_bittest(si->d_stdout.levels, level)) {
2,123,832✔
629
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,120,200✔
630
        bool wrote        = _sir_validstrnofail(write) &&
2,240,398✔
631
            _sir_write_stdout(write, buf->output_len);
1,120,200✔
632
        retval &= wrote;
1,120,198✔
633

634
        if (wrote)
1,120,198✔
635
            dispatched++;
1,095,076✔
636
        wanted++;
1,101,286✔
637
    }
638

639
    if (_sir_bittest(si->d_stderr.levels, level)) {
2,123,830✔
640
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,106✔
641
        bool wrote        = _sir_validstrnofail(write) &&
2,212✔
642
            _sir_write_stderr(write, buf->output_len);
1,106✔
643
        retval &= wrote;
1,106✔
644

645
        if (wrote)
1,106✔
646
            dispatched++;
1,097✔
647
        wanted++;
1,106✔
648
    }
649

650
#if !defined(SIR_NO_SYSTEM_LOGGERS)
651
    if (_sir_bittest(si->d_syslog.levels, level)) {
2,089,469✔
652
        if (_sir_syslog_write(level, buf, &si->d_syslog))
594✔
653
            dispatched++;
594✔
654
        wanted++;
594✔
655
    }
656
#endif
657

658
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,123,830✔
659
    size_t fdispatched = 0;
2,123,832✔
660
    size_t fwanted     = 0;
2,123,832✔
661
    retval &= _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted);
2,123,832✔
662
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,123,832✔
663

664
    dispatched += fdispatched;
2,123,832✔
665
    wanted += fwanted;
2,123,832✔
666

667
#if !defined(SIR_NO_PLUGINS)
668
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
117,256✔
669
    size_t pdispatched = 0;
117,256✔
670
    size_t pwanted     = 0;
117,256✔
671
    retval &= _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted);
117,256✔
672
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
117,256✔
673

674
    dispatched += pdispatched;
117,256✔
675
    wanted += pwanted;
117,256✔
676
#endif
677

678
    if (0 == wanted) {
2,123,832✔
679
        _sir_selflog("error: no destinations registered for level %04"PRIx16, level);
890✔
680
        return _sir_seterror(_SIR_E_NODEST);
943✔
681
    }
682

683
    return retval && (dispatched == wanted);
2,122,889✔
684
}
685

686
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,266,803✔
687
    if (_sir_validptr(buf)) {
2,266,803✔
688
        bool first = true;
2,222,215✔
689

690
        _sir_resetstr(buf->output);
2,266,762✔
691

692
        if (styling)
2,266,808✔
693
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,121,306✔
694

695
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,266,808✔
696
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,105,639✔
697
            first = false;
2,086,848✔
698

699
#if defined(SIR_MSEC_TIMER)
700
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,105,639✔
701
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
70,214✔
702
#endif
703
        }
704

705
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,266,835✔
706
            if (!first)
1,032,506✔
707
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,543✔
708
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,032,506✔
709
            first = false;
1,026,327✔
710
        }
711

712
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,266,868✔
713
            if (!first)
2,156,123✔
714
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,105,822✔
715
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,156,123✔
716
            first = false;
2,130,390✔
717
        }
718

719
        bool name = false;
2,222,157✔
720
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,266,743✔
721
            if (!first)
1,103,799✔
722
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,099,857✔
723
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,103,802✔
724
            first = false;
1,085,322✔
725
            name  = true;
1,085,322✔
726
        }
727

728
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,266,780✔
729
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,267,089✔
730

731
        if (wantpid || wanttid) {
2,267,065✔
732
            if (name)
2,137,985✔
733
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,098,471✔
734
            else if (!first)
1,039,514✔
735
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,039,508✔
736

737
            if (wantpid)
2,137,984✔
738
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,074,361✔
739

740
            if (wanttid) {
2,137,982✔
741
                if (wantpid)
2,132,617✔
742
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
2,069,008✔
743
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
2,132,618✔
744
            }
745

746
            if (name)
2,137,978✔
747
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,098,465✔
748

749
            if (first)
2,113,151✔
750
                first = false;
6✔
751
        }
752

753
        if (!first)
2,242,231✔
754
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,190,762✔
755

756
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,267,045✔
757

758
        if (styling)
2,266,885✔
759
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,121,298✔
760

761
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,266,885✔
762

763
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,266,877✔
764

765
        return buf->output;
2,266,877✔
766
    }
767

768
    return NULL;
×
769
}
770

771
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
223✔
772
#if !defined(SIR_NO_SYSTEM_LOGGERS)
773
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
223✔
774
        return false;
×
775

776
    /* begin resolve identity. */
777
    if (!_sir_validstrnofail(ctx->identity)) {
223✔
778
        _sir_selflog("ctx->identity is no good; trying name");
49✔
779
        if (_sir_validstrnofail(name)) {
52✔
780
            _sir_selflog("using name");
28✔
781
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
30✔
782
        } else {
783
            _sir_selflog("name is no good; trying filename");
21✔
784
            char* appbasename = _sir_getappbasename();
22✔
785
            if (_sir_validstrnofail(appbasename)) {
22✔
786
                _sir_selflog("filename is good: %s", appbasename);
16✔
787
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
16✔
788
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
789
            } else {
790
                _sir_selflog("filename no good; using fallback");
6✔
791
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
6✔
792
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
793
            }
794
            _sir_safefree(&appbasename);
22✔
795
        }
796
    } else {
797
        _sir_selflog("already have identity");
161✔
798
    }
799

800
    /* category */
801
    if (!_sir_validstrnofail(ctx->category)) {
223✔
802
        _sir_selflog("category not set; using fallback");
73✔
803
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
77✔
804
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
805
    } else {
806
        _sir_selflog("already have category");
137✔
807
    }
808

809
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
223✔
810
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
210✔
811

812
    return _sir_syslog_open(ctx);
223✔
813
#else
814
    SIR_UNUSED(name);
815
    SIR_UNUSED(ctx);
816
    return false;
×
817
#endif
818
}
819

820
bool _sir_syslog_open(sir_syslog_dest* ctx) {
223✔
821
#if !defined(SIR_NO_SYSTEM_LOGGERS)
822
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
223✔
823
        _sir_selflog("not initialized; ignoring");
×
824
        return _sir_seterror(_SIR_E_INVALID);
×
825
    }
826

827
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
223✔
828
        _sir_selflog("log already open; ignoring");
95✔
829
        return true;
95✔
830
    }
831

832
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
122✔
833
        ctx->opts);
834

835
# if defined(SIR_OS_LOG_ENABLED)
836
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
837
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
838
# elif defined(SIR_SYSLOG_ENABLED)
839
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
122✔
840
    int facility = LOG_USER;
101✔
841

842
    openlog(ctx->identity, logopt, facility);
122✔
843
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
115✔
844
# endif
845

846
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
122✔
847
    return true;
122✔
848
#else
849
    SIR_UNUSED(ctx);
850
    return false;
×
851
#endif
852
}
853

854
bool _sir_syslog_write(sir_level level, const sirbuf* buf, sir_syslog_dest* ctx) {
594✔
855
#if !defined(SIR_NO_SYSTEM_LOGGERS)
856
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
594✔
857
        _sir_selflog("not initialized; ignoring");
×
858
        return _sir_seterror(_SIR_E_INVALID);
×
859
    }
860

861
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
594✔
862
        _sir_selflog("log not open; ignoring");
×
863
        return _sir_seterror(_SIR_E_INVALID);
×
864
    }
865

866
# if defined(SIR_OS_LOG_ENABLED)
867
    if (SIRL_DEBUG == level)
868
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
869
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
870
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
871
    else if (SIRL_WARN == level || SIRL_ERROR == level)
872
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
873
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
874
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
875

876
    return true;
877
# elif defined(SIR_SYSLOG_ENABLED)
878
    int syslog_level;
879
    switch (level) {
594✔
880
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
25✔
881
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
27✔
882
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
80✔
883
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
80✔
884
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
80✔
885
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
106✔
886
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
80✔
887
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
106✔
888
        // GCOVR_EXCL_START
889
        case SIRL_NONE: /* this should never happen. */
890
        default:
891
            SIR_ASSERT(level);
892
            syslog_level = LOG_DEBUG;
893
        // GCOVR_EXCL_STOP
894
    }
895

896
    syslog(syslog_level, "%s", buf->message);
594✔
897
    return true;
594✔
898
# endif
899
#else
900
    SIR_UNUSED(level);
901
    SIR_UNUSED(buf);
902
    SIR_UNUSED(ctx);
903
    return false;
×
904
#endif
905
}
906

907
bool _sir_syslog_updated(sirinit* si, sir_update_config_data* data) {
229✔
908
#if !defined(SIR_NO_SYSTEM_LOGGERS)
909
    if (!_sir_validptr(si) || !_sir_validptr(data))
229✔
910
        return false;
×
911

912
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
229✔
913
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
216✔
914
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
229✔
915
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
216✔
916
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
229✔
917
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
229✔
918
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
229✔
919

920
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
216✔
921
                     " identity: %u, is_init: %u, is_open: %u)",
922
                     levels, options, category, identity, is_init, is_open);
923

924
        bool must_init = false;
190✔
925

926
# if defined(SIR_OS_LOG_ENABLED)
927
        /*
928
         * for os_log, if initialized and open already, only need to reconfigure
929
         * if identity or category changed.
930
         */
931
        must_init = (!is_init || !is_open) || (identity || category);
932
# elif defined(SIR_SYSLOG_ENABLED)
933
        /*
934
         * for os_log, if initialized and open already, only need to reconfigure
935
         * if identity or options changed.
936
         */
937
        must_init = (!is_init || !is_open) || (identity || options);
229✔
938
# endif
939
        bool init = true;
190✔
940
        if (must_init) {
190✔
941
            _sir_selflog("re-init...");
120✔
942
            init = _sir_syslog_init(si->name, &si->d_syslog);
127✔
943
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
120✔
944
        } else {
945
            _sir_selflog("no re-init necessary");
96✔
946
        }
947

948
        return init;
229✔
949
    } else {
950
        _sir_selflog("BUG: called without 'updated' flag set!");
×
951
        return false;
×
952
    }
953
#else
954
    SIR_UNUSED(si);
955
    SIR_UNUSED(data);
956
    return false;
×
957
#endif
958
}
959

960
bool _sir_syslog_close(sir_syslog_dest* ctx) {
538✔
961
#if !defined(SIR_NO_SYSTEM_LOGGERS)
962
    if (!_sir_validptr(ctx))
538✔
963
        return false;
×
964

965
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
538✔
966
        _sir_selflog("log not open; ignoring");
390✔
967
        return true;
390✔
968
    }
969

970
# if defined(SIR_OS_LOG_ENABLED)
971
    /* evidently, you don't need to close the handle returned from os_log_create(), and
972
     * if you make that call again, you'll get the same cached value. so let's keep the
973
     * value we've got in the global context. */
974
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
975
    _sir_selflog("log closure not necessary");
976
    return true;
977
# elif defined(SIR_SYSLOG_ENABLED)
978
    closelog();
122✔
979
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
122✔
980
    _sir_selflog("closed log");
115✔
981
    return true;
122✔
982
# endif
983
#else
984
    SIR_UNUSED(ctx);
985
    return false;
×
986
#endif
987
}
988

989
void _sir_syslog_reset(sir_syslog_dest* ctx) {
1,076✔
990
#if !defined(SIR_NO_SYSTEM_LOGGERS)
991
    if (_sir_validptr(ctx)) {
1,076✔
992
        uint32_t old       = ctx->_state.mask;
1,010✔
993
        ctx->_state.mask   = 0U;
1,076✔
994
        ctx->_state.logger = NULL;
1,076✔
995
        _sir_selflog("state reset; mask was %08"PRIx32, old);
1,010✔
996
    }
997
#else
998
    SIR_UNUSED(ctx);
999
#endif
1000
}
1,076✔
1001

1002
const char* _sir_formattedlevelstr(sir_level level) {
2,154,812✔
1003
    static const size_t low  = 0;
1004
    static const size_t high = SIR_NUMLEVELS - 1;
1005

1006
    const char* retval = SIR_UNKNOWN;
2,131,085✔
1007

1008
    _SIR_DECLARE_BIN_SEARCH(low, high);
2,131,085✔
1009
    _SIR_BEGIN_BIN_SEARCH()
1010

1011
    if (sir_level_to_str_map[_mid].level == level) {
8,576,716✔
1012
        retval = sir_level_to_str_map[_mid].fmt;
2,154,812✔
1013
        break;
2,154,812✔
1014
    }
1015

1016
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1));
6,421,904✔
1017
    _SIR_END_BIN_SEARCH();
1018

1019
    return retval;
2,154,812✔
1020
}
1021

1022
bool _sir_clock_gettime(int clock, time_t* tbuf, long* msecbuf) {
6,309,700✔
1023
    if (tbuf) {
6,309,700✔
1024
#if defined(SIR_MSEC_POSIX)
1025
        struct timespec ts = {0};
6,309,700✔
1026
        int ret            = clock_gettime(clock, &ts);
6,309,700✔
1027
        SIR_ASSERT(0 == ret);
6,293,879✔
1028

1029
        if (0 == ret) {
6,278,058✔
1030
            *tbuf = ts.tv_sec;
6,293,959✔
1031
            if (msecbuf)
6,293,959✔
1032
                *msecbuf = (long)(ts.tv_nsec / 1000000L);
6,293,959✔
1033
        } else {
1034
            if (msecbuf)
15,741✔
1035
                *msecbuf = 0L;
15,741✔
1036
            return _sir_handleerr(errno);
15,741✔
1037
        }
1038
#elif defined(SIR_MSEC_WIN32)
1039
        SIR_UNUSED(clock);
1040
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9;
1041

1042
        FILETIME ftutc = {0};
1043
        GetSystemTimePreciseAsFileTime(&ftutc);
1044

1045
        ULARGE_INTEGER ftnow = {0};
1046
        ftnow.HighPart = ftutc.dwHighDateTime;
1047
        ftnow.LowPart  = ftutc.dwLowDateTime;
1048
        ftnow.QuadPart = (ULONGLONG)((ftnow.QuadPart - uepoch) / 10000000ULL);
1049

1050
        *tbuf = (time_t)ftnow.QuadPart;
1051

1052
        SYSTEMTIME st = {0};
1053
        if (FileTimeToSystemTime(&ftutc, &st)) {
1054
            if (msecbuf)
1055
                *msecbuf = (long)st.wMilliseconds;
1056
        } else {
1057
            if (msecbuf)
1058
                *msecbuf = 0L;
1059
            return _sir_handlewin32err(GetLastError());
1060
        }
1061
#else
1062
        time(tbuf);
1063
        if (msecbuf)
1064
            *msecbuf = 0L;
1065
#endif
1066
        return true;
6,293,959✔
1067
    }
1068
    return false;
×
1069
}
1070

1071
double _sir_msec_since(const sir_time* when, sir_time* out) {
4,154,888✔
1072
    if (!_sir_validptr(out))
4,154,888✔
1073
        return 0.0;
×
1074
#if !defined(__WIN__) || defined(__ORANGEC__)
1075
    out->sec = 0;
4,154,888✔
1076
    out->msec = 0L;
4,154,888✔
1077

1078
    bool gettime = _sir_clock_gettime(SIR_INTERVALCLOCK, &out->sec, &out->msec);
4,154,888✔
1079
    SIR_ASSERT(gettime);
4,146,976✔
1080

1081
    if (!_sir_validptrnofail(when) || !gettime || (out->sec < when->sec ||
4,154,888✔
1082
        (out->sec == when->sec && out->msec < when->msec)))
4,144,548✔
1083
        return 0.0;
7,913✔
1084

1085
    return ((((double)out->sec) * 1e3) + (double)out->msec) -
4,146,969✔
1086
           ((((double)when->sec) * 1e3) + (double)when->msec);
4,146,969✔
1087
#else /* __WIN__ */
1088
    SIR_ASSERT(_sir_perfcntr_freq.QuadPart > 0LL);
1089

1090
    if (_sir_perfcntr_freq.QuadPart <= 0LL)
1091
        return 0.0;
1092

1093
    (void)QueryPerformanceCounter(&out->counter);
1094

1095
    if (!_sir_validptrnofail(when) || out->counter.QuadPart <= when->counter.QuadPart)
1096
        return 0.0;
1097

1098
    double msec_ratio = ((double)_sir_perfcntr_freq.QuadPart) / 1e3;
1099
    return ((double)(out->counter.QuadPart - when->counter.QuadPart)) / msec_ratio;
1100
#endif
1101
}
1102

1103
pid_t _sir_getpid(void) {
728✔
1104
#if !defined(__WIN__)
1105
    return getpid();
728✔
1106
#else /* __WIN__ */
1107
    return (pid_t)GetCurrentProcessId();
1108
#endif
1109
}
1110

1111
pid_t _sir_gettid(void) {
438✔
1112
    pid_t tid = 0;
375✔
1113
#if defined(__MACOS__)
1114
    uint64_t tid64 = 0ULL;
1115
    int gettid     = pthread_threadid_np(NULL, &tid64);
1116
    if (0 != gettid)
1117
        (void)_sir_handleerr(gettid);
1118
    tid = (pid_t)tid64;
1119
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1120
      defined(__DragonFly_getthreadid__)
1121
    tid = (pid_t)pthread_getthreadid_np();
1122
#elif defined(__OpenBSD__)
1123
    tid = (pid_t)getthrid();
1124
#elif defined(__SOLARIS__) || defined(__NetBSD__) || defined(__HURD__) || \
1125
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1126
    tid = (pid_t)pthread_self();
1127
#elif defined(__HAIKU__)
1128
    tid = get_pthread_thread_id(pthread_self());
1129
#elif defined(__linux__) || defined(__serenity__)
1130
# if (defined(__GLIBC__) && GLIBC_VERSION >= 23000) || defined(__serenity__)
1131
    tid = gettid();
438✔
1132
# else
1133
    tid = syscall(SYS_gettid);
1134
# endif
1135
#elif defined(__WIN__)
1136
    tid = (pid_t)GetCurrentThreadId();
1137
#else
1138
# error "cannot determine how to get thread id; please contact the author"
1139
#endif
1140
    return tid;
438✔
1141
}
1142

1143
bool _sir_getthreadname(char name[SIR_MAXPID]) {
342✔
1144
    _sir_resetstr(name);
342✔
1145
#if defined(__MACOS__) || \
1146
   (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1147
   (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1148
    defined(USE_PTHREAD_GETNAME_NP)
1149
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
342✔
1150
    if (0 != ret)
342✔
1151
        return _sir_handleerr(ret);
×
1152
# if defined(__HAIKU__)
1153
    if ((strncmp(name, "pthread_func", SIR_MAXPID)) || _sir_validstrnofail(name))
1154
        (void)snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1155
# endif
1156
    return _sir_validstrnofail(name);
342✔
1157
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1158
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1159
    return _sir_validstrnofail(name);
1160
#elif defined(__WIN__)
1161
    bool success       = false;
1162
    wchar_t* wide_name = NULL;
1163
    HRESULT hr         = GetThreadDescription(GetCurrentThread(), &wide_name);
1164
    if (SUCCEEDED(hr)) {
1165
# if defined(__HAVE_STDC_SECURE_OR_EXT1__)
1166
        size_t wide_len = wcsnlen_s(wide_name, SIR_MAXPID);
1167
# elif defined(__EMBARCADEROC__)
1168
        size_t wide_len = wcslen(wide_name);
1169
# else
1170
        size_t wide_len = wcsnlen(wide_name, SIR_MAXPID);
1171
# endif
1172
        if (wide_len > 0) {
1173
            if (WideCharToMultiByte(CP_UTF8, 0UL, wide_name, (int)wide_len, name, SIR_MAXPID,
1174
                NULL, NULL))
1175
                success = true;
1176
            else
1177
                (void)_sir_handlewin32err(GetLastError());
1178
        } else {
1179
            success = true;
1180
        }
1181
        (void)LocalFree(wide_name);
1182
    }
1183
    return success && _sir_validstrnofail(name);
1184
#else
1185
# if !defined(_AIX) && !defined(__HURD__) && !defined(SUNLINT)
1186
#  pragma message("unable to determine how to get a thread name")
1187
# endif
1188
    SIR_UNUSED(name);
1189
    return false;
1190
#endif
1191
}
1192

1193
bool _sir_gethostname(char name[SIR_MAXHOST]) {
8,298✔
1194
#if !defined(__WIN__)
1195
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,235✔
1196
    return 0 == ret ? true : _sir_handleerr(errno);
8,298✔
1197
#else
1198
    WSADATA wsad = {0};
1199
    int ret      = WSAStartup(MAKEWORD(2, 2), &wsad);
1200
    if (0 != ret)
1201
        return _sir_handlewin32err(ret);
1202

1203
    if (SOCKET_ERROR == gethostname(name, SIR_MAXHOST)) {
1204
        int err = WSAGetLastError();
1205
        WSACleanup();
1206
        return _sir_handlewin32err(err);
1207
    }
1208

1209
    WSACleanup();
1210
    return true;
1211
#endif /* !__WIN__ */
1212
}
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