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