This source file includes following definitions.
- pcmk_common_cleanup
- pcmk__is_user_in_group
- crm_user_lookup
- pcmk_daemon_user
- version_helper
- compare_version
- pcmk__daemonize
- crm_generate_uuid
- pcmk__sleep_ms
- pcmk__create_timer
- pcmk__timeout_ms2s
- _gnutls_log_func
- crm_gnutls_global_init
- crm_is_daemon_name
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/stat.h>
13 #include <sys/utsname.h>
14
15 #include <stdio.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <limits.h>
20 #include <pwd.h>
21 #include <time.h>
22 #include <libgen.h>
23 #include <signal.h>
24 #include <grp.h>
25
26 #include <qb/qbdefs.h>
27
28 #include <crm/crm.h>
29 #include <crm/services.h>
30 #include <crm/cib/internal.h>
31 #include <crm/common/xml.h>
32 #include <crm/common/util.h>
33 #include <crm/common/ipc.h>
34 #include <crm/common/iso8601.h>
35 #include <crm/common/mainloop.h>
36 #include <libxml/parser.h>
37 #include <libxml2/libxml/relaxng.h>
38
39 #include "crmcommon_private.h"
40
41 CRM_TRACE_INIT_DATA(common);
42
43 bool pcmk__config_has_error = false;
44 bool pcmk__config_has_warning = false;
45 char *crm_system_name = NULL;
46
47
48
49
50
51
52
53
54 void
55 pcmk_common_cleanup(void)
56 {
57
58 mainloop_cleanup();
59 pcmk__schema_cleanup();
60 pcmk__free_common_logger();
61
62 free(crm_system_name);
63 crm_system_name = NULL;
64
65
66 qb_log_fini();
67 xmlCleanupParser();
68 }
69
70 bool
71 pcmk__is_user_in_group(const char *user, const char *group)
72 {
73 struct group *grent;
74 char **gr_mem;
75
76 if (user == NULL || group == NULL) {
77 return false;
78 }
79
80 setgrent();
81 while ((grent = getgrent()) != NULL) {
82 if (grent->gr_mem == NULL) {
83 continue;
84 }
85
86 if(strcmp(group, grent->gr_name) != 0) {
87 continue;
88 }
89
90 gr_mem = grent->gr_mem;
91 while (*gr_mem != NULL) {
92 if (!strcmp(user, *gr_mem++)) {
93 endgrent();
94 return true;
95 }
96 }
97 }
98 endgrent();
99 return false;
100 }
101
102 int
103 crm_user_lookup(const char *name, uid_t * uid, gid_t * gid)
104 {
105 int rc = pcmk_ok;
106 char *buffer = NULL;
107 struct passwd pwd;
108 struct passwd *pwentry = NULL;
109
110 buffer = calloc(1, PCMK__PW_BUFFER_LEN);
111 if (buffer == NULL) {
112 return -ENOMEM;
113 }
114
115 rc = getpwnam_r(name, &pwd, buffer, PCMK__PW_BUFFER_LEN, &pwentry);
116 if (pwentry) {
117 if (uid) {
118 *uid = pwentry->pw_uid;
119 }
120 if (gid) {
121 *gid = pwentry->pw_gid;
122 }
123 crm_trace("User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
124
125 } else {
126 rc = rc? -rc : -EINVAL;
127 crm_info("User %s lookup: %s", name, pcmk_strerror(rc));
128 }
129
130 free(buffer);
131 return rc;
132 }
133
134
135
136
137
138
139
140
141
142 int
143 pcmk_daemon_user(uid_t *uid, gid_t *gid)
144 {
145 static uid_t daemon_uid;
146 static gid_t daemon_gid;
147 static bool found = false;
148 int rc = pcmk_ok;
149
150 if (!found) {
151 rc = crm_user_lookup(CRM_DAEMON_USER, &daemon_uid, &daemon_gid);
152 if (rc == pcmk_ok) {
153 found = true;
154 }
155 }
156 if (found) {
157 if (uid) {
158 *uid = daemon_uid;
159 }
160 if (gid) {
161 *gid = daemon_gid;
162 }
163 }
164 return rc;
165 }
166
167
168
169
170
171
172
173
174 static int
175 version_helper(const char *text, const char **end_text)
176 {
177 int atoi_result = -1;
178
179 pcmk__assert(end_text != NULL);
180
181 errno = 0;
182
183 if (text != NULL && text[0] != 0) {
184
185
186
187
188
189
190 atoi_result = (int) strtol(text, (char **) end_text, 10);
191
192 if (errno == EINVAL) {
193 crm_err("Conversion of '%s' %c failed", text, text[0]);
194 atoi_result = -1;
195 }
196 }
197 return atoi_result;
198 }
199
200
201
202
203
204
205 int
206 compare_version(const char *version1, const char *version2)
207 {
208 int rc = 0;
209 int lpc = 0;
210 const char *ver1_iter, *ver2_iter;
211
212 if (version1 == NULL && version2 == NULL) {
213 return 0;
214 } else if (version1 == NULL) {
215 return -1;
216 } else if (version2 == NULL) {
217 return 1;
218 }
219
220 ver1_iter = version1;
221 ver2_iter = version2;
222
223 while (1) {
224 int digit1 = 0;
225 int digit2 = 0;
226
227 lpc++;
228
229 if (ver1_iter == ver2_iter) {
230 break;
231 }
232
233 if (ver1_iter != NULL) {
234 digit1 = version_helper(ver1_iter, &ver1_iter);
235 }
236
237 if (ver2_iter != NULL) {
238 digit2 = version_helper(ver2_iter, &ver2_iter);
239 }
240
241 if (digit1 < digit2) {
242 rc = -1;
243 break;
244
245 } else if (digit1 > digit2) {
246 rc = 1;
247 break;
248 }
249
250 if (ver1_iter != NULL && *ver1_iter == '.') {
251 ver1_iter++;
252 }
253 if (ver1_iter != NULL && *ver1_iter == '\0') {
254 ver1_iter = NULL;
255 }
256
257 if (ver2_iter != NULL && *ver2_iter == '.') {
258 ver2_iter++;
259 }
260 if (ver2_iter != NULL && *ver2_iter == 0) {
261 ver2_iter = NULL;
262 }
263 }
264
265 if (rc == 0) {
266 crm_trace("%s == %s (%d)", version1, version2, lpc);
267 } else if (rc < 0) {
268 crm_trace("%s < %s (%d)", version1, version2, lpc);
269 } else if (rc > 0) {
270 crm_trace("%s > %s (%d)", version1, version2, lpc);
271 }
272
273 return rc;
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287 void
288 pcmk__daemonize(const char *name, const char *pidfile)
289 {
290 int rc;
291 pid_t pid;
292
293
294 rc = pcmk__pidfile_matches(pidfile, 1, name, &pid);
295 if ((rc != pcmk_rc_ok) && (rc != ENOENT)) {
296 crm_err("%s: already running [pid %lld in %s]",
297 name, (long long) pid, pidfile);
298 printf("%s: already running [pid %lld in %s]\n",
299 name, (long long) pid, pidfile);
300 crm_exit(CRM_EX_ERROR);
301 }
302
303 pid = fork();
304 if (pid < 0) {
305 fprintf(stderr, "%s: could not start daemon\n", name);
306 crm_perror(LOG_ERR, "fork");
307 crm_exit(CRM_EX_OSERR);
308
309 } else if (pid > 0) {
310 crm_exit(CRM_EX_OK);
311 }
312
313 rc = pcmk__lock_pidfile(pidfile, name);
314 if (rc != pcmk_rc_ok) {
315 crm_err("Could not lock '%s' for %s: %s " QB_XS " rc=%d",
316 pidfile, name, pcmk_rc_str(rc), rc);
317 printf("Could not lock '%s' for %s: %s (%d)\n",
318 pidfile, name, pcmk_rc_str(rc), rc);
319 crm_exit(CRM_EX_ERROR);
320 }
321
322 umask(S_IWGRP | S_IWOTH | S_IROTH);
323
324 close(STDIN_FILENO);
325 pcmk__open_devnull(O_RDONLY);
326
327 close(STDOUT_FILENO);
328 pcmk__open_devnull(O_WRONLY);
329
330 close(STDERR_FILENO);
331 pcmk__open_devnull(O_WRONLY);
332 }
333
334 #ifdef HAVE_UUID_UUID_H
335 # include <uuid/uuid.h>
336 #endif
337
338 char *
339 crm_generate_uuid(void)
340 {
341 unsigned char uuid[16];
342 char *buffer = malloc(37);
343
344 pcmk__mem_assert(buffer);
345 uuid_generate(uuid);
346 uuid_unparse(uuid, buffer);
347 return buffer;
348 }
349
350
351
352
353
354
355
356
357
358 void
359 pcmk__sleep_ms(unsigned int ms)
360 {
361
362
363
364
365 if (ms >= 1000) {
366 sleep(ms / 1000);
367 ms -= ms / 1000;
368 }
369
370 if (ms == 0) {
371 return;
372 }
373
374 #if defined(HAVE_NANOSLEEP)
375
376 {
377 struct timespec req = { .tv_sec = 0, .tv_nsec = (long) (ms * 1000000) };
378
379 nanosleep(&req, NULL);
380 }
381 #elif defined(HAVE_USLEEP)
382
383 usleep((useconds_t) ms);
384 #else
385
386 {
387 struct timeval tv = { .tv_sec = 0, .tv_usec = (suseconds_t) ms };
388
389 select(0, NULL, NULL, NULL, &tv);
390 }
391 #endif
392 }
393
394
395
396
397
398
399
400
401
402
403
404 guint
405 pcmk__create_timer(guint interval_ms, GSourceFunc fn, gpointer data)
406 {
407 pcmk__assert(interval_ms != 0 && fn != NULL);
408
409 if (interval_ms % 1000 == 0) {
410
411
412
413 return g_timeout_add_seconds(pcmk__timeout_ms2s(interval_ms), fn, data);
414 } else {
415 return g_timeout_add(interval_ms, fn, data);
416 }
417 }
418
419
420
421
422
423
424
425
426
427
428 guint
429 pcmk__timeout_ms2s(guint timeout_ms)
430 {
431 guint quot, rem;
432
433 if (timeout_ms == 0) {
434 return 0;
435 } else if (timeout_ms < 1000) {
436 return 1;
437 }
438
439 quot = timeout_ms / 1000;
440 rem = timeout_ms % 1000;
441
442 if (rem >= 500) {
443 quot += 1;
444 }
445
446 return quot;
447 }
448
449
450
451
452 #include <crm/common/util_compat.h>
453
454 static void
455 _gnutls_log_func(int level, const char *msg)
456 {
457 crm_trace("%s", msg);
458 }
459
460 void
461 crm_gnutls_global_init(void)
462 {
463 signal(SIGPIPE, SIG_IGN);
464 gnutls_global_init();
465 gnutls_global_set_log_level(8);
466 gnutls_global_set_log_function(_gnutls_log_func);
467 }
468
469
470
471
472
473
474
475
476
477
478
479 bool
480 crm_is_daemon_name(const char *name)
481 {
482 return pcmk__str_any_of(name,
483 "attrd",
484 CRM_SYSTEM_CIB,
485 CRM_SYSTEM_CRMD,
486 CRM_SYSTEM_DC,
487 CRM_SYSTEM_LRMD,
488 CRM_SYSTEM_MCP,
489 CRM_SYSTEM_PENGINE,
490 CRM_SYSTEM_TENGINE,
491 "pacemaker-attrd",
492 "pacemaker-based",
493 "pacemaker-controld",
494 "pacemaker-execd",
495 "pacemaker-fenced",
496 "pacemaker-remoted",
497 "pacemaker-schedulerd",
498 "stonith-ng",
499 "stonithd",
500 NULL);
501 }
502
503
504