hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * BlueALSA - log.c
 * Copyright (c) 2016-2018 Arkadiusz Bokowy
 *
 * This file is a part of bluez-alsa.
 *
 * This project is licensed under the terms of the MIT license.
 *
 */
 
#include "shared/log.h"
 
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
 
#include "shared/rt.h"
 
 
/* internal logging identifier */
static char *_ident = NULL;
/* if true, system logging is enabled */
static bool _syslog = false;
/* if true, print logging time */
static bool _time = BLUEALSA_LOGTIME;
 
 
void log_open(const char *ident, bool syslog, bool time) {
 
   free(_ident);
   _ident = strdup(ident);
 
   if ((_syslog = syslog) == true)
       openlog(ident, 0, LOG_USER);
 
   _time = time;
 
}
 
static void vlog(int priority, const char *format, va_list ap) {
 
   int oldstate;
 
   /* Threads cancellation is used extensively in the BlueALSA code. In order
    * to prevent termination within the logging function (which might provide
    * important information about what has happened), the thread cancellation
    * has to be temporally disabled. */
   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
 
   //if (_syslog) {
       va_list ap_syslog;
       va_copy(ap_syslog, ap);
       vsyslog(priority, format, ap_syslog);
       va_end(ap_syslog);
   //}
 
   flockfile(stderr);
 
   if (_ident != NULL)
       fprintf(stderr, "%s: ", _ident);
   if (_time) {
       struct timespec ts;
       gettimestamp(&ts);
       fprintf(stderr, "%lu.%.9lu: ", (long int)ts.tv_sec, ts.tv_nsec);
   }
   vfprintf(stderr, format, ap);
   fputs("\n", stderr);
 
   funlockfile(stderr);
 
   pthread_setcancelstate(oldstate, NULL);
 
}
 
void error(const char *format, ...) {
   va_list ap;
   va_start(ap, format);
   vlog(LOG_ERR, format, ap);
   va_end(ap);
}
 
void warn(const char *format, ...) {
   va_list ap;
   va_start(ap, format);
   vlog(LOG_WARNING, format, ap);
   va_end(ap);
}
 
void info(const char *format, ...) {
   va_list ap;
   va_start(ap, format);
   vlog(LOG_INFO, format, ap);
   va_end(ap);
}
 
#if DEBUG
void _debug(const char *format, ...) {
   va_list ap;
   va_start(ap, format);
   vlog(LOG_DEBUG, format, ap);
   va_end(ap);
}
#endif
 
#if DEBUG
/**
 * Dump memory using hexadecimal representation.
 *
 * @param label Label printed before the memory block output.
 * @param mem Address of the memory block.
 * @param len Number of bytes which should be printed. */
void hexdump(const char *label, const void *mem, size_t len) {
 
   char *buf = malloc(len * 3 + 1);
   char *p = buf;
 
   while (len--) {
       p += sprintf(p, " %02x", *(unsigned char *)mem & 0xFF);
       mem += 1;
   }
 
   fprintf(stderr, "%s:%s\n", label, buf);
   free(buf);
}
#endif
 
#if DEBUG && HAVE_REGISTER_PRINTF_SPECIFIER
/* Register 'B' specifier for printf() function family, so it can
 * be used to print integer values in a binary representation. */
 
#include <printf.h>
 
static int printf_arginfo(const struct printf_info *info, size_t n, int *argtypes, int *size) {
   (void)info;
   if (n >= 1)
       argtypes[0] = PA_INT;
   return *size = 1;
}
 
static int printf_output(FILE *stream, const struct printf_info *info, const void * const *args) {
 
   unsigned int v = *(unsigned int *)(args[0]);
   bool output = false;
   int len = 0;
   int i;
 
   if (info->alt)
       fputs("0b", stream);
 
   for (i = (sizeof(v) * 8) - 1; i >= 0; i--) {
       char c = '0' + ((v >> i) & 1);
       if (output || c == '1') {
           fputc(c, stream);
           output = true;
           len++;
       }
       else if (i == info->width)
           output = true;
   }
 
   return len;
}
 
void __attribute__ ((constructor)) _register_binary_specifier() {
   register_printf_specifier('B', printf_output, printf_arginfo);
}
#endif