GCC Code Coverage Report


Directory: src/
File: src/logger.c
Date: 2025-03-14 00:32:36
Exec Total Coverage
Lines: 182 187 97.3%
Functions: 27 27 100.0%
Branches: 60 82 73.2%

Line Branch Exec Source
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright (C) 2024 Omar Castro
3 #define LOGGER_C
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include <grp.h>
8 #include <pwd.h>
9 #include <polkit/polkit.h>
10 #include "cmdline.h"
11 #include "app.h"
12 #include "logger.h"
13 #include <json-glib/json-glib.h>
14
15
16 bool silenced_logs = false;
17 bool verbose_logs = false;
18
19
20 const char * currentFile = "";
21 const char * currentFunction = "";
22 int currentLine = 0;
23
24 #define UPDATE_CURRENT_SOURCE_LOCATION() currentFile = file; currentFunction = function; currentLine = line;
25 #define CHECK_VERBOSE() if(!verbose_logs || silenced_logs) { return; }
26
27 static void log__fail_cmdline(const char* text);
28 static void log__verbose_formatted(const char* format, ...);
29 41 static inline void log__verbose_raw(const char* text){ log__verbose_formatted("%s", text); }
30
31
32 11 void print_help (FILE *file)
33 {
34 11 size_t len_purpose = strlen(gengetopt_args_info_purpose);
35 11 size_t len_usage = strlen(gengetopt_args_info_usage);
36
37
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (len_usage > 0) {
38 11 fprintf(file, "%s\n", gengetopt_args_info_usage);
39 }
40
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (len_purpose > 0) {
41 11 fprintf(file, "%s\n", gengetopt_args_info_purpose);
42 }
43
44
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11 if (len_usage || len_purpose) {
45 11 fprintf(file, "\n");
46 }
47
48
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (strlen(gengetopt_args_info_description) > 0) {
49 11 fprintf(file, "%s\n\n", gengetopt_args_info_description);
50 }
51
52 11 int i = 0;
53
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 11 times.
110 while (gengetopt_args_info_help[i])
54 99 fprintf(file, "%s\n", gengetopt_args_info_help[i++]);
55 11 }
56
57
58 1 void log__silence(){
59 1 silenced_logs = true;
60 1 }
61 8 void log__verbose(){
62 8 verbose_logs = true;
63 8 }
64
65 // log error, print help and exits
66
67 4 void log__fail_cmdline__command_required(MACRO__SOURCE_LOCATION_PARAMS){
68 4 UPDATE_CURRENT_SOURCE_LOCATION()
69 4 log__fail_cmdline("command argument is required");
70 4 }
71
72 4 void log__fail_cmdline__either_parallel_or_series(MACRO__SOURCE_LOCATION_PARAMS){
73 4 UPDATE_CURRENT_SOURCE_LOCATION()
74 4 log__fail_cmdline("only serial or parallel mode must be selected, not both");
75 4 }
76
77 4 void log__fail_cmdline__parallel_or_series_required(MACRO__SOURCE_LOCATION_PARAMS){
78 4 UPDATE_CURRENT_SOURCE_LOCATION()
79 4 log__fail_cmdline("parallel or serial mode is required");
80 4 }
81
82 1 void log__fail_cmdline__error_parsing_command(MACRO__SOURCE_LOCATION_PARAMS, const char * message){
83 1 UPDATE_CURRENT_SOURCE_LOCATION()
84
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(!silenced_logs) {
85 1 fprintf(stderr, "Error parsing command line: error parsing shell command: %s\n", message);
86 1 log__fail_cmdline__print_help();
87 }
88 1 }
89
90
91 11 void log__fail_cmdline__print_help(){
92 11 fprintf(stderr, "\n");
93 11 print_help(stderr);
94 11 }
95
96
97
98 // logs on verbose only
99
100 33 void log__verbose__cmd_and_mode(MACRO__SOURCE_LOCATION_PARAMS){
101 33 UPDATE_CURRENT_SOURCE_LOCATION()
102 33 log__verbose_formatted("COMMAND TO EXECUTE: %s", app__get_cmd_line());
103
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 1 times.
33 log__verbose_formatted("AUTH HANDLING MODE: %s", app__get_auth_handling_mode() == AuthHandlingMode_PARALLEL ? "PARALLEL" : "SERIE");
104 33 }
105
106 4 void log__verbose__init_polkit_listener(MACRO__SOURCE_LOCATION_PARAMS){
107 4 UPDATE_CURRENT_SOURCE_LOCATION()
108 4 log__verbose_raw("Polkit Listener initialized");
109 4 }
110
111 6 void log__verbose__finalize_polkit_listener(MACRO__SOURCE_LOCATION_PARAMS){
112 6 UPDATE_CURRENT_SOURCE_LOCATION()
113 6 log__verbose_raw("Polkit Listener finalized");
114 6 }
115
116 10 void log__verbose__init_polkit_authentication(MACRO__SOURCE_LOCATION_PARAMS, const char *action_id, const char *message, const char *icon_name, const char * cookie ){
117 10 UPDATE_CURRENT_SOURCE_LOCATION()
118 10 log__verbose_raw("initiate Polkit authentication");
119 10 log__verbose_formatted("└─ action id : %s", action_id);
120 10 log__verbose_formatted("└─ message : %s", message);
121 10 log__verbose_formatted("└─ icon name : %s", icon_name);
122 10 log__verbose_formatted("└─ cookie : %s", cookie);
123
124 10 }
125
126
127 const gchar * polkit_auth_identity_to_json_string(PolkitIdentity * identity);
128 11 void log__verbose__polkit_auth_identities(MACRO__SOURCE_LOCATION_PARAMS, const GList* const identities){
129
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
11 CHECK_VERBOSE()
130 2 UPDATE_CURRENT_SOURCE_LOCATION()
131 2 log__verbose_raw("Polkit identities");
132
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (const GList *p = identities; p != NULL; p = p->next) {
133 4 PolkitIdentity *id = (PolkitIdentity *)p->data;
134 8 g_autofree const gchar* json = polkit_auth_identity_to_json_string(id);
135 4 log__verbose_formatted("└─ %s", json);
136 }
137 }
138
139 11 void log__verbose__polkit_auth_details(MACRO__SOURCE_LOCATION_PARAMS, PolkitDetails* const details){
140
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
11 CHECK_VERBOSE()
141 2 UPDATE_CURRENT_SOURCE_LOCATION()
142 2 char** keys = polkit_details_get_keys(details);
143
144 2 log__verbose_raw("Polkit details");
145
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (keys == NULL) {
146 1 log__verbose_raw("└─ (empty)");
147 1 return;
148 }
149
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for(char** key = keys;*key;key++) {
150 2 log__verbose_formatted("└─ %s: %s", *key, polkit_details_lookup(details, *key));
151 }
152 1 g_strfreev(keys);
153 }
154
155 10 void log__verbose__polkit_action_description(MACRO__SOURCE_LOCATION_PARAMS, PolkitActionDescription* const action_description){
156
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
10 CHECK_VERBOSE()
157 1 UPDATE_CURRENT_SOURCE_LOCATION()
158
159 1 log__verbose_raw("Polkit action description");
160 1 log__verbose_formatted("└─ id: %s", polkit_action_description_get_action_id(action_description));
161 1 log__verbose_formatted("└─ description: %s", polkit_action_description_get_description(action_description));
162 1 log__verbose_formatted("└─ message: %s", polkit_action_description_get_message(action_description));
163 1 log__verbose_formatted("└─ vendor name: %s", polkit_action_description_get_vendor_name(action_description));
164 1 log__verbose_formatted("└─ vendor url: %s", polkit_action_description_get_vendor_url(action_description));
165 1 log__verbose_raw("└─ annotations:");
166
167 1 const gchar *const * annotations = polkit_action_description_get_annotation_keys(action_description);
168
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for(const gchar *const * i = annotations; *i != NULL; ++i){
169 1 const gchar * annotation = *i;
170 1 log__verbose_formatted(" └─ %s: %s", annotation, polkit_action_description_get_annotation(action_description, annotation));
171 }
172 }
173
174 16 void log__verbose__polkit_session_completed(MACRO__SOURCE_LOCATION_PARAMS, bool authorized, bool canceled){
175
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
16 CHECK_VERBOSE()
176 4 UPDATE_CURRENT_SOURCE_LOCATION()
177 4 log__verbose_raw("Polkit session completed");
178
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 log__verbose_formatted("└─ {\"authorized\": \"%s\", \"canceled\":\"%s\" })", authorized ? "yes": "no", canceled ? "yes": "no");
179 }
180
181 1 void log__verbose__polkit_session_show_error(MACRO__SOURCE_LOCATION_PARAMS, const char *text){
182
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 CHECK_VERBOSE()
183 1 UPDATE_CURRENT_SOURCE_LOCATION()
184 1 log__verbose_formatted("Polkit session show error: %s", text);
185 }
186
187
188 1 void log__verbose__polkit_session_show_info(MACRO__SOURCE_LOCATION_PARAMS, const char *text){
189 1 UPDATE_CURRENT_SOURCE_LOCATION()
190 1 log__verbose_formatted("Polkit session show info: %s", text);
191 1 }
192
193
194 14 void log__verbose__polkit_session_request(MACRO__SOURCE_LOCATION_PARAMS, const char *text, bool visibility){
195 14 UPDATE_CURRENT_SOURCE_LOCATION()
196 14 log__verbose_formatted("Polkit session request: %s", text);
197
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 log__verbose_formatted("└─ visibility: %s", visibility ? "yes" : "no");
198
199 14 }
200
201 10 void log__verbose__finish_polkit_authentication(MACRO__SOURCE_LOCATION_PARAMS){
202 10 UPDATE_CURRENT_SOURCE_LOCATION()
203 10 log__verbose_raw("finish Polkit authentication");
204 10 }
205
206 24 void log__verbose__writing_to_command_stdin(MACRO__SOURCE_LOCATION_PARAMS, const char * message){
207 24 UPDATE_CURRENT_SOURCE_LOCATION()
208 24 log__verbose_formatted("writing to command stdin: %s", message);
209 24 }
210
211 13 void log__verbose__received_from_command_stdout(MACRO__SOURCE_LOCATION_PARAMS, const char * message){
212 13 UPDATE_CURRENT_SOURCE_LOCATION()
213 13 log__verbose_formatted("received line from command stdout: %s", message);
214 13 }
215
216 13 void log__verbose__reading_command_stdout(MACRO__SOURCE_LOCATION_PARAMS){
217 13 UPDATE_CURRENT_SOURCE_LOCATION()
218 13 log__verbose_formatted("reading output");
219 13 }
220
221
222
223 // private
224
225 243 static void log__verbose_formatted( const char* format, ... )
226 {
227
3/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 199 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
243 CHECK_VERBOSE()
228 va_list arglist;
229 44 printf( "Vrbos:%s:", currentFunction );
230 44 va_start( arglist, format );
231 44 vprintf( format, arglist );
232 44 va_end( arglist );
233 44 printf( "\n" );
234
235 }
236
237 12 static void log__fail_cmdline(const char* text){
238
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if(!silenced_logs) {
239 9 fprintf(stderr, "Error parsing command line: %s\n", text);
240 9 log__fail_cmdline__print_help();
241 }
242 12 }
243
244
245 4 const gchar * polkit_auth_identity_to_json_string(PolkitIdentity * identity){
246 8 g_autoptr(JsonBuilder) builder = json_builder_new ();
247
248 4 json_builder_begin_object (builder);
249
250
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if(identity == NULL){
251 1 json_builder_set_member_name (builder, "type");
252 1 json_builder_add_string_value (builder, "error");
253
254 1 json_builder_set_member_name (builder, "error");
255 1 json_builder_add_string_value (builder, "identity is null");
256
7/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
3 } else if(POLKIT_IS_UNIX_USER(identity)) {
257 1 uid_t uid = polkit_unix_user_get_uid(POLKIT_UNIX_USER(identity));
258 1 struct passwd *pwd = getpwuid(uid);
259 1 json_builder_set_member_name (builder, "type");
260 1 json_builder_add_string_value (builder, "user");
261
262 1 json_builder_set_member_name (builder, "name");
263 1 json_builder_add_string_value (builder, pwd->pw_name);
264
265 1 json_builder_set_member_name (builder, "id");
266 1 json_builder_add_int_value (builder, pwd->pw_uid);
267
268 1 json_builder_set_member_name (builder, "group id");
269 1 json_builder_add_int_value (builder, pwd->pw_gid);
270
271
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
2 } else if(POLKIT_IS_UNIX_GROUP(identity)) {
272 1 gid_t gid = polkit_unix_group_get_gid(POLKIT_UNIX_GROUP(identity));
273 1 struct group *grp = getgrgid(gid);
274
275 1 json_builder_set_member_name (builder, "type");
276 1 json_builder_add_string_value (builder, "group");
277
278 1 json_builder_set_member_name (builder, "name");
279 1 json_builder_add_string_value (builder, grp->gr_name);
280
281 1 json_builder_set_member_name (builder, "id");
282 1 json_builder_add_int_value (builder, grp->gr_gid);
283
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 } else if(POLKIT_IS_IDENTITY(identity)){
284 g_autofree gchar* value = polkit_identity_to_string(identity);
285
286 json_builder_set_member_name (builder, "type");
287 json_builder_add_string_value (builder, "other");
288
289 json_builder_set_member_name (builder, "value");
290 json_builder_add_string_value (builder, value);
291 } else {
292 1 json_builder_set_member_name (builder, "type");
293 1 json_builder_add_string_value (builder, "error");
294
295 1 json_builder_set_member_name (builder, "error");
296 1 json_builder_add_string_value (builder, "invalid type: not a polkit identity");
297 }
298
299 4 json_builder_end_object (builder);
300 8 g_autoptr(JsonNode) root = json_builder_get_root (builder);
301 8 g_autoptr(JsonGenerator) gen = json_generator_new ();
302 4 json_generator_set_root (gen, root);
303 4 return json_generator_to_data (gen, NULL);
304 }
305