This source file includes following definitions.
- char2score
- score2char_stack
- score2char
- crm_user_lookup
- pcmk_daemon_user
- version_helper
- compare_version
- crm_parse_interval_spec
- crm_abort
- pcmk__daemonize
- crm_meta_name
- crm_meta_value
- crm_generate_uuid
- crm_gnutls_global_init
- pcmk_hostname
- pcmk_str_is_infinity
- pcmk_str_is_minus_infinity
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #ifndef _GNU_SOURCE
13 # define _GNU_SOURCE
14 #endif
15
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <sys/stat.h>
19 #include <sys/utsname.h>
20
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <limits.h>
26 #include <pwd.h>
27 #include <time.h>
28 #include <libgen.h>
29 #include <signal.h>
30
31 #include <qb/qbdefs.h>
32
33 #include <crm/crm.h>
34 #include <crm/services.h>
35 #include <crm/msg_xml.h>
36 #include <crm/cib/internal.h>
37 #include <crm/common/xml.h>
38 #include <crm/common/util.h>
39 #include <crm/common/ipc.h>
40 #include <crm/common/iso8601.h>
41 #include <crm/common/mainloop.h>
42 #include <libxml2/libxml/relaxng.h>
43
44 #include "crmcommon_private.h"
45
46 #ifndef PW_BUFFER_LEN
47 # define PW_BUFFER_LEN 500
48 #endif
49
50 CRM_TRACE_INIT_DATA(common);
51
52 bool pcmk__config_error = false;
53 bool pcmk__config_warning = false;
54 char *crm_system_name = NULL;
55
56 int pcmk__score_red = 0;
57 int pcmk__score_green = 0;
58 int pcmk__score_yellow = 0;
59
60 int
61 char2score(const char *score)
62 {
63 int score_f = 0;
64
65 if (score == NULL) {
66
67 } else if (pcmk_str_is_minus_infinity(score)) {
68 score_f = -CRM_SCORE_INFINITY;
69
70 } else if (pcmk_str_is_infinity(score)) {
71 score_f = CRM_SCORE_INFINITY;
72
73 } else if (pcmk__str_eq(score, "red", pcmk__str_casei)) {
74 score_f = pcmk__score_red;
75
76 } else if (pcmk__str_eq(score, "yellow", pcmk__str_casei)) {
77 score_f = pcmk__score_yellow;
78
79 } else if (pcmk__str_eq(score, "green", pcmk__str_casei)) {
80 score_f = pcmk__score_green;
81
82 } else {
83 score_f = crm_parse_int(score, NULL);
84 if (score_f > 0 && score_f > CRM_SCORE_INFINITY) {
85 score_f = CRM_SCORE_INFINITY;
86
87 } else if (score_f < 0 && score_f < -CRM_SCORE_INFINITY) {
88 score_f = -CRM_SCORE_INFINITY;
89 }
90 }
91
92 return score_f;
93 }
94
95 char *
96 score2char_stack(int score, char *buf, size_t len)
97 {
98 if (score >= CRM_SCORE_INFINITY) {
99 strncpy(buf, CRM_INFINITY_S, 9);
100 } else if (score <= -CRM_SCORE_INFINITY) {
101 strncpy(buf, CRM_MINUS_INFINITY_S , 10);
102 } else {
103 return crm_itoa_stack(score, buf, len);
104 }
105
106 return buf;
107 }
108
109 char *
110 score2char(int score)
111 {
112 if (score >= CRM_SCORE_INFINITY) {
113 return strdup(CRM_INFINITY_S);
114
115 } else if (score <= -CRM_SCORE_INFINITY) {
116 return strdup(CRM_MINUS_INFINITY_S);
117 }
118 return crm_itoa(score);
119 }
120
121 int
122 crm_user_lookup(const char *name, uid_t * uid, gid_t * gid)
123 {
124 int rc = pcmk_ok;
125 char *buffer = NULL;
126 struct passwd pwd;
127 struct passwd *pwentry = NULL;
128
129 buffer = calloc(1, PW_BUFFER_LEN);
130 if (buffer == NULL) {
131 return -ENOMEM;
132 }
133
134 rc = getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
135 if (pwentry) {
136 if (uid) {
137 *uid = pwentry->pw_uid;
138 }
139 if (gid) {
140 *gid = pwentry->pw_gid;
141 }
142 crm_trace("User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
143
144 } else {
145 rc = rc? -rc : -EINVAL;
146 crm_info("User %s lookup: %s", name, pcmk_strerror(rc));
147 }
148
149 free(buffer);
150 return rc;
151 }
152
153
154
155
156
157
158
159
160
161 int
162 pcmk_daemon_user(uid_t *uid, gid_t *gid)
163 {
164 static uid_t daemon_uid;
165 static gid_t daemon_gid;
166 static bool found = false;
167 int rc = pcmk_err_generic;
168
169 if (!found) {
170 rc = crm_user_lookup(CRM_DAEMON_USER, &daemon_uid, &daemon_gid);
171 if (rc == pcmk_ok) {
172 found = true;
173 }
174 }
175 if (found) {
176 if (uid) {
177 *uid = daemon_uid;
178 }
179 if (gid) {
180 *gid = daemon_gid;
181 }
182 }
183 return rc;
184 }
185
186
187
188
189
190
191
192
193 static int
194 version_helper(const char *text, const char **end_text)
195 {
196 int atoi_result = -1;
197
198 CRM_ASSERT(end_text != NULL);
199
200 errno = 0;
201
202 if (text != NULL && text[0] != 0) {
203
204
205
206
207
208
209 atoi_result = (int) strtol(text, (char **) end_text, 10);
210
211 if (errno == EINVAL) {
212 crm_err("Conversion of '%s' %c failed", text, text[0]);
213 atoi_result = -1;
214 }
215 }
216 return atoi_result;
217 }
218
219
220
221
222
223
224 int
225 compare_version(const char *version1, const char *version2)
226 {
227 int rc = 0;
228 int lpc = 0;
229 const char *ver1_iter, *ver2_iter;
230
231 if (version1 == NULL && version2 == NULL) {
232 return 0;
233 } else if (version1 == NULL) {
234 return -1;
235 } else if (version2 == NULL) {
236 return 1;
237 }
238
239 ver1_iter = version1;
240 ver2_iter = version2;
241
242 while (1) {
243 int digit1 = 0;
244 int digit2 = 0;
245
246 lpc++;
247
248 if (ver1_iter == ver2_iter) {
249 break;
250 }
251
252 if (ver1_iter != NULL) {
253 digit1 = version_helper(ver1_iter, &ver1_iter);
254 }
255
256 if (ver2_iter != NULL) {
257 digit2 = version_helper(ver2_iter, &ver2_iter);
258 }
259
260 if (digit1 < digit2) {
261 rc = -1;
262 break;
263
264 } else if (digit1 > digit2) {
265 rc = 1;
266 break;
267 }
268
269 if (ver1_iter != NULL && *ver1_iter == '.') {
270 ver1_iter++;
271 }
272 if (ver1_iter != NULL && *ver1_iter == '\0') {
273 ver1_iter = NULL;
274 }
275
276 if (ver2_iter != NULL && *ver2_iter == '.') {
277 ver2_iter++;
278 }
279 if (ver2_iter != NULL && *ver2_iter == 0) {
280 ver2_iter = NULL;
281 }
282 }
283
284 if (rc == 0) {
285 crm_trace("%s == %s (%d)", version1, version2, lpc);
286 } else if (rc < 0) {
287 crm_trace("%s < %s (%d)", version1, version2, lpc);
288 } else if (rc > 0) {
289 crm_trace("%s > %s (%d)", version1, version2, lpc);
290 }
291
292 return rc;
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306 guint
307 crm_parse_interval_spec(const char *input)
308 {
309 long long msec = -1;
310
311 errno = 0;
312 if (input == NULL) {
313 return 0;
314
315 } else if (input[0] == 'P') {
316 crm_time_t *period_s = crm_time_parse_duration(input);
317
318 if (period_s) {
319 msec = 1000 * crm_time_get_seconds(period_s);
320 crm_time_free(period_s);
321 }
322
323 } else {
324 msec = crm_get_msec(input);
325 }
326
327 if (msec < 0) {
328 crm_warn("Using 0 instead of '%s'", input);
329 errno = EINVAL;
330 return 0;
331 }
332 return (msec >= G_MAXUINT)? G_MAXUINT : (guint) msec;
333 }
334
335
336 void
337 crm_abort(const char *file, const char *function, int line,
338 const char *assert_condition, gboolean do_core, gboolean do_fork)
339 {
340 int rc = 0;
341 int pid = 0;
342 int status = 0;
343
344
345
346
347 if (!pcmk__is_daemon) {
348
349
350
351 crm_enable_stderr(TRUE);
352 do_fork = FALSE;
353 }
354
355 if (do_core == FALSE) {
356 crm_err("%s: Triggered assert at %s:%d : %s", function, file, line, assert_condition);
357 return;
358
359 } else if (do_fork) {
360 pid = fork();
361
362 } else {
363 crm_err("%s: Triggered fatal assert at %s:%d : %s", function, file, line, assert_condition);
364 }
365
366 if (pid == -1) {
367 crm_crit("%s: Cannot create core for non-fatal assert at %s:%d : %s",
368 function, file, line, assert_condition);
369 return;
370
371 } else if(pid == 0) {
372
373 abort();
374 return;
375 }
376
377
378 crm_err("%s: Forked child %d to record non-fatal assert at %s:%d : %s",
379 function, pid, file, line, assert_condition);
380 crm_write_blackbox(SIGTRAP, NULL);
381
382 do {
383 rc = waitpid(pid, &status, 0);
384 if(rc == pid) {
385 return;
386 }
387
388 } while(errno == EINTR);
389
390 if (errno == ECHILD) {
391
392 crm_trace("Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN", pid);
393 return;
394 }
395 crm_perror(LOG_ERR, "Cannot wait on forked child %d", pid);
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409 void
410 pcmk__daemonize(const char *name, const char *pidfile)
411 {
412 int rc;
413 pid_t pid;
414
415
416 rc = pcmk__pidfile_matches(pidfile, 1, name, &pid);
417 if ((rc != pcmk_rc_ok) && (rc != ENOENT)) {
418 crm_err("%s: already running [pid %lld in %s]",
419 name, (long long) pid, pidfile);
420 printf("%s: already running [pid %lld in %s]\n",
421 name, (long long) pid, pidfile);
422 crm_exit(CRM_EX_ERROR);
423 }
424
425 pid = fork();
426 if (pid < 0) {
427 fprintf(stderr, "%s: could not start daemon\n", name);
428 crm_perror(LOG_ERR, "fork");
429 crm_exit(CRM_EX_OSERR);
430
431 } else if (pid > 0) {
432 crm_exit(CRM_EX_OK);
433 }
434
435 rc = pcmk__lock_pidfile(pidfile, name);
436 if (rc != pcmk_rc_ok) {
437 crm_err("Could not lock '%s' for %s: %s " CRM_XS " rc=%d",
438 pidfile, name, pcmk_rc_str(rc), rc);
439 printf("Could not lock '%s' for %s: %s (%d)\n",
440 pidfile, name, pcmk_rc_str(rc), rc);
441 crm_exit(CRM_EX_ERROR);
442 }
443
444 umask(S_IWGRP | S_IWOTH | S_IROTH);
445
446 close(STDIN_FILENO);
447 pcmk__open_devnull(O_RDONLY);
448
449 close(STDOUT_FILENO);
450 pcmk__open_devnull(O_WRONLY);
451
452 close(STDERR_FILENO);
453 pcmk__open_devnull(O_WRONLY);
454 }
455
456 char *
457 crm_meta_name(const char *field)
458 {
459 int lpc = 0;
460 int max = 0;
461 char *crm_name = NULL;
462
463 CRM_CHECK(field != NULL, return NULL);
464 crm_name = crm_strdup_printf(CRM_META "_%s", field);
465
466
467 max = strlen(crm_name);
468 for (; lpc < max; lpc++) {
469 switch (crm_name[lpc]) {
470 case '-':
471 crm_name[lpc] = '_';
472 break;
473 }
474 }
475 return crm_name;
476 }
477
478 const char *
479 crm_meta_value(GHashTable * hash, const char *field)
480 {
481 char *key = NULL;
482 const char *value = NULL;
483
484 key = crm_meta_name(field);
485 if (key) {
486 value = g_hash_table_lookup(hash, key);
487 free(key);
488 }
489
490 return value;
491 }
492
493 #ifdef HAVE_UUID_UUID_H
494 # include <uuid/uuid.h>
495 #endif
496
497 char *
498 crm_generate_uuid(void)
499 {
500 unsigned char uuid[16];
501 char *buffer = malloc(37);
502
503 uuid_generate(uuid);
504 uuid_unparse(uuid, buffer);
505 return buffer;
506 }
507
508 #ifdef HAVE_GNUTLS_GNUTLS_H
509 void
510 crm_gnutls_global_init(void)
511 {
512 signal(SIGPIPE, SIG_IGN);
513 gnutls_global_init();
514 }
515 #endif
516
517
518
519
520
521
522 char *
523 pcmk_hostname()
524 {
525 struct utsname hostinfo;
526
527 return (uname(&hostinfo) < 0)? NULL : strdup(hostinfo.nodename);
528 }
529
530 bool
531 pcmk_str_is_infinity(const char *s) {
532 return pcmk__str_any_of(s, CRM_INFINITY_S, CRM_PLUS_INFINITY_S, NULL);
533 }
534
535 bool
536 pcmk_str_is_minus_infinity(const char *s) {
537 return pcmk__str_eq(s, CRM_MINUS_INFINITY_S, pcmk__str_none);
538 }